mirror of
https://github.com/Z3Prover/z3
synced 2025-04-28 03:15:50 +00:00
checkpoint
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
4722fdfca5
commit
add684d8e9
377 changed files with 204 additions and 62 deletions
419
src/smt/smt_justification.cpp
Normal file
419
src/smt/smt_justification.cpp
Normal file
|
@ -0,0 +1,419 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
smt_justification.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-25.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"smt_context.h"
|
||||
#include"smt_conflict_resolution.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
|
||||
justification_proof_wrapper::justification_proof_wrapper(context & ctx, proof * pr, bool in_region):
|
||||
justification(in_region),
|
||||
m_proof(pr) {
|
||||
ctx.get_manager().inc_ref(pr);
|
||||
}
|
||||
|
||||
void justification_proof_wrapper::del_eh(ast_manager & m) {
|
||||
m.dec_ref(m_proof);
|
||||
}
|
||||
|
||||
proof * justification_proof_wrapper::mk_proof(conflict_resolution & cr) {
|
||||
return m_proof;
|
||||
}
|
||||
|
||||
unit_resolution_justification::unit_resolution_justification(region & r,
|
||||
justification * js,
|
||||
unsigned num_lits,
|
||||
literal const * lits):
|
||||
m_antecedent(js),
|
||||
m_num_literals(num_lits) {
|
||||
SASSERT(!js || js->in_region());
|
||||
m_literals = new (r) literal[num_lits];
|
||||
memcpy(m_literals, lits, sizeof(literal) * num_lits);
|
||||
TRACE("unit_resolution_justification_bug",
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
tout << lits[i] << " ";
|
||||
}
|
||||
tout << "\n";);
|
||||
}
|
||||
|
||||
unit_resolution_justification::unit_resolution_justification(justification * js,
|
||||
unsigned num_lits,
|
||||
literal const * lits):
|
||||
justification(false), // object is not allocated in a region
|
||||
m_antecedent(js),
|
||||
m_num_literals(num_lits) {
|
||||
SASSERT(!js || !js->in_region());
|
||||
m_literals = alloc_vect<literal>(num_lits);
|
||||
memcpy(m_literals, lits, sizeof(literal) * num_lits);
|
||||
TRACE("unit_resolution_justification_bug",
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
tout << lits[i] << " ";
|
||||
}
|
||||
tout << "\n";);
|
||||
}
|
||||
|
||||
unit_resolution_justification::~unit_resolution_justification() {
|
||||
if (!in_region()) {
|
||||
dealloc_svect(m_literals); // I don't need to invoke destructor...
|
||||
dealloc(m_antecedent);
|
||||
}
|
||||
}
|
||||
|
||||
void unit_resolution_justification::get_antecedents(conflict_resolution & cr) {
|
||||
if (m_antecedent)
|
||||
cr.mark_justification(m_antecedent);
|
||||
for (unsigned i = 0; i < m_num_literals; i++)
|
||||
cr.mark_literal(m_literals[i]);
|
||||
}
|
||||
|
||||
proof * unit_resolution_justification::mk_proof(conflict_resolution & cr) {
|
||||
SASSERT(m_antecedent);
|
||||
ptr_buffer<proof> prs;
|
||||
proof * pr = cr.get_proof(m_antecedent);
|
||||
bool visited = pr != 0;
|
||||
prs.push_back(pr);
|
||||
for (unsigned i = 0; i < m_num_literals; i++) {
|
||||
proof * pr = cr.get_proof(m_literals[i]);
|
||||
if (pr == 0)
|
||||
visited = false;
|
||||
else
|
||||
prs.push_back(pr);
|
||||
}
|
||||
if (!visited)
|
||||
return 0;
|
||||
ast_manager & m = cr.get_manager();
|
||||
TRACE("unit_resolution_justification_bug",
|
||||
tout << "in mk_proof\n";
|
||||
for (unsigned i = 0; i < m_num_literals; i++) {
|
||||
tout << m_literals[i] << " ";
|
||||
}
|
||||
tout << "\n";
|
||||
for (unsigned i = 0; i < prs.size(); i++) {
|
||||
tout << mk_ll_pp(m.get_fact(prs[i]), m);
|
||||
});
|
||||
return m.mk_unit_resolution(prs.size(), prs.c_ptr());
|
||||
}
|
||||
|
||||
void eq_conflict_justification::get_antecedents(conflict_resolution & cr) {
|
||||
SASSERT(m_node1->get_root()->is_interpreted());
|
||||
SASSERT(m_node2->get_root()->is_interpreted());
|
||||
cr.mark_eq(m_node1, m_node1->get_root());
|
||||
cr.mark_eq(m_node2, m_node2->get_root());
|
||||
cr.mark_justified_eq(m_node1, m_node2, m_js);
|
||||
}
|
||||
|
||||
proof * eq_conflict_justification::mk_proof(conflict_resolution & cr) {
|
||||
ast_manager & m = cr.get_manager();
|
||||
bool visited = true;
|
||||
ptr_buffer<proof> prs;
|
||||
|
||||
if (m_node1 != m_node1->get_root()) {
|
||||
proof * pr = cr.get_proof(m_node1, m_node1->get_root());
|
||||
if (pr && m.fine_grain_proofs())
|
||||
pr = m.mk_symmetry(pr);
|
||||
prs.push_back(pr);
|
||||
if (!pr)
|
||||
visited = false;
|
||||
}
|
||||
|
||||
SASSERT(m_node1 != m_node2);
|
||||
proof * pr = cr.get_proof(m_node1, m_node2, m_js);
|
||||
prs.push_back(pr);
|
||||
if (!pr)
|
||||
visited = false;
|
||||
|
||||
if (m_node2 != m_node2->get_root()) {
|
||||
proof * pr = cr.get_proof(m_node2, m_node2->get_root());
|
||||
prs.push_back(pr);
|
||||
if (!pr)
|
||||
visited = false;
|
||||
}
|
||||
|
||||
if (!visited)
|
||||
return 0;
|
||||
|
||||
expr * lhs = m_node1->get_root()->get_owner();
|
||||
expr * rhs = m_node2->get_root()->get_owner();
|
||||
proof * pr1 = m.mk_transitivity(prs.size(), prs.c_ptr(), lhs, rhs);
|
||||
proof * pr2 = m.mk_rewrite(m.mk_eq(lhs, rhs), m.mk_false());
|
||||
return m.mk_modus_ponens(pr1, pr2);
|
||||
}
|
||||
|
||||
void eq_root_propagation_justification::get_antecedents(conflict_resolution & cr) {
|
||||
cr.mark_eq(m_node, m_node->get_root());
|
||||
}
|
||||
|
||||
proof * eq_root_propagation_justification::mk_proof(conflict_resolution & cr) {
|
||||
ast_manager & m = cr.get_manager();
|
||||
expr * var = m_node->get_owner();
|
||||
expr * val = m_node->get_root()->get_owner();
|
||||
SASSERT(m.is_true(val) || m.is_false(val));
|
||||
proof * pr1 = cr.get_proof(m_node, m_node->get_root());
|
||||
if (pr1) {
|
||||
expr * lit;
|
||||
if (m.is_true(val))
|
||||
lit = var;
|
||||
else
|
||||
lit = m.mk_not(var);
|
||||
proof * pr2 = m.mk_rewrite(m.get_fact(pr1), lit);
|
||||
return m.mk_modus_ponens(pr1, pr2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void eq_propagation_justification::get_antecedents(conflict_resolution & cr) {
|
||||
cr.mark_eq(m_node1, m_node2);
|
||||
}
|
||||
|
||||
proof * eq_propagation_justification::mk_proof(conflict_resolution & cr) {
|
||||
return cr.get_proof(m_node1, m_node2);
|
||||
}
|
||||
|
||||
|
||||
void mp_iff_justification::get_antecedents(conflict_resolution & cr) {
|
||||
SASSERT(m_node1 != m_node2);
|
||||
cr.mark_eq(m_node1, m_node2);
|
||||
context & ctx = cr.get_context();
|
||||
bool_var v = ctx.enode2bool_var(m_node1);
|
||||
lbool val = ctx.get_assignment(v);
|
||||
literal l(v, val == l_false);
|
||||
cr.mark_literal(l);
|
||||
}
|
||||
|
||||
proof * mp_iff_justification::mk_proof(conflict_resolution & cr) {
|
||||
proof * pr1 = cr.get_proof(m_node1, m_node2);
|
||||
context & ctx = cr.get_context();
|
||||
bool_var v = ctx.enode2bool_var(m_node1);
|
||||
lbool val = ctx.get_assignment(v);
|
||||
literal l(v, val == l_false);
|
||||
proof * pr2 = cr.get_proof(l);
|
||||
if (pr1 && pr2) {
|
||||
ast_manager & m = cr.get_manager();
|
||||
proof * pr;
|
||||
SASSERT(m.has_fact(pr1));
|
||||
SASSERT(m.has_fact(pr2));
|
||||
app* fact1 = to_app(m.get_fact(pr1));
|
||||
app* fact2 = to_app(m.get_fact(pr2));
|
||||
SASSERT(m.is_iff(fact1));
|
||||
if (fact1->get_arg(1) == fact2) {
|
||||
pr1 = m.mk_symmetry(pr1);
|
||||
fact1 = to_app(m.get_fact(pr1));
|
||||
}
|
||||
SASSERT(m.is_iff(fact1));
|
||||
|
||||
if (l.sign()) {
|
||||
SASSERT(m.is_not(fact2));
|
||||
expr* lhs = fact1->get_arg(0);
|
||||
expr* rhs = fact1->get_arg(1);
|
||||
if (lhs != fact2->get_arg(0)) {
|
||||
pr1 = m.mk_symmetry(pr1);
|
||||
fact1 = to_app(m.get_fact(pr1));
|
||||
std::swap(lhs, rhs);
|
||||
}
|
||||
SASSERT(lhs == fact2->get_arg(0));
|
||||
app* new_lhs = fact2;
|
||||
app* new_rhs = m.mk_not(rhs);
|
||||
pr1 = m.mk_congruence(new_lhs, new_rhs, 1, &pr1);
|
||||
}
|
||||
pr = m.mk_modus_ponens(pr2, pr1);
|
||||
|
||||
TRACE("mp_iff_justification", tout << mk_pp(fact1, m) << "\n" << mk_pp(fact2, m) << "\n" <<
|
||||
mk_pp(m.get_fact(pr), m) << "\n";);
|
||||
return pr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
simple_justification::simple_justification(region & r, unsigned num_lits, literal const * lits):
|
||||
m_num_literals(num_lits) {
|
||||
m_literals = new (r) literal[num_lits];
|
||||
memcpy(m_literals, lits, sizeof(literal) * num_lits);
|
||||
#ifdef Z3DEBUG
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
SASSERT(lits[i] != null_literal);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void simple_justification::get_antecedents(conflict_resolution & cr) {
|
||||
for (unsigned i = 0; i < m_num_literals; i++)
|
||||
cr.mark_literal(m_literals[i]);
|
||||
}
|
||||
|
||||
bool simple_justification::antecedent2proof(conflict_resolution & cr, ptr_buffer<proof> & result) {
|
||||
bool visited = true;
|
||||
for (unsigned i = 0; i < m_num_literals; i++) {
|
||||
proof * pr = cr.get_proof(m_literals[i]);
|
||||
if (pr == 0)
|
||||
visited = false;
|
||||
else
|
||||
result.push_back(pr);
|
||||
}
|
||||
return visited;
|
||||
}
|
||||
|
||||
proof * theory_axiom_justification::mk_proof(conflict_resolution & cr) {
|
||||
context & ctx = cr.get_context();
|
||||
ast_manager & m = cr.get_manager();
|
||||
expr_ref_vector lits(m);
|
||||
for (unsigned i = 0; i < m_num_literals; i++) {
|
||||
expr_ref l(m);
|
||||
ctx.literal2expr(m_literals[i], l);
|
||||
lits.push_back(l);
|
||||
}
|
||||
if (lits.size() == 1)
|
||||
return m.mk_th_lemma(m_th_id, lits.get(0), 0, 0, m_params.size(), m_params.c_ptr());
|
||||
else
|
||||
return m.mk_th_lemma(m_th_id, m.mk_or(lits.size(), lits.c_ptr()), 0, 0, m_params.size(), m_params.c_ptr());
|
||||
}
|
||||
|
||||
proof * theory_propagation_justification::mk_proof(conflict_resolution & cr) {
|
||||
ptr_buffer<proof> prs;
|
||||
if (!antecedent2proof(cr, prs))
|
||||
return 0;
|
||||
context & ctx = cr.get_context();
|
||||
ast_manager & m = cr.get_manager();
|
||||
expr_ref fact(m);
|
||||
ctx.literal2expr(m_consequent, fact);
|
||||
return m.mk_th_lemma(m_th_id, fact, prs.size(), prs.c_ptr(), m_params.size(), m_params.c_ptr());
|
||||
}
|
||||
|
||||
proof * theory_conflict_justification::mk_proof(conflict_resolution & cr) {
|
||||
ptr_buffer<proof> prs;
|
||||
if (!antecedent2proof(cr, prs))
|
||||
return 0;
|
||||
ast_manager & m = cr.get_manager();
|
||||
return m.mk_th_lemma(m_th_id, m.mk_false(), prs.size(), prs.c_ptr(), m_params.size(), m_params.c_ptr());
|
||||
}
|
||||
|
||||
ext_simple_justification::ext_simple_justification(region & r, unsigned num_lits, literal const * lits, unsigned num_eqs, enode_pair const * eqs):
|
||||
simple_justification(r, num_lits, lits),
|
||||
m_num_eqs(num_eqs) {
|
||||
m_eqs = new (r) enode_pair[num_eqs];
|
||||
memcpy(m_eqs, eqs, sizeof(enode_pair) * num_eqs);
|
||||
DEBUG_CODE({
|
||||
for (unsigned i = 0; i < num_eqs; i++) {
|
||||
SASSERT(eqs[i].first->get_root() == eqs[i].second->get_root());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ext_simple_justification::get_antecedents(conflict_resolution & cr) {
|
||||
simple_justification::get_antecedents(cr);
|
||||
for (unsigned i = 0; i < m_num_eqs; i++) {
|
||||
enode_pair const & p = m_eqs[i];
|
||||
cr.mark_eq(p.first, p.second);
|
||||
}
|
||||
}
|
||||
|
||||
bool ext_simple_justification::antecedent2proof(conflict_resolution & cr, ptr_buffer<proof> & result) {
|
||||
bool visited = simple_justification::antecedent2proof(cr, result);
|
||||
for (unsigned i = 0; i < m_num_eqs; i++) {
|
||||
enode_pair const & p = m_eqs[i];
|
||||
proof * pr = cr.get_proof(p.first, p.second);
|
||||
if (pr == 0)
|
||||
visited = false;
|
||||
else
|
||||
result.push_back(pr);
|
||||
}
|
||||
return visited;
|
||||
}
|
||||
|
||||
proof * ext_theory_propagation_justification::mk_proof(conflict_resolution & cr) {
|
||||
ptr_buffer<proof> prs;
|
||||
if (!antecedent2proof(cr, prs))
|
||||
return 0;
|
||||
context & ctx = cr.get_context();
|
||||
ast_manager & m = cr.get_manager();
|
||||
expr_ref fact(m);
|
||||
ctx.literal2expr(m_consequent, fact);
|
||||
return m.mk_th_lemma(m_th_id, fact, prs.size(), prs.c_ptr(), m_params.size(), m_params.c_ptr());
|
||||
}
|
||||
|
||||
proof * ext_theory_conflict_justification::mk_proof(conflict_resolution & cr) {
|
||||
ptr_buffer<proof> prs;
|
||||
if (!antecedent2proof(cr, prs))
|
||||
return 0;
|
||||
ast_manager & m = cr.get_manager();
|
||||
return m.mk_th_lemma(m_th_id, m.mk_false(), prs.size(), prs.c_ptr(), m_params.size(), m_params.c_ptr());
|
||||
}
|
||||
|
||||
proof * ext_theory_eq_propagation_justification::mk_proof(conflict_resolution & cr) {
|
||||
ptr_buffer<proof> prs;
|
||||
if (!antecedent2proof(cr, prs))
|
||||
return 0;
|
||||
ast_manager & m = cr.get_manager();
|
||||
context & ctx = cr.get_context();
|
||||
expr * fact = ctx.mk_eq_atom(m_lhs->get_owner(), m_rhs->get_owner());
|
||||
return m.mk_th_lemma(m_th_id, fact, prs.size(), prs.c_ptr(), m_params.size(), m_params.c_ptr());
|
||||
}
|
||||
|
||||
|
||||
theory_lemma_justification::theory_lemma_justification(family_id fid, context & ctx, unsigned num_lits, literal const * lits,
|
||||
unsigned num_params, parameter* params):
|
||||
justification(false),
|
||||
m_th_id(fid),
|
||||
m_params(num_params, params),
|
||||
m_num_literals(num_lits) {
|
||||
ast_manager & m = ctx.get_manager();
|
||||
m_literals = alloc_svect(expr*, num_lits);
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
bool sign = lits[i].sign();
|
||||
expr * v = ctx.bool_var2expr(lits[i].var());
|
||||
m.inc_ref(v);
|
||||
m_literals[i] = TAG(expr*, v, sign);
|
||||
}
|
||||
SASSERT(!in_region());
|
||||
}
|
||||
|
||||
theory_lemma_justification::~theory_lemma_justification() {
|
||||
SASSERT(!in_region());
|
||||
dealloc_svect(m_literals);
|
||||
}
|
||||
|
||||
void theory_lemma_justification::del_eh(ast_manager & m) {
|
||||
for (unsigned i = 0; i < m_num_literals; i++) {
|
||||
m.dec_ref(UNTAG(expr*, m_literals[i]));
|
||||
}
|
||||
m_params.reset();
|
||||
}
|
||||
|
||||
proof * theory_lemma_justification::mk_proof(conflict_resolution & cr) {
|
||||
ast_manager & m = cr.get_manager();
|
||||
expr_ref_vector lits(m);
|
||||
for (unsigned i = 0; i < m_num_literals; i++) {
|
||||
bool sign = GET_TAG(m_literals[i]) != 0;
|
||||
expr * v = UNTAG(expr*, m_literals[i]);
|
||||
expr_ref l(m);
|
||||
if (sign)
|
||||
l = m.mk_not(v);
|
||||
else
|
||||
l = v;
|
||||
lits.push_back(l);
|
||||
}
|
||||
if (lits.size() == 1)
|
||||
return m.mk_th_lemma(m_th_id, lits.get(0), 0, 0, m_params.size(), m_params.c_ptr());
|
||||
else
|
||||
return m.mk_th_lemma(m_th_id, m.mk_or(lits.size(), lits.c_ptr()), 0, 0, m_params.size(), m_params.c_ptr());
|
||||
}
|
||||
|
||||
};
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue