3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-13 04:28:17 +00:00

Added rewriter.ignore_patterns_on_ground_qbody option to disable simplification of quantifiers that have their universals appear only in patterns, but otherwise have a ground body.

This commit is contained in:
Christoph M. Wintersteiger 2017-04-07 21:19:20 +01:00
parent 9a757ffffe
commit 27a1758857
19 changed files with 795 additions and 776 deletions

View file

@ -162,7 +162,7 @@ void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbo
1, symbol::null, symbol::null,
1, patterns);
TRACE("mk_definition_bug", tout << "before elim_unused_vars:\n" << mk_ismt2_pp(q, m_manager) << "\n";);
elim_unused_vars(m_manager, q, result);
elim_unused_vars(m_manager, q, params_ref(), result);
TRACE("mk_definition_bug", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m_manager) << "\n";);
}
}

View file

@ -138,7 +138,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, r);
elim_unused_vars(m_manager, q, params_ref(), r);
if (m_manager.proofs_enabled()) {
proof * p1 = m_manager.mk_elim_unused_vars(q, r);
pr = m_manager.mk_transitivity(pr, p1);

View file

@ -8,5 +8,6 @@ def_module_params('rewriter',
("push_ite_bv", BOOL, False, "push if-then-else over bit-vector terms."),
("pull_cheap_ite", BOOL, False, "pull if-then-else terms when cheap."),
("bv_ineq_consistency_test_max", UINT, 0, "max size of conjunctions on which to perform consistency test based on inequalities on bitvectors."),
("cache_all", BOOL, False, "cache all intermediate results.")))
("cache_all", BOOL, False, "cache all intermediate results."),
("ignore_patterns_on_ground_qbody", BOOL, True, "ignores patterns on quantifiers that don't mention their bound variables.")))

View file

@ -54,6 +54,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
bool m_cache_all;
bool m_push_ite_arith;
bool m_push_ite_bv;
bool m_ignore_patterns_on_ground_qbody;
// substitution support
expr_dependency_ref m_used_dependencies; // set of dependencies of used substitutions
@ -70,6 +71,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
m_cache_all = p.cache_all();
m_push_ite_arith = p.push_ite_arith();
m_push_ite_bv = p.push_ite_bv();
m_ignore_patterns_on_ground_qbody = p.ignore_patterns_on_ground_qbody();
}
void updt_params(params_ref const & p) {
@ -649,7 +651,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
SASSERT(is_well_sorted(m(), q1));
}
elim_unused_vars(m(), q1, result);
elim_unused_vars(m(), q1, params_ref(), result);
TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m()) << "\n";);

View file

@ -39,10 +39,16 @@ void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, exp
tout << mk_ismt2_pp(result, m_reducer.m()) << "\n";);
}
unused_vars_eliminator::unused_vars_eliminator(ast_manager & m, params_ref const & params) :
m(m), m_subst(m), m_params(params)
{
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) {
SASSERT(is_well_sorted(m, q));
if (is_ground(q->get_expr())) {
// ignore patterns if the body is a ground formula.
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;
}
@ -146,8 +152,8 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
SASSERT(is_well_sorted(m, result));
}
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
unused_vars_eliminator el(m);
void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & result) {
unused_vars_eliminator el(m, params);
el(q, result);
}

View file

