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

make proto-model evaluation use model_evaluator instead of legacy evaluator

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2016-03-05 10:14:15 -08:00
parent 6fef24edb4
commit 70f13ced33
22 changed files with 528 additions and 297 deletions

View file

@ -2095,6 +2095,7 @@ inline app * ast_manager::mk_app_core(func_decl * decl, expr * arg1, expr * arg2
} }
app * ast_manager::mk_app(func_decl * decl, unsigned num_args, expr * const * args) { app * ast_manager::mk_app(func_decl * decl, unsigned num_args, expr * const * args) {
bool type_error = bool type_error =
decl->get_arity() != num_args && !decl->is_right_associative() && decl->get_arity() != num_args && !decl->is_right_associative() &&
!decl->is_left_associative() && !decl->is_chainable(); !decl->is_left_associative() && !decl->is_chainable();

View file

@ -1075,7 +1075,7 @@ public:
if (strcmp(var_prefix, ALIAS_PREFIX) == 0) { if (strcmp(var_prefix, ALIAS_PREFIX) == 0) {
var_prefix = "_a"; var_prefix = "_a";
} }
unsigned idx = 1; unsigned idx = 0;
for (unsigned i = 0; i < num; i++) { for (unsigned i = 0; i < num; i++) {
symbol name = next_name(var_prefix, idx); symbol name = next_name(var_prefix, idx);
name = ensure_quote_sym(name); name = ensure_quote_sym(name);

View file

@ -0,0 +1,270 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
fpa2bv_rewriter.cpp
Abstract:
Rewriter for converting FPA to BV
Author:
Christoph (cwinter) 2012-02-09
Notes:
--*/
#include"rewriter_def.h"
#include"fpa2bv_rewriter.h"
#include"cooperate.h"
#include"fpa2bv_rewriter_params.hpp"
fpa2bv_rewriter_cfg::fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c, params_ref const & p) :
m_manager(m),
m_out(m),
m_conv(c),
m_bindings(m)
{
updt_params(p);
// We need to make sure that the mananger has the BV plugin loaded.
symbol s_bv("bv");
if (!m_manager.has_plugin(s_bv))
m_manager.register_plugin(s_bv, alloc(bv_decl_plugin));
}
void fpa2bv_rewriter_cfg::updt_local_params(params_ref const & _p) {
fpa2bv_rewriter_params p(_p);
bool v = p.hi_fp_unspecified();
m_conv.set_unspecified_fp_hi(v);
}
void fpa2bv_rewriter_cfg::updt_params(params_ref const & p) {
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
m_max_steps = p.get_uint("max_steps", UINT_MAX);
updt_local_params(p);
}
bool fpa2bv_rewriter_cfg::max_steps_exceeded(unsigned num_steps) const {
cooperate("fpa2bv");
return num_steps > m_max_steps;
}
br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
TRACE("fpa2bv_rw", tout << "APP: " << f->get_name() << std::endl; );
if (num == 0 && f->get_family_id() == null_family_id && m_conv.is_float(f->get_range())) {
m_conv.mk_const(f, result);
return BR_DONE;
}
if (num == 0 && f->get_family_id() == null_family_id && m_conv.is_rm(f->get_range())) {
m_conv.mk_rm_const(f, result);
return BR_DONE;
}
if (m().is_eq(f)) {
SASSERT(num == 2);
TRACE("fpa2bv_rw", tout << "(= " << mk_ismt2_pp(args[0], m()) << " " <<
mk_ismt2_pp(args[1], m()) << ")" << std::endl;);
SASSERT(m().get_sort(args[0]) == m().get_sort(args[1]));
sort * ds = f->get_domain()[0];
if (m_conv.is_float(ds)) {
m_conv.mk_eq(args[0], args[1], result);
return BR_DONE;
}
else if (m_conv.is_rm(ds)) {
result = m().mk_eq(args[0], args[1]);
return BR_DONE;
}
return BR_FAILED;
}
else if (m().is_ite(f)) {
SASSERT(num == 3);
if (m_conv.is_float(args[1])) {
m_conv.mk_ite(args[0], args[1], args[2], result);
return BR_DONE;
}
return BR_FAILED;
}
else if (m().is_distinct(f)) {
sort * ds = f->get_domain()[0];
if (m_conv.is_float(ds) || m_conv.is_rm(ds)) {
m_conv.mk_distinct(f, num, args, result);
return BR_DONE;
}
return BR_FAILED;
}
if (m_conv.is_float_family(f)) {
switch (f->get_decl_kind()) {
case OP_FPA_RM_NEAREST_TIES_TO_AWAY:
case OP_FPA_RM_NEAREST_TIES_TO_EVEN:
case OP_FPA_RM_TOWARD_NEGATIVE:
case OP_FPA_RM_TOWARD_POSITIVE:
case OP_FPA_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE;
case OP_FPA_NUM: m_conv.mk_numeral(f, num, args, result); return BR_DONE;
case OP_FPA_PLUS_INF: m_conv.mk_pinf(f, result); return BR_DONE;
case OP_FPA_MINUS_INF: m_conv.mk_ninf(f, result); return BR_DONE;
case OP_FPA_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE;
case OP_FPA_MINUS_ZERO: m_conv.mk_nzero(f, result); return BR_DONE;
case OP_FPA_NAN: m_conv.mk_nan(f, result); return BR_DONE;
case OP_FPA_ADD: m_conv.mk_add(f, num, args, result); return BR_DONE;
case OP_FPA_SUB: m_conv.mk_sub(f, num, args, result); return BR_DONE;
case OP_FPA_NEG: m_conv.mk_neg(f, num, args, result); return BR_DONE;
case OP_FPA_MUL: m_conv.mk_mul(f, num, args, result); return BR_DONE;
case OP_FPA_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE;
case OP_FPA_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE;
case OP_FPA_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
case OP_FPA_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE;
case OP_FPA_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE;
case OP_FPA_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE;
case OP_FPA_EQ: m_conv.mk_float_eq(f, num, args, result); return BR_DONE;
case OP_FPA_LT: m_conv.mk_float_lt(f, num, args, result); return BR_DONE;
case OP_FPA_GT: m_conv.mk_float_gt(f, num, args, result); return BR_DONE;
case OP_FPA_LE: m_conv.mk_float_le(f, num, args, result); return BR_DONE;
case OP_FPA_GE: m_conv.mk_float_ge(f, num, args, result); return BR_DONE;
case OP_FPA_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE;
case OP_FPA_IS_NAN: m_conv.mk_is_nan(f, num, args, result); return BR_DONE;
case OP_FPA_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE;
case OP_FPA_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE;
case OP_FPA_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE;
case OP_FPA_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE;
case OP_FPA_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE;
case OP_FPA_TO_FP: m_conv.mk_to_fp(f, num, args, result); return BR_DONE;
case OP_FPA_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE;
case OP_FPA_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE;
case OP_FPA_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE;
case OP_FPA_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE;
case OP_FPA_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE;
case OP_FPA_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_REWRITE_FULL;
case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_REWRITE_FULL;
case OP_FPA_INTERNAL_MIN_UNSPECIFIED: result = m_conv.mk_min_unspecified(f, args[0], args[1]); return BR_DONE;
case OP_FPA_INTERNAL_MAX_UNSPECIFIED: result = m_conv.mk_max_unspecified(f, args[0], args[1]); return BR_DONE;
case OP_FPA_INTERNAL_MIN_I: m_conv.mk_min_i(f, num, args, result); return BR_DONE;
case OP_FPA_INTERNAL_MAX_I: m_conv.mk_max_i(f, num, args, result); return BR_DONE;
case OP_FPA_INTERNAL_RM:
case OP_FPA_INTERNAL_BVWRAP:
case OP_FPA_INTERNAL_BVUNWRAP:
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: return BR_FAILED;
default:
TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n";
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;);
NOT_IMPLEMENTED_YET();
}
}
else {
SASSERT(!m_conv.is_float_family(f));
bool is_float_uf = m_conv.is_float(f->get_range()) || m_conv.is_rm(f->get_range());
for (unsigned i = 0; i < f->get_arity(); i++) {
sort * di = f->get_domain()[i];
is_float_uf |= m_conv.is_float(di) || m_conv.is_rm(di);
}
if (is_float_uf) {
m_conv.mk_uninterpreted_function(f, num, args, result);
return BR_DONE;
}
}
return BR_FAILED;
}
bool fpa2bv_rewriter_cfg::pre_visit(expr * t)
{
TRACE("fpa2bv", tout << "pre_visit: " << mk_ismt2_pp(t, m()) << std::endl;);
if (is_quantifier(t)) {
quantifier * q = to_quantifier(t);
TRACE("fpa2bv", tout << "pre_visit quantifier [" << q->get_id() << "]: " << mk_ismt2_pp(q->get_expr(), m()) << std::endl;);
sort_ref_vector new_bindings(m_manager);
for (unsigned i = 0 ; i < q->get_num_decls(); i++)
new_bindings.push_back(q->get_decl_sort(i));
SASSERT(new_bindings.size() == q->get_num_decls());
m_bindings.append(new_bindings);
}
return true;
}
bool fpa2bv_rewriter_cfg::reduce_quantifier(quantifier * old_q,
expr * new_body,
expr * const * new_patterns,
expr * const * new_no_patterns,
expr_ref & result,
proof_ref & result_pr) {
unsigned curr_sz = m_bindings.size();
SASSERT(old_q->get_num_decls() <= curr_sz);
unsigned num_decls = old_q->get_num_decls();
unsigned old_sz = curr_sz - num_decls;
string_buffer<> name_buffer;
ptr_buffer<sort> new_decl_sorts;
sbuffer<symbol> new_decl_names;
for (unsigned i = 0; i < num_decls; i++) {
symbol const & n = old_q->get_decl_name(i);
sort * s = old_q->get_decl_sort(i);
if (m_conv.is_float(s)) {
unsigned ebits = m_conv.fu().get_ebits(s);
unsigned sbits = m_conv.fu().get_sbits(s);
name_buffer.reset();
name_buffer << n << ".bv";
new_decl_names.push_back(symbol(name_buffer.c_str()));
new_decl_sorts.push_back(m_conv.bu().mk_sort(sbits+ebits));
}
else {
new_decl_sorts.push_back(s);
new_decl_names.push_back(n);
}
}
result = m().mk_quantifier(old_q->is_forall(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
new_body, old_q->get_weight(), old_q->get_qid(), old_q->get_skid(),
old_q->get_num_patterns(), new_patterns, old_q->get_num_no_patterns(), new_no_patterns);
result_pr = 0;
m_bindings.shrink(old_sz);
TRACE("fpa2bv", tout << "reduce_quantifier[" << old_q->get_depth() << "]: " <<
mk_ismt2_pp(old_q->get_expr(), m()) << std::endl <<
" new body: " << mk_ismt2_pp(new_body, m()) << std::endl;
tout << "result = " << mk_ismt2_pp(result, m()) << std::endl;);
return true;
}
bool fpa2bv_rewriter_cfg::reduce_var(var * t, expr_ref & result, proof_ref & result_pr) {
if (t->get_idx() >= m_bindings.size())
return false;
// unsigned inx = m_bindings.size() - t->get_idx() - 1;
expr_ref new_exp(m());
sort * s = t->get_sort();
if (m_conv.is_float(s))
{
expr_ref new_var(m());
unsigned ebits = m_conv.fu().get_ebits(s);
unsigned sbits = m_conv.fu().get_sbits(s);
new_var = m().mk_var(t->get_idx(), m_conv.bu().mk_sort(sbits+ebits));
m_conv.mk_fp(m_conv.bu().mk_extract(sbits+ebits-1, sbits+ebits-1, new_var),
m_conv.bu().mk_extract(ebits - 1, 0, new_var),
m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var),
new_exp);
}
else
new_exp = m().mk_var(t->get_idx(), s);
result = new_exp;
result_pr = 0;
TRACE("fpa2bv", tout << "reduce_var: " << mk_ismt2_pp(t, m()) << " -> " << mk_ismt2_pp(result, m()) << std::endl;);
return true;
}
template class rewriter_tpl<fpa2bv_rewriter_cfg>;

View file

@ -20,11 +20,9 @@ Notes:
#ifndef FPA2BV_REWRITER_H_ #ifndef FPA2BV_REWRITER_H_
#define FPA2BV_REWRITER_H_ #define FPA2BV_REWRITER_H_
#include"cooperate.h" #include"rewriter.h"
#include"rewriter_def.h"
#include"bv_decl_plugin.h" #include"bv_decl_plugin.h"
#include"fpa2bv_converter.h" #include"fpa2bv_converter.h"
#include"fpa2bv_rewriter_params.hpp"
struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
ast_manager & m_manager; ast_manager & m_manager;
@ -37,17 +35,7 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
ast_manager & m() const { return m_manager; } ast_manager & m() const { return m_manager; }
fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c, params_ref const & p) : fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c, params_ref const & p);
m_manager(m),
m_out(m),
m_conv(c),
m_bindings(m) {
updt_params(p);
// We need to make sure that the mananger has the BV plugin loaded.
symbol s_bv("bv");
if (!m_manager.has_plugin(s_bv))
m_manager.register_plugin(s_bv, alloc(bv_decl_plugin));
}
~fpa2bv_rewriter_cfg() { ~fpa2bv_rewriter_cfg() {
} }
@ -59,236 +47,28 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
void reset() { void reset() {
} }
void updt_local_params(params_ref const & _p) { void updt_local_params(params_ref const & _p);
fpa2bv_rewriter_params p(_p);
bool v = p.hi_fp_unspecified();
m_conv.set_unspecified_fp_hi(v);
}
void updt_params(params_ref const & p) { void updt_params(params_ref const & p);
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
m_max_steps = p.get_uint("max_steps", UINT_MAX);
updt_local_params(p);
}
bool max_steps_exceeded(unsigned num_steps) const { bool max_steps_exceeded(unsigned num_steps) const;
cooperate("fpa2bv");
return num_steps > m_max_steps;
}
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr);
TRACE("fpa2bv_rw", tout << "APP: " << f->get_name() << std::endl; );
if (num == 0 && f->get_family_id() == null_family_id && m_conv.is_float(f->get_range())) {
m_conv.mk_const(f, result);
return BR_DONE;
}
if (num == 0 && f->get_family_id() == null_family_id && m_conv.is_rm(f->get_range())) { bool pre_visit(expr * t);
m_conv.mk_rm_const(f, result);
return BR_DONE;
}
if (m().is_eq(f)) {
SASSERT(num == 2);
TRACE("fpa2bv_rw", tout << "(= " << mk_ismt2_pp(args[0], m()) << " " <<
mk_ismt2_pp(args[1], m()) << ")" << std::endl;);
SASSERT(m().get_sort(args[0]) == m().get_sort(args[1]));
sort * ds = f->get_domain()[0];
if (m_conv.is_float(ds)) {
m_conv.mk_eq(args[0], args[1], result);
return BR_DONE;
}
else if (m_conv.is_rm(ds)) {
result = m().mk_eq(args[0], args[1]);
return BR_DONE;
}
return BR_FAILED;
}
else if (m().is_ite(f)) {
SASSERT(num == 3);
if (m_conv.is_float(args[1])) {
m_conv.mk_ite(args[0], args[1], args[2], result);
return BR_DONE;
}
return BR_FAILED;
}
else if (m().is_distinct(f)) {
sort * ds = f->get_domain()[0];
if (m_conv.is_float(ds) || m_conv.is_rm(ds)) {
m_conv.mk_distinct(f, num, args, result);
return BR_DONE;
}
return BR_FAILED;
}
if (m_conv.is_float_family(f)) {
switch (f->get_decl_kind()) {
case OP_FPA_RM_NEAREST_TIES_TO_AWAY:
case OP_FPA_RM_NEAREST_TIES_TO_EVEN:
case OP_FPA_RM_TOWARD_NEGATIVE:
case OP_FPA_RM_TOWARD_POSITIVE:
case OP_FPA_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE;
case OP_FPA_NUM: m_conv.mk_numeral(f, num, args, result); return BR_DONE;
case OP_FPA_PLUS_INF: m_conv.mk_pinf(f, result); return BR_DONE;
case OP_FPA_MINUS_INF: m_conv.mk_ninf(f, result); return BR_DONE;
case OP_FPA_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE;
case OP_FPA_MINUS_ZERO: m_conv.mk_nzero(f, result); return BR_DONE;
case OP_FPA_NAN: m_conv.mk_nan(f, result); return BR_DONE;
case OP_FPA_ADD: m_conv.mk_add(f, num, args, result); return BR_DONE;
case OP_FPA_SUB: m_conv.mk_sub(f, num, args, result); return BR_DONE;
case OP_FPA_NEG: m_conv.mk_neg(f, num, args, result); return BR_DONE;
case OP_FPA_MUL: m_conv.mk_mul(f, num, args, result); return BR_DONE;
case OP_FPA_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE;
case OP_FPA_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE;
case OP_FPA_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
case OP_FPA_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE;
case OP_FPA_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE;
case OP_FPA_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE;
case OP_FPA_EQ: m_conv.mk_float_eq(f, num, args, result); return BR_DONE;
case OP_FPA_LT: m_conv.mk_float_lt(f, num, args, result); return BR_DONE;
case OP_FPA_GT: m_conv.mk_float_gt(f, num, args, result); return BR_DONE;
case OP_FPA_LE: m_conv.mk_float_le(f, num, args, result); return BR_DONE;
case OP_FPA_GE: m_conv.mk_float_ge(f, num, args, result); return BR_DONE;
case OP_FPA_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE;
case OP_FPA_IS_NAN: m_conv.mk_is_nan(f, num, args, result); return BR_DONE;
case OP_FPA_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE;
case OP_FPA_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE;
case OP_FPA_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE;
case OP_FPA_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE;
case OP_FPA_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE;
case OP_FPA_TO_FP: m_conv.mk_to_fp(f, num, args, result); return BR_DONE;
case OP_FPA_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE;
case OP_FPA_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE;
case OP_FPA_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE;
case OP_FPA_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE;
case OP_FPA_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE;
case OP_FPA_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_REWRITE_FULL;
case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_REWRITE_FULL;
case OP_FPA_INTERNAL_MIN_UNSPECIFIED: result = m_conv.mk_min_unspecified(f, args[0], args[1]); return BR_DONE;
case OP_FPA_INTERNAL_MAX_UNSPECIFIED: result = m_conv.mk_max_unspecified(f, args[0], args[1]); return BR_DONE;
case OP_FPA_INTERNAL_MIN_I: m_conv.mk_min_i(f, num, args, result); return BR_DONE;
case OP_FPA_INTERNAL_MAX_I: m_conv.mk_max_i(f, num, args, result); return BR_DONE;
case OP_FPA_INTERNAL_RM:
case OP_FPA_INTERNAL_BVWRAP:
case OP_FPA_INTERNAL_BVUNWRAP:
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: return BR_FAILED;
default:
TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n";
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;);
NOT_IMPLEMENTED_YET();
}
}
else {
SASSERT(!m_conv.is_float_family(f));
bool is_float_uf = m_conv.is_float(f->get_range()) || m_conv.is_rm(f->get_range());
for (unsigned i = 0; i < f->get_arity(); i++) {
sort * di = f->get_domain()[i];
is_float_uf |= m_conv.is_float(di) || m_conv.is_rm(di);
}
if (is_float_uf) {
m_conv.mk_uninterpreted_function(f, num, args, result);
return BR_DONE;
}
}
return BR_FAILED;
}
bool pre_visit(expr * t)
{
TRACE("fpa2bv", tout << "pre_visit: " << mk_ismt2_pp(t, m()) << std::endl;);
if (is_quantifier(t)) {
quantifier * q = to_quantifier(t);
TRACE("fpa2bv", tout << "pre_visit quantifier [" << q->get_id() << "]: " << mk_ismt2_pp(q->get_expr(), m()) << std::endl;);
sort_ref_vector new_bindings(m_manager);
for (unsigned i = 0 ; i < q->get_num_decls(); i++)
new_bindings.push_back(q->get_decl_sort(i));
SASSERT(new_bindings.size() == q->get_num_decls());
m_bindings.append(new_bindings);
}
return true;
}
bool reduce_quantifier(quantifier * old_q, bool reduce_quantifier(quantifier * old_q,
expr * new_body, expr * new_body,
expr * const * new_patterns, expr * const * new_patterns,
expr * const * new_no_patterns, expr * const * new_no_patterns,
expr_ref & result, expr_ref & result,
proof_ref & result_pr) { proof_ref & result_pr);
unsigned curr_sz = m_bindings.size();
SASSERT(old_q->get_num_decls() <= curr_sz);
unsigned num_decls = old_q->get_num_decls();
unsigned old_sz = curr_sz - num_decls;
string_buffer<> name_buffer;
ptr_buffer<sort> new_decl_sorts;
sbuffer<symbol> new_decl_names;
for (unsigned i = 0; i < num_decls; i++) {
symbol const & n = old_q->get_decl_name(i);
sort * s = old_q->get_decl_sort(i);
if (m_conv.is_float(s)) {
unsigned ebits = m_conv.fu().get_ebits(s);
unsigned sbits = m_conv.fu().get_sbits(s);
name_buffer.reset();
name_buffer << n << ".bv";
new_decl_names.push_back(symbol(name_buffer.c_str()));
new_decl_sorts.push_back(m_conv.bu().mk_sort(sbits+ebits));
}
else {
new_decl_sorts.push_back(s);
new_decl_names.push_back(n);
}
}
result = m().mk_quantifier(old_q->is_forall(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
new_body, old_q->get_weight(), old_q->get_qid(), old_q->get_skid(),
old_q->get_num_patterns(), new_patterns, old_q->get_num_no_patterns(), new_no_patterns);
result_pr = 0;
m_bindings.shrink(old_sz);
TRACE("fpa2bv", tout << "reduce_quantifier[" << old_q->get_depth() << "]: " <<
mk_ismt2_pp(old_q->get_expr(), m()) << std::endl <<
" new body: " << mk_ismt2_pp(new_body, m()) << std::endl;
tout << "result = " << mk_ismt2_pp(result, m()) << std::endl;);
return true;
}
bool reduce_var(var * t, expr_ref & result, proof_ref & result_pr) { bool reduce_var(var * t, expr_ref & result, proof_ref & result_pr);
if (t->get_idx() >= m_bindings.size())
return false;
// unsigned inx = m_bindings.size() - t->get_idx() - 1;
expr_ref new_exp(m());
sort * s = t->get_sort();
if (m_conv.is_float(s))
{
expr_ref new_var(m());
unsigned ebits = m_conv.fu().get_ebits(s);
unsigned sbits = m_conv.fu().get_sbits(s);
new_var = m().mk_var(t->get_idx(), m_conv.bu().mk_sort(sbits+ebits));
m_conv.mk_fp(m_conv.bu().mk_extract(sbits+ebits-1, sbits+ebits-1, new_var),
m_conv.bu().mk_extract(ebits - 1, 0, new_var),
m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var),
new_exp);
}
else
new_exp = m().mk_var(t->get_idx(), s);
result = new_exp;
result_pr = 0;
TRACE("fpa2bv", tout << "reduce_var: " << mk_ismt2_pp(t, m()) << " -> " << mk_ismt2_pp(result, m()) << std::endl;);
return true;
}
}; };
template class rewriter_tpl<fpa2bv_rewriter_cfg>;
struct fpa2bv_rewriter : public rewriter_tpl<fpa2bv_rewriter_cfg> { struct fpa2bv_rewriter : public rewriter_tpl<fpa2bv_rewriter_cfg> {
fpa2bv_rewriter_cfg m_cfg; fpa2bv_rewriter_cfg m_cfg;

View file

@ -61,8 +61,10 @@ br_status arith_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
case OP_ADD: st = mk_add_core(num_args, args, result); break; case OP_ADD: st = mk_add_core(num_args, args, result); break;
case OP_MUL: st = mk_mul_core(num_args, args, result); break; case OP_MUL: st = mk_mul_core(num_args, args, result); break;
case OP_SUB: st = mk_sub(num_args, args, result); break; case OP_SUB: st = mk_sub(num_args, args, result); break;
case OP_DIV: SASSERT(num_args == 2); st = mk_div_core(args[0], args[1], result); break; case OP_DIV: if (num_args == 1) { result = args[0]; st = BR_DONE; break; }
case OP_IDIV: SASSERT(num_args == 2); st = mk_idiv_core(args[0], args[1], result); break; SASSERT(num_args == 2); st = mk_div_core(args[0], args[1], result); break;
case OP_IDIV: if (num_args == 1) { result = args[0]; st = BR_DONE; break; }
SASSERT(num_args == 2); st = mk_idiv_core(args[0], args[1], result); break;
case OP_MOD: SASSERT(num_args == 2); st = mk_mod_core(args[0], args[1], result); break; case OP_MOD: SASSERT(num_args == 2); st = mk_mod_core(args[0], args[1], result); break;
case OP_REM: SASSERT(num_args == 2); st = mk_rem_core(args[0], args[1], result); break; case OP_REM: SASSERT(num_args == 2); st = mk_rem_core(args[0], args[1], result); break;
case OP_UMINUS: SASSERT(num_args == 1); st = mk_uminus(args[0], result); break; case OP_UMINUS: SASSERT(num_args == 1); st = mk_uminus(args[0], result); break;

View file

@ -572,36 +572,62 @@ bool bool_rewriter::local_ctx_simp(unsigned num_args, expr * const * args, expr_
*/ */
br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result) { br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result) {
SASSERT(m().is_ite(ite)); expr* cond, *t, *e;
VERIFY(m().is_ite(ite, cond, t, e));
SASSERT(m().is_value(val)); SASSERT(m().is_value(val));
expr * t = ite->get_arg(1); if (m().is_value(t) && m().is_value(e)) {
expr * e = ite->get_arg(2);
if (!m().is_value(t) || !m().is_value(e))
return BR_FAILED;
if (t != val && e != val) { if (t != val && e != val) {
TRACE("try_ite_value", tout << mk_ismt2_pp(t, m()) << " " << mk_ismt2_pp(e, m()) << " " << mk_ismt2_pp(val, m()) << "\n"; TRACE("try_ite_value", tout << mk_ismt2_pp(t, m()) << " " << mk_ismt2_pp(e, m()) << " " << mk_ismt2_pp(val, m()) << "\n";
tout << t << " " << e << " " << val << "\n";); tout << t << " " << e << " " << val << "\n";);
result = m().mk_false(); result = m().mk_false();
return BR_DONE;
} }
else if (t == val && e == val) {
if (t == val && e == val) {
result = m().mk_true(); result = m().mk_true();
return BR_DONE;
} }
else if (t == val) {
if (t == val) { result = cond;
result = ite->get_arg(0);
return BR_DONE;
} }
else {
SASSERT(e == val); SASSERT(e == val);
mk_not(cond, result);
mk_not(ite->get_arg(0), result); }
return BR_DONE; return BR_DONE;
} }
if (m().is_value(t)) {
if (val == t) {
result = m().mk_or(cond, m().mk_eq(val, e));
}
else {
mk_not(cond, result);
result = m().mk_and(result, m().mk_eq(val, e));
}
return BR_REWRITE2;
}
if (m().is_value(e)) {
if (val == e) {
mk_not(cond, result);
result = m().mk_or(result, m().mk_eq(val, t));
}
else {
result = m().mk_and(cond, m().mk_eq(val, t));
}
return BR_REWRITE2;
}
expr* cond2, *t2, *e2;
if (m().is_ite(t, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
try_ite_value(to_app(t), val, result);
result = m().mk_ite(cond, result, m().mk_eq(e, val));
return BR_REWRITE2;
}
if (m().is_ite(e, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
try_ite_value(to_app(e), val, result);
result = m().mk_ite(cond, m().mk_eq(t, val), result);
return BR_REWRITE2;
}
return BR_FAILED;
}
#if 0 #if 0
// Return true if ite is an if-then-else tree where the leaves are values, // Return true if ite is an if-then-else tree where the leaves are values,

View file

@ -51,6 +51,8 @@ void rewriter_core::cache_result(expr * k, expr * v) {
TRACE("rewriter_cache_result", tout << mk_ismt2_pp(k, m()) << "\n--->\n" << mk_ismt2_pp(v, m()) << "\n";); TRACE("rewriter_cache_result", tout << mk_ismt2_pp(k, m()) << "\n--->\n" << mk_ismt2_pp(v, m()) << "\n";);
SASSERT(m().get_sort(k) == m().get_sort(v));
m_cache->insert(k, v); m_cache->insert(k, v);
#if 0 #if 0
static unsigned num_cached = 0; static unsigned num_cached = 0;

View file

@ -214,9 +214,11 @@ protected:
unsigned m_num_steps; unsigned m_num_steps;
ptr_vector<expr> m_bindings; ptr_vector<expr> m_bindings;
var_shifter m_shifter; var_shifter m_shifter;
inv_var_shifter m_inv_shifter;
expr_ref m_r; expr_ref m_r;
proof_ref m_pr; proof_ref m_pr;
proof_ref m_pr2; proof_ref m_pr2;
unsigned_vector m_shifts;
svector<frame> & frame_stack() { return this->m_frame_stack; } svector<frame> & frame_stack() { return this->m_frame_stack; }
svector<frame> const & frame_stack() const { return this->m_frame_stack; } svector<frame> const & frame_stack() const { return this->m_frame_stack; }
@ -225,6 +227,8 @@ protected:
proof_ref_vector & result_pr_stack() { return this->m_result_pr_stack; } proof_ref_vector & result_pr_stack() { return this->m_result_pr_stack; }
proof_ref_vector const & result_pr_stack() const { return this->m_result_pr_stack; } proof_ref_vector const & result_pr_stack() const { return this->m_result_pr_stack; }
void display_bindings(std::ostream& out);
void set_new_child_flag(expr * old_t) { void set_new_child_flag(expr * old_t) {
SASSERT(frame_stack().empty() || frame_stack().back().m_state != PROCESS_CHILDREN || this->is_child_of_top_frame(old_t)); SASSERT(frame_stack().empty() || frame_stack().back().m_state != PROCESS_CHILDREN || this->is_child_of_top_frame(old_t));
if (!frame_stack().empty()) if (!frame_stack().empty())
@ -232,7 +236,6 @@ protected:
} }
void set_new_child_flag(expr * old_t, expr * new_t) { if (old_t != new_t) set_new_child_flag(old_t); } void set_new_child_flag(expr * old_t, expr * new_t) { if (old_t != new_t) set_new_child_flag(old_t); }
// cache the result of shared non atomic expressions. // cache the result of shared non atomic expressions.
bool cache_results() const { return m_cfg.cache_results(); } bool cache_results() const { return m_cfg.cache_results(); }
// cache all results share and non shared expressions non atomic expressions. // cache all results share and non shared expressions non atomic expressions.

View file

@ -24,6 +24,7 @@ template<bool ProofGen>
void rewriter_tpl<Config>::process_var(var * v) { void rewriter_tpl<Config>::process_var(var * v) {
if (m_cfg.reduce_var(v, m_r, m_pr)) { if (m_cfg.reduce_var(v, m_r, m_pr)) {
result_stack().push_back(m_r); result_stack().push_back(m_r);
SASSERT(v->get_sort() == m().get_sort(m_r));
if (ProofGen) { if (ProofGen) {
result_pr_stack().push_back(m_pr); result_pr_stack().push_back(m_pr);
m_pr = 0; m_pr = 0;
@ -36,18 +37,21 @@ void rewriter_tpl<Config>::process_var(var * v) {
// bindings are only used when Proof Generation is not enabled. // bindings are only used when Proof Generation is not enabled.
unsigned idx = v->get_idx(); unsigned idx = v->get_idx();
if (idx < m_bindings.size()) { if (idx < m_bindings.size()) {
expr * r = m_bindings[m_bindings.size() - idx - 1]; unsigned index = m_bindings.size() - idx - 1;
TRACE("process_var", if (r) tout << "idx: " << idx << " --> " << mk_ismt2_pp(r, m()) << "\n"; expr * r = m_bindings[index];
tout << "bindings:\n";
for (unsigned i = 0; i < m_bindings.size(); i++) if (m_bindings[i]) tout << i << ": " << mk_ismt2_pp(m_bindings[i], m()) << "\n";);
if (r != 0) { if (r != 0) {
if (m_num_qvars == 0 || is_ground(r)) { SASSERT(v->get_sort() == m().get_sort(r));
result_stack().push_back(r); if (!is_ground(r) && m_shifts[index] != UINT_MAX) {
unsigned shift_amount = m_bindings.size() - m_shifts[index];
expr_ref tmp(m());
m_shifter(r, shift_amount, tmp);
result_stack().push_back(tmp);
TRACE("process_var", tout << "shift: " << shift_amount << " idx: " << idx << " --> " << tmp << "\n";
display_bindings(tout););
} }
else { else {
expr_ref new_term(m()); result_stack().push_back(r);
m_shifter(r, m_num_qvars, new_term);
result_stack().push_back(new_term);
} }
set_new_child_flag(v); set_new_child_flag(v);
return; return;
@ -64,6 +68,7 @@ template<bool ProofGen>
void rewriter_tpl<Config>::process_const(app * t) { void rewriter_tpl<Config>::process_const(app * t) {
SASSERT(t->get_num_args() == 0); SASSERT(t->get_num_args() == 0);
br_status st = m_cfg.reduce_app(t->get_decl(), 0, 0, m_r, m_pr); br_status st = m_cfg.reduce_app(t->get_decl(), 0, 0, m_r, m_pr);
SASSERT(st != BR_DONE || m().get_sort(m_r) == m().get_sort(t));
SASSERT(st == BR_FAILED || st == BR_DONE); SASSERT(st == BR_FAILED || st == BR_DONE);
if (st == BR_DONE) { if (st == BR_DONE) {
result_stack().push_back(m_r.get()); result_stack().push_back(m_r.get());
@ -100,6 +105,7 @@ bool rewriter_tpl<Config>::visit(expr * t, unsigned max_depth) {
proof * new_t_pr; proof * new_t_pr;
if (m_cfg.get_subst(t, new_t, new_t_pr)) { if (m_cfg.get_subst(t, new_t, new_t_pr)) {
TRACE("rewriter_subst", tout << "subst\n" << mk_ismt2_pp(t, m()) << "\n---->\n" << mk_ismt2_pp(new_t, m()) << "\n";); TRACE("rewriter_subst", tout << "subst\n" << mk_ismt2_pp(t, m()) << "\n---->\n" << mk_ismt2_pp(new_t, m()) << "\n";);
SASSERT(m().get_sort(t) == m().get_sort(new_t));
result_stack().push_back(new_t); result_stack().push_back(new_t);
set_new_child_flag(t, new_t); set_new_child_flag(t, new_t);
if (ProofGen) if (ProofGen)
@ -124,6 +130,7 @@ bool rewriter_tpl<Config>::visit(expr * t, unsigned max_depth) {
#endif #endif
expr * r = get_cached(t); expr * r = get_cached(t);
if (r) { if (r) {
SASSERT(m().get_sort(r) == m().get_sort(t));
result_stack().push_back(r); result_stack().push_back(r);
set_new_child_flag(t, r); set_new_child_flag(t, r);
if (ProofGen) { if (ProofGen) {
@ -213,6 +220,7 @@ void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
} }
} }
br_status st = m_cfg.reduce_app(f, new_num_args, new_args, m_r, m_pr2); br_status st = m_cfg.reduce_app(f, new_num_args, new_args, m_r, m_pr2);
SASSERT(st != BR_DONE || m().get_sort(m_r) == m().get_sort(t));
TRACE("reduce_app", TRACE("reduce_app",
tout << mk_ismt2_pp(t, m()) << "\n"; tout << mk_ismt2_pp(t, m()) << "\n";
tout << "st: " << st; tout << "st: " << st;
@ -220,6 +228,7 @@ void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
tout << "\n";); tout << "\n";);
if (st != BR_FAILED) { if (st != BR_FAILED) {
result_stack().shrink(fr.m_spos); result_stack().shrink(fr.m_spos);
SASSERT(m().get_sort(m_r) == m().get_sort(t));
result_stack().push_back(m_r); result_stack().push_back(m_r);
if (ProofGen) { if (ProofGen) {
result_pr_stack().shrink(fr.m_spos); result_pr_stack().shrink(fr.m_spos);
@ -295,6 +304,7 @@ void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
if (get_macro(f, def, def_q, def_pr)) { if (get_macro(f, def, def_q, def_pr)) {
SASSERT(!f->is_associative() || !flat_assoc(f)); SASSERT(!f->is_associative() || !flat_assoc(f));
SASSERT(new_num_args == t->get_num_args()); SASSERT(new_num_args == t->get_num_args());
SASSERT(m().get_sort(def) == m().get_sort(t));
if (is_ground(def)) { if (is_ground(def)) {
m_r = def; m_r = def;
if (ProofGen) { if (ProofGen) {
@ -317,16 +327,18 @@ void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
TRACE("get_macro", tout << "f: " << f->get_name() << ", def: \n" << mk_ismt2_pp(def, m()) << "\n"; TRACE("get_macro", tout << "f: " << f->get_name() << ", def: \n" << mk_ismt2_pp(def, m()) << "\n";
tout << "Args num: " << num_args << "\n"; tout << "Args num: " << num_args << "\n";
for (unsigned i = 0; i < num_args; i++) tout << mk_ismt2_pp(new_args[i], m()) << "\n";); for (unsigned i = 0; i < num_args; i++) tout << mk_ismt2_pp(new_args[i], m()) << "\n";);
unsigned sz = m_bindings.size();
unsigned i = num_args; unsigned i = num_args;
while (i > 0) { while (i > 0) {
--i; --i;
m_bindings.push_back(new_args[i]); m_bindings.push_back(new_args[i]); // num_args - i - 1]);
m_shifts.push_back(sz);
} }
result_stack().push_back(def); result_stack().push_back(def);
TRACE("get_macro", tout << "bindings:\n"; TRACE("get_macro", display_bindings(tout););
for (unsigned j = 0; j < m_bindings.size(); j++) tout << j << ": " << mk_ismt2_pp(m_bindings[j], m()) << "\n";);
begin_scope(); begin_scope();
m_num_qvars = 0; m_num_qvars += num_args;
//m_num_qvars = 0;
m_root = def; m_root = def;
push_frame(def, false, RW_UNBOUNDED_DEPTH); push_frame(def, false, RW_UNBOUNDED_DEPTH);
return; return;
@ -383,9 +395,17 @@ void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
SASSERT(fr.m_spos + t->get_num_args() + 2 == result_stack().size()); SASSERT(fr.m_spos + t->get_num_args() + 2 == result_stack().size());
SASSERT(t->get_num_args() <= m_bindings.size()); SASSERT(t->get_num_args() <= m_bindings.size());
if (!ProofGen) { if (!ProofGen) {
m_bindings.shrink(m_bindings.size() - t->get_num_args()); expr_ref tmp(m());
unsigned num_args = t->get_num_args();
m_bindings.shrink(m_bindings.size() - num_args);
m_shifts.shrink(m_shifts.size() - num_args);
m_num_qvars -= num_args;
end_scope(); end_scope();
m_r = result_stack().back(); m_r = result_stack().back();
if (!is_ground(m_r)) {
m_inv_shifter(m_r, num_args, tmp);
m_r = tmp;
}
result_stack().shrink(fr.m_spos); result_stack().shrink(fr.m_spos);
result_stack().push_back(m_r); result_stack().push_back(m_r);
cache_result<ProofGen>(t, m_r, m_pr, fr.m_cache_result); cache_result<ProofGen>(t, m_r, m_pr, fr.m_cache_result);
@ -411,24 +431,27 @@ template<typename Config>
template<bool ProofGen> template<bool ProofGen>
void rewriter_tpl<Config>::process_quantifier(quantifier * q, frame & fr) { void rewriter_tpl<Config>::process_quantifier(quantifier * q, frame & fr) {
SASSERT(fr.m_state == PROCESS_CHILDREN); SASSERT(fr.m_state == PROCESS_CHILDREN);
unsigned num_decls = q->get_num_decls();
if (fr.m_i == 0) { if (fr.m_i == 0) {
if (!ProofGen) { if (!ProofGen) {
begin_scope(); begin_scope();
m_root = q->get_expr(); m_root = q->get_expr();
} unsigned sz = m_bindings.size();
m_num_qvars += q->get_num_decls(); for (unsigned i = 0; i < num_decls; i++) {
if (!ProofGen) {
for (unsigned i = 0; i < q->get_num_decls(); i++)
m_bindings.push_back(0); m_bindings.push_back(0);
m_shifts.push_back(sz);
} }
} }
m_num_qvars += num_decls;
}
unsigned num_children = rewrite_patterns() ? q->get_num_children() : 1; unsigned num_children = rewrite_patterns() ? q->get_num_children() : 1;
while (fr.m_i < num_children) { while (fr.m_i < num_children) {
expr * child = q->get_child(fr.m_i); expr * child = q->get_child(fr.m_i);
fr.m_i++; fr.m_i++;
if (!visit<ProofGen>(child, fr.m_max_depth)) if (!visit<ProofGen>(child, fr.m_max_depth)) {
return; return;
} }
}
SASSERT(fr.m_spos + num_children == result_stack().size()); SASSERT(fr.m_spos + num_children == result_stack().size());
expr * const * it = result_stack().c_ptr() + fr.m_spos; expr * const * it = result_stack().c_ptr() + fr.m_spos;
expr * new_body = *it; expr * new_body = *it;
@ -456,6 +479,8 @@ void rewriter_tpl<Config>::process_quantifier(quantifier * q, frame & fr) {
result_pr_stack().push_back(m_pr); result_pr_stack().push_back(m_pr);
} }
else { else {
expr_ref tmp(m());
if (!m_cfg.reduce_quantifier(q, new_body, new_pats, new_no_pats, m_r, m_pr)) { if (!m_cfg.reduce_quantifier(q, new_body, new_pats, new_no_pats, m_r, m_pr)) {
if (fr.m_new_child) { if (fr.m_new_child) {
m_r = m().update_quantifier(q, q->get_num_patterns(), new_pats, q->get_num_no_patterns(), new_no_pats, new_body); m_r = m().update_quantifier(q, q->get_num_patterns(), new_pats, q->get_num_no_patterns(), new_no_pats, new_body);
@ -468,9 +493,11 @@ void rewriter_tpl<Config>::process_quantifier(quantifier * q, frame & fr) {
} }
result_stack().shrink(fr.m_spos); result_stack().shrink(fr.m_spos);
result_stack().push_back(m_r.get()); result_stack().push_back(m_r.get());
SASSERT(m().is_bool(m_r));
if (!ProofGen) { if (!ProofGen) {
SASSERT(q->get_num_decls() <= m_bindings.size()); SASSERT(num_decls <= m_bindings.size());
m_bindings.shrink(m_bindings.size() - q->get_num_decls()); m_bindings.shrink(m_bindings.size() - num_decls);
m_shifts.shrink(m_shifts.size() - num_decls);
end_scope(); end_scope();
cache_result<ProofGen>(q, m_r, m_pr, fr.m_cache_result); cache_result<ProofGen>(q, m_r, m_pr, fr.m_cache_result);
} }
@ -496,6 +523,7 @@ rewriter_tpl<Config>::rewriter_tpl(ast_manager & m, bool proof_gen, Config & cfg
m_cfg(cfg), m_cfg(cfg),
m_num_steps(0), m_num_steps(0),
m_shifter(m), m_shifter(m),
m_inv_shifter(m),
m_r(m), m_r(m),
m_pr(m), m_pr(m),
m_pr2(m) { m_pr2(m) {
@ -510,7 +538,9 @@ void rewriter_tpl<Config>::reset() {
m_cfg.reset(); m_cfg.reset();
rewriter_core::reset(); rewriter_core::reset();
m_bindings.reset(); m_bindings.reset();
m_shifts.reset();
m_shifter.reset(); m_shifter.reset();
m_inv_shifter.reset();
} }
template<typename Config> template<typename Config>
@ -519,6 +549,17 @@ void rewriter_tpl<Config>::cleanup() {
rewriter_core::cleanup(); rewriter_core::cleanup();
m_bindings.finalize(); m_bindings.finalize();
m_shifter.cleanup(); m_shifter.cleanup();
m_shifts.finalize();
m_inv_shifter.cleanup();
}
template<typename Config>
void rewriter_tpl<Config>::display_bindings(std::ostream& out) {
out << "bindings:\n";
for (unsigned i = 0; i < m_bindings.size(); i++) {
if (m_bindings[i])
out << i << ": " << mk_ismt2_pp(m_bindings[i], m()) << "\n";
}
} }
template<typename Config> template<typename Config>
@ -526,11 +567,14 @@ void rewriter_tpl<Config>::set_bindings(unsigned num_bindings, expr * const * bi
SASSERT(!m_proof_gen); SASSERT(!m_proof_gen);
SASSERT(not_rewriting()); SASSERT(not_rewriting());
m_bindings.reset(); m_bindings.reset();
m_shifts.reset();
unsigned i = num_bindings; unsigned i = num_bindings;
while (i > 0) { while (i > 0) {
--i; --i;
m_bindings.push_back(bindings[i]); m_bindings.push_back(bindings[i]);
m_shifts.push_back(UINT_MAX);
} }
TRACE("rewriter", display_bindings(tout););
} }
template<typename Config> template<typename Config>
@ -538,9 +582,12 @@ void rewriter_tpl<Config>::set_inv_bindings(unsigned num_bindings, expr * const
SASSERT(!m_proof_gen); SASSERT(!m_proof_gen);
SASSERT(not_rewriting()); SASSERT(not_rewriting());
m_bindings.reset(); m_bindings.reset();
m_shifts.reset();
for (unsigned i = 0; i < num_bindings; i++) { for (unsigned i = 0; i < num_bindings; i++) {
m_bindings.push_back(bindings[i]); m_bindings.push_back(bindings[i]);
m_shifts.push_back(UINT_MAX);
} }
TRACE("rewriter", display_bindings(tout););
} }
template<typename Config> template<typename Config>
@ -562,10 +609,12 @@ void rewriter_tpl<Config>::main_loop(expr * t, expr_ref & result, proof_ref & re
result_pr = m().mk_reflexivity(t); result_pr = m().mk_reflexivity(t);
SASSERT(result_pr_stack().empty()); SASSERT(result_pr_stack().empty());
} }
return;
} }
else {
resume_core<ProofGen>(result, result_pr); resume_core<ProofGen>(result, result_pr);
} }
TRACE("rewriter", tout << mk_ismt2_pp(t, m()) << "\n=>\n" << result << "\n";;);
}
/** /**
\brief Resume the execution when it was interrupted by cancel() or check_max_steps(). \brief Resume the execution when it was interrupted by cancel() or check_max_steps().
@ -587,6 +636,7 @@ void rewriter_tpl<Config>::resume_core(expr_ref & result, proof_ref & result_pr)
if (first_visit(fr) && fr.m_cache_result) { if (first_visit(fr) && fr.m_cache_result) {
expr * r = get_cached(t); expr * r = get_cached(t);
if (r) { if (r) {
SASSERT(m().get_sort(r) == m().get_sort(t));
result_stack().push_back(r); result_stack().push_back(r);
if (ProofGen) { if (ProofGen) {
proof * pr = get_cached_pr(t); proof * pr = get_cached_pr(t);

View file

@ -579,7 +579,7 @@ br_status seq_rewriter::mk_seq_contains(expr* a, expr* b, expr_ref& result) {
unsigned lenA = 0, lenB = 0; unsigned lenA = 0, lenB = 0;
bool lA = min_length(as.size(), as.c_ptr(), lenA); bool lA = min_length(as.size(), as.c_ptr(), lenA);
if (lA) { if (lA) {
bool lB = min_length(bs.size(), bs.c_ptr(), lenB); min_length(bs.size(), bs.c_ptr(), lenB);
if (lenB > lenA) { if (lenB > lenA) {
result = m().mk_false(); result = m().mk_false();
return BR_DONE; return BR_DONE;

View file

@ -29,7 +29,6 @@ model_core::~model_core() {
decl2finterp::iterator it2 = m_finterp.begin(); decl2finterp::iterator it2 = m_finterp.begin();
decl2finterp::iterator end2 = m_finterp.end(); decl2finterp::iterator end2 = m_finterp.end();
for (; it2 != end2; ++it2) { for (; it2 != end2; ++it2) {
func_decl* d = it2->m_key;
m_manager.dec_ref(it2->m_key); m_manager.dec_ref(it2->m_key);
dealloc(it2->m_value); dealloc(it2->m_value);
} }

View file

@ -31,6 +31,7 @@ Revision History:
#include"rewriter_def.h" #include"rewriter_def.h"
#include"cooperate.h" #include"cooperate.h"
struct evaluator_cfg : public default_rewriter_cfg { struct evaluator_cfg : public default_rewriter_cfg {
model_core & m_model; model_core & m_model;
bool_rewriter m_b_rw; bool_rewriter m_b_rw;
@ -59,9 +60,10 @@ struct evaluator_cfg : public default_rewriter_cfg {
m_pb_rw(m), m_pb_rw(m),
m_f_rw(m), m_f_rw(m),
m_seq_rw(m) { m_seq_rw(m) {
m_b_rw.set_flat(false); bool flat = true;
m_a_rw.set_flat(false); m_b_rw.set_flat(flat);
m_bv_rw.set_flat(false); m_a_rw.set_flat(flat);
m_bv_rw.set_flat(flat);
m_bv_rw.set_mkbv2num(true); m_bv_rw.set_mkbv2num(true);
updt_params(p); updt_params(p);
} }
@ -181,10 +183,12 @@ struct evaluator_cfg : public default_rewriter_cfg {
} }
bool get_macro(func_decl * f, expr * & def, quantifier * & q, proof * & def_pr) { bool get_macro(func_decl * f, expr * & def, quantifier * & q, proof * & def_pr) {
TRACE("model_evaluator", tout << "get_macro for " << f->get_name() << " (model completion: " << m_model_completion << ")\n";);
#define TRACE_MACRO TRACE("model_evaluator", tout << "get_macro for " << f->get_name() << " (model completion: " << m_model_completion << ")\n";);
func_interp * fi = m_model.get_func_interp(f); func_interp * fi = m_model.get_func_interp(f);
if (fi != 0) { if (fi != 0) {
TRACE_MACRO;
if (fi->is_partial()) { if (fi->is_partial()) {
if (m_model_completion) { if (m_model_completion) {
sort * s = f->get_range(); sort * s = f->get_range();
@ -204,6 +208,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
(f->get_family_id() == null_family_id || (f->get_family_id() == null_family_id ||
m().get_plugin(f->get_family_id())->is_considered_uninterpreted(f))) m().get_plugin(f->get_family_id())->is_considered_uninterpreted(f)))
{ {
TRACE_MACRO;
sort * s = f->get_range(); sort * s = f->get_range();
expr * val = m_model.get_some_value(s); expr * val = m_model.get_some_value(s);
func_interp * new_fi = alloc(func_interp, m(), f->get_arity()); func_interp * new_fi = alloc(func_interp, m(), f->get_arity());

View file

@ -4,5 +4,6 @@ def_module_params('model',
('v1', BOOL, False, 'use Z3 version 1.x pretty printer'), ('v1', BOOL, False, 'use Z3 version 1.x pretty printer'),
('v2', BOOL, False, 'use Z3 version 2.x (x <= 16) pretty printer'), ('v2', BOOL, False, 'use Z3 version 2.x (x <= 16) pretty printer'),
('compact', BOOL, False, 'try to compact function graph (i.e., function interpretations that are lookup tables)'), ('compact', BOOL, False, 'try to compact function graph (i.e., function interpretations that are lookup tables)'),
('new_eval', BOOL, True, 'use new evaluator (temporary parameter for testing)'),
)) ))

View file

@ -30,12 +30,14 @@ Revision History:
proto_model::proto_model(ast_manager & m, simplifier & s, params_ref const & p): proto_model::proto_model(ast_manager & m, simplifier & s, params_ref const & p):
model_core(m), model_core(m),
m_simplifier(s), m_simplifier(s),
m_afid(m.mk_family_id(symbol("array"))) { m_afid(m.mk_family_id(symbol("array"))),
m_eval(*this) {
register_factory(alloc(basic_factory, m)); register_factory(alloc(basic_factory, m));
m_user_sort_factory = alloc(user_sort_factory, m); m_user_sort_factory = alloc(user_sort_factory, m);
register_factory(m_user_sort_factory); register_factory(m_user_sort_factory);
m_model_partial = model_params(p).partial(); m_model_partial = model_params(p).partial();
m_use_new_eval = model_params(p).new_eval();
} }
@ -157,6 +159,19 @@ bool proto_model::is_select_of_model_value(expr* e) const {
So, if model_completion == true, the evaluator never fails if it doesn't contain quantifiers. So, if model_completion == true, the evaluator never fails if it doesn't contain quantifiers.
*/ */
bool proto_model::eval(expr * e, expr_ref & result, bool model_completion) { bool proto_model::eval(expr * e, expr_ref & result, bool model_completion) {
if (m_use_new_eval) {
m_eval.set_model_completion(model_completion);
try {
m_eval(e, result);
return true;
}
catch (model_evaluator_exception & ex) {
(void)ex;
TRACE("model_evaluator", tout << ex.msg() << "\n";);
return false;
}
}
bool is_ok = true; bool is_ok = true;
SASSERT(is_well_sorted(m_manager, e)); SASSERT(is_well_sorted(m_manager, e));
TRACE("model_eval", tout << mk_pp(e, m_manager) << "\n"; TRACE("model_eval", tout << mk_pp(e, m_manager) << "\n";

View file

@ -29,6 +29,7 @@ Revision History:
#define PROTO_MODEL_H_ #define PROTO_MODEL_H_
#include"model_core.h" #include"model_core.h"
#include"model_evaluator.h"
#include"value_factory.h" #include"value_factory.h"
#include"plugin_manager.h" #include"plugin_manager.h"
#include"simplifier.h" #include"simplifier.h"
@ -44,8 +45,10 @@ class proto_model : public model_core {
family_id m_afid; //!< array family id: hack for displaying models in V1.x style family_id m_afid; //!< array family id: hack for displaying models in V1.x style
func_decl_set m_aux_decls; func_decl_set m_aux_decls;
ptr_vector<expr> m_tmp; ptr_vector<expr> m_tmp;
model_evaluator m_eval;
bool m_model_partial; bool m_model_partial;
bool m_use_new_eval;
expr * mk_some_interp_for(func_decl * d); expr * mk_some_interp_for(func_decl * d);

View file

@ -95,7 +95,8 @@ namespace smt {
expr * e = *it; expr * e = *it;
eqs.push_back(m.mk_eq(sk, e)); eqs.push_back(m.mk_eq(sk, e));
} }
m_aux_context->assert_expr(m.mk_or(eqs.size(), eqs.c_ptr())); expr_ref fml(m.mk_or(eqs.size(), eqs.c_ptr()), m);
m_aux_context->assert_expr(fml);
} }
#define PP_DEPTH 8 #define PP_DEPTH 8
@ -105,9 +106,13 @@ namespace smt {
The variables are replaced by skolem constants. These constants are stored in sks. The variables are replaced by skolem constants. These constants are stored in sks.
*/ */
void model_checker::assert_neg_q_m(quantifier * q, expr_ref_vector & sks) { void model_checker::assert_neg_q_m(quantifier * q, expr_ref_vector & sks) {
expr_ref tmp(m); expr_ref tmp(m);
m_curr_model->eval(q->get_expr(), tmp, true); if (!m_curr_model->eval(q->get_expr(), tmp, true)) {
return;
}
//std::cout << tmp << "\n";
TRACE("model_checker", tout << "q after applying interpretation:\n" << mk_ismt2_pp(tmp, m) << "\n";); TRACE("model_checker", tout << "q after applying interpretation:\n" << mk_ismt2_pp(tmp, m) << "\n";);
ptr_buffer<expr> subst_args; ptr_buffer<expr> subst_args;
unsigned num_decls = q->get_num_decls(); unsigned num_decls = q->get_num_decls();
@ -261,10 +266,11 @@ namespace smt {
lbool r = m_aux_context->check(); lbool r = m_aux_context->check();
TRACE("model_checker", tout << "[complete] model-checker result: " << to_sat_str(r) << "\n";); TRACE("model_checker", tout << "[complete] model-checker result: " << to_sat_str(r) << "\n";);
if (r == l_false) { if (r != l_true) {
m_aux_context->pop(1); m_aux_context->pop(1);
return true; // quantifier is satisfied by m_curr_model return r == l_false; // quantifier is satisfied by m_curr_model
} }
model_ref complete_cex; model_ref complete_cex;
m_aux_context->get_model(complete_cex); m_aux_context->get_model(complete_cex);
@ -276,7 +282,7 @@ namespace smt {
while (true) { while (true) {
lbool r = m_aux_context->check(); lbool r = m_aux_context->check();
TRACE("model_checker", tout << "[restricted] model-checker (" << (num_new_instances+1) << ") result: " << to_sat_str(r) << "\n";); TRACE("model_checker", tout << "[restricted] model-checker (" << (num_new_instances+1) << ") result: " << to_sat_str(r) << "\n";);
if (r == l_false) if (r != l_true)
break; break;
model_ref cex; model_ref cex;
m_aux_context->get_model(cex); m_aux_context->get_model(cex);

View file

@ -1619,6 +1619,7 @@ namespace smt {
m_found_underspecified_op(false), m_found_underspecified_op(false),
m_arith_eq_adapter(*this, params, m_util), m_arith_eq_adapter(*this, params, m_util),
m_asserted_qhead(0), m_asserted_qhead(0),
m_row_vars_top(0),
m_to_patch(1024), m_to_patch(1024),
m_blands_rule(false), m_blands_rule(false),
m_random(params.m_arith_random_seed), m_random(params.m_arith_random_seed),
@ -1631,7 +1632,6 @@ namespace smt {
m_liberal_final_check(true), m_liberal_final_check(true),
m_changed_assignment(false), m_changed_assignment(false),
m_assume_eq_head(0), m_assume_eq_head(0),
m_row_vars_top(0),
m_nl_rounds(0), m_nl_rounds(0),
m_nl_gb_exhausted(false), m_nl_gb_exhausted(false),
m_nl_new_exprs(m), m_nl_new_exprs(m),

View file

@ -1591,7 +1591,6 @@ bool theory_seq::solve_ne(unsigned idx) {
} }
bool theory_seq::solve_nc(unsigned idx) { bool theory_seq::solve_nc(unsigned idx) {
context& ctx = get_context();
nc const& n = m_ncs[idx]; nc const& n = m_ncs[idx];
dependency* deps = n.deps(); dependency* deps = n.deps();

View file

@ -24,6 +24,7 @@ Notes:
#include"params.h" #include"params.h"
#include"ast_pp.h" #include"ast_pp.h"
#include"bvarray2uf_rewriter.h" #include"bvarray2uf_rewriter.h"
#include"rewriter_def.h"
// [1] C. M. Wintersteiger, Y. Hamadi, and L. de Moura: Efficiently Solving // [1] C. M. Wintersteiger, Y. Hamadi, and L. de Moura: Efficiently Solving
// Quantified Bit-Vector Formulas, in Formal Methods in System Design, // Quantified Bit-Vector Formulas, in Formal Methods in System Design,
@ -345,3 +346,5 @@ bool bvarray2uf_rewriter_cfg::reduce_var(var * t, expr_ref & result, proof_ref &
NOT_IMPLEMENTED_YET(); NOT_IMPLEMENTED_YET();
return true; return true;
} }
template class rewriter_tpl<bvarray2uf_rewriter_cfg>;

View file

@ -20,7 +20,7 @@ Notes:
#ifndef BVARRAY2UF_REWRITER_H_ #ifndef BVARRAY2UF_REWRITER_H_
#define BVARRAY2UF_REWRITER_H_ #define BVARRAY2UF_REWRITER_H_
#include"rewriter_def.h" #include"rewriter.h"
#include"extension_model_converter.h" #include"extension_model_converter.h"
#include"filter_model_converter.h" #include"filter_model_converter.h"
@ -71,7 +71,6 @@ protected:
func_decl_ref mk_uf_for_array(expr * e); func_decl_ref mk_uf_for_array(expr * e);
}; };
template class rewriter_tpl<bvarray2uf_rewriter_cfg>;
struct bvarray2uf_rewriter : public rewriter_tpl<bvarray2uf_rewriter_cfg> { struct bvarray2uf_rewriter : public rewriter_tpl<bvarray2uf_rewriter_cfg> {
bvarray2uf_rewriter_cfg m_cfg; bvarray2uf_rewriter_cfg m_cfg;

View file

@ -226,6 +226,7 @@ int main(int argc, char ** argv) {
TST(sat_user_scope); TST(sat_user_scope);
TST(pdr); TST(pdr);
TST_ARGV(ddnf); TST_ARGV(ddnf);
TST(model_evaluator);
//TST_ARGV(hs); //TST_ARGV(hs);
} }

View file

@ -0,0 +1,66 @@
#include "model.h"
#include "model_evaluator.h"
#include "model_pp.h"
#include "arith_decl_plugin.h"
#include "reg_decl_plugins.h"
#include "ast_pp.h"
void tst_model_evaluator() {
ast_manager m;
reg_decl_plugins(m);
arith_util a(m);
model mdl(m);
sort* sI = a.mk_int();
sort* dom[2] = { sI, m.mk_bool_sort() };
func_decl_ref f(m.mk_func_decl(symbol("f"), 2, dom, sI), m);
func_decl_ref g(m.mk_func_decl(symbol("g"), 2, dom, sI), m);
func_decl_ref h(m.mk_func_decl(symbol("h"), 2, dom, sI), m);
func_decl_ref F(m.mk_func_decl(symbol("F"), 2, dom, sI), m);
func_decl_ref G(m.mk_func_decl(symbol("G"), 2, dom, sI), m);
expr_ref vI0(m.mk_var(0, sI), m);
expr_ref vI1(m.mk_var(1, sI), m);
expr_ref vB0(m.mk_var(0, m.mk_bool_sort()), m);
expr_ref vB1(m.mk_var(1, m.mk_bool_sort()), m);
expr_ref vB2(m.mk_var(2, m.mk_bool_sort()), m);
expr_ref f01(m.mk_app(f, vI0, vB1), m);
expr_ref g01(m.mk_app(g, vI0, vB1), m);
expr_ref h01(m.mk_app(h, vI0, vB1), m);
func_interp* fi = alloc(func_interp, m, 2);
func_interp* gi = alloc(func_interp, m, 2);
func_interp* hi = alloc(func_interp, m, 2);
hi->set_else(m.mk_ite(vB1, m.mk_app(f, vI0, vB1), m.mk_app(g, vI0, vB1)));
mdl.register_decl(h, hi);
model_evaluator eval(mdl);
expr_ref e(m), v(m);
{
symbol nI("N");
fi->set_else(m.mk_ite(m.mk_exists(1, &sI, &nI, a.mk_le(vI0, m.mk_app(F, vI1, vB2))), vI0, a.mk_int(1)));
gi->set_else(m.mk_ite(m.mk_exists(1, &sI, &nI, a.mk_le(vI0, m.mk_app(G, vI1, vB2))), a.mk_int(2), vI0));
mdl.register_decl(g, gi);
mdl.register_decl(f, fi);
model_pp(std::cout, mdl);
e = m.mk_app(h, vI0, vB1);
eval(e, v);
std::cout << e << " " << v << "\n";
}
{
fi->set_else(m.mk_app(F, vI0, vB1));
gi->set_else(m.mk_app(G, vI0, vB1));
mdl.register_decl(g, gi);
mdl.register_decl(h, hi);
model_pp(std::cout, mdl);
e = m.mk_app(h, vI0, vB1);
eval(e, v);
std::cout << e << " " << v << "\n";
}
}