3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-04-22 11:53:29 +00:00

Handle unit-unit prefix/suffix splits in simplify_and_init (#9097)

When both leading (or trailing) tokens of a string equality are
is_char_or_unit(), split the equality:
  unit(a) ++ rest1 == unit(b) ++ rest2  ->  unit(a)==unit(b), rest1==rest2
  unit(a) ++ rest1 == unit(b)           ->  unit(a)==unit(b), rest1==empty
  unit(a) == unit(b) ++ rest2           ->  unit(a)==unit(b), empty==rest2
(symmetric suffix case handled too)

Add three unit tests covering prefix split, prefix split with empty
rest, and suffix split.


Agent-Logs-Url: https://github.com/Z3Prover/z3/sessions/565287e9-a121-4bae-8aa4-6c2ec93e660f

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
Copilot 2026-03-22 19:39:33 -07:00 committed by GitHub
parent ad94dd1b7a
commit 8db175447b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 159 additions and 0 deletions

View file

@ -1009,6 +1009,8 @@ namespace seq {
}
// pass 2: detect symbol clashes, empty-propagation, and prefix cancellation
// unit equalities produced by unit-unit prefix/suffix splits below
svector<str_eq> unit_eqs;
for (str_eq& eq : m_str_eq) {
if (!eq.m_lhs || !eq.m_rhs)
continue;
@ -1046,6 +1048,13 @@ namespace seq {
m_reason = backtrack_reason::symbol_clash;
return simplify_result::conflict;
}
else if (lt->is_char_or_unit() && rt->is_char_or_unit()) {
// unit(a) ++ rest1 == unit(b) ++ rest2: split into unit(a)==unit(b) and rest1==rest2
str_eq ueq(lt, rt, eq.m_dep);
ueq.sort();
unit_eqs.push_back(ueq);
++prefix;
}
else
break;
}
@ -1063,6 +1072,13 @@ namespace seq {
m_reason = backtrack_reason::symbol_clash;
return simplify_result::conflict;
}
else if (lt->is_char_or_unit() && rt->is_char_or_unit()) {
// rest1 ++ unit(a) == rest2 ++ unit(b): split into unit(a)==unit(b) and rest1==rest2
str_eq ueq(lt, rt, eq.m_dep);
ueq.sort();
unit_eqs.push_back(ueq);
++suffix;
}
else
break;
}
@ -1126,6 +1142,12 @@ namespace seq {
}
}
// flush unit equalities generated by prefix/suffix unit splits
for (str_eq const& ueq : unit_eqs) {
m_str_eq.push_back(ueq);
changed = true;
}
// pass 3: power simplification (mirrors ZIPT's LcpCompression +
// SimplifyPowerElim + SimplifyPowerSingle)
for (str_eq& eq : m_str_eq) {