3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 01:25:31 +00:00
* arrays

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* arrays

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* na

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* arrays

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* na

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* fill

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* update drat and fix euf bugs

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>

* const qualifiers

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* na

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* reorg ba

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* reorg

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* build warnings

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-09-13 19:29:59 -07:00 committed by GitHub
parent d56dd1db7b
commit 796e2fd9eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
79 changed files with 2571 additions and 1850 deletions

View file

@ -1785,13 +1785,12 @@ bool ast_manager::slow_not_contains(ast const * n) {
}
#endif
#if 0
static unsigned s_count = 0;
#if 0
static void track_id(ast_manager& m, ast* n, unsigned id) {
if (n->get_id() != id) return;
++s_count;
std::cout << &m << " " << s_count << "\n";
SASSERT(s_count != 240);
TRACE("ast", tout << s_count << "\n";);
}
#endif
@ -1825,9 +1824,9 @@ ast * ast_manager::register_node_core(ast * n) {
n->m_id = is_decl(n) ? m_decl_id_gen.mk() : m_expr_id_gen.mk();
// track_id(*this, n, 254);
// track_id(*this, n, 3);
TRACE("ast", tout << "Object " << n->m_id << " was created.\n";);
TRACE("ast", tout << (s_count++) << " Object " << n->m_id << " was created.\n";);
TRACE("mk_var_bug", tout << "mk_ast: " << n->m_id << "\n";);
// increment reference counters
switch (n->get_kind()) {

View file

@ -81,8 +81,10 @@ namespace euf {
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()));
m_updates.push_back(update_record(m_new_lits_qhead, update_record::new_lits_qhead()));
SASSERT(m_new_lits_qhead <= m_new_lits.size());
SASSERT(m_new_th_eqs_qhead <= m_new_th_eqs.size());
}
void egraph::update_children(enode* n) {
@ -107,17 +109,23 @@ namespace euf {
return n;
}
enode_bool_pair p = m_table.insert(n);
enode* r = p.first;
if (r == n) {
enode* n2 = p.first;
if (n2 == n) {
update_children(n);
}
else {
SASSERT(r->get_expr() != n->get_expr());
merge_justification(n, r, justification::congruence(p.second));
std::swap(n->m_next, r->m_next);
n->m_root = r;
r->inc_class_size(n->class_size());
push_eq(n, n, r->num_parents());
merge(n, n2, justification::congruence(p.second));
#if 0
SASSERT(n2->get_expr() != n->get_expr());
SASSERT(n->class_size() == 1);
SASSERT(n->is_root());
merge_justification(n, n2, justification::congruence(p.second));
enode* r2 = n2->get_root();
std::swap(n->m_next, r2->m_next);
n->m_root = r2;
r2->inc_class_size(n->class_size());
push_eq(n, n, r2->num_parents());
#endif
}
return n;
}
@ -128,12 +136,14 @@ namespace euf {
}
void egraph::add_th_eq(theory_id id, theory_var v1, theory_var v2, enode* c, enode* r) {
TRACE("euf_verbose", tout << "eq: " << v1 << " == " << v2 << "\n";);
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) {
TRACE("euf_verbose", tout << "lit: " << n->get_expr_id() << "\n";);
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;
@ -186,6 +196,9 @@ namespace euf {
return;
}
num_scopes -= m_num_scopes;
m_num_scopes = 0;
SASSERT(m_new_lits_qhead <= m_new_lits.size());
unsigned old_lim = m_scopes.size() - num_scopes;
unsigned num_updates = m_scopes[old_lim];
auto undo_node = [&](enode* n) {
@ -240,16 +253,19 @@ namespace euf {
m_scopes.shrink(old_lim);
m_region.pop_scope(num_scopes);
m_worklist.reset();
SASSERT(m_new_lits_qhead <= m_new_lits.size());
SASSERT(m_new_th_eqs_qhead <= m_new_th_eqs.size());
}
void egraph::merge(enode* n1, enode* n2, justification j) {
void egraph::merge(enode* n1, enode* n2, justification j) {
SASSERT(m.get_sort(n1->get_expr()) == m.get_sort(n2->get_expr()));
TRACE("euf", tout << n1->get_expr_id() << " == " << n2->get_expr_id() << "\n";);
force_push();
enode* r1 = n1->get_root();
enode* r2 = n2->get_root();
if (r1 == r2)
return;
TRACE("euf", j.display(tout << n1->get_expr_id() << " == " << n2->get_expr_id() << " ", m_display_justification) << "\n";);
force_push();
SASSERT(m_num_scopes == 0);
++m_stats.m_num_merge;
if (r1->interpreted() && r2->interpreted()) {
set_conflict(n1, n2, j);
@ -294,6 +310,7 @@ namespace euf {
}
bool egraph::propagate() {
SASSERT(m_new_lits_qhead <= m_new_lits.size());
SASSERT(m_num_scopes == 0 || m_worklist.empty());
unsigned head = 0, tail = m_worklist.size();
while (head < tail && m.limit().inc() && !inconsistent()) {
@ -311,6 +328,7 @@ namespace euf {
tail = m_worklist.size();
}
m_worklist.reset();
force_push();
return
(m_new_lits_qhead < m_new_lits.size()) ||
(m_new_th_eqs_qhead < m_new_th_eqs.size()) ||
@ -329,17 +347,27 @@ namespace euf {
}
void egraph::merge_justification(enode* n1, enode* n2, justification j) {
SASSERT(!n1->get_root()->m_target);
SASSERT(!n2->get_root()->m_target);
SASSERT(n1->reaches(n1->get_root()));
SASSERT(!n2->reaches(n1->get_root()));
SASSERT(!n2->reaches(n1));
n1->reverse_justification();
n1->m_target = n2;
n1->m_justification = j;
SASSERT(n1->acyclic());
SASSERT(n2->acyclic());
SASSERT(n1->get_root()->reaches(n1));
SASSERT(!n2->get_root()->m_target);
TRACE("euf_verbose", tout << "merge " << n1->get_expr_id() << " " << n2->get_expr_id() << " updates: " << m_updates.size() << "\n";);
}
void egraph::unmerge_justification(enode* n1) {
TRACE("euf_verbose", tout << "unmerge " << n1->get_expr_id() << " " << n1->m_target->get_expr_id() << "\n";);
// r1 -> .. -> n1 -> n2 -> ... -> r2
// where n2 = n1->m_target
SASSERT(n1->get_root()->reaches(n1));
SASSERT(n1->m_target);
n1->m_target = nullptr;
n1->m_justification = justification::axiom();
n1->get_root()->reverse_justification();
@ -347,7 +375,7 @@ namespace euf {
// n1 -> ... -> r1
// n2 -> ... -> r2
SASSERT(n1->reaches(n1->get_root()));
SASSERT(n1->get_root()->m_target == nullptr);
SASSERT(!n1->get_root()->m_target);
}
/**
@ -359,8 +387,9 @@ namespace euf {
void egraph::push_congruence(enode* n1, enode* n2, bool comm) {
SASSERT(is_app(n1->get_expr()));
SASSERT(n1->get_decl() == n2->get_decl());
if (m_used_cc)
if (m_used_cc && !comm) {
m_used_cc(to_app(n1->get_expr()), to_app(n2->get_expr()));
}
if (comm &&
n1->get_arg(0)->get_root() == n2->get_arg(1)->get_root() &&
n1->get_arg(1)->get_root() == n2->get_arg(0)->get_root()) {
@ -409,6 +438,7 @@ namespace euf {
void egraph::end_explain() {
for (enode* n : m_todo)
n->unmark1();
DEBUG_CODE(for (enode* n : m_nodes) SASSERT(!n->is_marked1()););
m_todo.reset();
}
@ -424,7 +454,12 @@ namespace euf {
template <typename T>
void egraph::explain_eq(ptr_vector<T>& justifications, enode* a, enode* b) {
SASSERT(a->get_root() == b->get_root());
enode* lca = find_lca(a, b);
TRACE("euf_verbose", tout << "explain-eq: " << a->get_expr_id() << " = " << b->get_expr_id()
<< ": " << mk_bounded_pp(a->get_expr(), m)
<< " == " << mk_bounded_pp(b->get_expr(), m)
<< " lca: " << mk_bounded_pp(lca->get_expr(), m) << "\n";);
push_to_lca(a, lca);
push_to_lca(b, lca);
if (m_used_eq)
@ -438,6 +473,7 @@ namespace euf {
enode* n = m_todo[i];
if (n->m_target && !n->is_marked1()) {
n->mark1();
CTRACE("euf", m_display_justification, n->m_justification.display(tout << n->get_expr_id() << " = " << n->m_target->get_expr_id() << " ", m_display_justification) << "\n";);
explain_eq(justifications, n, n->m_target, n->m_justification);
}
}
@ -461,21 +497,26 @@ namespace euf {
out << "v:" << f->get_id();
out << "\n";
if (!n->m_parents.empty()) {
out << " ";
out << " parents ";
for (enode* p : enode_parents(n))
out << p->get_expr_id() << " ";
out << "\n";
}
if (n->has_th_vars()) {
out << " ";
out << " theories ";
for (auto v : enode_th_vars(n))
out << v.get_id() << ":" << v.get_var() << " ";
out << "\n";
}
if (n->m_target && m_display_justification)
n->m_justification.display(out << " = " << n->m_target->get_expr_id() << " j: ", m_display_justification) << "\n";
return out;
}
std::ostream& egraph::display(std::ostream& out) const {
out << "updates " << m_updates.size() << "\n";
out << "newlits " << m_new_lits.size() << " qhead: " << m_new_lits_qhead << "\n";
out << "neweqs " << m_new_th_eqs.size() << " qhead: " << m_new_th_eqs_qhead << "\n";
m_table.display(out);
unsigned max_args = 0;
for (enode* n : m_nodes)

View file

@ -125,7 +125,8 @@ namespace euf {
enode_vector m_todo;
stats m_stats;
std::function<void(expr*,expr*,expr*)> m_used_eq;
std::function<void(app*,app*)> m_used_cc;
std::function<void(app*,app*)> m_used_cc;
std::function<void(std::ostream&, void*)> m_display_justification;
void push_eq(enode* r1, enode* n1, unsigned r2_num_parents) {
m_updates.push_back(update_record(r1, n1, r2_num_parents));
@ -151,6 +152,7 @@ namespace euf {
void push_to_lca(enode* a, enode* lca);
void push_congruence(enode* n1, enode* n2, bool commutative);
void push_todo(enode* n);
template <typename T>
void explain_eq(ptr_vector<T>& justifications, enode* a, enode* b, justification const& j) {
if (j.is_external())
@ -200,8 +202,8 @@ namespace euf {
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 next_literal() { force_push(); SASSERT(m_new_lits_qhead < m_new_lits.size()); m_new_lits_qhead++; }
void next_th_eq() { force_push(); 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);
@ -209,7 +211,8 @@ namespace euf {
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 set_display_justification(std::function<void (std::ostream&, void*)> & d) { m_display_justification = d; }
void begin_explain();
void end_explain();
template <typename T>
@ -228,6 +231,8 @@ namespace euf {
e_pp pp(enode* n) const { return e_pp(*this, n); }
std::ostream& display(std::ostream& out) const;
void collect_statistics(statistics& st) const;
unsigned num_scopes() const { return m_scopes.size() + m_num_scopes; }
};
inline std::ostream& operator<<(std::ostream& out, egraph const& g) { return g.display(out); }

View file

@ -31,7 +31,8 @@ namespace euf {
VERIFY(found_root);
VERIFY(found_this);
VERIFY(this != m_root || class_size == m_class_size);
if (this == m_root) {
if (is_root()) {
VERIFY(!m_target);
for (enode* p : enode_parents(this)) {
bool found = false;
for (enode* arg : enode_args(p)) {
@ -69,8 +70,24 @@ namespace euf {
return true;
}
bool enode::acyclic() const {
enode const* n = this;
enode const* p = this;
while (n) {
n = n->m_target;
if (n) {
p = p->m_target;
n = n->m_target;
}
if (n == p)
return false;
}
return true;
}
bool enode::reaches(enode* n) const {
enode const* r = this;
SASSERT(acyclic());
while (r) {
if (r == n)
return true;

View file

@ -156,6 +156,7 @@ namespace euf {
void reverse_justification();
bool reaches(enode* n) const;
bool acyclic() const;
enode* const* begin_parents() const { return m_parents.begin(); }
enode* const* end_parents() const { return m_parents.end(); }

View file

@ -215,8 +215,6 @@ namespace euf {
return enode_bool_pair(n_prime, false);
case BINARY:
n_prime = UNTAG(binary_table*, t)->insert_if_not_there(n);
TRACE("euf", tout << "insert: " << n->get_expr_id() << " " << cg_binary_hash()(n) << " inserted: " << (n == n_prime) << " " << n_prime->get_expr_id() << "\n";
display_binary(tout, t); tout << "contains_ptr: " << contains_ptr(n) << "\n";);
return enode_bool_pair(n_prime, false);
case BINARY_COMM:
m_commutativity = false;
@ -236,7 +234,6 @@ namespace euf {
UNTAG(unary_table*, t)->erase(n);
break;
case BINARY:
TRACE("euf", tout << "erase: " << n->get_expr_id() << " " << cg_binary_hash()(n) << " contains: " << contains_ptr(n) << "\n";);
UNTAG(binary_table*, t)->erase(n);
break;
case BINARY_COMM:

View file

@ -20,7 +20,7 @@ Author:
namespace euf {
class justification {
enum kind_t {
enum class kind_t {
axiom_t,
congruence_t,
external_t
@ -29,20 +29,20 @@ namespace euf {
bool m_comm;
void* m_external;
justification(bool comm):
m_kind(congruence_t),
m_kind(kind_t::congruence_t),
m_comm(comm),
m_external(nullptr)
{}
justification(void* ext):
m_kind(external_t),
m_kind(kind_t::external_t),
m_comm(false),
m_external(ext)
{}
public:
justification():
m_kind(axiom_t),
m_kind(kind_t::axiom_t),
m_comm(false),
m_external(nullptr)
{}
@ -51,24 +51,43 @@ namespace euf {
static justification congruence(bool c) { return justification(c); }
static justification external(void* ext) { return justification(ext); }
bool is_external() const { return m_kind == external_t; }
bool is_congruence() const { return m_kind == congruence_t; }
bool is_external() const { return m_kind == kind_t::external_t; }
bool is_congruence() const { return m_kind == kind_t::congruence_t; }
bool is_commutative() const { return m_comm; }
template <typename T>
T* ext() const { SASSERT(is_external()); return static_cast<T*>(m_external); }
justification copy(std::function<void*(void*)>& copy_justification) const {
switch (m_kind) {
case external_t:
case kind_t::external_t:
return external(copy_justification(m_external));
case axiom_t:
case kind_t::axiom_t:
return axiom();
case congruence_t:
case kind_t::congruence_t:
return congruence(m_comm);
default:
UNREACHABLE();
return axiom();
}
}
std::ostream& display(std::ostream& out, std::function<void (std::ostream&, void*)> const& ext) const {
switch (m_kind) {
case kind_t::external_t:
if (ext)
ext(out, m_external);
else
out << "external";
return out;
case kind_t::axiom_t:
return out << "axiom";
case kind_t::congruence_t:
return out << "congruence";
default:
UNREACHABLE();
return out;
}
return out;
}
};
}