3
0
Fork 0
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:
Nikolaj Bjorner 2022-04-16 18:30:03 +02:00
commit 3533bf486f
223 changed files with 7175 additions and 2167 deletions

View file

@ -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();
}

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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() {

View file

@ -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;

View file

@ -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 {

View file

@ -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) {

View file

@ -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();

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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))

View file

@ -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; }

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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());
}