3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-07-20 05:55:49 +00:00

seq_split: fix derivative-complement soundness+perf via canonical range_predicate

Resolves the WIP soundness bug. Root cause: the char-classes emitted for cofactor conditions were non-canonical and unrecognized downstream (of_pred(lambda) -> opaque select(lambda,ele); raw range unions carried (and true RANGE) that is_char_const_range rejected). Fix: mk_charclass_re maps the cofactor condition (true/false/and/or/not/=/char.<=) to the canonical seq::range_predicate via its Boolean ops, then range_predicate_to_regex (seq_range_collapse.h) yields a canonical char-class regex the derivative/emptiness/primitive path handles natively. Also: derive_of_pred beta-reduces select(lambda,ele) (general of_pred soundness fix).

RESULT on gen-lb (119): 0 default disagreements, 0 nseq spurious-unsat. L15 negcount family (27) timeout->solved: e.g. l15-digit-m3-dash now sat in 0.02s (dfs-nodes 33071->55, split complement/max-split-set eliminated). No regression (L11 sat, L14 unsat). Validates the notes.md derivative-based split redesign for star-free complements.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Margus Veanes 2026-07-03 23:44:09 +03:00
parent 22eb098cd9
commit 07451d8922
3 changed files with 81 additions and 11 deletions

View file

@ -136,9 +136,12 @@ class seq_split {
// One level of the sigma rules: from_re(r) -> a SplitSet term built from the
// immediate subterms. `ok` is set false on an unsupported shape.
expr_ref expand_fromre(expr* r, bool& ok, obj_hashtable<expr>& deriv_memo);
// Build the single-character regex of_pred(lambda c. pred) from a cofactor
// path condition `pred` (a Boolean over the character (:var 0)).
expr_ref mk_charclass_re(expr* pred);
// Build the single-character regex for a cofactor path condition `pred` (a
// Boolean over the character (:var 0)). Prefer a range / union-of-ranges
// (which nseq's emptiness/primitive/length path fully supports); fall back to
// of_pred(lambda) only for predicates that are not a single (possibly negated)
// range.
expr_ref mk_charclass_re(expr* pred, sort* seq_sort);
// Distribute a left/right concatenation over a head-normal split-set.
expr_ref distribute_lcat(expr* r, expr* hs);
expr_ref distribute_rcat(expr* hs, expr* r);