3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-10 11:17:07 +00:00
z3/test/quant_solve.cpp
Leonardo de Moura 68269c43a6 other components
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:48:48 -07:00

158 lines
5 KiB
C++

#include "ast.h"
#include "front_end_params.h"
#include "qe.h"
#include "arith_decl_plugin.h"
#include "ast_pp.h"
#include "lbool.h"
#include <sstream>
#include "expr_replacer.h"
#include "smt_solver.h"
static void validate_quant_solution(ast_manager& m, app* x, expr* fml, expr* t, expr* new_fml) {
// verify:
// new_fml <=> fml[t/x]
scoped_ptr<expr_replacer> rep = mk_expr_simp_replacer(m);
expr_substitution sub(m);
sub.insert(x, t);
rep->set_substitution(&sub);
expr_ref fml1(fml, m);
(*rep)(fml1);
expr_ref tmp(m);
tmp = m.mk_not(m.mk_iff(new_fml, fml1));
front_end_params fp;
smt::solver solver(m, fp);
solver.assert_expr(tmp);
lbool res = solver.check();
std::cout << res << "\n";
SASSERT(res == l_false);
}
static void test_quant_solver(ast_manager& m, app* x, expr* fml) {
front_end_params params;
params.m_quant_elim = true;
qe::expr_quant_elim qe(m, params);
expr_ref_vector terms(m);
expr_ref_vector fmls(m);
bool success = qe.solve_for_var(x, fml, terms, fmls);
std::cout << "------------------------\n";
std::cout << mk_pp(fml, m) << "\n";
if (success) {
for (unsigned i = 0; i < terms.size(); ++i) {
std::cout << mk_pp(x, m) << " = " << mk_pp(terms[i].get(), m) << "\n" << mk_pp(fmls[i].get(), m) << "\n";
validate_quant_solution(m, x, fml, terms[i].get(), fmls[i].get());
}
}
else {
std::cout << "failed\n";
}
}
static void test_quant_solver_rec(ast_manager& m, unsigned num_vars, app* const* xs, expr* fml) {
if (num_vars == 0) {
return;
}
front_end_params params;
params.m_quant_elim = true;
qe::expr_quant_elim qe(m, params);
expr_ref_vector fmls(m), ors(m), terms(m);
app* x = xs[0];
bool success = qe.solve_for_var(x, fml, terms, fmls);
std::cout << "------------------------\n";
std::cout << mk_pp(fml, m) << "\n";
if (success) {
for (unsigned i = 0; i < terms.size(); ++i) {
std::cout << mk_pp(x, m) << " = " << mk_pp(terms[i].get(), m) << "\n" << mk_pp(fmls[i].get(), m) << "\n";
validate_quant_solution(m, x, fml, terms[i].get(), fmls[i].get());
ors.reset();
if (m.is_or(fmls[i].get())) {
ors.append(to_app(fmls[i].get())->get_num_args(), to_app(fmls[i].get())->get_args());
}
else {
ors.push_back(fmls[i].get());
}
for (unsigned j = 0; j < ors.size(); ++j) {
test_quant_solver_rec(m, num_vars-1, xs+1, ors[j].get());
}
}
}
else {
std::cout << "failed\n";
}
}
static void test_quant_solve1() {
ast_manager m;
arith_util ar(m);
m.register_decl_plugins();
sort* i = ar.mk_int();
app_ref x(m.mk_const(symbol("x"),i), m);
app_ref y(m.mk_const(symbol("y"),i), m);
app_ref a(m.mk_const(symbol("a"),i), m);
app_ref b(m.mk_const(symbol("b"),i), m);
expr_ref n2(ar.mk_numeral(rational(2), true), m);
expr_ref n3(ar.mk_numeral(rational(3), true), m);
expr_ref n4(ar.mk_numeral(rational(4), true), m);
expr_ref n10(ar.mk_numeral(rational(10), true), m);
expr_ref n20(ar.mk_numeral(rational(20), true), m);
expr_ref x2(ar.mk_mul(n2, x), m);
expr_ref x3(ar.mk_mul(n3, x), m);
expr_ref fml1(m), fml2(m), fml3(m), fml4(m);
expr_ref fml(m), t1(m), t2(m);
fml1 = m.mk_eq(x, a);
fml2 = ar.mk_lt(x, a);
fml3 = ar.mk_gt(x, a);
fml4 = m.mk_and(ar.mk_lt(x, a), ar.mk_lt(x, b));
expr_ref fml5(m.mk_and(ar.mk_gt(x, a), ar.mk_lt(x, b)), m);
expr_ref fml6(ar.mk_le(x, a), m);
expr_ref fml7(ar.mk_ge(x, a), m);
expr_ref fml8(ar.mk_lt(ar.mk_mul(n2, x), a), m);
expr_ref fml9(m.mk_eq(ar.mk_mul(n2, x), a), m);
test_quant_solver(m, x.get(), fml1.get());
test_quant_solver(m, x.get(), fml2.get());
test_quant_solver(m, x.get(), fml3.get());
test_quant_solver(m, x.get(), fml4.get());
test_quant_solver(m, x.get(), fml5.get());
test_quant_solver(m, x.get(), fml6.get());
test_quant_solver(m, x.get(), fml7.get());
test_quant_solver(m, x.get(), fml8.get());
test_quant_solver(m, x.get(), fml9.get());
fml = ar.mk_lt(x2, a); test_quant_solver(m, x.get(), fml.get());
fml = ar.mk_gt(x2, a); test_quant_solver(m, x.get(), fml.get());
fml = ar.mk_le(x2, a); test_quant_solver(m, x.get(), fml.get());
fml = ar.mk_ge(x2, a); test_quant_solver(m, x.get(), fml.get());
fml = m.mk_and(ar.mk_lt(a, ar.mk_mul(n3,x)), ar.mk_lt(ar.mk_mul(n3,x), b));
test_quant_solver(m, x.get(), fml.get());
t1 = ar.mk_sub(ar.mk_mul(n2,y),b);
t2 = ar.mk_add(ar.mk_mul(n3,x),a);
fml1 = ar.mk_le(t1, t2);
t1 = ar.mk_sub(ar.mk_mul(n2,x),a);
t2 = ar.mk_add(ar.mk_mul(n4,y),b);
fml2 = ar.mk_le(t1,t2);
fml = m.mk_and(fml1, fml2);
app* xy[2] = { x.get(), y.get() };
test_quant_solver_rec(m, 2, xy, fml.get());
}
void tst_quant_solve() {
test_quant_solve1();
memory::finalize();
#ifdef _WINDOWS
_CrtDumpMemoryLeaks();
#endif
exit(0);
}