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

Add more logging to polysat (#5186)

* Add polysat logging support

* Don't really need the usual log levels

* Indent log headings

* Add display method to ptr_vector

* Add some logging to solver

* Use __FUNCSIG__ on MSVC
This commit is contained in:
Jakob Rath 2021-04-15 17:35:57 +02:00 committed by GitHub
parent 7067fc16ae
commit feb31045f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 271 additions and 3 deletions

View file

@ -16,6 +16,7 @@ Author:
--*/
#include "math/polysat/solver.h"
#include "math/polysat/log.h"
namespace polysat {
@ -81,14 +82,40 @@ namespace polysat {
}
solver::~solver() {}
#if POLYSAT_LOGGING_ENABLED
void solver::log_viable(pvar v) {
if (size(v) <= 5) {
vector<rational> xs;
for (rational x = rational::zero(); x < rational::power_of_two(size(v)); x += 1) {
if (is_viable(v, x)) {
xs.push_back(x);
}
}
LOG("Viable for pvar " << v << ": " << xs);
} else {
LOG("Viable for pvar " << v << ": <range too big>");
}
}
#endif
lbool solver::check_sat() {
TRACE("polysat", tout << "check\n";);
while (m_lim.inc()) {
if (is_conflict() && at_base_level()) return l_false;
LOG_H1("Next solving loop iteration");
LOG("Free variables: " << m_free_vars);
LOG("Assignments: " << m_search);
LOG("Conflict: " << m_conflict);
IF_LOGGING({
for (pvar v = 0; v < m_viable.size(); ++v) {
log_viable(v);
}
});
if (is_conflict() && at_base_level()) { LOG_H2("UNSAT"); return l_false; }
else if (is_conflict()) resolve_conflict();
else if (can_propagate()) propagate();
else if (!can_decide()) return l_true;
else if (!can_decide()) { LOG_H2("SAT"); return l_true; }
else decide();
}
return l_undef;
@ -127,6 +154,7 @@ namespace polysat {
void solver::add_eq(pdd const& p, unsigned dep) {
p_dependency_ref d(mk_dep(dep), m_dm);
constraint* c = constraint::eq(m_level, p, d);
LOG("Adding constraint: " << *c);
m_constraints.push_back(c);
add_watch(*c);
}
@ -169,6 +197,7 @@ namespace polysat {
}
void solver::propagate(pvar v) {
LOG_H2("Propagate pvar " << v);
auto& wlist = m_watch[v];
unsigned i = 0, j = 0, sz = wlist.size();
for (; i < sz && !is_conflict(); ++i)
@ -179,6 +208,9 @@ namespace polysat {
wlist.shrink(j);
}
/**
* Return true iff the constraint should be removed from the current watch list.
*/
bool solver::propagate(pvar v, constraint& c) {
switch (c.kind()) {
case ckind_t::eq_t:
@ -193,6 +225,7 @@ namespace polysat {
}
bool solver::propagate_eq(pvar v, constraint& c) {
LOG_H3("Propagate " << m_vars[v] << " in " << c);
SASSERT(c.kind() == ckind_t::eq_t);
SASSERT(!c.vars().empty());
auto var = m_vars[v].var();
@ -210,11 +243,14 @@ namespace polysat {
}
LOG("Assignments: " << m_search);
auto p = c.p().subst_val(m_search);
LOG("Substituted: " << c.p() << " := " << p);
TRACE("polysat", tout << c.p() << " := " << p << "\n";);
if (p.is_zero())
return false;
if (p.is_never_zero()) {
LOG("Conflict (never zero under current assignment)");
// we could tag constraint to allow early substitution before
// swapping watch variable in case we can detect conflict earlier.
set_conflict(c);
@ -334,20 +370,25 @@ namespace polysat {
}
void solver::decide() {
LOG_H2("Decide");
SASSERT(can_decide());
decide(m_free_vars.next_var());
}
void solver::decide(pvar v) {
IF_LOGGING(log_viable(v));
rational val;
switch (find_viable(v, val)) {
case l_false:
LOG("Conflict: no value for pvar " << v);
set_conflict(v);
break;
case l_true:
LOG("Propagation: pvar " << v << " := " << val << " (due to unique value)");
assign_core(v, val, justification::propagation(m_level));
break;
case l_undef:
LOG("Decision: pvar " << v << " := " << val);
push_level();
assign_core(v, val, justification::decision(m_level));
break;
@ -360,6 +401,7 @@ namespace polysat {
else
++m_stats.m_num_propagations;
TRACE("polysat", tout << "v" << v << " := " << val << " " << j << "\n";);
LOG("pvar " << v << " := " << val << " by " << j);
SASSERT(is_viable(v, val));
m_value[v] = val;
m_search.push_back(std::make_pair(v, val));
@ -400,6 +442,7 @@ namespace polysat {
*
*/
void solver::resolve_conflict() {
LOG_H2("Resolve conflict");
++m_stats.m_num_conflicts;
SASSERT(!m_conflict.empty());
@ -413,6 +456,7 @@ namespace polysat {
reset_marks();
for (constraint* c : m_conflict) {
SASSERT(c);
LOG("Conflicting: " << *c);
for (auto v : c->vars())
set_mark(v);
}
@ -540,6 +584,7 @@ namespace polysat {
}
void solver::backjump(unsigned new_level) {
LOG_H3("Backjumping to level " << new_level << " from level " << m_level);
unsigned num_levels = m_level - new_level;
if (num_levels > 0)
pop_levels(num_levels);
@ -596,6 +641,7 @@ namespace polysat {
void solver::add_lemma(constraint* c) {
if (!c)
return;
LOG("Lemma: " << *c);
add_watch(*c);
m_redundant.push_back(c);
for (unsigned i = m_redundant.size() - 1; i-- > 0; ) {