3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-14 12:58:44 +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, symbol::null, symbol::null,
1, patterns); 1, patterns);
TRACE("mk_definition_bug", tout << "before elim_unused_vars:\n" << mk_ismt2_pp(q, m_manager) << "\n";); 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";); 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 // Eliminate variables that have become unused
if (reduced && is_forall(r)) { if (reduced && is_forall(r)) {
quantifier * q = to_quantifier(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()) { if (m_manager.proofs_enabled()) {
proof * p1 = m_manager.mk_elim_unused_vars(q, r); proof * p1 = m_manager.mk_elim_unused_vars(q, r);
pr = m_manager.mk_transitivity(pr, p1); 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."), ("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."), ("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."), ("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_cache_all;
bool m_push_ite_arith; bool m_push_ite_arith;
bool m_push_ite_bv; bool m_push_ite_bv;
bool m_ignore_patterns_on_ground_qbody;
// substitution support // substitution support
expr_dependency_ref m_used_dependencies; // set of dependencies of used substitutions 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_cache_all = p.cache_all();
m_push_ite_arith = p.push_ite_arith(); m_push_ite_arith = p.push_ite_arith();
m_push_ite_bv = p.push_ite_bv(); 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) { 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)); 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";); 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";); 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) { void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
SASSERT(is_well_sorted(m, q)); SASSERT(is_well_sorted(m, q));
if (is_ground(q->get_expr())) { if (m_ignore_patterns_on_ground_qbody && is_ground(q->get_expr())) {
// ignore patterns if the body is a ground formula. // Ignore patterns if the body is a ground formula.
result = q->get_expr(); result = q->get_expr();
return; return;
} }
@ -146,8 +152,8 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
SASSERT(is_well_sorted(m, result)); SASSERT(is_well_sorted(m, result));
} }
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) { void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & result) {
unused_vars_eliminator el(m); unused_vars_eliminator el(m, params);
el(q, result); el(q, result);
} }

View file

