mirror of
https://github.com/Z3Prover/z3
synced 2025-04-27 10:55:50 +00:00
Begin reorganizing resolve_value
This commit is contained in:
parent
b4e14c31d0
commit
7d58296ad2
6 changed files with 113 additions and 25 deletions
|
@ -165,6 +165,30 @@ namespace polysat {
|
||||||
return clause::from_literals(lvl, std::move(dep), std::move(literals));
|
return clause::from_literals(lvl, std::move(dep), std::move(literals));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool conflict_core::resolve_value(pvar v, vector<signed_constraint> const& cjust_v) {
|
||||||
|
// TODO: maybe don't do this automatically, because cjust-constraints are true and core constraints are false.
|
||||||
|
// issue: what if viable(v) is empty? then we only have cjust constraints and none of them is evaluable (at least not immediately because no value is set for this variable.)
|
||||||
|
// => think about what we want to do in this case (choose a value and evaluate? try all possible superpositions without caring about the value of the premises?)
|
||||||
|
// the last value_resolution method can then be the one that adds the cjusts and calls saturation and more general VE.
|
||||||
|
|
||||||
|
// No value resolution method was successful => fall back to saturation and variable elimination
|
||||||
|
for (auto c : cjust_v)
|
||||||
|
insert(c);
|
||||||
|
|
||||||
|
// Variable elimination
|
||||||
|
while (true) { // TODO: limit?
|
||||||
|
// TODO: maybe we shouldn't try to split up VE/Saturation in the implementation.
|
||||||
|
// 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?
|
||||||
|
// TODO: as a last resort, substitute v by m_value[v]?
|
||||||
|
if (!try_saturate(v))
|
||||||
|
break;
|
||||||
|
if (try_eliminate(v))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool conflict_core::try_eliminate(pvar v) {
|
bool conflict_core::try_eliminate(pvar v) {
|
||||||
// TODO: could be tracked incrementally when constraints are added/removed
|
// TODO: could be tracked incrementally when constraints are added/removed
|
||||||
vector<signed_constraint> v_constraints;
|
vector<signed_constraint> v_constraints;
|
||||||
|
|
|
@ -82,6 +82,11 @@ namespace polysat {
|
||||||
*/
|
*/
|
||||||
void resolve(constraint_manager const& m, sat::bool_var var, clause const& cl);
|
void resolve(constraint_manager const& m, sat::bool_var var, clause const& cl);
|
||||||
|
|
||||||
|
/** 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);
|
||||||
|
|
||||||
/** Convert the core into a lemma to be learned. */
|
/** Convert the core into a lemma to be learned. */
|
||||||
clause_ref build_lemma();
|
clause_ref build_lemma();
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,60 @@ Author:
|
||||||
|
|
||||||
namespace polysat {
|
namespace polysat {
|
||||||
|
|
||||||
|
constraint_manager& explainer::cm() { return s().m_constraints; }
|
||||||
|
|
||||||
|
bool ex_polynomial_superposition::try_explain(pvar v, vector<signed_constraint> const& cjust_v, conflict_core& core) {
|
||||||
|
// TODO: check superposition into disequality again (see notes)
|
||||||
|
|
||||||
|
// TODO: use indexing/marking for this instead of allocating a temporary vector
|
||||||
|
// TODO: core saturation premises are from \Gamma (i.e., has_bvar)... but here we further restrict to the core; might need to revise
|
||||||
|
// -- especially: should take into account results from previous saturations (they will be in \Gamma, but only if we use the constraint or one of its descendants for the lemma)
|
||||||
|
// actually: we want to take one from the current cjust (currently true) and one from the conflict (currently false)
|
||||||
|
vector<signed_constraint> candidates;
|
||||||
|
for (auto c : core)
|
||||||
|
if (c->has_bvar() && c.is_positive() && c->is_eq() && c->contains_var(v))
|
||||||
|
candidates.push_back(c);
|
||||||
|
|
||||||
|
// TODO: c1 should a currently true constraint, while c2 should take a currently false constraint.
|
||||||
|
// remove candidates vector (premature optimization)
|
||||||
|
// we may want to apply this multiple times (a single resolve might not eliminate the variable).
|
||||||
|
|
||||||
|
LOG_H3("Trying polynomial superposition...");
|
||||||
|
for (auto it1 = candidates.begin(); it1 != candidates.end(); ++it1) {
|
||||||
|
for (auto it2 = it1 + 1; it2 != candidates.end(); ++it2) {
|
||||||
|
signed_constraint c1 = *it1;
|
||||||
|
signed_constraint c2 = *it2;
|
||||||
|
SASSERT(c1 != c2);
|
||||||
|
LOG("c1: " << c1);
|
||||||
|
LOG("c2: " << c2);
|
||||||
|
|
||||||
|
pdd a = c1->to_eq().p();
|
||||||
|
pdd b = c2->to_eq().p();
|
||||||
|
pdd r = a;
|
||||||
|
if (!a.resolve(v, b, r) && !b.resolve(v, a, r))
|
||||||
|
continue;
|
||||||
|
unsigned const lvl = std::max(c1->level(), c2->level());
|
||||||
|
signed_constraint c = cm().eq(lvl, r);
|
||||||
|
LOG("resolved: " << c << " currently false? " << c.is_currently_false(s()));
|
||||||
|
if (!c.is_currently_false(s()))
|
||||||
|
continue;
|
||||||
|
vector<signed_constraint> premises;
|
||||||
|
premises.push_back(c1);
|
||||||
|
premises.push_back(c2);
|
||||||
|
core.insert(c, std::move(premises));
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// clause_builder clause(m_solver);
|
||||||
|
// clause.push_literal(~c1->blit());
|
||||||
|
// clause.push_literal(~c2->blit());
|
||||||
|
// clause.push_new_constraint(m_solver.m_constraints.eq(lvl, r));
|
||||||
|
// return clause.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// LOG_H3("Attempting to explain conflict for v" << v);
|
// LOG_H3("Attempting to explain conflict for v" << v);
|
||||||
// m_var = v;
|
// m_var = v;
|
||||||
// m_cjust_v = cjust;
|
// m_cjust_v = cjust;
|
||||||
|
|
|
@ -19,6 +19,30 @@ Author:
|
||||||
|
|
||||||
namespace polysat {
|
namespace polysat {
|
||||||
|
|
||||||
|
class solver;
|
||||||
|
class constraint_manager;
|
||||||
|
|
||||||
|
class explainer {
|
||||||
|
friend class conflict_core;
|
||||||
|
solver* m_solver = nullptr;
|
||||||
|
void set_solver(solver& s) { m_solver = &s; }
|
||||||
|
protected:
|
||||||
|
solver& s() { return *m_solver; }
|
||||||
|
constraint_manager& cm();
|
||||||
|
public:
|
||||||
|
virtual ~explainer() {}
|
||||||
|
virtual bool try_explain(pvar v, vector<signed_constraint> const& cjust_v, conflict_core& core) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ex_polynomial_superposition : public explainer {
|
||||||
|
bool try_explain(pvar v, vector<signed_constraint> const& cjust_v, conflict_core& core) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
class conflict_explainer {
|
class conflict_explainer {
|
||||||
|
@ -45,7 +69,7 @@ namespace polysat {
|
||||||
bool saturate();
|
bool saturate();
|
||||||
|
|
||||||
/** resolve conflict state against assignment to v */
|
/** resolve conflict state against assignment to v */
|
||||||
void resolve(pvar v, ptr_vector<constraint> const& cjust_v); // TODO: try variable elimination of 'v', if not possible, core saturation and core reduction. (actually reduction could be one specific VE method).
|
void resolve(pvar v, ptr_vector<constraint> const& cjust_v);
|
||||||
void resolve(sat::literal lit);
|
void resolve(sat::literal lit);
|
||||||
|
|
||||||
// TODO: move conflict resolution from solver into this class.
|
// TODO: move conflict resolution from solver into this class.
|
||||||
|
|
|
@ -526,32 +526,12 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value Resolution
|
// Value Resolution
|
||||||
// TODO: maybe don't do this automatically, because cjust-constraints are true and core constraints are false.
|
if (!m_conflict.resolve_value(v, m_cjust[v])) {
|
||||||
// issue: what if viable(v) is empty? then we only have cjust constraints and none of them is evaluable (at least not immediately because no value is set for this variable.)
|
|
||||||
// => think about what we want to do in this case (choose a value and evaluate? try all possible superpositions without caring about the value of the premises?)
|
|
||||||
// the last value_resolution method can then be the one that adds the cjusts and calls saturation and more general VE.
|
|
||||||
for (auto c : m_cjust[v])
|
|
||||||
m_conflict.insert(c);
|
|
||||||
|
|
||||||
// Variable elimination
|
|
||||||
while (true) {
|
|
||||||
// TODO:
|
|
||||||
// 1. Try variable elimination of 'v'
|
|
||||||
// 2. If not possible, try saturation and core reduction (actually reduction could be one specific VE method?).
|
|
||||||
// 3. as a last resort, substitute v by m_value[v]?
|
|
||||||
// TODO: maybe we shouldn't try to split up VE/Saturation in the implementation.
|
|
||||||
// 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;
|
|
||||||
if (!m_conflict.try_saturate(v))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Failed to resolve => bail out
|
// Failed to resolve => bail out
|
||||||
++m_stats.m_num_bailouts;
|
++m_stats.m_num_bailouts;
|
||||||
m_conflict.set_bailout();
|
m_conflict.set_bailout();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Conflict resolution case where boolean literal 'lit' is on top of the stack */
|
/** Conflict resolution case where boolean literal 'lit' is on top of the stack */
|
||||||
void solver::resolve_bool(sat::literal lit) {
|
void solver::resolve_bool(sat::literal lit) {
|
||||||
|
|
|
@ -56,6 +56,7 @@ namespace polysat {
|
||||||
friend class clause_builder;
|
friend class clause_builder;
|
||||||
friend class conflict_core;
|
friend class conflict_core;
|
||||||
friend class conflict_explainer;
|
friend class conflict_explainer;
|
||||||
|
friend class explainer;
|
||||||
friend class inference_engine;
|
friend class inference_engine;
|
||||||
friend class forbidden_intervals;
|
friend class forbidden_intervals;
|
||||||
friend class linear_solver;
|
friend class linear_solver;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue