3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 14:13:23 +00:00

resurrect Booelan decisions to deal with quot-rem and similar axioms

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2022-01-27 14:26:41 -08:00
parent be790b8892
commit ff4b471f93
4 changed files with 30 additions and 21 deletions

View file

@ -40,7 +40,6 @@ namespace polysat {
SASSERT_EQ(m_clause[var], nullptr); SASSERT_EQ(m_clause[var], nullptr);
SASSERT_EQ(m_deps[var], null_dependency); SASSERT_EQ(m_deps[var], null_dependency);
} }
m_free_vars.mk_var_eh(var);
return var; return var;
} }
@ -72,6 +71,12 @@ namespace polysat {
SASSERT(is_decision(lit)); SASSERT(is_decision(lit));
} }
void bool_var_manager::decide(sat::literal lit, unsigned lvl) {
LOG("Decide literal " << lit << " @ " << lvl);
assign(kind_t::decision, lit, lvl, nullptr);
SASSERT(is_decision(lit));
}
void bool_var_manager::eval(sat::literal lit, unsigned lvl) { void bool_var_manager::eval(sat::literal lit, unsigned lvl) {
LOG("Eval literal " << lit << " @ " << lvl); LOG("Eval literal " << lit << " @ " << lvl);
assign(kind_t::propagation, lit, lvl, nullptr); assign(kind_t::propagation, lit, lvl, nullptr);

View file

@ -74,6 +74,7 @@ namespace polysat {
unsigned_vector& activity() { return m_activity; } unsigned_vector& activity() { return m_activity; }
bool can_decide() const { return !m_free_vars.empty(); } bool can_decide() const { return !m_free_vars.empty(); }
sat::bool_var next_var() { return m_free_vars.next_var(); } sat::bool_var next_var() { return m_free_vars.next_var(); }
void track_var(sat::literal lit) { m_free_vars.mk_var_eh(lit.var()); }
// TODO connect activity updates with solver // TODO connect activity updates with solver
void inc_activity(sat::literal lit) { m_activity[lit.var()]++; } void inc_activity(sat::literal lit) { m_activity[lit.var()]++; }
@ -82,6 +83,8 @@ namespace polysat {
/// Set the given literal to true /// Set the given literal to true
void propagate(sat::literal lit, unsigned lvl, clause& reason); void propagate(sat::literal lit, unsigned lvl, clause& reason);
void decide(sat::literal lit, unsigned lvl, clause& lemma); void decide(sat::literal lit, unsigned lvl, clause& lemma);
void decide(sat::literal lit, unsigned lvl);
void eval(sat::literal lit, unsigned lvl); void eval(sat::literal lit, unsigned lvl);
void asserted(sat::literal lit, unsigned lvl, dependency dep); void asserted(sat::literal lit, unsigned lvl, dependency dep);
void unassign(sat::literal lit); void unassign(sat::literal lit);

View file

@ -150,20 +150,13 @@ namespace polysat {
add_eq(b * q + r - a); add_eq(b * q + r - a);
add_noovfl(b, q); add_noovfl(b, q);
add_ule(r, b*q+r); add_ule(r, b*q+r);
auto c1 = eq(b);
auto c2 = ult(r, b);
auto c3 = diseq(b);
auto c4 = eq(q + 1);
add_clause(c1, c2, false);
add_clause(c3, c4, false);
// BUG: auto c_eq = eq(b);
// need to watch these constraints. add_clause(c_eq, ult(r, b), false);
// ... but activation discipline seems to add_clause(~c_eq, eq(q + 1), false);
// work only for lemmas. Literals are watched only when assigned true.
// The literals are de-activated // force decisions on whether b == 0
// after propagation m_bvars.track_var(c_eq.blit());
// Should these clauses then be added as lemmas that force a branch?
return std::tuple<pdd, pdd>(q, r); return std::tuple<pdd, pdd>(q, r);
} }
@ -449,7 +442,10 @@ namespace polysat {
void solver::decide() { void solver::decide() {
LOG_H2("Decide"); LOG_H2("Decide");
SASSERT(can_decide()); SASSERT(can_decide());
pdecide(m_free_pvars.next_var()); if (!m_free_pvars.empty())
pdecide(m_free_pvars.next_var());
else
bdecide(m_bvars.next_var());
} }
void solver::pdecide(pvar v) { void solver::pdecide(pvar v) {
@ -472,9 +468,16 @@ namespace polysat {
push_level(); push_level();
assign_core(v, val, justification::decision(m_level)); assign_core(v, val, justification::decision(m_level));
break; break;
} }
} }
void solver::bdecide(sat::bool_var b) {
sat::literal lit(b);
m_bvars.decide(lit, m_level);
m_trail.push_back(trail_instr_t::assign_bool_i);
m_search.push_boolean(lit);
}
void solver::assign_core(pvar v, rational const& val, justification const& j) { void solver::assign_core(pvar v, rational const& val, justification const& j) {
if (j.is_decision()) if (j.is_decision())
++m_stats.m_num_decisions; ++m_stats.m_num_decisions;
@ -766,16 +769,14 @@ namespace polysat {
// The lemma where 'lit' comes from. // The lemma where 'lit' comes from.
// Currently, boolean decisions always come from guessing a literal of a learned non-unit lemma. // Currently, boolean decisions always come from guessing a literal of a learned non-unit lemma.
clause* lemma = m_bvars.lemma(var); // need to grab this while 'lit' is still assigned clause* lemma = m_bvars.lemma(var); // need to grab this while 'lit' is still assigned
// We only revert decisions that come from lemmas, so lemma must not be NULL here.
// (Externally asserted literals are at a base level, so we would return UNSAT instead of reverting.)
SASSERT(lemma);
backjump(m_bvars.level(var) - 1); backjump(m_bvars.level(var) - 1);
// reason should force ~lit after propagation // reason should force ~lit after propagation
add_clause(*reason); add_clause(*reason);
enqueue_decision_on_lemma(*lemma); if (lemma)
enqueue_decision_on_lemma(*lemma);
} }
unsigned solver::level(sat::literal lit0, clause const& cl) { unsigned solver::level(sat::literal lit0, clause const& cl) {

View file

@ -185,7 +185,7 @@ namespace polysat {
void set_conflict(clause& cl) { m_conflict.set(cl); } void set_conflict(clause& cl) { m_conflict.set(cl); }
void set_conflict(pvar v) { m_conflict.set(v); } void set_conflict(pvar v) { m_conflict.set(v); }
bool can_decide() const { return !m_free_pvars.empty(); } bool can_decide() const { return !m_free_pvars.empty() || m_bvars.can_decide(); }
void decide(); void decide();
void pdecide(pvar v); void pdecide(pvar v);
void bdecide(sat::bool_var b); void bdecide(sat::bool_var b);