3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 17:15:31 +00:00

testing bounds strengthening code

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2021-08-06 17:05:54 -07:00
parent 481e20bc20
commit f47930a4ff
5 changed files with 295 additions and 93 deletions

View file

@ -1,5 +1,10 @@
#include "math/polysat/fixplex.h"
#include "math/polysat/fixplex_def.h"
#include "ast/bv_decl_plugin.h"
#include "ast/reg_decl_plugins.h"
#include "smt/smt_kernel.h"
#include "smt/params/smt_params.h"
namespace polysat {
@ -118,7 +123,6 @@ namespace polysat {
static void test_gcd() {
std::cout << "gcd\n";
uint64_ext::manager e;
uint64_t x = 0, y = 0, z = 0, a = 0, b = 0;
uint64_t g = e.gcd(15, 27);
std::cout << g << "\n";
std::cout << 15 << " " << e.mul_inverse(15) << " " << 15*e.mul_inverse(15) << "\n";
@ -126,9 +130,172 @@ namespace polysat {
std::cout << 60 << " " << e.mul_inverse(60) << " " << 60*e.mul_inverse(60) << "\n";
std::cout << 29 << " " << e.mul_inverse(29) << " " << 29*e.mul_inverse(29) << "\n";
}
static void test_ineq1() {
std::cout << "ineq1\n";
scoped_fp fp;
var_t x = 0, y = 1;
fp.add_lt(x, y, 1);
fp.add_le(y, x, 2);
fp.run();
}
static void test_ineqs() {
var_t x = 0, y = 1;
unsigned nb = 6;
uint64_t bounds[6] = { 0, 1, 2, 10 , (uint64_t)-2, (uint64_t)-1 };
ast_manager m;
reg_decl_plugins(m);
bv_util bv(m);
expr_ref X(m.mk_const("x", bv.mk_sort(64)), m);
expr_ref Y(m.mk_const("y", bv.mk_sort(64)), m);
smt_params pa;
smt::kernel solver(m, pa);
auto mk_ult = [&](expr* a, expr* b) {
return m.mk_not(bv.mk_ule(b, a));
};
auto add_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(bv.mk_ule(I, x));
solver.assert_expr(mk_ult(x, J));
}
else if (i > j && j != 0)
solver.assert_expr(m.mk_or(bv.mk_ule(I, x), mk_ult(x, J)));
else if (i > j && j == 0)
solver.assert_expr(bv.mk_ule(I, x));
};
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;
scoped_fp fp;
fp.set_bounds(x, i, j, 1);
fp.set_bounds(y, k, l, 2);
if (test_le)
fp.add_le(x, y, 3);
else
fp.add_lt(x, y, 3);
lbool feas = fp.make_feasible();
// validate result
solver.push();
if (test_le)
solver.assert_expr(bv.mk_ule(X, Y));
else
solver.assert_expr(mk_ult(X, Y));
add_bound(X, i, j);
add_bound(Y, k, l);
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);
return;
}
bool bad = false;
switch (feas) {
case l_false:
for (unsigned c : fp.get_unsat_core())
std::cout << c << "\n";
std::cout << "\n";
break;
case l_true:
case l_undef:
// Check for missed bounds:
solver.push();
solver.assert_expr(m.mk_eq(X, bv.mk_numeral(fp.lo(x), 64)));
if (l_true != solver.check()) {
std::cout << "missed lower bound on x\n";
bad = true;
}
solver.pop(1);
solver.push();
solver.assert_expr(m.mk_eq(Y, bv.mk_numeral(fp.lo(y), 64)));
if (l_true != solver.check()) {
std::cout << "missed lower bound on y\n";
bad = true;
}
solver.pop(1);
if (fp.lo(x) != fp.hi(x) && fp.hi(x) != 0) {
solver.push();
solver.assert_expr(m.mk_eq(X, bv.mk_numeral(fp.hi(x)-1, 64)));
if (l_true != solver.check()) {
std::cout << "missed upper bound on x\n";
bad = true;
}
solver.pop(1);
}
if (fp.lo(y) != fp.hi(y) && fp.hi(y) != 0) {
solver.push();
solver.assert_expr(m.mk_eq(Y, bv.mk_numeral(fp.hi(y) - 1, 64)));
if (l_true != solver.check()) {
std::cout << "missed upper bound on y\n";
bad = true;
}
solver.pop(1);
}
if (bad) {
std::cout << fp << "\n";
std::cout << feas << " " << feas2 << "\n";
}
break;
}
// check assignment is valid when returning satisfiable.
if (false && feas == l_true) {
rational vx = fp.get_value(x);
rational vy = fp.get_value(y);
SASSERT(vx <= vy);
SASSERT(i >= j || (rational(i, rational::ui64()) <= vx && vx < rational(j, rational::ui64())));
SASSERT(k >= l || (rational(k, rational::ui64()) <= vy && vy < rational(l, rational::ui64())));
}
solver.pop(1);
return;
};
for (unsigned i = 0; i < nb; ++i)
for (unsigned j = 0; j < nb; ++j)
for (unsigned k = 0; k < nb; ++k)
for (unsigned l = 0; l < nb; ++l) {
test_le(true, bounds[i], bounds[j], bounds[k], bounds[l]);
test_le(false, bounds[i], bounds[j], bounds[k], bounds[l]);
}
}
}
void tst_fixplex() {
polysat::test_ineq1();
polysat::test_ineqs();
return;
polysat::test1();
polysat::test2();
polysat::test3();