3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-10 19:27:06 +00:00
z3/lib/ufbv_strategy.cpp
Leonardo de Moura e9eab22e5c Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:35:25 -07:00

493 lines
16 KiB
C++

/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
ufbv_strategy.cpp
Abstract:
General purpose strategy for UFBV benchmarks.
Author:
Christoph (cwinter) 2011-07-28
Notes:
--*/
#include"assertion_set_rewriter.h"
#include"nnf.h"
#include"der.h"
#include"distribute_forall.h"
#include"macro_finder.h"
#include"arith_simplifier_plugin.h"
#include"bv_simplifier_plugin.h"
#include"demodulator.h"
#include"quasi_macros.h"
#include"reduce_args.h"
#include"ufbv_strategy.h"
#include"shallow_context_simplifier.h"
#include"gaussian_elim.h"
#include"elim_var_model_converter.h"
#include"ast_smt2_pp.h"
// --- TRACE STRATEGY
#ifdef _TRACE
class trace_as_st : public assertion_set_strategy {
ast_manager & m;
const char * tag;
public:
trace_as_st(ast_manager & m, const char * tag) : m(m),tag(tag) { }
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
TRACE(tag, { s.display(tout); });
}
virtual void cleanup() {}
};
#endif
as_st * mk_trace_as(ast_manager & m, const char * tag) {
#ifdef _TRACE
return alloc(trace_as_st, m, tag);
#else
return noop();
#endif
}
as_st * mk_der_fp(ast_manager & m, params_ref const & p) {
return repeat(and_then(mk_der(m), mk_simplifier(m, p)));
}
// --- DISTRIBUTE-FORALL STRATEGY
class distribute_forall_st : public assertion_set_strategy {
ast_manager & m;
params_ref m_params;
bool m_produce_models;
bool m_cancel;
public:
distribute_forall_st(ast_manager & m, params_ref const & p = params_ref()) : m(m),m_params(p),m_produce_models(false),m_cancel(false) { }
virtual ~distribute_forall_st() {}
virtual void updt_params(params_ref const & p) {
m_produce_models = p.get_bool(":produce-models", false);
}
static void get_param_descrs(param_descrs & r) {
insert_produce_models(r);
}
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
as_st_report report("distribute-forall", s);
basic_simplifier_plugin bsimp(m);
bsimp.set_eliminate_and(true);
distribute_forall apply_dist(m, bsimp);
for (unsigned i = 0; i < s.size(); i++) {
if (m_cancel)
throw strategy_exception(STE_CANCELED_MSG);
expr * n = s.form(i);
expr_ref r(m);
apply_dist(n, r);
if (n != r.get()) {
if (m.proofs_enabled()) {
proof * old_pr = s.pr(i);
proof_ref new_pr(m);
new_pr = m.mk_rewrite_star(n, r, 0, 0);
new_pr = m.mk_modus_ponens(old_pr, new_pr);
s.update(i, r, new_pr);
}
else
s.update(i, r, 0);
}
}
mc = 0; // CMW: No model conversion necessary; variables and functions don't change.
TRACE("distribute_forall", s.display(tout););
}
virtual void cleanup() {}
protected:
virtual void set_cancel(bool f) { m_cancel = f; }
};
as_st * mk_distribute_forall(ast_manager & m, params_ref const & p) {
return alloc(distribute_forall_st, m, p);
}
model_converter * macro_manager2model_converter(macro_manager const & mm) {
elim_var_model_converter * mc = alloc(elim_var_model_converter, mm.get_manager());
unsigned num = mm.get_num_macros();
for (unsigned i = 0; i < num; i++) {
expr_ref f_interp(mm.get_manager());
func_decl * f = mm.get_macro_interpretation(i, f_interp);
mc->insert(f, f_interp);
}
return mc;
}
// --- MACRO FINDER STRATEGY
class macro_finder_st : public assertion_set_strategy {
ast_manager & m;
params_ref m_params;
bool m_produce_models;
bool m_cancel;
bool m_elim_and;
public:
macro_finder_st(ast_manager & m, params_ref const & p = params_ref(), bool elim_and=false) : m(m),m_params(p),m_produce_models(false),m_cancel(false),m_elim_and(elim_and) { }
virtual ~macro_finder_st() {}
virtual void updt_params(params_ref const & p) {
m_produce_models = p.get_bool(":produce-models", false);
}
static void get_param_descrs(param_descrs & r) {
insert_produce_models(r);
}
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
TRACE("debug_ids", m.display_free_ids(tout); tout << "\n";);
as_st_report report("macro-finder", s);
simplifier simp(m);
basic_simplifier_plugin * bsimp = alloc(basic_simplifier_plugin, m);
bsimp->set_eliminate_and(m_elim_and);
simp.register_plugin(bsimp);
arith_simplifier_params a_params;
arith_simplifier_plugin * asimp = alloc(arith_simplifier_plugin, m, *bsimp, a_params);
simp.register_plugin(asimp);
bv_simplifier_params bv_params;
bv_simplifier_plugin * bvsimp = alloc(bv_simplifier_plugin, m, *bsimp, bv_params);
simp.register_plugin(bvsimp);
macro_manager mm(m, simp);
macro_finder mf(m, mm);
expr_ref_vector forms(m), new_forms(m);
proof_ref_vector proofs(m), new_proofs(m);
for (unsigned i = 0; i < s.size(); i++) {
forms.push_back(s.form(i));
proofs.push_back(s.pr(i));
}
mf(forms.size(), forms.c_ptr(), proofs.c_ptr(), new_forms, new_proofs);
s.reset();
for (unsigned i = 0; i < new_forms.size(); i++) {
s.assert_expr(new_forms.get(i), (m.proofs_enabled()) ? new_proofs.get(i) : 0);
}
mc = macro_manager2model_converter(mm);
TRACE("debug_ids", m.display_free_ids(tout); tout << "\n";);
}
virtual void cleanup() {}
protected:
virtual void set_cancel(bool f) { m_cancel = f; }
};
as_st * mk_macro_finder(ast_manager & m, params_ref const & p, bool elim_and=false) {
return alloc(macro_finder_st, m, p, elim_and);
}
// --- DEMODULATOR STRATEGY
class demodulator_st : public assertion_set_strategy {
ast_manager & m;
params_ref m_params;
bool m_produce_models;
bool m_cancel;
public:
demodulator_st(ast_manager & m, params_ref const & p = params_ref()) : m(m),m_params(p),m_produce_models(false),m_cancel(false) { }
virtual ~demodulator_st() {}
virtual void updt_params(params_ref const & p) {
m_produce_models = p.get_bool(":produce-models", false);
}
static void get_param_descrs(param_descrs & r) {
insert_produce_models(r);
}
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
as_st_report report("demodulator", s);
basic_simplifier_plugin bsimp(m);
bsimp.set_eliminate_and(true);
demodulator dem(m, bsimp);
expr_ref_vector forms(m), new_forms(m);
proof_ref_vector proofs(m), new_proofs(m);
for (unsigned i = 0; i < s.size(); i++) {
forms.push_back(s.form(i));
proofs.push_back(s.pr(i));
}
dem(forms.size(), forms.c_ptr(), proofs.c_ptr(), new_forms, new_proofs);
s.reset();
for (unsigned i = 0; i < new_forms.size(); i++) {
s.assert_expr(new_forms.get(i), (m.proofs_enabled()) ? new_proofs.get(i) : 0);
}
mc = 0; // CMW: The demodulator could potentially remove all references to a variable.
}
virtual void cleanup() {}
protected:
virtual void set_cancel(bool f) { m_cancel = f; }
};
as_st * mk_demodulator(ast_manager & m, params_ref const & p) {
return alloc(demodulator_st, m, p);
}
// --- QUASI-MACROS STRATEGY
class quasi_macros_st : public assertion_set_strategy {
ast_manager & m;
params_ref m_params;
bool m_produce_models;
bool m_cancel;
public:
quasi_macros_st(ast_manager & m, params_ref const & p = params_ref()) : m(m),m_params(p),m_produce_models(false),m_cancel(false) { }
virtual ~quasi_macros_st() {}
virtual void updt_params(params_ref const & p) {
m_produce_models = p.get_bool(":produce-models", false);
}
static void get_param_descrs(param_descrs & r) {
insert_produce_models(r);
}
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
as_st_report report("quasi-macros", s);
simplifier simp(m);
basic_simplifier_plugin * bsimp = alloc(basic_simplifier_plugin, m);
bsimp->set_eliminate_and(true);
simp.register_plugin(bsimp);
arith_simplifier_params a_params;
arith_simplifier_plugin * asimp = alloc(arith_simplifier_plugin, m, *bsimp, a_params);
simp.register_plugin(asimp);
bv_simplifier_params bv_params;
bv_simplifier_plugin * bvsimp = alloc(bv_simplifier_plugin, m, *bsimp, bv_params);
simp.register_plugin(bvsimp);
macro_manager mm(m, simp);
quasi_macros qm(m, mm, *bsimp, simp);
bool more = true;
expr_ref_vector forms(m), new_forms(m);
proof_ref_vector proofs(m), new_proofs(m);
for (unsigned i = 0; i < s.size(); i++) {
forms.push_back(s.form(i));
proofs.push_back(s.pr(i));
}
while (more) { // CMW: This is applied until fixpoint; should we have a fixpoint_as_st for that?
if (m_cancel)
throw strategy_exception(STE_CANCELED_MSG);
new_forms.reset();
new_proofs.reset();
more = qm(forms.size(), forms.c_ptr(), proofs.c_ptr(), new_forms, new_proofs);
forms.swap(new_forms);
proofs.swap(new_proofs);
}
s.reset();
for (unsigned i = 0; i < forms.size(); i++) {
s.assert_expr(forms.get(i), (m.proofs_enabled()) ? proofs.get(i) : 0);
}
mc = macro_manager2model_converter(mm);
}
virtual void cleanup() {}
protected:
virtual void set_cancel(bool f) { m_cancel = f; }
};
as_st * mk_quasi_macros(ast_manager & m, params_ref const & p) {
return alloc(quasi_macros_st, m, p);
}
// --- ELIMINATE AND STRATEGY
as_st * mk_eliminate_and(ast_manager & m, params_ref const & p) {
params_ref elim_and_p;
elim_and_p.set_bool(":elim-and", true);
return using_params(mk_simplifier(m, p), elim_and_p);
}
// --- DISPLAY ASSERTION SET STRATEGY
// CMW: This was a temporary hack. Use cmd_context to print benchmark files.
//class display_as_st : public assertion_set_strategy {
// ast_manager & m;
// params_ref m_params;
//
//public:
// display_as_st (ast_manager & m, params_ref const & p = params_ref()) : m(m),m_params(p) { }
// virtual ~display_as_st() {}
//
// virtual void updt_params(params_ref const & p) {}
//
// static void get_param_descrs(param_descrs & r) {}
//
// virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
//
// struct find_uf_proc {
// ast_manager & m_manager;
// obj_hashtable<func_decl> & m_fds;
//
// find_uf_proc(ast_manager & m, obj_hashtable<func_decl> & fds):
// m_manager(m),
// m_fds(fds) {
// }
//
// void operator()(var * n) {}
//
// void operator()(quantifier * n) {}
//
// void operator()(app * n) {
// func_decl * d = n->get_decl();
// if (d->get_family_id() != null_family_id)
// return; // ignore interpreted symbols
// m_fds.insert(d);
// }
// };
//
// virtual void operator()(assertion_set & s, model_converter_ref & mc) {
// std::cerr << "(set-info :source ||)" << std::endl;
// std::cerr << "(set-info :status unknown)" << std::endl;
// std::cerr << "(set-logic UFBV)" << std::endl;
//
// // Find functions
// obj_hashtable<func_decl> fds;
// find_uf_proc proc(m, fds);
// unsigned sz = s.size();
// for (unsigned i = 0; i < sz; i++) {
// expr_fast_mark1 visited;
// quick_for_each_expr(proc, visited, s.form(i));
// }
//
// // print functions
// for (obj_hashtable<func_decl>::iterator it = fds.begin(); it != fds.end(); it++) {
// // How do we print (declare-fun ...) ?
// std::cerr << mk_ismt2_pp(*it, m) << std::endl;
// }
//
// // print assertions
// for (unsigned i = 0; i < s.size(); i++) {
// std::cerr << "(assert ";
// std::cerr << mk_ismt2_pp(s.form(i), m);
// std::cerr << ")" << std::endl;
// }
// std::cerr << "(check-sat)" << std::endl;
// }
//
// virtual void cleanup() {}
//protected:
// virtual void set_cancel(bool f) {}
//};
//
//as_st * mk_display_as(ast_manager & m, params_ref const & p) {
// return alloc(display_as_st, m, p);
//}
class debug_ids_st : public assertion_set_strategy {
ast_manager & m;
struct proc {
ast_manager & m;
proc(ast_manager & _m):m(_m) {}
void operator()(var * n) { TRACE_CODE(tout << n->get_id() << " ";); }
void operator()(app * n) { TRACE_CODE(tout << n->get_id() << " ";); }
void operator()(quantifier * n) { TRACE_CODE(tout << n->get_id() << " ";); }
};
public:
debug_ids_st(ast_manager & _m):m(_m) {}
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
mc = 0;
TRACE("debug_ids",
tout << "free ids:\n"; m.display_free_ids(tout); tout << "\n";
proc p(m);
tout << "assertion_set ids:\n";
for_each_expr_as(p, s);
tout << "\n";);
}
virtual void cleanup() {}
};
// --- UFBV STRATEGY
as_st * mk_preprocessor(ast_manager & m, params_ref const & p) {
return and_then(mk_trace_as(m, "ufbv_pre"),
and_then( mk_simplifier(m, p),
mk_constant_propagation(m, p),
and_then(mk_macro_finder(m, p, false), mk_simplifier(m, p)),
and_then(mk_snf(p), mk_simplifier(m, p)),
mk_eliminate_and(m, p),
mk_eq_solver(m, p),
and_then(mk_der_fp(m, p), mk_simplifier(m, p)),
and_then(mk_distribute_forall(m, p), mk_simplifier(m, p))
),
and_then( and_then(mk_reduce_args(m, p), mk_simplifier(m, p)),
and_then(mk_macro_finder(m, p, true), mk_simplifier(m, p)),
and_then(mk_demodulator(m, p), mk_simplifier(m, p)),
and_then(mk_quasi_macros(m, p), mk_simplifier(m, p)),
and_then(mk_der_fp(m, p), mk_simplifier(m, p)),
mk_simplifier(m, p)),
mk_trace_as(m, "ufbv_post"));
}
as_st * mk_ufbv_strategy(ast_manager & m, params_ref const & p) {
params_ref main_p(p);
main_p.set_bool(":mbqi", true);
main_p.set_uint(":mbqi-max-iterations", -1);
main_p.set_bool(":elim-and", true);
main_p.set_bool(":solver", true);
// this prints the skolemized version of a benchmark
// as_st * st = and_then(mk_skolemizer(m, main_p), mk_display_as(m, main_p));
as_st * st = and_then(repeat(mk_preprocessor(m, main_p), 2),
alloc(debug_ids_st, m),
using_params(mk_smt_solver(false), main_p));
st->updt_params(p);
return st;
}