mirror of
https://github.com/Z3Prover/z3
synced 2025-04-29 11:55:51 +00:00
wip - updates to proof logging and self-checking
move self-checking functionality to inside sat/smt so it can be used on-line and not just off-line. when self-validation fails, use vs, not clause, to check. It allows self-validation without checking and maintaining RUP validation. new options sat.smt.proof.check_rup, sat.smt.proof.check for online validation. z3 sat.smt.proof.check=true sat.euf=true /v:1 sat.smt.proof.check_rup=true /st file.smt2 sat.smt.proof=p.smt2
This commit is contained in:
parent
993ff40826
commit
ac1552d194
40 changed files with 539 additions and 419 deletions
|
@ -27,13 +27,12 @@ namespace euf {
|
|||
get_drat().add_theory(m.get_basic_family_id(), symbol("bool"));
|
||||
}
|
||||
if (!m_proof_out && s().get_config().m_drat &&
|
||||
(get_config().m_lemmas2console || s().get_config().m_smt_proof.is_non_empty_string())) {
|
||||
(get_config().m_lemmas2console ||
|
||||
s().get_config().m_smt_proof_check ||
|
||||
s().get_config().m_smt_proof.is_non_empty_string())) {
|
||||
TRACE("euf", tout << "init-proof " << s().get_config().m_smt_proof << "\n");
|
||||
m_proof_out = alloc(std::ofstream, s().get_config().m_smt_proof.str(), std::ios_base::out);
|
||||
if (get_config().m_lemmas2console)
|
||||
get_drat().set_clause_eh(*this);
|
||||
if (s().get_config().m_smt_proof.is_non_empty_string())
|
||||
get_drat().set_clause_eh(*this);
|
||||
get_drat().set_clause_eh(*this);
|
||||
}
|
||||
m_proof_initialized = true;
|
||||
}
|
||||
|
@ -90,6 +89,46 @@ namespace euf {
|
|||
return new (get_region()) eq_proof_hint(m_lit_head, m_lit_tail, m_cc_head, m_cc_tail);
|
||||
}
|
||||
|
||||
th_proof_hint* solver::mk_cc_proof_hint(sat::literal_vector const& ante, app* a, app* b) {
|
||||
if (!use_drat())
|
||||
return nullptr;
|
||||
SASSERT(a->get_decl() == b->get_decl());
|
||||
push(value_trail(m_lit_tail));
|
||||
push(value_trail(m_cc_tail));
|
||||
push(restore_size_trail(m_proof_literals));
|
||||
push(restore_size_trail(m_explain_cc, m_explain_cc.size()));
|
||||
|
||||
for (auto lit : ante)
|
||||
m_proof_literals.push_back(~lit);
|
||||
|
||||
m_explain_cc.push_back({a, b, 0, false});
|
||||
|
||||
m_lit_head = m_lit_tail;
|
||||
m_cc_head = m_cc_tail;
|
||||
m_lit_tail = m_proof_literals.size();
|
||||
m_cc_tail = m_explain_cc.size();
|
||||
return new (get_region()) eq_proof_hint(m_lit_head, m_lit_tail, m_cc_head, m_cc_tail);
|
||||
}
|
||||
|
||||
th_proof_hint* solver::mk_tc_proof_hint(sat::literal const* clause) {
|
||||
if (!use_drat())
|
||||
return nullptr;
|
||||
push(value_trail(m_lit_tail));
|
||||
push(value_trail(m_cc_tail));
|
||||
push(restore_size_trail(m_proof_literals));
|
||||
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
m_proof_literals.push_back(~clause[i]);
|
||||
|
||||
|
||||
m_lit_head = m_lit_tail;
|
||||
m_cc_head = m_cc_tail;
|
||||
m_lit_tail = m_proof_literals.size();
|
||||
m_cc_tail = m_explain_cc.size();
|
||||
return new (get_region()) eq_proof_hint(m_lit_head, m_lit_tail, m_cc_head, m_cc_tail);
|
||||
}
|
||||
|
||||
|
||||
expr* eq_proof_hint::get_hint(euf::solver& s) const {
|
||||
ast_manager& m = s.get_manager();
|
||||
func_decl_ref cc(m), cc_comm(m);
|
||||
|
@ -118,7 +157,7 @@ namespace euf {
|
|||
std::sort(s.m_explain_cc.data() + m_cc_head, s.m_explain_cc.data() + m_cc_tail, compare_ts);
|
||||
for (unsigned i = m_cc_head; i < m_cc_tail; ++i) {
|
||||
auto const& [a, b, ts, comm] = s.m_explain_cc[i];
|
||||
args.push_back(cc_proof(comm, m.mk_eq(a->get_expr(), b->get_expr())));
|
||||
args.push_back(cc_proof(comm, m.mk_eq(a, b)));
|
||||
}
|
||||
for (auto * arg : args)
|
||||
sorts.push_back(arg->get_sort());
|
||||
|
@ -126,6 +165,8 @@ namespace euf {
|
|||
func_decl* f = m.mk_func_decl(symbol("euf"), sorts.size(), sorts.data(), proof);
|
||||
return m.mk_app(f, args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
smt_proof_hint* solver::mk_smt_hint(symbol const& n, unsigned nl, literal const* lits, unsigned ne, expr_pair const* eqs, unsigned nd, expr_pair const* deqs) {
|
||||
if (!use_drat())
|
||||
|
@ -134,8 +175,14 @@ namespace euf {
|
|||
push(restore_size_trail(m_proof_literals));
|
||||
|
||||
for (unsigned i = 0; i < nl; ++i)
|
||||
if (sat::null_literal != lits[i])
|
||||
if (sat::null_literal != lits[i]) {
|
||||
if (!literal2expr(lits[i]))
|
||||
IF_VERBOSE(0, verbose_stream() << lits[i] << "\n"; display(verbose_stream()));
|
||||
|
||||
|
||||
SASSERT(literal2expr(lits[i]));
|
||||
m_proof_literals.push_back(lits[i]);
|
||||
}
|
||||
|
||||
push(value_trail(m_eq_tail));
|
||||
push(restore_size_trail(m_proof_eqs));
|
||||
|
@ -231,6 +278,7 @@ namespace euf {
|
|||
TRACE("euf", tout << "on-clause " << n << "\n");
|
||||
on_lemma(n, lits, st);
|
||||
on_proof(n, lits, st);
|
||||
on_check(n, lits, st);
|
||||
}
|
||||
|
||||
void solver::on_proof(unsigned n, literal const* lits, sat::status st) {
|
||||
|
@ -252,6 +300,21 @@ namespace euf {
|
|||
UNREACHABLE();
|
||||
out.flush();
|
||||
}
|
||||
|
||||
void solver::on_check(unsigned n, literal const* lits, sat::status st) {
|
||||
if (!s().get_config().m_smt_proof_check)
|
||||
return;
|
||||
expr_ref_vector clause(m);
|
||||
for (unsigned i = 0; i < n; ++i)
|
||||
clause.push_back(literal2expr(lits[i]));
|
||||
auto hint = status2proof_hint(st);
|
||||
if (st.is_asserted() || st.is_redundant())
|
||||
m_smt_proof_checker.infer(clause, hint);
|
||||
else if (st.is_deleted())
|
||||
m_smt_proof_checker.del(clause);
|
||||
else if (st.is_input())
|
||||
m_smt_proof_checker.assume(clause);
|
||||
}
|
||||
|
||||
void solver::on_lemma(unsigned n, literal const* lits, sat::status st) {
|
||||
if (!get_config().m_lemmas2console)
|
||||
|
@ -320,21 +383,21 @@ namespace euf {
|
|||
if (proof_hint)
|
||||
return display_expr(out << " ", proof_hint);
|
||||
else
|
||||
return out;
|
||||
return out;
|
||||
}
|
||||
|
||||
expr_ref solver::status2proof_hint(sat::status st) {
|
||||
app_ref solver::status2proof_hint(sat::status st) {
|
||||
if (st.is_sat())
|
||||
return expr_ref(m.mk_const("rup", m.mk_proof_sort()), m); // provable by reverse unit propagation
|
||||
return app_ref(m.mk_const("rup", m.mk_proof_sort()), m); // provable by reverse unit propagation
|
||||
auto* h = reinterpret_cast<euf::th_proof_hint const*>(st.get_hint());
|
||||
if (!h)
|
||||
return expr_ref(m);
|
||||
return app_ref(m);
|
||||
|
||||
expr* e = h->get_hint(*this);
|
||||
if (e)
|
||||
return expr_ref(e, m);
|
||||
return app_ref(to_app(e), m);
|
||||
|
||||
return expr_ref(m);
|
||||
return app_ref(m);
|
||||
}
|
||||
|
||||
std::ostream& solver::display_literals(std::ostream& out, unsigned n, literal const* lits) {
|
||||
|
@ -345,6 +408,7 @@ namespace euf {
|
|||
k = m.mk_const(symbol(lits[i].var()), m.mk_bool_sort());
|
||||
e = k;
|
||||
}
|
||||
SASSERT(e);
|
||||
if (lits[i].sign())
|
||||
display_expr(out << " (not ", e) << ")";
|
||||
else
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue