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

Revert "Derive with ranges" (#9964)

Reverts Z3Prover/z3#9963
This commit is contained in:
Nikolaj Bjorner 2026-06-25 18:57:30 -07:00 committed by GitHub
parent 22c2635786
commit f034616950
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 1000 additions and 3462 deletions

View file

@ -85,6 +85,45 @@ namespace seq {
return is_ground(r);
}
/*
Collect the leaves of a t-regex der (an ITE-tree whose leaves are
regex expressions) into the output vector. Empty (re.empty) leaves
are dropped.
Each leaf is treated as a single bisimulation state regardless of
its top-level shape (including re.union and re.antimirov_union):
descending into a union at the leaf would split one state into
several, which is semantically unsound for the bisimulation /
union-find merging that follows.
Returns false if we encountered an unexpected node (e.g. a free
variable creeping in) in that case the caller should bail out.
*/
bool regex_bisim::collect_leaves(expr* der, expr_ref_vector& leaves) {
ptr_vector<expr> work;
obj_hashtable<expr> seen;
work.push_back(der);
seen.insert(der);
while (!work.empty()) {
expr* e = work.back();
work.pop_back();
expr* c = nullptr, * t = nullptr, * f = nullptr;
if (m.is_ite(e, c, t, f)) {
if (seen.insert_if_not_there(t))
work.push_back(t);
if (seen.insert_if_not_there(f))
work.push_back(f);
continue;
}
if (m_util.re.is_empty(e))
continue;
if (!m_util.is_re(e))
return false;
leaves.push_back(e);
}
return true;
}
/*
Fast inequivalence check based on the get_info().classical flag.
@ -193,19 +232,15 @@ namespace seq {
m_worklist.pop_back();
// Compute the symbolic derivative wrt the canonical variable
// (:var 0) and enumerate its reachable leaves in fully
// ITE-hoisted normal form. Every if-then-else over the input
// character — even one that would otherwise be buried under a
// concat or union — is hoisted to the top and infeasible
// minterms are pruned, so each leaf is a ground regex free of
// (:var 0) whose nullability is always decidable. Unions are
// kept intact as single leaves (a union leaf denotes a single
// bisimulation state, never a split into separate states).
expr_ref_pair_vector cofs(m);
m_rw.brz_derivative_cofactors(r, cofs);
// (:var 0). The result is a transition regex (ITE tree) whose
// leaves are regex expressions. We use the classical Brzozowski
// entry point so the derivative stays as a single TRegex and
// does not lift unions to the top via antimirov nodes — this
// preserves the XOR-pair invariant the bisimulation relies on.
expr_ref d(m_rw.mk_brz_derivative(r), m);
expr_ref_vector leaves(m);
for (auto const& p : cofs)
leaves.push_back(p.second);
if (!collect_leaves(d, leaves))
return l_undef;
// First pass: check for any nullable leaf (definitive
// distinguishing empty-continuation word) or any classically