mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
inequality propagation
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
a4696a1c27
commit
6a829f831d
7 changed files with 720 additions and 56 deletions
|
@ -141,6 +141,7 @@ namespace polysat {
|
|||
}
|
||||
|
||||
static void test_ineqs() {
|
||||
unsigned num_bad = 0;
|
||||
var_t x = 0, y = 1;
|
||||
unsigned nb = 6;
|
||||
uint64_t bounds[6] = { 0, 1, 2, 10 , (uint64_t)-2, (uint64_t)-1 };
|
||||
|
@ -169,11 +170,25 @@ namespace polysat {
|
|||
solver.assert_expr(bv.mk_ule(I, x));
|
||||
};
|
||||
|
||||
auto add_not_bound = [&](expr* x, uint64_t i, uint64_t j) {
|
||||
expr_ref I(bv.mk_numeral(i, 64), m);
|
||||
expr_ref J(bv.mk_numeral(j, 64), m);
|
||||
if (i < j)
|
||||
solver.assert_expr(m.mk_not(m.mk_and(bv.mk_ule(I, x), mk_ult(x, J))));
|
||||
else if (i > j && j != 0)
|
||||
solver.assert_expr(m.mk_not(m.mk_or(bv.mk_ule(I, x), mk_ult(x, J))));
|
||||
else if (i > j && j == 0)
|
||||
solver.assert_expr(m.mk_not(bv.mk_ule(I, x)));
|
||||
else
|
||||
solver.assert_expr(m.mk_false());
|
||||
};
|
||||
|
||||
auto test_le = [&](bool test_le, uint64_t i, uint64_t j, uint64_t k, uint64_t l) {
|
||||
if (i == j && i != 0)
|
||||
return;
|
||||
if (k == l && k != 0)
|
||||
return;
|
||||
// std::cout << "test " << i << " " << j << " " << k << " " << l << "\n";
|
||||
scoped_fp fp;
|
||||
fp.set_bounds(x, i, j, 1);
|
||||
fp.set_bounds(y, k, l, 2);
|
||||
|
@ -197,13 +212,11 @@ namespace polysat {
|
|||
|
||||
lbool feas2 = solver.check();
|
||||
|
||||
|
||||
if (feas == feas2) {
|
||||
solver.pop(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (feas2 == l_false && feas == l_true) {
|
||||
std::cout << "BUG!\n";
|
||||
solver.pop(1);
|
||||
|
@ -217,10 +230,16 @@ namespace polysat {
|
|||
for (unsigned c : fp.get_unsat_core())
|
||||
std::cout << c << "\n";
|
||||
std::cout << "\n";
|
||||
// TBD: check that core is sufficient and minimal
|
||||
break;
|
||||
case l_true:
|
||||
case l_undef:
|
||||
|
||||
if (feas2 == l_false) {
|
||||
std::cout << "Missed conflict\n";
|
||||
std::cout << fp << "\n";
|
||||
break;
|
||||
}
|
||||
// Check for missed bounds:
|
||||
solver.push();
|
||||
solver.assert_expr(m.mk_eq(X, bv.mk_numeral(fp.lo(x), 64)));
|
||||
|
@ -258,9 +277,40 @@ namespace polysat {
|
|||
solver.pop(1);
|
||||
}
|
||||
|
||||
// check that inferred bounds are implied:
|
||||
solver.push();
|
||||
add_not_bound(X, fp.lo(x), fp.hi(x));
|
||||
if (l_false != solver.check()) {
|
||||
std::cout << "Bound on x is not implied\n";
|
||||
scoped_fp fp1;
|
||||
fp1.set_bounds(x, i, j, 1);
|
||||
fp1.set_bounds(y, k, l, 2);
|
||||
std::cout << fp1 << "\n";
|
||||
bad = true;
|
||||
}
|
||||
solver.pop(1);
|
||||
|
||||
solver.push();
|
||||
add_not_bound(Y, fp.lo(y), fp.hi(y));
|
||||
if (l_false != solver.check()) {
|
||||
std::cout << "Bound on y is not implied\n";
|
||||
scoped_fp fp1;
|
||||
fp1.set_bounds(x, i, j, 1);
|
||||
fp1.set_bounds(y, k, l, 2);
|
||||
std::cout << fp1 << "\n";
|
||||
bad = true;
|
||||
}
|
||||
solver.pop(1);
|
||||
|
||||
if (bad) {
|
||||
std::cout << fp << "\n";
|
||||
std::cout << feas << " " << feas2 << "\n";
|
||||
std::cout << fp << "\n";
|
||||
std::cout << "original:\n";
|
||||
scoped_fp fp1;
|
||||
fp1.set_bounds(x, i, j, 1);
|
||||
fp1.set_bounds(y, k, l, 2);
|
||||
std::cout << fp1 << "\n";
|
||||
++num_bad;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -287,6 +337,8 @@ namespace polysat {
|
|||
test_le(true, bounds[i], bounds[j], bounds[k], bounds[l]);
|
||||
test_le(false, bounds[i], bounds[j], bounds[k], bounds[l]);
|
||||
}
|
||||
|
||||
std::cout << "number of failures: " << num_bad << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,7 +346,6 @@ void tst_fixplex() {
|
|||
|
||||
polysat::test_ineq1();
|
||||
polysat::test_ineqs();
|
||||
return;
|
||||
|
||||
polysat::test1();
|
||||
polysat::test2();
|
||||
|
|
|
@ -90,12 +90,52 @@ static void test_interval2() {
|
|||
std::cout << " < 500: " << i << " -> " << i.intersect_ult(500) << "\n";
|
||||
i = mod_interval<uint32_t>(500, 10);
|
||||
std::cout << " < 501: " << i << " -> " << i.intersect_ult(501) << "\n";
|
||||
}
|
||||
|
||||
static void test_interval_intersect(unsigned i, unsigned j, unsigned k, unsigned l) {
|
||||
if (i == j && i != 0)
|
||||
return;
|
||||
if (k == l && k != 0)
|
||||
return;
|
||||
mod_interval<uint8_t> x(i, j);
|
||||
mod_interval<uint8_t> y(k, l);
|
||||
auto r = x & y;
|
||||
bool x_not_y = false, y_not_x = false;
|
||||
// check that & computes a join
|
||||
// it contains all elements in x, y
|
||||
// it contains no elements neither in x, y
|
||||
// it does not contain two elements, one in x\y the other in y\x
|
||||
for (i = 0; i < 256; ++i) {
|
||||
uint8_t c = (uint8_t)i;
|
||||
if ((x.contains(c) && y.contains(c)) && !r.contains(c)) {
|
||||
std::cout << x << " & " << y << " = " << r << "\n";
|
||||
std::cout << i << " " << r.contains(c) << " " << x.contains(c) << " " << y.contains(c) << "\n";
|
||||
}
|
||||
VERIFY(!(x.contains(c) && y.contains(c)) || r.contains(c));
|
||||
VERIFY(x.contains(c) || y.contains(c) || !r.contains(c));
|
||||
if (r.contains(c) && x.contains(c) && !y.contains(c))
|
||||
x_not_y = true;
|
||||
if (r.contains(c) && !x.contains(c) && y.contains(c))
|
||||
y_not_x = true;
|
||||
}
|
||||
if (x_not_y && y_not_x) {
|
||||
std::cout << x << " & " << y << " = " << r << "\n";
|
||||
VERIFY(!x_not_y || !y_not_x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void test_interval_intersect() {
|
||||
unsigned bounds[8] = { 0, 1, 2, 3, 252, 253, 254, 255 };
|
||||
for (unsigned i = 0; i < 8; ++i)
|
||||
for (unsigned j = 0; j < 8; ++j)
|
||||
for (unsigned k = 0; k < 8; ++k)
|
||||
for (unsigned l = 0; l < 8; ++l)
|
||||
test_interval_intersect(bounds[i], bounds[j], bounds[k], bounds[l]);
|
||||
}
|
||||
|
||||
void tst_mod_interval() {
|
||||
test_interval_intersect();
|
||||
test_interval1();
|
||||
test_interval2();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue