z3-z3-4.13.0.src.muz.base.dl_boogie_proof.cpp Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
/**
Example from Boogie:
(derivation
(step s!4 (main_loop_LoopHead true true)
rule!3 (subst
(= assertsPassed@@1 true)
(= assertsPassed@2@@0 true)
(= main_loop_LoopHead_assertsPassed true)
)
(labels @950 +895 +668 +670 +893 +899 )
(ref true ))
(step s!3 (main true false)
rule!1 (subst
(= assertsPassed true)
(= assertsPassed@0 true)
(= assertsPassed@2 false)
(= main_assertsPassed false)
)
(labels @839 +763 +547 +546 +761 +544 +545 +si_fcall_805 +681 +768 )
(ref s!4 ))
(step s!2 (main_SeqInstr true false)
rule!2 (subst
(= assertsPassed@@0 true)
(= assertsPassed@0@@0 false)
(= main_SeqInstr_assertsPassed false)
)
(labels @890 +851 +572 +si_fcall_883 +853 )
(ref s!3 ))
(step s!1 (@Fail!0)
rule!4 (subst
(= assertsPassed@@2 true)
(= main_SeqInstr_assertsPassed@@0 false)
)
(labels )
(ref s!2 ))
)
(model
"tickleBool -> {
true -> true
false -> true
else -> true
}
")
*/
#include "muz/base/dl_boogie_proof.h"
#include "model/model_pp.h"
#include "ast/proofs/proof_utils.h"
#include "ast/ast_pp.h"
#include "ast/ast_util.h"
namespace datalog {
/**
\brief push hyper-resolution steps upwards such that every use of
hyper-resolution uses a premise that is not derived from hyper-resolution.
perform the following rewrite:
hr(hr(p1,p2,p3,..),p4,p5) => hr(p1,hr(p2,p4),p3,..,p5)
*/
void mk_input_resolution(proof_ref& pr) {
ast_manager& m = pr.get_manager();
proof_ref pr1(m);
proof_ref_vector premises1(m), premises2(m), premises(m);
expr_ref conclusion1(m), conclusion2(m), conclusion(m);
svector > positions1, positions2, positions;
vector substs1, substs2, substs;
if (m.is_hyper_resolve(pr, premises1, conclusion1, positions1, substs1) &&
m.is_hyper_resolve(premises1[0].get(), premises, conclusion2, positions, substs2)) {
for (unsigned i = 1; i < premises1.size(); ++i) {
pr1 = premises1[i].get();
mk_input_resolution(pr1);
premises1[i] = pr1;
}
for (unsigned i = 0; i < premises.size(); ++i) {
pr1 = premises[i].get();
mk_input_resolution(pr1);
premises[i] = pr1;
}
unsigned sz = premises.size();
for (unsigned i = 1; i < sz; ++i) {
proof* premise = premises[i].get();
expr_ref_vector literals(m);
expr* l1, *l2;
if (!m.is_implies(premise, l1, l2)) {
continue;
}
flatten_and(l1, literals);
positions2.reset();
premises2.reset();
premises2.push_back(premise);
substs2.reset();
for (unsigned j = 0; j < literals.size(); ++j) {
expr* lit = literals[j].get();
for (unsigned k = 1; k < premises1.size(); ++k) {
if (m.get_fact(premises1[k].get()) == lit) {
premises2.push_back(premises1[k].get());
positions2.push_back(std::make_pair(j+1,0));
substs2.push_back(expr_ref_vector(m));
break;
}
}
}
premises[i] = m.mk_hyper_resolve(premises2.size(), premises2.data(), l2, positions2, substs2);
}
conclusion = conclusion1;
pr = m.mk_hyper_resolve(premises.size(), premises.data(), conclusion, positions, substs);
}
}
void boogie_proof::set_proof(proof* p) {
//std::cout << "set proof\n";
m_proof = p;
proof_utils::push_instantiations_up(m_proof);
mk_input_resolution(m_proof);
//std::cout << "proof set\n";
}
void boogie_proof::set_model(model* m) {
m_model = m;
}
void boogie_proof::pp(std::ostream& out) {
if (m_proof) {
pp_proof(out);
}
if (m_model) {
model_pp(out, *m_model);
}
}
void boogie_proof::pp_proof(std::ostream& out) {
vector steps;
ptr_vector rules;
rules.push_back(m_proof);
steps.push_back(step());
obj_map index;
index.insert(m_proof, 0);
for (unsigned j = 0; j < rules.size(); ++j) {
proof* p = rules[j];
proof_ref_vector premises(m);
expr_ref conclusion(m);
svector > positions;
vector substs;
expr* tmp;
steps[j].m_fact = m.get_fact(p);
m.is_implies(steps[j].m_fact, tmp, steps[j].m_fact);
get_subst(p, steps[j].m_subst);
get_labels(p, steps[j].m_labels);
if (m.is_hyper_resolve(p, premises, conclusion, positions, substs)) {
for (unsigned i = 1; i < premises.size(); ++i) {
proof* premise = premises[i].get();
unsigned position = 0;
if (!index.find(premise, position)) {
position = rules.size();
rules.push_back(premise);
steps.push_back(step());
index.insert(premise, position);
}
steps[j].m_refs.push_back(position);
}
get_rule_name(premises[0].get(), steps[j].m_rule_name);
}
}
for (unsigned j = steps.size(); j > 0; ) {
--j;
step &s = steps[j];
// TBD
// s.m_labels;
// set references, compensate for reverse ordering.
for (unsigned i = 0; i < s.m_refs.size(); ++i) {
s.m_refs[i] = rules.size()-1-s.m_refs[i];
}
}
steps.reverse();
pp_steps(out, steps);
}
/**
\brief extract the instantiation by searching for the first occurrence of a hyper-resolution
rule that produces an instance.
*/
void boogie_proof::get_subst(proof* p, subst& s) {
ptr_vector todo;
todo.push_back(p);
ast_mark visited;
//std::cout << "get_subst\n" << mk_pp(p, m) << "\n";
while (!todo.empty()) {
proof* p = todo.back();
todo.pop_back();
if (visited.is_marked(p)) {
continue;
}
visited.mark(p, true);
proof_ref_vector premises(m);
expr_ref conclusion(m);
svector > positions;
vector substs;
if (m.is_hyper_resolve(p, premises, conclusion, positions, substs)) {
expr_ref_vector const& sub = substs[0];
if (!sub.empty()) {
quantifier* q = to_quantifier(m.get_fact(premises[0].get()));
unsigned sz = sub.size();
SASSERT(sz == q->get_num_decls());
for (unsigned i = 0; i < sz; ++i) {
s.push_back(std::make_pair(q->get_decl_name(sz-1-i), sub[i]));
}
return;
}
}
unsigned sz = m.get_num_parents(p);
for (unsigned i = 0; i < sz; ++i) {
todo.push_back(m.get_parent(p, i));
}
}
}
void boogie_proof::get_rule_name(proof* p, symbol& n) {
}
void boogie_proof::get_labels(proof* p, labels& lbls) {
}
void boogie_proof::pp_steps(std::ostream& out, vector& steps) {
out << "(derivation\n";
for (unsigned i = 0; i < steps.size(); ++i) {
pp_step(out, i, steps[i]);
}
out << ")\n";
}
// step :: "(" "step" step-name fact rule-name subst labels premises ")"
void boogie_proof::pp_step(std::ostream& out, unsigned id, step& s) {
out << "(step\n";
out << " s!" << id << " ";
pp_fact(out, s.m_fact);
out << " " << s.m_rule_name << "\n";
pp_subst(out << " ", s.m_subst);
pp_labels(out << " ", s.m_labels);
pp_premises(out << " ", s.m_refs);
out << ")\n";
}
// fact :: "(" predicate theory-term* ")"
void boogie_proof::pp_fact(std::ostream& out, expr* fact) {
out << mk_pp(fact, m) << "\n";
}
// subst :: "(" "subst" assignment* ")"
void boogie_proof::pp_subst(std::ostream& out, subst& s) {
out << "(subst";
for (unsigned i = 0; i < s.size(); ++i) {
pp_assignment(out, s[i].first, s[i].second);
}
out << ")\n";
}
// assignment :: "(" "=" variable theory-term ")"
void boogie_proof::pp_assignment(std::ostream& out, symbol const& v, expr* t) {
out << "\n (= " << v << " " << mk_pp(t, m) << ")";
}
// labels :: "(" "labels" label* ")"
void boogie_proof::pp_labels(std::ostream& out, labels& lbls) {
out << "(labels";
for (unsigned i = 0; i < lbls.size(); ++i) {
out << " " << lbls[i];
}
out << ")\n";
}
// premises "(" "ref" step-name* ")"
void boogie_proof::pp_premises(std::ostream& out, refs& refs) {
out << "(ref";
for (unsigned i = 0; i < refs.size(); ++i) {
out << " s!" << refs[i];
}
out << ")\n";
}
}