3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-02 20:31:21 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2021-11-10 02:58:35 -08:00
parent ef320af90b
commit 931e1624b2
7 changed files with 53 additions and 14 deletions

View file

@ -17,6 +17,7 @@ Author:
--*/
#include "math/polysat/forbidden_intervals.h"
#include "math/polysat/interval.h"
#include "math/polysat/solver.h"
#include "math/polysat/log.h"
namespace polysat {
@ -219,6 +220,8 @@ namespace polysat {
return true;
if (match_linear4(c, a1, b1, e1, a2, b2, e2, out_interval, out_side_cond))
return true;
if (match_linear5(c, a1, b1, e1, a2, b2, e2, out_interval, out_side_cond))
return true;
_backtrack.released = false;
return false;
@ -386,16 +389,27 @@ namespace polysat {
}
/**
* Ad-hoc linear forbidden intervals
* ax <= b, b != -1, a < b: x not in [ceil((b+1)/a) .. floor((2^K-1)/a)]
* b <= ax, 0 < a < b: x not in [0 .. floor((b-1)/a)]
* ax < b, a < b: x not in [ceil(b/a) .. floor((2^K-1)/a)]
* b < ax, 0 < a <= b: x not in [0 .. floor(b/a)]
*
* TODO: generalize to ax + b <= c scenarios where ax does not overflow
* and ax+b does not overflow, but is larger than c
* Scenarios:
* - ax + b <= c
* - ax + b < c
* - c <= ax + b
* - c < ax + b
*/
bool forbidden_intervals::match_linear5(signed_constraint const& c,
rational const& a1, pdd const& b1, pdd const& e1,
rational const& a2, pdd const& b2, pdd const& e2,
eval_interval& interval, vector<signed_constraint>& side_cond) {
auto& m = e1.manager();
// ax <= b, b != -1, a < b: x not in [ceil((b+1)/a) .. floor((2^K-1)/a)]
if (c.is_positive() &&
!a1.is_zero() && !a1.is_one() &&
a2.is_zero() && b1.is_zero() && e2.is_val() &&
@ -404,11 +418,14 @@ namespace polysat {
side_cond.push_back(s.eq(e1));
auto lo_val = ceil((b2.val() + 1) / a1);
auto hi_val = floor(m.max_value() / a1) + 1;
SASSERT(lo_val < hi_val);
auto lo = m.mk_val(lo_val);
auto hi = m.mk_val(hi_val);
interval = eval_interval::proper(lo, lo_val, hi, hi_val);
return true;
}
// b <= ax, 0 < a < b: x not in [0 .. floor((b-1)/a)]
if (c.is_positive() &&
!a2.is_zero() && !a2.is_one() &&
a1.is_zero() && b2.is_zero() &&
@ -417,15 +434,39 @@ namespace polysat {
side_cond.push_back(s.eq(e2));
auto lo_val = rational::zero();
auto hi_val = floor((b1.val() - 1) / a2) + 1;
SASSERT(lo_val < hi_val);
auto lo = m.mk_val(lo_val);
auto hi = m.mk_val(hi_val);
interval = eval_interval::proper(lo, lo_val, hi, hi_val);
return true;
}
if (c.is_negative() &&
!a2.is_zero() && !a2.is_one() &&
a1.is_zero() && false) {
// ax < b, a < b: x not in [ceil(b/a) .. floor((2^K-1)/a)]
if (c.is_negative() &&
!a2.is_zero() && !a2.is_one() && b2.is_zero() &&
a1.is_zero() && e1.is_val() && a2 < b1.val()) {
if (!e2.is_val())
side_cond.push_back(s.eq(e2));
auto lo_val = ceil(b1.val() / a2);
auto hi_val = floor(m.max_value() / a2) + 1;
auto lo = m.mk_val(lo_val);
auto hi = m.mk_val(hi_val);
interval = eval_interval::proper(lo, lo_val, hi, hi_val);
return true;
}
// b < ax, 0 < a <= b: x not in [0 .. floor(b/a)]
if (c.is_negative() &&
!a1.is_zero() && !a1.is_one() && b1.is_zero() &&
a2.is_zero() && e2.is_val() && a1 <= b2.val()) {
if (!e1.is_val())
side_cond.push_back(s.eq(e2));
auto lo_val = rational::zero();
auto hi_val = floor(b2.val() / a1) + 1;
auto lo = m.mk_val(lo_val);
auto hi = m.mk_val(hi_val);
interval = eval_interval::proper(lo, lo_val, hi, hi_val);
return true;
}
return false;
}