3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-23 03:27:52 +00:00

added facility to persist model transformations

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-11-02 00:05:52 -05:00
commit fd49a0c89c
195 changed files with 3601 additions and 2139 deletions

View file

@ -10,6 +10,7 @@ z3_add_component(ast
ast_printer.cpp
ast_smt2_pp.cpp
ast_smt_pp.cpp
ast_pp_dot.cpp
ast_translation.cpp
ast_util.cpp
bv_decl_plugin.cpp

View file

@ -242,7 +242,9 @@ func_decl* array_decl_plugin::mk_select(unsigned arity, sort * const * domain) {
parameter const* parameters = s->get_parameters();
if (num_parameters != arity) {
m_manager->raise_exception("select requires as many arguments as the size of the domain");
std::stringstream strm;
strm << "select requires " << num_parameters << " arguments, but was provided with " << arity << " arguments";
m_manager->raise_exception(strm.str().c_str());
return 0;
}
ptr_buffer<sort> new_domain; // we need this because of coercions.
@ -314,7 +316,7 @@ func_decl * array_decl_plugin::mk_array_ext(unsigned arity, sort * const * domai
return 0;
}
sort * r = to_sort(s->get_parameter(i).get_ast());
parameter param(s);
parameter param(i);
return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, func_decl_info(m_family_id, OP_ARRAY_EXT, 1, &param));
}
@ -592,3 +594,9 @@ sort * array_util::mk_array_sort(unsigned arity, sort* const* domain, sort* rang
params.push_back(parameter(range));
return m_manager.mk_sort(m_fid, ARRAY_SORT, params.size(), params.c_ptr());
}
func_decl* array_util::mk_array_ext(sort *domain, unsigned i) {
sort * domains[2] = { domain, domain };
parameter p(i);
return m_manager.mk_func_decl(m_fid, OP_ARRAY_EXT, 1, &p, 2, domains);
}

View file

@ -143,6 +143,7 @@ public:
bool is_const(expr* n) const { return is_app_of(n, m_fid, OP_CONST_ARRAY); }
bool is_map(expr* n) const { return is_app_of(n, m_fid, OP_ARRAY_MAP); }
bool is_as_array(expr * n) const { return is_app_of(n, m_fid, OP_AS_ARRAY); }
bool is_as_array(expr * n, func_decl*& f) const { return is_as_array(n) && (f = get_as_array_func_decl(n), true); }
bool is_select(func_decl* f) const { return is_decl_of(f, m_fid, OP_SELECT); }
bool is_store(func_decl* f) const { return is_decl_of(f, m_fid, OP_STORE); }
bool is_const(func_decl* f) const { return is_decl_of(f, m_fid, OP_CONST_ARRAY); }
@ -182,13 +183,15 @@ public:
return mk_const_array(s, m_manager.mk_true());
}
func_decl * mk_array_ext(sort* domain, unsigned i);
sort * mk_array_sort(sort* dom, sort* range) { return mk_array_sort(1, &dom, range); }
sort * mk_array_sort(unsigned arity, sort* const* domain, sort* range);
app * mk_as_array(sort * s, func_decl * f) {
app * mk_as_array(func_decl * f) {
parameter param(f);
return m_manager.mk_app(m_fid, OP_AS_ARRAY, 1, &param, 0, 0, s);
return m_manager.mk_app(m_fid, OP_AS_ARRAY, 1, &param, 0, 0, 0);
}
};

View file

