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

first end-pass. Atomic

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2026-03-04 02:05:26 -08:00
parent 13f9fec339
commit 5aa3713d19
15 changed files with 6160 additions and 209 deletions

View file

@ -355,6 +355,22 @@ namespace euf {
if (n)
return n;
// decompose non-empty string constants into character chains
// so that Nielsen graph can do prefix matching on them
zstring s;
if (m_seq.str.is_string(e, s) && !s.empty()) {
snode* result = mk_char(s[s.length() - 1]);
for (unsigned i = s.length() - 1; i-- > 0; )
result = mk_concat(mk_char(s[i]), result);
// register the original string expression as an alias
unsigned eid = e->get_id();
m_expr2snode.reserve(eid + 1, nullptr);
m_expr2snode[eid] = result;
m_alias_trail.push_back(eid);
mk_enode(e);
return result;
}
snode_kind k = classify(e);
if (!is_app(e))
@ -400,6 +416,7 @@ namespace euf {
void sgraph::push() {
m_scopes.push_back(m_nodes.size());
m_alias_trail_lim.push_back(m_alias_trail.size());
++m_num_scopes;
m_egraph.push();
}
@ -420,6 +437,15 @@ namespace euf {
}
m_nodes.shrink(old_sz);
m_scopes.shrink(new_lvl);
// undo alias entries (string constant decompositions)
unsigned alias_old = m_alias_trail_lim[new_lvl];
for (unsigned i = m_alias_trail.size(); i-- > alias_old; ) {
unsigned eid = m_alias_trail[i];
if (eid < m_expr2snode.size())
m_expr2snode[eid] = nullptr;
}
m_alias_trail.shrink(alias_old);
m_alias_trail_lim.shrink(new_lvl);
m_num_scopes = new_lvl;
m_egraph.pop(num_scopes);
}
@ -520,6 +546,25 @@ namespace euf {
expr* ch = nullptr;
if (m_seq.str.is_unit(elem_expr, ch))
elem_expr = ch;
// If elem is a regex predicate (e.g., re.allchar from compute_minterms),
// extract a representative character for the derivative.
sort* seq_sort = nullptr, *ele_sort = nullptr;
if (m_seq.is_re(re_expr, seq_sort) && m_seq.is_seq(seq_sort, ele_sort)) {
if (ele_sort != elem_expr->get_sort()) {
expr* lo = nullptr, *hi = nullptr;
if (m_seq.re.is_full_char(elem_expr)) {
// re.allchar represents the entire alphabet; computing a derivative
// w.r.t. a single character would be imprecise and could incorrectly
// report fail. Return nullptr to prevent incorrect pruning.
return nullptr;
}
else if (m_seq.re.is_range(elem_expr, lo, hi) && lo)
elem_expr = lo;
else
return nullptr;
}
}
expr_ref result = m_rewriter.mk_derivative(elem_expr, re_expr);
if (!result)
return nullptr;