@ -21,6 +21,7 @@ Notes:
#include"rewriter.h"
#include"used_vars.h"
#include"params.h"
/**
\brief Alias for var_shifter class.
@ -55,15 +56,17 @@ public:
\brief Eliminate the unused variables from \c q. Store the result in \c r.
*/
class unused_vars_eliminator {
ast_manager& m;
var_subst m_subst;
used_vars m_used;
ast_manager & m;
var_subst m_subst;
used_vars m_used;
params_ref m_params;
bool m_ignore_patterns_on_ground_qbody;
public:
unused_vars_eliminator(ast_manager& m): m(m), m_subst(m) {}
unused_vars_eliminator(ast_manager & m, params_ref const & params);
void operator()(quantifier* q, expr_ref& r);
};
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & r);
void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & r);
/**
\brief Instantiate quantifier q using the given exprs.

View file

@ -126,7 +126,7 @@ void distribute_forall::reduce1_quantifier(quantifier * q) {
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, new_q);
elim_unused_vars(m_manager, tmp_q, params_ref(), new_q);
new_args.push_back(new_q);
}
expr_ref result(m_manager);

View file

@ -188,7 +188,7 @@ void elim_bounds::operator()(quantifier * q, expr_ref & r) {
}
quantifier_ref new_q(m_manager);
new_q = m_manager.update_quantifier(q, new_body);
elim_unused_vars(m_manager, new_q, r);
elim_unused_vars(m_manager, new_q, params_ref(), r);
TRACE("elim_bounds", tout << mk_pp(q, m_manager) << "\n" << mk_pp(r, m_manager) << "\n";);
}

View file

@ -852,7 +852,7 @@ void simplifier::reduce1_quantifier(quantifier * q) {
}
expr_ref r(m);
elim_unused_vars(m, q1, r);
elim_unused_vars(m, q1, params_ref(), r);
proof * pr = 0;
if (m.fine_grain_proofs()) {

View file

@ -29,6 +29,7 @@ Notes:
#include"bound_manager.h"
#include"used_vars.h"
#include"var_subst.h"
#include"gparams.h"
#ifndef _EXTERNAL_RELEASE
@ -271,7 +272,7 @@ UNARY_CMD(elim_unused_vars_cmd, "dbg-elim-unused-vars", "<expr>", "eliminate unu
return;
}
expr_ref r(ctx.m());
elim_unused_vars(ctx.m(), to_quantifier(arg), r);
elim_unused_vars(ctx.m(), to_quantifier(arg), gparams::get(), r);
SASSERT(!is_quantifier(r) || !to_quantifier(r)->may_have_unused_vars());
ctx.display(ctx.regular_stream(), r);
ctx.regular_stream() << std::endl;

View file

@ -348,7 +348,7 @@ namespace Duality {
expr expr::qe_lite() const {
::qe_lite qe(m());
::qe_lite qe(m(), params_ref());
expr_ref result(to_expr(raw()),m());
proof_ref pf(m());
qe(result,pf);
@ -356,7 +356,7 @@ namespace Duality {
}
expr expr::qe_lite(const std::set<int> &idxs, bool index_of_bound) const {
::qe_lite qe(m());
::qe_lite qe(m(), params_ref());
expr_ref result(to_expr(raw()),m());
proof_ref pf(m());
uint_set uis;

View file

@ -54,7 +54,7 @@ namespace datalog {
m_head(m),
m_args(m),
m_hnf(m),
m_qe(m),
m_qe(m, params_ref()),
m_rwr(m),
m_ufproc(m) {}

View file

@ -2241,7 +2241,7 @@ namespace pdr {
vars.append(aux_vars.size(), aux_vars.c_ptr());
scoped_ptr<expr_replacer> rep;
qe_lite qe(m);
qe_lite qe(m, m_params.p);
expr_ref phi1 = m_pm.mk_and(Phi);
qe(vars, phi1);
TRACE("pdr", tout << "Eliminated\n" << mk_pp(phi1, m) << "\n";);

View file

@ -520,7 +520,7 @@ namespace tb {
m_matcher(m),
m_refs(m),
m_subst(m),
m_qe(m),
m_qe(m, params_ref()),
m_rw(m),
m_solver(m, m_fparams) {}
@ -1067,7 +1067,7 @@ namespace tb {
}
bool unify(clause const& tgt, unsigned idx, clause const& src, bool compute_subst, ref<clause>& result) {
qe_lite qe(m);
qe_lite qe(m, params_ref());
reset();
SASSERT(tgt.get_predicate(idx)->get_decl() == src.get_decl());
unsigned var_cnt = std::max(tgt.get_num_vars(), src.get_num_vars());

View file

@ -91,6 +91,7 @@ namespace eq {
expr_ref_vector m_subst_map;
expr_ref_buffer m_new_args;
th_rewriter m_rewriter;
params_ref m_params;
void der_sort_vars(ptr_vector<var> & vars, ptr_vector<expr> & definitions, unsigned_vector & order) {
order.reset();
@ -563,7 +564,8 @@ namespace eq {
void elim_unused_vars(expr_ref& r, proof_ref &pr) {
if (is_quantifier(r)) {
quantifier * q = to_quantifier(r);
::elim_unused_vars(m, q, r);
::elim_unused_vars(m, q, m_params, r);
if (m.proofs_enabled()) {
proof * p1 = m.mk_elim_unused_vars(q, r);
pr = m.mk_transitivity(pr, p1);
@ -744,7 +746,7 @@ namespace eq {
}
public:
der(ast_manager & m):
der(ast_manager & m, params_ref const & p):
m(m),
a(m),
dt(m),
@ -753,7 +755,8 @@ namespace eq {
m_new_exprs(m),
m_subst_map(m),
m_new_args(m),
m_rewriter(m) {}
m_rewriter(m),
m_params(p) {}
void set_is_variable_proc(is_variable_proc& proc) { m_is_variable = &proc;}
@ -2346,9 +2349,9 @@ private:
}
public:
impl(ast_manager& m):
impl(ast_manager & m, params_ref const & p):
m(m),
m_der(m),
m_der(m, p),
m_fm(m),
m_array_der(m),
m_elim_star(*this),
@ -2438,8 +2441,8 @@ public:
};
qe_lite::qe_lite(ast_manager& m) {
m_impl = alloc(impl, m);
qe_lite::qe_lite(ast_manager & m, params_ref const & p) {
m_impl = alloc(impl, m, p);
}
qe_lite::~qe_lite() {
@ -2469,9 +2472,9 @@ class qe_lite_tactic : public tactic {
ast_manager& m;
qe_lite m_qe;
imp(ast_manager& m, params_ref const& p):
imp(ast_manager& m, params_ref const & p):
m(m),
m_qe(m)
m_qe(m, p)
{}
void checkpoint() {

View file

@ -31,7 +31,7 @@ class qe_lite {
class impl;
impl * m_impl;
public:
qe_lite(ast_manager& m);
qe_lite(ast_manager & m, params_ref const & p);
~qe_lite();

View file

@ -34,6 +34,7 @@ class elim_small_bv_tactic : public tactic {
struct rw_cfg : public default_rewriter_cfg {
ast_manager & m;
params_ref m_params;
bv_util m_util;
simplifier m_simp;
ref<filter_model_converter> m_mc;
@ -47,6 +48,7 @@ class elim_small_bv_tactic : public tactic {
rw_cfg(ast_manager & _m, params_ref const & p) :
m(_m),
m_params(p),
m_util(_m),
m_simp(_m),
m_bindings(_m),
@ -178,7 +180,7 @@ class elim_small_bv_tactic : public tactic {
quantifier_ref new_q(m);
new_q = m.update_quantifier(q, body);
unused_vars_eliminator el(m);
unused_vars_eliminator el(m, m_params);
el(new_q, result);
TRACE("elim_small_bv", tout << "elimination result: " << mk_ismt2_pp(result, m) << std::endl; );
@ -203,6 +205,7 @@ class elim_small_bv_tactic : public tactic {
}
void updt_params(params_ref const & p) {
m_params = p;
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
m_max_steps = p.get_uint("max_steps", UINT_MAX);
m_max_bits = p.get_uint("max_bits", 4);

View file

@ -50,7 +50,7 @@ class distribute_forall_tactic : public tactic {
quantifier_ref tmp_q(m);
tmp_q = m.update_quantifier(old_q, not_arg);
expr_ref new_q(m);
elim_unused_vars(m, tmp_q, new_q);
elim_unused_vars(m, tmp_q, params_ref(), new_q);
new_args.push_back(new_q);
}
result = m.mk_and(new_args.size(), new_args.c_ptr());
@ -70,7 +70,7 @@ class distribute_forall_tactic : public tactic {
quantifier_ref tmp_q(m);
tmp_q = m.update_quantifier(old_q, arg);
expr_ref new_q(m);
elim_unused_vars(m, tmp_q, new_q);
elim_unused_vars(m, tmp_q, params_ref(), new_q);
new_args.push_back(new_q);
}
result = m.mk_and(new_args.size(), new_args.c_ptr());

View file

@ -417,7 +417,7 @@ expr * ufbv_rewriter::rewrite(expr * n) {
q = m_manager.update_quantifier(to_quantifier(actual), new_body);
m_new_exprs.push_back(q);
expr_ref new_q(m_manager);
elim_unused_vars(m_manager, q, new_q);
elim_unused_vars(m_manager, q, params_ref(), new_q);
m_new_exprs.push_back(new_q);
rewrite_cache(e, new_q, true);
m_rewrite_todo.pop_back();