diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 2cf33941e..6d139a5bd 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -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(); diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp index e31e5aab6..7d5248b30 100644 --- a/src/ast/ast_smt2_pp.cpp +++ b/src/ast/ast_smt2_pp.cpp @@ -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); diff --git a/src/ast/fpa/fpa2bv_rewriter.cpp b/src/ast/fpa/fpa2bv_rewriter.cpp new file mode 100644 index 000000000..45a87087c --- /dev/null +++ b/src/ast/fpa/fpa2bv_rewriter.cpp @@ -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 new_decl_sorts; + sbuffer 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; diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index c3720421c..7bfc60be4 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -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 new_decl_sorts; - sbuffer 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; struct fpa2bv_rewriter : public rewriter_tpl { fpa2bv_rewriter_cfg m_cfg; diff --git a/src/ast/rewriter/arith_rewriter.cpp b/src/ast/rewriter/arith_rewriter.cpp index e48a4fd2a..550171ab5 100644 --- a/src/ast/rewriter/arith_rewriter.cpp +++ b/src/ast/rewriter/arith_rewriter.cpp @@ -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; diff --git a/src/ast/rewriter/bool_rewriter.cpp b/src/ast/rewriter/bool_rewriter.cpp index 0b8a51fb4..48dffdb58 100644 --- a/src/ast/rewriter/bool_rewriter.cpp +++ b/src/ast/rewriter/bool_rewriter.cpp @@ -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 diff --git a/src/ast/rewriter/rewriter.cpp b/src/ast/rewriter/rewriter.cpp index e9f66f10c..2b5e7e006 100644 --- a/src/ast/rewriter/rewriter.cpp +++ b/src/ast/rewriter/rewriter.cpp @@ -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; diff --git a/src/ast/rewriter/rewriter.h b/src/ast/rewriter/rewriter.h index 934d186aa..44f436fa8 100644 --- a/src/ast/rewriter/rewriter.h +++ b/src/ast/rewriter/rewriter.h @@ -214,10 +214,12 @@ protected: unsigned m_num_steps; ptr_vector 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_stack() { return this->m_frame_stack; } svector 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. diff --git a/src/ast/rewriter/rewriter_def.h b/src/ast/rewriter/rewriter_def.h index 9bfe47f46..4837a053f 100644 --- a/src/ast/rewriter/rewriter_def.h +++ b/src/ast/rewriter/rewriter_def.h @@ -24,6 +24,7 @@ template void rewriter_tpl::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::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 void rewriter_tpl::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::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::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::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::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::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::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::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(t, m_r, m_pr, fr.m_cache_result); @@ -411,23 +431,26 @@ template template void rewriter_tpl::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(child, fr.m_max_depth)) + if (!visit(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::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::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(q, m_r, m_pr, fr.m_cache_result); } @@ -496,6 +523,7 @@ rewriter_tpl::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::reset() { m_cfg.reset(); rewriter_core::reset(); m_bindings.reset(); + m_shifts.reset(); m_shifter.reset(); + m_inv_shifter.reset(); } template @@ -519,6 +549,17 @@ void rewriter_tpl::cleanup() { rewriter_core::cleanup(); m_bindings.finalize(); m_shifter.cleanup(); + m_shifts.finalize(); + m_inv_shifter.cleanup(); +} + +template +void rewriter_tpl::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 @@ -526,11 +567,14 @@ void rewriter_tpl::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 @@ -538,9 +582,12 @@ void rewriter_tpl::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 @@ -562,9 +609,11 @@ void rewriter_tpl::main_loop(expr * t, expr_ref & result, proof_ref & re result_pr = m().mk_reflexivity(t); SASSERT(result_pr_stack().empty()); } - return; } - resume_core(result, result_pr); + else { + resume_core(result, result_pr); + } + TRACE("rewriter", tout << mk_ismt2_pp(t, m()) << "\n=>\n" << result << "\n";;); } /** @@ -587,6 +636,7 @@ void rewriter_tpl::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); diff --git a/src/ast/rewriter/seq_rewriter.cpp b/src/ast/rewriter/seq_rewriter.cpp index f04d445e1..75c8266be 100644 --- a/src/ast/rewriter/seq_rewriter.cpp +++ b/src/ast/rewriter/seq_rewriter.cpp @@ -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; diff --git a/src/model/model_core.cpp b/src/model/model_core.cpp index 5c2fd81d4..3a3a8a93a 100644 --- a/src/model/model_core.cpp +++ b/src/model/model_core.cpp @@ -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); } diff --git a/src/model/model_evaluator.cpp b/src/model/model_evaluator.cpp index d417adc1b..486111ae4 100644 --- a/src/model/model_evaluator.cpp +++ b/src/model/model_evaluator.cpp @@ -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()); diff --git a/src/model/model_params.pyg b/src/model/model_params.pyg index 14e83952c..dfa3748bc 100644 --- a/src/model/model_params.pyg +++ b/src/model/model_params.pyg @@ -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)'), )) diff --git a/src/smt/proto_model/proto_model.cpp b/src/smt/proto_model/proto_model.cpp index 485fe1751..cb6b8c68d 100644 --- a/src/smt/proto_model/proto_model.cpp +++ b/src/smt/proto_model/proto_model.cpp @@ -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"; diff --git a/src/smt/proto_model/proto_model.h b/src/smt/proto_model/proto_model.h index 1b63f8b20..2c27ac39a 100644 --- a/src/smt/proto_model/proto_model.h +++ b/src/smt/proto_model/proto_model.h @@ -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 m_tmp; + model_evaluator m_eval; bool m_model_partial; + bool m_use_new_eval; expr * mk_some_interp_for(func_decl * d); diff --git a/src/smt/smt_model_checker.cpp b/src/smt/smt_model_checker.cpp index e4bfcc806..0d9c361f8 100644 --- a/src/smt/smt_model_checker.cpp +++ b/src/smt/smt_model_checker.cpp @@ -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 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); diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index 301b5d14d..291a0f0d8 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -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), diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index 551e80c85..5bd00db5d 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -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(); diff --git a/src/tactic/bv/bvarray2uf_rewriter.cpp b/src/tactic/bv/bvarray2uf_rewriter.cpp index f4f7fac16..54c654d54 100644 --- a/src/tactic/bv/bvarray2uf_rewriter.cpp +++ b/src/tactic/bv/bvarray2uf_rewriter.cpp @@ -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; diff --git a/src/tactic/bv/bvarray2uf_rewriter.h b/src/tactic/bv/bvarray2uf_rewriter.h index e65340cc3..81b53ddd7 100644 --- a/src/tactic/bv/bvarray2uf_rewriter.h +++ b/src/tactic/bv/bvarray2uf_rewriter.h @@ -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; struct bvarray2uf_rewriter : public rewriter_tpl { bvarray2uf_rewriter_cfg m_cfg; diff --git a/src/test/main.cpp b/src/test/main.cpp index be12286fb..875f7bed0 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -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); } diff --git a/src/test/model_evaluator.cpp b/src/test/model_evaluator.cpp new file mode 100644 index 000000000..6e3a1f441 --- /dev/null +++ b/src/test/model_evaluator.cpp @@ -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"; + } + +}