void subst(contains_app& x, rational const& vl, expr_ref& fml, expr_ref* def) override { app_ref c(m_bv.mk_numeral(vl, m_bv.get_bv_size(x.x())), m); m_replace.apply_substitution(x.x(), c, fml); if (def) { *def = m_bv.mk_numeral(vl, m_bv.get_bv_size(x.x())); } }
bool reduce_quantifier( quantifier * q, expr * old_body, expr * const * new_patterns, expr * const * new_no_patterns, expr_ref & result, proof_ref & result_pr) { if (q->get_kind() == lambda_k) return false; m_sorts.reset(); expr_ref_vector bounds(m); bool found = false; for (unsigned i = 0; i < q->get_num_decls(); ++i) { sort* s = q->get_decl_sort(i); if (m_imp.is_fd(s)) { unsigned bv_size = get_bv_size(s); m_sorts.push_back(m_bv.mk_sort(bv_size)); unsigned nc = m_dt.get_datatype_num_constructors(s); if (!is_power_of_two(nc) || nc == 1) { bounds.push_back(m_bv.mk_ule(m.mk_var(q->get_num_decls()-i-1, m_sorts[i]), m_bv.mk_numeral(nc-1, bv_size))); } found = true; } else { m_sorts.push_back(s); } } if (!found) { return false; } expr_ref new_body_ref(old_body, m), tmp(m); if (!bounds.empty()) { switch (q->get_kind()) { case forall_k: new_body_ref = m.mk_implies(mk_and(bounds), new_body_ref); break; case exists_k: bounds.push_back(new_body_ref); new_body_ref = mk_and(bounds); break; case lambda_k: UNREACHABLE(); break; } } result = m.mk_quantifier(q->get_kind(), q->get_num_decls(), m_sorts.c_ptr(), q->get_decl_names(), new_body_ref, q->get_weight(), q->get_qid(), q->get_skid(), q->get_num_patterns(), new_patterns, q->get_num_no_patterns(), new_no_patterns); result_pr = nullptr; return true; }
void operator()(app * n) { if (!m.is_bool(n) && !u.is_bv(n)) throw found(); family_id fid = n->get_family_id(); if (fid == m.get_basic_family_id()) return; if (fid == u.get_family_id()) return; if (is_uninterp_const(n)) return; throw found(); }
void operator()(app * n) { sort * s = get_sort(n); if (!m.is_bool(s) && !fu.is_float(s) && !fu.is_rm(s) && !bu.is_bv_sort(s) && !au.is_real(s)) throw found(); family_id fid = n->get_family_id(); if (fid == m.get_basic_family_id()) return; if (fid == fu.get_family_id() || fid == bu.get_family_id()) return; if (is_uninterp_const(n)) return; if (au.is_real(s) && au.is_numeral(n)) return; throw found(); }
bool project(contains_app& x, model_ref& model, expr_ref& fml) override { model_evaluator model_eval(*model); expr_ref val_x(m); rational val(0); unsigned bv_size; model_eval(x.x(), val_x); m_bv.is_numeral(val_x, val, bv_size); subst(x, val, fml, nullptr); return true; }
bool reduce_arg(expr* a, expr_ref& result) { sort* s = get_sort(a); if (!m_imp.is_fd(s)) { return false; } unsigned bv_size = get_bv_size(s); if (is_var(a)) { result = m.mk_var(to_var(a)->get_idx(), m_bv.mk_sort(bv_size)); return true; } SASSERT(is_app(a)); func_decl* f = to_app(a)->get_decl(); if (m_dt.is_constructor(f)) { unsigned idx = m_dt.get_constructor_idx(f); result = m_bv.mk_numeral(idx, bv_size); } else if (is_uninterp_const(a)) { func_decl* f_fresh; if (m_imp.m_enum2bv.find(f, f_fresh)) { result = m.mk_const(f_fresh); return true; } // create a fresh variable, add bounds constraints for it. unsigned nc = m_dt.get_datatype_num_constructors(s); result = m.mk_fresh_const(f->get_name().str().c_str(), m_bv.mk_sort(bv_size)); f_fresh = to_app(result)->get_decl(); if (!is_power_of_two(nc) || nc == 1) { m_imp.m_bounds.push_back(m_bv.mk_ule(result, m_bv.mk_numeral(nc-1, bv_size))); } expr_ref f_def(m); ptr_vector<func_decl> const& cs = *m_dt.get_datatype_constructors(s); f_def = m.mk_const(cs[nc-1]); for (unsigned i = nc - 1; i > 0; ) { --i; f_def = m.mk_ite(m.mk_eq(result, m_bv.mk_numeral(i,bv_size)), m.mk_const(cs[i]), f_def); } m_imp.m_enum2def.insert(f, f_def); m_imp.m_enum2bv.insert(f, f_fresh); m_imp.m_bv2enum.insert(f_fresh, f); m_imp.m_enum_consts.push_back(f); m_imp.m_enum_bvs.push_back(f_fresh); m_imp.m_enum_defs.push_back(f_def); } else { throw_non_fd(a); } ++m_imp.m_num_translated; return true; }
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { expr_ref a0(m), a1(m); expr_ref_vector _args(m); if (m.is_eq(f) && reduce_arg(args[0], a0) && reduce_arg(args[1], a1)) { result = m.mk_eq(a0, a1); return BR_DONE; } else if (m.is_distinct(f) && reduce_args(num, args, _args)) { result = m.mk_distinct(_args.size(), _args.c_ptr()); return BR_DONE; } else if (m_dt.is_recognizer(f) && reduce_arg(args[0], a0)) { unsigned idx = m_dt.get_recognizer_constructor_idx(f); a1 = m_bv.mk_numeral(rational(idx), get_sort(a0)); result = m.mk_eq(a0, a1); return BR_DONE; } else { check_for_fd(num, args); return BR_FAILED; } }
bool get_num_branches(contains_app& x, expr* fml, rational& nb) override { unsigned sz = m_bv.get_bv_size(x.x()); nb = power(rational(2), sz); return true; }
virtual void operator()( goal_ref const & g, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { SASSERT(g->is_well_sorted()); mc = 0; pc = 0; core = 0; m_trail.reset(); m_fd.reset(); m_max.reset(); m_nonfd.reset(); m_bounds.reset(); ref<bvmc> mc1 = alloc(bvmc); tactic_report report("eq2bv", *g); m_bounds(*g); for (unsigned i = 0; i < g->size(); i++) { collect_fd(g->form(i)); } cleanup_fd(mc1); if (m_max.empty()) { result.push_back(g.get()); return; } for (unsigned i = 0; i < g->size(); i++) { expr_ref new_curr(m); proof_ref new_pr(m); if (is_bound(g->form(i))) { g->update(i, m.mk_true(), 0, 0); continue; } m_rw(g->form(i), new_curr, new_pr); if (m.proofs_enabled() && !new_pr) { new_pr = m.mk_rewrite(g->form(i), new_curr); new_pr = m.mk_modus_ponens(g->pr(i), new_pr); } g->update(i, new_curr, new_pr, g->dep(i)); } obj_map<expr, unsigned>::iterator it = m_max.begin(), end = m_max.end(); for (; it != end; ++it) { expr* c = it->m_key; bool strict; rational r; if (m_bounds.has_lower(c, r, strict)) { SASSERT(!strict); expr* d = m_fd.find(c); g->assert_expr(bv.mk_ule(bv.mk_numeral(r, m.get_sort(d)), d), m_bounds.lower_dep(c)); } if (m_bounds.has_upper(c, r, strict)) { SASSERT(!strict); expr* d = m_fd.find(c); g->assert_expr(bv.mk_ule(d, bv.mk_numeral(r, m.get_sort(d))), m_bounds.upper_dep(c)); } } g->inc_depth(); mc = mc1.get(); result.push_back(g.get()); TRACE("pb", g->display(tout););