mirror of
https://github.com/Z3Prover/z3
synced 2025-06-24 14:53:40 +00:00
match additional cases in forbidden intervals
This commit is contained in:
parent
cd11b70864
commit
1cb7ca8dfc
3 changed files with 87 additions and 8 deletions
|
@ -55,7 +55,14 @@ namespace polysat {
|
||||||
|
|
||||||
_backtrack.released = true;
|
_backtrack.released = true;
|
||||||
|
|
||||||
|
|
||||||
|
// a*v <= 0, a odd
|
||||||
|
if (ok1 && ok2 && match_zero(c, a1, b1, e1, a2, b2, e2, fi))
|
||||||
|
return true;
|
||||||
|
|
||||||
// v > q
|
// v > q
|
||||||
|
// 2^k*a*v + b > 0
|
||||||
|
// TODO: is !ok2 required?
|
||||||
if (ok1 && !ok2 && match_non_zero(c, a1, b1, e1, fi))
|
if (ok1 && !ok2 && match_non_zero(c, a1, b1, e1, fi))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -70,7 +77,6 @@ namespace polysat {
|
||||||
SASSERT(b1.is_val());
|
SASSERT(b1.is_val());
|
||||||
SASSERT(b2.is_val());
|
SASSERT(b2.is_val());
|
||||||
|
|
||||||
|
|
||||||
if (match_linear1(c, a1, b1, e1, a2, b2, e2, fi))
|
if (match_linear1(c, a1, b1, e1, a2, b2, e2, fi))
|
||||||
return true;
|
return true;
|
||||||
if (match_linear2(c, a1, b1, e1, a2, b2, e2, fi))
|
if (match_linear2(c, a1, b1, e1, a2, b2, e2, fi))
|
||||||
|
@ -262,12 +268,36 @@ namespace polysat {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a*v <= 0, a odd
|
||||||
|
* forbidden interval for v is [1,0[
|
||||||
|
*/
|
||||||
|
bool forbidden_intervals::match_zero(
|
||||||
|
signed_constraint const& c,
|
||||||
|
rational const & a1, pdd const& b1, pdd const& e1,
|
||||||
|
rational const & a2, pdd const& b2, pdd const& e2,
|
||||||
|
fi_record& fi) {
|
||||||
|
if (c.is_positive() && a1.is_odd() && b1.is_zero() && a2.is_zero() && b2.is_zero()) {
|
||||||
|
auto& m = e1.manager();
|
||||||
|
rational lo_val(1);
|
||||||
|
auto lo = m.one();
|
||||||
|
rational hi_val(0);
|
||||||
|
auto hi = m.zero();
|
||||||
|
fi.coeff = 1;
|
||||||
|
fi.interval = eval_interval::proper(lo, lo_val, hi, hi_val);
|
||||||
|
if (b1 != e1)
|
||||||
|
fi.side_cond.push_back(s.eq(b1, e1));
|
||||||
|
if (b2 != e2)
|
||||||
|
fi.side_cond.push_back(s.eq(b2, e2));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* v > q
|
* v > q
|
||||||
* forbidden interval for v is [0,1[
|
* forbidden interval for v is [0,1[
|
||||||
*
|
*
|
||||||
* Generalizations todo:
|
|
||||||
*
|
|
||||||
* v - k > q
|
* v - k > q
|
||||||
* forbidden interval for v is [k,k+1[
|
* forbidden interval for v is [k,k+1[
|
||||||
*
|
*
|
||||||
|
@ -290,6 +320,21 @@ namespace polysat {
|
||||||
fi.side_cond.push_back(s.eq(b1, e1));
|
fi.side_cond.push_back(s.eq(b1, e1));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (a1.is_odd() && b1.is_val() && !c.is_positive()) {
|
||||||
|
auto& m = e1.manager();
|
||||||
|
rational const& mod_value = m.two_to_N();
|
||||||
|
rational a1_inv;
|
||||||
|
VERIFY(a1.mult_inverse(m.power_of_2(), a1_inv));
|
||||||
|
rational lo_val(mod(-b1.val() * a1_inv, mod_value));
|
||||||
|
auto lo = -e1 * a1_inv;
|
||||||
|
rational hi_val(mod(lo_val + 1, mod_value));
|
||||||
|
auto hi = lo + 1;
|
||||||
|
fi.coeff = 1;
|
||||||
|
fi.interval = eval_interval::proper(lo, lo_val, hi, hi_val);
|
||||||
|
if (b1 != e1)
|
||||||
|
fi.side_cond.push_back(s.eq(b1, e1));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,9 +348,18 @@ namespace polysat {
|
||||||
signed_constraint const& c,
|
signed_constraint const& c,
|
||||||
rational const & a2, pdd const& b2, pdd const& e2,
|
rational const & a2, pdd const& b2, pdd const& e2,
|
||||||
fi_record& fi) {
|
fi_record& fi) {
|
||||||
if (a2.is_one() && b2.is_zero() && !c.is_positive()) {
|
if (a2.is_one() && b2.is_val() && !c.is_positive()) {
|
||||||
// todo
|
auto& m = e2.manager();
|
||||||
|
rational const& mod_value = m.two_to_N();
|
||||||
|
rational lo_val(mod(-b2.val() - 1, mod_value));
|
||||||
|
auto lo = -e2 - 1;
|
||||||
|
rational hi_val(mod(lo_val + 1, mod_value));
|
||||||
|
auto hi = -e2;
|
||||||
|
fi.coeff = 1;
|
||||||
|
fi.interval = eval_interval::proper(lo, lo_val, hi, hi_val);
|
||||||
|
if (b2 != e2)
|
||||||
|
fi.side_cond.push_back(s.eq(b2, e2));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,11 @@ namespace polysat {
|
||||||
|
|
||||||
void add_non_unit_side_conds(fi_record& fi, pdd const& b1, pdd const& e1, pdd const& b2, pdd const& e2);
|
void add_non_unit_side_conds(fi_record& fi, pdd const& b1, pdd const& e1, pdd const& b2, pdd const& e2);
|
||||||
|
|
||||||
|
bool match_zero(signed_constraint const& c,
|
||||||
|
rational const & a1, pdd const& b1, pdd const& e1,
|
||||||
|
rational const & a2, pdd const& b2, pdd const& e2,
|
||||||
|
fi_record& fi);
|
||||||
|
|
||||||
bool match_non_zero(signed_constraint const& c,
|
bool match_non_zero(signed_constraint const& c,
|
||||||
rational const & a1, pdd const& b1, pdd const& e1,
|
rational const & a1, pdd const& b1, pdd const& e1,
|
||||||
fi_record& fi);
|
fi_record& fi);
|
||||||
|
|
|
@ -1069,6 +1069,22 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_fi_nonzero() {
|
||||||
|
scoped_solver s(__func__);
|
||||||
|
auto a = s.var(s.add_var(5));
|
||||||
|
auto b = s.var(s.add_var(5));
|
||||||
|
s.add_ult(b*b*b, 7*a + 6);
|
||||||
|
s.check();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_fi_nonmax() {
|
||||||
|
scoped_solver s(__func__);
|
||||||
|
auto a = s.var(s.add_var(5));
|
||||||
|
auto b = s.var(s.add_var(5));
|
||||||
|
s.add_ult(a + 8, b*b*b);
|
||||||
|
s.check();
|
||||||
|
}
|
||||||
|
|
||||||
// Goal: we probably mix up polysat variables and PDD variables at several points; try to uncover such cases
|
// Goal: we probably mix up polysat variables and PDD variables at several points; try to uncover such cases
|
||||||
// NOTE: actually, add_var seems to keep them in sync, so this is not an issue at the moment (but we should still test it later)
|
// NOTE: actually, add_var seems to keep them in sync, so this is not an issue at the moment (but we should still test it later)
|
||||||
// static void test_mixed_vars() {
|
// static void test_mixed_vars() {
|
||||||
|
@ -1321,6 +1337,10 @@ public:
|
||||||
void tst_polysat() {
|
void tst_polysat() {
|
||||||
using namespace polysat;
|
using namespace polysat;
|
||||||
|
|
||||||
|
test_polysat::test_fi_nonzero();
|
||||||
|
test_polysat::test_fi_nonmax();
|
||||||
|
return;
|
||||||
|
|
||||||
test_polysat::test_l2();
|
test_polysat::test_l2();
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue