3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-11 21:50:52 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2021-12-27 16:03:56 -08:00
parent 6f1be09993
commit 9527471967
6 changed files with 100 additions and 26 deletions

View file

@ -40,7 +40,7 @@ z3_add_component(sat_smt
recfun_solver.cpp recfun_solver.cpp
sat_dual_solver.cpp sat_dual_solver.cpp
sat_th.cpp sat_th.cpp
smt_relevancy.cpp smt_relevant.cpp
user_solver.cpp user_solver.cpp
COMPONENT_DEPENDENCIES COMPONENT_DEPENDENCIES
sat sat

View file

@ -22,16 +22,25 @@ Author:
namespace euf { namespace euf {
void solver::add_auto_relevant(expr* e) { void solver::add_auto_relevant(sat::literal lit) {
#if NEW_RELEVANCY
m_relevancy.mark_relevant(lit);
return;
#endif
if (!relevancy_enabled()) if (!relevancy_enabled())
return; return;
for (; m_auto_relevant_scopes > 0; --m_auto_relevant_scopes) for (; m_auto_relevant_scopes > 0; --m_auto_relevant_scopes)
m_auto_relevant_lim.push_back(m_auto_relevant.size()); m_auto_relevant_lim.push_back(m_auto_relevant.size());
// std::cout << "add-auto " << e->get_id() << " " << mk_bounded_pp(e, m) << "\n"; // std::cout << "add-auto " << e->get_id() << " " << mk_bounded_pp(e, m) << "\n";
expr* e = bool_var2expr(lit.var());
m_auto_relevant.push_back(e); m_auto_relevant.push_back(e);
} }
void solver::pop_relevant(unsigned n) { void solver::pop_relevant(unsigned n) {
#if NEW_RELEVANCY
m_relevancy.pop(n);
return;
#endif
if (m_auto_relevant_scopes >= n) { if (m_auto_relevant_scopes >= n) {
m_auto_relevant_scopes -= n; m_auto_relevant_scopes -= n;
return; return;
@ -45,18 +54,31 @@ namespace euf {
} }
void solver::push_relevant() { void solver::push_relevant() {
#if NEW_RELEVANCY
m_relevancy.push();
return;
#endif
++m_auto_relevant_scopes; ++m_auto_relevant_scopes;
} }
bool solver::is_relevant(expr* e) const { bool solver::is_relevant(expr* e) const {
#if NEW_RELEVANCY
return m_relevancy.is_relevant(e);
#endif
return m_relevant_expr_ids.get(e->get_id(), true); return m_relevant_expr_ids.get(e->get_id(), true);
} }
bool solver::is_relevant(enode* n) const { bool solver::is_relevant(enode* n) const {
#if NEW_RELEVANCY
return m_relevancy.is_relevant(n);
#endif
return m_relevant_expr_ids.get(n->get_expr_id(), true); return m_relevant_expr_ids.get(n->get_expr_id(), true);
} }
void solver::ensure_dual_solver() { void solver::ensure_dual_solver() {
#if NEW_RELEVANCY
return;
#endif
if (m_dual_solver) if (m_dual_solver)
return; return;
m_dual_solver = alloc(sat::dual_solver, s(), s().rlimit()); m_dual_solver = alloc(sat::dual_solver, s(), s().rlimit());
@ -71,6 +93,10 @@ namespace euf {
* not tracked. * not tracked.
*/ */
void solver::add_root(unsigned n, sat::literal const* lits) { void solver::add_root(unsigned n, sat::literal const* lits) {
#if NEW_RELEVANCY
m_relevancy.add_root(n, lits);
return;
#endif
if (!relevancy_enabled()) if (!relevancy_enabled())
return; return;
ensure_dual_solver(); ensure_dual_solver();
@ -78,6 +104,10 @@ namespace euf {
} }
void solver::add_aux(unsigned n, sat::literal const* lits) { void solver::add_aux(unsigned n, sat::literal const* lits) {
#if NEW_RELEVANCY
m_relevancy.add_def(n, lits);
return;
#endif
if (!relevancy_enabled()) if (!relevancy_enabled())
return; return;
ensure_dual_solver(); ensure_dual_solver();
@ -85,11 +115,17 @@ namespace euf {
} }
void solver::track_relevancy(sat::bool_var v) { void solver::track_relevancy(sat::bool_var v) {
#if NEW_RELEVANCY
return;
#endif
ensure_dual_solver(); ensure_dual_solver();
m_dual_solver->track_relevancy(v); m_dual_solver->track_relevancy(v);
} }
bool solver::init_relevancy() { bool solver::init_relevancy() {
#if NEW_RELEVANCY
return true;
#endif
m_relevant_expr_ids.reset(); m_relevant_expr_ids.reset();
if (!relevancy_enabled()) if (!relevancy_enabled())
return true; return true;
@ -108,16 +144,19 @@ namespace euf {
} }
void solver::push_relevant(sat::bool_var v) { void solver::push_relevant(sat::bool_var v) {
SASSERT(!NEW_RELEVANCY);
expr* e = m_bool_var2expr.get(v, nullptr); expr* e = m_bool_var2expr.get(v, nullptr);
if (e) if (e)
m_relevant_todo.push_back(e); m_relevant_todo.push_back(e);
} }
bool solver::is_propagated(sat::literal lit) { bool solver::is_propagated(sat::literal lit) {
SASSERT(!NEW_RELEVANCY);
return s().value(lit) == l_true && !s().get_justification(lit.var()).is_none(); return s().value(lit) == l_true && !s().get_justification(lit.var()).is_none();
} }
void solver::init_relevant_expr_ids() { void solver::init_relevant_expr_ids() {
SASSERT(!NEW_RELEVANCY);
unsigned max_id = 0; unsigned max_id = 0;
for (enode* n : m_egraph.nodes()) for (enode* n : m_egraph.nodes())
max_id = std::max(max_id, n->get_expr_id()); max_id = std::max(max_id, n->get_expr_id());
@ -127,6 +166,7 @@ namespace euf {
} }
void solver::relevant_subterms() { void solver::relevant_subterms() {
SASSERT(!NEW_RELEVANCY);
ptr_vector<expr>& todo = m_relevant_todo; ptr_vector<expr>& todo = m_relevant_todo;
bool_vector& visited = m_relevant_visited; bool_vector& visited = m_relevant_visited;
for (unsigned i = 0; i < todo.size(); ++i) { for (unsigned i = 0; i < todo.size(); ++i) {

View file

@ -41,6 +41,7 @@ namespace euf {
extension(symbol("euf"), m.mk_family_id("euf")), extension(symbol("euf"), m.mk_family_id("euf")),
m(m), m(m),
si(si), si(si),
m_relevancy(*this),
m_egraph(m), m_egraph(m),
m_trail(), m_trail(),
m_rewriter(m), m_rewriter(m),
@ -183,7 +184,7 @@ namespace euf {
} }
void solver::propagate(literal lit, ext_justification_idx idx) { void solver::propagate(literal lit, ext_justification_idx idx) {
add_auto_relevant(bool_var2expr(lit.var())); add_auto_relevant(lit);
s().assign(lit, sat::justification::mk_ext_justification(s().scope_lvl(), idx)); s().assign(lit, sat::justification::mk_ext_justification(s().scope_lvl(), idx));
} }
@ -243,10 +244,17 @@ namespace euf {
bool solver::propagate(enode* a, enode* b, ext_justification_idx idx) { bool solver::propagate(enode* a, enode* b, ext_justification_idx idx) {
if (a->get_root() == b->get_root()) if (a->get_root() == b->get_root())
return false; return false;
m_egraph.merge(a, b, to_ptr(idx)); merge(a, b, to_ptr(idx));
return true; return true;
} }
void solver::merge(enode* a, enode* b, void* r) {
#if NEW_RELEVANCY
m_relevancy.merge(a, b);
#endif
m_egraph.merge(a, b, r);
}
void solver::get_antecedents(literal l, constraint& j, literal_vector& r, bool probing) { void solver::get_antecedents(literal l, constraint& j, literal_vector& r, bool probing) {
expr* e = nullptr; expr* e = nullptr;
euf::enode* n = nullptr; euf::enode* n = nullptr;
@ -286,6 +294,12 @@ namespace euf {
} }
void solver::asserted(literal l) { void solver::asserted(literal l) {
#if NEW_RELEVANCY
if (!m_relevancy.is_relevant(l)) {
m_relevancy.asserted(l);
return;
}
#endif
expr* e = m_bool_var2expr.get(l.var(), nullptr); expr* e = m_bool_var2expr.get(l.var(), nullptr);
TRACE("euf", tout << "asserted: " << l << "@" << s().scope_lvl() << " := " << mk_bounded_pp(e, m) << "\n";); TRACE("euf", tout << "asserted: " << l << "@" << s().scope_lvl() << " := " << mk_bounded_pp(e, m) << "\n";);
if (!e) if (!e)
@ -306,14 +320,14 @@ namespace euf {
euf::enode* r = n->get_root(); euf::enode* r = n->get_root();
euf::enode* rb = sign ? mk_true() : mk_false(); euf::enode* rb = sign ? mk_true() : mk_false();
sat::literal rl(r->bool_var(), r->value() == l_false); sat::literal rl(r->bool_var(), r->value() == l_false);
m_egraph.merge(n, nb, c); merge(n, nb, c);
m_egraph.merge(r, rb, to_ptr(rl)); merge(r, rb, to_ptr(rl));
SASSERT(m_egraph.inconsistent()); SASSERT(m_egraph.inconsistent());
return; return;
} }
if (n->merge_tf()) { if (n->merge_tf()) {
euf::enode* nb = sign ? mk_false() : mk_true(); euf::enode* nb = sign ? mk_false() : mk_true();
m_egraph.merge(n, nb, c); merge(n, nb, c);
} }
if (n->is_equality()) { if (n->is_equality()) {
SASSERT(!m.is_iff(e)); SASSERT(!m.is_iff(e));
@ -321,7 +335,7 @@ namespace euf {
if (sign) if (sign)
m_egraph.new_diseq(n); m_egraph.new_diseq(n);
else else
m_egraph.merge(n->get_arg(0), n->get_arg(1), c); merge(n->get_arg(0), n->get_arg(1), c);
} }
} }
@ -329,6 +343,9 @@ namespace euf {
bool solver::unit_propagate() { bool solver::unit_propagate() {
bool propagated = false; bool propagated = false;
while (!s().inconsistent()) { while (!s().inconsistent()) {
#if NEW_RELEVANCY
m_relevancy.propagate();
#endif
if (m_egraph.inconsistent()) { if (m_egraph.inconsistent()) {
unsigned lvl = s().scope_lvl(); unsigned lvl = s().scope_lvl();
s().set_conflict(sat::justification::mk_ext_justification(lvl, conflict_constraint().to_index())); s().set_conflict(sat::justification::mk_ext_justification(lvl, conflict_constraint().to_index()));

View file

@ -28,8 +28,11 @@ Author:
#include "sat/smt/sat_dual_solver.h" #include "sat/smt/sat_dual_solver.h"
#include "sat/smt/euf_ackerman.h" #include "sat/smt/euf_ackerman.h"
#include "sat/smt/user_solver.h" #include "sat/smt/user_solver.h"
#include "sat/smt/smt_relevant.h"
#include "smt/params/smt_params.h" #include "smt/params/smt_params.h"
#define NEW_RELEVANCY 0
namespace euf { namespace euf {
typedef sat::literal literal; typedef sat::literal literal;
typedef sat::ext_constraint_idx ext_constraint_idx; typedef sat::ext_constraint_idx ext_constraint_idx;
@ -91,6 +94,7 @@ namespace euf {
std::function<::solver*(void)> m_mk_solver; std::function<::solver*(void)> m_mk_solver;
ast_manager& m; ast_manager& m;
sat::sat_internalizer& si; sat::sat_internalizer& si;
smt::relevancy m_relevancy;
smt_params m_config; smt_params m_config;
euf::egraph m_egraph; euf::egraph m_egraph;
trail_stack m_trail; trail_stack m_trail;
@ -289,6 +293,7 @@ namespace euf {
void propagate(literal lit, ext_justification_idx idx); void propagate(literal lit, ext_justification_idx idx);
bool propagate(enode* a, enode* b, ext_justification_idx idx); bool propagate(enode* a, enode* b, ext_justification_idx idx);
void merge(enode* a, enode* b, void* r);
void set_conflict(ext_justification_idx idx); void set_conflict(ext_justification_idx idx);
void propagate(literal lit, th_explain* p) { propagate(lit, p->to_index()); } void propagate(literal lit, th_explain* p) { propagate(lit, p->to_index()); }
@ -367,14 +372,14 @@ namespace euf {
bool is_shared(euf::enode* n) const; bool is_shared(euf::enode* n) const;
// relevancy // relevancy
bool m_relevancy = true; bool m_relevancy_enabled = true;
scoped_ptr<sat::dual_solver> m_dual_solver; scoped_ptr<sat::dual_solver> m_dual_solver;
ptr_vector<expr> m_auto_relevant; ptr_vector<expr> m_auto_relevant;
unsigned_vector m_auto_relevant_lim; unsigned_vector m_auto_relevant_lim;
unsigned m_auto_relevant_scopes = 0; unsigned m_auto_relevant_scopes = 0;
bool relevancy_enabled() const { return m_relevancy && get_config().m_relevancy_lvl > 0; } bool relevancy_enabled() const { return m_relevancy_enabled && get_config().m_relevancy_lvl > 0; }
void disable_relevancy(expr* e) { IF_VERBOSE(0, verbose_stream() << "disabling relevancy " << mk_pp(e, m) << "\n"); m_relevancy = false; } void disable_relevancy(expr* e) { IF_VERBOSE(0, verbose_stream() << "disabling relevancy " << mk_pp(e, m) << "\n"); m_relevancy_enabled = false; }
void add_root(unsigned n, sat::literal const* lits); void add_root(unsigned n, sat::literal const* lits);
void add_root(sat::literal_vector const& lits) { add_root(lits.size(), lits.data()); } void add_root(sat::literal_vector const& lits) { add_root(lits.size(), lits.data()); }
void add_root(sat::literal lit) { add_root(1, &lit); } void add_root(sat::literal lit) { add_root(1, &lit); }
@ -387,7 +392,7 @@ namespace euf {
void track_relevancy(sat::bool_var v); void track_relevancy(sat::bool_var v);
bool is_relevant(expr* e) const; bool is_relevant(expr* e) const;
bool is_relevant(enode* n) const; bool is_relevant(enode* n) const;
void add_auto_relevant(expr* e); void add_auto_relevant(sat::literal lit);
void pop_relevant(unsigned n); void pop_relevant(unsigned n);
void push_relevant(); void push_relevant();

View file

@ -13,12 +13,10 @@ Author:
Nikolaj Bjorner (nbjorner) 2021-12-27 Nikolaj Bjorner (nbjorner) 2021-12-27
--*/ --*/
#include "sat/sat_solver.h" #include "sat/sat_solver.h"
#include "sat/smt/euf_solver.h" #include "sat/smt/euf_solver.h"
#include "sat/smt/smt_relevancy.h" #include "sat/smt/smt_relevant.h"
namespace smt { namespace smt {
@ -28,11 +26,13 @@ namespace smt {
} }
void relevancy::relevant_eh(euf::enode* n) { void relevancy::relevant_eh(euf::enode* n) {
// callback into ctx. // nothing
} }
void relevancy::relevant_eh(sat::literal lit) { void relevancy::relevant_eh(sat::literal lit) {
// callback into ctx. SASSERT(ctx.s().value(lit) == l_true);
SASSERT(is_relevant(lit));
ctx.asserted(lit);
} }
void relevancy::pop(unsigned n) { void relevancy::pop(unsigned n) {
@ -97,12 +97,12 @@ namespace smt {
return; return;
} }
sat::clause cl = *m_alloc.mk_clause(n, lits, false); sat::clause* cl = m_alloc.mk_clause(n, lits, false);
unsigned sz = m_clauses.size(); unsigned sz = m_clauses.size();
m_clauses.push_back(&cl); m_clauses.push_back(cl);
m_roots.push_back(true); m_roots.push_back(true);
m_trail.push_back(std::make_pair(update::add_clause, 0)); m_trail.push_back(std::make_pair(update::add_clause, 0));
for (sat::literal lit : cl) for (sat::literal lit : *cl)
occurs(lit).push_back(sz); occurs(lit).push_back(sz);
} }
@ -116,16 +116,16 @@ namespace smt {
return; return;
} }
} }
sat::clause cl = *m_alloc.mk_clause(n, lits, false); sat::clause* cl = m_alloc.mk_clause(n, lits, false);
unsigned sz = m_clauses.size(); unsigned sz = m_clauses.size();
m_clauses.push_back(&cl); m_clauses.push_back(cl);
m_roots.push_back(false); m_roots.push_back(false);
m_trail.push_back(std::make_pair(update::add_clause, 0)); m_trail.push_back(std::make_pair(update::add_clause, 0));
for (sat::literal lit : cl) for (sat::literal lit : *cl)
occurs(lit).push_back(sz); occurs(lit).push_back(sz);
} }
void relevancy::assign(sat::literal lit) { void relevancy::asserted(sat::literal lit) {
if (!m_enabled) if (!m_enabled)
return; return;
flush(); flush();
@ -164,6 +164,13 @@ namespace smt {
} }
} }
void relevancy::merge(euf::enode* n1, euf::enode* n2) {
if (is_relevant(n1))
mark_relevant(n2);
else if (is_relevant(n2))
mark_relevant(n1);
}
void relevancy::mark_relevant(euf::enode* n) { void relevancy::mark_relevant(euf::enode* n) {
if (!m_enabled) if (!m_enabled)
return; return;
@ -191,6 +198,9 @@ namespace smt {
m_relevant_var_ids.setx(lit.var(), true, false); m_relevant_var_ids.setx(lit.var(), true, false);
m_trail.push_back(std::make_pair(update::relevant_var, lit.var())); m_trail.push_back(std::make_pair(update::relevant_var, lit.var()));
m_queue.push_back(std::make_pair(lit, nullptr)); m_queue.push_back(std::make_pair(lit, nullptr));
euf::enode* n = nullptr;
if (n)
mark_relevant(n);
} }
void relevancy::propagate_relevant(sat::literal lit) { void relevancy::propagate_relevant(sat::literal lit) {
@ -221,6 +231,7 @@ namespace smt {
void relevancy::propagate_relevant(euf::enode* n) { void relevancy::propagate_relevant(euf::enode* n) {
relevant_eh(n); relevant_eh(n);
// if is_bool_op n, return;
for (euf::enode* arg : euf::enode_args(n)) for (euf::enode* arg : euf::enode_args(n))
mark_relevant(arg); mark_relevant(arg);
} }

View file

@ -129,11 +129,12 @@ namespace smt {
void add_root(unsigned n, sat::literal const* lits); void add_root(unsigned n, sat::literal const* lits);
void add_def(unsigned n, sat::literal const* lits); void add_def(unsigned n, sat::literal const* lits);
void assign(sat::literal lit); void asserted(sat::literal lit);
void propagate(); void propagate();
void mark_relevant(euf::enode* n); void mark_relevant(euf::enode* n);
void mark_relevant(sat::literal lit); void mark_relevant(sat::literal lit);
void merge(euf::enode* n1, euf::enode* n2);
bool is_relevant(sat::literal lit) const { return !m_enabled || m_relevant_var_ids.get(lit.var(), false); } bool is_relevant(sat::literal lit) const { return !m_enabled || m_relevant_var_ids.get(lit.var(), false); }
bool is_relevant(euf::enode* n) const { return !m_enabled || m_relevant_expr_ids.get(n->get_expr_id(), false); } bool is_relevant(euf::enode* n) const { return !m_enabled || m_relevant_expr_ids.get(n->get_expr_id(), false); }