Skip to content

Commit

Permalink
release nodes
Browse files Browse the repository at this point in the history
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
  • Loading branch information
NikolajBjorner committed Aug 31, 2020
1 parent bbe027f commit a003af4
Show file tree
Hide file tree
Showing 15 changed files with 319 additions and 135 deletions.
5 changes: 5 additions & 0 deletions src/ast/euf/euf_egraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ namespace euf {
return n;
}

void egraph::~egraph() {
for (enode* n : m_nodes)
n->~enode();
}

void egraph::pop(unsigned num_scopes) {
if (num_scopes <= m_num_scopes) {
m_num_scopes -= num_scopes;
Expand Down
1 change: 1 addition & 0 deletions src/ast/euf/euf_egraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ namespace euf {

public:
egraph(ast_manager& m): m(m), m_table(m), m_exprs(m) {}
~egraph();
enode* find(expr* f) { return m_expr2enode.get(f->get_id(), nullptr); }
enode* mk(expr* f, unsigned n, enode *const* args);
void push() { ++m_num_scopes; }
Expand Down
2 changes: 1 addition & 1 deletion src/ast/euf/euf_etable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ namespace euf {
binary_table* tb = UNTAG(binary_table*, t);
out << "b ";
for (enode* n : *tb) {
out << n->get_owner_id() << " " << cg_binary_hash()(n) << " ";
out << n->get_owner_id() << " ";
}
out << "\n";
}
Expand Down
1 change: 1 addition & 0 deletions src/sat/smt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ z3_add_component(sat_smt
xor_solver.cpp
ba_internalize.cpp
euf_ackerman.cpp
euf_internalize.cpp
euf_solver.cpp
euf_model.cpp
COMPONENT_DEPENDENCIES
Expand Down
9 changes: 5 additions & 4 deletions src/sat/smt/ba_internalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ Module Name:

namespace sat {

literal ba_solver::internalize(expr* e, bool sign, bool root) {
literal ba_solver::internalize(expr* e, bool sign, bool root, bool redundant) {
flet<bool> _redundant(m_is_redundant, redundant);
if (m_pb.is_pb(e))
return internalize_pb(e, sign, root);
if (m.is_xor(e))
Expand All @@ -35,7 +36,7 @@ namespace sat {
sat::bool_var v = s().add_var(true);
lits.push_back(literal(v, true));
auto add_expr = [&](expr* a) {
literal lit = si.internalize(a);
literal lit = si.internalize(a, m_is_redundant);
s().set_external(lit.var());
lits.push_back(lit);
};
Expand All @@ -47,7 +48,7 @@ namespace sat {
for (unsigned i = 1; i + 1 < lits.size(); ++i) {
lits[i].neg();
}
add_xr(lits);
add_xr(lits, m_is_redundant);
auto* aig = s().get_cut_simplifier();
if (aig) aig->add_xor(~lits.back(), lits.size() - 1, lits.c_ptr() + 1);
sat::literal lit(v, sign);
Expand Down Expand Up @@ -100,7 +101,7 @@ namespace sat {

void ba_solver::convert_pb_args(app* t, literal_vector& lits) {
for (expr* arg : *t) {
lits.push_back(si.internalize(arg));
lits.push_back(si.internalize(arg, m_is_redundant));
s().set_external(lits.back().var());
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/sat/smt/ba_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1748,7 +1748,7 @@ namespace sat {

void ba_solver::add_at_least(bool_var v, literal_vector const& lits, unsigned k) {
literal lit = v == null_bool_var ? null_literal : literal(v, false);
add_at_least(lit, lits, k, false);
add_at_least(lit, lits, k, m_is_redundant);
}

ba_solver::constraint* ba_solver::add_at_least(literal lit, literal_vector const& lits, unsigned k, bool learned) {
Expand Down Expand Up @@ -1840,7 +1840,7 @@ namespace sat {

void ba_solver::add_pb_ge(bool_var v, svector<wliteral> const& wlits, unsigned k) {
literal lit = v == null_bool_var ? null_literal : literal(v, false);
add_pb_ge(lit, wlits, k, false);
add_pb_ge(lit, wlits, k, m_is_redundant);
}

/*
Expand Down
3 changes: 2 additions & 1 deletion src/sat/smt/ba_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ namespace sat {
void convert_to_wlits(app* t, sat::literal_vector const& lits, svector<wliteral>& wlits);
void convert_pb_args(app* t, svector<wliteral>& wlits);
void convert_pb_args(app* t, literal_vector& lits);
bool m_is_redundant{ false };
literal internalize_pb(expr* e, bool sign, bool root);
literal internalize_xor(expr* e, bool sign, bool root);

Expand Down Expand Up @@ -599,7 +600,7 @@ namespace sat {
bool is_blocked(literal l, ext_constraint_idx idx) override;
bool check_model(model const& m) const override;

literal internalize(expr* e, bool sign, bool root) override;
literal internalize(expr* e, bool sign, bool root, bool redundant) override;
bool to_formulas(std::function<expr_ref(sat::literal)>& l2e, expr_ref_vector& fmls) override;
th_solver* fresh(solver* s, ast_manager& m, sat_internalizer& si) override;

Expand Down
10 changes: 5 additions & 5 deletions src/sat/smt/euf_ackerman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,11 @@ namespace euf {
unsigned sz = a->get_num_args();
for (unsigned i = 0; i < sz; ++i) {
expr_ref eq(m.mk_eq(a->get_arg(i), b->get_arg(i)), m);
sat::literal lit = s.internalize(eq, true, false);
sat::literal lit = s.internalize(eq, true, false, true);
lits.push_back(~lit);
}
expr_ref eq(m.mk_eq(a, b), m);
lits.push_back(s.internalize(eq, false, false));
lits.push_back(s.internalize(eq, false, false, true));
s.s().mk_clause(lits, true);
}

Expand All @@ -202,9 +202,9 @@ namespace euf {
expr_ref eq1(m.mk_eq(a, c), m);
expr_ref eq2(m.mk_eq(b, c), m);
expr_ref eq3(m.mk_eq(a, b), m);
lits[0] = s.internalize(eq1, true, false);
lits[1] = s.internalize(eq2, true, false);
lits[2] = s.internalize(eq3, false, false);
lits[0] = s.internalize(eq1, true, false, true);
lits[1] = s.internalize(eq2, true, false, true);
lits[2] = s.internalize(eq3, false, false, true);
s.s().mk_clause(3, lits, true);
}
}
242 changes: 242 additions & 0 deletions src/sat/smt/euf_internalize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
/*++
Copyright (c) 2020 Microsoft Corporation
Module Name:
euf_internalize.cpp
Abstract:
Internalize utilities for EUF solver plugin.
Author:
Nikolaj Bjorner (nbjorner) 2020-08-25
--*/

#include "ast/ast_pp.h"
#include "ast/pb_decl_plugin.h"
#include "tactic/tactic_exception.h"
#include "sat/smt/euf_solver.h"

namespace euf {

sat::literal solver::internalize(expr* e, bool sign, bool root, bool learned) {
flet<bool> _is_learned(m_is_redundant, learned);
auto* ext = get_solver(e);
if (ext)
return ext->internalize(e, sign, root, learned);
IF_VERBOSE(110, verbose_stream() << "internalize: " << mk_pp(e, m) << "\n");
SASSERT(!si.is_bool_op(e));
sat::scoped_stack _sc(m_stack);
unsigned sz = m_stack.size();
euf::enode* n = visit(e);
while (m_stack.size() > sz) {
loop:
if (!m.inc())
throw tactic_exception(m.limit().get_cancel_msg());
sat::frame & fr = m_stack.back();
expr* e = fr.m_e;
if (m_egraph.find(e)) {
m_stack.pop_back();
continue;
}
unsigned num = is_app(e) ? to_app(e)->get_num_args() : 0;

while (fr.m_idx < num) {
expr* arg = to_app(e)->get_arg(fr.m_idx);
fr.m_idx++;
n = visit(arg);
if (!n)
goto loop;
}
m_args.reset();
for (unsigned i = 0; i < num; ++i)
m_args.push_back(m_egraph.find(to_app(e)->get_arg(i)));
if (root && internalize_root(to_app(e), m_args.c_ptr(), sign))
return sat::null_literal;
n = m_egraph.mk(e, num, m_args.c_ptr());
attach_node(n);
}
SASSERT(m_egraph.find(e));
return literal(m_expr2var.to_bool_var(e), sign);
}

euf::enode* solver::visit(expr* e) {
euf::enode* n = m_egraph.find(e);
if (n)
return n;
if (si.is_bool_op(e)) {
sat::literal lit = si.internalize(e, m_is_redundant);
n = m_var2node.get(lit.var(), nullptr);
if (n && !lit.sign())
return n;

n = m_egraph.mk(e, 0, nullptr);
attach_lit(lit, n);
if (!m.is_true(e) && !m.is_false(e))
s().set_external(lit.var());
return n;
}
if (is_app(e) && to_app(e)->get_num_args() > 0) {
m_stack.push_back(sat::frame(e));
return nullptr;
}
n = m_egraph.mk(e, 0, nullptr);
attach_node(n);
return n;
}

void solver::attach_node(euf::enode* n) {
expr* e = n->get_owner();
if (m.is_bool(e)) {
sat::bool_var v = si.add_bool_var(e);
attach_lit(literal(v, false), n);
}
axiomatize_basic(n);
}

void solver::attach_lit(literal lit, euf::enode* n) {
if (lit.sign()) {
sat::bool_var v = si.add_bool_var(n->get_owner());
sat::literal lit2 = literal(v, false);
s().mk_clause(~lit, lit2, false);
s().mk_clause(lit, ~lit2, false);
lit = lit2;
}
sat::bool_var v = lit.var();
m_var2node.reserve(v + 1, nullptr);
SASSERT(m_var2node[v] == nullptr);
m_var2node[v] = n;
m_var_trail.push_back(v);
}

bool solver::internalize_root(app* e, enode* const* args, bool sign) {
if (m.is_distinct(e)) {
if (sign)
add_not_distinct_axiom(e, args);
else
add_distinct_axiom(e, args);
return true;
}
return false;
}

void solver::add_not_distinct_axiom(app* e, enode* const* args) {
SASSERT(m.is_distinct(e));
unsigned sz = e->get_num_args();
if (sz <= 1)
return;

static const unsigned distinct_max_args = 24;
if (sz <= distinct_max_args) {
sat::literal_vector lits;
for (unsigned i = 0; i < sz; ++i) {
for (unsigned j = i + 1; j < sz; ++j) {
expr_ref eq(m.mk_eq(args[i]->get_owner(), args[j]->get_owner()), m);
sat::literal lit = internalize(eq, false, false, m_is_redundant);
lits.push_back(lit);
}
}
s().mk_clause(lits, false);
}
else {
// g(f(x_i)) = x_i
// f(x_1) = a + .... + f(x_n) = a >= 2
sort* srt = m.get_sort(e->get_arg(0));
SASSERT(!m.is_bool(srt));
sort_ref u(m.mk_fresh_sort("distinct-elems"), m);
sort* u_ptr = u.get();
func_decl_ref f(m.mk_fresh_func_decl("dist-f", "", 1, &srt, u), m);
func_decl_ref g(m.mk_fresh_func_decl("dist-g", "", 1, &u_ptr, srt), m);
expr_ref a(m.mk_fresh_const("a", u), m);
expr_ref_vector eqs(m);
for (expr* arg : *e) {
expr_ref fapp(m.mk_app(f, arg), m);
expr_ref gapp(m.mk_app(g, fapp.get()), m);
expr_ref eq(m.mk_eq(gapp, arg), m);
sat::literal lit = internalize(eq, false, false, m_is_redundant);
s().add_clause(1, &lit, false);
eqs.push_back(m.mk_eq(fapp, a));
}
pb_util pb(m);
expr_ref at_least2(pb.mk_at_least_k(eqs.size(), eqs.c_ptr(), 2), m);
sat::literal lit = si.internalize(at_least2, m_is_redundant);
s().mk_clause(1, &lit, false);
}
}

void solver::add_distinct_axiom(app* e, enode* const* args) {
SASSERT(m.is_distinct(e));
static const unsigned distinct_max_args = 24;
unsigned sz = e->get_num_args();
if (sz <= 1) {
s().mk_clause(0, nullptr, m_is_redundant);
return;
}
if (sz <= distinct_max_args) {
for (unsigned i = 0; i < sz; ++i) {
for (unsigned j = i + 1; j < sz; ++j) {
expr_ref eq(m.mk_eq(args[i]->get_owner(), args[j]->get_owner()), m);
sat::literal lit = internalize(eq, true, false, m_is_redundant);
s().add_clause(1, &lit, m_is_redundant);
}
}
}
else {
// dist-f(x_1) = v_1 & ... & dist-f(x_n) = v_n
sort* srt = m.get_sort(e->get_arg(0));
SASSERT(!m.is_bool(srt));
sort_ref u(m.mk_fresh_sort("distinct-elems"), m);
func_decl_ref f(m.mk_fresh_func_decl("dist-f", "", 1, &srt, u), m);
for (unsigned i = 0; i < sz; ++i) {
expr_ref fapp(m.mk_app(f, e->get_arg(i)), m);
expr_ref fresh(m.mk_fresh_const("dist-value", u), m);
enode* n = m_egraph.mk(fresh, 0, nullptr);
n->mark_interpreted();
expr_ref eq(m.mk_eq(fapp, fresh), m);
sat::literal lit = internalize(eq, false, false, m_is_redundant);
s().add_clause(1, &lit, m_is_redundant);
}
}
}

void solver::axiomatize_basic(enode* n) {
expr* e = n->get_owner();
if (m.is_ite(e)) {
app* a = to_app(e);
expr* c = a->get_arg(0);
expr* th = a->get_arg(1);
expr* el = a->get_arg(2);
sat::bool_var v = m_expr2var.to_bool_var(c);
SASSERT(v != sat::null_bool_var);
expr_ref eq_th(m.mk_eq(a, th), m);
expr_ref eq_el(m.mk_eq(a, el), m);
sat::literal lit_th = internalize(eq_th, false, false, m_is_redundant);
sat::literal lit_el = internalize(eq_el, false, false, m_is_redundant);
literal lits1[2] = { literal(v, true), lit_th };
literal lits2[2] = { literal(v, false), lit_el };
s().add_clause(2, lits1, m_is_redundant);
s().add_clause(2, lits2, m_is_redundant);
}
else if (m.is_distinct(e)) {
expr_ref_vector eqs(m);
unsigned sz = n->num_args();
for (unsigned i = 0; i < sz; ++i) {
for (unsigned j = i + 1; j < sz; ++j) {
expr_ref eq(m.mk_eq(n->get_arg(i)->get_owner(), n->get_arg(j)->get_owner()), m);
eqs.push_back(eq);
}
}
expr_ref fml(m.mk_or(eqs), m);
sat::literal dist(m_expr2var.to_bool_var(e), false);
sat::literal some_eq = si.internalize(fml, m_is_redundant);
sat::literal lits1[2] = { ~dist, ~some_eq };
sat::literal lits2[2] = { dist, some_eq };
s().add_clause(2, lits1, m_is_redundant);
s().add_clause(2, lits2, m_is_redundant);
}
}

}
Loading

0 comments on commit a003af4

Please sign in to comment.