#include "ast/reg_decl_plugins.h"
#include "ast/ff_decl_plugin.h"
#include "ast/ff/ff_evidence.h"
#include "solver/solver.h"
#include "sat/smt/euf_proof_checker.h"
#include "model/model.h"
#include "tactic/user_propagator_base.h"
#include "util/debug.h"
void tst_ff_euf() {
ast_manager m;
reg_decl_plugins(m);
ff_util ff(m);
sort_ref field(ff.mk_sort(rational(7)), m);
expr_ref x(m.mk_const("x", field), m), square(ff.mk_mul(x, x), m);
expr_ref one(ff.mk_numeral(rational(1), field), m), six(ff.mk_numeral(rational(6), field), m);
params_ref p;
p.set_bool("smt", true);
p.set_bool("euf", true);
p.set_bool("smt.proof.check", true);
scoped_ptr<solver> s = mk_smt2_solver(m, p);
expr_ref_vector proofs(m);
unsigned count = 0;
user_propagator::on_clause_eh_t callback = [&](void *, expr *proof, unsigned, unsigned const *, unsigned,
expr *const *) {
if (!is_app(proof) || to_app(proof)->get_name() != symbol("ff-pac"))
return;
ENSURE(ff::check_refutation(m, to_app(proof)));
proofs.push_back(proof);
++count;
};
s->register_on_clause(nullptr, callback);
expr_ref root(m.mk_eq(square, one), m);
s->assert_expr(root);
for (unsigned i = 0; i < 8; ++i) {
ENSURE(s->check_sat() == l_true);
model_ref model;
s->get_model(model);
expr_ref value(m);
ENSURE(model->eval_expr(root, value, true) && m.is_true(value));
s->push();
expr_ref positive(m.mk_not(m.mk_eq(x, one)), m);
expr_ref negative(m.mk_not(m.mk_eq(x, six)), m);
s->assert_expr(positive);
s->assert_expr(negative);
ENSURE(s->check_sat() == l_false);
s->pop(1);
ENSURE(s->check_sat() == l_true);
expr *assumptions[] = {positive, negative};
ENSURE(s->check_sat(2, assumptions) == l_false);
}
ENSURE(count > 0);
euf::smt_proof_checker rejecting(m, p);
app_ref malformed(m.mk_const("ff-pac", m.mk_proof_sort()), m);
expr_ref_vector tautology(m);
tautology.push_back(m.mk_true());
bool rejected = false;
try { rejecting.infer(tautology, malformed); }
catch (default_exception const&) { rejected = true; }
ENSURE(rejected);
for (expr *proof : proofs)
ENSURE(ff::check_refutation(m, to_app(proof)));
}