3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-12 12:08:18 +00:00

working on relevant

This commit is contained in:
Nikolaj Bjorner 2021-12-28 11:00:02 -08:00
parent 9527471967
commit 28bce8f09c
11 changed files with 121 additions and 98 deletions

View file

@ -446,8 +446,8 @@ namespace euf {
r2->inc_class_size(r1->class_size()); r2->inc_class_size(r1->class_size());
merge_th_eq(r1, r2); merge_th_eq(r1, r2);
reinsert_parents(r1, r2); reinsert_parents(r1, r2);
if (m_on_merge) for (auto& cb : m_on_merge)
m_on_merge(r2, r1); cb(r2, r1);
} }
void egraph::remove_parents(enode* r1, enode* r2) { void egraph::remove_parents(enode* r1, enode* r2) {

View file

@ -32,6 +32,7 @@ Notes:
#include "ast/euf/euf_enode.h" #include "ast/euf/euf_enode.h"
#include "ast/euf/euf_etable.h" #include "ast/euf/euf_etable.h"
#include "ast/ast_ll_pp.h" #include "ast/ast_ll_pp.h"
#include <vector>
namespace euf { namespace euf {
@ -181,7 +182,7 @@ namespace euf {
enode_vector m_todo; enode_vector m_todo;
stats m_stats; stats m_stats;
bool m_uses_congruence = false; bool m_uses_congruence = false;
std::function<void(enode*,enode*)> m_on_merge; std::vector<std::function<void(enode*,enode*)>> m_on_merge;
std::function<void(enode*)> m_on_make; std::function<void(enode*)> m_on_make;
std::function<void(expr*,expr*,expr*)> m_used_eq; 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;
@ -293,7 +294,7 @@ namespace euf {
void set_value(enode* n, lbool value); void set_value(enode* n, lbool value);
void set_bool_var(enode* n, unsigned v) { n->set_bool_var(v); } void set_bool_var(enode* n, unsigned v) { n->set_bool_var(v); }
void set_on_merge(std::function<void(enode* root,enode* other)>& on_merge) { m_on_merge = on_merge; } void set_on_merge(std::function<void(enode* root,enode* other)>& on_merge) { m_on_merge.push_back(on_merge); }
void set_on_make(std::function<void(enode* n)>& on_make) { m_on_make = on_make; } void set_on_make(std::function<void(enode* n)>& on_make) { m_on_make = on_make; }
void set_used_eq(std::function<void(expr*,expr*,expr*)>& used_eq) { m_used_eq = used_eq; } 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_used_cc(std::function<void(app*,app*)>& used_cc) { m_used_cc = used_cc; }

View file

@ -23,10 +23,10 @@ Author:
namespace euf { namespace euf {
void solver::add_auto_relevant(sat::literal lit) { void solver::add_auto_relevant(sat::literal lit) {
#if NEW_RELEVANCY if (m_relevancy.enabled()) {
m_relevancy.mark_relevant(lit); m_relevancy.mark_relevant(lit);
return; 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)
@ -37,10 +37,10 @@ namespace euf {
} }
void solver::pop_relevant(unsigned n) { void solver::pop_relevant(unsigned n) {
#if NEW_RELEVANCY if (m_relevancy.enabled()) {
m_relevancy.pop(n); m_relevancy.pop(n);
return; 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;
@ -54,31 +54,28 @@ namespace euf {
} }
void solver::push_relevant() { void solver::push_relevant() {
#if NEW_RELEVANCY if (m_relevancy.enabled()) {
m_relevancy.push(); m_relevancy.push();
return; 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 if (m_relevancy.enabled())
return m_relevancy.is_relevant(e); 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 if (m_relevancy.enabled())
return m_relevancy.is_relevant(n); 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 if (m_relevancy.enabled())
return; 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());
@ -93,10 +90,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 if (m_relevancy.enabled()) {
m_relevancy.add_root(n, lits); m_relevancy.add_root(n, lits);
return; return;
#endif }
if (!relevancy_enabled()) if (!relevancy_enabled())
return; return;
ensure_dual_solver(); ensure_dual_solver();
@ -104,10 +101,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 if (m_relevancy.enabled()) {
m_relevancy.add_def(n, lits); m_relevancy.add_def(n, lits);
return; return;
#endif }
if (!relevancy_enabled()) if (!relevancy_enabled())
return; return;
ensure_dual_solver(); ensure_dual_solver();
@ -115,17 +112,15 @@ namespace euf {
} }
void solver::track_relevancy(sat::bool_var v) { void solver::track_relevancy(sat::bool_var v) {
#if NEW_RELEVANCY if (m_relevancy.enabled())
return; 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 if (m_relevancy.enabled())
return true; return true;
#endif
m_relevant_expr_ids.reset(); m_relevant_expr_ids.reset();
if (!relevancy_enabled()) if (!relevancy_enabled())
return true; return true;
@ -144,19 +139,19 @@ namespace euf {
} }
void solver::push_relevant(sat::bool_var v) { void solver::push_relevant(sat::bool_var v) {
SASSERT(!NEW_RELEVANCY); SASSERT(!m_relevancy.enabled());
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); SASSERT(!m_relevancy.enabled());
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); SASSERT(!m_relevancy.enabled());
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());
@ -166,7 +161,7 @@ namespace euf {
} }
void solver::relevant_subterms() { void solver::relevant_subterms() {
SASSERT(!NEW_RELEVANCY); SASSERT(!m_relevancy.enabled());
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

@ -58,6 +58,14 @@ namespace euf {
display_justification_ptr(out, reinterpret_cast<size_t*>(j)); display_justification_ptr(out, reinterpret_cast<size_t*>(j));
}; };
m_egraph.set_display_justification(disp); m_egraph.set_display_justification(disp);
if (m_relevancy.enabled()) {
std::function<void(euf::enode* root, euf::enode* other)> on_merge =
[&](enode* root, enode* other) {
m_relevancy.merge(root, other);
};
m_egraph.set_on_merge(on_merge);
}
} }
void solver::updt_params(params_ref const& p) { void solver::updt_params(params_ref const& p) {
@ -244,17 +252,10 @@ 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;
merge(a, b, to_ptr(idx)); m_egraph.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;
@ -294,12 +295,11 @@ namespace euf {
} }
void solver::asserted(literal l) { void solver::asserted(literal l) {
#if NEW_RELEVANCY if (m_relevancy.enabled() && !m_relevancy.is_relevant(l)) {
if (!m_relevancy.is_relevant(l)) {
m_relevancy.asserted(l); m_relevancy.asserted(l);
return; 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)
@ -320,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);
merge(n, nb, c); m_egraph.merge(n, nb, c);
merge(r, rb, to_ptr(rl)); m_egraph.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();
merge(n, nb, c); m_egraph.merge(n, nb, c);
} }
if (n->is_equality()) { if (n->is_equality()) {
SASSERT(!m.is_iff(e)); SASSERT(!m.is_iff(e));
@ -335,7 +335,7 @@ namespace euf {
if (sign) if (sign)
m_egraph.new_diseq(n); m_egraph.new_diseq(n);
else else
merge(n->get_arg(0), n->get_arg(1), c); m_egraph.merge(n->get_arg(0), n->get_arg(1), c);
} }
} }
@ -343,9 +343,8 @@ 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 if (m_relevancy.enabled())
m_relevancy.propagate(); 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()));
@ -362,9 +361,13 @@ namespace euf {
if (m_solvers[i]->unit_propagate()) if (m_solvers[i]->unit_propagate())
propagated1 = true; propagated1 = true;
if (!propagated1) if (propagated1) {
break; propagated = true;
propagated = true; continue;
}
if (m_relevancy.enabled() && m_relevancy.can_propagate())
continue;
break;
} }
DEBUG_CODE(if (!propagated && !s().inconsistent()) check_missing_eq_propagation();); DEBUG_CODE(if (!propagated && !s().inconsistent()) check_missing_eq_propagation(););
return propagated; return propagated;
@ -439,12 +442,10 @@ namespace euf {
void solver::propagate_th_eqs() { void solver::propagate_th_eqs() {
for (; m_egraph.has_th_eq() && !s().inconsistent() && !m_egraph.inconsistent(); m_egraph.next_th_eq()) { for (; m_egraph.has_th_eq() && !s().inconsistent() && !m_egraph.inconsistent(); m_egraph.next_th_eq()) {
th_eq eq = m_egraph.get_th_eq(); th_eq eq = m_egraph.get_th_eq();
if (eq.is_eq()) { if (!eq.is_eq())
if (!is_self_propagated(eq))
m_id2solver[eq.id()]->new_eq_eh(eq);
}
else
m_id2solver[eq.id()]->new_diseq_eh(eq); m_id2solver[eq.id()]->new_diseq_eh(eq);
else if (!is_self_propagated(eq))
m_id2solver[eq.id()]->new_eq_eh(eq);
} }
} }

View file

@ -31,7 +31,6 @@ Author:
#include "sat/smt/smt_relevant.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;
@ -257,6 +256,10 @@ namespace euf {
sat::sat_internalizer& get_si() { return si; } sat::sat_internalizer& get_si() { return si; }
ast_manager& get_manager() { return m; } ast_manager& get_manager() { return m; }
enode* get_enode(expr* e) const { return m_egraph.find(e); } enode* get_enode(expr* e) const { return m_egraph.find(e); }
enode* bool_var2enode(sat::bool_var b) const {
expr* e = m_bool_var2expr.get(b);
return e ? get_enode(e) : nullptr;
}
sat::literal expr2literal(expr* e) const { return enode2literal(get_enode(e)); } sat::literal expr2literal(expr* e) const { return enode2literal(get_enode(e)); }
sat::literal enode2literal(enode* n) const { return sat::literal(n->bool_var(), false); } sat::literal enode2literal(enode* n) const { return sat::literal(n->bool_var(), false); }
lbool value(enode* n) const { return s().value(enode2literal(n)); } lbool value(enode* n) const { return s().value(enode2literal(n)); }
@ -293,7 +296,6 @@ 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()); }
@ -395,7 +397,7 @@ namespace euf {
void add_auto_relevant(sat::literal lit); void add_auto_relevant(sat::literal lit);
void pop_relevant(unsigned n); void pop_relevant(unsigned n);
void push_relevant(); void push_relevant();
smt::relevancy& relevancy() { return m_relevancy; }
// model construction // model construction
void update_model(model_ref& mdl); void update_model(model_ref& mdl);

View file

@ -66,13 +66,21 @@ namespace q {
}; };
std::function<void(euf::enode*)> _on_make = std::function<void(euf::enode*)> _on_make =
[&](euf::enode* n) { [&](euf::enode* n) {
m_mam->add_node(n, false); relevant_eh(n);
}; };
ctx.get_egraph().set_on_merge(_on_merge); ctx.get_egraph().set_on_merge(_on_merge);
ctx.get_egraph().set_on_make(_on_make); if (ctx.relevancy().enabled())
ctx.get_egraph().set_on_make(_on_make);
else
ctx.relevancy().add_relevant(&s);
m_mam = mam::mk(ctx, *this); m_mam = mam::mk(ctx, *this);
} }
void ematch::relevant_eh(euf::enode* n) {
m_mam->add_node(n, false);
}
void ematch::ensure_ground_enodes(expr* e) { void ematch::ensure_ground_enodes(expr* e) {
mam::ground_subterms(e, m_ground); mam::ground_subterms(e, m_ground);
for (expr* g : m_ground) for (expr* g : m_ground)

View file

@ -135,9 +135,10 @@ namespace q {
bool unit_propagate(); bool unit_propagate();
void add(quantifier* q); void add(quantifier* q);
void relevant_eh(euf::enode* n);
void collect_statistics(statistics& st) const; void collect_statistics(statistics& st) const;
void get_antecedents(sat::literal l, sat::ext_justification_idx idx, sat::literal_vector& r, bool probing); void get_antecedents(sat::literal l, sat::ext_justification_idx idx, sat::literal_vector& r, bool probing);

View file

@ -83,6 +83,7 @@ namespace q {
void init_search() override; void init_search() override;
void finalize_model(model& mdl) override; void finalize_model(model& mdl) override;
bool is_shared(euf::theory_var v) const override { return true; } bool is_shared(euf::theory_var v) const override { return true; }
void relevant_eh(euf::enode* n) override { m_ematch.relevant_eh(n); }
ast_manager& get_manager() { return m; } ast_manager& get_manager() { return m; }
sat::literal_vector const& universal() const { return m_universal; } sat::literal_vector const& universal() const { return m_universal; }

View file

@ -111,6 +111,8 @@ namespace euf {
virtual void new_diseq_eh(euf::th_eq const& eq) {} virtual void new_diseq_eh(euf::th_eq const& eq) {}
virtual void relevant_eh(euf::enode* n) {}
/** /**
\brief Parametric theories (e.g. Arrays) should implement this method. \brief Parametric theories (e.g. Arrays) should implement this method.
*/ */

View file

@ -3,7 +3,7 @@ Copyright (c) 2020 Microsoft Corporation
Module Name: Module Name:
relevancy.cpp smt_relevant.cpp
Abstract: Abstract:
@ -22,11 +22,13 @@ Author:
namespace smt { namespace smt {
relevancy::relevancy(euf::solver& ctx): ctx(ctx) { relevancy::relevancy(euf::solver& ctx): ctx(ctx) {
m_enabled = ctx.relevancy_enabled(); m_enabled = ctx.get_config().m_relevancy_lvl > 2;
} }
void relevancy::relevant_eh(euf::enode* n) { void relevancy::relevant_eh(euf::enode* n) {
// nothing SASSERT(is_relevant(n));
for (auto* th : m_relevant_eh)
th->relevant_eh(n);
} }
void relevancy::relevant_eh(sat::literal lit) { void relevancy::relevant_eh(sat::literal lit) {
@ -102,8 +104,10 @@ namespace smt {
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) {
ctx.s().set_external(lit.var());
occurs(lit).push_back(sz); occurs(lit).push_back(sz);
}
} }
void relevancy::add_def(unsigned n, sat::literal const* lits) { void relevancy::add_def(unsigned n, sat::literal const* lits) {
@ -121,15 +125,17 @@ namespace smt {
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); ctx.s().set_external(lit.var());
occurs(lit).push_back(sz);
}
} }
void relevancy::asserted(sat::literal lit) { void relevancy::asserted(sat::literal lit) {
if (!m_enabled) if (!m_enabled)
return; return;
flush(); flush();
if (ctx.s().lvl(lit) == 0) { if (ctx.s().lvl(lit) <= ctx.s().search_lvl()) {
mark_relevant(lit); mark_relevant(lit);
return; return;
} }
@ -164,11 +170,11 @@ namespace smt {
} }
} }
void relevancy::merge(euf::enode* n1, euf::enode* n2) { void relevancy::merge(euf::enode* root, euf::enode* other) {
if (is_relevant(n1)) if (is_relevant(root))
mark_relevant(n2); mark_relevant(other);
else if (is_relevant(n2)) else if (is_relevant(other))
mark_relevant(n1); mark_relevant(root);
} }
void relevancy::mark_relevant(euf::enode* n) { void relevancy::mark_relevant(euf::enode* n) {
@ -177,6 +183,8 @@ namespace smt {
flush(); flush();
if (is_relevant(n)) if (is_relevant(n))
return; return;
if (ctx.get_si().is_bool_op(n->get_expr()))
return;
for (euf::enode* sib : euf::enode_class(n)) for (euf::enode* sib : euf::enode_class(n))
set_relevant(sib); set_relevant(sib);
} }
@ -195,12 +203,12 @@ namespace smt {
flush(); flush();
if (is_relevant(lit)) if (is_relevant(lit))
return; return;
euf::enode* n = ctx.bool_var2enode(lit.var());
if (n)
mark_relevant(n);
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) {
@ -208,9 +216,9 @@ namespace smt {
for (auto idx : occurs(~lit)) { for (auto idx : occurs(~lit)) {
if (m_roots[idx]) if (m_roots[idx])
continue; continue;
sat::clause& cl = *m_clauses[idx]; sat::clause* cl = m_clauses[idx];
sat::literal true_lit = sat::null_literal; sat::literal true_lit = sat::null_literal;
for (sat::literal lit2 : cl) { for (sat::literal lit2 : *cl) {
if (ctx.s().value(lit2) == l_true) { if (ctx.s().value(lit2) == l_true) {
if (is_relevant(lit2)) if (is_relevant(lit2))
goto next; goto next;
@ -231,7 +239,6 @@ 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

@ -3,7 +3,7 @@ Copyright (c) 2020 Microsoft Corporation
Module Name: Module Name:
relevancy.h smt_relevant.h
Abstract: Abstract:
@ -26,7 +26,7 @@ The state transitions are:
-> ->
lit is set relevant lit is set relevant
lit is justified at level 0 lit is justified at search level
-> ->
lit is set relevant lit is set relevant
@ -39,7 +39,7 @@ The state transitions are:
-> ->
all clauses C in Defs where lit appears negatively are added to Roots all clauses C in Defs where lit appears negatively are added to Roots
- When a clause R is added to Roots: - When a clause R is added to Roots:
R contains a positive literal lit that is relevant R contains a positive literal lit that is relevant
-> ->
skip adding R to Roots skip adding R to Roots
@ -72,7 +72,7 @@ Can a literal that is not in a root be set relevant?
- yes, if we propagate over expressions - yes, if we propagate over expressions
Do we need full watch lists instead of 2-watch lists? Do we need full watch lists instead of 2-watch lists?
- probably, but unclear. The dual SAT solver only uses 2-watch lists, but has uses a large clause for tracking - probably, but unclear. The dual SAT solver only uses 2-watch lists, but uses a large clause for tracking
roots. roots.
@ -105,6 +105,7 @@ namespace smt {
vector<unsigned_vector> m_occurs; // where do literals occur vector<unsigned_vector> m_occurs; // where do literals occur
unsigned m_qhead = 0; // queue head for relevancy unsigned m_qhead = 0; // queue head for relevancy
svector<std::pair<sat::literal, euf::enode*>> m_queue; // propagation queue for relevancy svector<std::pair<sat::literal, euf::enode*>> m_queue; // propagation queue for relevancy
ptr_vector<euf::th_solver> m_relevant_eh;
// callbacks during propagation // callbacks during propagation
void relevant_eh(euf::enode* n); void relevant_eh(euf::enode* n);
@ -131,6 +132,7 @@ namespace smt {
void add_def(unsigned n, sat::literal const* lits); void add_def(unsigned n, sat::literal const* lits);
void asserted(sat::literal lit); void asserted(sat::literal lit);
void propagate(); void propagate();
bool can_propagate() const { return m_qhead < m_queue.size(); }
void mark_relevant(euf::enode* n); void mark_relevant(euf::enode* n);
void mark_relevant(sat::literal lit); void mark_relevant(sat::literal lit);
@ -139,6 +141,9 @@ namespace smt {
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); }
bool is_relevant(expr* e) const { return !m_enabled || m_relevant_expr_ids.get(e->get_id(), false); } bool is_relevant(expr* e) const { return !m_enabled || m_relevant_expr_ids.get(e->get_id(), false); }
bool enabled() const { return m_enabled; }
void add_relevant(euf::th_solver* th) { m_relevant_eh.push_back(th); }
}; };
} }