@ -768,7 +768,7 @@ func_decl * basic_decl_plugin::mk_compressed_proof_decl(char const * name, basic
func_decl * basic_decl_plugin::mk_proof_decl(char const * name, basic_op_kind k, unsigned num_parents, ptr_vector<func_decl> & cache) {
if (num_parents >= cache.size()) {
cache.resize(num_parents+1, 0);
cache.resize(num_parents+1);
}
if (cache[num_parents] == 0) {
cache[num_parents] = mk_proof_decl(name, k, num_parents);
@ -805,7 +805,6 @@ func_decl * basic_decl_plugin::mk_proof_decl(char const* name, basic_op_kind k,
}
func_decl * basic_decl_plugin::mk_proof_decl(basic_op_kind k, unsigned num_parents) {
SASSERT(k == PR_UNDEF || m_manager->proofs_enabled());
switch (static_cast<basic_op_kind>(k)) {
//
// A description of the semantics of the proof
@ -2631,7 +2630,7 @@ bool ast_manager::is_fully_interp(sort * s) const {
// -----------------------------------
proof * ast_manager::mk_proof(family_id fid, decl_kind k, unsigned num_args, expr * const * args) {
if (m_proof_mode == PGM_DISABLED)
if (proofs_disabled())
return m_undef_proof;
return mk_app(fid, k, num_args, args);
}
@ -2667,8 +2666,7 @@ proof * ast_manager::mk_goal(expr * f) {
}
proof * ast_manager::mk_modus_ponens(proof * p1, proof * p2) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
if (!p1 || !p2) return nullptr;
SASSERT(has_fact(p1));
SASSERT(has_fact(p2));
CTRACE("mk_modus_ponens", !(is_implies(get_fact(p2)) || is_iff(get_fact(p2)) || is_oeq(get_fact(p2))),
@ -2689,14 +2687,10 @@ proof * ast_manager::mk_modus_ponens(proof * p1, proof * p2) {
}
proof * ast_manager::mk_reflexivity(expr * e) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
return mk_app(m_basic_family_id, PR_REFLEXIVITY, mk_eq(e, e));
}
proof * ast_manager::mk_oeq_reflexivity(expr * e) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
return mk_app(m_basic_family_id, PR_REFLEXIVITY, mk_oeq(e, e));
}
@ -2710,8 +2704,7 @@ proof * ast_manager::mk_commutativity(app * f) {
\brief Given a proof of p, return a proof of (p <=> true)
*/
proof * ast_manager::mk_iff_true(proof * pr) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
if (!pr) return pr;
SASSERT(has_fact(pr));
SASSERT(is_bool(get_fact(pr)));
return mk_app(m_basic_family_id, PR_IFF_TRUE, pr, mk_iff(get_fact(pr), mk_true()));
@ -2721,8 +2714,7 @@ proof * ast_manager::mk_iff_true(proof * pr) {
\brief Given a proof of (not p), return a proof of (p <=> false)
*/
proof * ast_manager::mk_iff_false(proof * pr) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
if (!pr) return pr;
SASSERT(has_fact(pr));
SASSERT(is_not(get_fact(pr)));
expr * p = to_app(get_fact(pr))->get_arg(0);
@ -2730,10 +2722,7 @@ proof * ast_manager::mk_iff_false(proof * pr) {
}
proof * ast_manager::mk_symmetry(proof * p) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
if (!p)
return p;
if (!p) return p;
if (is_reflexivity(p))
return p;
if (is_symmetry(p))
@ -2746,8 +2735,6 @@ proof * ast_manager::mk_symmetry(proof * p) {
}
proof * ast_manager::mk_transitivity(proof * p1, proof * p2) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
if (!p1)
return p2;
if (!p2)
@ -2792,8 +2779,6 @@ proof * ast_manager::mk_transitivity(proof * p1, proof * p2, proof * p3, proof *
}
proof * ast_manager::mk_transitivity(unsigned num_proofs, proof * const * proofs) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
SASSERT(num_proofs > 0);
proof * r = proofs[0];
for (unsigned i = 1; i < num_proofs; i++)
@ -2802,11 +2787,8 @@ proof * ast_manager::mk_transitivity(unsigned num_proofs, proof * const * proofs
}
proof * ast_manager::mk_transitivity(unsigned num_proofs, proof * const * proofs, expr * n1, expr * n2) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
if (fine_grain_proofs())
return mk_transitivity(num_proofs, proofs);
SASSERT(num_proofs > 0);
if (num_proofs == 0)
return nullptr;
if (num_proofs == 1)
return proofs[0];
DEBUG_CODE({
@ -2822,8 +2804,6 @@ proof * ast_manager::mk_transitivity(unsigned num_proofs, proof * const * proofs
}
proof * ast_manager::mk_monotonicity(func_decl * R, app * f1, app * f2, unsigned num_proofs, proof * const * proofs) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
SASSERT(f1->get_num_args() == f2->get_num_args());
SASSERT(f1->get_decl() == f2->get_decl());
ptr_buffer<expr> args;
@ -2833,8 +2813,6 @@ proof * ast_manager::mk_monotonicity(func_decl * R, app * f1, app * f2, unsigned
}
proof * ast_manager::mk_congruence(app * f1, app * f2, unsigned num_proofs, proof * const * proofs) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
SASSERT(get_sort(f1) == get_sort(f2));
sort * s = get_sort(f1);
sort * d[2] = { s, s };
@ -2842,8 +2820,6 @@ proof * ast_manager::mk_congruence(app * f1, app * f2, unsigned num_proofs, proo
}
proof * ast_manager::mk_oeq_congruence(app * f1, app * f2, unsigned num_proofs, proof * const * proofs) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
SASSERT(get_sort(f1) == get_sort(f2));
sort * s = get_sort(f1);
sort * d[2] = { s, s };
@ -2851,11 +2827,7 @@ proof * ast_manager::mk_oeq_congruence(app * f1, app * f2, unsigned num_proofs,
}
proof * ast_manager::mk_quant_intro(quantifier * q1, quantifier * q2, proof * p) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
if (!p) {
return 0;
}
if (!p) return nullptr;
SASSERT(q1->get_num_decls() == q2->get_num_decls());
SASSERT(has_fact(p));
SASSERT(is_iff(get_fact(p)));
@ -2863,8 +2835,7 @@ proof * ast_manager::mk_quant_intro(quantifier * q1, quantifier * q2, proof * p)
}
proof * ast_manager::mk_oeq_quant_intro(quantifier * q1, quantifier * q2, proof * p) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
if (!p) return nullptr;
SASSERT(q1->get_num_decls() == q2->get_num_decls());
SASSERT(has_fact(p));
SASSERT(is_oeq(get_fact(p)));
@ -2872,25 +2843,26 @@ proof * ast_manager::mk_oeq_quant_intro(quantifier * q1, quantifier * q2, proof
}
proof * ast_manager::mk_distributivity(expr * s, expr * r) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
return mk_app(m_basic_family_id, PR_DISTRIBUTIVITY, mk_eq(s, r));
}
proof * ast_manager::mk_rewrite(expr * s, expr * t) {
if (m_proof_mode == PGM_DISABLED)
SASSERT(proofs_enabled());
if (proofs_disabled())
return m_undef_proof;
return mk_app(m_basic_family_id, PR_REWRITE, mk_eq(s, t));
}
proof * ast_manager::mk_oeq_rewrite(expr * s, expr * t) {
if (m_proof_mode == PGM_DISABLED)
SASSERT(proofs_enabled());
if (proofs_disabled())
return m_undef_proof;
return mk_app(m_basic_family_id, PR_REWRITE, mk_oeq(s, t));
}
proof * ast_manager::mk_rewrite_star(expr * s, expr * t, unsigned num_proofs, proof * const * proofs) {
if (m_proof_mode == PGM_DISABLED)
SASSERT(proofs_enabled());
if (proofs_disabled())
return m_undef_proof;
ptr_buffer<expr> args;
args.append(num_proofs, (expr**) proofs);
@ -2899,37 +2871,43 @@ proof * ast_manager::mk_rewrite_star(expr * s, expr * t, unsigned num_proofs, pr
}
proof * ast_manager::mk_pull_quant(expr * e, quantifier * q) {
if (m_proof_mode == PGM_DISABLED)
SASSERT(proofs_enabled());
if (proofs_disabled())
return m_undef_proof;
return mk_app(m_basic_family_id, PR_PULL_QUANT, mk_iff(e, q));
}
proof * ast_manager::mk_pull_quant_star(expr * e, quantifier * q) {
if (m_proof_mode == PGM_DISABLED)
SASSERT(proofs_enabled());
if (proofs_disabled())
return m_undef_proof;
return mk_app(m_basic_family_id, PR_PULL_QUANT_STAR, mk_iff(e, q));
}
proof * ast_manager::mk_push_quant(quantifier * q, expr * e) {
if (m_proof_mode == PGM_DISABLED)
SASSERT(proofs_enabled());
if (proofs_disabled())
return m_undef_proof;
return mk_app(m_basic_family_id, PR_PUSH_QUANT, mk_iff(q, e));
}
proof * ast_manager::mk_elim_unused_vars(quantifier * q, expr * e) {
if (m_proof_mode == PGM_DISABLED)
SASSERT(proofs_enabled());
if (proofs_disabled())
return m_undef_proof;
return mk_app(m_basic_family_id, PR_ELIM_UNUSED_VARS, mk_iff(q, e));
}
proof * ast_manager::mk_der(quantifier * q, expr * e) {
if (m_proof_mode == PGM_DISABLED)
SASSERT(proofs_enabled());
if (proofs_disabled())
return m_undef_proof;
return mk_app(m_basic_family_id, PR_DER, mk_iff(q, e));
}
proof * ast_manager::mk_quant_inst(expr * not_q_or_i, unsigned num_bind, expr* const* binding) {
if (m_proof_mode == PGM_DISABLED)
SASSERT(proofs_enabled());
if (proofs_disabled())
return m_undef_proof;
vector<parameter> params;
for (unsigned i = 0; i < num_bind; ++i) {
@ -2964,7 +2942,8 @@ bool ast_manager::is_rewrite(expr const* e, expr*& r1, expr*& r2) const {
}
proof * ast_manager::mk_def_axiom(expr * ax) {
if (m_proof_mode == PGM_DISABLED)
SASSERT(proofs_enabled());
if (proofs_disabled())
return m_undef_proof;
return mk_app(m_basic_family_id, PR_DEF_AXIOM, ax);
}
@ -3006,7 +2985,7 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
new_lits.push_back(lit);
}
DEBUG_CODE({
for (unsigned i = 1; m_proof_mode == PGM_FINE && i < num_proofs; i++) {
for (unsigned i = 1; proofs_enabled() && i < num_proofs; i++) {
CTRACE("mk_unit_resolution_bug", !found.get(i, false),
for (unsigned j = 0; j < num_proofs; j++) {
if (j == i) tout << "Index " << i << " was not found:\n";
@ -3085,14 +3064,11 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
}
proof * ast_manager::mk_hypothesis(expr * h) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
return mk_app(m_basic_family_id, PR_HYPOTHESIS, h);
}
proof * ast_manager::mk_lemma(proof * p, expr * lemma) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
if (!p) return p;
SASSERT(has_fact(p));
CTRACE("mk_lemma", !is_false(get_fact(p)), tout << mk_ll_pp(p, *this) << "\n";);
SASSERT(is_false(get_fact(p)));
@ -3105,7 +3081,7 @@ proof * ast_manager::mk_def_intro(expr * new_def) {
}
proof * ast_manager::mk_apply_defs(expr * n, expr * def, unsigned num_proofs, proof * const * proofs) {
if (m_proof_mode == PGM_DISABLED)
if (proofs_disabled())
return m_undef_proof;
ptr_buffer<expr> args;
args.append(num_proofs, (expr**) proofs);
@ -3114,10 +3090,7 @@ proof * ast_manager::mk_apply_defs(expr * n, expr * def, unsigned num_proofs, pr
}
proof * ast_manager::mk_iff_oeq(proof * p) {
if (m_proof_mode == PGM_DISABLED)
return m_undef_proof;
if (!p)
return p;
if (!p) return p;
SASSERT(has_fact(p));
SASSERT(is_iff(get_fact(p)) || is_oeq(get_fact(p)));
@ -3141,7 +3114,7 @@ bool ast_manager::check_nnf_proof_parents(unsigned num_proofs, proof * const * p
}
proof * ast_manager::mk_nnf_pos(expr * s, expr * t, unsigned num_proofs, proof * const * proofs) {
if (m_proof_mode == PGM_DISABLED)
if (proofs_disabled())
return m_undef_proof;
check_nnf_proof_parents(num_proofs, proofs);
ptr_buffer<expr> args;
@ -3151,7 +3124,7 @@ proof * ast_manager::mk_nnf_pos(expr * s, expr * t, unsigned num_proofs, proof *
}
proof * ast_manager::mk_nnf_neg(expr * s, expr * t, unsigned num_proofs, proof * const * proofs) {
if (m_proof_mode == PGM_DISABLED)
if (proofs_disabled())
return m_undef_proof;
check_nnf_proof_parents(num_proofs, proofs);
ptr_buffer<expr> args;
@ -3161,7 +3134,7 @@ proof * ast_manager::mk_nnf_neg(expr * s, expr * t, unsigned num_proofs, proof *
}
proof * ast_manager::mk_nnf_star(expr * s, expr * t, unsigned num_proofs, proof * const * proofs) {
if (m_proof_mode == PGM_DISABLED)
if (proofs_disabled())
return m_undef_proof;
ptr_buffer<expr> args;
args.append(num_proofs, (expr**) proofs);
@ -3170,7 +3143,7 @@ proof * ast_manager::mk_nnf_star(expr * s, expr * t, unsigned num_proofs, proof
}
proof * ast_manager::mk_skolemization(expr * q, expr * e) {
if (m_proof_mode == PGM_DISABLED)
if (proofs_disabled())
return m_undef_proof;
SASSERT(is_bool(q));
SASSERT(is_bool(e));
@ -3178,7 +3151,7 @@ proof * ast_manager::mk_skolemization(expr * q, expr * e) {
}
proof * ast_manager::mk_cnf_star(expr * s, expr * t, unsigned num_proofs, proof * const * proofs) {
if (m_proof_mode == PGM_DISABLED)
if (proofs_disabled())
return m_undef_proof;
ptr_buffer<expr> args;
args.append(num_proofs, (expr**) proofs);
@ -3187,7 +3160,7 @@ proof * ast_manager::mk_cnf_star(expr * s, expr * t, unsigned num_proofs, proof
}
proof * ast_manager::mk_and_elim(proof * p, unsigned i) {
if (m_proof_mode == PGM_DISABLED)
if (proofs_disabled())
return m_undef_proof;
SASSERT(has_fact(p));
SASSERT(is_and(get_fact(p)));
@ -3198,7 +3171,7 @@ proof * ast_manager::mk_and_elim(proof * p, unsigned i) {
}
proof * ast_manager::mk_not_or_elim(proof * p, unsigned i) {
if (m_proof_mode == PGM_DISABLED)
if (proofs_disabled())
return m_undef_proof;
SASSERT(has_fact(p));
SASSERT(is_not(get_fact(p)));
@ -3221,7 +3194,7 @@ proof * ast_manager::mk_th_lemma(
unsigned num_params, parameter const* params
)
{
if (m_proof_mode == PGM_DISABLED)
if (proofs_disabled())
return m_undef_proof;
ptr_buffer<expr> args;

View file

@ -121,6 +121,20 @@ public:
explicit parameter(unsigned ext_id, bool):m_kind(PARAM_EXTERNAL), m_ext_id(ext_id) {}
parameter(parameter const&);
parameter(parameter && other) : m_kind(other.m_kind) {
switch (other.m_kind) {
case PARAM_INT: m_int = other.get_int(); break;
case PARAM_AST: m_ast = other.get_ast(); break;
case PARAM_SYMBOL: m_symbol = other.m_symbol; break;
case PARAM_RATIONAL: m_rational = 0; std::swap(m_rational, other.m_rational); break;
case PARAM_DOUBLE: m_dval = other.m_dval; break;
case PARAM_EXTERNAL: m_ext_id = other.m_ext_id; break;
default:
UNREACHABLE();
break;
}
}
~parameter();
parameter& operator=(parameter const& other);
@ -1382,8 +1396,7 @@ public:
enum proof_gen_mode {
PGM_DISABLED,
PGM_COARSE,
PGM_FINE
PGM_ENABLED
};
// -----------------------------------
@ -2076,15 +2089,14 @@ protected:
proof * mk_proof(family_id fid, decl_kind k, expr * arg1, expr * arg2);
proof * mk_proof(family_id fid, decl_kind k, expr * arg1, expr * arg2, expr * arg3);
proof * mk_undef_proof() const { return m_undef_proof; }
public:
bool proofs_enabled() const { return m_proof_mode != PGM_DISABLED; }
bool proofs_disabled() const { return m_proof_mode == PGM_DISABLED; }
bool coarse_grain_proofs() const { return m_proof_mode == PGM_COARSE; }
bool fine_grain_proofs() const { return m_proof_mode == PGM_FINE; }
proof_gen_mode proof_mode() const { return m_proof_mode; }
void toggle_proof_mode(proof_gen_mode m) { m_proof_mode = m; } // APIs for creating proof objects return [undef]
proof * mk_undef_proof() const { return m_undef_proof; }
bool is_proof(expr const * n) const { return is_app(n) && to_app(n)->get_decl()->get_range() == m_proof_sort; }

133
src/ast/ast_pp_dot.cpp Normal file
View file

@ -0,0 +1,133 @@
/*++
Abstract: Pretty-printer for proofs in Graphviz format
--*/
#include "util/util.h"
#include "util/map.h"
#include "ast/ast_pp_dot.h"
// string escaping for DOT
std::string escape_dot(std::string const & s) {
std::string res;
res.reserve(s.size()); // preallocate
for (auto c : s) {
if (c == '\n')
res.append("\\l");
else
res.push_back(c);
}
return res;
}
// map from proofs to unique IDs
typedef obj_map<const expr, unsigned> expr2id;
// temporary structure for traversing the proof and printing it
struct ast_pp_dot_st {
ast_manager & m_manager;
std::ostream & m_out;
const ast_pp_dot * m_pp;
unsigned m_next_id;
expr2id m_id_map;
obj_hashtable<const expr> m_printed;
svector<const expr *> m_to_print;
bool m_first;
ast_pp_dot_st(const ast_pp_dot * pp, std::ostream & out) :
m_manager(pp->get_manager()),
m_out(out),
m_pp(pp),
m_next_id(0),
m_id_map(),
m_printed(),
m_to_print(),
m_first(true) {}
~ast_pp_dot_st() {};
void push_term(const expr * a) { m_to_print.push_back(a); }
void pp_loop() {
// DFS traversal
while (!m_to_print.empty()) {
const expr * a = m_to_print.back();
m_to_print.pop_back();
if (!m_printed.contains(a)) {
m_printed.insert(a);
if (m().is_proof(a))
pp_step(to_app(a));
else
pp_atomic_step(a);
}
}
}
private:
inline ast_manager & m() const { return m_manager; }
// label for an expression
std::string label_of_expr(const expr * e) const {
expr_ref er((expr*)e, m());
std::ostringstream out;
out << er << std::flush;
return escape_dot(out.str());
}
void pp_atomic_step(const expr * e) {
unsigned id = get_id(e);
m_out << "node_" << id << " [shape=box,color=\"yellow\",style=\"filled\",label=\"" << label_of_expr(e) << "\"] ;" << std::endl;
}
void pp_step(const proof * p) {
TRACE("pp_ast_dot_step", tout << " :kind " << p->get_kind() << " :num-args " << p->get_num_args() << "\n";);
if (m().has_fact(p)) {
// print result
expr* p_res = m().get_fact(p); // result of proof step
unsigned id = get_id(p);
unsigned num_parents = m().get_num_parents(p);
const char* color =
m_first ? (m_first=false,"color=\"red\"") : num_parents==0 ? "color=\"yellow\"": "";
m_out << "node_" << id <<
" [shape=box,style=\"filled\",label=\"" << label_of_expr(p_res) << "\""
<< color << "]" << std::endl;
// now print edges to parents (except last one, which is the result)
std::string label = p->get_decl()->get_name().str();
for (unsigned i = 0 ; i < num_parents; ++i) {
expr* parent = m().get_parent(p, i);
// explore parent, also print a link to it
push_term(to_app(parent));
m_out << "node_" << id << " -> " << "node_" << get_id((expr*)parent)
<< "[label=\"" << label << "\"];" << std::endl;;
}
} else {
pp_atomic_step(p);
}
}
// find a unique ID for this proof
unsigned get_id(const expr * e) {
unsigned id = 0;
if (!m_id_map.find(e, id)) {
id = m_next_id++;
m_id_map.insert(e, id);
}
return id;
}
};
// main printer
std::ostream & ast_pp_dot::pp(std::ostream & out) const {
out << "digraph proof { " << std::endl;
ast_pp_dot_st pp_st(this, out);
pp_st.push_term(m_pr);
pp_st.pp_loop();
out << std::endl << " } " << std::endl << std::flush;
return out;
}
std::ostream &operator<<(std::ostream &out, const ast_pp_dot & p) { return p.pp(out); }

24
src/ast/ast_pp_dot.h Normal file
View file

@ -0,0 +1,24 @@
/*++
Abstract: Pretty-printer for proofs in Graphviz format
--*/
#pragma once
#include <iostream>
#include "ast_pp.h"
class ast_pp_dot {
ast_manager & m_manager;
proof * const m_pr;
public:
ast_pp_dot(proof *pr, ast_manager &m) : m_manager(m), m_pr(pr) {}
ast_pp_dot(proof_ref &e) : m_manager(e.m()), m_pr(e.get()) {}
std::ostream & pp(std::ostream & out) const;
ast_manager & get_manager() const { return m_manager; }
};
std::ostream &operator<<(std::ostream &out, const ast_pp_dot & p);

View file

@ -36,6 +36,26 @@ format * smt2_pp_environment::pp_fdecl_name(symbol const & s0, unsigned & len, b
symbol s = m_renaming.get_symbol(s0, is_skolem);
len = static_cast<unsigned>(strlen(s.bare_str()));
return mk_string(m, s.bare_str());
#if 0
if (is_smt2_quoted_symbol(s)) {
std::string str = mk_smt2_quoted_symbol(s);
len = static_cast<unsigned>(str.length());
return mk_string(m, str.c_str());
}
else if (s.is_numerical()) {
std::string str = s.str();
len = static_cast<unsigned>(str.length());
return mk_string(m, str.c_str());
}
else if (!s.bare_str()) {
len = 4;
return mk_string(m, "null");
}
else {
len = static_cast<unsigned>(strlen(s.bare_str()));
return mk_string(m, s.bare_str());
}
#endif
}
format * smt2_pp_environment::pp_fdecl_name(func_decl * f, unsigned & len) const {

View file

@ -863,8 +863,7 @@ app * bv_util::mk_numeral(rational const & val, sort* s) const {
}
app * bv_util::mk_numeral(rational const & val, unsigned bv_size) const {
parameter p1(val);
parameter p[2] = { p1, parameter(static_cast<int>(bv_size)) };
parameter p[2] = { parameter(val), parameter(static_cast<int>(bv_size)) };
return m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, 0);
}

View file

@ -80,6 +80,7 @@ public:
m_trail_lim.resize(new_sz);
}
}
unsigned scope_level() const { return m_trail_lim.size(); }
bool empty() const { return m_subst.empty(); }
expr* find(expr * e) { proof* pr; expr* d = 0; if (find(e, d, pr)) return d; else return e; }
bool find(expr * s, expr * & def, proof * & def_pr) { return m_subst.find(s, def, def_pr); }

View file

@ -250,7 +250,7 @@ bv2fpa_converter::array_model bv2fpa_converter::convert_array_func_interp(model_
am.new_float_fd = m.mk_fresh_func_decl(arity, array_domain.c_ptr(), rng);
am.new_float_fi = convert_func_interp(mc, am.new_float_fd, bv_f);
am.bv_fd = bv_f;
am.result = arr_util.mk_as_array(f->get_range(), am.new_float_fd);
am.result = arr_util.mk_as_array(am.new_float_fd);
return am;
}

View file

@ -3076,8 +3076,6 @@ void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const *
split_fp(x, sgn, e, s);
mk_is_nan(x, x_is_nan);
sort * fp_srt = m.get_sort(x);
expr_ref unspec(m);
mk_to_ieee_bv_unspecified(f, num, args, unspec);

View file

@ -40,7 +40,7 @@ enum nnf_mode {
transformation will be in skolem normal form.
If a formula is too expensive to be put into NNF,
then nested quantifiers and labels are renamed.
This mode is sufficient when using E-matching.
*/
NNF_QUANT, /* A subformula is put into NNF if it contains
@ -48,7 +48,7 @@ enum nnf_mode {
quantifier. The result of the transformation will be
in skolem normal form, and the body of quantifiers
will be in NNF. If a ground formula is too expensive to
be put into NNF, then nested quantifiers and labels
be put into NNF, then nested quantifiers and labels
are renamed.
This mode is sufficient when using Superposition
@ -89,7 +89,7 @@ class skolemizer {
}
TRACE("skolemizer", tout << "skid: " << q->get_skid() << "\n";);
expr_ref_vector substitution(m());
unsigned num_decls = q->get_num_decls();
for (unsigned i = num_decls; i > 0; ) {
@ -111,7 +111,7 @@ class skolemizer {
substitution.push_back(0);
}
//
// (VAR num_decls) ... (VAR num_decls+sz-1)
// (VAR num_decls) ... (VAR num_decls+sz-1)
// are in positions num_decls .. num_decls+sz-1
//
std::reverse(substitution.c_ptr(), substitution.c_ptr() + substitution.size());
@ -139,7 +139,7 @@ class skolemizer {
s(body, substitution.size(), substitution.c_ptr(), r);
p = 0;
if (m().proofs_enabled()) {
if (q->is_forall())
if (q->is_forall())
p = m().mk_skolemization(m().mk_not(q), m().mk_not(r));
else
p = m().mk_skolemization(q, r);
@ -175,7 +175,7 @@ public:
m_cache_pr.insert(q, p);
}
}
bool is_sk_hack(expr * p) const {
SASSERT(m().is_pattern(p));
if (to_app(p)->get_num_args() != 1)
@ -204,11 +204,11 @@ struct nnf::imp {
unsigned m_i:28;
unsigned m_pol:1; // pos/neg polarity
unsigned m_in_q:1; // true if m_curr is nested in a quantifier
unsigned m_new_child:1;
unsigned m_new_child:1;
unsigned m_cache_result:1;
unsigned m_spos; // top of the result stack, when the frame was created.
frame(expr_ref& n, bool pol, bool in_q, bool cache_res, unsigned spos):
m_curr(n),
frame(expr_ref && n, bool pol, bool in_q, bool cache_res, unsigned spos):
m_curr(std::move(n)),
m_i(0),
m_pol(pol),
m_in_q(in_q),
@ -216,6 +216,16 @@ struct nnf::imp {
m_cache_result(cache_res),
m_spos(spos) {
}
frame(frame && other):
m_curr(std::move(other.m_curr)),
m_i(other.m_i),
m_pol(other.m_pol),
m_in_q(other.m_in_q),
m_new_child(other.m_new_child),
m_cache_result(other.m_cache_result),
m_spos(other.m_spos) {
}
};
// There are four caches:
@ -223,22 +233,22 @@ struct nnf::imp {
#define POS_NQ_CIDX 1 // positive polarity and not nested in a quantifier
#define NEG_Q_CIDX 2 // negative polarity and nested in a quantifier
#define POS_Q_CIDX 3 // positive polarity and nested in a quantifier
ast_manager & m_manager;
vector<frame> m_frame_stack;
expr_ref_vector m_result_stack;
typedef act_cache cache;
cache * m_cache[4];
expr_ref_vector m_todo_defs;
proof_ref_vector m_todo_proofs;
// proof generation goodness ----
proof_ref_vector m_result_pr_stack;
cache * m_cache_pr[4];
// ------------------------------
skolemizer m_skolemizer;
// configuration ----------------
@ -249,7 +259,7 @@ struct nnf::imp {
name_exprs * m_name_nested_formulas;
name_exprs * m_name_quant;
unsigned long long m_max_memory; // in bytes
imp(ast_manager & m, defined_names & n, params_ref const & p):
@ -292,9 +302,9 @@ struct nnf::imp {
m_mode = NNF_FULL;
else if (mode_sym == "quantifiers")
m_mode = NNF_QUANT;
else
else
throw nnf_params_exception("invalid NNF mode");
TRACE("nnf", tout << "nnf-mode: " << m_mode << " " << mode_sym << "\n" << _p << "\n";);
m_ignore_labels = p.ignore_labels();
@ -324,12 +334,11 @@ struct nnf::imp {
}
void push_frame(expr * t, bool pol, bool in_q, bool cache_res) {
expr_ref tr(t, m());
m_frame_stack.push_back(frame(tr, pol, in_q, cache_res, m_result_stack.size()));
m_frame_stack.push_back(frame(expr_ref(t, m()), pol, in_q, cache_res, m_result_stack.size()));
}
static unsigned get_cache_idx(bool pol, bool in_q) {
return static_cast<unsigned>(in_q) * 2 + static_cast<unsigned>(pol);
static unsigned get_cache_idx(bool pol, bool in_q) {
return static_cast<unsigned>(in_q) * 2 + static_cast<unsigned>(pol);
}
void cache_result(expr * t, bool pol, bool in_q, expr * v, proof * pr) {
@ -339,8 +348,8 @@ struct nnf::imp {
m_cache_pr[idx]->insert(t, pr);
}
expr * get_cached(expr * t, bool pol, bool in_q) const {
return m_cache[get_cache_idx(pol, in_q)]->find(t);
expr * get_cached(expr * t, bool pol, bool in_q) const {
return m_cache[get_cache_idx(pol, in_q)]->find(t);
}
proof * get_cached_pr(expr * t, bool pol, bool in_q) const {
@ -368,12 +377,12 @@ struct nnf::imp {
return false;
}
void checkpoint() {
cooperate("nnf");
if (memory::get_allocation_size() > m_max_memory)
throw nnf_exception(Z3_MAX_MEMORY_MSG);
if (m().canceled())
if (m().canceled())
throw nnf_exception(m().limit().get_cancel_msg());
}
@ -382,11 +391,11 @@ struct nnf::imp {
m_frame_stack.back().m_new_child = true;
}
void set_new_child_flag(expr * old_t, expr * new_t) {
if (old_t != new_t)
set_new_child_flag();
void set_new_child_flag(expr * old_t, expr * new_t) {
if (old_t != new_t)
set_new_child_flag();
}
void skip(expr * t, bool pol) {
expr * r = pol ? t : m().mk_not(t);
m_result_stack.push_back(r);
@ -448,10 +457,10 @@ struct nnf::imp {
if (pol) {
if (old_e->get_decl() == new_e->get_decl())
return m().mk_oeq_congruence(old_e, new_e, num_parents, parents);
else
else
return m().mk_nnf_pos(old_e, new_e, num_parents, parents);
}
else
else
return m().mk_nnf_neg(old_e, new_e, num_parents, parents);
}
@ -468,7 +477,7 @@ struct nnf::imp {
r = m().mk_and(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
else
r = m().mk_or(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
m_result_stack.shrink(fr.m_spos);
m_result_stack.push_back(r);
if (proofs_enabled()) {
@ -520,7 +529,7 @@ struct nnf::imp {
r = m().mk_or(2, m_result_stack.c_ptr() + fr.m_spos);
else
r = m().mk_and(2, m_result_stack.c_ptr() + fr.m_spos);
m_result_stack.shrink(fr.m_spos);
m_result_stack.push_back(r);
if (proofs_enabled()) {
@ -554,7 +563,7 @@ struct nnf::imp {
default:
break;
}
expr * const * rs = m_result_stack.c_ptr() + fr.m_spos;
expr * _cond = rs[0];
expr * _not_cond = rs[1];
@ -574,7 +583,7 @@ struct nnf::imp {
}
bool is_eq(app * t) const { return m().is_eq(t) || m().is_iff(t); }
bool process_iff_xor(app * t, frame & fr) {
SASSERT(t->get_num_args() == 2);
switch (fr.m_i) {
@ -605,7 +614,7 @@ struct nnf::imp {
expr * not_rhs = rs[3];
app * r;
if (is_eq(t) == fr.m_pol)
if (is_eq(t) == fr.m_pol)
r = m().mk_and(m().mk_or(not_lhs, rhs), m().mk_or(lhs, not_rhs));
else
r = m().mk_and(m().mk_or(lhs, rhs), m().mk_or(not_lhs, not_rhs));
@ -626,7 +635,7 @@ struct nnf::imp {
else
return process_default(t, fr);
}
bool process_default(app * t, frame & fr) {
SASSERT(fr.m_i == 0);
if (m_mode == NNF_FULL || t->has_quantifiers() || t->has_labels()) {
@ -636,10 +645,10 @@ struct nnf::imp {
m_name_nested_formulas->operator()(t, m_todo_defs, m_todo_proofs, n2, pr2);
else
m_name_quant->operator()(t, m_todo_defs, m_todo_proofs, n2, pr2);
if (!fr.m_pol)
n2 = m().mk_not(n2);
m_result_stack.push_back(n2);
if (proofs_enabled()) {
if (!fr.m_pol) {
@ -666,10 +675,10 @@ struct nnf::imp {
expr * arg = m_result_stack.back();
proof * arg_pr = proofs_enabled() ? m_result_pr_stack.back() : 0;
if (m_ignore_labels && !proofs_enabled())
if (m_ignore_labels && !proofs_enabled())
return true; // the result is already on the stack
buffer<symbol> names;
bool pos;
m().is_label(t, pos, names);
@ -684,7 +693,7 @@ struct nnf::imp {
pr = m().mk_transitivity(mk_proof(fr.m_pol, 1, &arg_pr, t, to_app(aux)),
m().mk_iff_oeq(m().mk_rewrite(aux, r)));
}
}
}
else {
r = arg;
if (proofs_enabled()) {
@ -692,7 +701,7 @@ struct nnf::imp {
pr = m().mk_transitivity(p1, arg_pr);
}
}
m_result_stack.pop_back();
m_result_stack.push_back(r);
if (proofs_enabled()) {
@ -729,7 +738,7 @@ struct nnf::imp {
if (m().is_label(t)) {
return process_label(t, fr);
}
return process_default(t, fr);
}
@ -737,7 +746,7 @@ struct nnf::imp {
skip(v, fr.m_pol);
return true;
}
bool process_quantifier(quantifier * q, frame & fr) {
expr_ref r(m());
proof_ref pr(m());
@ -757,7 +766,7 @@ struct nnf::imp {
if (q->is_forall() == fr.m_pol || !m_skolemize) {
expr * new_expr = m_result_stack.back();
proof * new_expr_pr = proofs_enabled() ? m_result_pr_stack.back() : 0;
ptr_buffer<expr> new_patterns;
if (q->is_forall() == fr.m_pol) {
@ -773,7 +782,7 @@ struct nnf::imp {
// New quantifier has existential force.
// So, ignore patterns
}
quantifier * new_q = 0;
proof * new_q_pr = 0;
if (fr.m_pol) {
@ -786,7 +795,7 @@ struct nnf::imp {
if (proofs_enabled())
new_q_pr = m().mk_nnf_neg(q, new_q, 1, &new_expr_pr);
}
m_result_stack.pop_back();
m_result_stack.push_back(new_q);
if (proofs_enabled()) {
@ -809,7 +818,7 @@ struct nnf::imp {
}
return true;
}
void recover_result(expr * t, expr_ref & result, proof_ref & result_pr) {
// recover result from the top of the stack.
result = m_result_stack.back();
@ -873,7 +882,7 @@ struct nnf::imp {
process(n, r, pr);
unsigned old_sz1 = new_defs.size();
unsigned old_sz2 = new_def_proofs.size();
for (unsigned i = 0; i < m_todo_defs.size(); i++) {
expr_ref dr(m());
proof_ref dpr(m());
@ -881,7 +890,7 @@ struct nnf::imp {
new_defs.push_back(dr);
if (proofs_enabled()) {
proof * new_pr = m().mk_modus_ponens(m_todo_proofs.get(i), dpr);
new_def_proofs.push_back(new_pr);
new_def_proofs.push_back(new_pr);
}
}
std::reverse(new_defs.c_ptr() + old_sz1, new_defs.c_ptr() + new_defs.size());
@ -898,7 +907,7 @@ nnf::nnf(ast_manager & m, defined_names & n, params_ref const & p) {
nnf::~nnf() {
dealloc(m_imp);
}
void nnf::operator()(expr * n, expr_ref_vector & new_defs, proof_ref_vector & new_def_proofs, expr_ref & r, proof_ref & p) {
m_imp->operator()(n, new_defs, new_def_proofs, r, p);
TRACE("nnf_result", tout << mk_ismt2_pp(n, m_imp->m()) << "\nNNF result:\n" << mk_ismt2_pp(r, m_imp->m()) << "\n";);

View file

@ -229,7 +229,7 @@ struct pull_quant::imp {
proofs.push_back(m_manager.mk_pull_quant(arg, to_quantifier(new_arg)));
}
pull_quant1(to_app(n)->get_decl(), new_args.size(), new_args.c_ptr(), r);
if (m_manager.fine_grain_proofs()) {
if (m_manager.proofs_enabled()) {
app * r1 = m_manager.mk_app(to_app(n)->get_decl(), new_args.size(), new_args.c_ptr());
proof * p1 = proofs.empty() ? 0 : m_manager.mk_congruence(to_app(n), r1, proofs.size(), proofs.c_ptr());
proof * p2 = r1 == r ? 0 : m_manager.mk_pull_quant(r1, to_quantifier(r));
@ -240,7 +240,7 @@ struct pull_quant::imp {
expr_ref new_expr(m_manager);
pull_quant1(to_quantifier(n)->get_expr(), new_expr);
pull_quant1(to_quantifier(n), new_expr, r);
if (m_manager.fine_grain_proofs()) {
if (m_manager.proofs_enabled()) {
quantifier * q1 = m_manager.update_quantifier(to_quantifier(n), new_expr);
proof * p1 = 0;
if (n != q1) {

View file

@ -179,11 +179,11 @@ expr_pattern_match::compile(expr* q)
}
if (m_regs.size() <= max_reg) {
m_regs.resize(max_reg+1, 0);
m_regs.resize(max_reg+1);
}
if (m_bound_dom.size() <= num_bound) {
m_bound_dom.resize(num_bound+1, 0);
m_bound_rng.resize(num_bound+1, 0);
m_bound_dom.resize(num_bound+1);
m_bound_rng.resize(num_bound+1);
}
instr.m_kind = YIELD;

View file

@ -606,7 +606,7 @@ bool pattern_inference_cfg::reduce_quantifier(
result = m.update_quantifier_weight(tmp, new_weight);
TRACE("pattern_inference", tout << "found patterns in database, weight: " << new_weight << "\n" << mk_pp(new_q, m) << "\n";);
}
if (m.fine_grain_proofs())
if (m.proofs_enabled())
result_pr = m.mk_rewrite(q, new_q);
return true;
}
@ -671,7 +671,7 @@ bool pattern_inference_cfg::reduce_quantifier(
quantifier_ref new_q(m.update_quantifier(q, new_patterns.size(), (expr**) new_patterns.c_ptr(), new_body), m);
if (weight != q->get_weight())
new_q = m.update_quantifier_weight(new_q, weight);
if (m.fine_grain_proofs()) {
if (m.proofs_enabled()) {
proof* new_body_pr = m.mk_reflexivity(new_body);
result_pr = m.mk_quant_intro(q, new_q, new_body_pr);
}
@ -689,7 +689,7 @@ bool pattern_inference_cfg::reduce_quantifier(
warning_msg("pulled nested quantifier to be able to find an useable pattern (quantifier id: %s)", q->get_qid().str().c_str());
}
new_q = m.update_quantifier(result2, new_patterns.size(), (expr**) new_patterns.c_ptr(), result2->get_expr());
if (m.fine_grain_proofs()) {
if (m.proofs_enabled()) {
result_pr = m.mk_transitivity(new_pr, m.mk_quant_intro(result2, new_q, m.mk_reflexivity(new_q->get_expr())));
}
TRACE("pattern_inference", tout << "pulled quantifier:\n" << mk_pp(new_q, m) << "\n";);

View file

@ -1,6 +1,7 @@
z3_add_component(proof_checker
z3_add_component(proofs
SOURCES
proof_checker.cpp
proof_utils.cpp
COMPONENT_DEPENDENCIES
rewriter
)
)

View file

@ -4,10 +4,9 @@ Copyright (c) 2015 Microsoft Corporation
--*/
#include "ast/proof_checker/proof_checker.h"
#include "ast/proofs/proof_checker.h"
#include "ast/ast_ll_pp.h"
#include "ast/ast_pp.h"
// include "spc_decl_plugin.h"
#include "ast/ast_smt_pp.h"
#include "ast/arith_decl_plugin.h"
#include "ast/rewriter/th_rewriter.h"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,238 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
proof_utils.h
Abstract:
Utilities to traverse and manipulate proofs
Author:
Bernhard Gleiss
Arie Gurfinkel
Nikolaj Bjorner
Revision History:
--*/
#ifndef PROOF_UTILS_H_
#define PROOF_UTILS_H_
#include "ast/ast.h"
#include "ast/ast_pp.h"
#include "ast/rewriter/bool_rewriter.h"
#include "ast/proofs/proof_checker.h"
/*
* iterator, which traverses the proof in depth-first post-order.
*/
class proof_post_order {
public:
proof_post_order(proof* refutation, ast_manager& manager);
bool hasNext();
proof* next();
private:
ptr_vector<proof> m_todo;
ast_mark m_visited; // the proof nodes we have already visited
ast_manager& m;
};
void reduce_hypotheses(proof_ref &pr);
class proof_utils {
public:
/**
\brief reduce the set of hypotheses used in the proof.
*/
static void reduce_hypotheses(proof_ref& pr);
/**
\brief Check that a proof does not contain open hypotheses.
*/
static bool is_closed(ast_manager& m, proof* p);
/**
\brief Permute unit resolution rule with th-lemma
*/
static void permute_unit_resolution(proof_ref& pr);
/**
\brief Push instantiations created in hyper-resolutions up to leaves.
This produces a "ground" proof where leaves are annotated by instantiations.
*/
static void push_instantiations_up(proof_ref& pr);
};
class elim_aux_assertions {
static bool matches_fact(expr_ref_vector &args, expr* &match) {
ast_manager &m = args.get_manager();
expr *fact = args.back();
for (unsigned i = 0, sz = args.size() - 1; i < sz; ++i) {
expr *arg = args.get(i);
if (m.is_proof(arg) &&
m.has_fact(to_app(arg)) &&
m.get_fact(to_app(arg)) == fact) {
match = arg;
return true;
}
}
return false;
}
app_ref m_aux;
public:
elim_aux_assertions(app_ref aux) : m_aux(aux) {}
void mk_or_core(expr_ref_vector &args, expr_ref &res)
{
ast_manager &m = args.get_manager();
unsigned j = 0;
for (unsigned i = 0, sz = args.size(); i < sz; ++i) {
if (m.is_false(args.get(i))) { continue; }
if (i != j) { args [j] = args.get(i); }
++j;
}
SASSERT(j >= 1);
res = j > 1 ? m.mk_or(j, args.c_ptr()) : args.get(0);
}
void mk_app(func_decl *decl, expr_ref_vector &args, expr_ref &res)
{
ast_manager &m = args.get_manager();
bool_rewriter brwr(m);
if (m.is_or(decl))
{ mk_or_core(args, res); }
else if (m.is_iff(decl) && args.size() == 2)
// avoiding simplifying equalities. In particular,
// we don't want (= (not a) (not b)) to be reduced to (= a b)
{ res = m.mk_iff(args.get(0), args.get(1)); }
else
{ brwr.mk_app(decl, args.size(), args.c_ptr(), res); }
}
void operator()(ast_manager &m, proof *pr, proof_ref &res)
{
DEBUG_CODE(proof_checker pc(m);
expr_ref_vector side(m);
SASSERT(pc.check(pr, side));
);
obj_map<app, app*> cache;
bool_rewriter brwr(m);
// for reference counting of new proofs
app_ref_vector pinned(m);
ptr_vector<app> todo;
todo.push_back(pr);
expr_ref not_aux(m);
not_aux = m.mk_not(m_aux);
expr_ref_vector args(m);
while (!todo.empty()) {
app *p, *r;
expr *a;
p = todo.back();
if (cache.find(pr, r)) {
todo.pop_back();
continue;
}
SASSERT(!todo.empty() || pr == p);
bool dirty = false;
unsigned todo_sz = todo.size();
args.reset();
for (unsigned i = 0, sz = p->get_num_args(); i < sz; ++i) {
expr* arg = p->get_arg(i);
if (arg == m_aux.get()) {
dirty = true;
args.push_back(m.mk_true());
} else if (arg == not_aux.get()) {
dirty = true;
args.push_back(m.mk_false());
}
// skip (asserted m_aux)
else if (m.is_asserted(arg, a) && a == m_aux.get()) {
dirty = true;
}
// skip (hypothesis m_aux)
else if (m.is_hypothesis(arg, a) && a == m_aux.get()) {
dirty = true;
} else if (is_app(arg) && cache.find(to_app(arg), r)) {
dirty |= (arg != r);
args.push_back(r);
} else if (is_app(arg))
{ todo.push_back(to_app(arg)); }
else
// -- not an app
{ args.push_back(arg); }
}
if (todo_sz < todo.size()) {
// -- process parents
args.reset();
continue;
}
// ready to re-create
app_ref newp(m);
if (!dirty) { newp = p; }
else if (m.is_unit_resolution(p)) {
if (args.size() == 2)
// unit resolution with m_aux that got collapsed to nothing
{ newp = to_app(args.get(0)); }
else {
ptr_vector<proof> parents;
for (unsigned i = 0, sz = args.size() - 1; i < sz; ++i)
{ parents.push_back(to_app(args.get(i))); }
SASSERT(parents.size() == args.size() - 1);
newp = m.mk_unit_resolution(parents.size(), parents.c_ptr());
// XXX the old and new facts should be
// equivalent. The test here is much
// stronger. It might need to be relaxed.
SASSERT(m.get_fact(newp) == args.back());
pinned.push_back(newp);
}
} else if (matches_fact(args, a)) {
newp = to_app(a);
} else {
expr_ref papp(m);
mk_app(p->get_decl(), args, papp);
newp = to_app(papp.get());
pinned.push_back(newp);
}
cache.insert(p, newp);
todo.pop_back();
CTRACE("virtual",
p->get_decl_kind() == PR_TH_LEMMA &&
p->get_decl()->get_parameter(0).get_symbol() == "arith" &&
p->get_decl()->get_num_parameters() > 1 &&
p->get_decl()->get_parameter(1).get_symbol() == "farkas",
tout << "Old pf: " << mk_pp(p, m) << "\n"
<< "New pf: " << mk_pp(newp, m) << "\n";);
}
proof *r;
VERIFY(cache.find(pr, r));
DEBUG_CODE(
proof_checker pc(m);
expr_ref_vector side(m);
SASSERT(pc.check(r, side));
);
res = r ;
}
};
#endif

View file

@ -272,7 +272,7 @@ void bit_blaster_tpl<Cfg>::mk_multiplier(unsigned sz, expr * const * a_bits, exp
zero = m().mk_false();
vector< expr_ref_vector > pps;
pps.resize(sz, m());
pps.resize(sz, expr_ref_vector(m()));
for (unsigned i = 0; i < sz; i++) {
checkpoint();

View file

@ -119,17 +119,15 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const
// BV -> float
SASSERT(bvs1 == sbits + ebits);
unsynch_mpz_manager & mpzm = m_fm.mpz_manager();
unsynch_mpq_manager & mpqm = m_fm.mpq_manager();
scoped_mpz sig(mpzm), exp(mpzm);
const mpz & sm1 = m_fm.m_powers2(sbits - 1);
const mpz & em1 = m_fm.m_powers2(ebits);
scoped_mpq q(mpqm);
mpqm.set(q, r1.to_mpq());
SASSERT(mpzm.is_one(q.get().denominator()));
const mpq & q = r1.to_mpq();
SASSERT(mpzm.is_one(q.denominator()));
scoped_mpz z(mpzm);
z = q.get().numerator();
z = q.numerator();
mpzm.rem(z, sm1, sig);
mpzm.div(z, sm1, z);

View file

@ -37,7 +37,7 @@ public:
class scoped_proof : public scoped_proof_mode {
public:
scoped_proof(ast_manager& m): scoped_proof_mode(m, PGM_FINE) {}
scoped_proof(ast_manager& m): scoped_proof_mode(m, PGM_ENABLED) {}
};
class scoped_no_proof : public scoped_proof_mode {

View file

@ -256,7 +256,7 @@ void substitution_tree::insert(expr * new_expr) {
sort * s = to_var(new_expr)->get_sort();
unsigned id = s->get_decl_id();
if (id >= m_vars.size())
m_vars.resize(id+1, 0);
m_vars.resize(id+1);
if (m_vars[id] == 0)
m_vars[id] = alloc(var_ref_vector, m_manager);
var_ref_vector * v = m_vars[id];
@ -277,7 +277,7 @@ void substitution_tree::insert(app * new_expr) {
unsigned id = d->get_decl_id();
if (id >= m_roots.size())
m_roots.resize(id+1, 0);
m_roots.resize(id+1);
if (!m_roots[id]) {
// there is no tree for the function symbol heading new_expr

View file

@ -58,7 +58,7 @@ void used_vars::process(expr * n, unsigned delta) {
if (idx >= delta) {
idx = idx - delta;
if (idx >= m_found_vars.size())
m_found_vars.resize(idx + 1, 0);
m_found_vars.resize(idx + 1);
m_found_vars[idx] = to_var(n)->get_sort();
}
break;