3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 18:31:49 +00:00

preparing handling of arrays/quantifiers, fix cover-related bugs reported by Arie

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2012-11-25 12:08:49 -08:00
parent 6834abd781
commit 93ad91d2f9
16 changed files with 1134 additions and 705 deletions

View file

@ -144,7 +144,21 @@ public:
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_tree(expr * n);
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); }
bool is_map(func_decl* f) const { return is_decl_of(f, m_fid, OP_ARRAY_MAP); }
bool is_as_array(func_decl* f) const { return is_decl_of(f, m_fid, OP_AS_ARRAY); }
func_decl * get_as_array_func_decl(app * n) const { SASSERT(is_as_array(n)); return to_func_decl(n->get_decl()->get_parameter(0).get_ast()); }
app * mk_store(unsigned num_args, expr * const * args) {
return m_manager.mk_app(m_fid, OP_STORE, 0, 0, num_args, args);
}
app * mk_select(unsigned num_args, expr * const * args) {
return m_manager.mk_app(m_fid, OP_SELECT, 0, 0, num_args, args);
}
app * mk_map(func_decl * f, unsigned num_args, expr * const * args) {
parameter p(f);
return m_manager.mk_app(m_fid, OP_ARRAY_MAP, 1, &p, num_args, args);

View file

@ -44,8 +44,7 @@ namespace datalog {
m_num_sym("N"),
m_lt_sym("<"),
m_le_sym("<="),
m_rule_sym("R"),
m_hyper_resolve_sym("hyper-res")
m_rule_sym("R")
{
}

View file

@ -69,7 +69,6 @@ namespace datalog {
symbol m_lt_sym;
symbol m_le_sym;
symbol m_rule_sym;
symbol m_hyper_resolve_sym;
bool check_bounds(char const* msg, unsigned low, unsigned up, unsigned val) const;
bool check_domain(unsigned low, unsigned up, unsigned val) const;
@ -93,7 +92,6 @@ namespace datalog {
func_decl * mk_compare(decl_kind k, symbol const& sym, sort*const* domain);
func_decl * mk_clone(sort* r);
func_decl * mk_rule(unsigned arity);
func_decl * mk_hyper_res(unsigned num_params, parameter const* params, unsigned arity, sort *const* domain);
sort * mk_finite_sort(unsigned num_params, parameter const* params);
sort * mk_relation_sort(unsigned num_params, parameter const* params);

View file

@ -147,7 +147,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
return m_a_rw.mk_app_core(f, num, args, result);
if (fid == m_bv_rw.get_fid())
return m_bv_rw.mk_app_core(f, num, args, result);
if (fid == m_ar_rw.get_fid())
if (fid == m_ar_rw.get_fid())
return m_ar_rw.mk_app_core(f, num, args, result);
if (fid == m_dt_rw.get_fid())
return m_dt_rw.mk_app_core(f, num, args, result);

View file

@ -54,6 +54,7 @@ Revision History:
#include"expr_functors.h"
#include"dl_mk_partial_equiv.h"
#include"dl_mk_bit_blast.h"
#include"dl_mk_array_blast.h"
#include"datatype_decl_plugin.h"
#include"expr_abstract.h"
@ -944,6 +945,7 @@ namespace datalog {
transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34880));
transf.register_plugin(alloc(datalog::mk_bit_blast, *this, 35000));
transf.register_plugin(alloc(datalog::mk_array_blast, *this, 36000));
transform_rules(transf, mc, pc);
}

View file

@ -0,0 +1,139 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
dl_mk_array_blast.cpp
Abstract:
Remove array variables from rules.
Author:
Nikolaj Bjorner (nbjorner) 2012-11-23
Revision History:
--*/
#include "dl_mk_array_blast.h"
#include "expr_replacer.h"
namespace datalog {
mk_array_blast::mk_array_blast(context & ctx, unsigned priority) :
rule_transformer::plugin(priority, false),
m_ctx(ctx),
m(ctx.get_manager()),
a(m),
rm(ctx.get_rule_manager()),
m_rewriter(m, m_params){
m_params.set_bool(":expand-select-store",true);
m_rewriter.updt_params(m_params);
}
mk_array_blast::~mk_array_blast() {
}
bool mk_array_blast::is_store_def(expr* e, expr*& x, expr*& y) {
if (m.is_iff(e, x, y) || m.is_eq(e, x, y)) {
if (!a.is_store(y)) {
std::swap(x,y);
}
if (is_var(x) && a.is_store(y)) {
return true;
}
}
return false;
}
bool mk_array_blast::blast(rule& r, rule_set& rules) {
unsigned utsz = r.get_uninterpreted_tail_size();
unsigned tsz = r.get_tail_size();
expr_ref_vector conjs(m), new_conjs(m);
for (unsigned i = 0; i < utsz; ++i) {
new_conjs.push_back(r.get_tail(i));
}
for (unsigned i = utsz; i < tsz; ++i) {
conjs.push_back(r.get_tail(i));
}
flatten_and(conjs);
expr_substitution sub(m);
uint_set lhs_vars, rhs_vars;
for (unsigned i = 0; i < conjs.size(); ++i) {
expr* x, *y;
if (is_store_def(conjs[i].get(), x, y)) {
// enforce topological order consistency:
uint_set lhs;
collect_vars(m, x, lhs_vars);
collect_vars(m, y, rhs_vars);
lhs = lhs_vars;
lhs &= rhs_vars;
if (!lhs.empty()) {
new_conjs.push_back(conjs[i].get());
}
else {
sub.insert(x, y);
}
}
else {
new_conjs.push_back(conjs[i].get());
}
}
if (sub.empty()) {
rules.add_rule(&r);
return false;
}
rule_ref_vector new_rules(rm);
expr_ref fml1(m), fml2(m), body(m), head(m);
r.to_formula(fml1);
body = m.mk_and(new_conjs.size(), new_conjs.c_ptr());
head = r.get_head();
scoped_ptr<expr_replacer> replace = mk_default_expr_replacer(m);
replace->set_substitution(&sub);
(*replace)(body);
m_rewriter(body);
(*replace)(head);
m_rewriter(head);
fml2 = m.mk_implies(body, head);
rm.mk_rule(fml2, new_rules, r.name());
SASSERT(new_rules.size() == 1);
rules.add_rule(new_rules[0].get());
if (m_pc) {
new_rules[0]->to_formula(fml2);
m_pc->insert(fml1, fml2);
}
return true;
}
rule_set * mk_array_blast::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
ref<equiv_proof_converter> epc;
if (pc) {
epc = alloc(equiv_proof_converter, m);
}
m_pc = epc.get();
rule_set* rules = alloc(rule_set, m_ctx);
rule_set::iterator it = source.begin(), end = source.end();
bool change = false;
for (; it != end; ++it) {
change = blast(**it, *rules) || change;
}
if (!change) {
dealloc(rules);
rules = 0;
}
if (pc) {
pc = concat(pc.get(), epc.get());
}
return rules;
}
};

View file

@ -0,0 +1,61 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
dl_mk_array_blast.h
Abstract:
Remove array variables from rules.
Author:
Nikolaj Bjorner (nbjorner) 2012-11-23
Revision History:
--*/
#ifndef _DL_MK_ARRAY_BLAST_H_
#define _DL_MK_ARRAY_BLAST_H_
#include"dl_context.h"
#include"dl_rule_set.h"
#include"dl_rule_transformer.h"
#include "equiv_proof_converter.h"
#include "array_decl_plugin.h"
namespace datalog {
/**
\brief Blast occurrences of arrays in rules
*/
class mk_array_blast : public rule_transformer::plugin {
context& m_ctx;
ast_manager& m;
array_util a;
rule_manager& rm;
params_ref m_params;
th_rewriter m_rewriter;
equiv_proof_converter* m_pc;
bool blast(rule& r, rule_set& new_rules);
bool is_store_def(expr* e, expr*& x, expr*& y);
public:
/**
\brief Create rule transformer that extracts universal quantifiers (over recursive predicates).
*/
mk_array_blast(context & ctx, unsigned priority);
virtual ~mk_array_blast();
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
};
};
#endif /* _DL_MK_ARRAY_BLAST_H_ */

View file

@ -40,29 +40,32 @@ namespace datalog {
void mk_extract_quantifiers::extract(rule& r, rule_set& new_rules) {
app_ref_vector tail(m);
svector<bool> neg_tail;
expr_ref_vector tail(m);
quantifier_ref_vector quantifiers(m);
unsigned utsz = r.get_uninterpreted_tail_size();
unsigned tsz = r.get_tail_size();
for (unsigned i = 0; i < utsz; ++i) {
tail.push_back(r.get_tail(i));
neg_tail.push_back(r.is_neg_tail(i));
if (r.is_neg_tail(i)) {
new_rules.add_rule(&r);
return;
}
}
for (unsigned i = utsz; i < tsz; ++i) {
SASSERT(!r.is_neg_tail(i));
app* t = r.get_tail(i);
expr_ref_vector conjs(m);
datalog::flatten_and(t, conjs);
quantifier_ref qe(m);
quantifier* q = 0;
for (unsigned j = 0; j < conjs.size(); ++j) {
expr* e = conjs[j].get();
quantifier* q = 0;
if (rule_manager::is_forall(m, e, q)) {
quantifiers.push_back(q);
qe = m.mk_exists(q->get_num_decls(), q->get_decl_sorts(), q->get_decl_names(), q->get_expr());
tail.push_back(qe);
}
else {
tail.push_back(is_app(e)?to_app(e):m.mk_eq(e, m.mk_true()));
neg_tail.push_back(false);
tail.push_back(e);
}
}
}
@ -70,11 +73,16 @@ namespace datalog {
new_rules.add_rule(&r);
}
else {
rule* new_rule = rm.mk(r.get_head(), tail.size(), tail.c_ptr(), neg_tail.c_ptr(), r.name(), false);
new_rules.add_rule(new_rule);
expr_ref fml(m);
rule_ref_vector rules(rm);
fml = m.mk_implies(m.mk_and(tail.size(), tail.c_ptr()), r.get_head());
rm.mk_rule(fml, rules, r.name());
quantifier_ref_vector* qs = alloc(quantifier_ref_vector, quantifiers);
m_quantifiers.insert(new_rule, qs);
m_refs.push_back(qs);
for (unsigned i = 0; i < rules.size(); ++i) {
m_quantifiers.insert(rules[i].get(), qs);
new_rules.add_rule(rules[i].get());
}
}
}

View file

@ -196,6 +196,12 @@ namespace datalog {
scoped_no_proof(ast_manager& m): scoped_proof_mode(m, PGM_DISABLED) {}
};
class scoped_restore_proof : public scoped_proof_mode {
public:
scoped_restore_proof(ast_manager& m): scoped_proof_mode(m, m.proof_mode()) {}
};
class variable_intersection

View file

@ -0,0 +1,58 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
equiv_proof_converter.h
Abstract:
Proof converter that applies equivalence rule to leaves.
Given a proof P with occurrences of [asserted fml]
replace [asserted fml] by a proof of the form
[mp [asserted fml'] [~ fml fml']]
Author:
Nikolaj Bjorner (nbjorner) 2012-11-23
Revision History:
--*/
#ifndef _EQUIV_PROOF_CONVERTER_H_
#define _EQUIV_PROOF_CONVERTER_H_
#include "replace_proof_converter.h"
class equiv_proof_converter : public proof_converter {
ast_manager& m;
replace_proof_converter m_replace;
public:
equiv_proof_converter(ast_manager& m): m(m), m_replace(m) {}
virtual ~equiv_proof_converter() {}
virtual void operator()(ast_manager & m, unsigned num_source, proof * const * source, proof_ref & result) {
m_replace(m, num_source, source, result);
}
virtual proof_converter * translate(ast_translation & translator) {
return m_replace.translate(translator);
}
void insert(expr* fml1, expr* fml2) {
proof_ref p1(m), p2(m), p3(m);
p1 = m.mk_asserted(fml1);
p2 = m.mk_rewrite(fml1, fml2);
p3 = m.mk_modus_ponens(p1, p2);
m_replace.insert(p3);
}
ast_manager& get_manager() { return m; }
};
#endif

View file

@ -35,7 +35,6 @@ Notes:
#include "pdr_generalizers.h"
#include "datatype_decl_plugin.h"
#include "for_each_expr.h"
#include "model_v2_pp.h"
#include "dl_rule_set.h"
#include "unit_subsumption_tactic.h"
#include "model_smt2_pp.h"
@ -146,7 +145,6 @@ namespace pdr {
expr_ref vl(m);
for (; it != end; ++it) {
expr* pred = it->m_key;
TRACE("pdr", tout << mk_pp(pred, m) << "\n";);
if (model.eval(to_app(pred)->get_decl(), vl) && m.is_true(vl)) {
return *it->m_value;
}
@ -362,7 +360,7 @@ namespace pdr {
}
// replace local constants by bound variables.
expr_substitution sub(m);
for (unsigned i = 0; i < m_sig.size(); ++i) {
for (unsigned i = 0; i < sig_size(); ++i) {
c = m.mk_const(pm.o2n(sig(i), 0));
v = m.mk_var(i, sig(i)->get_range());
sub.insert(c, v);
@ -397,7 +395,7 @@ namespace pdr {
// replace bound variables by local constants.
expr_ref result(property, m), v(m), c(m);
expr_substitution sub(m);
for (unsigned i = 0; i < m_sig.size(); ++i) {
for (unsigned i = 0; i < sig_size(); ++i) {
c = m.mk_const(pm.o2n(sig(i), 0));
v = m.mk_var(i, sig(i)->get_range());
sub.insert(v, c);
@ -602,6 +600,12 @@ namespace pdr {
}
m_rule2inst.insert(&rule,&var_reprs);
m_rule2vars.insert(&rule, aux_vars);
TRACE("pdr",
tout << rule.get_decl()->get_name() << "\n";
for (unsigned i = 0; i < var_reprs.size(); ++i) {
tout << mk_pp(var_reprs[i].get(), m) << " ";
}
tout << "\n";);
}
bool pred_transformer::check_filled(app_ref_vector const& v) const {
@ -723,7 +727,7 @@ namespace pdr {
pred_transformer& p = pt();
ast_manager& m = p.get_manager();
manager& pm = p.get_pdr_manager();
TRACE("pdr", model_v2_pp(tout, get_model()););
TRACE("pdr", model_smt2_pp(tout, m, get_model(), 0););
func_decl* f = p.head();
unsigned arity = f->get_arity();
expr_ref_vector args(m);

View file

@ -116,6 +116,7 @@ namespace pdr {
ptr_vector<datalog::rule> const& rules() const { return m_rules; }
func_decl* sig(unsigned i) { init_sig(); return m_sig[i].get(); } // signature
func_decl* const* sig() { init_sig(); return m_sig.c_ptr(); }
unsigned sig_size() { init_sig(); return m_sig.size(); }
expr* transition() const { return m_transition; }
expr* initial_state() const { return m_initial_state; }
expr* rule2tag(datalog::rule const* r) { return m_rule2tag.find(r); }

View file

@ -58,18 +58,18 @@ dl_interface::~dl_interface() {
//
void dl_interface::check_reset() {
datalog::rule_ref_vector const& new_rules = m_ctx.get_rules().get_rules();
datalog::rule_ref_vector const& old_rules = m_old_rules.get_rules();
for (unsigned i = 0; i < new_rules.size(); ++i) {
bool found = false;
for (unsigned j = 0; !found && j < old_rules.size(); ++j) {
datalog::rule_ref_vector const& old_rules = m_old_rules.get_rules();
bool is_subsumed = !old_rules.empty();
for (unsigned i = 0; is_subsumed && i < new_rules.size(); ++i) {
is_subsumed = false;
for (unsigned j = 0; !is_subsumed && j < old_rules.size(); ++j) {
if (m_ctx.check_subsumes(*old_rules[j], *new_rules[i])) {
found = true;
is_subsumed = true;
}
}
if (!found) {
CTRACE("pdr", (old_rules.size() > 0), new_rules[i]->display(m_ctx, tout << "Fresh rule "););
if (!is_subsumed) {
TRACE("pdr", new_rules[i]->display(m_ctx, tout << "Fresh rule "););
m_context->reset();
break;
}
}
m_old_rules.reset();
@ -160,6 +160,8 @@ lbool dl_interface::query(expr * query) {
m_ctx.replace_rules(old_rules);
quantifier_model_checker quantifier_mc(*m_context, m, extract_quantifiers->quantifiers(), m_pdr_rules);
datalog::scoped_restore_proof _sc(m); // update_rules may overwrite the proof mode.
m_context->set_proof_converter(pc);
m_context->set_model_converter(mc);

View file

@ -24,6 +24,7 @@ Revision History:
#include "qe.h"
#include "var_subst.h"
#include "dl_rule_set.h"
#include "model_smt2_pp.h"
namespace pdr {
@ -181,25 +182,21 @@ namespace pdr {
bool found_instance = false;
TRACE("pdr", tout << mk_pp(m_A,m) << "\n";);
ast_manager mp(PGM_COARSE);
ast_translation tr(m, mp);
ast_translation rev_tr(mp, m);
expr_ref_vector fmls(mp);
datalog::scoped_coarse_proof _scp(m);
expr_ref_vector fmls(m);
front_end_params fparams;
fparams.m_proof_mode = PGM_COARSE;
// TBD: does not work on integers: fparams.m_mbqi = true;
expr_ref C(m);
fmls.push_back(tr(m_A.get()));
for (unsigned i = 0; i < m_Bs.size(); ++i) {
C = m.update_quantifier(qs[i], m_Bs[i].get());
fmls.push_back(tr(C.get()));
}
fmls.push_back(m_A.get());
fmls.append(m_Bs);
TRACE("pdr",
tout << "assert\n";
for (unsigned i = 0; i < fmls.size(); ++i) {
tout << mk_pp(fmls[i].get(), mp) << "\n";
tout << mk_pp(fmls[i].get(), m) << "\n";
});
smt::kernel solver(mp, fparams);
smt::kernel solver(m, fparams);
for (unsigned i = 0; i < fmls.size(); ++i) {
solver.assert_expr(fmls[i].get());
}
@ -216,8 +213,8 @@ namespace pdr {
}
proof* p = solver.get_proof();
TRACE("pdr", tout << mk_ismt2_pp(p, mp) << "\n";);
collect_insts collector(mp);
TRACE("pdr", tout << mk_ismt2_pp(p, m) << "\n";);
collect_insts collector(m);
for_each_expr(collector, p);
ptr_vector<quantifier> const& quants = collector.quantifiers();
@ -225,20 +222,20 @@ namespace pdr {
symbol qid = quants[i]->get_qid();
if (!qid_map.find(qid, q)) {
TRACE("pdr", tout << "Could not find quantifier "
<< mk_pp(quants[i], mp) << "\n";);
<< mk_pp(quants[i], m) << "\n";);
continue;
}
expr_ref_vector const& binding = collector.bindings()[i];
TRACE("pdr", tout << "Instantiating:\n" << mk_pp(quants[i], mp) << "\n";
TRACE("pdr", tout << "Instantiating:\n" << mk_pp(quants[i], m) << "\n";
for (unsigned j = 0; j < binding.size(); ++j) {
tout << mk_pp(binding[j], mp) << " ";
tout << mk_pp(binding[j], m) << " ";
}
tout << "\n";);
expr_ref_vector new_binding(m);
for (unsigned j = 0; j < binding.size(); ++j) {
new_binding.push_back(rev_tr(binding[j]));
new_binding.push_back(binding[j]);
}
add_binding(q, new_binding);
found_instance = true;
@ -258,11 +255,32 @@ namespace pdr {
return found_instance;
}
/**
Given node:
- pt - predicate transformer for rule:
P(x) :- Body1(x,y) || Body2(x,z) & (Fa u . Q(u,x,z)).
- rule - P(x) :- Body2(x,z)
- qis - Fa u . Q(u,x,z)
- A := node.state(x) && Body2(x,y)
- Bs := array of Bs of the form:
. Fa u . Q(u, P_x, P_y) - instantiate quantifier to P variables.
. B := inv(Q_0,Q_1,Q_2)
. B := inv(u, P_x, P_y) := B[u/Q_0, P_x/Q_1, P_y/Q_2]
. B := Fa u . inv(u, P_x, P_y)
*/
void quantifier_model_checker::model_check_node(model_node& node) {
TRACE("pdr", node.display(tout, 0););
pred_transformer& pt = node.pt();
manager& pm = pt.get_pdr_manager();
expr_ref A(m), B(m), C(m);
expr_ref A(m), B(m), C(m), v(m);
expr_ref_vector As(m);
m_Bs.reset();
//
@ -285,8 +303,12 @@ namespace pdr {
return;
}
unsigned level = node.level();
unsigned previous_level = (level == 0)?0:(level-1);
if (level == 0) {
return;
}
unsigned previous_level = level - 1;
As.push_back(pt.get_propagation_formula(m_ctx.get_pred_transformers(), level));
As.push_back(node.state());
As.push_back(pt.rule2tag(m_current_rule));
@ -296,28 +318,42 @@ namespace pdr {
{
datalog::scoped_no_proof _no_proof(m);
quantifier_ref q(m);
scoped_ptr<expr_replacer> rep = mk_default_expr_replacer(m);
for (unsigned j = 0; j < qis->size(); ++j) {
quantifier* q = (*qis)[j].get();
q = (*qis)[j].get();
app_ref_vector& inst = pt.get_inst(m_current_rule);
ptr_vector<app>& aux_vars = pt.get_aux_vars(*m_current_rule);
TRACE("pdr",
tout << "q:\n" << mk_pp(q, m) << "\n";
tout << "level: " << level << "\n";
model_smt2_pp(tout, m, node.get_model(), 0);
m_current_rule->display(m_ctx.get_context(), tout << "rule:\n");
);
var_subst vs(m, false);
vs(q, inst.size(), (expr*const*)inst.c_ptr(), B);
q = to_quantifier(B);
TRACE("pdr", tout << "q instantiated:\n" << mk_pp(q, m) << "\n";);
app* a = to_app(q->get_expr());
func_decl* f = a->get_decl();
pred_transformer& pt2 = m_ctx.get_pred_transformer(f);
B = pt2.get_formulas(previous_level, true);
TRACE("pdr", tout << "B:\n" << mk_pp(B, m) << "\n";);
expr_substitution sub(m);
expr_ref_vector refs(m);
for (unsigned i = 0; i < a->get_num_args(); ++i) {
expr* v = m.mk_const(pm.o2n(pt2.sig(i),0));
v = m.mk_const(pm.o2n(pt2.sig(i),0));
sub.insert(v, a->get_arg(i));
refs.push_back(v);
}
rep->set_substitution(&sub);
(*rep)(B);
app_ref_vector& inst = pt.get_inst(m_current_rule);
ptr_vector<app>& aux_vars = pt.get_aux_vars(*m_current_rule);
pt.ground_free_vars(B, inst, aux_vars);
var_subst vs(m, false);
vs(B, inst.size(), (expr*const*)inst.c_ptr(), B);
TRACE("pdr", tout << "B substituted:\n" << mk_pp(B, m) << "\n";);
B = m.update_quantifier(q, B);
m_Bs.push_back(B);
}
}

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,7 @@ Revision History:
#include "trace.h"
#include "vector.h"
#include "arith_decl_plugin.h"
#include "array_decl_plugin.h"
#include "bv_decl_plugin.h"
@ -56,6 +57,7 @@ namespace pdr {
class model_evaluator {
ast_manager& m;
arith_util m_arith;
array_util m_array;
obj_map<expr,rational> m_numbers;
expr_ref_vector m_refs;
obj_map<expr, expr*> m_values;
@ -78,7 +80,8 @@ namespace pdr {
expr_ref_vector prune_by_cone_of_influence(ptr_vector<expr> const & formulas);
void eval_arith(app* e);
void eval_basic(app* e);
void eval_iff(app* e, expr* arg1, expr* arg2);
void eval_eq(app* e, expr* arg1, expr* arg2);
void eval_array_eq(app* e, expr* arg1, expr* arg2);
void inherit_value(expr* e, expr* v);
inline bool is_unknown(expr* x) { return !m1.is_marked(x) && !m2.is_marked(x); }
@ -99,9 +102,11 @@ namespace pdr {
inline void set_value(expr* x, expr* v) { set_v(x); m_refs.push_back(v); m_values.insert(x, v); }
bool check_model(ptr_vector<expr> const & formulas);
bool extract_array_func_interp(expr* a, vector<expr_ref_vector>& stores, expr_ref else_case);
public:
model_evaluator(ast_manager& m) : m(m), m_arith(m), m_refs(m) {}
model_evaluator(ast_manager& m) : m(m), m_arith(m), m_array(m), m_refs(m) {}
/**
\brief extract equalities from model that suffice to satisfy formula.
@ -118,13 +123,12 @@ namespace pdr {
*/
expr_ref_vector minimize_literals(ptr_vector<expr> const & formulas, model_ref& mdl);
// for_each_expr visitor.
/**
for_each_expr visitor.
*/
void operator()(expr* e) {}
};
void get_value_from_model(const model_core & mdl, func_decl * f, expr_ref& res);
/**
\brief replace variables that are used in many disequalities by
an equality using the model.