mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
moving remaining qsat functionality over
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
296addf246
commit
20bbdfe31a
23 changed files with 3876 additions and 225 deletions
|
@ -21,6 +21,8 @@ Notes:
|
|||
#include"nlsat_evaluator.h"
|
||||
#include"nlsat_solver.h"
|
||||
#include"util.h"
|
||||
#include"nlsat_explain.h"
|
||||
#include"polynomial_cache.h"
|
||||
#include"rlimit.h"
|
||||
|
||||
nlsat::interval_set_ref tst_interval(nlsat::interval_set_ref const & s1,
|
||||
|
@ -29,7 +31,6 @@ nlsat::interval_set_ref tst_interval(nlsat::interval_set_ref const & s1,
|
|||
bool check_num_intervals = true) {
|
||||
nlsat::interval_set_manager & ism = s1.m();
|
||||
nlsat::interval_set_ref r(ism);
|
||||
std::cout << "------------------\n";
|
||||
std::cout << "s1: " << s1 << "\n";
|
||||
std::cout << "s2: " << s2 << "\n";
|
||||
r = ism.mk_union(s1, s2);
|
||||
|
@ -277,10 +278,12 @@ static void tst5() {
|
|||
nlsat::assignment as(am);
|
||||
small_object_allocator allocator;
|
||||
nlsat::interval_set_manager ism(am, allocator);
|
||||
nlsat::evaluator ev(as, pm, allocator);
|
||||
nlsat::evaluator ev(s, as, pm, allocator);
|
||||
nlsat::var x0, x1;
|
||||
x0 = pm.mk_var();
|
||||
x1 = pm.mk_var();
|
||||
nlsat::interval_set_ref i(ism);
|
||||
|
||||
polynomial_ref p(pm);
|
||||
polynomial_ref _x0(pm), _x1(pm);
|
||||
_x0 = pm.mk_polynomial(x0);
|
||||
|
@ -291,7 +294,6 @@ static void tst5() {
|
|||
nlsat::bool_var b = s.mk_ineq_atom(nlsat::atom::GT, 1, _p, is_even);
|
||||
nlsat::atom * a = s.bool_var2atom(b);
|
||||
SASSERT(a != 0);
|
||||
nlsat::interval_set_ref i(ism);
|
||||
scoped_anum zero(am);
|
||||
am.set(zero, 0);
|
||||
as.set(0, zero);
|
||||
|
@ -302,8 +304,414 @@ static void tst5() {
|
|||
std::cout << "2) " << i << "\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void project(nlsat::solver& s, nlsat::explain& ex, nlsat::var x, unsigned num, nlsat::literal const* lits) {
|
||||
std::cout << "Project ";
|
||||
s.display(std::cout, num, lits);
|
||||
nlsat::scoped_literal_vector result(s);
|
||||
ex.project(x, num, lits, result);
|
||||
s.display(std::cout << "\n==>\n", result.size(), result.c_ptr());
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
static nlsat::literal mk_gt(nlsat::solver& s, nlsat::poly* p) {
|
||||
nlsat::poly * _p[1] = { p };
|
||||
bool is_even[1] = { false };
|
||||
return s.mk_ineq_literal(nlsat::atom::GT, 1, _p, is_even);
|
||||
}
|
||||
|
||||
static nlsat::literal mk_eq(nlsat::solver& s, nlsat::poly* p) {
|
||||
nlsat::poly * _p[1] = { p };
|
||||
bool is_even[1] = { false };
|
||||
return s.mk_ineq_literal(nlsat::atom::EQ, 1, _p, is_even);
|
||||
}
|
||||
|
||||
static void tst6() {
|
||||
params_ref ps;
|
||||
reslimit rlim;
|
||||
nlsat::solver s(rlim, ps);
|
||||
anum_manager & am = s.am();
|
||||
nlsat::pmanager & pm = s.pm();
|
||||
nlsat::assignment as(am);
|
||||
nlsat::explain& ex = s.get_explain();
|
||||
nlsat::var x0, x1, x2, a, b, c, d;
|
||||
a = s.mk_var(false);
|
||||
b = s.mk_var(false);
|
||||
c = s.mk_var(false);
|
||||
d = s.mk_var(false);
|
||||
x0 = s.mk_var(false);
|
||||
x1 = s.mk_var(false);
|
||||
x2 = s.mk_var(false);
|
||||
|
||||
polynomial_ref p1(pm), p2(pm), p3(pm), p4(pm), p5(pm);
|
||||
polynomial_ref _x0(pm), _x1(pm), _x2(pm);
|
||||
polynomial_ref _a(pm), _b(pm), _c(pm), _d(pm);
|
||||
_x0 = pm.mk_polynomial(x0);
|
||||
_x1 = pm.mk_polynomial(x1);
|
||||
_x2 = pm.mk_polynomial(x2);
|
||||
_a = pm.mk_polynomial(a);
|
||||
_b = pm.mk_polynomial(b);
|
||||
_c = pm.mk_polynomial(c);
|
||||
_d = pm.mk_polynomial(d);
|
||||
|
||||
p1 = (_a*(_x0^2)) + _x2 + 2;
|
||||
p2 = (_b*_x1) - (2*_x2) - _x0 + 8;
|
||||
nlsat::scoped_literal_vector lits(s);
|
||||
lits.push_back(mk_gt(s, p1));
|
||||
lits.push_back(mk_gt(s, p2));
|
||||
lits.push_back(mk_gt(s, (_c*_x0) + _x2 + 1));
|
||||
lits.push_back(mk_gt(s, (_d*_x0) - _x1 + 5*_x2));
|
||||
|
||||
scoped_anum zero(am), one(am), two(am);
|
||||
am.set(zero, 0);
|
||||
am.set(one, 1);
|
||||
am.set(two, 2);
|
||||
as.set(0, one);
|
||||
as.set(1, one);
|
||||
as.set(2, two);
|
||||
as.set(3, two);
|
||||
as.set(4, two);
|
||||
as.set(5, one);
|
||||
as.set(6, one);
|
||||
s.set_rvalues(as);
|
||||
|
||||
|
||||
project(s, ex, x0, 2, lits.c_ptr());
|
||||
project(s, ex, x1, 3, lits.c_ptr());
|
||||
project(s, ex, x2, 3, lits.c_ptr());
|
||||
project(s, ex, x2, 2, lits.c_ptr());
|
||||
project(s, ex, x2, 4, lits.c_ptr());
|
||||
project(s, ex, x2, 3, lits.c_ptr()+1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void tst7() {
|
||||
params_ref ps;
|
||||
reslimit rlim;
|
||||
nlsat::solver s(rlim, ps);
|
||||
anum_manager & am = s.am();
|
||||
nlsat::pmanager & pm = s.pm();
|
||||
nlsat::var x0, x1, x2, a, b, c, d;
|
||||
a = s.mk_var(false);
|
||||
b = s.mk_var(false);
|
||||
c = s.mk_var(false);
|
||||
d = s.mk_var(false);
|
||||
x0 = s.mk_var(false);
|
||||
x1 = s.mk_var(false);
|
||||
x2 = s.mk_var(false);
|
||||
polynomial_ref p1(pm), p2(pm), p3(pm), p4(pm), p5(pm);
|
||||
polynomial_ref _x0(pm), _x1(pm), _x2(pm);
|
||||
polynomial_ref _a(pm), _b(pm), _c(pm), _d(pm);
|
||||
_x0 = pm.mk_polynomial(x0);
|
||||
_x1 = pm.mk_polynomial(x1);
|
||||
_x2 = pm.mk_polynomial(x2);
|
||||
_a = pm.mk_polynomial(a);
|
||||
_b = pm.mk_polynomial(b);
|
||||
_c = pm.mk_polynomial(c);
|
||||
_d = pm.mk_polynomial(d);
|
||||
|
||||
p1 = _x0 + _x1;
|
||||
p2 = _x2 - _x0;
|
||||
p3 = (-1*_x0) - _x1;
|
||||
|
||||
nlsat::scoped_literal_vector lits(s);
|
||||
lits.push_back(mk_gt(s, p1));
|
||||
lits.push_back(mk_gt(s, p2));
|
||||
lits.push_back(mk_gt(s, p3));
|
||||
|
||||
nlsat::literal_vector litsv(lits.size(), lits.c_ptr());
|
||||
lbool res = s.check(litsv);
|
||||
SASSERT(res == l_false);
|
||||
for (unsigned i = 0; i < litsv.size(); ++i) {
|
||||
s.display(std::cout, litsv[i]);
|
||||
std::cout << " ";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
litsv.reset();
|
||||
litsv.append(2, lits.c_ptr());
|
||||
res = s.check(litsv);
|
||||
SASSERT(res == l_true);
|
||||
s.display(std::cout);
|
||||
s.am().display(std::cout, s.value(x0)); std::cout << "\n";
|
||||
s.am().display(std::cout, s.value(x1)); std::cout << "\n";
|
||||
s.am().display(std::cout, s.value(x2)); std::cout << "\n";
|
||||
|
||||
}
|
||||
|
||||
static void tst8() {
|
||||
params_ref ps;
|
||||
reslimit rlim;
|
||||
nlsat::solver s(rlim, ps);
|
||||
anum_manager & am = s.am();
|
||||
nlsat::pmanager & pm = s.pm();
|
||||
nlsat::assignment as(am);
|
||||
nlsat::explain& ex = s.get_explain();
|
||||
nlsat::var x0, x1, x2, a, b, c, d;
|
||||
a = s.mk_var(false);
|
||||
b = s.mk_var(false);
|
||||
c = s.mk_var(false);
|
||||
d = s.mk_var(false);
|
||||
x0 = s.mk_var(false);
|
||||
x1 = s.mk_var(false);
|
||||
x2 = s.mk_var(false);
|
||||
|
||||
polynomial_ref p1(pm), p2(pm), p3(pm), p4(pm), p5(pm);
|
||||
polynomial_ref _x0(pm), _x1(pm), _x2(pm);
|
||||
polynomial_ref _a(pm), _b(pm), _c(pm), _d(pm);
|
||||
_x0 = pm.mk_polynomial(x0);
|
||||
_x1 = pm.mk_polynomial(x1);
|
||||
_x2 = pm.mk_polynomial(x2);
|
||||
_a = pm.mk_polynomial(a);
|
||||
_b = pm.mk_polynomial(b);
|
||||
_c = pm.mk_polynomial(c);
|
||||
_d = pm.mk_polynomial(d);
|
||||
|
||||
scoped_anum zero(am), one(am), two(am), six(am);
|
||||
am.set(zero, 0);
|
||||
am.set(one, 1);
|
||||
am.set(two, 2);
|
||||
am.set(six, 6);
|
||||
as.set(0, two); // a
|
||||
as.set(1, one); // b
|
||||
as.set(2, six); // c
|
||||
as.set(3, zero); // d
|
||||
as.set(4, zero); // x0
|
||||
as.set(5, zero); // x1
|
||||
as.set(6, two); // x2
|
||||
s.set_rvalues(as);
|
||||
|
||||
nlsat::scoped_literal_vector lits(s);
|
||||
lits.push_back(mk_eq(s, (_a*_x2*_x2) - (_b*_x2) - _c));
|
||||
project(s, ex, x2, 1, lits.c_ptr());
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void tst9() {
|
||||
params_ref ps;
|
||||
reslimit rlim;
|
||||
nlsat::solver s(rlim, ps);
|
||||
anum_manager & am = s.am();
|
||||
nlsat::pmanager & pm = s.pm();
|
||||
nlsat::assignment as(am);
|
||||
nlsat::explain& ex = s.get_explain();
|
||||
int num_lo = 4;
|
||||
int num_hi = 5;
|
||||
svector<nlsat::var> los, his;
|
||||
for (int i = 0; i < num_lo; ++i) {
|
||||
los.push_back(s.mk_var(false));
|
||||
scoped_anum num(am);
|
||||
am.set(num, - i - 1);
|
||||
as.set(i, num);
|
||||
}
|
||||
for (int i = 0; i < num_hi; ++i) {
|
||||
his.push_back(s.mk_var(false));
|
||||
scoped_anum num(am);
|
||||
am.set(num, i + 1);
|
||||
as.set(num_lo + i, num);
|
||||
}
|
||||
nlsat::var _z = s.mk_var(false);
|
||||
nlsat::var _x = s.mk_var(false);
|
||||
polynomial_ref x(pm), z(pm);
|
||||
x = pm.mk_polynomial(_x);
|
||||
scoped_anum val(am);
|
||||
am.set(val, 0);
|
||||
as.set(num_lo + num_hi, val);
|
||||
as.set(num_lo + num_hi + 1, val);
|
||||
s.set_rvalues(as);
|
||||
nlsat::scoped_literal_vector lits(s);
|
||||
|
||||
for (int i = 0; i < num_lo; ++i) {
|
||||
polynomial_ref y(pm);
|
||||
y = pm.mk_polynomial(los[i]);
|
||||
lits.push_back(mk_gt(s, x - y));
|
||||
}
|
||||
for (int i = 0; i < num_hi; ++i) {
|
||||
polynomial_ref y(pm);
|
||||
y = pm.mk_polynomial(his[i]);
|
||||
lits.push_back(mk_gt(s, y - x));
|
||||
}
|
||||
z = pm.mk_polynomial(_z);
|
||||
lits.push_back(mk_eq(s, x - z));
|
||||
|
||||
#define TEST_ON_OFF() \
|
||||
std::cout << "Off "; \
|
||||
ex.set_signed_project(false); \
|
||||
project(s, ex, _x, lits.size()-1, lits.c_ptr()); \
|
||||
std::cout << "On "; \
|
||||
ex.set_signed_project(true); \
|
||||
project(s, ex, _x, lits.size()-1, lits.c_ptr()); \
|
||||
std::cout << "Off "; \
|
||||
ex.set_signed_project(false); \
|
||||
project(s, ex, _x, lits.size(), lits.c_ptr()); \
|
||||
std::cout << "On "; \
|
||||
ex.set_signed_project(true); \
|
||||
project(s, ex, _x, lits.size(), lits.c_ptr()) \
|
||||
|
||||
TEST_ON_OFF();
|
||||
|
||||
lits.reset();
|
||||
polynomial_ref u(pm);
|
||||
u = pm.mk_polynomial(his[1]);
|
||||
for (int i = 0; i < num_lo; ++i) {
|
||||
polynomial_ref y(pm);
|
||||
y = pm.mk_polynomial(los[i]);
|
||||
lits.push_back(mk_gt(s, u*x - y));
|
||||
}
|
||||
for (int i = 0; i < num_hi; ++i) {
|
||||
polynomial_ref y(pm);
|
||||
y = pm.mk_polynomial(his[i]);
|
||||
lits.push_back(mk_gt(s, y - u*x));
|
||||
}
|
||||
z = pm.mk_polynomial(_z);
|
||||
lits.push_back(mk_eq(s, u*x - z));
|
||||
|
||||
TEST_ON_OFF();
|
||||
|
||||
lits.reset();
|
||||
u = pm.mk_polynomial(los[1]);
|
||||
for (int i = 0; i < num_lo; ++i) {
|
||||
polynomial_ref y(pm);
|
||||
y = pm.mk_polynomial(los[i]);
|
||||
lits.push_back(mk_gt(s, u*x - y));
|
||||
}
|
||||
for (int i = 0; i < num_hi; ++i) {
|
||||
polynomial_ref y(pm);
|
||||
y = pm.mk_polynomial(his[i]);
|
||||
lits.push_back(mk_gt(s, y - u*x));
|
||||
}
|
||||
z = pm.mk_polynomial(_z);
|
||||
lits.push_back(mk_eq(s, x - z));
|
||||
|
||||
TEST_ON_OFF();
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
static void test_root_literal(nlsat::solver& s, nlsat::explain& ex, nlsat::var x, nlsat::atom::kind k, unsigned i, nlsat::poly* p) {
|
||||
nlsat::scoped_literal_vector result(s);
|
||||
ex.test_root_literal(k, x, 1, p, result);
|
||||
nlsat::bool_var b = s.mk_root_atom(k, x, i, p);
|
||||
s.display(std::cout, nlsat::literal(b, false));
|
||||
s.display(std::cout << " ==> ", result.size(), result.c_ptr());
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
static bool satisfies_root(nlsat::solver& s, nlsat::atom::kind k, nlsat::poly* p) {
|
||||
nlsat::pmanager & pm = s.pm();
|
||||
anum_manager & am = s.am();
|
||||
nlsat::assignment as(am);
|
||||
s.get_rvalues(as);
|
||||
polynomial_ref pr(p, pm);
|
||||
switch (k) {
|
||||
case nlsat::atom::ROOT_EQ: return am.eval_sign_at(pr, as) == 0;
|
||||
case nlsat::atom::ROOT_LE: return am.eval_sign_at(pr, as) <= 0;
|
||||
case nlsat::atom::ROOT_LT: return am.eval_sign_at(pr, as) < 0;
|
||||
case nlsat::atom::ROOT_GE: return am.eval_sign_at(pr, as) >= 0;
|
||||
case nlsat::atom::ROOT_GT: return am.eval_sign_at(pr, as) > 0;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void tst10() {
|
||||
params_ref ps;
|
||||
reslimit rlim;
|
||||
nlsat::solver s(rlim, ps);
|
||||
anum_manager & am = s.am();
|
||||
nlsat::pmanager & pm = s.pm();
|
||||
nlsat::assignment as(am);
|
||||
nlsat::explain& ex = s.get_explain();
|
||||
nlsat::var _a = s.mk_var(false);
|
||||
nlsat::var _b = s.mk_var(false);
|
||||
nlsat::var _c = s.mk_var(false);
|
||||
nlsat::var _x = s.mk_var(false);
|
||||
|
||||
polynomial_ref x(pm), a(pm), b(pm), c(pm), p(pm);
|
||||
x = pm.mk_polynomial(_x);
|
||||
a = pm.mk_polynomial(_a);
|
||||
b = pm.mk_polynomial(_b);
|
||||
c = pm.mk_polynomial(_c);
|
||||
p = a*x*x + b*x + c;
|
||||
scoped_anum one(am), two(am), three(am), mone(am), mtwo(am), mthree(am), zero(am), one_a_half(am);
|
||||
am.set(zero, 0);
|
||||
am.set(one, 1);
|
||||
am.set(two, 2);
|
||||
am.set(three, 3);
|
||||
am.set(mone, -1);
|
||||
am.set(mtwo, -2);
|
||||
am.set(mthree, -3);
|
||||
rational oah(1,2);
|
||||
am.set(one_a_half, oah.to_mpq());
|
||||
|
||||
|
||||
scoped_anum_vector nums(am);
|
||||
nums.push_back(one);
|
||||
nums.push_back(two);
|
||||
nums.push_back(one_a_half);
|
||||
nums.push_back(mone);
|
||||
nums.push_back(three);
|
||||
|
||||
// a = 1, b = -3, c = 2:
|
||||
// has roots x = 2, x = 1:
|
||||
// 2^2 - 3*2 + 2 = 0
|
||||
// 1 - 3 + 2 = 0
|
||||
as.set(_a, one);
|
||||
as.set(_b, mthree);
|
||||
as.set(_c, two);
|
||||
|
||||
for (unsigned i = 0; i < nums.size(); ++i) {
|
||||
as.set(_x, nums[i]);
|
||||
s.set_rvalues(as);
|
||||
std::cout << p << "\n";
|
||||
as.display(std::cout);
|
||||
for (unsigned k = nlsat::atom::ROOT_EQ; k <= nlsat::atom::ROOT_GE; ++k) {
|
||||
if (satisfies_root(s, (nlsat::atom::kind) k, p)) {
|
||||
test_root_literal(s, ex, _x, (nlsat::atom::kind) k, 1, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
as.set(_a, mone);
|
||||
as.set(_b, three);
|
||||
as.set(_c, mtwo);
|
||||
for (unsigned i = 0; i < nums.size(); ++i) {
|
||||
as.set(_x, nums[i]);
|
||||
s.set_rvalues(as);
|
||||
std::cout << p << "\n";
|
||||
as.display(std::cout);
|
||||
for (unsigned k = nlsat::atom::ROOT_EQ; k <= nlsat::atom::ROOT_GE; ++k) {
|
||||
if (satisfies_root(s, (nlsat::atom::kind) k, p)) {
|
||||
test_root_literal(s, ex, _x, (nlsat::atom::kind) k, 1, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
void tst_nlsat() {
|
||||
tst10();
|
||||
std::cout << "------------------\n";
|
||||
exit(0);
|
||||
tst9();
|
||||
std::cout << "------------------\n";
|
||||
exit(0);
|
||||
tst8();
|
||||
std::cout << "------------------\n";
|
||||
tst7();
|
||||
std::cout << "------------------\n";
|
||||
tst6();
|
||||
std::cout << "------------------\n";
|
||||
tst5();
|
||||
std::cout << "------------------\n";
|
||||
tst4();
|
||||
std::cout << "------------------\n";
|
||||
tst3();
|
||||
}
|
||||
|
|
|
@ -12,9 +12,9 @@ Copyright (c) 2015 Microsoft Corporation
|
|||
#include "reg_decl_plugins.h"
|
||||
#include "arith_rewriter.h"
|
||||
#include "ast_pp.h"
|
||||
#include "qe_util.h"
|
||||
#include "smt_context.h"
|
||||
#include "expr_abstract.h"
|
||||
#include "expr_safe_replace.h"
|
||||
|
||||
static expr_ref parse_fml(ast_manager& m, char const* str) {
|
||||
expr_ref result(m);
|
||||
|
@ -29,6 +29,11 @@ static expr_ref parse_fml(ast_manager& m, char const* str) {
|
|||
<< "(declare-const t Real)\n"
|
||||
<< "(declare-const a Real)\n"
|
||||
<< "(declare-const b Real)\n"
|
||||
<< "(declare-const i Int)\n"
|
||||
<< "(declare-const j Int)\n"
|
||||
<< "(declare-const k Int)\n"
|
||||
<< "(declare-const l Int)\n"
|
||||
<< "(declare-const m Int)\n"
|
||||
<< "(assert " << str << ")\n";
|
||||
std::istringstream is(buffer.str());
|
||||
VERIFY(parse_smt2_commands(ctx, is));
|
||||
|
@ -42,6 +47,8 @@ static char const* example2 = "(and (<= z x) (<= x 3.0) (<= (* 3.0 x) y) (<= z y
|
|||
static char const* example3 = "(and (<= z x) (<= x 3.0) (< (* 3.0 x) y) (<= z y))";
|
||||
static char const* example4 = "(and (<= z x) (<= x 3.0) (not (>= (* 3.0 x) y)) (<= z y))";
|
||||
static char const* example5 = "(and (<= y x) (<= z x) (<= x u) (<= x v) (<= x t))";
|
||||
static char const* example7 = "(and (<= x y) (<= x z) (<= u x) (< v x))";
|
||||
static char const* example8 = "(and (<= (* 2 i) k) (<= j (* 3 i)))";
|
||||
|
||||
static char const* example6 = "(and (<= 0 (+ x z))\
|
||||
(>= y x) \
|
||||
|
@ -51,30 +58,175 @@ static char const* example6 = "(and (<= 0 (+ x z))\
|
|||
(>= x 0.0)\
|
||||
(<= x 1.0))";
|
||||
|
||||
// phi[M] => result => E x . phi[x]
|
||||
|
||||
static void test(char const *ex) {
|
||||
static void test(app* var, expr_ref& fml) {
|
||||
|
||||
ast_manager& m = fml.get_manager();
|
||||
smt_params params;
|
||||
params.m_model = true;
|
||||
|
||||
symbol x_name(var->get_decl()->get_name());
|
||||
sort* x_sort = m.get_sort(var);
|
||||
|
||||
expr_ref pr(m);
|
||||
expr_ref_vector lits(m);
|
||||
flatten_and(fml, lits);
|
||||
|
||||
model_ref md;
|
||||
{
|
||||
smt::context ctx(m, params);
|
||||
ctx.assert_expr(fml);
|
||||
lbool result = ctx.check();
|
||||
if (result != l_true) return;
|
||||
ctx.get_model(md);
|
||||
}
|
||||
VERIFY(qe::arith_project(*md, var, lits));
|
||||
pr = mk_and(lits);
|
||||
|
||||
std::cout << "original: " << mk_pp(fml, m) << "\n";
|
||||
std::cout << "projected: " << mk_pp(pr, m) << "\n";
|
||||
|
||||
// projection is consistent with model.
|
||||
expr_ref tmp(m);
|
||||
VERIFY(md->eval(pr, tmp) && m.is_true(tmp));
|
||||
|
||||
// projection implies E x. fml
|
||||
{
|
||||
qe::expr_quant_elim qelim(m, params);
|
||||
expr_ref result(m), efml(m);
|
||||
expr* x = var;
|
||||
expr_abstract(m, 0, 1, &x, fml, efml);
|
||||
efml = m.mk_exists(1, &x_sort, &x_name, efml);
|
||||
qelim(m.mk_true(), efml, result);
|
||||
|
||||
smt::context ctx(m, params);
|
||||
ctx.assert_expr(pr);
|
||||
ctx.assert_expr(m.mk_not(result));
|
||||
std::cout << "exists: " << pr << " =>\n" << result << "\n";
|
||||
VERIFY(l_false == ctx.check());
|
||||
}
|
||||
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void testR(char const *ex) {
|
||||
ast_manager m;
|
||||
reg_decl_plugins(m);
|
||||
arith_util a(m);
|
||||
expr_ref fml = parse_fml(m, ex);
|
||||
app_ref_vector vars(m);
|
||||
expr_ref_vector lits(m);
|
||||
vars.push_back(m.mk_const(symbol("x"), a.mk_real()));
|
||||
flatten_and(fml, lits);
|
||||
symbol x_name("x");
|
||||
sort_ref x_sort(a.mk_real(), m);
|
||||
app_ref var(m.mk_const(x_name, x_sort), m);
|
||||
test(var, fml);
|
||||
}
|
||||
|
||||
smt::context ctx(m, params);
|
||||
ctx.assert_expr(fml);
|
||||
lbool result = ctx.check();
|
||||
SASSERT(result == l_true);
|
||||
ref<model> md;
|
||||
ctx.get_model(md);
|
||||
expr_ref pr = qe::arith_project(*md, vars, lits);
|
||||
|
||||
std::cout << mk_pp(fml, m) << "\n";
|
||||
std::cout << mk_pp(pr, m) << "\n";
|
||||
static void testI(char const *ex) {
|
||||
ast_manager m;
|
||||
reg_decl_plugins(m);
|
||||
arith_util a(m);
|
||||
expr_ref fml = parse_fml(m, ex);
|
||||
symbol x_name("i");
|
||||
sort_ref x_sort(a.mk_int(), m);
|
||||
app_ref var(m.mk_const(x_name, x_sort), m);
|
||||
test(var, fml);
|
||||
}
|
||||
|
||||
static expr_ref_vector mk_ineqs(app* x, app* y, app_ref_vector const& nums) {
|
||||
ast_manager& m = nums.get_manager();
|
||||
arith_util a(m);
|
||||
expr_ref_vector result(m);
|
||||
for (unsigned i = 0; i < nums.size(); ++i) {
|
||||
expr_ref ax(a.mk_mul(nums[i], x), m);
|
||||
result.push_back(a.mk_le(ax, y));
|
||||
result.push_back(m.mk_not(a.mk_ge(ax, y)));
|
||||
result.push_back(m.mk_not(a.mk_gt(y, ax)));
|
||||
result.push_back(a.mk_lt(y, ax));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static app_ref generate_ineqs(ast_manager& m, sort* s, vector<expr_ref_vector>& cs, bool mods_too) {
|
||||
arith_util a(m);
|
||||
app_ref_vector vars(m), nums(m);
|
||||
vars.push_back(m.mk_const(symbol("x"), s));
|
||||
vars.push_back(m.mk_const(symbol("y"), s));
|
||||
vars.push_back(m.mk_const(symbol("z"), s));
|
||||
vars.push_back(m.mk_const(symbol("u"), s));
|
||||
vars.push_back(m.mk_const(symbol("v"), s));
|
||||
vars.push_back(m.mk_const(symbol("w"), s));
|
||||
nums.push_back(a.mk_numeral(rational(1), s));
|
||||
nums.push_back(a.mk_numeral(rational(2), s));
|
||||
nums.push_back(a.mk_numeral(rational(3), s));
|
||||
|
||||
app* x = vars[0].get();
|
||||
app* y = vars[1].get();
|
||||
app* z = vars[2].get();
|
||||
//
|
||||
// ax <= by, ax < by, not (ax >= by), not (ax > by)
|
||||
//
|
||||
cs.push_back(mk_ineqs(x, vars[1].get(), nums));
|
||||
cs.push_back(mk_ineqs(x, vars[2].get(), nums));
|
||||
cs.push_back(mk_ineqs(x, vars[3].get(), nums));
|
||||
cs.push_back(mk_ineqs(x, vars[4].get(), nums));
|
||||
cs.push_back(mk_ineqs(x, vars[5].get(), nums));
|
||||
|
||||
if (mods_too) {
|
||||
expr_ref_vector mods(m);
|
||||
expr_ref zero(a.mk_numeral(rational(0), s), m);
|
||||
mods.push_back(m.mk_true());
|
||||
for (unsigned j = 0; j < nums.size(); ++j) {
|
||||
mods.push_back(m.mk_eq(a.mk_mod(a.mk_add(a.mk_mul(nums[j].get(),x), y), nums[1].get()), zero));
|
||||
}
|
||||
cs.push_back(mods);
|
||||
mods.resize(1);
|
||||
for (unsigned j = 0; j < nums.size(); ++j) {
|
||||
mods.push_back(m.mk_eq(a.mk_mod(a.mk_add(a.mk_mul(nums[j].get(),x), y), nums[2].get()), zero));
|
||||
}
|
||||
cs.push_back(mods);
|
||||
}
|
||||
return app_ref(x, m);
|
||||
}
|
||||
|
||||
|
||||
static void test_c(app* x, expr_ref_vector const& c) {
|
||||
ast_manager& m = c.get_manager();
|
||||
expr_ref fml(m);
|
||||
fml = m.mk_and(c.size(), c.c_ptr());
|
||||
test(x, fml);
|
||||
}
|
||||
|
||||
static void test_cs(app* x, expr_ref_vector& c, vector<expr_ref_vector> const& cs) {
|
||||
if (c.size() == cs.size()) {
|
||||
test_c(x, c);
|
||||
return;
|
||||
}
|
||||
expr_ref_vector const& c1 = cs[c.size()];
|
||||
for (unsigned i = 0; i < c1.size(); ++i) {
|
||||
c.push_back(c1[i]);
|
||||
test_cs(x, c, cs);
|
||||
c.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void test_ineqs(ast_manager& m, sort* s, bool mods_too) {
|
||||
vector<expr_ref_vector> ineqs;
|
||||
app_ref x = generate_ineqs(m, s, ineqs, mods_too);
|
||||
expr_ref_vector cs(m);
|
||||
test_cs(x, cs, ineqs);
|
||||
}
|
||||
|
||||
static void test_ineqs() {
|
||||
ast_manager m;
|
||||
reg_decl_plugins(m);
|
||||
arith_util a(m);
|
||||
sort* s_int = a.mk_int();
|
||||
sort* s_real = a.mk_real();
|
||||
test_ineqs(m, s_int, true);
|
||||
test_ineqs(m, s_real, false);
|
||||
}
|
||||
|
||||
static void test2(char const *ex) {
|
||||
|
@ -102,7 +254,7 @@ static void test2(char const *ex) {
|
|||
|
||||
std::cout << mk_pp(fml, m) << "\n";
|
||||
|
||||
expr_ref pr2(m), fml2(m);
|
||||
expr_ref pr1(m), pr2(m), fml2(m);
|
||||
expr_ref_vector bound(m);
|
||||
ptr_vector<sort> sorts;
|
||||
svector<symbol> names;
|
||||
|
@ -114,7 +266,10 @@ static void test2(char const *ex) {
|
|||
expr_abstract(m, 0, bound.size(), bound.c_ptr(), fml, fml2);
|
||||
fml2 = m.mk_exists(bound.size(), sorts.c_ptr(), names.c_ptr(), fml2);
|
||||
qe::expr_quant_elim qe(m, params);
|
||||
expr_ref pr1 = qe::arith_project(*md, vars, lits);
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
VERIFY(qe::arith_project(*md, vars[i].get(), lits));
|
||||
}
|
||||
pr1 = mk_and(lits);
|
||||
qe(m.mk_true(), fml2, pr2);
|
||||
std::cout << mk_pp(pr1, m) << "\n";
|
||||
std::cout << mk_pp(pr2, m) << "\n";
|
||||
|
@ -131,11 +286,17 @@ static void test2(char const *ex) {
|
|||
}
|
||||
|
||||
void tst_qe_arith() {
|
||||
// enable_trace("qe");
|
||||
testI(example8);
|
||||
testR(example7);
|
||||
test_ineqs();
|
||||
return;
|
||||
testR(example1);
|
||||
testR(example2);
|
||||
testR(example3);
|
||||
testR(example4);
|
||||
testR(example5);
|
||||
return;
|
||||
test2(example6);
|
||||
return;
|
||||
test(example1);
|
||||
test(example2);
|
||||
test(example3);
|
||||
test(example4);
|
||||
test(example5);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue