mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
prepare for theory plugins
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
141edef0d6
commit
116390833b
27 changed files with 492 additions and 336 deletions
|
@ -35,7 +35,7 @@ namespace euf {
|
|||
|
||||
void undo(egraph & ctx) override {
|
||||
theory_var v = m_enode->get_th_var(m_th_id);
|
||||
SASSERT(v != null_var);
|
||||
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)
|
||||
|
@ -43,6 +43,26 @@ namespace euf {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\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());
|
||||
|
@ -84,7 +104,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_eqs.push_back(p);
|
||||
m_new_lits.push_back(enode_bool_pair(p, true));
|
||||
++m_stats.m_num_eqs;
|
||||
}
|
||||
}
|
||||
|
@ -93,25 +113,17 @@ namespace euf {
|
|||
return m.is_eq(p->get_owner());
|
||||
}
|
||||
|
||||
void egraph::dedup_equalities() {
|
||||
unsigned j = 0;
|
||||
for (enode* p : m_new_eqs) {
|
||||
if (!p->is_marked1())
|
||||
m_new_eqs[j++] = p;
|
||||
p->mark1();
|
||||
}
|
||||
for (enode* p : m_new_eqs)
|
||||
p->unmark1();
|
||||
m_new_eqs.shrink(j);
|
||||
}
|
||||
|
||||
void egraph::force_push() {
|
||||
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_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_region.push_scope();
|
||||
}
|
||||
|
@ -160,10 +172,27 @@ namespace euf {
|
|||
|
||||
void egraph::add_th_var(enode* n, theory_var v, theory_id id) {
|
||||
force_push();
|
||||
SASSERT(null_var == n->get_th_var(id));
|
||||
SASSERT(n->class_size() == 1);
|
||||
n->add_th_var(v, id, m_region);
|
||||
m_trail.push_back(new (m_region) add_th_var_trail(n, id));
|
||||
theory_var w = n->get_th_var(id);
|
||||
enode* r = n->get_root();
|
||||
|
||||
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));
|
||||
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));
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
void egraph::pop(unsigned num_scopes) {
|
||||
|
@ -187,9 +216,13 @@ namespace euf {
|
|||
}
|
||||
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_scopes.shrink(old_lim);
|
||||
m_region.pop_scope(num_scopes);
|
||||
}
|
||||
|
@ -212,7 +245,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(n1);
|
||||
m_new_lits.push_back(enode_pair(n1, false));
|
||||
++m_stats.m_num_lits;
|
||||
}
|
||||
for (enode* p : enode_parents(n1))
|
||||
|
@ -235,7 +268,7 @@ 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_var) {
|
||||
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));
|
||||
}
|
||||
|
@ -246,10 +279,7 @@ namespace euf {
|
|||
}
|
||||
}
|
||||
|
||||
void egraph::propagate() {
|
||||
m_new_eqs.reset();
|
||||
m_new_lits.reset();
|
||||
m_new_th_eqs.reset();
|
||||
bool egraph::propagate() {
|
||||
SASSERT(m_num_scopes == 0 || m_worklist.empty());
|
||||
unsigned head = 0, tail = m_worklist.size();
|
||||
while (head < tail && m.limit().inc() && !inconsistent()) {
|
||||
|
@ -267,7 +297,10 @@ namespace euf {
|
|||
tail = m_worklist.size();
|
||||
}
|
||||
m_worklist.reset();
|
||||
dedup_equalities();
|
||||
return
|
||||
(m_new_lits_qhead < m_new_lits.size()) ||
|
||||
(m_new_th_eqs_qhead < m_new_th_eqs.size()) ||
|
||||
inconsistent();
|
||||
}
|
||||
|
||||
void egraph::set_conflict(enode* n1, enode* n2, justification j) {
|
||||
|
|
|
@ -63,6 +63,10 @@ namespace euf {
|
|||
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;
|
||||
|
@ -87,8 +91,9 @@ namespace euf {
|
|||
enode *m_n1 { nullptr };
|
||||
enode *m_n2 { nullptr };
|
||||
justification m_justification;
|
||||
enode_vector m_new_eqs;
|
||||
enode_vector m_new_lits;
|
||||
unsigned m_new_lits_qhead { 0 };
|
||||
unsigned m_new_th_eqs_qhead { 0 };
|
||||
svector<enode_bool_pair> m_new_lits;
|
||||
svector<th_eq> m_new_th_eqs;
|
||||
enode_vector m_todo;
|
||||
stats m_stats;
|
||||
|
@ -107,7 +112,6 @@ namespace euf {
|
|||
void merge_th_eq(enode* n, enode* root);
|
||||
void merge_justification(enode* n1, enode* n2, justification j);
|
||||
void unmerge_justification(enode* n1);
|
||||
void dedup_equalities();
|
||||
void reinsert_equality(enode* p);
|
||||
void update_children(enode* n);
|
||||
void push_lca(enode* a, enode* b);
|
||||
|
@ -151,11 +155,22 @@ namespace euf {
|
|||
equated nodes are merged. Use then new_eqs() to extract the vector
|
||||
of new equalities.
|
||||
*/
|
||||
void propagate();
|
||||
bool propagate();
|
||||
bool inconsistent() const { return m_inconsistent; }
|
||||
enode_vector const& new_eqs() const { return m_new_eqs; }
|
||||
enode_vector const& new_lits() const { return m_new_lits; }
|
||||
svector<th_eq> const& new_th_eqs() const { return m_new_th_eqs; }
|
||||
|
||||
/**
|
||||
\brief Maintain and update cursor into propagated consequences.
|
||||
The result of get_literal() is a pair (n, is_eq)
|
||||
where \c n is an enode and \c is_eq indicates whether the enode
|
||||
is an equality consequence.
|
||||
*/
|
||||
bool has_literal() const { return m_new_lits_qhead < m_new_lits.size(); }
|
||||
bool has_th_eq() const { return m_new_th_eqs_qhead < m_new_th_eqs.size(); }
|
||||
enode_bool_pair get_literal() const { return m_new_lits[m_new_lits_qhead]; }
|
||||
th_eq get_th_eq() const { return m_new_th_eqs[m_new_th_eqs_qhead]; }
|
||||
void next_literal() { SASSERT(m_new_lits_qhead < m_new_lits.size()); m_new_lits_qhead++; }
|
||||
void next_th_eq() { SASSERT(m_new_th_eqs_qhead < m_new_th_eqs.size()); m_new_th_eqs_qhead++; }
|
||||
|
||||
|
||||
void add_th_var(enode* n, theory_var v, theory_id id);
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ namespace euf {
|
|||
typedef id_var_list<> th_var_list;
|
||||
typedef int theory_var;
|
||||
typedef int theory_id;
|
||||
const theory_var null_var = -1;
|
||||
const theory_id null_id = -1;
|
||||
const theory_var null_theory_var = -1;
|
||||
const theory_id null_theory_id = -1;
|
||||
|
||||
class enode {
|
||||
expr* m_owner;
|
||||
|
@ -83,6 +83,7 @@ namespace euf {
|
|||
void set_update_children() { m_update_children = true; }
|
||||
|
||||
friend class add_th_var_trail;
|
||||
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); }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue