mirror of
https://github.com/Z3Prover/z3
synced 2025-10-09 09:21:56 +00:00
merge with master
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
3533bf486f
223 changed files with 7175 additions and 2167 deletions
|
@ -67,15 +67,8 @@ namespace sat {
|
|||
}
|
||||
};
|
||||
|
||||
unsigned scc::operator()() {
|
||||
if (m_solver.m_inconsistent)
|
||||
return 0;
|
||||
if (!m_scc)
|
||||
return 0;
|
||||
CASSERT("scc_bug", m_solver.check_invariant());
|
||||
report rpt(*this);
|
||||
TRACE("scc", m_solver.display(tout););
|
||||
TRACE("scc_details", m_solver.display_watches(tout););
|
||||
bool scc::extract_roots(literal_vector& roots, bool_var_vector& to_elim) {
|
||||
literal_vector lits;
|
||||
unsigned_vector index;
|
||||
unsigned_vector lowlink;
|
||||
unsigned_vector s;
|
||||
|
@ -84,11 +77,9 @@ namespace sat {
|
|||
index.resize(num_lits, UINT_MAX);
|
||||
lowlink.resize(num_lits, UINT_MAX);
|
||||
in_s.resize(num_lits, false);
|
||||
literal_vector roots, lits;
|
||||
roots.resize(m_solver.num_vars(), null_literal);
|
||||
unsigned next_index = 0;
|
||||
svector<frame> frames;
|
||||
bool_var_vector to_elim;
|
||||
|
||||
for (unsigned l_idx = 0; l_idx < num_lits; l_idx++) {
|
||||
if (index[l_idx] != UINT_MAX)
|
||||
|
@ -182,7 +173,7 @@ namespace sat {
|
|||
j--;
|
||||
if (to_literal(l2_idx) == ~l) {
|
||||
m_solver.set_conflict();
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
if (m_solver.is_external(to_literal(l2_idx).var())) {
|
||||
r = to_literal(l2_idx);
|
||||
|
@ -226,6 +217,23 @@ namespace sat {
|
|||
roots[i] = literal(i, false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
unsigned scc::operator()() {
|
||||
if (m_solver.m_inconsistent)
|
||||
return 0;
|
||||
if (!m_scc)
|
||||
return 0;
|
||||
CASSERT("scc_bug", m_solver.check_invariant());
|
||||
report rpt(*this);
|
||||
TRACE("scc", m_solver.display(tout););
|
||||
TRACE("scc_details", m_solver.display_watches(tout););
|
||||
literal_vector roots;
|
||||
bool_var_vector to_elim;
|
||||
if (!extract_roots(roots, to_elim))
|
||||
return 0;
|
||||
TRACE("scc", for (unsigned i = 0; i < roots.size(); i++) { tout << i << " -> " << roots[i] << "\n"; }
|
||||
tout << "to_elim: "; for (unsigned v : to_elim) tout << v << " "; tout << "\n";);
|
||||
m_num_elim += to_elim.size();
|
||||
|
@ -234,9 +242,8 @@ namespace sat {
|
|||
TRACE("scc_detail", m_solver.display(tout););
|
||||
CASSERT("scc_bug", m_solver.check_invariant());
|
||||
|
||||
if (m_scc_tr) {
|
||||
if (m_scc_tr)
|
||||
reduce_tr();
|
||||
}
|
||||
TRACE("scc_detail", m_solver.display(tout););
|
||||
return to_elim.size();
|
||||
}
|
||||
|
|
|
@ -41,9 +41,13 @@ namespace sat {
|
|||
void reduce_tr();
|
||||
unsigned reduce_tr(bool learned);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
scc(solver & s, params_ref const & p);
|
||||
|
||||
bool extract_roots(literal_vector& roots, bool_var_vector& lits);
|
||||
|
||||
unsigned operator()();
|
||||
|
||||
void updt_params(params_ref const & p);
|
||||
|
|
|
@ -652,6 +652,7 @@ namespace sat {
|
|||
|
||||
inline void simplifier::propagate_unit(literal l) {
|
||||
unsigned old_trail_sz = s.m_trail.size();
|
||||
unsigned num_clauses = s.m_clauses.size();
|
||||
s.assign_scoped(l);
|
||||
s.propagate_core(false); // must not use propagate(), since s.m_clauses is not in a consistent state.
|
||||
if (s.inconsistent())
|
||||
|
@ -672,6 +673,8 @@ namespace sat {
|
|||
}
|
||||
cs.reset();
|
||||
}
|
||||
for (unsigned i = num_clauses; i < s.m_clauses.size(); ++i)
|
||||
m_use_list.insert(*s.m_clauses[i]);
|
||||
}
|
||||
|
||||
void simplifier::elim_lit(clause & c, literal l) {
|
||||
|
@ -1806,6 +1809,8 @@ namespace sat {
|
|||
*/
|
||||
bool simplifier::resolve(clause_wrapper const & c1, clause_wrapper const & c2, literal l, literal_vector & r) {
|
||||
CTRACE("resolve_bug", !c1.contains(l), tout << c1 << "\n" << c2 << "\nl: " << l << "\n";);
|
||||
if (m_visited.size() <= 2*s.num_vars())
|
||||
m_visited.resize(2*s.num_vars(), false);
|
||||
SASSERT(c1.contains(l));
|
||||
SASSERT(c2.contains(~l));
|
||||
bool res = true;
|
||||
|
@ -1825,6 +1830,10 @@ namespace sat {
|
|||
literal l2 = c2[i];
|
||||
if (not_l == l2)
|
||||
continue;
|
||||
if ((~l2).index() >= m_visited.size()) {
|
||||
s.display(std::cout << l2 << " " << s.num_vars() << " " << m_visited.size() << "\n");
|
||||
exit(0);
|
||||
}
|
||||
if (m_visited[(~l2).index()]) {
|
||||
res = false;
|
||||
break;
|
||||
|
|
|
@ -2968,11 +2968,9 @@ namespace sat {
|
|||
}
|
||||
break;
|
||||
case PS_SAT_CACHING:
|
||||
if (m_search_state == s_sat) {
|
||||
for (unsigned i = 0; i < m_phase.size(); ++i) {
|
||||
m_phase[i] = m_best_phase[i];
|
||||
}
|
||||
}
|
||||
if (m_search_state == s_sat)
|
||||
for (unsigned i = 0; i < m_phase.size(); ++i)
|
||||
m_phase[i] = m_best_phase[i];
|
||||
break;
|
||||
case PS_RANDOM:
|
||||
for (auto& p : m_phase) p = (m_rand() % 2) == 0;
|
||||
|
@ -3823,6 +3821,8 @@ namespace sat {
|
|||
void solver::move_to_front(bool_var b) {
|
||||
if (b >= num_vars())
|
||||
return;
|
||||
if (m_case_split_queue.empty())
|
||||
return;
|
||||
bool_var next = m_case_split_queue.min_var();
|
||||
auto next_act = m_activity[next];
|
||||
set_activity(b, next_act + 1);
|
||||
|
@ -4177,7 +4177,7 @@ namespace sat {
|
|||
lbool solver::find_mutexes(literal_vector const& lits, vector<literal_vector> & mutexes) {
|
||||
max_cliques<neg_literal> mc;
|
||||
m_user_bin_clauses.reset();
|
||||
m_binary_clause_graph.reset();
|
||||
// m_binary_clause_graph.reset();
|
||||
collect_bin_clauses(m_user_bin_clauses, true, false);
|
||||
hashtable<literal_pair, pair_hash<literal_hash, literal_hash>, default_eq<literal_pair> > seen_bc;
|
||||
for (auto const& b : m_user_bin_clauses) {
|
||||
|
@ -4192,20 +4192,22 @@ namespace sat {
|
|||
vector<unsigned_vector> _mutexes;
|
||||
literal_vector _lits(lits);
|
||||
if (m_ext) {
|
||||
// m_ext->find_mutexes(_lits, mutexes);
|
||||
m_ext->find_mutexes(_lits, mutexes);
|
||||
}
|
||||
unsigned_vector ps;
|
||||
for (literal lit : _lits) {
|
||||
for (literal lit : _lits)
|
||||
ps.push_back(lit.index());
|
||||
}
|
||||
mc.cliques(ps, _mutexes);
|
||||
mc.cliques2(ps, _mutexes);
|
||||
vector<vector<literal_vector>> sorted;
|
||||
for (auto const& mux : _mutexes) {
|
||||
literal_vector clique;
|
||||
for (auto const& idx : mux) {
|
||||
sorted.reserve(mux.size() + 1);
|
||||
for (auto const& idx : mux)
|
||||
clique.push_back(to_literal(idx));
|
||||
}
|
||||
mutexes.push_back(clique);
|
||||
sorted[mux.size()].push_back(clique);
|
||||
}
|
||||
for (unsigned i = sorted.size(); i-- > 0; )
|
||||
mutexes.append(sorted[i]);
|
||||
return l_true;
|
||||
}
|
||||
|
||||
|
|
|
@ -374,7 +374,7 @@ namespace sat {
|
|||
void set_eliminated(bool_var v, bool f) override;
|
||||
bool was_eliminated(literal l) const { return was_eliminated(l.var()); }
|
||||
void set_phase(literal l) override { if (l.var() < num_vars()) m_best_phase[l.var()] = m_phase[l.var()] = !l.sign(); }
|
||||
bool_var get_phase(bool_var b) { return m_phase.get(b, false); }
|
||||
bool get_phase(bool_var b) { return m_phase.get(b, false); }
|
||||
void move_to_front(bool_var b);
|
||||
unsigned scope_lvl() const { return m_scope_lvl; }
|
||||
unsigned search_lvl() const { return m_search_lvl; }
|
||||
|
@ -755,7 +755,7 @@ namespace sat {
|
|||
|
||||
u_map<index_set> m_antecedents;
|
||||
literal_vector m_todo_antecedents;
|
||||
vector<literal_vector> m_binary_clause_graph;
|
||||
// vector<literal_vector> m_binary_clause_graph;
|
||||
|
||||
bool extract_assumptions(literal lit, index_set& s);
|
||||
|
||||
|
|
|
@ -390,7 +390,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
expr_ref_vector get_trail() override {
|
||||
expr_ref_vector get_trail(unsigned max_level) override {
|
||||
expr_ref_vector result(m);
|
||||
unsigned sz = m_solver.trail_size();
|
||||
expr_ref_vector lit2expr(m);
|
||||
|
@ -398,7 +398,11 @@ public:
|
|||
m_map.mk_inv(lit2expr);
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
sat::literal lit = m_solver.trail_literal(i);
|
||||
result.push_back(lit2expr[lit.index()].get());
|
||||
if (m_solver.lvl(lit) > max_level)
|
||||
continue;
|
||||
expr_ref e(lit2expr.get(lit.index()), m);
|
||||
if (e)
|
||||
result.push_back(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -683,11 +687,11 @@ public:
|
|||
ensure_euf()->user_propagate_register_diseq(diseq_eh);
|
||||
}
|
||||
|
||||
unsigned user_propagate_register_expr(expr* e) override {
|
||||
return ensure_euf()->user_propagate_register_expr(e);
|
||||
void user_propagate_register_expr(expr* e) override {
|
||||
ensure_euf()->user_propagate_register_expr(e);
|
||||
}
|
||||
|
||||
void user_propagate_register_created(user_propagator::created_eh_t& r) {
|
||||
void user_propagate_register_created(user_propagator::created_eh_t& r) override {
|
||||
ensure_euf()->user_propagate_register_created(r);
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ namespace arith {
|
|||
m_nla->settings().grobner_number_of_conflicts_to_report() = prms.arith_nl_grobner_cnfl_to_report();
|
||||
m_nla->settings().grobner_quota() = prms.arith_nl_gr_q();
|
||||
m_nla->settings().grobner_frequency() = prms.arith_nl_grobner_frequency();
|
||||
m_nla->settings().expensive_patching() = prms.arith_nl_expp();
|
||||
m_nla->settings().expensive_patching() = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -549,13 +549,14 @@ namespace arith {
|
|||
found_compatible = false;
|
||||
for (; it != end; ++it) {
|
||||
api_bound* a2 = *it;
|
||||
if (a1 == a2) continue;
|
||||
if (a2->get_bound_kind() != kind) continue;
|
||||
if (a1 == a2)
|
||||
continue;
|
||||
if (a2->get_bound_kind() != kind)
|
||||
continue;
|
||||
rational const& k2(a2->get_value());
|
||||
found_compatible = true;
|
||||
if (k1 < k2) {
|
||||
if (k1 < k2)
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
|
|
@ -419,6 +419,7 @@ namespace arith {
|
|||
void false_case_of_check_nla(const nla::lemma& l);
|
||||
void dbg_finalize_model(model& mdl);
|
||||
|
||||
|
||||
public:
|
||||
solver(euf::solver& ctx, theory_id id);
|
||||
~solver() override;
|
||||
|
@ -426,6 +427,8 @@ namespace arith {
|
|||
void get_antecedents(literal l, sat::ext_justification_idx idx, literal_vector& r, bool probing) override;
|
||||
void asserted(literal l) override;
|
||||
sat::check_result check() override;
|
||||
void simplify() override {}
|
||||
void init_search() override {}
|
||||
|
||||
std::ostream& display(std::ostream& out) const override;
|
||||
std::ostream& display_justification(std::ostream& out, sat::ext_justification_idx idx) const override;
|
||||
|
|
|
@ -556,7 +556,7 @@ namespace array {
|
|||
bool has_default = false;
|
||||
for (euf::enode* p : euf::enode_parents(n))
|
||||
has_default |= a.is_default(p->get_expr());
|
||||
if (has_default)
|
||||
if (!has_default)
|
||||
propagate_parent_default(v);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,27 +24,32 @@ namespace array {
|
|||
|
||||
void solver::init_model() {
|
||||
collect_defaults();
|
||||
collect_selects();
|
||||
}
|
||||
|
||||
void solver::finalize_model(model& mdl) {
|
||||
std::for_each(m_selects_range.begin(), m_selects_range.end(), delete_proc<select_set>());
|
||||
}
|
||||
|
||||
bool solver::add_dep(euf::enode* n, top_sort<euf::enode>& dep) {
|
||||
bool solver::add_dep(euf::enode* n, top_sort<euf::enode>& dep) {
|
||||
if (!a.is_array(n->get_expr())) {
|
||||
dep.insert(n, nullptr);
|
||||
return true;
|
||||
}
|
||||
for (euf::enode* p : euf::enode_parents(n->get_root())) {
|
||||
if (a.is_default(p->get_expr())) {
|
||||
}
|
||||
if (a.is_array(n->get_expr())) {
|
||||
for (euf::enode* p : euf::enode_parents(n->get_root()))
|
||||
if (a.is_default(p->get_expr()))
|
||||
dep.add(n, p);
|
||||
|
||||
for (euf::enode* p : *get_select_set(n)) {
|
||||
dep.add(n, p);
|
||||
continue;
|
||||
for (unsigned i = 1; i < p->num_args(); ++i)
|
||||
dep.add(n, p->get_arg(i));
|
||||
}
|
||||
if (!a.is_select(p->get_expr()))
|
||||
continue;
|
||||
dep.add(n, p);
|
||||
for (unsigned i = 1; i < p->num_args(); ++i)
|
||||
dep.add(n, p->get_arg(i));
|
||||
}
|
||||
for (euf::enode* k : euf::enode_class(n))
|
||||
if (a.is_const(k->get_expr()))
|
||||
dep.add(n, k->get_arg(0));
|
||||
dep.add(n, k->get_arg(0));
|
||||
theory_var v = get_th_var(n);
|
||||
euf::enode* d = get_default(v);
|
||||
if (d)
|
||||
|
@ -103,17 +108,27 @@ namespace array {
|
|||
|
||||
if (!get_else(v) && fi->get_else())
|
||||
set_else(v, fi->get_else());
|
||||
|
||||
for (euf::enode* p : euf::enode_parents(n)) {
|
||||
if (a.is_select(p->get_expr()) && p->get_arg(0)->get_root() == n) {
|
||||
expr* value = values.get(p->get_root_id(), nullptr);
|
||||
if (!value || value == fi->get_else())
|
||||
continue;
|
||||
args.reset();
|
||||
for (unsigned i = 1; i < p->num_args(); ++i)
|
||||
args.push_back(values.get(p->get_arg(i)->get_root_id()));
|
||||
fi->insert_entry(args.data(), value);
|
||||
|
||||
if (!get_else(v)) {
|
||||
expr* else_value = mdl.get_some_value(get_array_range(srt));
|
||||
fi->set_else(else_value);
|
||||
set_else(v, else_value);
|
||||
}
|
||||
|
||||
for (euf::enode* p : *get_select_set(n)) {
|
||||
expr* value = values.get(p->get_root_id(), nullptr);
|
||||
if (!value || value == fi->get_else())
|
||||
continue;
|
||||
args.reset();
|
||||
for (unsigned i = 1; i < p->num_args(); ++i) {
|
||||
if (!values.get(p->get_arg(i)->get_root_id())) {
|
||||
TRACE("array", tout << ctx.bpp(p->get_arg(i)) << "\n");
|
||||
}
|
||||
SASSERT(values.get(p->get_arg(i)->get_root_id()));
|
||||
}
|
||||
for (unsigned i = 1; i < p->num_args(); ++i)
|
||||
args.push_back(values.get(p->get_arg(i)->get_root_id()));
|
||||
fi->insert_entry(args.data(), value);
|
||||
}
|
||||
|
||||
TRACE("array", tout << "array-as-function " << ctx.bpp(n) << " := " << mk_pp(f, m) << "\n" << "default " << mk_pp(fi->get_else(), m) << "\n";);
|
||||
|
@ -135,52 +150,103 @@ namespace array {
|
|||
return true;
|
||||
|
||||
return false;
|
||||
#if 0
|
||||
struct eq {
|
||||
solver& s;
|
||||
eq(solver& s) :s(s) {}
|
||||
bool operator()(euf::enode* n1, euf::enode* n2) const {
|
||||
SASSERT(s.a.is_select(n1->get_expr()));
|
||||
SASSERT(s.a.is_select(n2->get_expr()));
|
||||
for (unsigned i = n1->num_args(); i-- > 1; )
|
||||
if (n1->get_arg(i)->get_root() != n2->get_arg(i)->get_root())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct hash {
|
||||
solver& s;
|
||||
hash(solver& s) :s(s) {}
|
||||
unsigned operator()(euf::enode* n) const {
|
||||
SASSERT(s.a.is_select(n->get_expr()));
|
||||
unsigned h = 33;
|
||||
for (unsigned i = n->num_args(); i-- > 1; )
|
||||
h = hash_u_u(h, n->get_arg(i)->get_root_id());
|
||||
return h;
|
||||
}
|
||||
};
|
||||
eq eq_proc(*this);
|
||||
hash hash_proc(*this);
|
||||
hashtable<euf::enode*, hash, eq> table(DEFAULT_HASHTABLE_INITIAL_CAPACITY, hash_proc, eq_proc);
|
||||
euf::enode* p2 = nullptr;
|
||||
auto maps_diff = [&](euf::enode* p, euf::enode* else_, euf::enode* r) {
|
||||
return table.find(p, p2) ? p2->get_root() != r : (else_ && else_ != r);
|
||||
};
|
||||
auto table_diff = [&](euf::enode* r1, euf::enode* r2, euf::enode* else1) {
|
||||
table.reset();
|
||||
for (euf::enode* p : euf::enode_parents(r1))
|
||||
if (a.is_select(p->get_expr()) && r1 == p->get_arg(0)->get_root())
|
||||
table.insert(p);
|
||||
for (euf::enode* p : euf::enode_parents(r2))
|
||||
if (a.is_select(p->get_expr()) && r2 == p->get_arg(0)->get_root())
|
||||
if (maps_diff(p, else1, p->get_root()))
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
return table_diff(r1, r2, else1) || table_diff(r2, r1, else2);
|
||||
}
|
||||
|
||||
#endif
|
||||
unsigned solver::sel_hash::operator()(euf::enode * n) const {
|
||||
return get_composite_hash<euf::enode *, sel_khasher, sel_chasher>(n, n->num_args() - 1, sel_khasher(), sel_chasher());
|
||||
}
|
||||
|
||||
bool solver::sel_eq::operator()(euf::enode * n1, euf::enode * n2) const {
|
||||
SASSERT(n1->num_args() == n2->num_args());
|
||||
unsigned num_args = n1->num_args();
|
||||
for (unsigned i = 1; i < num_args; i++)
|
||||
if (n1->get_arg(i)->get_root() != n2->get_arg(i)->get_root())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void solver::collect_selects() {
|
||||
int num_vars = get_num_vars();
|
||||
|
||||
m_selects.reset();
|
||||
m_selects_domain.reset();
|
||||
m_selects_range.reset();
|
||||
|
||||
for (theory_var v = 0; v < num_vars; ++v) {
|
||||
euf::enode * r = var2enode(v)->get_root();
|
||||
if (is_representative(v) && ctx.is_relevant(r)) {
|
||||
for (euf::enode * parent : euf::enode_parents(r)) {
|
||||
if (parent->get_cg() == parent &&
|
||||
ctx.is_relevant(parent) &&
|
||||
a.is_select(parent->get_expr()) &&
|
||||
parent->get_arg(0)->get_root() == r) {
|
||||
select_set * s = get_select_set(r);
|
||||
SASSERT(!s->contains(parent) || (*(s->find(parent)))->get_root() == parent->get_root());
|
||||
s->insert(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
euf::enode_pair_vector todo;
|
||||
for (euf::enode * r : m_selects_domain)
|
||||
for (euf::enode* sel : *get_select_set(r))
|
||||
propagate_select_to_store_parents(r, sel, todo);
|
||||
for (unsigned qhead = 0; qhead < todo.size(); qhead++) {
|
||||
euf::enode_pair & pair = todo[qhead];
|
||||
euf::enode * r = pair.first;
|
||||
euf::enode * sel = pair.second;
|
||||
propagate_select_to_store_parents(r, sel, todo);
|
||||
}
|
||||
}
|
||||
|
||||
void solver::propagate_select_to_store_parents(euf::enode* r, euf::enode* sel, euf::enode_pair_vector& todo) {
|
||||
SASSERT(r->get_root() == r);
|
||||
SASSERT(a.is_select(sel->get_expr()));
|
||||
if (!ctx.is_relevant(r))
|
||||
return;
|
||||
|
||||
for (euf::enode * parent : euf::enode_parents(r)) {
|
||||
if (ctx.is_relevant(parent) &&
|
||||
a.is_store(parent->get_expr()) &&
|
||||
parent->get_arg(0)->get_root() == r) {
|
||||
// propagate upward
|
||||
select_set * parent_sel_set = get_select_set(parent);
|
||||
euf::enode * parent_root = parent->get_root();
|
||||
|
||||
if (parent_sel_set->contains(sel))
|
||||
continue;
|
||||
|
||||
SASSERT(sel->num_args() + 1 == parent->num_args());
|
||||
|
||||
// check whether the sel idx was overwritten by the store
|
||||
unsigned num_args = sel->num_args();
|
||||
unsigned i = 1;
|
||||
for (; i < num_args; i++) {
|
||||
if (sel->get_arg(i)->get_root() != parent->get_arg(i)->get_root())
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < num_args) {
|
||||
SASSERT(!parent_sel_set->contains(sel) || (*(parent_sel_set->find(sel)))->get_root() == sel->get_root());
|
||||
parent_sel_set->insert(sel);
|
||||
todo.push_back(std::make_pair(parent_root, sel));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
solver::select_set* solver::get_select_set(euf::enode* n) {
|
||||
euf::enode * r = n->get_root();
|
||||
select_set * set = nullptr;
|
||||
m_selects.find(r, set);
|
||||
if (set == nullptr) {
|
||||
set = alloc(select_set);
|
||||
m_selects.insert(r, set);
|
||||
m_selects_domain.push_back(r);
|
||||
m_selects_range.push_back(set);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
void solver::collect_defaults() {
|
||||
|
|
|
@ -218,11 +218,39 @@ namespace array {
|
|||
void pop_core(unsigned n) override;
|
||||
|
||||
// models
|
||||
// I need a set of select enodes where select(A,i) = select(B,j) if i->get_root() == j->get_root()
|
||||
struct sel_khasher {
|
||||
unsigned operator()(euf::enode const * n) const { return 0; }
|
||||
};
|
||||
|
||||
struct sel_chasher {
|
||||
unsigned operator()(euf::enode const * n, unsigned idx) const {
|
||||
return n->get_arg(idx+1)->get_root()->hash();
|
||||
}
|
||||
};
|
||||
|
||||
struct sel_hash {
|
||||
unsigned operator()(euf::enode * n) const;
|
||||
};
|
||||
|
||||
struct sel_eq {
|
||||
bool operator()(euf::enode * n1, euf::enode * n2) const;
|
||||
};
|
||||
|
||||
typedef ptr_hashtable<euf::enode, sel_hash, sel_eq> select_set;
|
||||
euf::enode_vector m_defaults; // temporary field for model construction
|
||||
ptr_vector<expr> m_else_values; //
|
||||
svector<int> m_parents; // temporary field for model construction
|
||||
obj_map<euf::enode, select_set*> m_selects; // mapping from array -> relevant selects
|
||||
ptr_vector<euf::enode> m_selects_domain;
|
||||
ptr_vector<select_set> m_selects_range;
|
||||
|
||||
bool must_have_different_model_values(theory_var v1, theory_var v2);
|
||||
select_set* get_select_set(euf::enode* n);
|
||||
void collect_defaults();
|
||||
void collect_selects(); // mapping from array -> relevant selects
|
||||
void propagate_select_to_store_parents(euf::enode* r, euf::enode* sel, euf::enode_pair_vector& todo);
|
||||
|
||||
void mg_merge(theory_var u, theory_var v);
|
||||
theory_var mg_find(theory_var n);
|
||||
void set_default(theory_var v, euf::enode* n);
|
||||
|
@ -254,6 +282,7 @@ namespace array {
|
|||
void new_diseq_eh(euf::th_eq const& eq) override;
|
||||
bool unit_propagate() override;
|
||||
void init_model() override;
|
||||
void finalize_model(model& mdl) override;
|
||||
bool include_func_interp(func_decl* f) const override { return a.is_ext(f); }
|
||||
void add_value(euf::enode* n, model& mdl, expr_ref_vector& values) override;
|
||||
bool add_dep(euf::enode* n, top_sort<euf::enode>& dep) override;
|
||||
|
|
|
@ -19,6 +19,7 @@ Notes:
|
|||
|
||||
#include "util/ref_util.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "tactic/goal.h"
|
||||
#include "sat/smt/atom2bool_var.h"
|
||||
|
||||
|
@ -27,7 +28,7 @@ void atom2bool_var::mk_inv(expr_ref_vector & lit2expr) const {
|
|||
sat::literal l(static_cast<sat::bool_var>(kv.m_value), false);
|
||||
lit2expr.set(l.index(), kv.m_key);
|
||||
l.neg();
|
||||
lit2expr.set(l.index(), m().mk_not(kv.m_key));
|
||||
lit2expr.set(l.index(), mk_not(m(), kv.m_key));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,12 +41,12 @@ void atom2bool_var::mk_var_inv(expr_ref_vector & var2expr) const {
|
|||
|
||||
sat::bool_var atom2bool_var::to_bool_var(expr * n) const {
|
||||
unsigned idx = m_id2map.get(n->get_id(), UINT_MAX);
|
||||
if (idx == UINT_MAX) {
|
||||
if (idx == UINT_MAX)
|
||||
return sat::null_bool_var;
|
||||
}
|
||||
else {
|
||||
else if (idx >= m_mapping.size())
|
||||
return sat::null_bool_var;
|
||||
else
|
||||
return m_mapping[idx].m_value;
|
||||
}
|
||||
}
|
||||
|
||||
struct collect_boolean_interface_proc {
|
||||
|
|
|
@ -190,8 +190,9 @@ namespace euf {
|
|||
m_egraph.set_bool_var(n, v);
|
||||
if (m.is_eq(e) || m.is_or(e) || m.is_and(e) || m.is_not(e))
|
||||
m_egraph.set_merge_enabled(n, false);
|
||||
if (s().value(lit) != l_undef)
|
||||
m_egraph.set_value(n, s().value(lit));
|
||||
lbool val = s().value(lit);
|
||||
if (val != l_undef)
|
||||
m_egraph.set_value(n, val, justification::external(to_ptr(val == l_true ? lit : ~lit)));
|
||||
return lit;
|
||||
}
|
||||
|
||||
|
@ -311,6 +312,7 @@ namespace euf {
|
|||
}
|
||||
}
|
||||
else if (m.is_distinct(e)) {
|
||||
// TODO - add lazy case for large values of sz.
|
||||
expr_ref_vector eqs(m);
|
||||
unsigned sz = n->num_args();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
|
|
|
@ -63,9 +63,17 @@ namespace euf {
|
|||
}
|
||||
};
|
||||
|
||||
void solver::save_model(model_ref& mdl) {
|
||||
m_qmodel = mdl;
|
||||
}
|
||||
|
||||
void solver::update_model(model_ref& mdl) {
|
||||
TRACE("model", tout << "create model\n";);
|
||||
mdl->reset_eval_cache();
|
||||
if (m_qmodel) {
|
||||
mdl = m_qmodel;
|
||||
return;
|
||||
}
|
||||
mdl->reset_eval_cache();
|
||||
for (auto* mb : m_solvers)
|
||||
mb->init_model();
|
||||
m_values.reset();
|
||||
|
|
|
@ -309,7 +309,7 @@ namespace euf {
|
|||
if (!n)
|
||||
return;
|
||||
bool sign = l.sign();
|
||||
m_egraph.set_value(n, sign ? l_false : l_true);
|
||||
m_egraph.set_value(n, sign ? l_false : l_true, justification::external(to_ptr(l)));
|
||||
for (auto const& th : enode_th_vars(n))
|
||||
m_id2solver[th.get_id()]->asserted(l);
|
||||
|
||||
|
|
|
@ -154,6 +154,7 @@ namespace euf {
|
|||
// model building
|
||||
expr_ref_vector m_values;
|
||||
obj_map<expr, enode*> m_values2root;
|
||||
model_ref m_qmodel;
|
||||
bool include_func_interp(func_decl* f);
|
||||
void register_macros(model& mdl);
|
||||
void dependencies2values(user_sort& us, deps_t& deps, model_ref& mdl);
|
||||
|
@ -396,6 +397,7 @@ namespace euf {
|
|||
relevancy& get_relevancy() { return m_relevancy; }
|
||||
|
||||
// model construction
|
||||
void save_model(model_ref& mdl);
|
||||
void update_model(model_ref& mdl);
|
||||
obj_map<expr, enode*> const& values2root();
|
||||
void model_updated(model_ref& mdl);
|
||||
|
@ -435,9 +437,9 @@ namespace euf {
|
|||
check_for_user_propagator();
|
||||
m_user_propagator->register_created(ceh);
|
||||
}
|
||||
unsigned user_propagate_register_expr(expr* e) {
|
||||
void user_propagate_register_expr(expr* e) {
|
||||
check_for_user_propagator();
|
||||
return m_user_propagator->add_expr(e);
|
||||
m_user_propagator->add_expr(e);
|
||||
}
|
||||
|
||||
// solver factory
|
||||
|
|
|
@ -21,6 +21,7 @@ Author:
|
|||
#include "sat/smt/pb_solver.h"
|
||||
#include "sat/smt/euf_solver.h"
|
||||
#include "sat/sat_simplifier_params.hpp"
|
||||
#include "sat/sat_scc.h"
|
||||
|
||||
namespace pb {
|
||||
|
||||
|
@ -69,7 +70,7 @@ namespace pb {
|
|||
SASSERT(s().at_base_lvl());
|
||||
if (p.lit() != sat::null_literal && value(p.lit()) == l_false) {
|
||||
TRACE("ba", tout << "pb: flip sign " << p << "\n";);
|
||||
IF_VERBOSE(1, verbose_stream() << "sign is flipped " << p << "\n";);
|
||||
IF_VERBOSE(2, verbose_stream() << "sign is flipped " << p << "\n";);
|
||||
return;
|
||||
}
|
||||
bool nullify = p.lit() != sat::null_literal && value(p.lit()) == l_true;
|
||||
|
@ -109,22 +110,21 @@ namespace pb {
|
|||
}
|
||||
}
|
||||
else if (true_val >= p.k()) {
|
||||
if (p.lit() != sat::null_literal) {
|
||||
IF_VERBOSE(100, display(verbose_stream() << "assign true literal ", p, true););
|
||||
IF_VERBOSE(100, display(verbose_stream() << "assign true literal ", p, true););
|
||||
if (p.lit() != sat::null_literal)
|
||||
s().assign_scoped(p.lit());
|
||||
}
|
||||
remove_constraint(p, "is true");
|
||||
else
|
||||
remove_constraint(p, "is true");
|
||||
}
|
||||
else if (slack + true_val < p.k()) {
|
||||
if (p.lit() != sat::null_literal) {
|
||||
IF_VERBOSE(100, display(verbose_stream() << "assign false literal ", p, true););
|
||||
IF_VERBOSE(3, display(verbose_stream() << "assign false literal ", p, true););
|
||||
s().assign_scoped(~p.lit());
|
||||
}
|
||||
else {
|
||||
IF_VERBOSE(1, verbose_stream() << "unsat during simplification\n";);
|
||||
IF_VERBOSE(1, verbose_stream() << "unsat during simplification\n");
|
||||
s().set_conflict(sat::justification(0));
|
||||
}
|
||||
remove_constraint(p, "is false");
|
||||
}
|
||||
else if (slack + true_val == p.k()) {
|
||||
literal_vector lits(p.literals());
|
||||
|
@ -132,14 +132,16 @@ namespace pb {
|
|||
remove_constraint(p, "is tight");
|
||||
}
|
||||
else {
|
||||
|
||||
unsigned sz = p.size();
|
||||
clear_watch(p);
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
literal l = p.get_lit(i);
|
||||
if (value(l) == l_undef) {
|
||||
if (i != j) p.swap(i, j);
|
||||
++j;
|
||||
if (i != j)
|
||||
p.swap(i, j);
|
||||
++j;
|
||||
}
|
||||
}
|
||||
sz = j;
|
||||
|
@ -167,6 +169,7 @@ namespace pb {
|
|||
_bad_id = 11111111;
|
||||
SASSERT(p.well_formed());
|
||||
m_simplify_change = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1422,7 +1425,7 @@ namespace pb {
|
|||
c->watch_literal(*this, ~lit);
|
||||
}
|
||||
if (!c->well_formed())
|
||||
std::cout << *c << "\n";
|
||||
IF_VERBOSE(0, verbose_stream() << *c << "\n");
|
||||
VERIFY(c->well_formed());
|
||||
if (m_solver && m_solver->get_config().m_drat) {
|
||||
std::function<void(std::ostream& out)> fn = [&](std::ostream& out) {
|
||||
|
@ -1457,7 +1460,7 @@ namespace pb {
|
|||
return nullptr;
|
||||
}
|
||||
rational weight(0);
|
||||
for (auto const [w, l] : wlits)
|
||||
for (auto const &[w, l] : wlits)
|
||||
weight += w;
|
||||
if (weight < k) {
|
||||
if (lit == sat::null_literal)
|
||||
|
@ -2035,7 +2038,7 @@ namespace pb {
|
|||
m_constraint_to_reinit.shrink(sz);
|
||||
}
|
||||
|
||||
void solver::simplify() {
|
||||
void solver::simplify() {
|
||||
if (!s().at_base_lvl())
|
||||
s().pop_to_base_level();
|
||||
if (s().inconsistent())
|
||||
|
@ -2192,7 +2195,7 @@ namespace pb {
|
|||
}
|
||||
}
|
||||
|
||||
bool solver::set_root(literal l, literal r) {
|
||||
bool solver::set_root(literal l, literal r) {
|
||||
if (s().is_assumption(l.var()))
|
||||
return false;
|
||||
reserve_roots();
|
||||
|
@ -2205,17 +2208,18 @@ namespace pb {
|
|||
}
|
||||
|
||||
void solver::flush_roots() {
|
||||
if (m_roots.empty()) return;
|
||||
if (m_roots.empty())
|
||||
return;
|
||||
reserve_roots();
|
||||
// validate();
|
||||
DEBUG_CODE(validate(););
|
||||
m_constraint_removed = false;
|
||||
for (unsigned sz = m_constraints.size(), i = 0; i < sz; ++i)
|
||||
flush_roots(*m_constraints[i]);
|
||||
for (unsigned sz = m_learned.size(), i = 0; i < sz; ++i)
|
||||
flush_roots(*m_learned[i]);
|
||||
cleanup_constraints();
|
||||
// validate();
|
||||
// validate_eliminated();
|
||||
DEBUG_CODE(validate(););
|
||||
DEBUG_CODE(validate_eliminated(););
|
||||
}
|
||||
|
||||
void solver::validate_eliminated() {
|
||||
|
@ -2633,6 +2637,10 @@ namespace pb {
|
|||
* add ~root(~l) to c, k <- k + 1
|
||||
*/
|
||||
void solver::unit_strengthen() {
|
||||
return;
|
||||
|
||||
// TODO - this is unsound exposed by 4_21_21_-1.txt
|
||||
|
||||
sat::big big(s().m_rand);
|
||||
big.init(s(), true);
|
||||
for (unsigned sz = m_constraints.size(), i = 0; i < sz; ++i)
|
||||
|
@ -2642,7 +2650,8 @@ namespace pb {
|
|||
}
|
||||
|
||||
void solver::unit_strengthen(sat::big& big, constraint& p) {
|
||||
if (p.lit() != sat::null_literal) return;
|
||||
if (p.lit() != sat::null_literal)
|
||||
return;
|
||||
unsigned sz = p.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
literal u = p.get_lit(i);
|
||||
|
@ -2690,8 +2699,8 @@ namespace pb {
|
|||
}
|
||||
}
|
||||
++m_stats.m_num_big_strengthenings;
|
||||
constraint* c = add_pb_ge(sat::null_literal, wlits, b, p.learned());
|
||||
p.set_removed();
|
||||
add_pb_ge(sat::null_literal, wlits, b, p.learned());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2764,7 +2773,7 @@ namespace pb {
|
|||
ptr_vector<constraint>::iterator it2 = it;
|
||||
ptr_vector<constraint>::iterator end = cs.end();
|
||||
for (; it != end; ++it) {
|
||||
constraint& c = *(*it);
|
||||
constraint& c = *(*it);
|
||||
if (c.was_removed()) {
|
||||
clear_watch(c);
|
||||
c.nullify_tracking_literal(*this);
|
||||
|
@ -3133,32 +3142,35 @@ namespace pb {
|
|||
void solver::find_mutexes(literal_vector& lits, vector<literal_vector> & mutexes) {
|
||||
sat::literal_set slits(lits);
|
||||
bool change = false;
|
||||
|
||||
for (constraint* cp : m_constraints) {
|
||||
if (!cp->is_card()) continue;
|
||||
if (!cp->is_card())
|
||||
continue;
|
||||
if (cp->lit() != sat::null_literal)
|
||||
continue;
|
||||
card const& c = cp->to_card();
|
||||
if (c.size() == c.k() + 1) {
|
||||
literal_vector mux;
|
||||
for (literal lit : c) {
|
||||
if (slits.contains(~lit)) {
|
||||
mux.push_back(~lit);
|
||||
}
|
||||
}
|
||||
if (mux.size() <= 1) {
|
||||
continue;
|
||||
}
|
||||
if (c.size() != c.k() + 1)
|
||||
continue;
|
||||
|
||||
for (literal m : mux) {
|
||||
slits.remove(m);
|
||||
}
|
||||
change = true;
|
||||
mutexes.push_back(mux);
|
||||
}
|
||||
literal_vector mux;
|
||||
for (literal lit : c)
|
||||
if (slits.contains(~lit))
|
||||
mux.push_back(~lit);
|
||||
|
||||
if (mux.size() <= 1)
|
||||
continue;
|
||||
|
||||
for (literal m : mux)
|
||||
slits.remove(m);
|
||||
|
||||
change = true;
|
||||
mutexes.push_back(mux);
|
||||
}
|
||||
if (!change) return;
|
||||
if (!change)
|
||||
return;
|
||||
lits.reset();
|
||||
for (literal l : slits) {
|
||||
for (literal l : slits)
|
||||
lits.push_back(l);
|
||||
}
|
||||
}
|
||||
|
||||
void solver::display(std::ostream& out, ineq const& ineq, bool values) const {
|
||||
|
@ -3224,9 +3236,6 @@ namespace pb {
|
|||
display(verbose_stream(), p, true););
|
||||
return false;
|
||||
}
|
||||
// if (value(alit) == l_true && lvl(l) == lvl(alit)) {
|
||||
// std::cout << "same level " << alit << " " << l << "\n";
|
||||
// }
|
||||
}
|
||||
// the sum of elements not in r or alit add up to less than k.
|
||||
unsigned sum = 0;
|
||||
|
@ -3421,19 +3430,11 @@ namespace pb {
|
|||
++num_max_level;
|
||||
}
|
||||
}
|
||||
if (m_overflow) {
|
||||
if (m_overflow)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (slack >= k) {
|
||||
#if 0
|
||||
return active2constraint();
|
||||
active2pb(m_A);
|
||||
std::cout << "not asserting\n";
|
||||
display(std::cout, m_A, true);
|
||||
#endif
|
||||
if (slack >= k)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// produce asserting cardinality constraint
|
||||
literal_vector lits;
|
||||
|
|
|
@ -1893,7 +1893,8 @@ namespace q {
|
|||
}
|
||||
|
||||
void recycle_enode_vector(enode_vector * v) {
|
||||
m_pool.recycle(v);
|
||||
if (v)
|
||||
m_pool.recycle(v);
|
||||
}
|
||||
|
||||
void update_max_generation(enode * n, enode * prev) {
|
||||
|
@ -2197,8 +2198,10 @@ namespace q {
|
|||
if (curr->num_args() == expected_num_args && ctx.is_relevant(curr))
|
||||
break;
|
||||
}
|
||||
if (bp.m_it == bp.m_end)
|
||||
if (bp.m_it == bp.m_end) {
|
||||
recycle_enode_vector(bp.m_to_recycle);
|
||||
return nullptr;
|
||||
}
|
||||
m_top++;
|
||||
update_max_generation(*(bp.m_it), nullptr);
|
||||
return *(bp.m_it);
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace q {
|
|||
lbool mbqi::operator()() {
|
||||
lbool result = l_true;
|
||||
m_model = nullptr;
|
||||
ctx.save_model(m_model);
|
||||
m_instantiations.reset();
|
||||
for (sat::literal lit : m_qs.m_universal) {
|
||||
quantifier* q = to_quantifier(ctx.bool_var2expr(lit.var()));
|
||||
|
@ -73,6 +74,9 @@ namespace q {
|
|||
m_qs.add_clause(~qlit, ~lit);
|
||||
}
|
||||
m_instantiations.reset();
|
||||
if (result != l_true)
|
||||
m_model = nullptr;
|
||||
ctx.save_model(m_model);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -184,6 +184,8 @@ namespace q {
|
|||
for (euf::enode* n : ctx.get_egraph().enodes_of(f)) {
|
||||
expr* t = n->get_arg(idx)->get_expr();
|
||||
values.push_back(mdl(t));
|
||||
if (!m.is_value(values.back()))
|
||||
return expr_ref(m.mk_var(idx, srt), m);
|
||||
md->v2t.insert(values.back(), t);
|
||||
md->t2v.insert(t, values.back());
|
||||
}
|
||||
|
@ -299,6 +301,10 @@ namespace q {
|
|||
auto term = [&](unsigned j) {
|
||||
return md->v2t[md->values[j]];
|
||||
};
|
||||
|
||||
for (unsigned j = 0; j < sz; ++j)
|
||||
std::cout << mk_pp(md->values[j], m) << "\n";
|
||||
|
||||
|
||||
expr* arg = t->get_arg(i);
|
||||
|
||||
|
|
|
@ -262,6 +262,8 @@ namespace q {
|
|||
m_expanded.push_back(r);
|
||||
return true;
|
||||
}
|
||||
if (r == q)
|
||||
return false;
|
||||
q = to_quantifier(r);
|
||||
}
|
||||
if (is_forall(q))
|
||||
|
|
|
@ -188,6 +188,7 @@ namespace euf {
|
|||
enode* expr2enode(expr* e) const;
|
||||
enode* var2enode(theory_var v) const { return m_var2enode[v]; }
|
||||
expr* var2expr(theory_var v) const { return var2enode(v)->get_expr(); }
|
||||
bool is_representative(theory_var v) const { return v == get_representative(v); }
|
||||
expr* bool_var2expr(sat::bool_var v) const;
|
||||
expr_ref literal2expr(sat::literal lit) const;
|
||||
enode* bool_var2enode(sat::bool_var v) const { expr* e = bool_var2expr(v); return e ? expr2enode(e) : nullptr; }
|
||||
|
|
|
@ -28,31 +28,33 @@ namespace user_solver {
|
|||
dealloc(m_api_context);
|
||||
}
|
||||
|
||||
unsigned solver::add_expr(expr* e) {
|
||||
void solver::add_expr(expr* e) {
|
||||
force_push();
|
||||
ctx.internalize(e, false);
|
||||
euf::enode* n = expr2enode(e);
|
||||
if (is_attached_to_var(n))
|
||||
return n->get_th_var(get_id());
|
||||
return;
|
||||
euf::theory_var v = mk_var(n);
|
||||
ctx.attach_th_var(n, this, v);
|
||||
expr_ref r(m);
|
||||
sat::literal_vector explain;
|
||||
if (ctx.is_fixed(n, r, explain))
|
||||
m_prop.push_back(prop_info(explain, v, r));
|
||||
return v;
|
||||
m_prop.push_back(prop_info(explain, v, r));
|
||||
}
|
||||
|
||||
void solver::propagate_cb(
|
||||
unsigned num_fixed, unsigned const* fixed_ids,
|
||||
unsigned num_eqs, unsigned const* eq_lhs, unsigned const* eq_rhs,
|
||||
unsigned num_fixed, expr* const* fixed_ids,
|
||||
unsigned num_eqs, expr* const* eq_lhs, expr* const* eq_rhs,
|
||||
expr* conseq) {
|
||||
m_prop.push_back(prop_info(num_fixed, fixed_ids, num_eqs, eq_lhs, eq_rhs, expr_ref(conseq, m)));
|
||||
m_fixed_ids.reset();
|
||||
for (unsigned i = 0; i < num_fixed; ++i)
|
||||
m_fixed_ids.push_back(get_th_var(fixed_ids[i]));
|
||||
m_prop.push_back(prop_info(num_fixed, m_fixed_ids.data(), num_eqs, eq_lhs, eq_rhs, expr_ref(conseq, m)));
|
||||
DEBUG_CODE(validate_propagation(););
|
||||
}
|
||||
|
||||
unsigned solver::register_cb(expr* e) {
|
||||
return add_expr(e);
|
||||
void solver::register_cb(expr* e) {
|
||||
add_expr(e);
|
||||
}
|
||||
|
||||
sat::check_result solver::check() {
|
||||
|
@ -68,7 +70,7 @@ namespace user_solver {
|
|||
return;
|
||||
force_push();
|
||||
m_id2justification.setx(v, sat::literal_vector(num_lits, jlits), sat::literal_vector());
|
||||
m_fixed_eh(m_user_context, this, v, value);
|
||||
m_fixed_eh(m_user_context, this, var2expr(v), value);
|
||||
}
|
||||
|
||||
void solver::asserted(sat::literal lit) {
|
||||
|
@ -80,13 +82,13 @@ namespace user_solver {
|
|||
sat::literal_vector lits;
|
||||
lits.push_back(lit);
|
||||
m_id2justification.setx(v, lits, sat::literal_vector());
|
||||
m_fixed_eh(m_user_context, this, v, lit.sign() ? m.mk_false() : m.mk_true());
|
||||
m_fixed_eh(m_user_context, this, var2expr(v), lit.sign() ? m.mk_false() : m.mk_true());
|
||||
}
|
||||
|
||||
void solver::push_core() {
|
||||
th_euf_solver::push_core();
|
||||
m_prop_lim.push_back(m_prop.size());
|
||||
m_push_eh(m_user_context);
|
||||
m_push_eh(m_user_context, this);
|
||||
}
|
||||
|
||||
void solver::pop_core(unsigned num_scopes) {
|
||||
|
@ -94,7 +96,7 @@ namespace user_solver {
|
|||
unsigned old_sz = m_prop_lim.size() - num_scopes;
|
||||
m_prop.shrink(m_prop_lim[old_sz]);
|
||||
m_prop_lim.shrink(old_sz);
|
||||
m_pop_eh(m_user_context, num_scopes);
|
||||
m_pop_eh(m_user_context, this, num_scopes);
|
||||
}
|
||||
|
||||
void solver::propagate_consequence(prop_info const& prop) {
|
||||
|
@ -141,9 +143,9 @@ namespace user_solver {
|
|||
auto& j = justification::from_index(idx);
|
||||
auto const& prop = m_prop[j.m_propagation_index];
|
||||
for (unsigned id : prop.m_ids)
|
||||
r.append(m_id2justification[id]);
|
||||
r.append(m_id2justification[id]);
|
||||
for (auto const& p : prop.m_eqs)
|
||||
ctx.add_antecedent(var2enode(p.first), var2enode(p.second));
|
||||
ctx.add_antecedent(expr2enode(p.first), expr2enode(p.second));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -156,7 +158,7 @@ namespace user_solver {
|
|||
for (auto lit: m_id2justification[id])
|
||||
VERIFY(s().value(lit) == l_true);
|
||||
for (auto const& p : prop.m_eqs)
|
||||
VERIFY(var2enode(p.first)->get_root() == var2enode(p.second)->get_root());
|
||||
VERIFY(expr2enode(p.first)->get_root() == expr2enode(p.second)->get_root());
|
||||
}
|
||||
|
||||
std::ostream& solver::display(std::ostream& out) const {
|
||||
|
@ -171,7 +173,7 @@ namespace user_solver {
|
|||
for (unsigned id : prop.m_ids)
|
||||
out << id << ": " << m_id2justification[id];
|
||||
for (auto const& p : prop.m_eqs)
|
||||
out << "v" << p.first << " == v" << p.second << " ";
|
||||
out << "v" << mk_pp(p.first, m) << " == v" << mk_pp(p.second, m) << " ";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -224,9 +226,9 @@ namespace user_solver {
|
|||
SASSERT(!n || !n->is_attached_to(get_id()));
|
||||
if (!n)
|
||||
n = mk_enode(e, false);
|
||||
auto v = add_expr(e);
|
||||
add_expr(e);
|
||||
if (m_created_eh)
|
||||
m_created_eh(m_user_context, this, e, v);
|
||||
m_created_eh(m_user_context, this, e);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,13 +29,13 @@ namespace user_solver {
|
|||
class solver : public euf::th_euf_solver, public user_propagator::callback {
|
||||
|
||||
struct prop_info {
|
||||
unsigned_vector m_ids;
|
||||
expr_ref m_conseq;
|
||||
svector<std::pair<unsigned, unsigned>> m_eqs;
|
||||
unsigned_vector m_ids;
|
||||
expr_ref m_conseq;
|
||||
svector<std::pair<expr*, expr*>> m_eqs;
|
||||
sat::literal_vector m_lits;
|
||||
euf::theory_var m_var = euf::null_theory_var;
|
||||
euf::theory_var m_var = euf::null_theory_var;
|
||||
|
||||
prop_info(unsigned num_fixed, unsigned const* fixed_ids, unsigned num_eqs, unsigned const* eq_lhs, unsigned const* eq_rhs, expr_ref const& c):
|
||||
prop_info(unsigned num_fixed, unsigned const* fixed_ids, unsigned num_eqs, expr* const* eq_lhs, expr* const* eq_rhs, expr_ref const& c):
|
||||
m_ids(num_fixed, fixed_ids),
|
||||
m_conseq(c)
|
||||
{
|
||||
|
@ -72,6 +72,7 @@ namespace user_solver {
|
|||
vector<sat::literal_vector> m_id2justification;
|
||||
sat::literal_vector m_lits;
|
||||
euf::enode_pair_vector m_eqs;
|
||||
unsigned_vector m_fixed_ids;
|
||||
stats m_stats;
|
||||
|
||||
struct justification {
|
||||
|
@ -118,7 +119,7 @@ namespace user_solver {
|
|||
m_fresh_eh = fresh_eh;
|
||||
}
|
||||
|
||||
unsigned add_expr(expr* e);
|
||||
void add_expr(expr* e);
|
||||
|
||||
void register_final(user_propagator::final_eh_t& final_eh) { m_final_eh = final_eh; }
|
||||
void register_fixed(user_propagator::fixed_eh_t& fixed_eh) { m_fixed_eh = fixed_eh; }
|
||||
|
@ -128,8 +129,8 @@ namespace user_solver {
|
|||
|
||||
bool has_fixed() const { return (bool)m_fixed_eh; }
|
||||
|
||||
void propagate_cb(unsigned num_fixed, unsigned const* fixed_ids, unsigned num_eqs, unsigned const* lhs, unsigned const* rhs, expr* conseq) override;
|
||||
unsigned register_cb(expr* e) override;
|
||||
void propagate_cb(unsigned num_fixed, expr* const* fixed_ids, unsigned num_eqs, expr* const* lhs, expr* const* rhs, expr* conseq) override;
|
||||
void register_cb(expr* e) override;
|
||||
|
||||
void new_fixed_eh(euf::theory_var v, expr* value, unsigned num_lits, sat::literal const* jlits);
|
||||
|
||||
|
|
|
@ -405,6 +405,8 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
|||
m_result_stack.shrink(old_sz);
|
||||
}
|
||||
else {
|
||||
if (process_cached(t, root, sign))
|
||||
return;
|
||||
SASSERT(num <= m_result_stack.size());
|
||||
sat::bool_var k = add_var(false, t);
|
||||
sat::literal l(k, false);
|
||||
|
@ -454,6 +456,8 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
|||
m_result_stack.shrink(old_sz);
|
||||
}
|
||||
else {
|
||||
if (process_cached(t, root, sign))
|
||||
return;
|
||||
SASSERT(num <= m_result_stack.size());
|
||||
sat::bool_var k = add_var(false, t);
|
||||
sat::literal l(k, false);
|
||||
|
@ -507,6 +511,8 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (process_cached(n, root, sign))
|
||||
return;
|
||||
sat::bool_var k = add_var(false, n);
|
||||
sat::literal l(k, false);
|
||||
cache(n, l);
|
||||
|
@ -537,6 +543,8 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
|||
mk_root_clause(sign ? lit : ~lit);
|
||||
}
|
||||
else {
|
||||
if (process_cached(t, root, sign))
|
||||
return;
|
||||
sat::bool_var k = add_var(false, t);
|
||||
sat::literal l(k, false);
|
||||
cache(t, l);
|
||||
|
@ -567,6 +575,8 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (process_cached(t, root, sign))
|
||||
return;
|
||||
sat::bool_var k = add_var(false, t);
|
||||
sat::literal l(k, false);
|
||||
cache(t, l);
|
||||
|
@ -603,6 +613,8 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (process_cached(t, root, sign))
|
||||
return;
|
||||
sat::bool_var k = add_var(false, t);
|
||||
sat::literal l(k, false);
|
||||
if (m.is_xor(t))
|
||||
|
@ -805,6 +817,7 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
|||
}
|
||||
|
||||
sat::literal internalize(expr* n, bool redundant) override {
|
||||
bool is_not = m.is_not(n, n);
|
||||
flet<bool> _top(m_top_level, false);
|
||||
unsigned sz = m_result_stack.size();
|
||||
(void)sz;
|
||||
|
@ -820,6 +833,9 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
|||
m_map.insert(n, result.var());
|
||||
m_solver.set_external(result.var());
|
||||
}
|
||||
|
||||
if (is_not)
|
||||
result.neg();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -218,7 +218,7 @@ struct sat2goal::imp {
|
|||
}
|
||||
sat::literal lit(l.var(), false);
|
||||
m_lit2expr.set(lit.index(), aux);
|
||||
m_lit2expr.set((~lit).index(), m.mk_not(aux));
|
||||
m_lit2expr.set((~lit).index(), mk_not(m, aux));
|
||||
}
|
||||
return m_lit2expr.get(l.index());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue