mirror of
https://github.com/Z3Prover/z3
synced 2025-04-06 17:44:08 +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:
parent
6fef24edb4
commit
70f13ced33
|
@ -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) {
|
||||
|
||||
bool type_error =
|
||||
decl->get_arity() != num_args && !decl->is_right_associative() &&
|
||||
!decl->is_left_associative() && !decl->is_chainable();
|
||||
|
|
|
@ -1075,7 +1075,7 @@ public:
|
|||
if (strcmp(var_prefix, ALIAS_PREFIX) == 0) {
|
||||
var_prefix = "_a";
|
||||
}
|
||||
unsigned idx = 1;
|
||||
unsigned idx = 0;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
symbol name = next_name(var_prefix, idx);
|
||||
name = ensure_quote_sym(name);
|
||||
|
|
270
src/ast/fpa/fpa2bv_rewriter.cpp
Normal file
270
src/ast/fpa/fpa2bv_rewriter.cpp
Normal 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>;
|
|
@ -20,11 +20,9 @@ Notes:
|
|||
#ifndef FPA2BV_REWRITER_H_
|
||||
#define FPA2BV_REWRITER_H_
|
||||
|
||||
#include"cooperate.h"
|
||||
#include"rewriter_def.h"
|
||||
#include"rewriter.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"fpa2bv_converter.h"
|
||||
#include"fpa2bv_rewriter_params.hpp"
|
||||
|
||||
struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
|
||||
ast_manager & m_manager;
|
||||
|
@ -37,17 +35,7 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
|
|||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
|
||||
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(ast_manager & m, fpa2bv_converter & c, params_ref const & p);
|
||||
|
||||
~fpa2bv_rewriter_cfg() {
|
||||
}
|
||||
|
@ -59,236 +47,28 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
|
|||
void reset() {
|
||||
}
|
||||
|
||||
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_local_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);
|
||||
}
|
||||
void updt_params(params_ref const & p);
|
||||
|
||||
bool max_steps_exceeded(unsigned num_steps) const {
|
||||
cooperate("fpa2bv");
|
||||
return num_steps > m_max_steps;
|
||||
}
|
||||
bool max_steps_exceeded(unsigned num_steps) const;
|
||||
|
||||
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; );
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr);
|
||||
|
||||
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 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 pre_visit(expr * t);
|
||||
|
||||
bool 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;
|
||||
}
|
||||
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;
|
||||
bool reduce_var(var * t, expr_ref & result, proof_ref & result_pr);
|
||||
|
||||
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> {
|
||||
fpa2bv_rewriter_cfg m_cfg;
|
||||
|
|
|
@ -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_MUL: st = mk_mul_core(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_IDIV: SASSERT(num_args == 2); st = mk_idiv_core(args[0], args[1], result); break;
|
||||
case OP_DIV: if (num_args == 1) { result = args[0]; st = BR_DONE; 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_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;
|
||||
|
|
|
@ -572,35 +572,61 @@ 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) {
|
||||
SASSERT(m().is_ite(ite));
|
||||
expr* cond, *t, *e;
|
||||
VERIFY(m().is_ite(ite, cond, t, e));
|
||||
SASSERT(m().is_value(val));
|
||||
|
||||
expr * t = ite->get_arg(1);
|
||||
expr * e = ite->get_arg(2);
|
||||
if (!m().is_value(t) || !m().is_value(e))
|
||||
return BR_FAILED;
|
||||
|
||||
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";
|
||||
tout << t << " " << e << " " << val << "\n";);
|
||||
result = m().mk_false();
|
||||
if (m().is_value(t) && m().is_value(e)) {
|
||||
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";
|
||||
tout << t << " " << e << " " << val << "\n";);
|
||||
result = m().mk_false();
|
||||
}
|
||||
else if (t == val && e == val) {
|
||||
result = m().mk_true();
|
||||
}
|
||||
else if (t == val) {
|
||||
result = cond;
|
||||
}
|
||||
else {
|
||||
SASSERT(e == val);
|
||||
mk_not(cond, result);
|
||||
}
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
if (t == val && e == val) {
|
||||
result = m().mk_true();
|
||||
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;
|
||||
}
|
||||
|
||||
if (t == val) {
|
||||
result = ite->get_arg(0);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
SASSERT(e == val);
|
||||
|
||||
mk_not(ite->get_arg(0), result);
|
||||
return BR_DONE;
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -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";);
|
||||
|
||||
SASSERT(m().get_sort(k) == m().get_sort(v));
|
||||
|
||||
m_cache->insert(k, v);
|
||||
#if 0
|
||||
static unsigned num_cached = 0;
|
||||
|
|
|
@ -214,10 +214,12 @@ protected:
|
|||
unsigned m_num_steps;
|
||||
ptr_vector<expr> m_bindings;
|
||||
var_shifter m_shifter;
|
||||
inv_var_shifter m_inv_shifter;
|
||||
expr_ref m_r;
|
||||
proof_ref m_pr;
|
||||
proof_ref m_pr2;
|
||||
|
||||
unsigned_vector m_shifts;
|
||||
|
||||
svector<frame> & frame_stack() { return this->m_frame_stack; }
|
||||
svector<frame> const & frame_stack() const { return this->m_frame_stack; }
|
||||
expr_ref_vector & result_stack() { return this->m_result_stack; }
|
||||
|
@ -225,6 +227,8 @@ protected:
|
|||
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; }
|
||||
|
||||
void display_bindings(std::ostream& out);
|
||||
|
||||
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));
|
||||
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); }
|
||||
|
||||
|
||||
// cache the result of shared non atomic expressions.
|
||||
bool cache_results() const { return m_cfg.cache_results(); }
|
||||
// cache all results share and non shared expressions non atomic expressions.
|
||||
|
|
|
@ -24,6 +24,7 @@ template<bool ProofGen>
|
|||
void rewriter_tpl<Config>::process_var(var * v) {
|
||||
if (m_cfg.reduce_var(v, m_r, m_pr)) {
|
||||
result_stack().push_back(m_r);
|
||||
SASSERT(v->get_sort() == m().get_sort(m_r));
|
||||
if (ProofGen) {
|
||||
result_pr_stack().push_back(m_pr);
|
||||
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.
|
||||
unsigned idx = v->get_idx();
|
||||
if (idx < m_bindings.size()) {
|
||||
expr * r = m_bindings[m_bindings.size() - idx - 1];
|
||||
TRACE("process_var", if (r) tout << "idx: " << idx << " --> " << mk_ismt2_pp(r, m()) << "\n";
|
||||
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";);
|
||||
unsigned index = m_bindings.size() - idx - 1;
|
||||
expr * r = m_bindings[index];
|
||||
if (r != 0) {
|
||||
if (m_num_qvars == 0 || is_ground(r)) {
|
||||
result_stack().push_back(r);
|
||||
SASSERT(v->get_sort() == m().get_sort(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 {
|
||||
expr_ref new_term(m());
|
||||
m_shifter(r, m_num_qvars, new_term);
|
||||
result_stack().push_back(new_term);
|
||||
result_stack().push_back(r);
|
||||
}
|
||||
set_new_child_flag(v);
|
||||
return;
|
||||
|
@ -64,6 +68,7 @@ template<bool ProofGen>
|
|||
void rewriter_tpl<Config>::process_const(app * t) {
|
||||
SASSERT(t->get_num_args() == 0);
|
||||
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);
|
||||
if (st == BR_DONE) {
|
||||
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;
|
||||
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";);
|
||||
SASSERT(m().get_sort(t) == m().get_sort(new_t));
|
||||
result_stack().push_back(new_t);
|
||||
set_new_child_flag(t, new_t);
|
||||
if (ProofGen)
|
||||
|
@ -124,6 +130,7 @@ bool rewriter_tpl<Config>::visit(expr * t, unsigned max_depth) {
|
|||
#endif
|
||||
expr * r = get_cached(t);
|
||||
if (r) {
|
||||
SASSERT(m().get_sort(r) == m().get_sort(t));
|
||||
result_stack().push_back(r);
|
||||
set_new_child_flag(t, r);
|
||||
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);
|
||||
SASSERT(st != BR_DONE || m().get_sort(m_r) == m().get_sort(t));
|
||||
TRACE("reduce_app",
|
||||
tout << mk_ismt2_pp(t, m()) << "\n";
|
||||
tout << "st: " << st;
|
||||
|
@ -220,6 +228,7 @@ void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
|
|||
tout << "\n";);
|
||||
if (st != BR_FAILED) {
|
||||
result_stack().shrink(fr.m_spos);
|
||||
SASSERT(m().get_sort(m_r) == m().get_sort(t));
|
||||
result_stack().push_back(m_r);
|
||||
if (ProofGen) {
|
||||
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)) {
|
||||
SASSERT(!f->is_associative() || !flat_assoc(f));
|
||||
SASSERT(new_num_args == t->get_num_args());
|
||||
SASSERT(m().get_sort(def) == m().get_sort(t));
|
||||
if (is_ground(def)) {
|
||||
m_r = def;
|
||||
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";
|
||||
tout << "Args num: " << num_args << "\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;
|
||||
while (i > 0) {
|
||||
--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);
|
||||
TRACE("get_macro", tout << "bindings:\n";
|
||||
for (unsigned j = 0; j < m_bindings.size(); j++) tout << j << ": " << mk_ismt2_pp(m_bindings[j], m()) << "\n";);
|
||||
TRACE("get_macro", display_bindings(tout););
|
||||
begin_scope();
|
||||
m_num_qvars = 0;
|
||||
m_num_qvars += num_args;
|
||||
//m_num_qvars = 0;
|
||||
m_root = def;
|
||||
push_frame(def, false, RW_UNBOUNDED_DEPTH);
|
||||
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(t->get_num_args() <= m_bindings.size());
|
||||
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();
|
||||
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().push_back(m_r);
|
||||
cache_result<ProofGen>(t, m_r, m_pr, fr.m_cache_result);
|
||||
|
@ -411,23 +431,26 @@ template<typename Config>
|
|||
template<bool ProofGen>
|
||||
void rewriter_tpl<Config>::process_quantifier(quantifier * q, frame & fr) {
|
||||
SASSERT(fr.m_state == PROCESS_CHILDREN);
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
if (fr.m_i == 0) {
|
||||
if (!ProofGen) {
|
||||
begin_scope();
|
||||
m_root = q->get_expr();
|
||||
}
|
||||
m_num_qvars += q->get_num_decls();
|
||||
if (!ProofGen) {
|
||||
for (unsigned i = 0; i < q->get_num_decls(); i++)
|
||||
unsigned sz = m_bindings.size();
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
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;
|
||||
while (fr.m_i < num_children) {
|
||||
expr * child = q->get_child(fr.m_i);
|
||||
fr.m_i++;
|
||||
if (!visit<ProofGen>(child, fr.m_max_depth))
|
||||
if (!visit<ProofGen>(child, fr.m_max_depth)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
SASSERT(fr.m_spos + num_children == result_stack().size());
|
||||
expr * const * it = result_stack().c_ptr() + fr.m_spos;
|
||||
|
@ -456,6 +479,8 @@ void rewriter_tpl<Config>::process_quantifier(quantifier * q, frame & fr) {
|
|||
result_pr_stack().push_back(m_pr);
|
||||
}
|
||||
else {
|
||||
expr_ref tmp(m());
|
||||
|
||||
if (!m_cfg.reduce_quantifier(q, new_body, new_pats, new_no_pats, m_r, m_pr)) {
|
||||
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);
|
||||
|
@ -468,9 +493,11 @@ void rewriter_tpl<Config>::process_quantifier(quantifier * q, frame & fr) {
|
|||
}
|
||||
result_stack().shrink(fr.m_spos);
|
||||
result_stack().push_back(m_r.get());
|
||||
SASSERT(m().is_bool(m_r));
|
||||
if (!ProofGen) {
|
||||
SASSERT(q->get_num_decls() <= m_bindings.size());
|
||||
m_bindings.shrink(m_bindings.size() - q->get_num_decls());
|
||||
SASSERT(num_decls <= m_bindings.size());
|
||||
m_bindings.shrink(m_bindings.size() - num_decls);
|
||||
m_shifts.shrink(m_shifts.size() - num_decls);
|
||||
end_scope();
|
||||
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_num_steps(0),
|
||||
m_shifter(m),
|
||||
m_inv_shifter(m),
|
||||
m_r(m),
|
||||
m_pr(m),
|
||||
m_pr2(m) {
|
||||
|
@ -510,7 +538,9 @@ void rewriter_tpl<Config>::reset() {
|
|||
m_cfg.reset();
|
||||
rewriter_core::reset();
|
||||
m_bindings.reset();
|
||||
m_shifts.reset();
|
||||
m_shifter.reset();
|
||||
m_inv_shifter.reset();
|
||||
}
|
||||
|
||||
template<typename Config>
|
||||
|
@ -519,6 +549,17 @@ void rewriter_tpl<Config>::cleanup() {
|
|||
rewriter_core::cleanup();
|
||||
m_bindings.finalize();
|
||||
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>
|
||||
|
@ -526,11 +567,14 @@ void rewriter_tpl<Config>::set_bindings(unsigned num_bindings, expr * const * bi
|
|||
SASSERT(!m_proof_gen);
|
||||
SASSERT(not_rewriting());
|
||||
m_bindings.reset();
|
||||
m_shifts.reset();
|
||||
unsigned i = num_bindings;
|
||||
while (i > 0) {
|
||||
--i;
|
||||
m_bindings.push_back(bindings[i]);
|
||||
m_shifts.push_back(UINT_MAX);
|
||||
}
|
||||
TRACE("rewriter", display_bindings(tout););
|
||||
}
|
||||
|
||||
template<typename Config>
|
||||
|
@ -538,9 +582,12 @@ void rewriter_tpl<Config>::set_inv_bindings(unsigned num_bindings, expr * const
|
|||
SASSERT(!m_proof_gen);
|
||||
SASSERT(not_rewriting());
|
||||
m_bindings.reset();
|
||||
m_shifts.reset();
|
||||
for (unsigned i = 0; i < num_bindings; i++) {
|
||||
m_bindings.push_back(bindings[i]);
|
||||
m_shifts.push_back(UINT_MAX);
|
||||
}
|
||||
TRACE("rewriter", display_bindings(tout););
|
||||
}
|
||||
|
||||
template<typename Config>
|
||||
|
@ -562,9 +609,11 @@ void rewriter_tpl<Config>::main_loop(expr * t, expr_ref & result, proof_ref & re
|
|||
result_pr = m().mk_reflexivity(t);
|
||||
SASSERT(result_pr_stack().empty());
|
||||
}
|
||||
return;
|
||||
}
|
||||
resume_core<ProofGen>(result, result_pr);
|
||||
else {
|
||||
resume_core<ProofGen>(result, result_pr);
|
||||
}
|
||||
TRACE("rewriter", tout << mk_ismt2_pp(t, m()) << "\n=>\n" << result << "\n";;);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
expr * r = get_cached(t);
|
||||
if (r) {
|
||||
SASSERT(m().get_sort(r) == m().get_sort(t));
|
||||
result_stack().push_back(r);
|
||||
if (ProofGen) {
|
||||
proof * pr = get_cached_pr(t);
|
||||
|
|
|
@ -579,7 +579,7 @@ br_status seq_rewriter::mk_seq_contains(expr* a, expr* b, expr_ref& result) {
|
|||
unsigned lenA = 0, lenB = 0;
|
||||
bool lA = min_length(as.size(), as.c_ptr(), lenA);
|
||||
if (lA) {
|
||||
bool lB = min_length(bs.size(), bs.c_ptr(), lenB);
|
||||
min_length(bs.size(), bs.c_ptr(), lenB);
|
||||
if (lenB > lenA) {
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
|
|
|
@ -29,7 +29,6 @@ model_core::~model_core() {
|
|||
decl2finterp::iterator it2 = m_finterp.begin();
|
||||
decl2finterp::iterator end2 = m_finterp.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
func_decl* d = it2->m_key;
|
||||
m_manager.dec_ref(it2->m_key);
|
||||
dealloc(it2->m_value);
|
||||
}
|
||||
|
|
|
@ -31,8 +31,9 @@ Revision History:
|
|||
#include"rewriter_def.h"
|
||||
#include"cooperate.h"
|
||||
|
||||
|
||||
struct evaluator_cfg : public default_rewriter_cfg {
|
||||
model_core & m_model;
|
||||
model_core & m_model;
|
||||
bool_rewriter m_b_rw;
|
||||
arith_rewriter m_a_rw;
|
||||
bv_rewriter m_bv_rw;
|
||||
|
@ -59,9 +60,10 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
m_pb_rw(m),
|
||||
m_f_rw(m),
|
||||
m_seq_rw(m) {
|
||||
m_b_rw.set_flat(false);
|
||||
m_a_rw.set_flat(false);
|
||||
m_bv_rw.set_flat(false);
|
||||
bool flat = true;
|
||||
m_b_rw.set_flat(flat);
|
||||
m_a_rw.set_flat(flat);
|
||||
m_bv_rw.set_flat(flat);
|
||||
m_bv_rw.set_mkbv2num(true);
|
||||
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) {
|
||||
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);
|
||||
if (fi != 0) {
|
||||
TRACE_MACRO;
|
||||
if (fi->is_partial()) {
|
||||
if (m_model_completion) {
|
||||
sort * s = f->get_range();
|
||||
|
@ -204,6 +208,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
(f->get_family_id() == null_family_id ||
|
||||
m().get_plugin(f->get_family_id())->is_considered_uninterpreted(f)))
|
||||
{
|
||||
TRACE_MACRO;
|
||||
sort * s = f->get_range();
|
||||
expr * val = m_model.get_some_value(s);
|
||||
func_interp * new_fi = alloc(func_interp, m(), f->get_arity());
|
||||
|
|
|
@ -4,5 +4,6 @@ def_module_params('model',
|
|||
('v1', BOOL, False, 'use Z3 version 1.x 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)'),
|
||||
('new_eval', BOOL, True, 'use new evaluator (temporary parameter for testing)'),
|
||||
))
|
||||
|
||||
|
|
|
@ -30,12 +30,14 @@ Revision History:
|
|||
proto_model::proto_model(ast_manager & m, simplifier & s, params_ref const & p):
|
||||
model_core(m),
|
||||
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));
|
||||
m_user_sort_factory = alloc(user_sort_factory, m);
|
||||
register_factory(m_user_sort_factory);
|
||||
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
SASSERT(is_well_sorted(m_manager, e));
|
||||
TRACE("model_eval", tout << mk_pp(e, m_manager) << "\n";
|
||||
|
|
|
@ -29,6 +29,7 @@ Revision History:
|
|||
#define PROTO_MODEL_H_
|
||||
|
||||
#include"model_core.h"
|
||||
#include"model_evaluator.h"
|
||||
#include"value_factory.h"
|
||||
#include"plugin_manager.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
|
||||
func_decl_set m_aux_decls;
|
||||
ptr_vector<expr> m_tmp;
|
||||
model_evaluator m_eval;
|
||||
|
||||
bool m_model_partial;
|
||||
bool m_use_new_eval;
|
||||
|
||||
expr * mk_some_interp_for(func_decl * d);
|
||||
|
||||
|
|
|
@ -95,7 +95,8 @@ namespace smt {
|
|||
expr * e = *it;
|
||||
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
|
||||
|
@ -105,9 +106,13 @@ namespace smt {
|
|||
|
||||
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) {
|
||||
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";);
|
||||
ptr_buffer<expr> subst_args;
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
|
@ -261,10 +266,11 @@ namespace smt {
|
|||
|
||||
lbool r = m_aux_context->check();
|
||||
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);
|
||||
return true; // quantifier is satisfied by m_curr_model
|
||||
return r == l_false; // quantifier is satisfied by m_curr_model
|
||||
}
|
||||
|
||||
model_ref complete_cex;
|
||||
m_aux_context->get_model(complete_cex);
|
||||
|
||||
|
@ -276,7 +282,7 @@ namespace smt {
|
|||
while (true) {
|
||||
lbool r = m_aux_context->check();
|
||||
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;
|
||||
model_ref cex;
|
||||
m_aux_context->get_model(cex);
|
||||
|
|
|
@ -1619,6 +1619,7 @@ namespace smt {
|
|||
m_found_underspecified_op(false),
|
||||
m_arith_eq_adapter(*this, params, m_util),
|
||||
m_asserted_qhead(0),
|
||||
m_row_vars_top(0),
|
||||
m_to_patch(1024),
|
||||
m_blands_rule(false),
|
||||
m_random(params.m_arith_random_seed),
|
||||
|
@ -1631,7 +1632,6 @@ namespace smt {
|
|||
m_liberal_final_check(true),
|
||||
m_changed_assignment(false),
|
||||
m_assume_eq_head(0),
|
||||
m_row_vars_top(0),
|
||||
m_nl_rounds(0),
|
||||
m_nl_gb_exhausted(false),
|
||||
m_nl_new_exprs(m),
|
||||
|
|
|
@ -1591,7 +1591,6 @@ bool theory_seq::solve_ne(unsigned idx) {
|
|||
}
|
||||
|
||||
bool theory_seq::solve_nc(unsigned idx) {
|
||||
context& ctx = get_context();
|
||||
nc const& n = m_ncs[idx];
|
||||
|
||||
dependency* deps = n.deps();
|
||||
|
|
|
@ -24,6 +24,7 @@ Notes:
|
|||
#include"params.h"
|
||||
#include"ast_pp.h"
|
||||
#include"bvarray2uf_rewriter.h"
|
||||
#include"rewriter_def.h"
|
||||
|
||||
// [1] C. M. Wintersteiger, Y. Hamadi, and L. de Moura: Efficiently Solving
|
||||
// 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();
|
||||
return true;
|
||||
}
|
||||
|
||||
template class rewriter_tpl<bvarray2uf_rewriter_cfg>;
|
||||
|
|
|
@ -20,7 +20,7 @@ Notes:
|
|||
#ifndef BVARRAY2UF_REWRITER_H_
|
||||
#define BVARRAY2UF_REWRITER_H_
|
||||
|
||||
#include"rewriter_def.h"
|
||||
#include"rewriter.h"
|
||||
#include"extension_model_converter.h"
|
||||
#include"filter_model_converter.h"
|
||||
|
||||
|
@ -71,7 +71,6 @@ protected:
|
|||
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> {
|
||||
bvarray2uf_rewriter_cfg m_cfg;
|
||||
|
|
|
@ -226,6 +226,7 @@ int main(int argc, char ** argv) {
|
|||
TST(sat_user_scope);
|
||||
TST(pdr);
|
||||
TST_ARGV(ddnf);
|
||||
TST(model_evaluator);
|
||||
//TST_ARGV(hs);
|
||||
}
|
||||
|
||||
|
|
66
src/test/model_evaluator.cpp
Normal file
66
src/test/model_evaluator.cpp
Normal 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";
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue