mirror of
https://github.com/Z3Prover/z3
synced 2026-06-02 07:07:52 +00:00
Fixed definition extension rule
This commit is contained in:
parent
d8871e5c1e
commit
608227a27e
3 changed files with 33 additions and 22 deletions
|
|
@ -178,9 +178,8 @@ namespace euf {
|
||||||
arg(0)->collect_tokens(tokens);
|
arg(0)->collect_tokens(tokens);
|
||||||
arg(1)->collect_tokens(tokens);
|
arg(1)->collect_tokens(tokens);
|
||||||
}
|
}
|
||||||
else if (!is_empty()) {
|
else if (!is_empty())
|
||||||
tokens.push_back(const_cast<snode*>(this));
|
tokens.push_back(const_cast<snode*>(this));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// access the i-th token (0-based, left-to-right order)
|
// access the i-th token (0-based, left-to-right order)
|
||||||
|
|
|
||||||
|
|
@ -879,6 +879,19 @@ namespace seq {
|
||||||
return search_result::unknown;
|
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) {
|
bool nielsen_graph::apply_det_modifier(nielsen_node* node) {
|
||||||
for (str_eq const& eq : node->str_eqs()) {
|
for (str_eq const& eq : node->str_eqs()) {
|
||||||
if (eq.is_trivial())
|
if (eq.is_trivial())
|
||||||
|
|
@ -886,28 +899,23 @@ namespace seq {
|
||||||
if (!eq.m_lhs || !eq.m_rhs)
|
if (!eq.m_lhs || !eq.m_rhs)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
euf::snode_vector lhs_toks, rhs_toks;
|
// variable definition: x = t where x is a single var and x ∉ vars(t)
|
||||||
eq.m_lhs->collect_tokens(lhs_toks);
|
// → deterministically substitute x → t throughout the node
|
||||||
eq.m_rhs->collect_tokens(rhs_toks);
|
euf::snode* var = nullptr;
|
||||||
if (lhs_toks.empty() || rhs_toks.empty())
|
euf::snode* def;
|
||||||
continue;
|
if (eq.m_lhs->is_var() && !snode_contains_var(eq.m_rhs, eq.m_lhs)) {
|
||||||
|
var = eq.m_lhs;
|
||||||
euf::snode* lhead = lhs_toks[0];
|
def = eq.m_rhs;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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_node* child = mk_child(node);
|
||||||
nielsen_edge* e = mk_edge(node, child, true);
|
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);
|
e->add_subst(s);
|
||||||
child->apply_subst(m_sg, s);
|
child->apply_subst(m_sg, s);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -349,7 +349,11 @@ namespace seq {
|
||||||
|
|
||||||
nielsen_subst(): m_var(nullptr), m_replacement(nullptr) {}
|
nielsen_subst(): m_var(nullptr), m_replacement(nullptr) {}
|
||||||
nielsen_subst(euf::snode* var, euf::snode* repl, dep_tracker const& dep):
|
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
|
// an eliminating substitution does not contain the variable in the replacement
|
||||||
bool is_eliminating() const;
|
bool is_eliminating() const;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue