3
0
Fork 0
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:
Nikolaj Bjorner 2020-09-02 10:42:07 -07:00
parent 141edef0d6
commit 116390833b
27 changed files with 492 additions and 336 deletions

View file

@ -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) {

View file

@ -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);

View file

@ -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); }