mirror of
https://github.com/Z3Prover/z3
synced 2025-08-27 05:26:01 +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
|
@ -9,6 +9,7 @@ z3_add_component(sat_smt
|
|||
euf_model.cpp
|
||||
euf_proof.cpp
|
||||
euf_solver.cpp
|
||||
sat_th.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
sat
|
||||
ast
|
||||
|
|
|
@ -19,6 +19,7 @@ Author:
|
|||
#include "util/mpz.h"
|
||||
#include "sat/sat_types.h"
|
||||
#include "sat/smt/ba_solver.h"
|
||||
#include "sat/smt/euf_solver.h"
|
||||
#include "sat/sat_simplifier_params.hpp"
|
||||
#include "sat/sat_xor_finder.h"
|
||||
|
||||
|
@ -359,7 +360,7 @@ namespace sat {
|
|||
}
|
||||
if (p.k() == 1 && p.lit() == null_literal) {
|
||||
literal_vector lits(p.literals());
|
||||
s().mk_clause(lits.size(), lits.c_ptr(), p.learned());
|
||||
s().mk_clause(lits.size(), lits.c_ptr(), status::ba(p.learned()));
|
||||
IF_VERBOSE(100, display(verbose_stream() << "add clause: " << lits << "\n", p, true););
|
||||
remove_constraint(p, "implies clause");
|
||||
}
|
||||
|
@ -411,7 +412,7 @@ namespace sat {
|
|||
|
||||
if (k == 1 && p.lit() == null_literal) {
|
||||
literal_vector lits(sz, p.literals().c_ptr());
|
||||
s().mk_clause(sz, lits.c_ptr(), p.learned());
|
||||
s().mk_clause(sz, lits.c_ptr(), status::ba(p.learned()));
|
||||
remove_constraint(p, "is clause");
|
||||
return;
|
||||
}
|
||||
|
@ -794,7 +795,7 @@ namespace sat {
|
|||
|
||||
else if (k == 1 && p.lit() == null_literal) {
|
||||
literal_vector lits(sz, p.literals().c_ptr());
|
||||
s().mk_clause(sz, lits.c_ptr(), p.learned());
|
||||
s().mk_clause(sz, lits.c_ptr(), status::ba(p.learned()));
|
||||
remove_constraint(p, "recompiled to clause");
|
||||
return;
|
||||
}
|
||||
|
@ -1597,7 +1598,7 @@ namespace sat {
|
|||
TRACE("ba", tout << m_lemma << "\n";);
|
||||
|
||||
if (get_config().m_drat && m_solver) {
|
||||
s().m_drat.add(m_lemma, sat::drat::status::ba);
|
||||
s().m_drat.add(m_lemma, sat::status::ba_redundant());
|
||||
}
|
||||
|
||||
s().m_lemma.reset();
|
||||
|
@ -1719,8 +1720,12 @@ namespace sat {
|
|||
return p;
|
||||
}
|
||||
|
||||
ba_solver::ba_solver(ast_manager& m, sat_internalizer& si)
|
||||
: m(m), si(si), m_pb(m),
|
||||
ba_solver::ba_solver(euf::solver& ctx, euf::theory_id id) :
|
||||
ba_solver(ctx.get_manager(), ctx.get_si(), id) {}
|
||||
|
||||
ba_solver::ba_solver(ast_manager& m, sat::sat_internalizer& si, euf::theory_id id)
|
||||
: euf::th_solver(m, id),
|
||||
si(si), m_pb(m),
|
||||
m_solver(nullptr), m_lookahead(nullptr),
|
||||
m_constraint_id(0), m_ba(*this), m_sort(m_ba) {
|
||||
TRACE("ba", tout << this << "\n";);
|
||||
|
@ -1745,7 +1750,7 @@ namespace sat {
|
|||
ba_solver::constraint* ba_solver::add_at_least(literal lit, literal_vector const& lits, unsigned k, bool learned) {
|
||||
if (k == 1 && lit == null_literal) {
|
||||
literal_vector _lits(lits);
|
||||
s().mk_clause(_lits.size(), _lits.c_ptr(), learned);
|
||||
s().mk_clause(_lits.size(), _lits.c_ptr(), status::ba(learned));
|
||||
return nullptr;
|
||||
}
|
||||
if (!learned && clausify(lit, lits.size(), lits.c_ptr(), k)) {
|
||||
|
@ -2135,7 +2140,7 @@ namespace sat {
|
|||
for (literal lit : r)
|
||||
lits.push_back(~lit);
|
||||
lits.push_back(l);
|
||||
s().m_drat.add(lits, sat::drat::status::ba);
|
||||
s().m_drat.add(lits, sat::status::ba_redundant());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2894,7 +2899,7 @@ namespace sat {
|
|||
|
||||
if (k == 1 && c.lit() == null_literal) {
|
||||
literal_vector lits(sz, c.literals().c_ptr());
|
||||
s().mk_clause(sz, lits.c_ptr(), c.learned());
|
||||
s().mk_clause(sz, lits.c_ptr(), sat::status::ba(c.learned()));
|
||||
remove_constraint(c, "recompiled to clause");
|
||||
return;
|
||||
}
|
||||
|
@ -2902,27 +2907,27 @@ namespace sat {
|
|||
if (sz == 0) {
|
||||
if (c.lit() == null_literal) {
|
||||
if (k > 0) {
|
||||
s().mk_clause(0, nullptr, true);
|
||||
s().mk_clause(0, nullptr, status::ba_asserted());
|
||||
}
|
||||
}
|
||||
else if (k > 0) {
|
||||
literal lit = ~c.lit();
|
||||
s().mk_clause(1, &lit, c.learned());
|
||||
s().mk_clause(1, &lit, status::ba(c.learned()));
|
||||
}
|
||||
else {
|
||||
literal lit = c.lit();
|
||||
s().mk_clause(1, &lit, c.learned());
|
||||
s().mk_clause(1, &lit, status::ba(c.learned()));
|
||||
}
|
||||
remove_constraint(c, "recompiled to clause");
|
||||
return;
|
||||
}
|
||||
if (all_units && sz < k) {
|
||||
if (c.lit() == null_literal) {
|
||||
s().mk_clause(0, nullptr, true);
|
||||
s().mk_clause(0, nullptr, status::ba_redundant());
|
||||
}
|
||||
else {
|
||||
literal lit = ~c.lit();
|
||||
s().mk_clause(1, &lit, c.learned());
|
||||
s().mk_clause(1, &lit, status::ba(c.learned()));
|
||||
}
|
||||
remove_constraint(c, "recompiled to clause");
|
||||
return;
|
||||
|
@ -3719,12 +3724,16 @@ namespace sat {
|
|||
}
|
||||
|
||||
extension* ba_solver::copy(solver* s) {
|
||||
return fresh(s, m, si);
|
||||
return fresh(s, m, si, m_id);
|
||||
}
|
||||
|
||||
th_solver* ba_solver::fresh(solver* s, ast_manager& m, sat_internalizer& si) {
|
||||
ba_solver* result = alloc(ba_solver, m, si);
|
||||
result->set_solver(s);
|
||||
euf::th_solver* ba_solver::fresh(solver* new_s, euf::solver& new_ctx) {
|
||||
return fresh(new_s, new_ctx.get_manager(), new_ctx.get_si(), get_id());
|
||||
}
|
||||
|
||||
euf::th_solver* ba_solver::fresh(solver* new_s, ast_manager& m, sat::sat_internalizer& si, euf::theory_id id) {
|
||||
ba_solver* result = alloc(ba_solver, m, si, id);
|
||||
result->set_solver(new_s);
|
||||
copy_constraints(result, m_constraints);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace sat {
|
|||
|
||||
class xor_finder;
|
||||
|
||||
class ba_solver : public th_solver {
|
||||
class ba_solver : public euf::th_solver {
|
||||
|
||||
friend class local_search;
|
||||
|
||||
|
@ -232,7 +232,6 @@ namespace sat {
|
|||
bool contains(literal l) const { for (auto wl : m_wlits) if (wl.second == l) return true; return false; }
|
||||
};
|
||||
|
||||
ast_manager& m;
|
||||
sat_internalizer& si;
|
||||
pb_util m_pb;
|
||||
|
||||
|
@ -305,6 +304,9 @@ namespace sat {
|
|||
bool_vector m_root_vars;
|
||||
unsigned_vector m_weights;
|
||||
svector<wliteral> m_wlits;
|
||||
|
||||
euf::th_solver* ba_solver::fresh(sat::solver* new_s, ast_manager& m, sat::sat_internalizer& si, euf::theory_id id);
|
||||
|
||||
bool subsumes(card& c1, card& c2, literal_vector& comp);
|
||||
bool subsumes(card& c1, clause& c2, bool& self);
|
||||
bool subsumed(card& c1, literal l1, literal l2);
|
||||
|
@ -563,7 +565,8 @@ namespace sat {
|
|||
expr_ref get_xor(std::function<expr_ref(sat::literal)>& l2e, ba_solver::xr const& x);
|
||||
|
||||
public:
|
||||
ba_solver(ast_manager& m, sat_internalizer& si);
|
||||
ba_solver(euf::solver& ctx, euf::theory_id id);
|
||||
ba_solver(ast_manager& m, sat::sat_internalizer& si, euf::theory_id id);
|
||||
~ba_solver() override;
|
||||
void set_solver(solver* s) override { m_solver = s; }
|
||||
void set_lookahead(lookahead* l) override { m_lookahead = l; }
|
||||
|
@ -602,7 +605,7 @@ namespace sat {
|
|||
|
||||
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;
|
||||
euf::th_solver* fresh(solver* s, euf::solver& ctx) override;
|
||||
|
||||
ptr_vector<constraint> const & constraints() const { return m_constraints; }
|
||||
std::ostream& display(std::ostream& out, constraint const& c, bool values) const;
|
||||
|
|
|
@ -194,7 +194,7 @@ namespace euf {
|
|||
}
|
||||
expr_ref eq(m.mk_eq(a, b), m);
|
||||
lits.push_back(s.internalize(eq, false, false, true));
|
||||
s.s().mk_clause(lits, true);
|
||||
s.s().mk_clause(lits, sat::status::euf_learned());
|
||||
}
|
||||
|
||||
void ackerman::add_eq(expr* a, expr* b, expr* c) {
|
||||
|
@ -205,6 +205,6 @@ namespace euf {
|
|||
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);
|
||||
s.s().mk_clause(3, lits, sat::status::euf_learned());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,11 +22,11 @@ Author:
|
|||
|
||||
namespace euf {
|
||||
|
||||
sat::literal solver::internalize(expr* e, bool sign, bool root, bool learned) {
|
||||
flet<bool> _is_learned(m_is_redundant, learned);
|
||||
sat::literal solver::internalize(expr* e, bool sign, bool root, bool redundant) {
|
||||
flet<bool> _is_learned(m_is_redundant, redundant);
|
||||
auto* ext = get_solver(e);
|
||||
if (ext)
|
||||
return ext->internalize(e, sign, root, learned);
|
||||
return ext->internalize(e, sign, root, redundant);
|
||||
IF_VERBOSE(110, verbose_stream() << "internalize: " << mk_pp(e, m) << "\n");
|
||||
SASSERT(!si.is_bool_op(e));
|
||||
sat::scoped_stack _sc(m_stack);
|
||||
|
@ -103,8 +103,8 @@ namespace euf {
|
|||
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);
|
||||
s().mk_clause(~lit, lit2, sat::status::euf_asserted());
|
||||
s().mk_clause(lit, ~lit2, sat::status::euf_asserted());
|
||||
lit = lit2;
|
||||
}
|
||||
sat::bool_var v = lit.var();
|
||||
|
@ -132,6 +132,7 @@ namespace euf {
|
|||
if (sz <= 1)
|
||||
return;
|
||||
|
||||
sat::status st = m_is_redundant ? sat::status::euf_learned() : sat::status::euf_asserted();
|
||||
static const unsigned distinct_max_args = 32;
|
||||
if (sz <= distinct_max_args) {
|
||||
sat::literal_vector lits;
|
||||
|
@ -142,7 +143,7 @@ namespace euf {
|
|||
lits.push_back(lit);
|
||||
}
|
||||
}
|
||||
s().mk_clause(lits, false);
|
||||
s().mk_clause(lits, st);
|
||||
}
|
||||
else {
|
||||
// g(f(x_i)) = x_i
|
||||
|
@ -160,13 +161,13 @@ namespace euf {
|
|||
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, m_is_redundant);
|
||||
s().add_clause(1, &lit, st);
|
||||
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, m_is_redundant);
|
||||
s().mk_clause(1, &lit, st);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,8 +175,9 @@ namespace euf {
|
|||
SASSERT(m.is_distinct(e));
|
||||
static const unsigned distinct_max_args = 32;
|
||||
unsigned sz = e->get_num_args();
|
||||
sat::status st = m_is_redundant ? sat::status::euf_learned() : sat::status::euf_asserted();
|
||||
if (sz <= 1) {
|
||||
s().mk_clause(0, nullptr, m_is_redundant);
|
||||
s().mk_clause(0, nullptr, st);
|
||||
return;
|
||||
}
|
||||
if (sz <= distinct_max_args) {
|
||||
|
@ -183,7 +185,7 @@ namespace euf {
|
|||
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);
|
||||
s().add_clause(1, &lit, st);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,13 +202,14 @@ namespace euf {
|
|||
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);
|
||||
s().add_clause(1, &lit, st);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void solver::axiomatize_basic(enode* n) {
|
||||
expr* e = n->get_owner();
|
||||
sat::status st = m_is_redundant ? sat::status::euf_learned() : sat::status::euf_asserted();
|
||||
if (m.is_ite(e)) {
|
||||
app* a = to_app(e);
|
||||
expr* c = a->get_arg(0);
|
||||
|
@ -221,8 +224,8 @@ namespace euf {
|
|||
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);
|
||||
s().add_clause(2, lits1, st);
|
||||
s().add_clause(2, lits2, st);
|
||||
}
|
||||
else if (m.is_distinct(e)) {
|
||||
expr_ref_vector eqs(m);
|
||||
|
@ -238,8 +241,8 @@ namespace euf {
|
|||
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);
|
||||
s().add_clause(2, lits1, st);
|
||||
s().add_clause(2, lits2, st);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace euf {
|
|||
return true;
|
||||
if (f->get_family_id() == m.get_basic_family_id())
|
||||
return false;
|
||||
sat::th_model_builder* mb = get_solver(f);
|
||||
euf::th_model_builder* mb = get_solver(f);
|
||||
return mb && mb->include_func_interp(f);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace euf {
|
|||
for (literal lit : r) lits.push_back(~lit);
|
||||
if (l != sat::null_literal)
|
||||
lits.push_back(l);
|
||||
s().get_drat().add(lits, sat::drat::status::euf);
|
||||
s().get_drat().add(lits, sat::status::euf_learned());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace euf {
|
|||
/**
|
||||
* retrieve extension that is associated with Boolean variable.
|
||||
*/
|
||||
sat::th_solver* solver::get_solver(sat::bool_var v) {
|
||||
th_solver* solver::get_solver(sat::bool_var v) {
|
||||
if (v >= m_var2node.size())
|
||||
return nullptr;
|
||||
euf::enode* n = m_var2node[v];
|
||||
|
@ -41,13 +41,13 @@ namespace euf {
|
|||
return get_solver(n->get_owner());
|
||||
}
|
||||
|
||||
sat::th_solver* solver::get_solver(expr* e) {
|
||||
th_solver* solver::get_solver(expr* e) {
|
||||
if (is_app(e))
|
||||
return get_solver(to_app(e)->get_decl());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sat::th_solver* solver::get_solver(func_decl* f) {
|
||||
th_solver* solver::get_solver(func_decl* f) {
|
||||
family_id fid = f->get_family_id();
|
||||
if (fid == null_family_id)
|
||||
return nullptr;
|
||||
|
@ -58,7 +58,7 @@ namespace euf {
|
|||
return nullptr;
|
||||
pb_util pb(m);
|
||||
if (pb.get_family_id() == fid) {
|
||||
ext = alloc(sat::ba_solver, m, si);
|
||||
ext = alloc(sat::ba_solver, *this, fid);
|
||||
}
|
||||
if (ext) {
|
||||
ext->set_solver(m_solver);
|
||||
|
@ -71,7 +71,7 @@ namespace euf {
|
|||
return ext;
|
||||
}
|
||||
|
||||
void solver::add_solver(family_id fid, sat::th_solver* th) {
|
||||
void solver::add_solver(family_id fid, th_solver* th) {
|
||||
m_solvers.push_back(th);
|
||||
m_id2solver.setx(fid, th, nullptr);
|
||||
}
|
||||
|
@ -173,43 +173,52 @@ namespace euf {
|
|||
propagate();
|
||||
}
|
||||
|
||||
void solver::propagate() {
|
||||
m_egraph.propagate();
|
||||
unsigned lvl = s().scope_lvl();
|
||||
void solver::propagate() {
|
||||
while (m_egraph.propagate() && !s().inconsistent()) {
|
||||
if (m_egraph.inconsistent()) {
|
||||
unsigned lvl = s().scope_lvl();
|
||||
s().set_conflict(sat::justification::mk_ext_justification(lvl, conflict_constraint().to_index()));
|
||||
return;
|
||||
}
|
||||
propagate_literals();
|
||||
propagate_th_eqs();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_egraph.inconsistent()) {
|
||||
s().set_conflict(sat::justification::mk_ext_justification(lvl, conflict_constraint().to_index()));
|
||||
return;
|
||||
}
|
||||
for (euf::enode* eq : m_egraph.new_eqs()) {
|
||||
bool_var v = m_expr2var.to_bool_var(eq->get_owner());
|
||||
void solver::propagate_literals() {
|
||||
for (; m_egraph.has_literal() && !s().inconsistent() && !m_egraph.inconsistent(); m_egraph.next_literal()) {
|
||||
euf::enode_bool_pair p = m_egraph.get_literal();
|
||||
euf::enode* n = p.first;
|
||||
bool is_eq = p.second;
|
||||
expr* e = n->get_owner();
|
||||
expr* a = nullptr, *b = nullptr;
|
||||
if (s().value(v) == l_false && m_ackerman && m.is_eq(eq->get_owner(), a, b))
|
||||
m_ackerman->cg_conflict_eh(a, b);
|
||||
literal lit(v, false);
|
||||
if (s().value(lit) == l_true)
|
||||
continue;
|
||||
s().assign(literal(v, false), sat::justification::mk_ext_justification(lvl, eq_constraint().to_index()));
|
||||
if (s().inconsistent())
|
||||
return;
|
||||
}
|
||||
for (euf::enode* p : m_egraph.new_lits()) {
|
||||
expr* e = p->get_owner();
|
||||
bool sign = m.is_false(p->get_root()->get_owner());
|
||||
SASSERT(m.is_bool(e));
|
||||
SASSERT(m.is_true(p->get_root()->get_owner()) || sign);
|
||||
bool_var v = m_expr2var.to_bool_var(e);
|
||||
literal lit(v, sign);
|
||||
if (s().value(lit) == l_true)
|
||||
continue;
|
||||
SASSERT(m.is_bool(e));
|
||||
size_t cnstr;
|
||||
literal lit;
|
||||
if (is_eq) {
|
||||
VERIFY(m.is_eq(e, a, b));
|
||||
cnstr = eq_constraint().to_index();
|
||||
lit = literal(v, false);
|
||||
}
|
||||
else {
|
||||
a = e, b = n->get_root()->get_owner();
|
||||
SASSERT(m.is_true(a) || m.is_false(b));
|
||||
cnstr = lit_constraint().to_index();
|
||||
lit = literal(v, m.is_false(b));
|
||||
}
|
||||
if (s().value(lit) == l_false && m_ackerman)
|
||||
m_ackerman->cg_conflict_eh(p->get_owner(), p->get_root()->get_owner());
|
||||
s().assign(lit, sat::justification::mk_ext_justification(lvl, lit_constraint().to_index()));
|
||||
if (s().inconsistent())
|
||||
return;
|
||||
m_ackerman->cg_conflict_eh(a, b);
|
||||
unsigned lvl = s().scope_lvl();
|
||||
if (s().value(lit) != l_true)
|
||||
s().assign(lit, sat::justification::mk_ext_justification(lvl, cnstr));
|
||||
}
|
||||
for (euf::th_eq const& eq : m_egraph.new_th_eqs()) {
|
||||
// m_id2solver[eq.m_id]->new_eq_eh(eq);
|
||||
}
|
||||
|
||||
void solver::propagate_th_eqs() {
|
||||
for (; m_egraph.has_th_eq() && !s().inconsistent() && !m_egraph.inconsistent(); m_egraph.next_th_eq()) {
|
||||
th_eq eq = m_egraph.get_th_eq();
|
||||
m_id2solver[eq.m_id]->new_eq_eh(eq);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,7 +356,7 @@ namespace euf {
|
|||
for (unsigned i = 0; i < m_id2solver.size(); ++i) {
|
||||
auto* e = m_id2solver[i];
|
||||
if (e)
|
||||
r->add_solver(i, e->fresh(s, *m_to_m, *m_to_si));
|
||||
r->add_solver(i, e->fresh(s, *r));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -48,9 +48,10 @@ namespace euf {
|
|||
size_t to_index() const { return sat::constraint_base::mem2base(this); }
|
||||
};
|
||||
|
||||
class solver : public sat::extension, public sat::th_internalizer, public sat::th_decompile {
|
||||
class solver : public sat::extension, public th_internalizer, public th_decompile {
|
||||
typedef top_sort<euf::enode> deps_t;
|
||||
friend class ackerman;
|
||||
// friend class sat::ba_solver;
|
||||
struct stats {
|
||||
unsigned m_num_dynack;
|
||||
stats() { reset(); }
|
||||
|
@ -87,8 +88,8 @@ namespace euf {
|
|||
unsigned m_num_scopes { 0 };
|
||||
unsigned_vector m_var_trail;
|
||||
svector<scope> m_scopes;
|
||||
scoped_ptr_vector<sat::th_solver> m_solvers;
|
||||
ptr_vector<sat::th_solver> m_id2solver;
|
||||
scoped_ptr_vector<th_solver> m_solvers;
|
||||
ptr_vector<th_solver> m_id2solver;
|
||||
|
||||
constraint* m_conflict { nullptr };
|
||||
constraint* m_eq { nullptr };
|
||||
|
@ -110,10 +111,10 @@ namespace euf {
|
|||
euf::enode* mk_false();
|
||||
|
||||
// extensions
|
||||
sat::th_solver* get_solver(func_decl* f);
|
||||
sat::th_solver* get_solver(expr* e);
|
||||
sat::th_solver* get_solver(sat::bool_var v);
|
||||
void add_solver(family_id fid, sat::th_solver* th);
|
||||
th_solver* get_solver(func_decl* f);
|
||||
th_solver* get_solver(expr* e);
|
||||
th_solver* get_solver(sat::bool_var v);
|
||||
void add_solver(family_id fid, th_solver* th);
|
||||
void unhandled_function(func_decl* f);
|
||||
void init_ackerman();
|
||||
|
||||
|
@ -126,6 +127,8 @@ namespace euf {
|
|||
|
||||
// solving
|
||||
void propagate();
|
||||
void propagate_literals();
|
||||
void propagate_th_eqs();
|
||||
void get_antecedents(literal l, constraint& j, literal_vector& r);
|
||||
void force_push();
|
||||
void log_antecedents(std::ostream& out, literal l, literal_vector const& r);
|
||||
|
@ -175,6 +178,10 @@ namespace euf {
|
|||
}
|
||||
};
|
||||
|
||||
sat::sat_internalizer& get_si() { return si; }
|
||||
ast_manager& get_manager() { return m; }
|
||||
enode* get_enode(expr* e) { return m_egraph.find(e); }
|
||||
|
||||
void updt_params(params_ref const& p);
|
||||
void set_solver(sat::solver* s) override { m_solver = s; m_drat = s->get_config().m_drat; }
|
||||
void set_lookahead(sat::lookahead* s) override { m_lookahead = s; }
|
||||
|
@ -214,7 +221,6 @@ namespace euf {
|
|||
sat::literal internalize(expr* e, bool sign, bool root, bool learned) override;
|
||||
void update_model(model_ref& mdl);
|
||||
|
||||
func_decl_ref_vector const& unhandled_functions() { return m_unhandled_functions; }
|
||||
|
||||
func_decl_ref_vector const& unhandled_functions() { return m_unhandled_functions; }
|
||||
};
|
||||
};
|
||||
|
|
|
@ -20,13 +20,15 @@ Author:
|
|||
#include "sat/smt/sat_smt.h"
|
||||
#include "ast/euf/euf_egraph.h"
|
||||
|
||||
namespace sat {
|
||||
namespace euf {
|
||||
|
||||
class solver;
|
||||
|
||||
class th_internalizer {
|
||||
public:
|
||||
virtual ~th_internalizer() {}
|
||||
|
||||
virtual literal internalize(expr* e, bool sign, bool root, bool redundant) = 0;
|
||||
virtual sat::literal internalize(expr* e, bool sign, bool root, bool redundant) = 0;
|
||||
};
|
||||
|
||||
class th_decompile {
|
||||
|
@ -58,14 +60,49 @@ namespace sat {
|
|||
virtual bool include_func_interp(func_decl* f) const { return false; }
|
||||
};
|
||||
|
||||
class th_solver : public extension, public th_model_builder, public th_decompile, public th_internalizer {
|
||||
class th_solver : public sat::extension, public th_model_builder, public th_decompile, public th_internalizer {
|
||||
protected:
|
||||
ast_manager & m;
|
||||
euf::theory_id m_id;
|
||||
public:
|
||||
virtual ~th_solver() {}
|
||||
th_solver(ast_manager& m, euf::theory_id id): m(m), m_id(id) {}
|
||||
|
||||
virtual th_solver* fresh(solver* s, ast_manager& m, sat_internalizer& si) = 0;
|
||||
virtual th_solver* fresh(sat::solver* s, euf::solver& ctx) = 0;
|
||||
|
||||
virtual void new_eq_eh(euf::th_eq const& eq) {}
|
||||
};
|
||||
|
||||
class th_euf_solver : public th_solver {
|
||||
protected:
|
||||
solver & ctx;
|
||||
euf::enode_vector m_var2enode;
|
||||
unsigned_vector m_var2enode_lim;
|
||||
public:
|
||||
virtual ~th_euf_solver() {}
|
||||
|
||||
th_euf_solver(euf::solver& ctx, euf::theory_id id);
|
||||
|
||||
virtual euf::theory_var mk_var(enode * n) {
|
||||
SASSERT(!is_attached_to_var(n));
|
||||
euf::theory_var v = m_var2enode.size();
|
||||
m_var2enode.push_back(n);
|
||||
return v;
|
||||
}
|
||||
|
||||
enode* get_enode(theory_var v) const { return m_var2enode[v]; }
|
||||
|
||||
euf::theory_var get_th_var(expr* e) const;
|
||||
|
||||
euf::theory_var get_th_var(euf::enode* n) const {
|
||||
return n->get_th_var(get_id());
|
||||
}
|
||||
|
||||
bool is_attached_to_var(enode* n) const {
|
||||
theory_var v = n->get_th_var(get_id());
|
||||
return v != null_theory_var && get_enode(v) == n;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue