mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 08:35:31 +00:00
prepare for new viable
This commit is contained in:
parent
b0bf03457c
commit
d86570ce75
8 changed files with 99 additions and 13 deletions
|
@ -81,7 +81,7 @@ namespace polysat {
|
|||
}
|
||||
else {
|
||||
SASSERT(c.is_currently_false(s));
|
||||
// TBD: fails with test_subst SASSERT(c.bvalue(s) == l_true);
|
||||
// TBD: fails with test_subst SASSERT(c.bvalue(s) == l_true);
|
||||
c->set_var_dependent();
|
||||
insert(c);
|
||||
}
|
||||
|
@ -100,10 +100,12 @@ namespace polysat {
|
|||
LOG("Conflict: v" << v);
|
||||
SASSERT(empty());
|
||||
m_conflict_var = v;
|
||||
#if !NEW_VIABLE
|
||||
for (auto c : s.m_cjust[v]) {
|
||||
c->set_var_dependent(); // ??
|
||||
insert(c);
|
||||
}
|
||||
#endif
|
||||
SASSERT(!empty());
|
||||
}
|
||||
|
||||
|
@ -286,7 +288,7 @@ namespace polysat {
|
|||
}
|
||||
|
||||
|
||||
bool conflict::resolve_value(pvar v, vector<signed_constraint> const& cjust_v) {
|
||||
bool conflict::resolve_value(pvar v) {
|
||||
// NOTE:
|
||||
// In the "standard" case where "v = val" is on the stack:
|
||||
// - cjust_v contains true constraints
|
||||
|
@ -298,13 +300,23 @@ namespace polysat {
|
|||
return false;
|
||||
}
|
||||
|
||||
#if NEW_VIABLE
|
||||
if (conflict_var() == v && s.m_viable.resolve(v, *this))
|
||||
return true;
|
||||
#else
|
||||
if (conflict_var() == v && s.m_forbidden_intervals.perform(v, cjust_v, *this))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
m_vars.remove(v);
|
||||
|
||||
#if NEW_VIABLE
|
||||
for (auto const& c : s.m_viable.get_constraints(v))
|
||||
insert(c);
|
||||
#else
|
||||
for (auto c : cjust_v)
|
||||
insert(c);
|
||||
#endif
|
||||
|
||||
for (auto* engine : ex_engines)
|
||||
if (engine->try_explain(v, *this))
|
||||
|
|
|
@ -103,7 +103,7 @@ namespace polysat {
|
|||
/** Perform value resolution by applying various inference rules.
|
||||
* Returns true if it was possible to eliminate the variable 'v'.
|
||||
*/
|
||||
bool resolve_value(pvar v, vector<signed_constraint> const& cjust_v);
|
||||
bool resolve_value(pvar v);
|
||||
|
||||
/** Convert the core into a lemma to be learned. */
|
||||
clause_builder build_lemma();
|
||||
|
|
|
@ -180,10 +180,17 @@ namespace polysat {
|
|||
if (x_max * y_max > pddm.max_value())
|
||||
push_omega_bisect(x, x_max, y, y_max);
|
||||
else {
|
||||
#if NEW_VIABLE
|
||||
for (auto const& c : s.m_viable.get_constraints(y.var()))
|
||||
m_new_constraints.insert(c);
|
||||
for (auto const& c : s.m_viable.get_constraints(x.var()))
|
||||
m_new_constraints.insert(c);
|
||||
#else
|
||||
for (auto c : s.m_cjust[y.var()])
|
||||
m_new_constraints.insert(c);
|
||||
for (auto c : s.m_cjust[x.var()])
|
||||
m_new_constraints.insert(c);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,9 @@ namespace polysat {
|
|||
m_value.push_back(rational::zero());
|
||||
m_justification.push_back(justification::unassigned());
|
||||
m_viable.push(sz);
|
||||
#if !NEW_VIABLE
|
||||
m_cjust.push_back({});
|
||||
#endif
|
||||
m_pwatch.push_back({});
|
||||
m_activity.push_back(0);
|
||||
m_vars.push_back(sz2pdd(sz).mk_var(v));
|
||||
|
@ -116,7 +118,9 @@ namespace polysat {
|
|||
// TODO also remove v from all learned constraints.
|
||||
pvar v = m_value.size() - 1;
|
||||
m_viable.pop();
|
||||
#if !NEW_VIABLE
|
||||
m_cjust.pop_back();
|
||||
#endif
|
||||
m_value.pop_back();
|
||||
m_justification.pop_back();
|
||||
m_pwatch.pop_back();
|
||||
|
@ -342,10 +346,12 @@ namespace polysat {
|
|||
break;
|
||||
}
|
||||
case trail_instr_t::just_i: {
|
||||
#if !NEW_VIABLE
|
||||
auto v = m_cjust_trail.back();
|
||||
LOG_V("Undo just_i");
|
||||
m_cjust[v].pop_back();
|
||||
m_cjust_trail.pop_back();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -474,8 +480,12 @@ namespace polysat {
|
|||
LOG_H2("Resolve conflict");
|
||||
LOG("\n" << *this);
|
||||
LOG("search state: " << m_search);
|
||||
#if NEW_VIABLE
|
||||
m_viable.log();
|
||||
#else
|
||||
for (pvar v = 0; v < m_cjust.size(); ++v)
|
||||
LOG("cjust[v" << v << "]: " << m_cjust[v]);
|
||||
#endif
|
||||
++m_stats.m_num_conflicts;
|
||||
|
||||
SASSERT(is_conflict());
|
||||
|
@ -527,7 +537,7 @@ namespace polysat {
|
|||
|
||||
/** Conflict resolution case where propagation 'v := ...' is on top of the stack */
|
||||
bool solver::resolve_value(pvar v) {
|
||||
return m_conflict.resolve_value(v, m_cjust[v]);
|
||||
return m_conflict.resolve_value(v);
|
||||
}
|
||||
|
||||
/** Conflict resolution case where boolean literal 'lit' is on top of the stack
|
||||
|
@ -762,6 +772,7 @@ namespace polysat {
|
|||
void solver::narrow(pvar v) {
|
||||
if (is_conflict())
|
||||
return;
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Add lemma to storage
|
||||
|
@ -793,7 +804,7 @@ namespace polysat {
|
|||
unsigned base_level = m_base_levels[m_base_levels.size() - num_scopes];
|
||||
LOG("Pop " << num_scopes << " user scopes; lowest popped level = " << base_level << "; current level = " << m_level);
|
||||
pop_levels(m_level - base_level + 1);
|
||||
m_conflict.reset(); // TODO: maybe keep conflict if level of all constraints is lower than base_level?
|
||||
m_conflict.reset();
|
||||
}
|
||||
|
||||
bool solver::at_base_level() const {
|
||||
|
@ -817,9 +828,11 @@ namespace polysat {
|
|||
if (item.is_assignment()) {
|
||||
pvar v = item.var();
|
||||
auto const& j = m_justification[v];
|
||||
out << "\t" << assignment_pp(*this, v, get_value(v)) << " @" << j.level();
|
||||
out << "\t" << assignment_pp(*this, v, get_value(v)) << " @" << j.level();
|
||||
#if !NEW_VIABLE
|
||||
if (j.is_propagation())
|
||||
out << " " << m_cjust[v];
|
||||
#endif
|
||||
out << "\n";
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -32,8 +32,12 @@ Author:
|
|||
#include "math/polysat/forbidden_intervals.h"
|
||||
#include "math/polysat/trail.h"
|
||||
#include "math/polysat/viable.h"
|
||||
#include "math/polysat/viable2.h"
|
||||
#include "math/polysat/log.h"
|
||||
|
||||
|
||||
#define NEW_VIABLE 0
|
||||
|
||||
namespace polysat {
|
||||
|
||||
class solver {
|
||||
|
@ -71,7 +75,11 @@ namespace polysat {
|
|||
|
||||
reslimit& m_lim;
|
||||
params_ref m_params;
|
||||
#if NEW_VIABLE
|
||||
viable2 m_viable;
|
||||
#else
|
||||
viable m_viable; // viable sets per variable
|
||||
#endif
|
||||
scoped_ptr_vector<dd::pdd_manager> m_pdd;
|
||||
linear_solver m_linear_solver;
|
||||
conflict m_conflict;
|
||||
|
@ -92,7 +100,9 @@ namespace polysat {
|
|||
// Per variable information
|
||||
vector<rational> m_value; // assigned value
|
||||
vector<justification> m_justification; // justification for variable assignment
|
||||
#if !NEW_VIABLE
|
||||
vector<signed_constraints> m_cjust; // constraints justifying variable range.
|
||||
#endif
|
||||
vector<signed_constraints> m_pwatch; // watch list datastructure into constraints.
|
||||
|
||||
unsigned_vector m_activity;
|
||||
|
@ -121,6 +131,7 @@ namespace polysat {
|
|||
m_qhead_trail.pop_back();
|
||||
}
|
||||
|
||||
#if !NEW_VIABLE
|
||||
void push_cjust(pvar v, signed_constraint c) {
|
||||
if (m_cjust[v].contains(c)) // TODO: better check (flag on constraint?)
|
||||
return;
|
||||
|
@ -130,6 +141,7 @@ namespace polysat {
|
|||
m_trail.push_back(trail_instr_t::just_i);
|
||||
m_cjust_trail.push_back(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned size(pvar v) const { return m_size[v]; }
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ namespace polysat {
|
|||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if NEW_VIABLE
|
||||
// setup with viable2:
|
||||
// we no longer need cjust
|
||||
pvar v = null_var;
|
||||
|
@ -139,9 +139,9 @@ namespace polysat {
|
|||
v = q.var();
|
||||
if (v != null_var) {
|
||||
signed_constraint sc(this, is_positive);
|
||||
s.m_viable2.intersect(v, sc);
|
||||
s.m_viable.intersect(v, sc);
|
||||
rational val;
|
||||
switch (s.m_viable2.find_viable(v, val)) {
|
||||
switch (s.m_viable.find_viable(v, val)) {
|
||||
case dd::find_t::singleton:
|
||||
s.propagate(v, val, sc);
|
||||
break;
|
||||
|
|
|
@ -246,12 +246,13 @@ namespace polysat {
|
|||
return dd::find_t::multiple;
|
||||
}
|
||||
|
||||
void viable2::get_core(pvar v, conflict& core) {
|
||||
core.reset();
|
||||
bool viable2::resolve(pvar v, conflict& core) {
|
||||
if (has_viable(v))
|
||||
return false;
|
||||
auto* e = m_viable[v];
|
||||
entry* first = e;
|
||||
SASSERT(e);
|
||||
SASSERT(!has_viable(v));
|
||||
core.reset();
|
||||
do {
|
||||
// Build constraint: upper bound of each interval is not contained in the next interval,
|
||||
// using the equivalence: t \in [l;h[ <=> t-l < h-l
|
||||
|
@ -280,6 +281,7 @@ namespace polysat {
|
|||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void viable2::log(pvar v) {
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace polysat {
|
|||
* Retrieve the unsat core for v.
|
||||
* \pre there are no viable values for v
|
||||
*/
|
||||
void get_core(pvar v, conflict& core);
|
||||
bool resolve(pvar v, conflict& core);
|
||||
|
||||
/** Log all viable values for the given variable.
|
||||
* (Inefficient, but useful for debugging small instances.)
|
||||
|
@ -108,6 +108,46 @@ namespace polysat {
|
|||
void log();
|
||||
|
||||
std::ostream& display(std::ostream& out) const;
|
||||
|
||||
class iterator {
|
||||
entry* curr = nullptr;
|
||||
bool visited = false;
|
||||
public:
|
||||
iterator(entry* curr, bool visited) :
|
||||
curr(curr), visited(visited || !curr) {}
|
||||
|
||||
iterator& operator++() {
|
||||
visited = true;
|
||||
curr = curr->next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
signed_constraint& operator*() {
|
||||
return curr->src;
|
||||
}
|
||||
|
||||
bool operator==(iterator const& other) const {
|
||||
return visited == other.visited && curr == other.curr;
|
||||
}
|
||||
|
||||
bool operator!=(iterator const& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
class constraints {
|
||||
viable2& viable;
|
||||
pvar var;
|
||||
public:
|
||||
constraints(viable2& viable, pvar var) : viable(viable), var(var) {}
|
||||
iterator begin() const { return iterator(viable.m_viable[var], false); }
|
||||
iterator end() const { return iterator(viable.m_viable[var], true); }
|
||||
};
|
||||
|
||||
constraints get_constraints(pvar v) {
|
||||
return constraints(*this, v);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, viable2 const& v) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue