3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 00:55:31 +00:00

Merge resolve_bailout into resolve_conflict

This commit is contained in:
Jakob Rath 2021-09-06 16:44:47 +02:00
parent 39d42913cf
commit ec1e6725de
3 changed files with 27 additions and 77 deletions

View file

@ -54,7 +54,7 @@ namespace polysat {
pvar conflict_var() const { return m_conflict_var; }
bool is_bailout() const { return m_bailout; }
void set_bailout() { m_bailout = true; }
void set_bailout() { SASSERT(!is_bailout()); m_bailout = true; }
bool empty() const {
return m_constraints.empty() && !m_needs_model && m_conflict_var == null_var;

View file

@ -450,11 +450,7 @@ namespace polysat {
if (m_conflict.conflict_var() != null_var) {
// This case corresponds to a propagation of conflict_var, except it's not explicitly on the stack.
if (!resolve_value(m_conflict.conflict_var())) {
m_conflict.set_bailout();
resolve_bailout(m_search.size() - 1);
return;
}
resolve_value(m_conflict.conflict_var());
reset_marks();
set_marks(m_conflict);
}
@ -477,11 +473,7 @@ namespace polysat {
return;
}
SASSERT(j.is_propagation());
if (!resolve_value(v)) {
m_conflict.set_bailout();
resolve_bailout(i);
return;
}
resolve_value(v);
reset_marks();
set_marks(m_conflict);
}
@ -509,7 +501,7 @@ namespace polysat {
}
/** Conflict resolution case where propagation 'v := ...' is on top of the stack */
bool solver::resolve_value(pvar v) {
void solver::resolve_value(pvar v) {
// SASSERT(m_justification[v].is_propagation()); // doesn't hold if we enter because of conflict_var
// Conceptually:
// - Value Resolution
@ -518,6 +510,12 @@ namespace polysat {
// m_conflict.set_var(v);
if (m_conflict.is_bailout()) {
for (auto c : m_cjust[v])
m_conflict.insert(c);
return;
}
// Value Resolution
for (auto c : m_cjust[v])
m_conflict.insert(c);
@ -532,12 +530,14 @@ namespace polysat {
// it might be better to just have more general "core inferences" that may combine elimination/saturation steps that fit together...
// or even keep the whole "value resolution + VE/Saturation" as a single step. we might want to know which constraints come from the current cjusts?
if (m_conflict.try_eliminate(v))
return true;
return;
if (!m_conflict.try_saturate(v))
return false;
break;
}
return false;
// Failed to resolve => bail out
++m_stats.m_num_bailouts;
m_conflict.set_bailout();
}
/** Conflict resolution case where boolean literal 'lit' is on top of the stack */
@ -545,70 +545,17 @@ namespace polysat {
LOG_H3("resolve_bool: " << lit);
SASSERT(m_bvars.is_propagation(lit.var()));
if (m_conflict.is_bailout()) {
NOT_IMPLEMENTED_YET();
// clause* other = m_bvars.reason(var);
// set_marks(*other);
// m_conflict.push_back(other);
}
clause* other = m_bvars.reason(lit.var());
m_conflict.resolve(m_constraints, lit.var(), *other);
}
void solver::resolve_bailout(unsigned i) {
// TODO: add bailout bit to conflict state, then merge this function into resolve_conflict...; check the bailout bit in revert_decision and in resolve_value.
++m_stats.m_num_bailouts;
// TODO: conflict resolution failed or was aborted. what to do with the current conflict core?
// (we could still use it as lemma, but it probably doesn't help much)
// or use a fallback lemma which just contains v/=val for each decision variable v up to i
// (goal is to have strong enough explanation to avoid this function as much as possible)
do {
auto const& item = m_search[i];
if (item.is_assignment()) {
// Backtrack over variable assignment
auto v = item.var();
LOG_H2("Working on pvar " << v);
if (!is_marked(v))
continue;
justification& j = m_justification[v];
if (j.level() <= base_level())
break;
if (j.is_decision()) {
revert_decision(v);
return;
}
// retrieve constraint used for propagation
// add variables to COI
SASSERT(j.is_propagation());
for (auto c : m_cjust[v]) {
for (auto w : c->vars())
set_mark(w);
m_bvars.set_mark(c->bvar());
m_conflict.insert(c);
}
}
else {
// Backtrack over boolean literal
SASSERT(item.is_boolean());
sat::literal lit = item.lit();
LOG_H2("Working on boolean literal " << lit);
sat::bool_var var = lit.var();
SASSERT(m_bvars.is_assigned(var));
if (!m_bvars.is_marked(var))
continue;
if (m_bvars.level(var) <= base_level())
break;
if (m_bvars.is_decision(var)) {
NOT_IMPLEMENTED_YET();
// revert_bool_decision(lit);
return;
}
SASSERT(m_bvars.is_propagation(var));
NOT_IMPLEMENTED_YET();
// clause* other = m_bvars.reason(var);
// set_marks(*other);
// m_conflict.push_back(other);
}
}
while (i-- > 0);
// add_lemma(lemma); // TODO: this lemma is stored but otherwise "lost" because it will not be activated / not added to any watch data structures
report_unsat();
}
void solver::report_unsat() {
backjump(base_level());
SASSERT(!m_conflict.empty());
@ -743,6 +690,10 @@ namespace polysat {
LOG_H3("Reverting boolean decision: " << lit);
SASSERT(m_bvars.is_decision(var));
if (m_conflict.is_bailout()) {
NOT_IMPLEMENTED_YET();
}
// TODO:
// Current situation: we have a decision for boolean literal L on top of the stack, and a conflict core.
//

View file

@ -212,9 +212,8 @@ namespace polysat {
unsigned base_level() const;
void resolve_conflict();
bool resolve_value(pvar v);
void resolve_value(pvar v);
void resolve_bool(sat::literal lit);
void resolve_bailout(unsigned i);
void revert_decision(pvar v);
void revert_bool_decision(sat::literal lit);