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

218 lines
6.5 KiB
C++

/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
dl_mk_bit_blast.cpp
Abstract:
<abstract>
Author:
Nikolaj Bjorner (nbjorner) 2012-08-30
Revision History:
--*/
#include "dl_mk_bit_blast.h"
#include "bit_blaster_rewriter.h"
#include "rewriter_def.h"
#include "ast_pp.h"
namespace datalog {
//
// P(v) :- Q(extract[1:1]v ++ 0), R(1 ++ extract[0:0]v).
// ->
// P(bv(x,y)) :- Q(bv(x,0)), R(bv(1,y)) .
//
// Introduce P_bv:
// P_bv(x,y) :- Q_bv(x,0), R_bv(1,y)
// P(bv(x,y)) :- P_bv(x,y)
// Query
class expand_mkbv_cfg : public default_rewriter_cfg {
context& m_context;
rule_ref_vector& m_rules;
ast_manager& m;
bv_util m_util;
expr_ref_vector m_args, m_f_vars, m_g_vars;
func_decl_ref_vector m_pinned;
obj_map<func_decl,func_decl*> m_pred2blast;
public:
expand_mkbv_cfg(context& ctx, rule_ref_vector& rules):
m_context(ctx),
m_rules(rules),
m(ctx.get_manager()),
m_util(m),
m_args(m),
m_f_vars(m),
m_g_vars(m),
m_pinned(m)
{}
~expand_mkbv_cfg() {}
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
rule_manager& rm = m_context.get_rule_manager();
bool found = false;
for (unsigned j = 0; !found && j < num; ++j) {
found = m_util.is_mkbv(args[j]);
}
if (!found) {
return BR_FAILED;
}
//
// f(mk_bv(args),...)
//
m_args.reset();
m_g_vars.reset();
m_f_vars.reset();
expr_ref fml(m);
unsigned idx = 0;
for (unsigned j = 0; j < num; ++j) {
expr* arg = args[j];
if (m_util.is_mkbv(arg)) {
app* a = to_app(arg);
unsigned sz = a->get_num_args();
for (unsigned i = 0; i < sz; ++i) {
m_args.push_back(a->get_arg(i));
m_g_vars.push_back(m.mk_var(idx++,m.mk_bool_sort()));
}
m_f_vars.push_back(m_util.mk_bv(sz, m_g_vars.c_ptr()+m_g_vars.size()-sz));
}
else {
m_args.push_back(arg);
m_f_vars.push_back(m.mk_var(idx++, m.get_sort(arg)));
m_g_vars.push_back(m_f_vars.back());
}
}
func_decl* g = 0;
if (!m_pred2blast.find(f, g)) {
ptr_vector<sort> domain;
for (unsigned i = 0; i < m_args.size(); ++i) {
domain.push_back(m.get_sort(m_args[i].get()));
}
g = m_context.mk_fresh_head_predicate(f->get_name(), symbol("bv"), m_args.size(), domain.c_ptr(), f);
m_pinned.push_back(g);
m_pred2blast.insert(f, g);
// Create rule f(mk_mkbv(args)) :- g(args)
fml = m.mk_implies(m.mk_app(g, m_g_vars.size(), m_g_vars.c_ptr()), m.mk_app(f, m_f_vars.size(), m_f_vars.c_ptr()));
rm.mk_rule(fml, m_rules, g->get_name());
}
result = m.mk_app(g, m_args.size(), m_args.c_ptr());
result_pr = 0;
return BR_DONE;
}
};
struct expand_mkbv : public rewriter_tpl<expand_mkbv_cfg> {
expand_mkbv_cfg m_cfg;
expand_mkbv(ast_manager& m, context& ctx, rule_ref_vector& rules):
rewriter_tpl<expand_mkbv_cfg>(m, m.proofs_enabled(), m_cfg),
m_cfg(ctx, rules) {
}
};
class mk_bit_blast::impl {
context & m_context;
ast_manager & m;
params_ref m_params;
rule_ref_vector m_rules;
bit_blaster_rewriter m_blaster;
expand_mkbv m_rewriter;
bool blast(expr_ref& fml) {
proof_ref pr(m);
expr_ref fml1(m), fml2(m);
m_blaster(fml, fml1, pr);
m_rewriter(fml1, fml2);
TRACE("dl", tout << mk_pp(fml, m) << " -> " << mk_pp(fml1, m) << " -> " << mk_pp(fml2, m) << "\n";);
if (fml2 != fml) {
fml = fml2;
return true;
}
else {
return false;
}
}
void reset() {
m_rules.reset();
}
public:
impl(context& ctx):
m_context(ctx),
m(ctx.get_manager()),
m_rules(ctx.get_rule_manager()),
m_params(ctx.get_params()),
m_blaster(ctx.get_manager(), m_params),
m_rewriter(ctx.get_manager(), ctx, m_rules) {
m_params.set_bool(":blast-full", true);
m_params.set_bool(":blast-quant", true);
m_blaster.updt_params(m_params);
}
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
// TODO mc, pc
if (!m_context.get_params().get_bool(":bit-blast", false)) {
return 0;
}
if (m_context.get_engine() != PDR_ENGINE) {
return 0;
}
rule_manager& rm = m_context.get_rule_manager();
unsigned sz = source.get_num_rules();
expr_ref fml(m);
reset();
rule_set * result = alloc(rule_set, m_context);
for (unsigned i = 0; i < sz; ++i) {
rule * r = source.get_rule(i);
r->to_formula(fml);
if (blast(fml)) {
rm.mk_rule(fml, m_rules, r->name());
}
else {
m_rules.push_back(r);
}
}
for (unsigned i = 0; i < m_rules.size(); ++i) {
result->add_rule(m_rules.get(i));
}
return result;
}
};
mk_bit_blast::mk_bit_blast(context & ctx, unsigned priority) : plugin(priority) {
m_impl = alloc(impl, ctx);
}
mk_bit_blast::~mk_bit_blast() {
dealloc(m_impl);
}
rule_set * mk_bit_blast::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
return (*m_impl)(source, mc, pc);
}
};