mirror of
https://github.com/Z3Prover/z3
synced 2025-04-08 18:31:49 +00:00
updates
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
127bae85bd
commit
49d7fd4f9c
|
@ -1985,6 +1985,15 @@ namespace smt {
|
|||
m_watches[(~cls->get_literal(idx)).index()].remove_clause(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Remove boolean variable from watch lists.
|
||||
*/
|
||||
void context::remove_watch(bool_var v) {
|
||||
literal lit(v);
|
||||
m_watches[lit.index()].reset();
|
||||
m_watches[(~lit).index()].reset();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Update the index used for backward subsumption.
|
||||
*/
|
||||
|
|
|
@ -302,6 +302,7 @@ namespace smt {
|
|||
}
|
||||
#endif
|
||||
|
||||
clause_vector const& get_lemmas() const { return m_lemmas; }
|
||||
|
||||
literal get_literal(expr * n) const;
|
||||
|
||||
|
@ -604,8 +605,6 @@ namespace smt {
|
|||
|
||||
void remove_cls_occs(clause * cls);
|
||||
|
||||
void mark_as_deleted(clause * cls);
|
||||
|
||||
void del_clause(clause * cls);
|
||||
|
||||
void del_clauses(clause_vector & v, unsigned old_size);
|
||||
|
@ -630,6 +629,14 @@ namespace smt {
|
|||
|
||||
void reassert_units(unsigned units_to_reassert_lim);
|
||||
|
||||
public:
|
||||
// \brief exposed for PB solver to participate in GC
|
||||
|
||||
void remove_watch(bool_var v);
|
||||
|
||||
void mark_as_deleted(clause * cls);
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Internalization
|
||||
|
|
|
@ -289,31 +289,12 @@ namespace smt {
|
|||
std::swap(m_args[index], m_args[bound]);
|
||||
}
|
||||
SASSERT(th.validate_unit_propagation(*this));
|
||||
literal_vector& lits = th.get_literals();
|
||||
lits.push_back(m_lit);
|
||||
for (unsigned i = bound; i < sz; ++i) {
|
||||
SASSERT(ctx.get_assignment(lit(i)) == l_false);
|
||||
lits.push_back(~lit(i));
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < bound; ++i) {
|
||||
literal lit2 = lit(i);
|
||||
lbool value = ctx.get_assignment(lit2);
|
||||
switch (value) {
|
||||
case l_true:
|
||||
break;
|
||||
case l_false:
|
||||
TRACE("pb", tout << "conflict: " << alit << " " << lit2 << "\n";);
|
||||
set_conflict(th, lit2);
|
||||
return l_false;
|
||||
case l_undef:
|
||||
SASSERT(validate_assign(th, lits, lit2));
|
||||
th.add_assign(*this, lits, lit2);
|
||||
break;
|
||||
}
|
||||
for (unsigned i = 0; i < bound && !ctx.inconsistent(); ++i) {
|
||||
th.add_assign(*this, lit(i));
|
||||
}
|
||||
|
||||
return l_true;
|
||||
return ctx.inconsistent() ? l_false : l_true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -369,10 +350,8 @@ namespace smt {
|
|||
SASSERT(ctx.get_assignment(lit()) == l_true);
|
||||
unsigned j = 0, sz = size(), bound = k();
|
||||
if (bound == sz) {
|
||||
literal_vector& lits = th.get_literals();
|
||||
lits.push_back(lit());
|
||||
for (unsigned i = 0; i < sz && !ctx.inconsistent(); ++i) {
|
||||
th.add_assign(*this, lits, lit(i));
|
||||
th.add_assign(*this, lit(i));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -412,11 +391,8 @@ namespace smt {
|
|||
set_conflict(th, alit);
|
||||
}
|
||||
else if (j == bound) {
|
||||
literal_vector lits(sz - bound, m_args.c_ptr() + bound);
|
||||
th.negate(lits);
|
||||
lits.push_back(lit());
|
||||
for (unsigned i = 0; i < bound && !ctx.inconsistent(); ++i) {
|
||||
th.add_assign(*this, lits, lit(i));
|
||||
th.add_assign(*this, lit(i));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -457,9 +433,11 @@ namespace smt {
|
|||
theory(m.mk_family_id("pb")),
|
||||
m_params(p),
|
||||
m_simplex(m.limit()),
|
||||
m_util(m),
|
||||
pb(m),
|
||||
m_max_compiled_coeff(rational(8)),
|
||||
m_cardinality_lemma(false),
|
||||
m_restart_lim(3),
|
||||
m_restart_inc(0),
|
||||
m_antecedent_exprs(m),
|
||||
m_cardinality_exprs(m)
|
||||
{
|
||||
|
@ -485,7 +463,7 @@ namespace smt {
|
|||
SASSERT(!ctx.b_internalized(atom));
|
||||
m_stats.m_num_predicates++;
|
||||
|
||||
if (m_util.is_aux_bool(atom)) {
|
||||
if (pb.is_aux_bool(atom)) {
|
||||
bool_var abv = ctx.mk_bool_var(atom);
|
||||
ctx.set_var_theory(abv, get_id());
|
||||
std::cout << "aux bool " << ctx.get_scope_level() << " " << mk_pp(atom, get_manager()) << " " << literal(abv) << "\n";
|
||||
|
@ -496,17 +474,17 @@ namespace smt {
|
|||
return true;
|
||||
}
|
||||
|
||||
SASSERT(m_util.is_at_most_k(atom) || m_util.is_le(atom) ||
|
||||
m_util.is_ge(atom) || m_util.is_at_least_k(atom) ||
|
||||
m_util.is_eq(atom));
|
||||
SASSERT(pb.is_at_most_k(atom) || pb.is_le(atom) ||
|
||||
pb.is_ge(atom) || pb.is_at_least_k(atom) ||
|
||||
pb.is_eq(atom));
|
||||
|
||||
|
||||
unsigned num_args = atom->get_num_args();
|
||||
bool_var abv = ctx.mk_bool_var(atom);
|
||||
ctx.set_var_theory(abv, get_id());
|
||||
|
||||
ineq* c = alloc(ineq, m_mpz_mgr, literal(abv), m_util.is_eq(atom));
|
||||
c->m_args[0].m_k = m_util.get_k(atom);
|
||||
ineq* c = alloc(ineq, m_mpz_mgr, literal(abv), pb.is_eq(atom));
|
||||
c->m_args[0].m_k = pb.get_k(atom);
|
||||
numeral& k = c->m_args[0].m_k;
|
||||
arg_t& args = c->m_args[0];
|
||||
|
||||
|
@ -514,10 +492,10 @@ namespace smt {
|
|||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
expr* arg = atom->get_arg(i);
|
||||
literal l = compile_arg(arg);
|
||||
numeral c = m_util.get_coeff(atom, i);
|
||||
numeral c = pb.get_coeff(atom, i);
|
||||
args.push_back(std::make_pair(l, c));
|
||||
}
|
||||
if (m_util.is_at_most_k(atom) || m_util.is_le(atom)) {
|
||||
if (pb.is_at_most_k(atom) || pb.is_le(atom)) {
|
||||
// turn W <= k into -W >= -k
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
args[i].second = -args[i].second;
|
||||
|
@ -525,7 +503,7 @@ namespace smt {
|
|||
k = -k;
|
||||
}
|
||||
else {
|
||||
SASSERT(m_util.is_at_least_k(atom) || m_util.is_ge(atom) || m_util.is_eq(atom));
|
||||
SASSERT(pb.is_at_least_k(atom) || pb.is_ge(atom) || pb.is_eq(atom));
|
||||
}
|
||||
TRACE("pb", display(tout, *c););
|
||||
//app_ref fml1(m), fml2(m);
|
||||
|
@ -640,7 +618,6 @@ namespace smt {
|
|||
// is available.
|
||||
if (!has_bv) {
|
||||
app_ref tmp(m), fml(m);
|
||||
pb_util pb(m);
|
||||
tmp = pb.mk_fresh_bool();
|
||||
fml = m.mk_iff(tmp, arg);
|
||||
TRACE("pb", tout << "create proxy " << fml << "\n";);
|
||||
|
@ -754,23 +731,38 @@ namespace smt {
|
|||
// ----------------------------
|
||||
// cardinality constraints
|
||||
|
||||
class theory_pb::card_justification : public theory_propagation_justification {
|
||||
|
||||
class theory_pb::card_justification : public justification {
|
||||
card& m_card;
|
||||
family_id m_fid;
|
||||
public:
|
||||
card_justification(card& c, family_id fid, region & r,
|
||||
unsigned num_lits, literal const * lits, literal consequent):
|
||||
theory_propagation_justification(fid, r, num_lits, lits, consequent),
|
||||
m_card(c)
|
||||
{}
|
||||
card_justification(card& c, family_id fid)
|
||||
: justification(true), m_card(c), m_fid(fid) {}
|
||||
|
||||
card& get_card() { return m_card; }
|
||||
|
||||
virtual void get_antecedents(conflict_resolution& cr) {
|
||||
cr.mark_literal(m_card.lit());
|
||||
for (unsigned i = m_card.k(); i < m_card.size(); ++i) {
|
||||
cr.mark_literal(~m_card.lit(i));
|
||||
}
|
||||
}
|
||||
|
||||
virtual theory_id get_from_theory() const {
|
||||
return m_fid;
|
||||
}
|
||||
|
||||
virtual proof* mk_proof(smt::conflict_resolution& cr) { return 0; }
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
bool theory_pb::is_cardinality_constraint(app * atom) {
|
||||
if (m_util.is_ge(atom) && m_util.has_unit_coefficients(atom)) {
|
||||
if (pb.is_ge(atom) && pb.has_unit_coefficients(atom)) {
|
||||
return true;
|
||||
}
|
||||
if (m_util.is_at_least_k(atom)) {
|
||||
if (pb.is_at_least_k(atom)) {
|
||||
return true;
|
||||
}
|
||||
// TBD: other conditions
|
||||
|
@ -789,7 +781,7 @@ namespace smt {
|
|||
unsigned num_args = atom->get_num_args();
|
||||
bool_var abv = ctx.mk_bool_var(atom);
|
||||
ctx.set_var_theory(abv, get_id());
|
||||
unsigned bound = m_util.get_k(atom).get_unsigned();
|
||||
unsigned bound = pb.get_k(atom).get_unsigned();
|
||||
literal lit(abv);
|
||||
|
||||
if (bound == 0) {
|
||||
|
@ -801,8 +793,11 @@ namespace smt {
|
|||
ctx.mk_th_axiom(get_id(), 1, &lit);
|
||||
return true;
|
||||
}
|
||||
|
||||
// hack to differentiate constraints that come from input vs. lemmas.
|
||||
bool aux = pb.is_at_least_k(atom);
|
||||
|
||||
card* c = alloc(card, lit, bound);
|
||||
card* c = alloc(card, lit, bound, aux);
|
||||
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
expr* arg = atom->get_arg(i);
|
||||
|
@ -923,7 +918,7 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
out << " >= " << c.k() << "\n";
|
||||
if (c.num_propagations()) out << "propagations: " << c.num_propagations() << "\n";
|
||||
if (c.all_propagations()) out << "propagations: " << c.all_propagations() << "\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -942,19 +937,16 @@ namespace smt {
|
|||
SASSERT(ctx.inconsistent());
|
||||
}
|
||||
|
||||
void theory_pb::add_assign(card& c, literal_vector const& lits, literal l) {
|
||||
void theory_pb::add_assign(card& c, literal l) {
|
||||
context& ctx = get_context();
|
||||
if (ctx.get_assignment(l) == l_true) {
|
||||
return;
|
||||
}
|
||||
c.inc_propagations(*this);
|
||||
m_stats.m_num_propagations++;
|
||||
TRACE("pb", tout << "#prop: " << c.num_propagations() << " - " << lits << " " << c.lit() << " => " << l << "\n";);
|
||||
SASSERT(validate_antecedents(lits));
|
||||
TRACE("pb", tout << "#prop: " << c.num_propagations() << " - " << c.lit() << " => " << l << "\n";);
|
||||
SASSERT(validate_unit_propagation(c));
|
||||
ctx.assign(l, ctx.mk_justification(
|
||||
card_justification(
|
||||
c, get_id(), ctx.get_region(), lits.size(), lits.c_ptr(), l)));
|
||||
ctx.assign(l, ctx.mk_justification(card_justification(c, get_id())));
|
||||
}
|
||||
|
||||
void theory_pb::clear_watch(card& c) {
|
||||
|
@ -1459,6 +1451,83 @@ namespace smt {
|
|||
compile_ineq(*m_to_compile[i]);
|
||||
}
|
||||
m_to_compile.reset();
|
||||
|
||||
return;
|
||||
|
||||
if (m_restart_lim <= m_restart_inc) {
|
||||
m_restart_inc = 0;
|
||||
if (gc()) {
|
||||
m_restart_lim = 3;
|
||||
}
|
||||
else {
|
||||
m_restart_lim *= 4;
|
||||
m_restart_lim /= 3;
|
||||
}
|
||||
}
|
||||
++m_restart_inc;
|
||||
}
|
||||
|
||||
bool theory_pb::gc() {
|
||||
|
||||
context& ctx = get_context();
|
||||
|
||||
unsigned z = 0, nz = 0;
|
||||
m_occs.reset();
|
||||
for (unsigned i = 0; i < m_card_trail.size(); ++i) {
|
||||
bool_var v = m_card_trail[i];
|
||||
if (v == null_bool_var) continue;
|
||||
card* c = m_var_infos[v].m_card;
|
||||
if (c) {
|
||||
unsigned np = c->num_propagations();
|
||||
c->reset_propagations();
|
||||
literal lit = c->lit();
|
||||
if (c->is_aux() && ctx.get_assign_level(lit) > ctx.get_search_level()) {
|
||||
double activity = ctx.get_activity(v);
|
||||
// std::cout << "activity: " << ctx.get_activity(v) << " " << np << "\n";
|
||||
if (activity <= 0) {
|
||||
nz++;
|
||||
}
|
||||
else {
|
||||
z++;
|
||||
clear_watch(*c);
|
||||
m_var_infos[v].m_card = 0;
|
||||
dealloc(c);
|
||||
m_card_trail[i] = null_bool_var;
|
||||
ctx.remove_watch(v);
|
||||
// TBD: maybe v was used in a clause for propagation.
|
||||
m_occs.insert(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
clause_vector const& lemmas = ctx.get_lemmas();
|
||||
for (unsigned i = 0; i < lemmas.size(); ++i) {
|
||||
clause* cl = lemmas[i];
|
||||
if (!cl->deleted()) {
|
||||
unsigned sz = cl->get_num_literals();
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
literal lit = cl->get_literal(j);
|
||||
if (m_occs.contains(lit.var())) {
|
||||
//std::cout << "deleting clause " << lit << " " << sz << "\n";
|
||||
//ctx.mark_as_deleted(cl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "zs: " << z << " nzs: " << nz << " lemmas: " << ctx.get_lemmas().size() << " trail: " << m_card_trail.size() << "\n";
|
||||
return z*10 >= nz;
|
||||
|
||||
m_occs.reset();
|
||||
for (unsigned i = 0; i < lemmas.size(); ++i) {
|
||||
clause* cl = lemmas[i];
|
||||
unsigned sz = cl->get_num_literals();
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
unsigned idx = cl->get_literal(j).index();
|
||||
m_occs.insert(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1562,10 +1631,12 @@ namespace smt {
|
|||
while (m_card_trail.size() > sz) {
|
||||
bool_var v = m_card_trail.back();
|
||||
m_card_trail.pop_back();
|
||||
card* c = m_var_infos[v].m_card;
|
||||
clear_watch(*c);
|
||||
m_var_infos[v].m_card = 0;
|
||||
dealloc(c);
|
||||
if (v != null_bool_var) {
|
||||
card* c = m_var_infos[v].m_card;
|
||||
clear_watch(*c);
|
||||
m_var_infos[v].m_card = 0;
|
||||
dealloc(c);
|
||||
}
|
||||
}
|
||||
|
||||
m_card_lim.resize(new_lim);
|
||||
|
@ -1803,22 +1874,18 @@ namespace smt {
|
|||
m_coeff2args[coeff].push_back(v);
|
||||
}
|
||||
std::sort(m_active_coeffs.begin(), m_active_coeffs.end());
|
||||
for (unsigned i = 0; i < m_active_coeffs.size(); ++i) {
|
||||
std::cout << m_active_coeffs[i] << " ";
|
||||
}
|
||||
std::cout << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
void theory_pb::add_cardinality_lemma() {
|
||||
context& ctx = get_context();
|
||||
normalize_active_coeffs();
|
||||
SASSERT(m_seen.empty());
|
||||
int s = 0;
|
||||
int new_bound = 0;
|
||||
if (!init_arg_max()) {
|
||||
return;
|
||||
}
|
||||
// TBD: can be optimized
|
||||
while (s < m_bound) {
|
||||
int coeff;
|
||||
int arg = arg_max(coeff);
|
||||
|
@ -1826,12 +1893,8 @@ namespace smt {
|
|||
s += coeff;
|
||||
++new_bound;
|
||||
}
|
||||
int slack = m_active_coeffs.empty() ? m_bound : (std::min(m_bound, static_cast<int>(m_active_coeffs[0]) - 1));
|
||||
reset_arg_max();
|
||||
int slack = m_bound;
|
||||
for (unsigned i = 0; i < m_active_vars.size(); ++i) {
|
||||
int coeff = get_abs_coeff(m_active_vars[i]);
|
||||
slack = std::min(slack, coeff - 1);
|
||||
}
|
||||
|
||||
while (slack > 0) {
|
||||
bool found = false;
|
||||
|
@ -2007,7 +2070,6 @@ namespace smt {
|
|||
m_cardinality_exprs[i] = m.mk_not(a);
|
||||
}
|
||||
}
|
||||
pb_util pb(m);
|
||||
app_ref atl(pb.mk_at_least_k(m_cardinality_exprs.size(), m_cardinality_exprs.c_ptr(), m_bound), m);
|
||||
VERIFY(internalize_card(atl, false));
|
||||
bool_var abv = ctx.get_bool_var(atl);
|
||||
|
@ -2138,9 +2200,6 @@ namespace smt {
|
|||
else {
|
||||
card& c2 = pbj->get_card();
|
||||
process_card(c2, offset);
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < c2.size() && c2.lit(i) != conseq; ++i) {}
|
||||
// std::cout << c2.lit() << " index at " << i << " of " << c2.size();
|
||||
bound = c2.k();
|
||||
}
|
||||
|
||||
|
@ -2185,7 +2244,7 @@ namespace smt {
|
|||
slack -= get_abs_coeff(alit.var());
|
||||
|
||||
for (unsigned i = 0; 0 <= slack; ++i) {
|
||||
SASSERT(i < m_active_vars.size());
|
||||
SASSERT(i < m_active_vars.size());
|
||||
bool_var v = m_active_vars[i];
|
||||
literal lit(v, get_coeff(v) < 0);
|
||||
if (v != alit.var() && ctx.get_assignment(lit) == l_false) {
|
||||
|
@ -2196,7 +2255,7 @@ namespace smt {
|
|||
SASSERT(validate_antecedents(m_antecedents));
|
||||
ctx.assign(alit, ctx.mk_justification(theory_propagation_justification(get_id(), ctx.get_region(), m_antecedents.size(), m_antecedents.c_ptr(), alit, 0, 0)));
|
||||
|
||||
add_cardinality_lemma();
|
||||
// add_cardinality_lemma();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -198,16 +198,20 @@ namespace smt {
|
|||
literal_vector m_args;
|
||||
unsigned m_bound;
|
||||
unsigned m_num_propagations;
|
||||
unsigned m_all_propagations;
|
||||
unsigned m_compilation_threshold;
|
||||
lbool m_compiled;
|
||||
bool m_aux;
|
||||
|
||||
public:
|
||||
card(literal l, unsigned bound):
|
||||
card(literal l, unsigned bound, bool is_aux):
|
||||
m_lit(l),
|
||||
m_bound(bound),
|
||||
m_num_propagations(0),
|
||||
m_all_propagations(0),
|
||||
m_compilation_threshold(0),
|
||||
m_compiled(l_false)
|
||||
m_compiled(l_false),
|
||||
m_aux(is_aux)
|
||||
{
|
||||
SASSERT(bound > 0);
|
||||
}
|
||||
|
@ -216,6 +220,7 @@ namespace smt {
|
|||
literal lit(unsigned i) const { return m_args[i]; }
|
||||
unsigned k() const { return m_bound; }
|
||||
unsigned size() const { return m_args.size(); }
|
||||
unsigned all_propagations() const { return m_all_propagations; }
|
||||
unsigned num_propagations() const { return m_num_propagations; }
|
||||
void add_arg(literal l);
|
||||
|
||||
|
@ -228,6 +233,11 @@ namespace smt {
|
|||
app_ref to_expr(context& ctx);
|
||||
|
||||
void inc_propagations(theory_pb& th);
|
||||
|
||||
void reset_propagations() { m_all_propagations += m_num_propagations; m_num_propagations = 0; }
|
||||
|
||||
bool is_aux() const { return m_aux; }
|
||||
|
||||
private:
|
||||
|
||||
bool validate_conflict(theory_pb& th);
|
||||
|
@ -293,7 +303,7 @@ namespace smt {
|
|||
unsigned_vector m_ineqs_trail;
|
||||
unsigned_vector m_ineqs_lim;
|
||||
literal_vector m_literals; // temporary vector
|
||||
pb_util m_util;
|
||||
pb_util pb;
|
||||
stats m_stats;
|
||||
ptr_vector<ineq> m_to_compile; // inequalities to compile.
|
||||
unsigned m_conflict_frequency;
|
||||
|
@ -302,6 +312,9 @@ namespace smt {
|
|||
rational m_max_compiled_coeff;
|
||||
|
||||
bool m_cardinality_lemma;
|
||||
unsigned m_restart_lim;
|
||||
unsigned m_restart_inc;
|
||||
uint_set m_occs;
|
||||
|
||||
// internalize_atom:
|
||||
literal compile_arg(expr* arg);
|
||||
|
@ -330,7 +343,7 @@ namespace smt {
|
|||
// be handled using cardinality constraints.
|
||||
|
||||
unsigned_vector m_card_trail;
|
||||
unsigned_vector m_card_lim;
|
||||
unsigned_vector m_card_lim;
|
||||
bool is_cardinality_constraint(app * atom);
|
||||
bool internalize_card(app * atom, bool gate_ctx);
|
||||
void card2conjunction(card const& c);
|
||||
|
@ -339,9 +352,10 @@ namespace smt {
|
|||
void watch_literal(literal lit, card* c);
|
||||
void unwatch_literal(literal w, card* c);
|
||||
void add_clause(card& c, literal_vector const& lits);
|
||||
void add_assign(card& c, literal_vector const& lits, literal l);
|
||||
void add_assign(card& c, literal l);
|
||||
void remove(ptr_vector<card>& cards, card* c);
|
||||
void clear_watch(card& c);
|
||||
void clear_watch(card& c);
|
||||
bool gc();
|
||||
std::ostream& display(std::ostream& out, card const& c, bool values = false) const;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue