#include "ast/proofs/proof_checker.h"
#include "ast/ast_ll_pp.h"
#include "ast/reg_decl_plugins.h"
#include "sat/smt/euf_proof_checker.h"
#include <iostream>
void tst_checker1() {
ast_manager m(PGM_ENABLED);
expr_ref a(m);
proof_ref p1(m), p2(m), p3(m), p4(m);
expr_ref_vector side_conditions(m);
a = m.mk_const(symbol("a"), m.mk_bool_sort());
p1 = m.mk_hypothesis(a.get());
p2 = m.mk_hypothesis(m.mk_not(a.get()));
ast_ll_pp(std::cout, m, p1.get());
ast_ll_pp(std::cout, m, p2.get());
proof* proofs[2] = { p1.get(), p2.get() };
p3 = m.mk_unit_resolution(2, proofs);
p4 = m.mk_lemma(p3.get(), a.get());
ast_ll_pp(std::cout, m, p4.get());
proof_checker checker(m);
p4 = m.mk_lemma(p3.get(), m.mk_or(a.get(), m.mk_not(a.get())));
ast_ll_pp(std::cout, m, p4.get());
VERIFY(checker.check(p4.get(), side_conditions));
}
void tst_initializer_list_overloads() {
ast_manager m(PGM_ENABLED);
expr_ref a(m), b(m);
proof_ref p1(m), p2(m), p3(m), p4(m);
expr_ref_vector side_conditions(m);
a = m.mk_const(symbol("a"), m.mk_bool_sort());
b = m.mk_const(symbol("b"), m.mk_bool_sort());
p1 = m.mk_hypothesis(a.get());
p2 = m.mk_hypothesis(m.mk_not(a.get()));
p3 = m.mk_unit_resolution({ p1.get(), p2.get() });
VERIFY(m.get_fact(p3.get()) == m.mk_false());
expr_ref fact(m.mk_or(a.get(), b.get()), m);
proof_ref pa_or_b(m.mk_hypothesis(fact.get()), m);
proof_ref pnot_a(m.mk_hypothesis(m.mk_not(a.get())), m);
p4 = m.mk_unit_resolution({ pa_or_b.get(), pnot_a.get() }, b.get());
VERIFY(m.get_fact(p4.get()) == b.get());
expr_ref c(m);
c = m.mk_const(symbol("c"), m.mk_bool_sort());
proof_ref pr_ab(m.mk_rewrite(a.get(), b.get()), m);
proof_ref pr_bc(m.mk_rewrite(b.get(), c.get()), m);
proof_ref p5(m.mk_transitivity({ pr_ab.get(), pr_bc.get() }), m);
VERIFY(p5.get() != nullptr);
expr* trans_fact = m.get_fact(p5.get());
VERIFY(m.is_eq(trans_fact));
VERIFY(to_app(trans_fact)->get_arg(0) == a.get());
VERIFY(to_app(trans_fact)->get_arg(1) == c.get());
std::cout << "Initializer list overloads test passed!" << std::endl;
}
static void tst_euf_negation() {
ast_manager m;
reg_decl_plugins(m);
euf::theory_checker checker(m);
expr_ref x(m.mk_const(symbol("x"), m.mk_bool_sort()), m);
expr_ref y(m.mk_const(symbol("y"), m.mk_bool_sort()), m);
expr_ref nx(m.mk_not(x), m);
expr_ref eq(m.mk_eq(nx, y), m);
auto check = [&](std::initializer_list<expr*> args) {
expr_ref hint(m.mk_app(symbol("euf"), args.size(), args.begin(), m.mk_proof_sort()), m);
return checker.check(hint);
};
VERIFY(check({m.mk_eq(x, nx)}));
VERIFY(!check({eq, y}));
VERIFY(check({x, eq, y}));
VERIFY(!check({x, eq, m.mk_not(y)}));
VERIFY(check({nx, eq, m.mk_not(y)}));
VERIFY(!check({nx, eq, y}));
}
static void tst_euf_negation_large_classes() {
ast_manager m;
reg_decl_plugins(m);
euf::theory_checker checker(m);
expr_ref x(m.mk_const(symbol("x"), m.mk_bool_sort()), m);
expr_ref nx(m.mk_not(x), m);
expr_ref_vector args(m);
for (unsigned i = 0; i < 16384; ++i) {
expr_ref y(m.mk_fresh_const("y", m.mk_bool_sort()), m);
args.push_back(m.mk_eq(x, y));
args.push_back(m.mk_eq(nx, m.mk_not(y)));
}
expr_ref hint(m.mk_app(symbol("euf"), args.size(), args.data(), m.mk_proof_sort()), m);
VERIFY(!checker.check(hint));
args.push_back(m.mk_false());
hint = m.mk_app(symbol("euf"), args.size(), args.data(), m.mk_proof_sort());
VERIFY(checker.check(hint));
}
static void tst_quant_intro() {
ast_manager m(PGM_ENABLED);
reg_decl_plugins(m);
sort_ref B(m.mk_bool_sort(), m);
sort* Bs = B.get();
func_decl_ref f(m.mk_func_decl(symbol("f"), B, B, func_decl_info()), m);
func_decl_ref g(m.mk_func_decl(symbol("g"), B, B, func_decl_info()), m);
expr_ref var0(m.mk_var(0, B), m);
expr_ref body1(m.mk_app(f, var0.get()), m);
expr_ref body2(m.mk_app(g, var0.get()), m);
symbol xname("x");
proof_checker checker(m);
expr_ref_vector side_conditions(m);
quantifier_ref q1(m.mk_forall(1, &Bs, &xname, body1.get()), m);
quantifier_ref q2(m.mk_forall(1, &Bs, &xname, body2.get()), m);
proof_ref p0(m.mk_rewrite(body1.get(), body2.get()), m);
proof_ref p_bind(m.mk_bind_proof(q1.get(), p0.get()), m);
proof_ref p_qi(m.mk_quant_intro(q1.get(), q2.get(), p_bind.get()), m);
VERIFY(checker.check(p_qi.get(), side_conditions));
}
static void tst_push_quant() {
ast_manager m(PGM_ENABLED);
reg_decl_plugins(m);
sort_ref B(m.mk_bool_sort(), m);
sort* Bs = B.get();
func_decl_ref f(m.mk_func_decl(symbol("f"), B, B, func_decl_info()), m);
func_decl_ref g(m.mk_func_decl(symbol("g"), B, B, func_decl_info()), m);
expr_ref var0(m.mk_var(0, B), m);
expr_ref f0(m.mk_app(f, var0.get()), m);
expr_ref g0(m.mk_app(g, var0.get()), m);
symbol xname("x");
proof_checker checker(m);
expr_ref_vector side_conditions(m);
{
expr_ref body(m.mk_and(f0.get(), g0.get()), m);
quantifier_ref q(m.mk_forall(1, &Bs, &xname, body.get()), m);
quantifier_ref qf(m.mk_forall(1, &Bs, &xname, f0.get()), m);
quantifier_ref qg(m.mk_forall(1, &Bs, &xname, g0.get()), m);
expr_ref result(m.mk_and(qf.get(), qg.get()), m);
proof_ref pr(m.mk_push_quant(q.get(), result.get()), m);
VERIFY(checker.check(pr.get(), side_conditions));
}
{
expr_ref body(m.mk_or(f0.get(), g0.get()), m);
quantifier_ref q(m.mk_exists(1, &Bs, &xname, body.get()), m);
quantifier_ref qf(m.mk_exists(1, &Bs, &xname, f0.get()), m);
quantifier_ref qg(m.mk_exists(1, &Bs, &xname, g0.get()), m);
expr_ref result(m.mk_or(qf.get(), qg.get()), m);
proof_ref pr(m.mk_push_quant(q.get(), result.get()), m);
VERIFY(checker.check(pr.get(), side_conditions));
}
}
static void tst_demodulation() {
ast_manager m(PGM_ENABLED);
reg_decl_plugins(m);
sort_ref B(m.mk_bool_sort(), m);
func_decl_ref f(m.mk_func_decl(symbol("f"), B, B, B, func_decl_info()), m);
func_decl_ref p(m.mk_func_decl(symbol("p"), B, B), m);
expr_ref a(m.mk_const(symbol("a"), B), m);
expr_ref b(m.mk_const(symbol("b"), B), m);
expr_ref c(m.mk_const(symbol("c"), B), m);
expr_ref d(m.mk_const(symbol("d"), B), m);
proof_checker checker(m);
expr_ref_vector side_conditions(m);
{
proof_ref eq_ab(m.mk_rewrite(a.get(), b.get()), m);
expr_ref t1(m.mk_app(p, m.mk_app(f, a.get(), a.get())), m);
expr_ref t2(m.mk_app(p, m.mk_app(f, b.get(), b.get())), m);
proof* eqs[1] = { eq_ab.get() };
proof_ref pr(m.mk_demodulation(t1.get(), t2.get(), 1, eqs), m);
VERIFY(checker.check(pr.get(), side_conditions));
}
{
proof_ref eq_ab(m.mk_rewrite(a.get(), b.get()), m);
proof_ref eq_cd(m.mk_rewrite(c.get(), d.get()), m);
expr_ref t1(m.mk_app(f, a.get(), c.get()), m);
expr_ref t2(m.mk_app(f, b.get(), d.get()), m);
proof* eqs[2] = { eq_ab.get(), eq_cd.get() };
proof_ref pr(m.mk_demodulation(t1.get(), t2.get(), 2, eqs), m);
VERIFY(checker.check(pr.get(), side_conditions));
}
{
expr_ref t1(m.mk_app(p, a.get()), m);
proof_ref pr(m.mk_demodulation(t1.get(), t1.get(), 0, nullptr), m);
VERIFY(checker.check(pr.get(), side_conditions));
}
}
void tst_proof_checker() {
tst_checker1();
tst_initializer_list_overloads();
tst_euf_negation();
tst_euf_negation_large_classes();
tst_quant_intro();
tst_push_quant();
tst_demodulation();
}