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

integrate lambda expressions

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2018-06-26 07:23:04 -07:00
parent bf4edef761
commit 520ce9a5ee
139 changed files with 2243 additions and 1506 deletions

View file

@ -20,6 +20,7 @@ Notes:
#include "ast/rewriter/array_rewriter_params.hpp"
#include "ast/ast_lt.h"
#include "ast/ast_pp.h"
#include "ast/rewriter/var_subst.h"
void array_rewriter::updt_params(params_ref const & _p) {
array_rewriter_params p(_p);
@ -196,6 +197,17 @@ br_status array_rewriter::mk_select_core(unsigned num_args, expr * const * args,
return BR_DONE;
}
if (is_lambda(args[0])) {
// anywhere lambda reduction as opposed to whnf
// select(lambda(X) M, N) -> M[N/X]
quantifier* q = to_quantifier(args[0]);
SASSERT(q->get_num_decls() == num_args - 1);
var_subst subst(m());
result = subst(q->get_expr(), num_args - 1, args + 1);
return BR_REWRITE_FULL;
}
if (m_util.is_as_array(args[0])) {
// select(as-array[f], I) --> f(I)
func_decl * f = m_util.get_as_array_func_decl(to_app(args[0]));

View file

@ -636,7 +636,7 @@ MK_PARAMETRIC_UNARY_REDUCE(reduce_sign_extend, mk_sign_extend);
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(),
result = m().mk_quantifier(old_q->get_kind(), 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 = nullptr;

View file

@ -588,58 +588,39 @@ br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result)
VERIFY(m().is_ite(ite, cond, t, e));
SASSERT(m().is_value(val));
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) {
if (m().are_distinct(val, e)) {
result = m().mk_and(m().mk_eq(t, val), cond);
return BR_REWRITE2;
}
if (m().are_distinct(val, t)) {
result = m().mk_and(m().mk_eq(e, val), m().mk_not(cond));
return BR_REWRITE2;
}
if (m().are_equal(val, t)) {
if (m().are_equal(val, e)) {
result = m().mk_true();
}
else if (t == val) {
result = cond;
return BR_DONE;
}
else {
SASSERT(e == val);
mk_not(cond, result);
result = m().mk_or(m().mk_eq(e, val), cond);
}
return BR_DONE;
return BR_REWRITE2;
}
if (m_ite_extra_rules) {
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;
}
if (m().are_equal(val, e)) {
result = m().mk_or(m().mk_eq(t, val), m().mk_not(cond));
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;
}
expr* cond2 = nullptr, *t2 = nullptr, *e2 = nullptr;
if (m().is_ite(t, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
try_ite_value(to_app(t), val, result);
result = m().mk_ite(cond, result, m().mk_eq(e, val));
return BR_REWRITE2;
}
if (m().is_ite(e, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
try_ite_value(to_app(e), val, result);
result = m().mk_ite(cond, m().mk_eq(t, val), result);
return BR_REWRITE2;
}
return BR_FAILED;

View file

@ -87,20 +87,16 @@ bool bv_elim_cfg::reduce_quantifier(quantifier * q,
expr* const* sub = subst_map.c_ptr();
unsigned sub_size = subst_map.size();
subst(old_body, sub_size, sub, new_body);
new_body = subst(old_body, sub_size, sub);
for (unsigned j = 0; j < q->get_num_patterns(); j++) {
expr_ref pat(m);
subst(new_patterns[j], sub_size, sub, pat);
pats.push_back(pat);
pats.push_back(subst(new_patterns[j], sub_size, sub));
}
for (unsigned j = 0; j < q->get_num_no_patterns(); j++) {
expr_ref nopat(m);
subst(new_no_patterns[j], sub_size, sub, nopat);
no_pats.push_back(nopat);
no_pats.push_back(subst(new_no_patterns[j], sub_size, sub));
}
result = m.mk_quantifier(true,
result = m.mk_quantifier(forall_k,
names.size(),
sorts.c_ptr(),
names.c_ptr(),

View file

@ -133,7 +133,7 @@ void der::operator()(quantifier * q, expr_ref & r, proof_ref & pr) {
// Eliminate variables that have become unused
if (reduced && is_forall(r)) {
quantifier * q = to_quantifier(r);
elim_unused_vars(m_manager, q, params_ref(), r);
r = elim_unused_vars(m_manager, q, params_ref());
if (m_manager.proofs_enabled()) {
proof * p1 = m_manager.mk_elim_unused_vars(q, r);
pr = m_manager.mk_transitivity(pr, p1);
@ -343,8 +343,7 @@ void der::create_substitution(unsigned sz) {
expr_ref cur(m_map[m_order[i]], m_manager);
// do all the previous substitutions before inserting
expr_ref r(m_manager);
m_subst(cur, m_subst_map.size(), m_subst_map.c_ptr(), r);
expr_ref r = m_subst(cur, m_subst_map.size(), m_subst_map.c_ptr());
unsigned inx = sz - m_order[i]- 1;
SASSERT(m_subst_map[inx]==0);
@ -369,21 +368,18 @@ void der::apply_substitution(quantifier * q, expr_ref & r) {
unsigned sz = m_new_args.size();
expr_ref t(m_manager);
t = (sz == 1) ? m_new_args[0] : m_manager.mk_or(sz, m_new_args.c_ptr());
expr_ref new_e(m_manager);
m_subst(t, m_subst_map.size(), m_subst_map.c_ptr(), new_e);
expr_ref new_e = m_subst(t, m_subst_map.size(), m_subst_map.c_ptr());
// don't forget to update the quantifier patterns
expr_ref_buffer new_patterns(m_manager);
expr_ref_buffer new_no_patterns(m_manager);
for (unsigned j = 0; j < q->get_num_patterns(); j++) {
expr_ref new_pat(m_manager);
m_subst(q->get_pattern(j), m_subst_map.size(), m_subst_map.c_ptr(), new_pat);
expr_ref new_pat = m_subst(q->get_pattern(j), m_subst_map.size(), m_subst_map.c_ptr());
new_patterns.push_back(new_pat);
}
for (unsigned j = 0; j < q->get_num_no_patterns(); j++) {
expr_ref new_nopat(m_manager);
m_subst(q->get_no_pattern(j), m_subst_map.size(), m_subst_map.c_ptr(), new_nopat);
expr_ref new_nopat = m_subst(q->get_no_pattern(j), m_subst_map.size(), m_subst_map.c_ptr());
new_no_patterns.push_back(new_nopat);
}

View file

@ -100,7 +100,7 @@ void distribute_forall::reduce1_app(app * a) {
void distribute_forall::reduce1_quantifier(quantifier * q) {
// This transformation is applied after skolemization/quantifier elimination. So, all quantifiers are universal.
SASSERT(q->is_forall());
SASSERT(q->get_kind() == forall_k);
// This transformation is applied after basic pre-processing steps.
// So, we can assume that
@ -126,8 +126,7 @@ void distribute_forall::reduce1_quantifier(quantifier * q) {
br.mk_not(arg, not_arg);
quantifier_ref tmp_q(m_manager);
tmp_q = m_manager.update_quantifier(q, not_arg);
expr_ref new_q(m_manager);
elim_unused_vars(m_manager, tmp_q, params_ref(), new_q);
expr_ref new_q = elim_unused_vars(m_manager, tmp_q, params_ref());
new_args.push_back(new_q);
}
expr_ref result(m_manager);

View file

@ -114,7 +114,7 @@ bool elim_bounds_cfg::reduce_quantifier(quantifier * q,
expr * const * new_no_patterns,
expr_ref & result,
proof_ref & result_pr) {
if (!q->is_forall()) {
if (!is_forall(q)) {
return false;
}
unsigned num_vars = q->get_num_decls();
@ -194,7 +194,7 @@ bool elim_bounds_cfg::reduce_quantifier(quantifier * q,
}
quantifier_ref new_q(m);
new_q = m.update_quantifier(q, new_body);
elim_unused_vars(m, new_q, params_ref(), result);
result = elim_unused_vars(m, new_q, params_ref());
result_pr = m.mk_rewrite(q, result);
TRACE("elim_bounds", tout << mk_pp(q, m) << "\n" << result << "\n";);
return true;

View file

@ -159,6 +159,8 @@ struct enum2bv_rewriter::imp {
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;
@ -182,15 +184,20 @@ struct enum2bv_rewriter::imp {
}
expr_ref new_body_ref(old_body, m), tmp(m);
if (!bounds.empty()) {
if (q->is_forall()) {
switch (q->get_kind()) {
case forall_k:
new_body_ref = m.mk_implies(mk_and(bounds), new_body_ref);
}
else {
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->is_forall(), q->get_num_decls(), m_sorts.c_ptr(), q->get_decl_names(), new_body_ref,
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);

View file

@ -32,7 +32,7 @@ bool simplify_inj_axiom(ast_manager & m, quantifier * q, expr_ref & result) {
expr* arg1 = nullptr, * arg2 = nullptr, *narg = nullptr;
expr* app1 = nullptr, * app2 = nullptr;
expr* var1 = nullptr, * var2 = nullptr;
if (q->is_forall() && m.is_or(n, arg1, arg2)) {
if (is_forall(q) && m.is_or(n, arg1, arg2)) {
if (m.is_not(arg2))
std::swap(arg1, arg2);
if (m.is_not(arg1, narg) &&

View file

@ -79,12 +79,12 @@ public:
vars.push_back(a);
}
expr * const * exprs = (expr* const*) (vars.c_ptr() + vars.size()- nd);
instantiate(m, q, exprs, result);
result = instantiate(m, q, exprs);
}
unsigned pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names, bool use_fresh, bool rewrite_ok) {
unsigned pull_quantifier(bool _is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names, bool use_fresh, bool rewrite_ok) {
unsigned index = var_counter().get_next_var(fml);
while (is_quantifier(fml) && (is_forall == to_quantifier(fml)->is_forall())) {
while (is_quantifier(fml) && _is_forall == is_forall(fml)) {
quantifier* q = to_quantifier(fml);
index += q->get_num_decls();
if (names) {
@ -99,7 +99,7 @@ public:
return index;
}
app_ref_vector vars(m);
pull_quantifier(is_forall, fml, vars, use_fresh, rewrite_ok);
pull_quantifier(_is_forall, fml, vars, use_fresh, rewrite_ok);
if (vars.empty()) {
return index;
}
@ -277,12 +277,16 @@ private:
}
case AST_QUANTIFIER: {
quantifier* q = to_quantifier(fml);
expr_ref tmp(m);
if (!is_compatible(qt, q->is_forall())) {
if (is_lambda(q)) {
result = fml;
break;
}
set_quantifier_type(qt, q->is_forall());
expr_ref tmp(m);
if (!is_compatible(qt, is_forall(q))) {
result = fml;
break;
}
set_quantifier_type(qt, is_forall(q));
extract_quantifier(q, vars, tmp, use_fresh);
pull_quantifier(tmp, qt, vars, result, use_fresh, rewrite_ok);
break;

View file

@ -208,12 +208,10 @@ void rewriter_core::cleanup() {
#ifdef _TRACE
void rewriter_core::display_stack(std::ostream & out, unsigned pp_depth) {
svector<frame>::iterator it = m_frame_stack.begin();
svector<frame>::iterator end = m_frame_stack.end();
for (; it != end; ++it) {
out << mk_bounded_pp(it->m_curr, m(), pp_depth) << "\n";
out << "state: " << it->m_state << "\n";
out << "cache: " << it->m_cache_result << ", new_child: " << it->m_new_child << ", max-depth: " << it->m_max_depth << ", i: " << it->m_i << "\n";
for (frame& f : m_frame_stack) {
out << mk_bounded_pp(f.m_curr, m(), pp_depth) << "\n";
out << "state: " << f.m_state << "\n";
out << "cache: " << f.m_cache_result << ", new_child: " << f.m_new_child << ", max-depth: " << f.m_max_depth << ", i: " << f.m_i << "\n";
out << "------------------\n";
}
}

View file

@ -350,11 +350,13 @@ public:
void update_inv_binding_at(unsigned i, expr* binding);
void operator()(expr * t, expr_ref & result, proof_ref & result_pr);
void operator()(expr * t, expr_ref & result) { operator()(t, result, m_pr); }
void operator()(expr * n, unsigned num_bindings, expr * const * bindings, expr_ref & result) {
expr_ref operator()(expr * n, unsigned num_bindings, expr * const * bindings) {
expr_ref result(m());
SASSERT(!m_proof_gen);
reset();
set_inv_bindings(num_bindings, bindings);
operator()(n, result);
return result;
}
void resume(expr_ref & result, proof_ref & result_pr);

View file

@ -542,7 +542,7 @@ 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));
SASSERT(m().get_sort(q) == m().get_sort(m_r));
if (!ProofGen) {
SASSERT(num_decls <= m_bindings.size());
m_bindings.shrink(m_bindings.size() - num_decls);

View file

@ -36,7 +36,7 @@ expr_ref sym_expr::accept(expr* e) {
switch (m_ty) {
case t_pred: {
var_subst subst(m);
subst(m_t, 1, &e, result);
result = subst(m_t, 1, &e);
break;
}
case t_char:

View file

@ -16,6 +16,7 @@ Author:
Notes:
--*/
#include "util/cooperate.h"
#include "ast/rewriter/th_rewriter.h"
#include "ast/rewriter/rewriter_params.hpp"
#include "ast/rewriter/bool_rewriter.h"
@ -28,10 +29,9 @@ Notes:
#include "ast/rewriter/pb_rewriter.h"
#include "ast/rewriter/seq_rewriter.h"
#include "ast/rewriter/rewriter_def.h"
#include "ast/rewriter/var_subst.h"
#include "ast/expr_substitution.h"
#include "ast/ast_smt2_pp.h"
#include "util/cooperate.h"
#include "ast/rewriter/var_subst.h"
#include "ast/ast_util.h"
#include "ast/well_sorted.h"
@ -606,7 +606,8 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
quantifier_ref q1(m());
proof * p1 = nullptr;
if (is_quantifier(new_body) &&
to_quantifier(new_body)->is_forall() == old_q->is_forall() &&
to_quantifier(new_body)->get_kind() == old_q->get_kind() &&
to_quantifier(new_body)->get_kind() != lambda_k &&
!old_q->has_patterns() &&
!to_quantifier(new_body)->has_patterns()) {
@ -619,7 +620,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
sorts.append(nested_q->get_num_decls(), nested_q->get_decl_sorts());
names.append(nested_q->get_num_decls(), nested_q->get_decl_names());
q1 = m().mk_quantifier(old_q->is_forall(),
q1 = m().mk_quantifier(old_q->get_kind(),
sorts.size(),
sorts.c_ptr(),
names.c_ptr(),
@ -653,17 +654,19 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
SASSERT(is_well_sorted(m(), q1));
}
elim_unused_vars(m(), q1, params_ref(), result);
SASSERT(m().get_sort(old_q) == m().get_sort(q1));
result = elim_unused_vars(m(), q1, params_ref());
TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m()) << "\n";);
TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << result << "\n";);
result_pr = nullptr;
if (m().proofs_enabled()) {
proof * p2 = nullptr;
if (q1.get() != result.get())
if (q1.get() != result.get() && q1->get_kind() != lambda_k)
p2 = m().mk_elim_unused_vars(q1, result);
result_pr = m().mk_transitivity(p1, p2);
}
SASSERT(m().get_sort(old_q) == m().get_sort(result));
return true;
}
@ -784,8 +787,8 @@ void th_rewriter::operator()(expr * t, expr_ref & result, proof_ref & result_pr)
m_imp->operator()(t, result, result_pr);
}
void th_rewriter::operator()(expr * n, unsigned num_bindings, expr * const * bindings, expr_ref & result) {
m_imp->operator()(n, num_bindings, bindings, result);
expr_ref th_rewriter::operator()(expr * n, unsigned num_bindings, expr * const * bindings) {
return m_imp->operator()(n, num_bindings, bindings);
}
void th_rewriter::set_substitution(expr_substitution * s) {

View file

@ -45,7 +45,7 @@ public:
void operator()(expr_ref& term);
void operator()(expr * t, expr_ref & result);
void operator()(expr * t, expr_ref & result, proof_ref & result_pr);
void operator()(expr * n, unsigned num_bindings, expr * const * bindings, expr_ref & result);
expr_ref operator()(expr * n, unsigned num_bindings, expr * const * bindings);
expr_ref mk_app(func_decl* f, unsigned num_args, expr* const* args);

View file

@ -23,10 +23,11 @@ Notes:
#include "ast/well_sorted.h"
#include "ast/for_each_expr.h"
void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, expr_ref & result) {
expr_ref var_subst::operator()(expr * n, unsigned num_args, expr * const * args) {
expr_ref result(m_reducer.m());
if (is_ground(n)) {
result = n;
return;
return result;
}
SASSERT(is_well_sorted(result.m(), n));
m_reducer.reset();
@ -41,6 +42,7 @@ void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, exp
for (unsigned i = 0; i < num_args; i++) tout << mk_ismt2_pp(args[i], m_reducer.m()) << "\n";
tout << "\n------>\n";
tout << mk_ismt2_pp(result, m_reducer.m()) << "\n";);
return result;
}
unused_vars_eliminator::unused_vars_eliminator(ast_manager & m, params_ref const & params) :
@ -49,16 +51,22 @@ unused_vars_eliminator::unused_vars_eliminator(ast_manager & m, params_ref const
m_ignore_patterns_on_ground_qbody = m_params.get_bool("ignore_patterns_on_ground_qbody", true);
}
void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
expr_ref unused_vars_eliminator::operator()(quantifier* q) {
expr_ref result(m);
SASSERT(is_well_sorted(m, q));
TRACE("elim_unused_vars", tout << expr_ref(q, m) << "\n";);
if (is_lambda(q)) {
result = q;
return result;
}
if (m_ignore_patterns_on_ground_qbody && is_ground(q->get_expr())) {
// Ignore patterns if the body is a ground formula.
result = q->get_expr();
return;
return result;
}
if (!q->may_have_unused_vars()) {
result = q;
return;
return result;
}
m_used.reset();
m_used.process(q->get_expr());
@ -73,7 +81,7 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
if (m_used.uses_all_vars(num_decls)) {
q->set_no_unused_vars();
result = q;
return;
return result;
}
ptr_buffer<sort> used_decl_sorts;
@ -120,11 +128,11 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
expr_ref new_expr(m);
m_subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr(), new_expr);
new_expr = m_subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr());
if (num_removed == num_decls) {
result = new_expr;
return;
return result;
}
expr_ref tmp(m);
@ -132,15 +140,15 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
expr_ref_buffer new_no_patterns(m);
for (unsigned i = 0; i < num_patterns; i++) {
m_subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
tmp = m_subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr());
new_patterns.push_back(tmp);
}
for (unsigned i = 0; i < num_no_patterns; i++) {
m_subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
tmp = m_subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr());
new_no_patterns.push_back(tmp);
}
result = m.mk_quantifier(q->is_forall(),
result = m.mk_quantifier(q->get_kind(),
used_decl_sorts.size(),
used_decl_sorts.c_ptr(),
used_decl_names.c_ptr(),
@ -154,24 +162,28 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
new_no_patterns.c_ptr());
to_quantifier(result)->set_no_unused_vars();
SASSERT(is_well_sorted(m, result));
return result;
}
void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & result) {
expr_ref elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params) {
unused_vars_eliminator el(m, params);
el(q, result);
expr_ref result = el(q);
TRACE("elim_unused_vars", tout << expr_ref(q, m) << " -> " << result << "\n";);
return result;
}
void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref & result) {
expr_ref instantiate(ast_manager & m, quantifier * q, expr * const * exprs) {
var_subst subst(m);
expr_ref new_expr(m);
subst(q->get_expr(), q->get_num_decls(), exprs, new_expr);
TRACE("var_subst", tout << mk_pp(q, m) << "\n" << mk_pp(new_expr, m) << "\n";);
expr_ref new_expr(m), result(m);
new_expr = subst(q->get_expr(), q->get_num_decls(), exprs);
TRACE("var_subst", tout << mk_pp(q, m) << "\n" << new_expr << "\n";);
inv_var_shifter shift(m);
shift(new_expr, q->get_num_decls(), result);
SASSERT(is_well_sorted(m, result));
TRACE("instantiate_bug", tout << mk_ismt2_pp(q, m) << "\nusing\n";
for (unsigned i = 0; i < q->get_num_decls(); i++) tout << mk_ismt2_pp(exprs[i], m) << "\n";
tout << "\n----->\n" << mk_ismt2_pp(result, m) << "\n";);
return result;
}
static void get_free_vars_offset(expr_sparse_mark& mark, ptr_vector<expr>& todo, unsigned offset, expr* e, ptr_vector<sort>& sorts) {

View file

@ -48,7 +48,7 @@ public:
Otherwise, (VAR 0) is stored in the first position, (VAR 1) in the second, and so on.
*/
void operator()(expr * n, unsigned num_args, expr * const * args, expr_ref & result);
expr_ref operator()(expr * n, unsigned num_args, expr * const * args);
void reset() { m_reducer.reset(); }
};
@ -63,10 +63,10 @@ class unused_vars_eliminator {
bool m_ignore_patterns_on_ground_qbody;
public:
unused_vars_eliminator(ast_manager & m, params_ref const & params);
void operator()(quantifier* q, expr_ref& r);
expr_ref operator()(quantifier* q);
};
void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & r);
expr_ref elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params);
/**
\brief Instantiate quantifier q using the given exprs.
@ -77,7 +77,7 @@ void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params
...
(VAR (q->get_num_decls() - 1)) is stored in the first position of the array.
*/
void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref & result);
expr_ref instantiate(ast_manager & m, quantifier * q, expr * const * exprs);
/**
\brief Enumerate set of free variables in expression.