/*++ Copyright (c) 2015 Microsoft Corporation --*/ #include "ast/rewriter/bv_elim.h" #include "ast/bv_decl_plugin.h" #include "ast/rewriter/var_subst.h" #include "ast/rewriter/rewriter_def.h" #include bool bv_elim_cfg::reduce_quantifier(quantifier * q, expr * body, expr * const * new_patterns, expr * const * new_no_patterns, expr_ref & result, proof_ref & result_pr) { svector names, _names; sort_ref_buffer sorts(m), _sorts(m); expr_ref_buffer pats(m); expr_ref_buffer no_pats(m); expr_ref_buffer subst_map(m), _subst_map(m); var_subst subst(m); bv_util bv(m); expr_ref new_body(m); expr* old_body = body; unsigned num_decls = q->get_num_decls(); family_id bfid = m.mk_family_id("bv"); // // Traverse sequence of bound variables to eliminate // bit-vecctor variables and replace them by // Booleans. // unsigned var_idx = 0; bool found = false; for (unsigned i = num_decls; i > 0; ) { --i; sort* s = q->get_decl_sort(i); symbol nm = q->get_decl_name(i); if (bv.is_bv_sort(s)) { // convert n-bit bit-vector variable into sequence of n-Booleans. unsigned num_bits = bv.get_bv_size(s); expr_ref_buffer args(m); expr_ref bv(m); found = true; for (unsigned j = 0; j < num_bits; ++j) { std::ostringstream new_name; new_name << nm.str(); new_name << '_'; new_name << j; var* v = m.mk_var(var_idx++, m.mk_bool_sort()); args.push_back(v); _sorts.push_back(m.mk_bool_sort()); _names.push_back(symbol(new_name.str())); } bv = m.mk_app(bfid, OP_MKBV, 0, nullptr, args.size(), args.data()); _subst_map.push_back(bv.get()); } else { _subst_map.push_back(m.mk_var(var_idx++, s)); _sorts.push_back(s); _names.push_back(nm); } } if (!found) { return false; } // // reverse the vectors. // SASSERT(_names.size() == _sorts.size()); for (unsigned i = _names.size(); i > 0; ) { --i; names.push_back(_names[i]); sorts.push_back(_sorts[i]); } for (unsigned i = _subst_map.size(); i > 0; ) { --i; subst_map.push_back(_subst_map[i]); } expr* const* sub = subst_map.data(); unsigned sub_size = subst_map.size(); new_body = subst(old_body, sub_size, sub); for (unsigned j = 0; j < q->get_num_patterns(); j++) { pats.push_back(subst(new_patterns[j], sub_size, sub)); } for (unsigned j = 0; j < q->get_num_no_patterns(); j++) { no_pats.push_back(subst(new_no_patterns[j], sub_size, sub)); } result = m.mk_quantifier(forall_k, names.size(), sorts.data(), names.data(), new_body.get(), q->get_weight(), q->get_qid(), q->get_skid(), pats.size(), pats.data(), no_pats.size(), no_pats.data()); result_pr = m.mk_rewrite(q, result); return true; }