mirror of
https://github.com/Z3Prover/z3
synced 2025-07-18 02:16:40 +00:00
running updates to bv_solver (#4674)
* na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * dbg Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * bv Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * drat and fresh Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * move ackerman functionality Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * debugability Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * towards debugability Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * missing file Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove csp Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
4d1a2a2784
commit
d02b0cde7a
63 changed files with 3060 additions and 3095 deletions
|
@ -17,52 +17,11 @@ Author:
|
|||
|
||||
#include "ast/euf/euf_egraph.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/ast_translation.h"
|
||||
|
||||
namespace euf {
|
||||
|
||||
/**
|
||||
\brief Trail for add_th_var
|
||||
*/
|
||||
class add_th_var_trail : public trail<egraph> {
|
||||
enode * m_enode;
|
||||
theory_id m_th_id;
|
||||
public:
|
||||
add_th_var_trail(enode * n, theory_id th_id):
|
||||
m_enode(n),
|
||||
m_th_id(th_id) {
|
||||
}
|
||||
|
||||
void undo(egraph & ctx) override {
|
||||
theory_var v = m_enode->get_th_var(m_th_id);
|
||||
SASSERT(v != null_theory_var);
|
||||
m_enode->del_th_var(m_th_id);
|
||||
enode * root = m_enode->get_root();
|
||||
if (root != m_enode && root->get_th_var(m_th_id) == v)
|
||||
root->del_th_var(m_th_id);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Trail for replace_th_var
|
||||
*/
|
||||
class replace_th_var_trail : public trail<egraph> {
|
||||
enode * m_enode;
|
||||
unsigned m_th_id:8;
|
||||
unsigned m_old_th_var:24;
|
||||
public:
|
||||
replace_th_var_trail(enode * n, theory_id th_id, theory_var old_var):
|
||||
m_enode(n),
|
||||
m_th_id(th_id),
|
||||
m_old_th_var(old_var) {
|
||||
}
|
||||
|
||||
void undo(egraph & ctx) override {
|
||||
SASSERT(m_enode->get_th_var(m_th_id) != null_theory_var);
|
||||
m_enode->replace_th_var(m_old_th_var, m_th_id);
|
||||
}
|
||||
};
|
||||
|
||||
void egraph::undo_eq(enode* r1, enode* n1, unsigned r2_num_parents) {
|
||||
enode* r2 = r1->get_root();
|
||||
r2->dec_class_size(r1->class_size());
|
||||
|
@ -82,6 +41,9 @@ namespace euf {
|
|||
enode* n = enode::mk(m_region, f, num_args, args);
|
||||
m_nodes.push_back(n);
|
||||
m_exprs.push_back(f);
|
||||
push_node(n);
|
||||
for (unsigned i = 0; i < num_args; ++i)
|
||||
set_merge_enabled(args[i], true);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -104,8 +66,7 @@ namespace euf {
|
|||
void egraph::reinsert_equality(enode* p) {
|
||||
SASSERT(is_equality(p));
|
||||
if (p->get_arg(0)->get_root() == p->get_arg(1)->get_root()) {
|
||||
m_new_lits.push_back(enode_bool_pair(p, true));
|
||||
++m_stats.m_num_eqs;
|
||||
add_literal(p, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,19 +75,14 @@ namespace euf {
|
|||
}
|
||||
|
||||
void egraph::force_push() {
|
||||
if (m_num_scopes == 0)
|
||||
return;
|
||||
for (; m_num_scopes > 0; --m_num_scopes) {
|
||||
scope s;
|
||||
s.m_inconsistent = m_inconsistent;
|
||||
s.m_num_eqs = m_eqs.size();
|
||||
s.m_num_nodes = m_nodes.size();
|
||||
s.m_trail_sz = m_trail.size();
|
||||
s.m_new_lits_sz = m_new_lits.size();
|
||||
s.m_new_th_eqs_sz = m_new_th_eqs.size();
|
||||
s.m_new_lits_qhead = m_new_lits_qhead;
|
||||
s.m_new_th_eqs_qhead = m_new_th_eqs_qhead;
|
||||
m_scopes.push_back(s);
|
||||
m_scopes.push_back(m_updates.size());
|
||||
m_region.push_scope();
|
||||
}
|
||||
m_updates.push_back(update_record(m_new_lits_qhead, update_record::new_lits_qhead()));
|
||||
m_updates.push_back(update_record(m_new_th_eqs_qhead, update_record::new_th_eq_qhead()));
|
||||
}
|
||||
|
||||
void egraph::update_children(enode* n) {
|
||||
|
@ -147,6 +103,7 @@ namespace euf {
|
|||
return n;
|
||||
if (is_equality(n)) {
|
||||
update_children(n);
|
||||
reinsert_equality(n);
|
||||
return n;
|
||||
}
|
||||
enode_bool_pair p = m_table.insert(n);
|
||||
|
@ -170,6 +127,18 @@ namespace euf {
|
|||
n->m_parents.finalize();
|
||||
}
|
||||
|
||||
void egraph::add_th_eq(theory_id id, theory_var v1, theory_var v2, enode* c, enode* r) {
|
||||
m_new_th_eqs.push_back(th_eq(id, v1, v2, c, r));
|
||||
m_updates.push_back(update_record(update_record::new_th_eq()));
|
||||
++m_stats.m_num_th_eqs;
|
||||
}
|
||||
|
||||
void egraph::add_literal(enode* n, bool is_eq) {
|
||||
m_new_lits.push_back(enode_bool_pair(n, is_eq));
|
||||
m_updates.push_back(update_record(update_record::new_lit()));
|
||||
if (is_eq) ++m_stats.m_num_eqs; else ++m_stats.m_num_lits;
|
||||
}
|
||||
|
||||
void egraph::add_th_var(enode* n, theory_var v, theory_id id) {
|
||||
force_push();
|
||||
theory_var w = n->get_th_var(id);
|
||||
|
@ -177,21 +146,37 @@ namespace euf {
|
|||
|
||||
if (w == null_theory_var) {
|
||||
n->add_th_var(v, id, m_region);
|
||||
m_trail.push_back(new (m_region) add_th_var_trail(n, id));
|
||||
m_updates.push_back(update_record(n, id, update_record::add_th_var()));
|
||||
if (r != n) {
|
||||
theory_var u = r->get_th_var(id);
|
||||
if (u == null_theory_var)
|
||||
r->add_th_var(v, id, m_region);
|
||||
else
|
||||
m_new_th_eqs.push_back(th_eq(id, v, u, n, r));
|
||||
add_th_eq(id, v, u, n, r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
theory_var u = r->get_th_var(id);
|
||||
SASSERT(u != v && u != null_theory_var);
|
||||
n->replace_th_var(v, id);
|
||||
m_trail.push_back(new (m_region) replace_th_var_trail(n, id, u));
|
||||
m_new_th_eqs.push_back(th_eq(id, v, u, n, r));
|
||||
m_updates.push_back(update_record(n, id, u, update_record::replace_th_var()));
|
||||
add_th_eq(id, v, u, n, r);
|
||||
}
|
||||
}
|
||||
|
||||
void egraph::undo_add_th_var(enode* n, theory_id tid) {
|
||||
theory_var v = n->get_th_var(tid);
|
||||
SASSERT(v != null_theory_var);
|
||||
n->del_th_var(tid);
|
||||
enode* root = n->get_root();
|
||||
if (root != n && root->get_th_var(tid) == v)
|
||||
root->del_th_var(tid);
|
||||
}
|
||||
|
||||
void egraph::set_merge_enabled(enode* n, bool enable_merge) {
|
||||
if (enable_merge != n->merge_enabled()) {
|
||||
m_updates.push_back(update_record(n, update_record::toggle_merge()));
|
||||
n->set_merge_enabled(enable_merge);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,29 +187,59 @@ namespace euf {
|
|||
}
|
||||
num_scopes -= m_num_scopes;
|
||||
unsigned old_lim = m_scopes.size() - num_scopes;
|
||||
scope s = m_scopes[old_lim];
|
||||
for (unsigned i = m_eqs.size(); i-- > s.m_num_eqs; ) {
|
||||
auto const& p = m_eqs[i];
|
||||
undo_eq(p.r1, p.n1, p.r2_num_parents);
|
||||
}
|
||||
for (unsigned i = m_nodes.size(); i-- > s.m_num_nodes; ) {
|
||||
enode* n = m_nodes[i];
|
||||
unsigned num_updates = m_scopes[old_lim];
|
||||
auto undo_node = [&](enode* n) {
|
||||
if (n->num_args() > 1)
|
||||
m_table.erase(n);
|
||||
m_expr2enode[n->get_owner_id()] = nullptr;
|
||||
n->~enode();
|
||||
}
|
||||
undo_trail_stack<egraph>(*this, m_trail, s.m_trail_sz);
|
||||
m_inconsistent = s.m_inconsistent;
|
||||
m_new_lits_qhead = s.m_new_lits_qhead;
|
||||
m_new_th_eqs_qhead = s.m_new_th_eqs_qhead;
|
||||
m_eqs.shrink(s.m_num_eqs);
|
||||
m_nodes.shrink(s.m_num_nodes);
|
||||
m_exprs.shrink(s.m_num_nodes);
|
||||
m_new_lits.shrink(s.m_new_lits_sz);
|
||||
m_new_th_eqs.shrink(s.m_new_th_eqs_sz);
|
||||
m_nodes.pop_back();
|
||||
m_exprs.pop_back();
|
||||
};
|
||||
for (unsigned i = m_updates.size(); i-- > num_updates; ) {
|
||||
auto const& p = m_updates[i];
|
||||
switch (p.tag) {
|
||||
case update_record::tag_t::is_add_node:
|
||||
undo_node(p.r1);
|
||||
break;
|
||||
case update_record::tag_t::is_toggle_merge:
|
||||
p.r1->set_merge_enabled(!p.r1->merge_enabled());
|
||||
break;
|
||||
case update_record::tag_t::is_set_parent:
|
||||
undo_eq(p.r1, p.n1, p.r2_num_parents);
|
||||
break;
|
||||
case update_record::tag_t::is_add_th_var:
|
||||
undo_add_th_var(p.r1, p.r2_num_parents);
|
||||
break;
|
||||
case update_record::tag_t::is_replace_th_var:
|
||||
SASSERT(p.r1->get_th_var(p.m_th_id) != null_theory_var);
|
||||
p.r1->replace_th_var(p.m_old_th_var, p.m_th_id);
|
||||
break;
|
||||
case update_record::tag_t::is_new_lit:
|
||||
m_new_lits.pop_back();
|
||||
break;
|
||||
case update_record::tag_t::is_new_th_eq:
|
||||
m_new_th_eqs.pop_back();
|
||||
break;
|
||||
case update_record::tag_t::is_new_th_eq_qhead:
|
||||
m_new_th_eqs_qhead = p.qhead;
|
||||
break;
|
||||
case update_record::tag_t::is_new_lits_qhead:
|
||||
m_new_lits_qhead = p.qhead;
|
||||
break;
|
||||
case update_record::tag_t::is_inconsistent:
|
||||
m_inconsistent = p.m_inconsistent;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_updates.shrink(num_updates);
|
||||
m_scopes.shrink(old_lim);
|
||||
m_region.pop_scope(num_scopes);
|
||||
m_worklist.reset();
|
||||
}
|
||||
|
||||
void egraph::merge(enode* n1, enode* n2, justification j) {
|
||||
|
@ -245,8 +260,7 @@ namespace euf {
|
|||
std::swap(n1, n2);
|
||||
}
|
||||
if ((m.is_true(r2->get_owner()) || m.is_false(r2->get_owner())) && j.is_congruence()) {
|
||||
m_new_lits.push_back(enode_bool_pair(n1, false));
|
||||
++m_stats.m_num_lits;
|
||||
add_literal(n1, false);
|
||||
}
|
||||
for (enode* p : enode_parents(n1))
|
||||
m_table.erase(p);
|
||||
|
@ -268,13 +282,13 @@ namespace euf {
|
|||
for (auto iv : enode_th_vars(n)) {
|
||||
theory_id id = iv.get_id();
|
||||
theory_var v = root->get_th_var(id);
|
||||
if (v == null_theory_var) {
|
||||
root->add_th_var(iv.get_var(), id, m_region);
|
||||
m_trail.push_back(new (m_region) add_th_var_trail(root, id));
|
||||
if (v == null_theory_var) {
|
||||
root->add_th_var(iv.get_var(), id, m_region);
|
||||
m_updates.push_back(update_record(root, id, update_record::add_th_var()));
|
||||
}
|
||||
else {
|
||||
SASSERT(v != iv.get_var());
|
||||
m_new_th_eqs.push_back(th_eq(id, v, iv.get_var(), n, root));
|
||||
add_th_eq(id, v, iv.get_var(), n, root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -308,6 +322,7 @@ namespace euf {
|
|||
if (m_inconsistent)
|
||||
return;
|
||||
m_inconsistent = true;
|
||||
m_updates.push_back(update_record(false, update_record::inconsistent()));
|
||||
m_n1 = n1;
|
||||
m_n2 = n2;
|
||||
m_justification = j;
|
||||
|
@ -387,10 +402,19 @@ namespace euf {
|
|||
}
|
||||
}
|
||||
|
||||
void egraph::begin_explain() {
|
||||
SASSERT(m_todo.empty());
|
||||
}
|
||||
|
||||
void egraph::end_explain() {
|
||||
for (enode* n : m_todo)
|
||||
n->unmark1();
|
||||
m_todo.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void egraph::explain(ptr_vector<T>& justifications) {
|
||||
SASSERT(m_inconsistent);
|
||||
SASSERT(m_todo.empty());
|
||||
push_todo(m_n1);
|
||||
push_todo(m_n2);
|
||||
explain_eq(justifications, m_n1, m_n2, m_justification);
|
||||
|
@ -399,7 +423,6 @@ namespace euf {
|
|||
|
||||
template <typename T>
|
||||
void egraph::explain_eq(ptr_vector<T>& justifications, enode* a, enode* b) {
|
||||
SASSERT(m_todo.empty());
|
||||
SASSERT(a->get_root() == b->get_root());
|
||||
enode* lca = find_lca(a, b);
|
||||
push_to_lca(a, lca);
|
||||
|
@ -418,9 +441,6 @@ namespace euf {
|
|||
explain_eq(justifications, n, n->m_target, n->m_justification);
|
||||
}
|
||||
}
|
||||
for (enode* n : m_todo)
|
||||
n->unmark1();
|
||||
m_todo.reset();
|
||||
}
|
||||
|
||||
void egraph::invariant() {
|
||||
|
@ -429,25 +449,29 @@ namespace euf {
|
|||
}
|
||||
|
||||
std::ostream& egraph::display(std::ostream& out, unsigned max_args, enode* n) const {
|
||||
out << std::setw(5)
|
||||
<< n->get_owner_id() << " := ";
|
||||
out << n->get_owner_id() << " := ";
|
||||
if (!n->is_root())
|
||||
out << "[" << n->get_root()->get_owner_id() << "] ";
|
||||
expr* f = n->get_owner();
|
||||
if (is_app(f))
|
||||
out << to_app(f)->get_decl()->get_name() << " ";
|
||||
out << mk_bounded_pp(f, m, 1);
|
||||
else if (is_quantifier(f))
|
||||
out << "q ";
|
||||
out << "q:" << f->get_id();
|
||||
else
|
||||
out << "v ";
|
||||
for (enode* arg : enode_args(n))
|
||||
out << arg->get_owner_id() << " ";
|
||||
for (unsigned i = n->num_args(); i < max_args; ++i)
|
||||
out << " ";
|
||||
out << "\t";
|
||||
for (enode* p : enode_parents(n))
|
||||
out << p->get_owner_id() << " ";
|
||||
out << "v:" << f->get_id();
|
||||
out << "\n";
|
||||
if (!n->m_parents.empty()) {
|
||||
out << " ";
|
||||
for (enode* p : enode_parents(n))
|
||||
out << p->get_owner_id() << " ";
|
||||
out << "\n";
|
||||
}
|
||||
if (n->has_th_vars()) {
|
||||
out << " ";
|
||||
for (auto v : enode_th_vars(n))
|
||||
out << v.get_id() << ":" << v.get_var() << " ";
|
||||
out << "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -464,8 +488,9 @@ namespace euf {
|
|||
void egraph::collect_statistics(statistics& st) const {
|
||||
st.update("euf merge", m_stats.m_num_merge);
|
||||
st.update("euf conflicts", m_stats.m_num_conflicts);
|
||||
st.update("euf eq prop", m_stats.m_num_eqs);
|
||||
st.update("euf lit prop", m_stats.m_num_lits);
|
||||
st.update("euf equality propagations", m_stats.m_num_eqs);
|
||||
st.update("euf theory equality propagations", m_stats.m_num_th_eqs);
|
||||
st.update("euf literal propagations", m_stats.m_num_lits);
|
||||
}
|
||||
|
||||
void egraph::copy_from(egraph const& src, std::function<void*(void*)>& copy_justification) {
|
||||
|
@ -504,7 +529,7 @@ template void euf::egraph::explain(ptr_vector<int>& justifications);
|
|||
template void euf::egraph::explain_todo(ptr_vector<int>& justifications);
|
||||
template void euf::egraph::explain_eq(ptr_vector<int>& justifications, enode* a, enode* b);
|
||||
|
||||
template void euf::egraph::explain(ptr_vector<unsigned>& justifications);
|
||||
template void euf::egraph::explain_todo(ptr_vector<unsigned>& justifications);
|
||||
template void euf::egraph::explain_eq(ptr_vector<unsigned>& justifications, enode* a, enode* b);
|
||||
template void euf::egraph::explain(ptr_vector<size_t>& justifications);
|
||||
template void euf::egraph::explain_todo(ptr_vector<size_t>& justifications);
|
||||
template void euf::egraph::explain_eq(ptr_vector<size_t>& justifications, enode* a, enode* b);
|
||||
|
||||
|
|
|
@ -31,14 +31,6 @@ Notes:
|
|||
|
||||
namespace euf {
|
||||
|
||||
struct add_eq_record {
|
||||
enode* r1;
|
||||
enode* n1;
|
||||
unsigned r2_num_parents;
|
||||
add_eq_record(enode* r1, enode* n1, unsigned r2_num_parents):
|
||||
r1(r1), n1(n1), r2_num_parents(r2_num_parents) {}
|
||||
};
|
||||
|
||||
/***
|
||||
\brief store derived theory equalities.
|
||||
Theory 'id' is notified with the equality of theory variables v1, v2
|
||||
|
@ -58,31 +50,66 @@ namespace euf {
|
|||
|
||||
class egraph {
|
||||
typedef ptr_vector<trail<egraph> > trail_stack;
|
||||
struct scope {
|
||||
bool m_inconsistent;
|
||||
unsigned m_num_eqs;
|
||||
unsigned m_num_nodes;
|
||||
unsigned m_trail_sz;
|
||||
unsigned m_new_lits_sz;
|
||||
unsigned m_new_th_eqs_sz;
|
||||
unsigned m_new_lits_qhead;
|
||||
unsigned m_new_th_eqs_qhead;
|
||||
};
|
||||
struct stats {
|
||||
unsigned m_num_merge;
|
||||
unsigned m_num_th_eqs;
|
||||
unsigned m_num_lits;
|
||||
unsigned m_num_eqs;
|
||||
unsigned m_num_conflicts;
|
||||
stats() { reset(); }
|
||||
void reset() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
struct update_record {
|
||||
struct toggle_merge {};
|
||||
struct add_th_var {};
|
||||
struct replace_th_var {};
|
||||
struct new_lit {};
|
||||
struct new_th_eq {};
|
||||
struct new_th_eq_qhead {};
|
||||
struct new_lits_qhead {};
|
||||
struct inconsistent {};
|
||||
enum tag_t { is_set_parent, is_add_node, is_toggle_merge,
|
||||
is_add_th_var, is_replace_th_var, is_new_lit, is_new_th_eq,
|
||||
is_new_th_eq_qhead, is_new_lits_qhead, is_inconsistent };
|
||||
tag_t tag;
|
||||
enode* r1;
|
||||
enode* n1;
|
||||
union {
|
||||
unsigned r2_num_parents;
|
||||
struct {
|
||||
unsigned m_th_id : 8;
|
||||
unsigned m_old_th_var : 24;
|
||||
};
|
||||
unsigned qhead;
|
||||
bool m_inconsistent;
|
||||
};
|
||||
update_record(enode* r1, enode* n1, unsigned r2_num_parents) :
|
||||
tag(tag_t::is_set_parent), r1(r1), n1(n1), r2_num_parents(r2_num_parents) {}
|
||||
update_record(enode* n) :
|
||||
tag(tag_t::is_add_node), r1(n), n1(nullptr), r2_num_parents(UINT_MAX) {}
|
||||
update_record(enode* n, toggle_merge) :
|
||||
tag(tag_t::is_toggle_merge), r1(n), n1(nullptr), r2_num_parents(UINT_MAX) {}
|
||||
update_record(enode* n, unsigned id, add_th_var) :
|
||||
tag(tag_t::is_add_th_var), r1(n), n1(nullptr), r2_num_parents(id) {}
|
||||
update_record(enode* n, theory_id id, theory_var v, replace_th_var) :
|
||||
tag(tag_t::is_replace_th_var), r1(n), n1(nullptr), m_th_id(id), m_old_th_var(v) {}
|
||||
update_record(new_lit) :
|
||||
tag(tag_t::is_new_lit), r1(nullptr), n1(nullptr), r2_num_parents(0) {}
|
||||
update_record(new_th_eq) :
|
||||
tag(tag_t::is_new_th_eq), r1(nullptr), n1(nullptr), r2_num_parents(0) {}
|
||||
update_record(unsigned qh, new_th_eq_qhead):
|
||||
tag(tag_t::is_new_th_eq_qhead), r1(nullptr), n1(nullptr), qhead(qh) {}
|
||||
update_record(unsigned qh, new_lits_qhead):
|
||||
tag(tag_t::is_new_lits_qhead), r1(nullptr), n1(nullptr), qhead(qh) {}
|
||||
update_record(bool inc, inconsistent) :
|
||||
tag(tag_t::is_inconsistent), m_inconsistent(inc) {}
|
||||
};
|
||||
ast_manager& m;
|
||||
trail_stack m_trail;
|
||||
region m_region;
|
||||
enode_vector m_worklist;
|
||||
etable m_table;
|
||||
svector<add_eq_record> m_eqs;
|
||||
svector<scope> m_scopes;
|
||||
region m_region;
|
||||
svector<update_record> m_updates;
|
||||
unsigned_vector m_scopes;
|
||||
enode_vector m_expr2enode;
|
||||
enode_vector m_nodes;
|
||||
expr_ref_vector m_exprs;
|
||||
|
@ -101,9 +128,14 @@ namespace euf {
|
|||
std::function<void(app*,app*)> m_used_cc;
|
||||
|
||||
void push_eq(enode* r1, enode* n1, unsigned r2_num_parents) {
|
||||
m_eqs.push_back(add_eq_record(r1, n1, r2_num_parents));
|
||||
m_updates.push_back(update_record(r1, n1, r2_num_parents));
|
||||
}
|
||||
void push_node(enode* n) { m_updates.push_back(update_record(n)); }
|
||||
|
||||
void add_th_eq(theory_id id, theory_var v1, theory_var v2, enode* c, enode* r);
|
||||
void add_literal(enode* n, bool is_eq);
|
||||
void undo_eq(enode* r1, enode* n1, unsigned r2_num_parents);
|
||||
void undo_add_th_var(enode* n, theory_id id);
|
||||
enode* mk_enode(expr* f, unsigned num_args, enode * const* args);
|
||||
void reinsert(enode* n);
|
||||
void force_push();
|
||||
|
@ -173,10 +205,13 @@ namespace euf {
|
|||
|
||||
|
||||
void add_th_var(enode* n, theory_var v, theory_id id);
|
||||
void set_merge_enabled(enode* n, bool enable_merge);
|
||||
|
||||
void set_used_eq(std::function<void(expr*,expr*,expr*)>& used_eq) { m_used_eq = used_eq; }
|
||||
void set_used_cc(std::function<void(app*,app*)>& used_cc) { m_used_cc = used_cc; }
|
||||
|
||||
void begin_explain();
|
||||
void end_explain();
|
||||
template <typename T>
|
||||
void explain(ptr_vector<T>& justifications);
|
||||
template <typename T>
|
||||
|
|
|
@ -36,21 +36,22 @@ namespace euf {
|
|||
const theory_id null_theory_id = -1;
|
||||
|
||||
class enode {
|
||||
expr* m_owner;
|
||||
expr* m_owner{ nullptr };
|
||||
bool m_mark1 { false };
|
||||
bool m_mark2 { false };
|
||||
bool m_commutative { false };
|
||||
bool m_update_children { false };
|
||||
bool m_interpreted { false };
|
||||
bool m_merge_enabled { true };
|
||||
unsigned m_class_size { 1 };
|
||||
unsigned m_table_id { UINT_MAX };
|
||||
enode_vector m_parents;
|
||||
enode* m_next;
|
||||
enode* m_root;
|
||||
enode* m_next{ nullptr };
|
||||
enode* m_root{ nullptr };
|
||||
enode* m_target { nullptr };
|
||||
th_var_list m_th_vars;
|
||||
justification m_justification;
|
||||
unsigned m_num_args;
|
||||
unsigned m_num_args { 0 };
|
||||
enode* m_args[0];
|
||||
|
||||
friend class enode_args;
|
||||
|
@ -73,6 +74,7 @@ namespace euf {
|
|||
n->m_root = n;
|
||||
n->m_commutative = num_args == 2 && is_app(f) && to_app(f)->get_decl()->is_commutative();
|
||||
n->m_num_args = num_args;
|
||||
n->m_merge_enabled = true;
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
SASSERT(to_app(f)->get_arg(i) == args[i]->get_owner());
|
||||
n->m_args[i] = args[i];
|
||||
|
@ -86,7 +88,8 @@ namespace euf {
|
|||
friend class replace_th_var_trail;
|
||||
void add_th_var(theory_var v, theory_id id, region & r) { m_th_vars.add_var(v, id, r); }
|
||||
void replace_th_var(theory_var v, theory_id id) { m_th_vars.replace(v, id); }
|
||||
void del_th_var(theory_id id) { m_th_vars.del_var(id); }
|
||||
void del_th_var(theory_id id) { m_th_vars.del_var(id); }
|
||||
void set_merge_enabled(bool m) { m_merge_enabled = m; }
|
||||
|
||||
public:
|
||||
~enode() {
|
||||
|
@ -106,6 +109,7 @@ namespace euf {
|
|||
bool interpreted() const { return m_interpreted; }
|
||||
bool commutative() const { return m_commutative; }
|
||||
void mark_interpreted() { SASSERT(num_args() == 0); m_interpreted = true; }
|
||||
bool merge_enabled() { return m_merge_enabled; }
|
||||
|
||||
enode* get_arg(unsigned i) const { SASSERT(i < num_args()); return m_args[i]; }
|
||||
unsigned hash() const { return m_owner->hash(); }
|
||||
|
@ -143,6 +147,7 @@ namespace euf {
|
|||
unsigned get_owner_id() const { return m_owner->get_id(); }
|
||||
unsigned get_root_id() const { return m_root->m_owner->get_id(); }
|
||||
theory_var get_th_var(theory_id id) const { return m_th_vars.find(id); }
|
||||
bool is_attached_to(theory_id id) const { return get_th_var(id) != null_theory_var; }
|
||||
bool has_th_vars() const { return !m_th_vars.empty(); }
|
||||
|
||||
void inc_class_size(unsigned n) { m_class_size += n; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue