3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-06-10 19:07:18 +00:00

Fix right-side can_add indexing in sls_seq_plugin edit-distance repair (#9773)

`seq_plugin::edit_distance_with_updates` used the left-string DP index
when checking whether the right string could accept an insertion from
the `d[i][j - 1]` transition. This miscomputed updateable edit distance
and could suppress valid repair proposals when `i != j`.

- **Bug fix**
- Change the right-side insertion guard in
`src/ast/sls/sls_seq_plugin.cpp` from `b.can_add(i - 1)` to `b.can_add(j
- 1)`.
- This aligns the mutability check with the DP transition being
evaluated and with the existing update-generation logic below it.

- **Regression coverage**
- Add a focused test in `src/test/sls_seq_plugin.cpp` for an asymmetric
variable/value layout on the right-hand side.
- The test asserts that the repair logic admits the right-side add at `j
- 1`, which is the case that the previous index mixup could reject.

- **Reference**
  - The updated condition now matches the intended transition semantics:

```cpp
if (d[i][j - 1] < u[i][j] && b.can_add(j - 1)) {
    m_string_updates.reset();
    u[i][j] = d[i][j - 1];
}
```

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
Copilot 2026-06-08 19:36:14 -07:00 committed by GitHub
parent aa872bd289
commit 49014fe302
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 25 additions and 1 deletions

View file

@ -912,7 +912,7 @@ namespace sls {
m_string_updates.reset(); m_string_updates.reset();
u[i][j] = d[i - 1][j]; u[i][j] = d[i - 1][j];
} }
if (d[i][j - 1] < u[i][j] && b.can_add(i - 1)) { if (d[i][j - 1] < u[i][j] && b.can_add(j - 1)) {
m_string_updates.reset(); m_string_updates.reset();
u[i][j] = d[i][j - 1]; u[i][j] = d[i][j - 1];
} }

View file

@ -351,4 +351,28 @@ void tst_sls_seq_plugin() {
app_ref eq(m.mk_eq(l, r), m); app_ref eq(m.mk_eq(l, r), m);
verbose_stream() << eq << "\n"; verbose_stream() << eq << "\n";
ts.repair_down_str_eq_edit_distance_incremental(eq); ts.repair_down_str_eq_edit_distance_incremental(eq);
test_seq::string_instance lhs, rhs;
lhs.s = zstring("a");
lhs.is_value.push_back(false);
lhs.prev_is_var.push_back(false);
lhs.next_is_var.push_back(false);
rhs.s = zstring("ab");
rhs.is_value.push_back(true);
rhs.prev_is_var.push_back(false);
rhs.next_is_var.push_back(false);
rhs.is_value.push_back(false);
rhs.prev_is_var.push_back(false);
rhs.next_is_var.push_back(false);
ENSURE(ts.edit_distance_with_updates(lhs, rhs) == 0);
ENSURE(ts.m_string_updates.size() == 2);
ENSURE(ts.m_string_updates[0].side == test_seq::side_t::right);
ENSURE(ts.m_string_updates[0].op == test_seq::op_t::add);
ENSURE(ts.m_string_updates[0].i == 0);
ENSURE(ts.m_string_updates[0].j == 1);
ENSURE(ts.m_string_updates[1].side == test_seq::side_t::right);
ENSURE(ts.m_string_updates[1].op == test_seq::op_t::del);
ENSURE(ts.m_string_updates[1].i == 1);
ENSURE(ts.m_string_updates[1].j == 0);
} }