/*++ Copyright (c) 2019 Microsoft Corporation Module Name: smt_clause_proof.cpp Author: Nikolaj Bjorner (nbjorner) 2019-03-15 Revision History: --*/ #include "smt/smt_clause_proof.h" #include "smt/smt_context.h" #include "ast/ast_pp.h" #include "ast/ast_ll_pp.h" namespace smt { clause_proof::clause_proof(context& ctx): ctx(ctx), m(ctx.get_manager()), m_lits(m) {} clause_proof::status clause_proof::kind2st(clause_kind k) { switch (k) { case CLS_AUX: return status::assumption; case CLS_TH_AXIOM: return status::th_assumption; case CLS_LEARNED: return status::lemma; case CLS_TH_LEMMA: return status::th_lemma; default: UNREACHABLE(); return status::lemma; } } proof* clause_proof::justification2proof(justification* j) { return (m.proofs_enabled() && j) ? j->mk_proof(ctx.get_cr()) : nullptr; } void clause_proof::add(clause& c) { if (ctx.get_fparams().m_clause_proof) { justification* j = c.get_justification(); proof_ref pr(justification2proof(j), m); CTRACE("mk_clause", pr.get(), tout << mk_bounded_pp(pr, m, 4) << "\n";); update(c, kind2st(c.get_kind()), pr); } } void clause_proof::add(unsigned n, literal const* lits, clause_kind k, justification* j) { if (ctx.get_fparams().m_clause_proof) { proof_ref pr(justification2proof(j), m); CTRACE("mk_clause", pr.get(), tout << mk_bounded_pp(pr, m, 4) << "\n";); m_lits.reset(); for (unsigned i = 0; i < n; ++i) { m_lits.push_back(ctx.literal2expr(lits[i])); } update(kind2st(k), m_lits, pr); } } void clause_proof::shrink(clause& c, unsigned new_size) { if (ctx.get_fparams().m_clause_proof) { m_lits.reset(); for (unsigned i = 0; i < new_size; ++i) { m_lits.push_back(ctx.literal2expr(c[i])); } update(status::lemma, m_lits, nullptr); for (unsigned i = new_size; i < c.get_num_literals(); ++i) { m_lits.push_back(ctx.literal2expr(c[i])); } update(status::deleted, m_lits, nullptr); } } void clause_proof::add(literal lit, clause_kind k, justification* j) { if (ctx.get_fparams().m_clause_proof) { m_lits.reset(); m_lits.push_back(ctx.literal2expr(lit)); proof* pr = justification2proof(j); update(kind2st(k), m_lits, pr); } } void clause_proof::add(literal lit1, literal lit2, clause_kind k, justification* j) { if (ctx.get_fparams().m_clause_proof) { m_lits.reset(); m_lits.push_back(ctx.literal2expr(lit1)); m_lits.push_back(ctx.literal2expr(lit2)); proof* pr = justification2proof(j); m_trail.push_back(info(kind2st(k), m_lits, pr)); } } void clause_proof::del(clause& c) { update(c, status::deleted, nullptr); } void clause_proof::update(status st, expr_ref_vector& v, proof* p) { TRACE("clause_proof", tout << m_trail.size() << " " << st << " " << v << "\n";); IF_VERBOSE(3, verbose_stream() << st << " " << v << "\n"); m_trail.push_back(info(st, v, p)); } void clause_proof::update(clause& c, status st, proof* p) { if (ctx.get_fparams().m_clause_proof) { m_lits.reset(); for (literal lit : c) { m_lits.push_back(ctx.literal2expr(lit)); } update(st, m_lits, p); } } proof_ref clause_proof::get_proof(bool inconsistent) { TRACE("context", tout << "get-proof " << ctx.get_fparams().m_clause_proof << "\n";); if (!ctx.get_fparams().m_clause_proof) { return proof_ref(m); } proof_ref_vector ps(m); for (auto& info : m_trail) { expr_ref fact = mk_or(info.m_clause); proof* pr = info.m_proof; switch (info.m_status) { case status::assumption: ps.push_back(m.mk_assumption_add(pr, fact)); break; case status::lemma: ps.push_back(m.mk_lemma_add(pr, fact)); break; case status::th_assumption: ps.push_back(m.mk_th_assumption_add(pr, fact)); break; case status::th_lemma: ps.push_back(m.mk_th_lemma_add(pr, fact)); break; case status::deleted: ps.push_back(m.mk_redundant_del(fact)); break; } } if (inconsistent) { ps.push_back(m.mk_false()); } else { ps.push_back(m.mk_const("clause-trail-end", m.mk_bool_sort())); } return proof_ref(m.mk_clause_trail(ps.size(), ps.data()), m); } std::ostream& operator<<(std::ostream& out, clause_proof::status st) { switch (st) { case clause_proof::status::assumption: return out << "asm"; case clause_proof::status::th_assumption: return out << "th_asm"; case clause_proof::status::lemma: return out << "lem"; case clause_proof::status::th_lemma: return out << "th_lem"; case clause_proof::status::deleted: return out << "del"; default: return out << "unkn"; } } };