@ -21,6 +21,7 @@ Notes:
#include"rewriter.h" #include"rewriter.h"
#include"used_vars.h" #include"used_vars.h"
#include"params.h"
/** /**
\brief Alias for var_shifter class. \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. \brief Eliminate the unused variables from \c q. Store the result in \c r.
*/ */
class unused_vars_eliminator { class unused_vars_eliminator {
ast_manager& m; ast_manager & m;
var_subst m_subst; var_subst m_subst;
used_vars m_used; used_vars m_used;
params_ref m_params;
bool m_ignore_patterns_on_ground_qbody;
public: 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 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. \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); quantifier_ref tmp_q(m_manager);
tmp_q = m_manager.update_quantifier(q, not_arg); tmp_q = m_manager.update_quantifier(q, not_arg);
expr_ref new_q(m_manager); 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); new_args.push_back(new_q);
} }
expr_ref result(m_manager); 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); quantifier_ref new_q(m_manager);
new_q = m_manager.update_quantifier(q, new_body); 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";); 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); expr_ref r(m);
elim_unused_vars(m, q1, r); elim_unused_vars(m, q1, params_ref(), r);
proof * pr = 0; proof * pr = 0;
if (m.fine_grain_proofs()) { if (m.fine_grain_proofs()) {

View file

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

View file

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

View file

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

View file

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

View file

@ -520,7 +520,7 @@ namespace tb {
m_matcher(m), m_matcher(m),
m_refs(m), m_refs(m),
m_subst(m), m_subst(m),
m_qe(m), m_qe(m, params_ref()),
m_rw(m), m_rw(m),
m_solver(m, m_fparams) {} 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) { 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(); reset();
SASSERT(tgt.get_predicate(idx)->get_decl() == src.get_decl()); SASSERT(tgt.get_predicate(idx)->get_decl() == src.get_decl());
unsigned var_cnt = std::max(tgt.get_num_vars(), src.get_num_vars()); 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_vector m_subst_map;
expr_ref_buffer m_new_args; expr_ref_buffer m_new_args;
th_rewriter m_rewriter; th_rewriter m_rewriter;
params_ref m_params;
void der_sort_vars(ptr_vector<var> & vars, ptr_vector<expr> & definitions, unsigned_vector & order) { void der_sort_vars(ptr_vector<var> & vars, ptr_vector<expr> & definitions, unsigned_vector & order) {
order.reset(); order.reset();
@ -563,7 +564,8 @@ namespace eq {
void elim_unused_vars(expr_ref& r, proof_ref &pr) { void elim_unused_vars(expr_ref& r, proof_ref &pr) {
if (is_quantifier(r)) { if (is_quantifier(r)) {
quantifier * q = to_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()) { if (m.proofs_enabled()) {
proof * p1 = m.mk_elim_unused_vars(q, r); proof * p1 = m.mk_elim_unused_vars(q, r);
pr = m.mk_transitivity(pr, p1); pr = m.mk_transitivity(pr, p1);
@ -744,7 +746,7 @@ namespace eq {
} }
public: public:
der(ast_manager & m): der(ast_manager & m, params_ref const & p):
m(m), m(m),
a(m), a(m),
dt(m), dt(m),
@ -753,7 +755,8 @@ namespace eq {
m_new_exprs(m), m_new_exprs(m),
m_subst_map(m), m_subst_map(m),
m_new_args(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;} void set_is_variable_proc(is_variable_proc& proc) { m_is_variable = &proc;}
@ -2346,9 +2349,9 @@ private:
} }
public: public:
impl(ast_manager& m): impl(ast_manager & m, params_ref const & p):
m(m), m(m),
m_der(m), m_der(m, p),
m_fm(m), m_fm(m),
m_array_der(m), m_array_der(m),
m_elim_star(*this), m_elim_star(*this),
@ -2438,8 +2441,8 @@ public:
}; };
qe_lite::qe_lite(ast_manager& m) { qe_lite::qe_lite(ast_manager & m, params_ref const & p) {
m_impl = alloc(impl, m); m_impl = alloc(impl, m, p);
} }
qe_lite::~qe_lite() { qe_lite::~qe_lite() {
@ -2469,9 +2472,9 @@ class qe_lite_tactic : public tactic {
ast_manager& m; ast_manager& m;
qe_lite m_qe; qe_lite m_qe;
imp(ast_manager& m, params_ref const& p): imp(ast_manager& m, params_ref const & p):
m(m), m(m),
m_qe(m) m_qe(m, p)
{} {}
void checkpoint() { void checkpoint() {

View file

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

View file

@ -34,6 +34,7 @@ class elim_small_bv_tactic : public tactic {
struct rw_cfg : public default_rewriter_cfg { struct rw_cfg : public default_rewriter_cfg {
ast_manager & m; ast_manager & m;
params_ref m_params;
bv_util m_util; bv_util m_util;
simplifier m_simp; simplifier m_simp;
ref<filter_model_converter> m_mc; 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) : rw_cfg(ast_manager & _m, params_ref const & p) :
m(_m), m(_m),
m_params(p),
m_util(_m), m_util(_m),
m_simp(_m), m_simp(_m),
m_bindings(_m), m_bindings(_m),
@ -178,7 +180,7 @@ class elim_small_bv_tactic : public tactic {
quantifier_ref new_q(m); quantifier_ref new_q(m);
new_q = m.update_quantifier(q, body); new_q = m.update_quantifier(q, body);
unused_vars_eliminator el(m); unused_vars_eliminator el(m, m_params);
el(new_q, result); el(new_q, result);
TRACE("elim_small_bv", tout << "elimination result: " << mk_ismt2_pp(result, m) << std::endl; ); 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) { 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_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
m_max_steps = p.get_uint("max_steps", UINT_MAX); m_max_steps = p.get_uint("max_steps", UINT_MAX);
m_max_bits = p.get_uint("max_bits", 4); 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); quantifier_ref tmp_q(m);
tmp_q = m.update_quantifier(old_q, not_arg); tmp_q = m.update_quantifier(old_q, not_arg);
expr_ref new_q(m); 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); new_args.push_back(new_q);
} }
result = m.mk_and(new_args.size(), new_args.c_ptr()); 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); quantifier_ref tmp_q(m);
tmp_q = m.update_quantifier(old_q, arg); tmp_q = m.update_quantifier(old_q, arg);
expr_ref new_q(m); 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); new_args.push_back(new_q);
} }
result = m.mk_and(new_args.size(), new_args.c_ptr()); 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); q = m_manager.update_quantifier(to_quantifier(actual), new_body);
m_new_exprs.push_back(q); m_new_exprs.push_back(q);
expr_ref new_q(m_manager); 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); m_new_exprs.push_back(new_q);
rewrite_cache(e, new_q, true); rewrite_cache(e, new_q, true);
m_rewrite_todo.pop_back(); m_rewrite_todo.pop_back();