mirror of
https://github.com/Z3Prover/z3
synced 2025-06-19 20:33:38 +00:00
add variable minimization
This commit is contained in:
parent
c82bbaad7d
commit
e6c413b249
6 changed files with 85 additions and 51 deletions
|
@ -22,6 +22,7 @@ Notes:
|
||||||
It should apply saturation rules currently only available for propagated values.
|
It should apply saturation rules currently only available for propagated values.
|
||||||
|
|
||||||
TODO: dependency tracking for constraints evaluating to false should be minimized.
|
TODO: dependency tracking for constraints evaluating to false should be minimized.
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#include "math/polysat/conflict.h"
|
#include "math/polysat/conflict.h"
|
||||||
|
@ -39,9 +40,7 @@ namespace polysat {
|
||||||
conflict::conflict(solver& s):s(s) {
|
conflict::conflict(solver& s):s(s) {
|
||||||
ex_engines.push_back(alloc(ex_polynomial_superposition, s));
|
ex_engines.push_back(alloc(ex_polynomial_superposition, s));
|
||||||
ve_engines.push_back(alloc(ve_reduction));
|
ve_engines.push_back(alloc(ve_reduction));
|
||||||
inf_engines.push_back(alloc(inf_saturate));
|
inf_engines.push_back(alloc(inf_saturate, s));
|
||||||
for (auto* engine : inf_engines)
|
|
||||||
engine->set_solver(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
conflict::~conflict() {}
|
conflict::~conflict() {}
|
||||||
|
@ -218,6 +217,9 @@ namespace polysat {
|
||||||
while (!m_constraints.empty())
|
while (!m_constraints.empty())
|
||||||
keep(m_constraints.back());
|
keep(m_constraints.back());
|
||||||
|
|
||||||
|
for (auto c : *this)
|
||||||
|
minimize_vars(c);
|
||||||
|
|
||||||
for (auto c : *this)
|
for (auto c : *this)
|
||||||
lemma.push(~c);
|
lemma.push(~c);
|
||||||
|
|
||||||
|
@ -232,6 +234,34 @@ namespace polysat {
|
||||||
return lemma;
|
return lemma;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void conflict::minimize_vars(signed_constraint c) {
|
||||||
|
if (m_vars.empty())
|
||||||
|
return;
|
||||||
|
if (!c.is_currently_false(s))
|
||||||
|
return;
|
||||||
|
assignment_t a;
|
||||||
|
for (auto v : m_vars)
|
||||||
|
a.push_back(std::make_pair(v, s.get_value(v)));
|
||||||
|
for (unsigned i = 0; i < a.size(); ++i) {
|
||||||
|
auto save = a[i];
|
||||||
|
auto last = a.back();
|
||||||
|
a[i] = last;
|
||||||
|
a.pop_back();
|
||||||
|
if (c.is_currently_false(a))
|
||||||
|
--i;
|
||||||
|
else {
|
||||||
|
a.push_back(last);
|
||||||
|
a[i] = save;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (a.size() == m_vars.num_elems())
|
||||||
|
return;
|
||||||
|
m_vars.reset();
|
||||||
|
for (auto [v, val] : a)
|
||||||
|
m_vars.insert(v);
|
||||||
|
LOG("reduced " << m_vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool conflict::resolve_value(pvar v, vector<signed_constraint> const& cjust_v) {
|
bool conflict::resolve_value(pvar v, vector<signed_constraint> const& cjust_v) {
|
||||||
// NOTE:
|
// NOTE:
|
||||||
|
|
|
@ -50,6 +50,8 @@ namespace polysat {
|
||||||
void insert_literal(sat::literal lit);
|
void insert_literal(sat::literal lit);
|
||||||
void remove_literal(sat::literal lit);
|
void remove_literal(sat::literal lit);
|
||||||
|
|
||||||
|
void minimize_vars(signed_constraint c);
|
||||||
|
|
||||||
/** Whether we are in a bailout state. We enter a bailout state when we give up on proper conflict resolution. */
|
/** Whether we are in a bailout state. We enter a bailout state when we give up on proper conflict resolution. */
|
||||||
bool m_bailout = false;
|
bool m_bailout = false;
|
||||||
|
|
||||||
|
@ -65,6 +67,7 @@ namespace polysat {
|
||||||
pvar conflict_var() const { return m_conflict_var; }
|
pvar conflict_var() const { return m_conflict_var; }
|
||||||
|
|
||||||
bool is_bailout() const { return m_bailout; }
|
bool is_bailout() const { return m_bailout; }
|
||||||
|
|
||||||
void set_bailout();
|
void set_bailout();
|
||||||
|
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
|
|
|
@ -122,11 +122,11 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool signed_constraint::is_currently_false(solver& s) const {
|
bool signed_constraint::is_currently_false(solver& s) const {
|
||||||
return get()->is_currently_false(s.assignment(), is_positive());
|
return is_currently_false(s.assignment());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool signed_constraint::is_currently_true(solver& s) const {
|
bool signed_constraint::is_currently_true(solver& s) const {
|
||||||
return get()->is_currently_true(s.assignment(), is_positive());
|
return is_currently_true(s.assignment());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Look up constraint among stored constraints. */
|
/** Look up constraint among stored constraints. */
|
||||||
|
@ -182,20 +182,20 @@ namespace polysat {
|
||||||
return m_constraints.size() > m_num_external + 100;
|
return m_constraints.size() > m_num_external + 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
signed_constraint constraint_manager::eq(pdd const& p) {
|
|
||||||
pdd z = p.manager().zero();
|
|
||||||
return {dedup(alloc(ule_constraint, *this, p, z)), true};
|
|
||||||
}
|
|
||||||
|
|
||||||
signed_constraint constraint_manager::ule(pdd const& a, pdd const& b) {
|
signed_constraint constraint_manager::ule(pdd const& a, pdd const& b) {
|
||||||
return {dedup(alloc(ule_constraint, *this, a, b)), true};
|
return { dedup(alloc(ule_constraint, *this, a, b)), true };
|
||||||
}
|
}
|
||||||
|
|
||||||
signed_constraint constraint_manager::ult(pdd const& a, pdd const& b) {
|
signed_constraint constraint_manager::eq(pdd const& p) {
|
||||||
// a < b <=> !(b <= a)
|
return ule(p, p.manager().zero());
|
||||||
return ~ule(b, a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signed_constraint constraint_manager::ult(pdd const& a, pdd const& b) {
|
||||||
|
return ~ule(b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// To do signed comparison of bitvectors, flip the msb and do unsigned comparison:
|
// To do signed comparison of bitvectors, flip the msb and do unsigned comparison:
|
||||||
//
|
//
|
||||||
// x <=s y <=> x + 2^(w-1) <=u y + 2^(w-1)
|
// x <=s y <=> x + 2^(w-1) <=u y + 2^(w-1)
|
||||||
|
|
|
@ -90,7 +90,7 @@ namespace polysat {
|
||||||
|
|
||||||
signed_constraint eq(pdd const& p);
|
signed_constraint eq(pdd const& p);
|
||||||
signed_constraint ule(pdd const& a, pdd const& b);
|
signed_constraint ule(pdd const& a, pdd const& b);
|
||||||
signed_constraint ult(pdd const& a, pdd const& b);
|
signed_constraint ult(pdd const& a, pdd const& b);
|
||||||
signed_constraint sle(pdd const& a, pdd const& b);
|
signed_constraint sle(pdd const& a, pdd const& b);
|
||||||
signed_constraint slt(pdd const& a, pdd const& b);
|
signed_constraint slt(pdd const& a, pdd const& b);
|
||||||
|
|
||||||
|
@ -224,6 +224,8 @@ namespace polysat {
|
||||||
bool is_always_true() const { return get()->is_always_false(is_negative()); }
|
bool is_always_true() const { return get()->is_always_false(is_negative()); }
|
||||||
bool is_currently_false(solver& s) const;
|
bool is_currently_false(solver& s) const;
|
||||||
bool is_currently_true(solver& s) const;
|
bool is_currently_true(solver& s) const;
|
||||||
|
bool is_currently_false(assignment_t const& a) const { return get()->is_currently_false(a, is_positive()); }
|
||||||
|
bool is_currently_true(assignment_t const& a) const { return get()->is_currently_true(a, is_positive()); }
|
||||||
lbool bvalue(solver& s) const;
|
lbool bvalue(solver& s) const;
|
||||||
unsigned level(solver& s) const { return get()->level(s); }
|
unsigned level(solver& s) const { return get()->level(s); }
|
||||||
void narrow(solver& s) { get()->narrow(s, is_positive()); }
|
void narrow(solver& s) { get()->narrow(s, is_positive()); }
|
||||||
|
|
|
@ -50,9 +50,9 @@ namespace polysat {
|
||||||
|
|
||||||
signed_constraint inf_saturate::ineq(bool is_strict, pdd const& lhs, pdd const& rhs) {
|
signed_constraint inf_saturate::ineq(bool is_strict, pdd const& lhs, pdd const& rhs) {
|
||||||
if (is_strict)
|
if (is_strict)
|
||||||
return s().ult(lhs, rhs);
|
return s.ult(lhs, rhs);
|
||||||
else
|
else
|
||||||
return s().ule(lhs, rhs);
|
return s.ule(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,12 +60,12 @@ namespace polysat {
|
||||||
* The lemmas outlined in the rules are valid and therefore c is implied.
|
* The lemmas outlined in the rules are valid and therefore c is implied.
|
||||||
*/
|
*/
|
||||||
bool inf_saturate::propagate(conflict& core, inequality const& crit1, inequality const& crit2, signed_constraint& c, vector<signed_constraint>& new_constraints) {
|
bool inf_saturate::propagate(conflict& core, inequality const& crit1, inequality const& crit2, signed_constraint& c, vector<signed_constraint>& new_constraints) {
|
||||||
bool crit1_false = crit1.as_signed_constraint().is_currently_false(s());
|
bool crit1_false = crit1.as_signed_constraint().is_currently_false(s);
|
||||||
bool crit2_false = crit2.as_signed_constraint().is_currently_false(s());
|
bool crit2_false = crit2.as_signed_constraint().is_currently_false(s);
|
||||||
if (!crit1_false && !crit2_false)
|
if (!crit1_false && !crit2_false)
|
||||||
return false;
|
return false;
|
||||||
bool is_bool_false = c.bvalue(s()) == l_false;
|
bool is_bool_false = c.bvalue(s) == l_false;
|
||||||
bool is_model_false = c.is_currently_false(s());
|
bool is_model_false = c.is_currently_false(s);
|
||||||
if (!is_bool_false && !is_model_false)
|
if (!is_bool_false && !is_model_false)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -95,8 +95,8 @@ namespace polysat {
|
||||||
rational x_val, y_val;
|
rational x_val, y_val;
|
||||||
auto& pddm = x.manager();
|
auto& pddm = x.manager();
|
||||||
rational bound = pddm.max_value();
|
rational bound = pddm.max_value();
|
||||||
VERIFY(s().try_eval(x, x_val));
|
VERIFY(s.try_eval(x, x_val));
|
||||||
VERIFY(s().try_eval(y, y_val));
|
VERIFY(s.try_eval(y, y_val));
|
||||||
SASSERT(x_val * y_val <= bound);
|
SASSERT(x_val * y_val <= bound);
|
||||||
|
|
||||||
rational x_lo = x_val, x_hi = x_max, y_lo = y_val, y_hi = y_max;
|
rational x_lo = x_val, x_hi = x_max, y_lo = y_val, y_hi = y_max;
|
||||||
|
@ -140,8 +140,8 @@ namespace polysat {
|
||||||
// conflict resolution should be able to pick up this as a valid justification.
|
// conflict resolution should be able to pick up this as a valid justification.
|
||||||
// or we resort to the same extension as in the original mul_overflow code
|
// or we resort to the same extension as in the original mul_overflow code
|
||||||
// where we add explicit equality propagations from the current assignment.
|
// where we add explicit equality propagations from the current assignment.
|
||||||
auto c1 = s().ule(x, pddm.mk_val(x_lo));
|
auto c1 = s.ule(x, pddm.mk_val(x_lo));
|
||||||
auto c2 = s().ule(y, pddm.mk_val(y_lo));
|
auto c2 = s.ule(y, pddm.mk_val(y_lo));
|
||||||
new_constraints.insert(c1);
|
new_constraints.insert(c1);
|
||||||
new_constraints.insert(c2);
|
new_constraints.insert(c2);
|
||||||
}
|
}
|
||||||
|
@ -154,16 +154,16 @@ namespace polysat {
|
||||||
rational y_max = pddm.max_value();
|
rational y_max = pddm.max_value();
|
||||||
|
|
||||||
if (x.is_var())
|
if (x.is_var())
|
||||||
x_max = s().m_viable.max_viable(x.var());
|
x_max = s.m_viable.max_viable(x.var());
|
||||||
if (y.is_var())
|
if (y.is_var())
|
||||||
y_max = s().m_viable.max_viable(y.var());
|
y_max = s.m_viable.max_viable(y.var());
|
||||||
|
|
||||||
if (x_max * y_max > pddm.max_value())
|
if (x_max * y_max > pddm.max_value())
|
||||||
push_omega_bisect(new_constraints, x, x_max, y, y_max);
|
push_omega_bisect(new_constraints, x, x_max, y, y_max);
|
||||||
else {
|
else {
|
||||||
for (auto c : s().m_cjust[y.var()])
|
for (auto c : s.m_cjust[y.var()])
|
||||||
new_constraints.insert(c);
|
new_constraints.insert(c);
|
||||||
for (auto c : s().m_cjust[x.var()])
|
for (auto c : s.m_cjust[x.var()])
|
||||||
new_constraints.insert(c);
|
new_constraints.insert(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,14 +172,14 @@ namespace polysat {
|
||||||
* Match [v] .. <= v
|
* Match [v] .. <= v
|
||||||
*/
|
*/
|
||||||
bool inf_saturate::is_l_v(pvar v, inequality const& i) {
|
bool inf_saturate::is_l_v(pvar v, inequality const& i) {
|
||||||
return i.rhs == s().var(v);
|
return i.rhs == s.var(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Match [v] v <= ...
|
* Match [v] v <= ...
|
||||||
*/
|
*/
|
||||||
bool inf_saturate::is_g_v(pvar v, inequality const& i) {
|
bool inf_saturate::is_g_v(pvar v, inequality const& i) {
|
||||||
return i.lhs == s().var(v);
|
return i.lhs == s.var(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -199,7 +199,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inf_saturate::verify_Y_l_Ax(pvar x, inequality const& d, pdd const& a, pdd const& y) {
|
bool inf_saturate::verify_Y_l_Ax(pvar x, inequality const& d, pdd const& a, pdd const& y) {
|
||||||
return d.lhs == y && d.rhs == a * s().var(x);
|
return d.lhs == y && d.rhs == a * s.var(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -218,7 +218,7 @@ namespace polysat {
|
||||||
rational x_val, y_val;
|
rational x_val, y_val;
|
||||||
auto& pddm = x.manager();
|
auto& pddm = x.manager();
|
||||||
rational bound = rational::power_of_two(pddm.power_of_2());
|
rational bound = rational::power_of_two(pddm.power_of_2());
|
||||||
return s().try_eval(x, x_val) && s().try_eval(y, y_val) && x_val * y_val < bound;
|
return s.try_eval(x, x_val) && s.try_eval(y, y_val) && x_val * y_val < bound;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -229,7 +229,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inf_saturate::verify_Xy_l_XZ(pvar v, inequality const& c, pdd const& x, pdd const& z) {
|
bool inf_saturate::verify_Xy_l_XZ(pvar v, inequality const& c, pdd const& x, pdd const& z) {
|
||||||
return c.lhs == s().var(v) * x && c.rhs == z * x;
|
return c.lhs == s.var(v) * x && c.rhs == z * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -240,7 +240,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inf_saturate::verify_YX_l_zX(pvar z, inequality const& c, pdd const& x, pdd const& y) {
|
bool inf_saturate::verify_YX_l_zX(pvar z, inequality const& c, pdd const& x, pdd const& y) {
|
||||||
return c.lhs == y * x && c.rhs == s().var(z) * x;
|
return c.lhs == y * x && c.rhs == s.var(z) * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,19 +263,19 @@ namespace polysat {
|
||||||
* [x] yx <= zx ==> Ω*(x,y) \/ y <= z \/ x = 0
|
* [x] yx <= zx ==> Ω*(x,y) \/ y <= z \/ x = 0
|
||||||
*/
|
*/
|
||||||
bool inf_saturate::try_ugt_x(pvar v, conflict& core, inequality const& c) {
|
bool inf_saturate::try_ugt_x(pvar v, conflict& core, inequality const& c) {
|
||||||
pdd x = s().var(v);
|
pdd x = s.var(v);
|
||||||
pdd y = x;
|
pdd y = x;
|
||||||
pdd z = x;
|
pdd z = x;
|
||||||
if (!is_xY_l_xZ(v, c, y, z))
|
if (!is_xY_l_xZ(v, c, y, z))
|
||||||
return false;
|
return false;
|
||||||
if (!is_non_overflow(x, y))
|
if (!is_non_overflow(x, y))
|
||||||
return false;
|
return false;
|
||||||
if (!c.is_strict && s().get_value(v).is_zero())
|
if (!c.is_strict && s.get_value(v).is_zero())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
vector<signed_constraint> new_constraints;
|
vector<signed_constraint> new_constraints;
|
||||||
if (!c.is_strict)
|
if (!c.is_strict)
|
||||||
new_constraints.push_back(~s().eq(x));
|
new_constraints.push_back(~s.eq(x));
|
||||||
push_omega(new_constraints, x, y);
|
push_omega(new_constraints, x, y);
|
||||||
return propagate(core, c, c, c.is_strict, y, z, new_constraints);
|
return propagate(core, c, c, c.is_strict, y, z, new_constraints);
|
||||||
}
|
}
|
||||||
|
@ -283,7 +283,7 @@ namespace polysat {
|
||||||
/// [y] z' <= y /\ zx > yx ==> Ω*(x,y) \/ zx > z'x
|
/// [y] z' <= y /\ zx > yx ==> Ω*(x,y) \/ zx > z'x
|
||||||
/// [y] z' <= y /\ yx <= zx ==> Ω*(x,y) \/ z'x <= zx
|
/// [y] z' <= y /\ yx <= zx ==> Ω*(x,y) \/ z'x <= zx
|
||||||
bool inf_saturate::try_ugt_y(pvar v, conflict& core, inequality const& le_y, inequality const& yx_l_zx, pdd const& x, pdd const& z) {
|
bool inf_saturate::try_ugt_y(pvar v, conflict& core, inequality const& le_y, inequality const& yx_l_zx, pdd const& x, pdd const& z) {
|
||||||
pdd const y = s().var(v);
|
pdd const y = s.var(v);
|
||||||
|
|
||||||
SASSERT(is_l_v(v, le_y));
|
SASSERT(is_l_v(v, le_y));
|
||||||
SASSERT(verify_Xy_l_XZ(v, yx_l_zx, x, z));
|
SASSERT(verify_Xy_l_XZ(v, yx_l_zx, x, z));
|
||||||
|
@ -303,7 +303,7 @@ namespace polysat {
|
||||||
bool inf_saturate::try_ugt_y(pvar v, conflict& core, inequality const& c) {
|
bool inf_saturate::try_ugt_y(pvar v, conflict& core, inequality const& c) {
|
||||||
if (!is_l_v(v, c))
|
if (!is_l_v(v, c))
|
||||||
return false;
|
return false;
|
||||||
pdd x = s().var(v);
|
pdd x = s.var(v);
|
||||||
pdd z = x;
|
pdd z = x;
|
||||||
for (auto dd : core) {
|
for (auto dd : core) {
|
||||||
if (!dd->is_ule())
|
if (!dd->is_ule())
|
||||||
|
@ -321,7 +321,7 @@ namespace polysat {
|
||||||
bool inf_saturate::try_y_l_ax_and_x_l_z(pvar x, conflict& core, inequality const& c) {
|
bool inf_saturate::try_y_l_ax_and_x_l_z(pvar x, conflict& core, inequality const& c) {
|
||||||
if (!is_g_v(x, c))
|
if (!is_g_v(x, c))
|
||||||
return false;
|
return false;
|
||||||
pdd y = s().var(x);
|
pdd y = s.var(x);
|
||||||
pdd a = y;
|
pdd a = y;
|
||||||
for (auto dd : core) {
|
for (auto dd : core) {
|
||||||
if (!dd->is_ule())
|
if (!dd->is_ule())
|
||||||
|
@ -353,7 +353,7 @@ namespace polysat {
|
||||||
bool inf_saturate::try_ugt_z(pvar z, conflict& core, inequality const& c) {
|
bool inf_saturate::try_ugt_z(pvar z, conflict& core, inequality const& c) {
|
||||||
if (!is_g_v(z, c))
|
if (!is_g_v(z, c))
|
||||||
return false;
|
return false;
|
||||||
pdd y = s().var(z);
|
pdd y = s.var(z);
|
||||||
pdd x = y;
|
pdd x = y;
|
||||||
for (auto dd : core) {
|
for (auto dd : core) {
|
||||||
if (!dd->is_ule())
|
if (!dd->is_ule())
|
||||||
|
@ -387,19 +387,19 @@ namespace polysat {
|
||||||
return false;
|
return false;
|
||||||
if (c.lhs.is_val() || c.rhs.is_val())
|
if (c.lhs.is_val() || c.rhs.is_val())
|
||||||
return false;
|
return false;
|
||||||
if (!c.as_signed_constraint().is_currently_false(s()))
|
if (!c.as_signed_constraint().is_currently_false(s))
|
||||||
return false;
|
return false;
|
||||||
rational l_val, r_val;
|
rational l_val, r_val;
|
||||||
if (!s().try_eval(c.lhs, l_val))
|
if (!s.try_eval(c.lhs, l_val))
|
||||||
return false;
|
return false;
|
||||||
if (!s().try_eval(c.rhs, r_val))
|
if (!s.try_eval(c.rhs, r_val))
|
||||||
return false;
|
return false;
|
||||||
SASSERT(c.is_strict || l_val > r_val);
|
SASSERT(c.is_strict || l_val > r_val);
|
||||||
SASSERT(!c.is_strict || l_val >= r_val);
|
SASSERT(!c.is_strict || l_val >= r_val);
|
||||||
vector<signed_constraint> new_constraints;
|
vector<signed_constraint> new_constraints;
|
||||||
new_constraints.push_back(c.as_signed_constraint());
|
new_constraints.push_back(c.as_signed_constraint());
|
||||||
new_constraints.push_back(s().ule(c.rhs, r_val));
|
new_constraints.push_back(s.ule(c.rhs, r_val));
|
||||||
return propagate(core, c, c, c.is_strict ? s().ult(c.lhs, r_val) : s().ule(c.lhs, r_val), new_constraints);
|
return propagate(core, c, c, c.is_strict ? s.ult(c.lhs, r_val) : s.ule(c.lhs, r_val), new_constraints);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,10 @@ namespace polysat {
|
||||||
|
|
||||||
class inference_engine {
|
class inference_engine {
|
||||||
friend class conflict;
|
friend class conflict;
|
||||||
solver* m_solver = nullptr;
|
|
||||||
void set_solver(solver& s) { m_solver = &s; }
|
|
||||||
protected:
|
protected:
|
||||||
solver& s() { return *m_solver; }
|
solver& s;
|
||||||
public:
|
public:
|
||||||
|
inference_engine(solver& s) :s(s) {}
|
||||||
virtual ~inference_engine() {}
|
virtual ~inference_engine() {}
|
||||||
/** Try to apply an inference rule.
|
/** Try to apply an inference rule.
|
||||||
* Derive new constraints from constraints containing the variable v (i.e., at least one premise must contain v).
|
* Derive new constraints from constraints containing the variable v (i.e., at least one premise must contain v).
|
||||||
|
@ -91,7 +90,7 @@ namespace polysat {
|
||||||
bool is_coeffxY(pdd const& coeff_x, pdd const& p, pdd& y);
|
bool is_coeffxY(pdd const& coeff_x, pdd const& p, pdd& y);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
inf_saturate(solver& s) : inference_engine(s) {}
|
||||||
bool perform(pvar v, conflict& core) override;
|
bool perform(pvar v, conflict& core) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue