3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-26 15:53:41 +00:00

fix add_overflow

This commit is contained in:
Jakob Rath 2023-02-20 16:25:41 +01:00
parent 455abb1db3
commit 1dea87a07a
2 changed files with 33 additions and 31 deletions

View file

@ -1284,42 +1284,42 @@ namespace polysat {
/** /**
* x >= x + y & x <= n => y = 0 or y >= N - n * x >= x + y & x <= n ==> y >= M - n or y = 0
* x > x + y & x <= n => y >= N - n * x > x + y & x <= n ==> y >= M - n
* -x <= -x - y & x <= n => y = 0 or y >= N - n * -x <= -x - y & x <= n ==> y >= M - n or y = 0 or x = 0
* -x < -x - y & x <= n => y >= N - n * -x < -x - y & x <= n ==> y >= M - n or x = 0
* *
* NOTE: x + y <= x <==> -y <= x <==> -x-1 <= y-1 * NOTE: x + y <= x <=> -y <= x <=> -x-1 <= y-1
* x <= x + y <==> x <= -y-1 <==> y <= -x-1 * x <= x + y <=> x <= -y-1 <=> y <= -x-1
* (see notes on equivalent forms in ule_constraint.cpp) * (see notes on equivalent forms in ule_constraint.cpp)
* *
* x >= x + y ==> -y <= x * p <= q ==> p = 0 or -q <= -p
* x > x + y ==> y <= -x-1
* -x <= -x - y ==> -y <= x-1
* -x < -x - y ==> y <= -x
* Add these as simplification rules on ule_constraint instead of this inference rule?
*/ */
bool saturation::try_add_overflow_bound(pvar x, conflict& core, inequality const& axb_l_y) { bool saturation::try_add_overflow_bound(pvar x, conflict& core, inequality const& i) {
return false;
set_rule("[x] x >= x + y & x <= n => y = 0 or y >= 2^N - n"); set_rule("[x] x >= x + y & x <= n => y = 0 or y >= 2^N - n");
signed_constraint y_eq_0; signed_constraint y_eq_0, x_eq_0;
vector<signed_constraint> x_ge_bound; vector<signed_constraint> x_le_bound;
auto& m = s.var2pdd(x); auto& m = s.var2pdd(x);
pdd y = m.zero(); pdd y = m.zero();
if (!is_add_overflow(x, axb_l_y, y)) bool is_minus;
if (!is_add_overflow(x, i, y, is_minus))
return false; return false;
if (!axb_l_y.is_strict() && !is_forced_diseq(y, 0, y_eq_0)) if (!i.is_strict() && !is_forced_diseq(y, 0, y_eq_0))
return false;
if (is_minus && !is_forced_diseq(s.var(x), 0, x_eq_0))
return false; return false;
rational bound; rational bound;
if (!has_upper_bound(x, core, bound, x_ge_bound)) if (!has_upper_bound(x, core, bound, x_le_bound))
return false; return false;
SASSERT(bound != 0); SASSERT(bound != 0);
m_lemma.reset(); m_lemma.reset();
if (!axb_l_y.is_strict()) if (!i.is_strict())
m_lemma.insert_eval(y_eq_0); m_lemma.insert_eval(y_eq_0);
for (auto c : x_ge_bound) if (is_minus)
m_lemma.insert_eval(x_eq_0);
for (auto c : x_le_bound)
m_lemma.insert_eval(~c); m_lemma.insert_eval(~c);
return propagate(x, core, axb_l_y, s.uge(y, m.two_to_N() - bound)); return propagate(x, core, i, s.uge(y, m.two_to_N() - bound));
} }
/** /**
@ -1329,20 +1329,23 @@ namespace polysat {
* -x <= -x - y * -x <= -x - y
* -x < -x - y * -x < -x - y
*/ */
bool saturation::is_add_overflow(pvar x, inequality const& i, pdd& y) { bool saturation::is_add_overflow(pvar x, inequality const& i, pdd& y, bool& is_minus) {
auto& m = s.var2pdd(x); auto& m = s.var2pdd(x);
pdd X = s.var(x); pdd const X = s.var(x);
pdd a = X; pdd a = X;
if (i.lhs().degree(x) != 1 || i.rhs().degree(x) != 1) if (i.lhs().degree(x) != 1 || i.rhs().degree(x) != 1)
return false; return false;
if (i.rhs() == X) { if (i.rhs() == X) {
i.lhs().factor(x, 1, a, y); i.lhs().factor(x, 1, a, y);
if (a.is_one()) if (a.is_one()) {
is_minus = false;
return true; return true;
} }
}
if (i.lhs() == -X) { if (i.lhs() == -X) {
i.rhs().factor(x, 1, a, y); i.rhs().factor(x, 1, a, y);
if ((-a).is_one()) { if ((-a).is_one()) {
is_minus = true;
y = -y; y = -y;
return true; return true;
} }

View file

@ -138,8 +138,7 @@ namespace polysat {
// p := coeff*x*y where coeff_x = coeff*x, x a variable // p := coeff*x*y where coeff_x = coeff*x, x a variable
bool is_coeffxY(pdd const& coeff_x, pdd const& p, pdd& y); bool is_coeffxY(pdd const& coeff_x, pdd const& p, pdd& y);
// i := x + y >= x or x + y > x bool is_add_overflow(pvar x, inequality const& i, pdd& y, bool& is_minus);
bool is_add_overflow(pvar x, inequality const& i, pdd& y);
bool has_upper_bound(pvar x, conflict& core, rational& bound, vector<signed_constraint>& x_ge_bound); bool has_upper_bound(pvar x, conflict& core, rational& bound, vector<signed_constraint>& x_ge_bound);