mirror of
https://github.com/Z3Prover/z3
synced 2025-06-27 00:18:45 +00:00
Merge remote-tracking branch 'origin/polysat' into polysat
This commit is contained in:
commit
208f166934
7 changed files with 261 additions and 99 deletions
|
@ -37,6 +37,7 @@ void bv_rewriter::updt_local_params(params_ref const & _p) {
|
||||||
m_ite2id = p.bv_ite2id();
|
m_ite2id = p.bv_ite2id();
|
||||||
m_le_extra = p.bv_le_extra();
|
m_le_extra = p.bv_le_extra();
|
||||||
m_le2extract = p.bv_le2extract();
|
m_le2extract = p.bv_le2extract();
|
||||||
|
m_le2extract = false; //
|
||||||
set_sort_sums(p.bv_sort_ac());
|
set_sort_sums(p.bv_sort_ac());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1724,6 +1725,9 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_le2extract)
|
||||||
|
return BR_FAILED;
|
||||||
|
|
||||||
if (!v1.is_zero() && new_args.size() == 1) {
|
if (!v1.is_zero() && new_args.size() == 1) {
|
||||||
v1 = m_util.norm(v1, sz);
|
v1 = m_util.norm(v1, sz);
|
||||||
#ifdef _TRACE
|
#ifdef _TRACE
|
||||||
|
|
|
@ -32,44 +32,84 @@ namespace polysat {
|
||||||
|
|
||||||
saturation::saturation(solver& s) : s(s), m_lemma(s) {}
|
saturation::saturation(solver& s) : s(s), m_lemma(s) {}
|
||||||
|
|
||||||
|
void saturation::log_lemma(pvar v, conflict& core) {
|
||||||
|
IF_VERBOSE(1, auto const& cl = core.lemmas().back();
|
||||||
|
verbose_stream() << m_rule << " v" << v << " ";
|
||||||
|
for (auto lit : *cl) verbose_stream() << s.lit2cnstr(lit) << " ";
|
||||||
|
verbose_stream() << "\n");
|
||||||
|
}
|
||||||
|
|
||||||
void saturation::perform(pvar v, conflict& core) {
|
void saturation::perform(pvar v, conflict& core) {
|
||||||
|
IF_VERBOSE(2, verbose_stream() << "v" << v << " " << core << "\n");
|
||||||
for (auto c : core)
|
for (auto c : core)
|
||||||
if (perform(v, c, core)) {
|
if (perform(v, c, core))
|
||||||
IF_VERBOSE(0, auto const& cl = core.lemmas().back();
|
|
||||||
verbose_stream() << m_rule << " v" << v << " ";
|
|
||||||
for (auto lit : *cl) verbose_stream() << s.lit2cnstr(lit) << " ";
|
|
||||||
verbose_stream() << "\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool saturation::perform(pvar v, signed_constraint const& c, conflict& core) {
|
bool saturation::perform(pvar v, signed_constraint const& c, conflict& core) {
|
||||||
if (!c->is_ule())
|
|
||||||
return false;
|
|
||||||
if (c.is_currently_true(s))
|
if (c.is_currently_true(s))
|
||||||
return false;
|
return false;
|
||||||
auto i = inequality::from_ule(c);
|
|
||||||
if (try_mul_bounds(v, core, i))
|
if (c->is_ule()) {
|
||||||
return true;
|
auto i = inequality::from_ule(c);
|
||||||
if (try_parity(v, core, i))
|
return try_inequality(v, i, core);
|
||||||
return true;
|
}
|
||||||
if (try_parity_diseq(v, core, i))
|
|
||||||
return true;
|
#if 0
|
||||||
if (try_factor_equality(v, core, i))
|
if (c->is_umul_ovfl())
|
||||||
return true;
|
return try_umul_ovfl(v, c, core);
|
||||||
if (try_ugt_x(v, core, i))
|
#endif
|
||||||
return true;
|
|
||||||
if (try_ugt_y(v, core, i))
|
|
||||||
return true;
|
|
||||||
if (try_ugt_z(v, core, i))
|
|
||||||
return true;
|
|
||||||
if (try_y_l_ax_and_x_l_z(v, core, i))
|
|
||||||
return true;
|
|
||||||
if (false && try_tangent(v, core, i))
|
|
||||||
return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool saturation::try_inequality(pvar v, inequality const& i, conflict& core) {
|
||||||
|
bool prop = false;
|
||||||
|
if (try_mul_bounds(v, core, i))
|
||||||
|
prop = true;
|
||||||
|
if (try_parity(v, core, i))
|
||||||
|
prop = true;
|
||||||
|
if (try_parity_diseq(v, core, i))
|
||||||
|
prop = true;
|
||||||
|
if (try_transitivity(v, core, i))
|
||||||
|
prop = true;
|
||||||
|
if (try_factor_equality(v, core, i))
|
||||||
|
prop = true;
|
||||||
|
if (try_ugt_x(v, core, i))
|
||||||
|
prop = true;
|
||||||
|
if (try_ugt_y(v, core, i))
|
||||||
|
prop = true;
|
||||||
|
if (try_ugt_z(v, core, i))
|
||||||
|
prop = true;
|
||||||
|
if (try_y_l_ax_and_x_l_z(v, core, i))
|
||||||
|
prop = true;
|
||||||
|
if (false && try_tangent(v, core, i))
|
||||||
|
prop = true;
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool saturation::try_umul_ovfl(pvar v, signed_constraint const& c, conflict& core) {
|
||||||
|
set_rule("[x] ~ovfl(x, y) => y = 0 or x <= x * y");
|
||||||
|
SASSERT(c->is_umul_ovfl());
|
||||||
|
if (!c.is_negative())
|
||||||
|
return false;
|
||||||
|
auto const& ovfl = c->to_umul_ovfl();
|
||||||
|
auto V = s.var(v);
|
||||||
|
auto p = ovfl.p(), q = ovfl.q();
|
||||||
|
// TODO could relax condition to be that V occurs in p
|
||||||
|
if (q == V)
|
||||||
|
std::swap(p, q);
|
||||||
|
signed_constraint q_eq_0;
|
||||||
|
if (p == V && is_forced_diseq(q, 0, q_eq_0)) {
|
||||||
|
// ~ovfl(V,q) => q = 0 or V <= V*q
|
||||||
|
m_lemma.reset();
|
||||||
|
m_lemma.insert_eval(q_eq_0);
|
||||||
|
if (propagate(v, core, c, s.ule(p, p * q)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
signed_constraint saturation::ineq(bool is_strict, pdd const& lhs, pdd const& rhs) {
|
signed_constraint saturation::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);
|
||||||
|
@ -77,7 +117,11 @@ namespace polysat {
|
||||||
return s.ule(lhs, rhs);
|
return s.ule(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool saturation::propagate(conflict& core, inequality const& crit, signed_constraint c) {
|
bool saturation::propagate(pvar v, conflict& core, inequality const& crit, signed_constraint c) {
|
||||||
|
return propagate(v, core, crit.as_signed_constraint(), c);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool saturation::propagate(pvar v, conflict& core, signed_constraint const& crit, signed_constraint c) {
|
||||||
if (is_forced_true(c))
|
if (is_forced_true(c))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -95,25 +139,21 @@ namespace polysat {
|
||||||
// The current assumptions on how conflict lemmas are used do not accomodate propagation it seems.
|
// The current assumptions on how conflict lemmas are used do not accomodate propagation it seems.
|
||||||
//
|
//
|
||||||
|
|
||||||
m_lemma.insert(~crit.as_signed_constraint());
|
m_lemma.insert(~crit);
|
||||||
|
|
||||||
IF_VERBOSE(10, verbose_stream() << "propagate " << m_rule << " ";
|
|
||||||
for (auto lit : m_lemma) verbose_stream() << s.lit2cnstr(lit) << " ";
|
|
||||||
verbose_stream() << c << "\n";
|
|
||||||
);
|
|
||||||
|
|
||||||
SASSERT(all_of(m_lemma, [this](sat::literal lit) { return is_forced_false(s.lit2cnstr(lit)); }));
|
SASSERT(all_of(m_lemma, [this](sat::literal lit) { return is_forced_false(s.lit2cnstr(lit)); }));
|
||||||
|
|
||||||
m_lemma.insert(c);
|
m_lemma.insert(c);
|
||||||
core.add_lemma(m_rule, m_lemma.build());
|
core.add_lemma(m_rule, m_lemma.build());
|
||||||
|
log_lemma(v, core);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool saturation::add_conflict(conflict& core, inequality const& crit1, signed_constraint c) {
|
bool saturation::add_conflict(pvar v, conflict& core, inequality const& crit1, signed_constraint c) {
|
||||||
return add_conflict(core, crit1, crit1, c);
|
return add_conflict(v, core, crit1, crit1, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool saturation::add_conflict(conflict& core, inequality const& _crit1, inequality const& _crit2, signed_constraint const c) {
|
bool saturation::add_conflict(pvar v, conflict& core, inequality const& _crit1, inequality const& _crit2, signed_constraint const c) {
|
||||||
auto crit1 = _crit1.as_signed_constraint();
|
auto crit1 = _crit1.as_signed_constraint();
|
||||||
auto crit2 = _crit2.as_signed_constraint();
|
auto crit2 = _crit2.as_signed_constraint();
|
||||||
m_lemma.insert(~crit1);
|
m_lemma.insert(~crit1);
|
||||||
|
@ -135,6 +175,7 @@ namespace polysat {
|
||||||
|
|
||||||
m_lemma.insert_eval(c);
|
m_lemma.insert_eval(c);
|
||||||
core.add_lemma(m_rule, m_lemma.build());
|
core.add_lemma(m_rule, m_lemma.build());
|
||||||
|
log_lemma(v, core);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,8 +262,7 @@ namespace polysat {
|
||||||
*/
|
*/
|
||||||
bool saturation::is_AxB_l_Y(pvar x, inequality const& i, pdd& a, pdd& b, pdd& y) {
|
bool saturation::is_AxB_l_Y(pvar x, inequality const& i, pdd& a, pdd& b, pdd& y) {
|
||||||
y = i.rhs();
|
y = i.rhs();
|
||||||
pdd aa = a, bb = b;
|
return i.lhs().degree(x) == 1 && (i.lhs().factor(x, 1, a, b), true);
|
||||||
return i.lhs().degree(x) == 1 && (i.lhs().factor(x, 1, aa, bb), aa == a && bb == b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool saturation::verify_AxB_l_Y(pvar x, inequality const& i, pdd const& a, pdd const& b, pdd const& y) {
|
bool saturation::verify_AxB_l_Y(pvar x, inequality const& i, pdd const& a, pdd const& b, pdd const& y) {
|
||||||
|
@ -232,8 +272,7 @@ namespace polysat {
|
||||||
|
|
||||||
bool saturation::is_Y_l_AxB(pvar x, inequality const& i, pdd& y, pdd& a, pdd& b) {
|
bool saturation::is_Y_l_AxB(pvar x, inequality const& i, pdd& y, pdd& a, pdd& b) {
|
||||||
y = i.lhs();
|
y = i.lhs();
|
||||||
pdd aa = a, bb = b;
|
return i.rhs().degree(x) == 1 && (i.rhs().factor(x, 1, a, b), true);
|
||||||
return i.rhs().degree(x) == 1 && (i.rhs().factor(x, 1, aa, bb), aa == a && bb == b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool saturation::verify_Y_l_AxB(pvar x, inequality const& i, pdd const& y, pdd const& a, pdd& b) {
|
bool saturation::verify_Y_l_AxB(pvar x, inequality const& i, pdd const& y, pdd const& a, pdd& b) {
|
||||||
|
@ -386,7 +425,7 @@ namespace polysat {
|
||||||
m_lemma.insert_eval(~non_ovfl);
|
m_lemma.insert_eval(~non_ovfl);
|
||||||
if (!xy_l_xz.is_strict())
|
if (!xy_l_xz.is_strict())
|
||||||
m_lemma.insert_eval(s.eq(x));
|
m_lemma.insert_eval(s.eq(x));
|
||||||
return add_conflict(core, xy_l_xz, ineq(xy_l_xz.is_strict(), y, z));
|
return add_conflict(v, core, xy_l_xz, ineq(xy_l_xz.is_strict(), y, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -427,7 +466,7 @@ namespace polysat {
|
||||||
pdd const& z_prime = l_y.lhs();
|
pdd const& z_prime = l_y.lhs();
|
||||||
m_lemma.reset();
|
m_lemma.reset();
|
||||||
m_lemma.insert_eval(~non_ovfl);
|
m_lemma.insert_eval(~non_ovfl);
|
||||||
return add_conflict(core, l_y, yx_l_zx, ineq(yx_l_zx.is_strict() || l_y.is_strict(), z_prime * x, z * x));
|
return add_conflict(v, core, l_y, yx_l_zx, ineq(yx_l_zx.is_strict() || l_y.is_strict(), z_prime * x, z * x));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -467,7 +506,7 @@ namespace polysat {
|
||||||
return false;
|
return false;
|
||||||
m_lemma.reset();
|
m_lemma.reset();
|
||||||
m_lemma.insert_eval(~non_ovfl);
|
m_lemma.insert_eval(~non_ovfl);
|
||||||
return add_conflict(core, yx_l_zx, z_l_y, ineq(z_l_y.is_strict() || yx_l_zx.is_strict(), y * x, y_prime * x));
|
return add_conflict(z, core, yx_l_zx, z_l_y, ineq(z_l_y.is_strict() || yx_l_zx.is_strict(), y * x, y_prime * x));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -508,7 +547,7 @@ namespace polysat {
|
||||||
return false;
|
return false;
|
||||||
m_lemma.reset();
|
m_lemma.reset();
|
||||||
m_lemma.insert_eval(~non_ovfl);
|
m_lemma.insert_eval(~non_ovfl);
|
||||||
return add_conflict(core, y_l_ax, x_l_z, ineq(x_l_z.is_strict() || y_l_ax.is_strict(), y, a * z));
|
return add_conflict(x, core, y_l_ax, x_l_z, ineq(x_l_z.is_strict() || y_l_ax.is_strict(), y, a * z));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -546,7 +585,7 @@ namespace polysat {
|
||||||
m_lemma.insert_eval(~s.eq(y));
|
m_lemma.insert_eval(~s.eq(y));
|
||||||
m_lemma.insert_eval(x_eq_0);
|
m_lemma.insert_eval(x_eq_0);
|
||||||
m_lemma.insert_eval(a_eq_0);
|
m_lemma.insert_eval(a_eq_0);
|
||||||
return propagate(core, axb_l_y, c);
|
return propagate(x, core, axb_l_y, c);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto prop2 = [&](signed_constraint ante, signed_constraint c) {
|
auto prop2 = [&](signed_constraint ante, signed_constraint c) {
|
||||||
|
@ -556,7 +595,7 @@ namespace polysat {
|
||||||
m_lemma.insert_eval(x_eq_0);
|
m_lemma.insert_eval(x_eq_0);
|
||||||
m_lemma.insert_eval(a_eq_0);
|
m_lemma.insert_eval(a_eq_0);
|
||||||
m_lemma.insert_eval(~ante);
|
m_lemma.insert_eval(~ante);
|
||||||
return propagate(core, axb_l_y, c);
|
return propagate(x, core, axb_l_y, c);
|
||||||
};
|
};
|
||||||
|
|
||||||
pdd minus_a = -a;
|
pdd minus_a = -a;
|
||||||
|
@ -612,6 +651,12 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// bench 5
|
||||||
|
bool saturation::try_mul_eq_bound(pvar x, conflict& core, inequality const& axb_l_y) {
|
||||||
|
set_rule("[x] 2^k*x = 2^k*y & x < 2^N-k => y = x or y >= 2^{N-k}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* x*y = 1 & ~ovfl(x,y) => x = 1
|
* x*y = 1 & ~ovfl(x,y) => x = 1
|
||||||
* x*y = -1 & ~ovfl(-x,y) => -x = 1
|
* x*y = -1 & ~ovfl(-x,y) => -x = 1
|
||||||
|
@ -634,9 +679,9 @@ namespace polysat {
|
||||||
m_lemma.insert_eval(~s.eq(b, rational(-1)));
|
m_lemma.insert_eval(~s.eq(b, rational(-1)));
|
||||||
m_lemma.insert_eval(~s.eq(y));
|
m_lemma.insert_eval(~s.eq(y));
|
||||||
m_lemma.insert_eval(~non_ovfl);
|
m_lemma.insert_eval(~non_ovfl);
|
||||||
if (propagate(core, axb_l_y, s.eq(X, 1)))
|
if (propagate(x, core, axb_l_y, s.eq(X, 1)))
|
||||||
return true;
|
return true;
|
||||||
if (propagate(core, axb_l_y, s.eq(a, 1)))
|
if (propagate(x, core, axb_l_y, s.eq(a, 1)))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -669,8 +714,7 @@ namespace polysat {
|
||||||
auto& m = s.var2pdd(x);
|
auto& m = s.var2pdd(x);
|
||||||
unsigned N = m.power_of_2();
|
unsigned N = m.power_of_2();
|
||||||
pdd y = m.zero();
|
pdd y = m.zero();
|
||||||
pdd a = m.zero();
|
pdd a = y, b = y;
|
||||||
pdd b = m.zero();
|
|
||||||
pdd X = s.var(x);
|
pdd X = s.var(x);
|
||||||
if (!is_AxB_eq_0(x, axb_l_y, a, b, y))
|
if (!is_AxB_eq_0(x, axb_l_y, a, b, y))
|
||||||
return false;
|
return false;
|
||||||
|
@ -688,7 +732,7 @@ namespace polysat {
|
||||||
m_lemma.reset();
|
m_lemma.reset();
|
||||||
m_lemma.insert_eval(~s.eq(y));
|
m_lemma.insert_eval(~s.eq(y));
|
||||||
m_lemma.insert_eval(~premise);
|
m_lemma.insert_eval(~premise);
|
||||||
return propagate(core, axb_l_y, conseq);
|
return propagate(x, core, axb_l_y, conseq);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto propagate2 = [&](signed_constraint premise1, signed_constraint premise2, signed_constraint conseq) {
|
auto propagate2 = [&](signed_constraint premise1, signed_constraint premise2, signed_constraint conseq) {
|
||||||
|
@ -696,7 +740,7 @@ namespace polysat {
|
||||||
m_lemma.insert_eval(~s.eq(y));
|
m_lemma.insert_eval(~s.eq(y));
|
||||||
m_lemma.insert_eval(~premise1);
|
m_lemma.insert_eval(~premise1);
|
||||||
m_lemma.insert_eval(~premise2);
|
m_lemma.insert_eval(~premise2);
|
||||||
return propagate(core, axb_l_y, conseq);
|
return propagate(x, core, axb_l_y, conseq);
|
||||||
};
|
};
|
||||||
#if 0
|
#if 0
|
||||||
LOG_H1("try_parity: " << X << " on: " << lit_pp(s, axb_l_y.as_signed_constraint()));
|
LOG_H1("try_parity: " << X << " on: " << lit_pp(s, axb_l_y.as_signed_constraint()));
|
||||||
|
@ -741,7 +785,7 @@ namespace polysat {
|
||||||
//
|
//
|
||||||
// if b has at most b_parity, then a*x has at most b_parity
|
// if b has at most b_parity, then a*x has at most b_parity
|
||||||
//
|
//
|
||||||
else if (!is_forced_eq(b, 0)) {
|
if (!is_forced_eq(b, 0)) {
|
||||||
unsigned b_parity = 1;
|
unsigned b_parity = 1;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (; b_parity < N; ++b_parity) {
|
for (; b_parity < N; ++b_parity) {
|
||||||
|
@ -780,7 +824,8 @@ namespace polysat {
|
||||||
auto& m = s.var2pdd(x);
|
auto& m = s.var2pdd(x);
|
||||||
unsigned N = m.power_of_2();
|
unsigned N = m.power_of_2();
|
||||||
pdd y = m.zero();
|
pdd y = m.zero();
|
||||||
pdd a = y, b = y, X = y;
|
pdd a = y, b = y;
|
||||||
|
pdd X = s.var(x);
|
||||||
if (!is_AxB_diseq_0(x, axb_l_y, a, b, y))
|
if (!is_AxB_diseq_0(x, axb_l_y, a, b, y))
|
||||||
return false;
|
return false;
|
||||||
if (!is_forced_eq(b, 0))
|
if (!is_forced_eq(b, 0))
|
||||||
|
@ -793,7 +838,7 @@ namespace polysat {
|
||||||
m_lemma.reset();
|
m_lemma.reset();
|
||||||
m_lemma.insert_eval(~s.eq(y));
|
m_lemma.insert_eval(~s.eq(y));
|
||||||
m_lemma.insert_eval(~s.eq(b));
|
m_lemma.insert_eval(~s.eq(b));
|
||||||
return propagate(core, axb_l_y, ~s.parity(X, N - k));
|
return propagate(x, core, axb_l_y, ~s.parity(X, N - k));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -818,16 +863,52 @@ namespace polysat {
|
||||||
m_lemma.insert_eval(s.eq(y));
|
m_lemma.insert_eval(s.eq(y));
|
||||||
m_lemma.insert_eval(~s.eq(b));
|
m_lemma.insert_eval(~s.eq(b));
|
||||||
m_lemma.insert_eval(a_eq_0);
|
m_lemma.insert_eval(a_eq_0);
|
||||||
if (propagate(core, axb_l_y, s.even(X)))
|
if (propagate(x, core, axb_l_y, s.even(X)))
|
||||||
return true;
|
return true;
|
||||||
if (!is_forced_diseq(X, 0, x_eq_0))
|
if (!is_forced_diseq(X, 0, x_eq_0))
|
||||||
return false;
|
return false;
|
||||||
m_lemma.insert_eval(x_eq_0);
|
m_lemma.insert_eval(x_eq_0);
|
||||||
if (propagate(core, axb_l_y, s.even(a)))
|
if (propagate(x, core, axb_l_y, s.even(a)))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO If both inequalities are strict, then the implied inequality has a gap of 2
|
||||||
|
* a < b, b < c => a + 1 < c & a + 1 != 0
|
||||||
|
*/
|
||||||
|
bool saturation::try_transitivity(pvar x, conflict& core, inequality const& a_l_b) {
|
||||||
|
set_rule("[x] q < x & x <= p => q < p");
|
||||||
|
auto& m = s.var2pdd(x);
|
||||||
|
pdd p = m.zero();
|
||||||
|
pdd a = p, b = p, q = p;
|
||||||
|
// x <= p
|
||||||
|
if (!is_Ax_l_Y(x, a_l_b, a, p))
|
||||||
|
return false;
|
||||||
|
if (!is_forced_eq(a, 1))
|
||||||
|
return false;
|
||||||
|
for (auto c : core) {
|
||||||
|
if (!c->is_ule())
|
||||||
|
continue;
|
||||||
|
auto i = inequality::from_ule(c);
|
||||||
|
if (c == a_l_b.as_signed_constraint())
|
||||||
|
continue;
|
||||||
|
if (!is_Y_l_Ax(x, i, b, q))
|
||||||
|
continue;
|
||||||
|
if (!is_forced_eq(b, 1))
|
||||||
|
continue;
|
||||||
|
m_lemma.reset();
|
||||||
|
m_lemma.insert_eval(~s.eq(a, 1));
|
||||||
|
m_lemma.insert_eval(~s.eq(b, 1));
|
||||||
|
m_lemma.insert(~c);
|
||||||
|
auto ineq = i.is_strict() || a_l_b.is_strict() ? s.ult(q, p) : s.ule(q, p);
|
||||||
|
if (propagate(x, core, a_l_b, ineq))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [x] ax + p <= q, ax + r = 0 => -r + p <= q
|
* [x] ax + p <= q, ax + r = 0 => -r + p <= q
|
||||||
* [x] p <= ax + q, ax + r = 0 => p <= -r + q
|
* [x] p <= ax + q, ax + r = 0 => p <= -r + q
|
||||||
|
@ -837,6 +918,7 @@ namespace polysat {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool saturation::try_factor_equality(pvar x, conflict& core, inequality const& a_l_b) {
|
bool saturation::try_factor_equality(pvar x, conflict& core, inequality const& a_l_b) {
|
||||||
|
set_rule("[x] a1x+p <= a2x + q & a3*x + b3 = 0 => a1*inv(a3)*-b3 + p <= a2*inv(a3)*-b3 + q");
|
||||||
auto& m = s.var2pdd(x);
|
auto& m = s.var2pdd(x);
|
||||||
unsigned N = m.power_of_2();
|
unsigned N = m.power_of_2();
|
||||||
pdd y1 = m.zero();
|
pdd y1 = m.zero();
|
||||||
|
@ -846,14 +928,10 @@ namespace polysat {
|
||||||
bool is_axb_l_y = is_AxB_l_Y(x, a_l_b, a1, b1, y1);
|
bool is_axb_l_y = is_AxB_l_Y(x, a_l_b, a1, b1, y1);
|
||||||
bool is_y_l_axb = is_Y_l_AxB(x, a_l_b, y2, a2, b2);
|
bool is_y_l_axb = is_Y_l_AxB(x, a_l_b, y2, a2, b2);
|
||||||
|
|
||||||
if (!a_l_b.is_strict() && a_l_b.rhs().is_zero())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!is_axb_l_y && !is_y_l_axb)
|
if (!is_axb_l_y && !is_y_l_axb)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (a1.is_val() && a2.is_val())
|
bool factored = false;
|
||||||
return false;
|
|
||||||
|
|
||||||
for (auto c : core) {
|
for (auto c : core) {
|
||||||
if (!c->is_ule())
|
if (!c->is_ule())
|
||||||
|
@ -865,31 +943,52 @@ namespace polysat {
|
||||||
continue;
|
continue;
|
||||||
if (c == a_l_b.as_signed_constraint())
|
if (c == a_l_b.as_signed_constraint())
|
||||||
continue;
|
continue;
|
||||||
pdd lhs = i.lhs();
|
pdd lhs = a_l_b.lhs();
|
||||||
pdd rhs = i.rhs();
|
pdd rhs = a_l_b.rhs();
|
||||||
bool change = false;
|
bool change = false;
|
||||||
|
|
||||||
if (is_axb_l_y && a1 == a3) {
|
if (is_axb_l_y && a1 == a3) {
|
||||||
change = true;
|
change = true;
|
||||||
lhs = b3 - b1;
|
lhs = b1 - b3;
|
||||||
|
}
|
||||||
|
else if (is_axb_l_y && a1 == -a3) {
|
||||||
|
change = true;
|
||||||
|
lhs = b1 + b3;
|
||||||
|
}
|
||||||
|
else if (is_axb_l_y && a3.is_val() && a3.val().is_odd()) {
|
||||||
|
// a3*x + b3 == 0
|
||||||
|
// a3 is odd => x = inverse(a3)*-b3
|
||||||
|
change = true;
|
||||||
|
rational a3_inv;
|
||||||
|
VERIFY(a3.val().mult_inverse(m.power_of_2(), a3_inv));
|
||||||
|
lhs = b1 - a1*(b3 * a3_inv);
|
||||||
}
|
}
|
||||||
if (is_y_l_axb && a2 == a3) {
|
if (is_y_l_axb && a2 == a3) {
|
||||||
change = true;
|
change = true;
|
||||||
rhs = b3 - b2;
|
rhs = b2 - b3;
|
||||||
|
}
|
||||||
|
else if (is_y_l_axb && a2 == -a3) {
|
||||||
|
change = true;
|
||||||
|
rhs = b2 + b3;
|
||||||
|
}
|
||||||
|
else if (is_y_l_axb && a3.is_val() && a3.val().is_odd()) {
|
||||||
|
change = true;
|
||||||
|
rational a3_inv;
|
||||||
|
VERIFY(a3.val().mult_inverse(m.power_of_2(), a3_inv));
|
||||||
|
rhs = b2 - a2*(b3 * a3_inv);
|
||||||
}
|
}
|
||||||
if (!change) {
|
if (!change) {
|
||||||
IF_VERBOSE(0, verbose_stream() << "missed factor equality " << c << " " << a_l_b << "\n");
|
IF_VERBOSE(1, verbose_stream() << "missed factor equality " << c << " " << a_l_b << "\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
signed_constraint conseq = i.is_strict() ? s.ult(lhs, rhs) : s.ule(lhs, rhs);
|
signed_constraint conseq = a_l_b.is_strict() ? s.ult(lhs, rhs) : s.ule(lhs, rhs);
|
||||||
m_lemma.reset();
|
m_lemma.reset();
|
||||||
m_lemma.insert(~s.eq(y3));
|
m_lemma.insert(~s.eq(y3));
|
||||||
m_lemma.insert(~c);
|
m_lemma.insert(~c);
|
||||||
IF_VERBOSE(0, verbose_stream() << "factor equality " << a_l_b << "\n");
|
if (propagate(x, core, a_l_b, conseq))
|
||||||
if (propagate(core, a_l_b, conseq))
|
factored = true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return factored;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* TODO
|
* TODO
|
||||||
|
@ -949,7 +1048,7 @@ namespace polysat {
|
||||||
return false;
|
return false;
|
||||||
m_lemma.insert_eval(~d);
|
m_lemma.insert_eval(~d);
|
||||||
auto conseq = s.ult(r_val, c.rhs());
|
auto conseq = s.ult(r_val, c.rhs());
|
||||||
return add_conflict(core, c, conseq);
|
return add_conflict(v, core, c, conseq);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto d = s.ule(c.rhs(), r_val);
|
auto d = s.ule(c.rhs(), r_val);
|
||||||
|
@ -957,7 +1056,7 @@ namespace polysat {
|
||||||
return false;
|
return false;
|
||||||
m_lemma.insert_eval(~d);
|
m_lemma.insert_eval(~d);
|
||||||
auto conseq = s.ule(c.lhs(), r_val);
|
auto conseq = s.ule(c.lhs(), r_val);
|
||||||
return add_conflict(core, c, conseq);
|
return add_conflict(v, core, c, conseq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,11 @@ namespace polysat {
|
||||||
bool is_non_overflow(pdd const& x, pdd const& y, signed_constraint& c);
|
bool is_non_overflow(pdd const& x, pdd const& y, signed_constraint& c);
|
||||||
signed_constraint ineq(bool strict, pdd const& lhs, pdd const& rhs);
|
signed_constraint ineq(bool strict, pdd const& lhs, pdd const& rhs);
|
||||||
|
|
||||||
bool propagate(conflict& core, inequality const& crit1, signed_constraint c);
|
void log_lemma(pvar v, conflict& core);
|
||||||
bool add_conflict(conflict& core, inequality const& crit1, signed_constraint c);
|
bool propagate(pvar v, conflict& core, signed_constraint const& crit1, signed_constraint c);
|
||||||
bool add_conflict(conflict& core, inequality const& crit1, inequality const& crit2, signed_constraint c);
|
bool propagate(pvar v, conflict& core, inequality const& crit1, signed_constraint c);
|
||||||
|
bool add_conflict(pvar v, conflict& core, inequality const& crit1, signed_constraint c);
|
||||||
|
bool add_conflict(pvar v, conflict& core, inequality const& crit1, inequality const& crit2, signed_constraint c);
|
||||||
|
|
||||||
bool try_ugt_x(pvar v, conflict& core, inequality const& c);
|
bool try_ugt_x(pvar v, conflict& core, inequality const& c);
|
||||||
|
|
||||||
|
@ -52,6 +54,8 @@ namespace polysat {
|
||||||
bool try_factor_equality(pvar x, conflict& core, inequality const& a_l_b);
|
bool try_factor_equality(pvar x, conflict& core, inequality const& a_l_b);
|
||||||
bool try_mul_eq_1(pvar x, conflict& core, inequality const& axb_l_y);
|
bool try_mul_eq_1(pvar x, conflict& core, inequality const& axb_l_y);
|
||||||
bool try_mul_odd(pvar x, conflict& core, inequality const& axb_l_y);
|
bool try_mul_odd(pvar x, conflict& core, inequality const& axb_l_y);
|
||||||
|
bool try_mul_eq_bound(pvar x, conflict& core, inequality const& axb_l_y);
|
||||||
|
bool try_transitivity(pvar x, conflict& core, inequality const& axb_l_y);
|
||||||
bool try_tangent(pvar v, conflict& core, inequality const& c);
|
bool try_tangent(pvar v, conflict& core, inequality const& c);
|
||||||
|
|
||||||
// c := lhs ~ v
|
// c := lhs ~ v
|
||||||
|
@ -118,6 +122,10 @@ namespace polysat {
|
||||||
|
|
||||||
bool is_forced_true(signed_constraint const& sc);
|
bool is_forced_true(signed_constraint const& sc);
|
||||||
|
|
||||||
|
bool try_inequality(pvar v, inequality const& i, conflict& core);
|
||||||
|
|
||||||
|
bool try_umul_ovfl(pvar v, signed_constraint const& c, conflict& core);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
saturation(solver& s);
|
saturation(solver& s);
|
||||||
void perform(pvar v, conflict& core);
|
void perform(pvar v, conflict& core);
|
||||||
|
|
|
@ -99,8 +99,8 @@ namespace polysat {
|
||||||
signed_constraint sc(this, is_positive);
|
signed_constraint sc(this, is_positive);
|
||||||
// ¬Omega(p, q) ==> q = 0 \/ p <= p*q
|
// ¬Omega(p, q) ==> q = 0 \/ p <= p*q
|
||||||
// ¬Omega(p, q) ==> p = 0 \/ q <= p*q
|
// ¬Omega(p, q) ==> p = 0 \/ q <= p*q
|
||||||
s.add_clause(~sc, /* s.eq(p()), */ s.eq(q()), s.ule(p(), p()*q()), false);
|
s.add_clause(~sc, s.eq(q()), s.ule(p(), p()*q()), false);
|
||||||
s.add_clause(~sc, s.eq(p()), /* s.eq(q()), */ s.ule(q(), p()*q()), false);
|
s.add_clause(~sc, s.eq(p()), s.ule(q(), p()*q()), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ namespace polysat {
|
||||||
bv = alloc(bv_util, m);
|
bv = alloc(bv_util, m);
|
||||||
params_ref p;
|
params_ref p;
|
||||||
p.set_bool("bv.polysat", false);
|
p.set_bool("bv.polysat", false);
|
||||||
|
// p.set_bool("smt", true);
|
||||||
s = mk_solver(m, p, false, true, true, symbol::null);
|
s = mk_solver(m, p, false, true, true, symbol::null);
|
||||||
x_decl = m.mk_const_decl("x", bv->mk_sort(bit_width));
|
x_decl = m.mk_const_decl("x", bv->mk_sort(bit_width));
|
||||||
x = m.mk_const(x_decl);
|
x = m.mk_const(x_decl);
|
||||||
|
@ -66,7 +67,8 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_cache() {
|
void push_cache() {
|
||||||
model_cache.push_back(model_cache.back());
|
rational v = model_cache.back();
|
||||||
|
model_cache.push_back(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_cache() {
|
void pop_cache() {
|
||||||
|
@ -94,6 +96,13 @@ namespace polysat {
|
||||||
return bv->mk_numeral(r, bit_width);
|
return bv->mk_numeral(r, bit_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_zero(univariate const& p) const {
|
||||||
|
for (auto n : p)
|
||||||
|
if (n != 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// [d,c,b,a] --> ((a*x + b)*x + c)*x + d
|
// [d,c,b,a] --> ((a*x + b)*x + c)*x + d
|
||||||
expr* mk_poly(univariate const& p) const {
|
expr* mk_poly(univariate const& p) const {
|
||||||
|
@ -128,16 +137,18 @@ namespace polysat {
|
||||||
return mk_numeral(rational::zero());
|
return mk_numeral(rational::zero());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
expr* e = mk_numeral(p[0]);
|
expr* e = p[0] != 0 ? mk_numeral(p[0]) : nullptr;
|
||||||
expr* xpow = x;
|
expr_ref xpow = x;
|
||||||
for (unsigned i = 1; i < p.size(); ++i) {
|
for (unsigned i = 1; i < p.size(); ++i) {
|
||||||
if (!p[i].is_zero()) {
|
if (!p[i].is_zero()) {
|
||||||
expr* t = mk_poly_term(p[i], xpow);
|
expr* t = mk_poly_term(p[i], xpow);
|
||||||
e = bv->mk_bv_add(e, t);
|
e = e ? bv->mk_bv_add(e, t) : t;
|
||||||
}
|
}
|
||||||
if (i + 1 < p.size())
|
if (i + 1 < p.size())
|
||||||
xpow = bv->mk_bv_mul(xpow, x);
|
xpow = bv->mk_bv_mul(xpow, x);
|
||||||
}
|
}
|
||||||
|
if (!e)
|
||||||
|
e = mk_numeral(p[0]);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,13 +158,22 @@ namespace polysat {
|
||||||
reset_cache();
|
reset_cache();
|
||||||
if (sign)
|
if (sign)
|
||||||
e = m.mk_not(e);
|
e = m.mk_not(e);
|
||||||
expr* a = m.mk_const(m.mk_const_decl(symbol(dep), m.mk_bool_sort()));
|
if (dep == null_dep) {
|
||||||
s->assert_expr(e, a);
|
s->assert_expr(e);
|
||||||
IF_VERBOSE(10, verbose_stream() << "(assert (! " << expr_ref(e, m) << " :named " << expr_ref(a, m) << "))\n");
|
IF_VERBOSE(10, verbose_stream() << "(assert " << expr_ref(e, m) << ")\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
expr* a = m.mk_const(m.mk_const_decl(symbol(dep), m.mk_bool_sort()));
|
||||||
|
s->assert_expr(e, a);
|
||||||
|
IF_VERBOSE(10, verbose_stream() << "(assert (! " << expr_ref(e, m) << " :named " << expr_ref(a, m) << "))\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_ule(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) override {
|
void add_ule(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) override {
|
||||||
add(bv->mk_ule(mk_poly(lhs), mk_poly(rhs)), sign, dep);
|
if (is_zero(rhs))
|
||||||
|
add(m.mk_eq(mk_poly(lhs), mk_poly(rhs)), sign, dep);
|
||||||
|
else
|
||||||
|
add(bv->mk_ule(mk_poly(lhs), mk_poly(rhs)), sign, dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_umul_ovfl(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) override {
|
void add_umul_ovfl(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) override {
|
||||||
|
@ -197,7 +217,10 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_ule_const(rational const& val, bool sign, dep_t dep) override {
|
void add_ule_const(rational const& val, bool sign, dep_t dep) override {
|
||||||
add(bv->mk_ule(x, mk_numeral(val)), sign, dep);
|
if (val == 0)
|
||||||
|
add(m.mk_eq(x, mk_numeral(val)), sign, dep);
|
||||||
|
else
|
||||||
|
add(bv->mk_ule(x, mk_numeral(val)), sign, dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_uge_const(rational const& val, bool sign, dep_t dep) override {
|
void add_uge_const(rational const& val, bool sign, dep_t dep) override {
|
||||||
|
@ -220,6 +243,7 @@ namespace polysat {
|
||||||
unsigned dep = to_app(a)->get_decl()->get_name().get_num();
|
unsigned dep = to_app(a)->get_decl()->get_name().get_num();
|
||||||
deps.push_back(dep);
|
deps.push_back(dep);
|
||||||
}
|
}
|
||||||
|
IF_VERBOSE(10, verbose_stream() << "core " << deps << "\n");
|
||||||
SASSERT(deps.size() > 0);
|
SASSERT(deps.size() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +269,7 @@ namespace polysat {
|
||||||
// try reducing val by setting bits to 0, starting at the msb.
|
// try reducing val by setting bits to 0, starting at the msb.
|
||||||
for (unsigned k = bit_width; k-- > 0; ) {
|
for (unsigned k = bit_width; k-- > 0; ) {
|
||||||
if (!val.get_bit(k)) {
|
if (!val.get_bit(k)) {
|
||||||
add_bit0(k, 0);
|
add_bit0(k, null_dep);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// try decreasing k-th bit
|
// try decreasing k-th bit
|
||||||
|
@ -258,9 +282,9 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
pop(1);
|
pop(1);
|
||||||
if (result == l_true)
|
if (result == l_true)
|
||||||
add_bit0(k, 0);
|
add_bit0(k, null_dep);
|
||||||
else if (result == l_false)
|
else if (result == l_false)
|
||||||
add_bit1(k, 0);
|
add_bit1(k, null_dep);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -287,9 +311,9 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
pop(1);
|
pop(1);
|
||||||
if (result == l_true)
|
if (result == l_true)
|
||||||
add_bit1(k, 0);
|
add_bit1(k, null_dep);
|
||||||
else if (result == l_false)
|
else if (result == l_false)
|
||||||
add_bit0(k, 0);
|
add_bit0(k, null_dep);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -297,6 +321,27 @@ namespace polysat {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool find_two(rational& out1, rational& out2) {
|
||||||
|
out1 = model();
|
||||||
|
bool ok = true;
|
||||||
|
push();
|
||||||
|
add(m.mk_eq(mk_numeral(out1), x), true, null_dep);
|
||||||
|
switch (check()) {
|
||||||
|
case l_true:
|
||||||
|
out2 = model();
|
||||||
|
break;
|
||||||
|
case l_false:
|
||||||
|
out2 = out1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pop(1);
|
||||||
|
IF_VERBOSE(10, verbose_stream() << "viable " << out1 << " " << out2 << "\n");
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& display(std::ostream& out) const override {
|
std::ostream& display(std::ostream& out) const override {
|
||||||
return out << *s;
|
return out << *s;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ namespace polysat {
|
||||||
/// e.g., the vector [ c, b, a ] represents a*x^2 + b*x + c.
|
/// e.g., the vector [ c, b, a ] represents a*x^2 + b*x + c.
|
||||||
using univariate = vector<rational>;
|
using univariate = vector<rational>;
|
||||||
|
|
||||||
|
const dep_t null_dep = UINT_MAX;
|
||||||
|
|
||||||
virtual ~univariate_solver() = default;
|
virtual ~univariate_solver() = default;
|
||||||
|
|
||||||
virtual void push() = 0;
|
virtual void push() = 0;
|
||||||
|
@ -70,6 +72,14 @@ namespace polysat {
|
||||||
*/
|
*/
|
||||||
virtual bool find_max(rational& out_max) = 0;
|
virtual bool find_max(rational& out_max) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find up to two viable values.
|
||||||
|
*
|
||||||
|
* Precondition: check() returned l_true
|
||||||
|
* returns: true on success, false on resource out
|
||||||
|
*/
|
||||||
|
virtual bool find_two(rational& out1, rational& out2) = 0;
|
||||||
|
|
||||||
virtual void add_ule(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) = 0;
|
virtual void add_ule(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) = 0;
|
||||||
virtual void add_umul_ovfl(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) = 0;
|
virtual void add_umul_ovfl(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) = 0;
|
||||||
virtual void add_smul_ovfl(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) = 0;
|
virtual void add_smul_ovfl(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) = 0;
|
||||||
|
|
|
@ -799,11 +799,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool viable::query_find_fallback(pvar v, univariate_solver& us, rational& lo, rational& hi) {
|
lbool viable::query_find_fallback(pvar v, univariate_solver& us, rational& lo, rational& hi) {
|
||||||
if (!us.find_min(lo))
|
return us.find_two(lo, hi) ? l_true : l_undef;
|
||||||
return l_undef;
|
|
||||||
if (!us.find_max(hi))
|
|
||||||
return l_undef;
|
|
||||||
return l_true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool viable::query_min_fallback(pvar v, univariate_solver& us, rational& lo) {
|
lbool viable::query_min_fallback(pvar v, univariate_solver& us, rational& lo) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue