diff --git a/src/sat/smt/CMakeLists.txt b/src/sat/smt/CMakeLists.txt index 01681a6b1..dc7f73c93 100644 --- a/src/sat/smt/CMakeLists.txt +++ b/src/sat/smt/CMakeLists.txt @@ -40,7 +40,7 @@ z3_add_component(sat_smt recfun_solver.cpp sat_dual_solver.cpp sat_th.cpp - smt_relevancy.cpp + smt_relevant.cpp user_solver.cpp COMPONENT_DEPENDENCIES sat diff --git a/src/sat/smt/euf_relevancy.cpp b/src/sat/smt/euf_relevancy.cpp index e722e6412..64aea0c8c 100644 --- a/src/sat/smt/euf_relevancy.cpp +++ b/src/sat/smt/euf_relevancy.cpp @@ -22,16 +22,25 @@ Author: 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()) return; for (; m_auto_relevant_scopes > 0; --m_auto_relevant_scopes) m_auto_relevant_lim.push_back(m_auto_relevant.size()); // 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); } void solver::pop_relevant(unsigned n) { +#if NEW_RELEVANCY + m_relevancy.pop(n); + return; +#endif if (m_auto_relevant_scopes >= n) { m_auto_relevant_scopes -= n; return; @@ -45,18 +54,31 @@ namespace euf { } void solver::push_relevant() { +#if NEW_RELEVANCY + m_relevancy.push(); + return; +#endif ++m_auto_relevant_scopes; } 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); } 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); } void solver::ensure_dual_solver() { +#if NEW_RELEVANCY + return; +#endif if (m_dual_solver) return; m_dual_solver = alloc(sat::dual_solver, s(), s().rlimit()); @@ -71,6 +93,10 @@ namespace euf { * not tracked. */ void solver::add_root(unsigned n, sat::literal const* lits) { +#if NEW_RELEVANCY + m_relevancy.add_root(n, lits); + return; +#endif if (!relevancy_enabled()) return; ensure_dual_solver(); @@ -78,6 +104,10 @@ namespace euf { } void solver::add_aux(unsigned n, sat::literal const* lits) { +#if NEW_RELEVANCY + m_relevancy.add_def(n, lits); + return; +#endif if (!relevancy_enabled()) return; ensure_dual_solver(); @@ -85,11 +115,17 @@ namespace euf { } void solver::track_relevancy(sat::bool_var v) { +#if NEW_RELEVANCY + return; +#endif ensure_dual_solver(); m_dual_solver->track_relevancy(v); } bool solver::init_relevancy() { +#if NEW_RELEVANCY + return true; +#endif m_relevant_expr_ids.reset(); if (!relevancy_enabled()) return true; @@ -108,16 +144,19 @@ namespace euf { } void solver::push_relevant(sat::bool_var v) { + SASSERT(!NEW_RELEVANCY); expr* e = m_bool_var2expr.get(v, nullptr); if (e) m_relevant_todo.push_back(e); } bool solver::is_propagated(sat::literal lit) { + SASSERT(!NEW_RELEVANCY); return s().value(lit) == l_true && !s().get_justification(lit.var()).is_none(); } void solver::init_relevant_expr_ids() { + SASSERT(!NEW_RELEVANCY); unsigned max_id = 0; for (enode* n : m_egraph.nodes()) max_id = std::max(max_id, n->get_expr_id()); @@ -127,6 +166,7 @@ namespace euf { } void solver::relevant_subterms() { + SASSERT(!NEW_RELEVANCY); ptr_vector& todo = m_relevant_todo; bool_vector& visited = m_relevant_visited; for (unsigned i = 0; i < todo.size(); ++i) { diff --git a/src/sat/smt/euf_solver.cpp b/src/sat/smt/euf_solver.cpp index bbdd6ce0e..2c602d205 100644 --- a/src/sat/smt/euf_solver.cpp +++ b/src/sat/smt/euf_solver.cpp @@ -41,6 +41,7 @@ namespace euf { extension(symbol("euf"), m.mk_family_id("euf")), m(m), si(si), + m_relevancy(*this), m_egraph(m), m_trail(), m_rewriter(m), @@ -183,7 +184,7 @@ namespace euf { } 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)); } @@ -243,10 +244,17 @@ namespace euf { bool solver::propagate(enode* a, enode* b, ext_justification_idx idx) { if (a->get_root() == b->get_root()) return false; - m_egraph.merge(a, b, to_ptr(idx)); + merge(a, b, to_ptr(idx)); 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) { expr* e = nullptr; euf::enode* n = nullptr; @@ -286,6 +294,12 @@ namespace euf { } 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); TRACE("euf", tout << "asserted: " << l << "@" << s().scope_lvl() << " := " << mk_bounded_pp(e, m) << "\n";); if (!e) @@ -306,14 +320,14 @@ namespace euf { euf::enode* r = n->get_root(); euf::enode* rb = sign ? mk_true() : mk_false(); sat::literal rl(r->bool_var(), r->value() == l_false); - m_egraph.merge(n, nb, c); - m_egraph.merge(r, rb, to_ptr(rl)); + merge(n, nb, c); + merge(r, rb, to_ptr(rl)); SASSERT(m_egraph.inconsistent()); return; } if (n->merge_tf()) { euf::enode* nb = sign ? mk_false() : mk_true(); - m_egraph.merge(n, nb, c); + merge(n, nb, c); } if (n->is_equality()) { SASSERT(!m.is_iff(e)); @@ -321,7 +335,7 @@ namespace euf { if (sign) m_egraph.new_diseq(n); 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 propagated = false; while (!s().inconsistent()) { +#if NEW_RELEVANCY + m_relevancy.propagate(); +#endif if (m_egraph.inconsistent()) { unsigned lvl = s().scope_lvl(); s().set_conflict(sat::justification::mk_ext_justification(lvl, conflict_constraint().to_index())); diff --git a/src/sat/smt/euf_solver.h b/src/sat/smt/euf_solver.h index 114cfbd8c..1396e00fb 100644 --- a/src/sat/smt/euf_solver.h +++ b/src/sat/smt/euf_solver.h @@ -28,8 +28,11 @@ Author: #include "sat/smt/sat_dual_solver.h" #include "sat/smt/euf_ackerman.h" #include "sat/smt/user_solver.h" +#include "sat/smt/smt_relevant.h" #include "smt/params/smt_params.h" +#define NEW_RELEVANCY 0 + namespace euf { typedef sat::literal literal; typedef sat::ext_constraint_idx ext_constraint_idx; @@ -91,6 +94,7 @@ namespace euf { std::function<::solver*(void)> m_mk_solver; ast_manager& m; sat::sat_internalizer& si; + smt::relevancy m_relevancy; smt_params m_config; euf::egraph m_egraph; trail_stack m_trail; @@ -289,6 +293,7 @@ namespace euf { void propagate(literal lit, 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 propagate(literal lit, th_explain* p) { propagate(lit, p->to_index()); } @@ -367,14 +372,14 @@ namespace euf { bool is_shared(euf::enode* n) const; // relevancy - bool m_relevancy = true; + bool m_relevancy_enabled = true; scoped_ptr m_dual_solver; ptr_vector m_auto_relevant; unsigned_vector m_auto_relevant_lim; unsigned m_auto_relevant_scopes = 0; - bool relevancy_enabled() const { return m_relevancy && 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; } + 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_enabled = false; } 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 lit) { add_root(1, &lit); } @@ -387,7 +392,7 @@ namespace euf { void track_relevancy(sat::bool_var v); bool is_relevant(expr* e) 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 push_relevant(); diff --git a/src/sat/smt/smt_relevancy.cpp b/src/sat/smt/smt_relevant.cpp similarity index 88% rename from src/sat/smt/smt_relevancy.cpp rename to src/sat/smt/smt_relevant.cpp index 21d570dd2..d70d37beb 100644 --- a/src/sat/smt/smt_relevancy.cpp +++ b/src/sat/smt/smt_relevant.cpp @@ -13,12 +13,10 @@ Author: Nikolaj Bjorner (nbjorner) 2021-12-27 - - --*/ #include "sat/sat_solver.h" #include "sat/smt/euf_solver.h" -#include "sat/smt/smt_relevancy.h" +#include "sat/smt/smt_relevant.h" namespace smt { @@ -28,11 +26,13 @@ namespace smt { } void relevancy::relevant_eh(euf::enode* n) { - // callback into ctx. + // nothing } 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) { @@ -97,12 +97,12 @@ namespace smt { 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(); - m_clauses.push_back(&cl); + m_clauses.push_back(cl); m_roots.push_back(true); 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); } @@ -116,16 +116,16 @@ namespace smt { 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(); - m_clauses.push_back(&cl); + m_clauses.push_back(cl); m_roots.push_back(false); 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); } - void relevancy::assign(sat::literal lit) { + void relevancy::asserted(sat::literal lit) { if (!m_enabled) return; flush(); @@ -163,6 +163,13 @@ namespace smt { propagate_relevant(lit); } } + + 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) { if (!m_enabled) @@ -187,10 +194,13 @@ namespace smt { return; flush(); if (is_relevant(lit)) - return; + return; m_relevant_var_ids.setx(lit.var(), true, false); m_trail.push_back(std::make_pair(update::relevant_var, lit.var())); 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) { @@ -221,6 +231,7 @@ namespace smt { void relevancy::propagate_relevant(euf::enode* n) { relevant_eh(n); + // if is_bool_op n, return; for (euf::enode* arg : euf::enode_args(n)) mark_relevant(arg); } diff --git a/src/sat/smt/smt_relevancy.h b/src/sat/smt/smt_relevant.h similarity index 97% rename from src/sat/smt/smt_relevancy.h rename to src/sat/smt/smt_relevant.h index 5532cd5a3..6faa66b0f 100644 --- a/src/sat/smt/smt_relevancy.h +++ b/src/sat/smt/smt_relevant.h @@ -129,11 +129,12 @@ namespace smt { void add_root(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 mark_relevant(euf::enode* n); 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(euf::enode* n) const { return !m_enabled || m_relevant_expr_ids.get(n->get_expr_id(), false); }