3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-03-07 05:44:51 +00:00

Fixed definition extension rule

This commit is contained in:
CEisenhofer 2026-03-05 18:33:58 +01:00
parent d8871e5c1e
commit 608227a27e
3 changed files with 33 additions and 22 deletions

View file

@ -178,9 +178,8 @@ namespace euf {
arg(0)->collect_tokens(tokens);
arg(1)->collect_tokens(tokens);
}
else if (!is_empty()) {
else if (!is_empty())
tokens.push_back(const_cast<snode*>(this));
}
}
// access the i-th token (0-based, left-to-right order)

View file

@ -879,6 +879,19 @@ namespace seq {
return search_result::unknown;
}
// Returns true if variable snode `var` appears anywhere in the token list of `n`.
static bool snode_contains_var(euf::snode const* n, euf::snode const* var) {
if (!n || !var)
return false;
euf::snode_vector tokens;
n->collect_tokens(tokens);
for (const euf::snode* t : tokens) {
if (t == var)
return true;
}
return false;
}
bool nielsen_graph::apply_det_modifier(nielsen_node* node) {
for (str_eq const& eq : node->str_eqs()) {
if (eq.is_trivial())
@ -886,28 +899,23 @@ namespace seq {
if (!eq.m_lhs || !eq.m_rhs)
continue;
euf::snode_vector lhs_toks, rhs_toks;
eq.m_lhs->collect_tokens(lhs_toks);
eq.m_rhs->collect_tokens(rhs_toks);
if (lhs_toks.empty() || rhs_toks.empty())
continue;
euf::snode* lhead = lhs_toks[0];
euf::snode* rhead = rhs_toks[0];
// variable definition: x = t where x ∉ vars(t) → subst x → t
if (lhead->is_var() && eq.m_rhs->is_empty()) {
nielsen_node* child = mk_child(node);
nielsen_edge* e = mk_edge(node, child, true);
nielsen_subst s(lhead, m_sg.mk_empty(), eq.m_dep);
e->add_subst(s);
child->apply_subst(m_sg, s);
return true;
// variable definition: x = t where x is a single var and x ∉ vars(t)
// → deterministically substitute x → t throughout the node
euf::snode* var = nullptr;
euf::snode* def;
if (eq.m_lhs->is_var() && !snode_contains_var(eq.m_rhs, eq.m_lhs)) {
var = eq.m_lhs;
def = eq.m_rhs;
}
if (rhead->is_var() && eq.m_lhs->is_empty()) {
else if (eq.m_rhs->is_var() && !snode_contains_var(eq.m_lhs, eq.m_rhs)) {
var = eq.m_rhs;
def = eq.m_lhs;
}
if (var) {
nielsen_node* child = mk_child(node);
nielsen_edge* e = mk_edge(node, child, true);
nielsen_subst s(rhead, m_sg.mk_empty(), eq.m_dep);
nielsen_subst s(var, def, eq.m_dep);
e->add_subst(s);
child->apply_subst(m_sg, s);
return true;

View file

@ -349,7 +349,11 @@ namespace seq {
nielsen_subst(): m_var(nullptr), m_replacement(nullptr) {}
nielsen_subst(euf::snode* var, euf::snode* repl, dep_tracker const& dep):
m_var(var), m_replacement(repl), m_dep(dep) {}
m_var(var), m_replacement(repl), m_dep(dep) {
SASSERT(var != nullptr);
SASSERT(repl != nullptr);
SASSERT(var->is_var());
}
// an eliminating substitution does not contain the variable in the replacement
bool is_eliminating() const;