mirror of
https://github.com/Z3Prover/z3
synced 2025-08-01 17:03:18 +00:00
compute polysat unsat core
This commit is contained in:
parent
579275a17d
commit
1a733a3a50
3 changed files with 105 additions and 13 deletions
|
@ -412,7 +412,7 @@ namespace polysat {
|
||||||
s.inc_activity(v);
|
s.inc_activity(v);
|
||||||
|
|
||||||
m_vars.remove(v);
|
m_vars.remove(v);
|
||||||
for (auto const& c : s.m_viable.get_constraints(v))
|
for (signed_constraint const c : s.m_viable.get_constraints(v))
|
||||||
insert(c);
|
insert(c);
|
||||||
for (auto const& i : s.m_viable.units(v)) {
|
for (auto const& i : s.m_viable.units(v)) {
|
||||||
insert(s.eq(i.lo(), i.lo_val()));
|
insert(s.eq(i.lo(), i.lo_val()));
|
||||||
|
@ -500,18 +500,82 @@ namespace polysat {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void conflict::find_deps(dependency_vector& out_deps) const {
|
void conflict::find_deps(dependency_vector& out_deps) const {
|
||||||
sat::literal_vector todo;
|
sat::literal_vector todo_lits;
|
||||||
sat::literal_set done;
|
sat::literal_set done_lits;
|
||||||
|
unsigned_vector todo_vars;
|
||||||
|
uint_set done_vars;
|
||||||
indexed_uint_set deps;
|
indexed_uint_set deps;
|
||||||
|
|
||||||
LOG("conflict: " << *this);
|
LOG("Conflict: " << *this);
|
||||||
|
|
||||||
// TODO: starting at literals/variables in the conflict, chase propagations backwards and accumulate dependencies.
|
auto const enqueue_lit = [&](sat::literal lit) {
|
||||||
verbose_stream() << "WARNING: unsat_core requested but dependency tracking in polysat is TODO\n";
|
if (done_lits.contains(lit))
|
||||||
for (signed_constraint c : *this) {
|
return;
|
||||||
dependency d = s.m_bvars.dep(c.blit());
|
// verbose_stream() << "enqueue " << lit_pp(s, lit) << "\n";
|
||||||
if (!d.is_null())
|
todo_lits.push_back(lit);
|
||||||
deps.insert(d.val());
|
done_lits.insert(lit);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto const enqueue_var = [&](pvar v) {
|
||||||
|
if (done_vars.contains(v))
|
||||||
|
return;
|
||||||
|
// verbose_stream() << "enqueue v" << v << "\n";
|
||||||
|
todo_vars.push_back(v);
|
||||||
|
done_vars.insert(v);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Starting at literals/variables in the conflict, chase propagations backwards and accumulate dependencies.
|
||||||
|
for (signed_constraint c : *this)
|
||||||
|
enqueue_lit(c.blit());
|
||||||
|
for (pvar v : m_vars)
|
||||||
|
enqueue_var(v);
|
||||||
|
|
||||||
|
while (!todo_vars.empty() || !todo_lits.empty()) {
|
||||||
|
while (!todo_vars.empty()) {
|
||||||
|
pvar const v = todo_vars.back();
|
||||||
|
todo_vars.pop_back();
|
||||||
|
|
||||||
|
if (s.m_justification[v].is_decision())
|
||||||
|
continue;
|
||||||
|
SASSERT(s.m_justification[v].is_propagation());
|
||||||
|
|
||||||
|
for (signed_constraint c : s.m_viable.get_constraints(v))
|
||||||
|
enqueue_lit(c.blit());
|
||||||
|
for (auto const& i : s.m_viable.units(v)) {
|
||||||
|
enqueue_lit(s.try_eval(s.eq(i.lo(), i.lo_val())));
|
||||||
|
enqueue_lit(s.try_eval(s.eq(i.hi(), i.hi_val())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!todo_lits.empty()) {
|
||||||
|
sat::literal const lit = todo_lits.back();
|
||||||
|
todo_lits.pop_back();
|
||||||
|
|
||||||
|
dependency const d = s.m_bvars.dep(lit);
|
||||||
|
if (!d.is_null())
|
||||||
|
deps.insert(d.val());
|
||||||
|
|
||||||
|
if (s.m_bvars.is_decision(lit))
|
||||||
|
continue;
|
||||||
|
else if (s.m_bvars.is_assumption(lit))
|
||||||
|
continue;
|
||||||
|
else if (s.m_bvars.is_bool_propagation(lit)) {
|
||||||
|
for (sat::literal other : *s.m_bvars.reason(lit))
|
||||||
|
enqueue_lit(other);
|
||||||
|
}
|
||||||
|
else if (s.m_bvars.is_evaluation(lit)) {
|
||||||
|
unsigned const lvl = s.m_bvars.level(lit);
|
||||||
|
for (pvar v : s.lit2cnstr(lit).vars()) {
|
||||||
|
if (!s.is_assigned(v))
|
||||||
|
continue;
|
||||||
|
if (s.get_level(v) > lvl)
|
||||||
|
continue;
|
||||||
|
enqueue_var(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned d : deps)
|
for (unsigned d : deps)
|
||||||
|
|
|
@ -153,7 +153,7 @@ namespace polysat {
|
||||||
if (is_conflict())
|
if (is_conflict())
|
||||||
return; // no need to do anything if we already have a conflict at base level
|
return; // no need to do anything if we already have a conflict at base level
|
||||||
sat::literal lit = c.blit();
|
sat::literal lit = c.blit();
|
||||||
LOG("New constraint: " << c);
|
LOG("New constraint: " << lit_pp(*this, c));
|
||||||
switch (m_bvars.value(lit)) {
|
switch (m_bvars.value(lit)) {
|
||||||
case l_false:
|
case l_false:
|
||||||
// Input literal contradicts current boolean state (e.g., opposite literals in the input)
|
// Input literal contradicts current boolean state (e.g., opposite literals in the input)
|
||||||
|
@ -1085,6 +1085,21 @@ namespace polysat {
|
||||||
assign_eval(lit);
|
assign_eval(lit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sat::literal solver::try_eval(sat::literal lit) {
|
||||||
|
signed_constraint const c = lit2cnstr(lit);
|
||||||
|
switch (c.eval(*this)) {
|
||||||
|
case l_true:
|
||||||
|
assign_eval(lit);
|
||||||
|
break;
|
||||||
|
case l_false:
|
||||||
|
assign_eval(~lit);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return lit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activate constraint immediately
|
* Activate constraint immediately
|
||||||
* Activation and de-activation of constraints follows the scope controlled by push/pop.
|
* Activation and de-activation of constraints follows the scope controlled by push/pop.
|
||||||
|
@ -1282,13 +1297,19 @@ namespace polysat {
|
||||||
|
|
||||||
void solver::report_unsat() {
|
void solver::report_unsat() {
|
||||||
backjump(base_level());
|
backjump(base_level());
|
||||||
SASSERT(!m_conflict.empty());
|
VERIFY(!m_conflict.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::unsat_core(dependency_vector& deps) {
|
void solver::unsat_core(dependency_vector& deps) {
|
||||||
VERIFY(is_conflict());
|
VERIFY(is_conflict());
|
||||||
deps.reset();
|
deps.reset();
|
||||||
m_conflict.find_deps(deps);
|
m_conflict.find_deps(deps);
|
||||||
|
IF_VERBOSE(10,
|
||||||
|
verbose_stream() << "polysat unsat_core";
|
||||||
|
for (auto d : deps)
|
||||||
|
verbose_stream() << " " << d;
|
||||||
|
verbose_stream() << "\n";
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& solver::display(std::ostream& out) const {
|
std::ostream& solver::display(std::ostream& out) const {
|
||||||
|
@ -1335,7 +1356,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& lit_pp::display(std::ostream& out) const {
|
std::ostream& lit_pp::display(std::ostream& out) const {
|
||||||
auto c = s.lit2cnstr(lit);
|
signed_constraint const c = s.lit2cnstr(lit);
|
||||||
out << lpad(5, lit) << ": " << rpad(30, c);
|
out << lpad(5, lit) << ": " << rpad(30, c);
|
||||||
if (!c)
|
if (!c)
|
||||||
return out;
|
return out;
|
||||||
|
@ -1357,6 +1378,9 @@ namespace polysat {
|
||||||
out << " pwatched";
|
out << " pwatched";
|
||||||
if (c->is_external())
|
if (c->is_external())
|
||||||
out << " ext";
|
out << " ext";
|
||||||
|
dependency const d = s.m_bvars.dep(lit);
|
||||||
|
if (!d.is_null())
|
||||||
|
out << " dep:" << d.val();
|
||||||
out << " ]";
|
out << " ]";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,6 +307,10 @@ namespace polysat {
|
||||||
clause_ref mk_clause(std::initializer_list<signed_constraint> cs, bool is_redundant);
|
clause_ref mk_clause(std::initializer_list<signed_constraint> cs, bool is_redundant);
|
||||||
clause_ref mk_clause(unsigned n, signed_constraint const* cs, bool is_redundant);
|
clause_ref mk_clause(unsigned n, signed_constraint const* cs, bool is_redundant);
|
||||||
|
|
||||||
|
// Evaluate constraint under the current assignment.
|
||||||
|
sat::literal try_eval(sat::literal lit);
|
||||||
|
sat::literal try_eval(signed_constraint c) { return try_eval(c.blit()); }
|
||||||
|
|
||||||
signed_constraint lit2cnstr(sat::literal lit) const { return m_constraints.lookup(lit); }
|
signed_constraint lit2cnstr(sat::literal lit) const { return m_constraints.lookup(lit); }
|
||||||
|
|
||||||
bool inc() { return m_lim.inc(); }
|
bool inc() { return m_lim.inc(); }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue