mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +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:
parent
9a757ffffe
commit
27a1758857
19 changed files with 795 additions and 776 deletions
|
@ -28,7 +28,7 @@ struct defined_names::impl {
|
|||
typedef obj_map<expr, proof *> expr2proof;
|
||||
ast_manager & m_manager;
|
||||
symbol m_z3name;
|
||||
|
||||
|
||||
/**
|
||||
\brief Mapping from expressions to their names. A name is an application.
|
||||
If the expression does not have free variables, then the name is just a constant.
|
||||
|
@ -38,25 +38,25 @@ struct defined_names::impl {
|
|||
\brief Mapping from expressions to the apply-def proof.
|
||||
That is, for each expression e, m_expr2proof[e] is the
|
||||
proof e and m_expr2name[2] are observ. equivalent.
|
||||
|
||||
|
||||
This mapping is not used if proof production is disabled.
|
||||
*/
|
||||
expr2proof m_expr2proof;
|
||||
|
||||
|
||||
/**
|
||||
\brief Domain of m_expr2name. It is used to keep the expressions
|
||||
alive and for backtracking
|
||||
*/
|
||||
expr_ref_vector m_exprs;
|
||||
expr_ref_vector m_exprs;
|
||||
expr_ref_vector m_names; //!< Range of m_expr2name. It is used to keep the names alive.
|
||||
proof_ref_vector m_apply_proofs; //!< Range of m_expr2proof. It is used to keep the def-intro proofs alive.
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned_vector m_lims; //!< Backtracking support.
|
||||
|
||||
|
||||
impl(ast_manager & m, char const * prefix);
|
||||
virtual ~impl();
|
||||
|
||||
|
||||
app * gen_name(expr * e, sort_ref_buffer & var_sorts, buffer<symbol> & var_names);
|
||||
void cache_new_name(expr * e, app * name);
|
||||
void cache_new_name_intro_proof(expr * e, proof * pr);
|
||||
|
@ -106,7 +106,7 @@ app * defined_names::impl::gen_name(expr * e, sort_ref_buffer & var_sorts, buffe
|
|||
for (unsigned i = 0; i < num_vars; i++) {
|
||||
sort * s = uv.get(i);
|
||||
if (s) {
|
||||
domain.push_back(s);
|
||||
domain.push_back(s);
|
||||
new_args.push_back(m_manager.mk_var(i, s));
|
||||
var_sorts.push_back(s);
|
||||
}
|
||||
|
@ -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";);
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ bool defined_names::impl::mk_name(expr * e, expr_ref & new_def, proof_ref & new_
|
|||
|
||||
app * n_ptr;
|
||||
if (m_expr2name.find(e, n_ptr)) {
|
||||
TRACE("mk_definition_bug", tout << "name for expression is already cached..., returning false...\n";);
|
||||
TRACE("mk_definition_bug", tout << "name for expression is already cached..., returning false...\n";);
|
||||
n = n_ptr;
|
||||
if (m_manager.proofs_enabled()) {
|
||||
proof * pr_ptr = 0;
|
||||
|
@ -220,19 +220,19 @@ bool defined_names::impl::mk_name(expr * e, expr_ref & new_def, proof_ref & new_
|
|||
else {
|
||||
sort_ref_buffer var_sorts(m_manager);
|
||||
buffer<symbol> var_names;
|
||||
|
||||
|
||||
n = gen_name(e, var_sorts, var_names);
|
||||
cache_new_name(e, n);
|
||||
|
||||
|
||||
TRACE("mk_definition_bug", tout << "name: " << mk_ismt2_pp(n, m_manager) << "\n";);
|
||||
// variables are in reverse order in quantifiers
|
||||
std::reverse(var_sorts.c_ptr(), var_sorts.c_ptr() + var_sorts.size());
|
||||
std::reverse(var_names.c_ptr(), var_names.c_ptr() + var_names.size());
|
||||
|
||||
|
||||
mk_definition(e, n, var_sorts, var_names, new_def);
|
||||
|
||||
|
||||
TRACE("mk_definition_bug", tout << "new_def:\n" << mk_ismt2_pp(new_def, m_manager) << "\n";);
|
||||
|
||||
|
||||
if (m_manager.proofs_enabled()) {
|
||||
new_def_pr = m_manager.mk_def_intro(new_def);
|
||||
pr = m_manager.mk_apply_def(e, n, new_def_pr);
|
||||
|
@ -311,11 +311,11 @@ void defined_names::reset() {
|
|||
m_pos_impl->reset();
|
||||
}
|
||||
|
||||
unsigned defined_names::get_num_names() const {
|
||||
unsigned defined_names::get_num_names() const {
|
||||
return m_impl->get_num_names() + m_pos_impl->get_num_names();
|
||||
}
|
||||
|
||||
func_decl * defined_names::get_name_decl(unsigned i) const {
|
||||
func_decl * defined_names::get_name_decl(unsigned i) const {
|
||||
SASSERT(i < get_num_names());
|
||||
unsigned n1 = m_impl->get_num_names();
|
||||
return i < n1 ? m_impl->get_name_decl(i) : m_pos_impl->get_name_decl(i - n1);
|
||||
|
|
|
@ -36,7 +36,7 @@ static bool is_neg_var(ast_manager & m, expr * e, unsigned num_decls) {
|
|||
|
||||
/**
|
||||
\brief Return true if \c e is of the form (not (= VAR t)) or (not (iff VAR t)) or (iff VAR t) or (iff (not VAR) t) or (VAR IDX) or (not (VAR IDX)).
|
||||
The last case can be viewed
|
||||
The last case can be viewed
|
||||
*/
|
||||
bool der::is_var_diseq(expr * e, unsigned num_decls, var * & v, expr_ref & t) {
|
||||
// (not (= VAR t)) and (not (iff VAR t)) cases
|
||||
|
@ -49,7 +49,7 @@ bool der::is_var_diseq(expr * e, unsigned num_decls, var * & v, expr_ref & t) {
|
|||
return false;
|
||||
if (!is_var(lhs, num_decls))
|
||||
std::swap(lhs, rhs);
|
||||
SASSERT(is_var(lhs, num_decls));
|
||||
SASSERT(is_var(lhs, num_decls));
|
||||
// Remark: Occurs check is not necessary here... the top-sort procedure will check for cycles...
|
||||
// if (occurs(lhs, rhs)) {
|
||||
// return false;
|
||||
|
@ -67,7 +67,7 @@ bool der::is_var_diseq(expr * e, unsigned num_decls, var * & v, expr_ref & t) {
|
|||
if (is_var(lhs, num_decls) || is_var(rhs, num_decls)) {
|
||||
if (!is_var(lhs, num_decls))
|
||||
std::swap(lhs, rhs);
|
||||
SASSERT(is_var(lhs, num_decls));
|
||||
SASSERT(is_var(lhs, num_decls));
|
||||
// Remark: Occurs check is not necessary here... the top-sort procedure will check for cycles...
|
||||
// if (occurs(lhs, rhs)) {
|
||||
// return false;
|
||||
|
@ -83,11 +83,11 @@ bool der::is_var_diseq(expr * e, unsigned num_decls, var * & v, expr_ref & t) {
|
|||
if (!is_neg_var(m_manager, lhs, num_decls))
|
||||
std::swap(lhs, rhs);
|
||||
SASSERT(is_neg_var(m_manager, lhs, num_decls));
|
||||
expr * lhs_var = to_app(lhs)->get_arg(0);
|
||||
expr * lhs_var = to_app(lhs)->get_arg(0);
|
||||
// Remark: Occurs check is not necessary here... the top-sort procedure will check for cycles...
|
||||
// if (occurs(lhs_var, rhs)) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
v = to_var(lhs_var);
|
||||
t = rhs;
|
||||
TRACE("der", tout << mk_pp(e, m_manager) << "\n";);
|
||||
|
@ -134,11 +134,11 @@ void der::operator()(quantifier * q, expr_ref & r, proof_ref & pr) {
|
|||
pr = m_manager.mk_transitivity(pr, curr_pr);
|
||||
}
|
||||
} while (q != r && is_quantifier(r));
|
||||
|
||||
|
||||
// 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);
|
||||
|
@ -153,24 +153,24 @@ void der::reduce1(quantifier * q, expr_ref & r, proof_ref & pr) {
|
|||
r = q;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
expr * e = q->get_expr();
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
var * v = 0;
|
||||
expr_ref t(m_manager);
|
||||
expr_ref t(m_manager);
|
||||
|
||||
if (m_manager.is_or(e)) {
|
||||
unsigned num_args = to_app(e)->get_num_args();
|
||||
unsigned i = 0;
|
||||
unsigned diseq_count = 0;
|
||||
unsigned largest_vinx = 0;
|
||||
|
||||
|
||||
m_map.reset();
|
||||
m_pos2var.reset();
|
||||
m_inx2var.reset();
|
||||
|
||||
|
||||
m_pos2var.reserve(num_args, -1);
|
||||
|
||||
|
||||
// Find all disequalities
|
||||
for (; i < num_args; i++) {
|
||||
if (is_var_diseq(to_app(e)->get_arg(i), num_decls, v, t)) {
|
||||
|
@ -192,7 +192,7 @@ void der::reduce1(quantifier * q, expr_ref & r, proof_ref & pr) {
|
|||
get_elimination_order();
|
||||
SASSERT(m_order.size() <= diseq_count); // some might be missing because of cycles
|
||||
|
||||
if (!m_order.empty()) {
|
||||
if (!m_order.empty()) {
|
||||
create_substitution(largest_vinx + 1);
|
||||
apply_substitution(q, r);
|
||||
}
|
||||
|
@ -202,22 +202,22 @@ void der::reduce1(quantifier * q, expr_ref & r, proof_ref & pr) {
|
|||
r = q;
|
||||
}
|
||||
}
|
||||
// Remark: get_elimination_order/top-sort checks for cycles, but it is not invoked for unit clauses.
|
||||
// Remark: get_elimination_order/top-sort checks for cycles, but it is not invoked for unit clauses.
|
||||
// So, we must perform a occurs check here.
|
||||
else if (is_var_diseq(e, num_decls, v, t) && !occurs(v, t)) {
|
||||
r = m_manager.mk_false();
|
||||
}
|
||||
else
|
||||
else
|
||||
r = q;
|
||||
|
||||
|
||||
if (m_manager.proofs_enabled()) {
|
||||
pr = r == q ? 0 : m_manager.mk_der(q, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void der_sort_vars(ptr_vector<var> & vars, ptr_vector<expr> & definitions, unsigned_vector & order) {
|
||||
order.reset();
|
||||
|
||||
|
||||
// eliminate self loops, and definitions containing quantifiers.
|
||||
bool found = false;
|
||||
for (unsigned i = 0; i < definitions.size(); i++) {
|
||||
|
@ -228,7 +228,7 @@ void der_sort_vars(ptr_vector<var> & vars, ptr_vector<expr> & definitions, unsig
|
|||
else
|
||||
found = true; // found at least one candidate
|
||||
}
|
||||
|
||||
|
||||
if (!found)
|
||||
return;
|
||||
|
||||
|
@ -329,14 +329,14 @@ void der::get_elimination_order() {
|
|||
// der::top_sort ts(m_manager);
|
||||
der_sort_vars(m_inx2var, m_map, m_order);
|
||||
|
||||
TRACE("der",
|
||||
TRACE("der",
|
||||
tout << "Elimination m_order:" << std::endl;
|
||||
for(unsigned i=0; i<m_order.size(); i++)
|
||||
{
|
||||
if (i != 0) tout << ",";
|
||||
tout << m_order[i];
|
||||
}
|
||||
tout << std::endl;
|
||||
tout << std::endl;
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -359,24 +359,24 @@ void der::create_substitution(unsigned sz) {
|
|||
|
||||
void der::apply_substitution(quantifier * q, expr_ref & r) {
|
||||
expr * e = q->get_expr();
|
||||
unsigned num_args=to_app(e)->get_num_args();
|
||||
|
||||
unsigned num_args=to_app(e)->get_num_args();
|
||||
|
||||
// get a new expression
|
||||
m_new_args.reset();
|
||||
for(unsigned i = 0; i < num_args; i++) {
|
||||
int x = m_pos2var[i];
|
||||
if (x != -1 && m_map[x] != 0)
|
||||
if (x != -1 && m_map[x] != 0)
|
||||
continue; // this is a disequality with definition (vanishes)
|
||||
|
||||
|
||||
m_new_args.push_back(to_app(e)->get_arg(i));
|
||||
}
|
||||
|
||||
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);
|
||||
expr_ref new_e(m_manager);
|
||||
m_subst(t, m_subst_map.size(), m_subst_map.c_ptr(), new_e);
|
||||
|
||||
|
||||
// don't forget to update the quantifier patterns
|
||||
expr_ref_buffer new_patterns(m_manager);
|
||||
expr_ref_buffer new_no_patterns(m_manager);
|
||||
|
@ -392,7 +392,7 @@ void der::apply_substitution(quantifier * q, expr_ref & r) {
|
|||
new_no_patterns.push_back(new_nopat);
|
||||
}
|
||||
|
||||
r = m_manager.update_quantifier(q, new_patterns.size(), new_patterns.c_ptr(),
|
||||
r = m_manager.update_quantifier(q, new_patterns.size(), new_patterns.c_ptr(),
|
||||
new_no_patterns.size(), new_no_patterns.c_ptr(), new_e);
|
||||
}
|
||||
|
||||
|
@ -404,9 +404,9 @@ struct der_rewriter_cfg : public default_rewriter_cfg {
|
|||
|
||||
ast_manager & m() const { return m_der.m(); }
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
|
|
|
@ -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.")))
|
||||
|
||||
|
|
|
@ -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,8 +71,9 @@ 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) {
|
||||
m_b_rw.updt_params(p);
|
||||
m_a_rw.updt_params(p);
|
||||
|
@ -82,7 +84,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
updt_local_params(p);
|
||||
}
|
||||
|
||||
bool flat_assoc(func_decl * f) const {
|
||||
bool flat_assoc(func_decl * f) const {
|
||||
if (!m_flat) return false;
|
||||
family_id fid = f->get_family_id();
|
||||
if (fid == null_family_id)
|
||||
|
@ -98,10 +100,10 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
|
||||
bool rewrite_patterns() const { return false; }
|
||||
|
||||
|
||||
bool cache_all_results() const { return m_cache_all; }
|
||||
|
||||
bool max_steps_exceeded(unsigned num_steps) const {
|
||||
bool max_steps_exceeded(unsigned num_steps) const {
|
||||
cooperate("simplifier");
|
||||
if (memory::get_allocation_size() > m_max_memory)
|
||||
throw rewriter_exception(Z3_MAX_MEMORY_MSG);
|
||||
|
@ -179,13 +181,13 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
st = m_ar_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_seq_rw.get_fid())
|
||||
st = m_seq_rw.mk_eq_core(args[0], args[1], result);
|
||||
|
||||
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
if (k == OP_EQ || k == OP_IFF) {
|
||||
SASSERT(num == 2);
|
||||
st = apply_tamagotchi(args[0], args[1], result);
|
||||
st = apply_tamagotchi(args[0], args[1], result);
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
|
@ -239,13 +241,13 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
else {
|
||||
if (SWAP) {
|
||||
result = m().mk_ite(ite->get_arg(0),
|
||||
result = m().mk_ite(ite->get_arg(0),
|
||||
m().mk_app(p, value, ite->get_arg(1)),
|
||||
m().mk_app(p, value, ite->get_arg(2)));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
else {
|
||||
result = m().mk_ite(ite->get_arg(0),
|
||||
result = m().mk_ite(ite->get_arg(0),
|
||||
m().mk_app(p, ite->get_arg(1), value),
|
||||
m().mk_app(p, ite->get_arg(2), value));
|
||||
return BR_REWRITE2;
|
||||
|
@ -257,7 +259,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
// ite-value-tree := (ite c <subtree> <subtree>)
|
||||
// subtree := value
|
||||
// | (ite c <subtree> <subtree>)
|
||||
//
|
||||
//
|
||||
bool is_ite_value_tree(expr * t) {
|
||||
if (!m().is_ite(t))
|
||||
return false;
|
||||
|
@ -281,7 +283,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
br_status pull_ite(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
if (num == 2 && m().is_bool(f->get_range()) && !m().is_bool(args[0])) {
|
||||
if (m().is_ite(args[0])) {
|
||||
|
@ -325,7 +327,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
if (!is_app(t))
|
||||
return false;
|
||||
family_id fid = to_app(t)->get_family_id();
|
||||
return ((fid == m_a_rw.get_fid() && m_push_ite_arith) ||
|
||||
return ((fid == m_a_rw.get_fid() && m_push_ite_arith) ||
|
||||
(fid == m_bv_rw.get_fid() && m_push_ite_bv));
|
||||
}
|
||||
|
||||
|
@ -349,7 +351,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Try to "unify" t1 and t2
|
||||
Examples
|
||||
|
@ -463,7 +465,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
// terms matched...
|
||||
bool is_int = m_a_util.is_int(t1);
|
||||
if (!new_t1)
|
||||
if (!new_t1)
|
||||
new_t1 = m_a_util.mk_numeral(rational(0), is_int);
|
||||
if (!new_t2)
|
||||
new_t2 = m_a_util.mk_numeral(rational(0), is_int);
|
||||
|
@ -476,7 +478,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
args.push_back(arg);
|
||||
}
|
||||
SASSERT(!args.empty());
|
||||
if (args.size() == 1)
|
||||
if (args.size() == 1)
|
||||
c = args[0];
|
||||
else
|
||||
c = m_a_util.mk_add(args.size(), args.c_ptr());
|
||||
|
@ -518,7 +520,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
|
||||
// Apply transformations of the form
|
||||
//
|
||||
// (ite c (+ k1 a) (+ k2 a)) --> (+ (ite c k1 k2) a)
|
||||
// (ite c (+ k1 a) (+ k2 a)) --> (+ (ite c k1 k2) a)
|
||||
// (ite c (* k1 a) (* k2 a)) --> (* (ite c k1 k2) a)
|
||||
//
|
||||
// These transformations are useful for bit-vector problems, since
|
||||
|
@ -536,7 +538,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
if (unify(t, e, f_prime, new_t, new_e, common, first)) {
|
||||
if (first)
|
||||
result = m().mk_app(f_prime, common, m().mk_ite(c, new_t, new_e));
|
||||
else
|
||||
else
|
||||
result = m().mk_app(f_prime, m().mk_ite(c, new_t, new_e), common);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -558,7 +560,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
result_pr = 0;
|
||||
br_status st = reduce_app_core(f, num, args, result);
|
||||
if (st != BR_DONE && st != BR_FAILED) {
|
||||
CTRACE("th_rewriter_step", st != BR_FAILED,
|
||||
CTRACE("th_rewriter_step", st != BR_FAILED,
|
||||
tout << f->get_name() << "\n";
|
||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << "\n";
|
||||
tout << "---------->\n" << mk_ismt2_pp(result, m()) << "\n";);
|
||||
|
@ -576,7 +578,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
else
|
||||
st = pull_ite(result);
|
||||
}
|
||||
CTRACE("th_rewriter_step", st != BR_FAILED,
|
||||
CTRACE("th_rewriter_step", st != BR_FAILED,
|
||||
tout << f->get_name() << "\n";
|
||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << "\n";
|
||||
tout << "---------->\n" << mk_ismt2_pp(result, m()) << "\n";);
|
||||
|
@ -593,28 +595,28 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
quantifier_ref q1(m());
|
||||
proof * p1 = 0;
|
||||
if (is_quantifier(new_body) &&
|
||||
if (is_quantifier(new_body) &&
|
||||
to_quantifier(new_body)->is_forall() == old_q->is_forall() &&
|
||||
!old_q->has_patterns() &&
|
||||
!to_quantifier(new_body)->has_patterns()) {
|
||||
|
||||
|
||||
quantifier * nested_q = to_quantifier(new_body);
|
||||
|
||||
|
||||
ptr_buffer<sort> sorts;
|
||||
buffer<symbol> names;
|
||||
buffer<symbol> names;
|
||||
sorts.append(old_q->get_num_decls(), old_q->get_decl_sorts());
|
||||
names.append(old_q->get_num_decls(), old_q->get_decl_names());
|
||||
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(),
|
||||
sorts.size(),
|
||||
sorts.c_ptr(),
|
||||
|
@ -624,9 +626,9 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
old_q->get_qid(),
|
||||
old_q->get_skid(),
|
||||
0, 0, 0, 0);
|
||||
|
||||
|
||||
SASSERT(is_well_sorted(m(), q1));
|
||||
|
||||
|
||||
if (m().proofs_enabled()) {
|
||||
SASSERT(old_q->get_expr() == new_body);
|
||||
p1 = m().mk_pull_quant(old_q, q1);
|
||||
|
@ -635,24 +637,24 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
else {
|
||||
ptr_buffer<expr> new_patterns_buf;
|
||||
ptr_buffer<expr> new_no_patterns_buf;
|
||||
|
||||
|
||||
new_patterns_buf.append(old_q->get_num_patterns(), new_patterns);
|
||||
new_no_patterns_buf.append(old_q->get_num_no_patterns(), new_no_patterns);
|
||||
|
||||
remove_duplicates(new_patterns_buf);
|
||||
remove_duplicates(new_no_patterns_buf);
|
||||
|
||||
q1 = m().update_quantifier(old_q,
|
||||
|
||||
q1 = m().update_quantifier(old_q,
|
||||
new_patterns_buf.size(), new_patterns_buf.c_ptr(), new_no_patterns_buf.size(), new_no_patterns_buf.c_ptr(),
|
||||
new_body);
|
||||
TRACE("reduce_quantifier", tout << mk_ismt2_pp(old_q, m()) << "\n----->\n" << mk_ismt2_pp(q1, m()) << "\n";);
|
||||
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";);
|
||||
|
||||
|
||||
result_pr = 0;
|
||||
if (m().proofs_enabled()) {
|
||||
proof * p2 = 0;
|
||||
|
@ -758,7 +760,7 @@ unsigned th_rewriter::get_num_steps() const {
|
|||
void th_rewriter::cleanup() {
|
||||
ast_manager & m = m_imp->m();
|
||||
dealloc(m_imp);
|
||||
m_imp = alloc(imp, m, m_params);
|
||||
m_imp = alloc(imp, m, m_params);
|
||||
}
|
||||
|
||||
void th_rewriter::reset() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ Notes:
|
|||
|
||||
#include"rewriter.h"
|
||||
#include"used_vars.h"
|
||||
#include"params.h"
|
||||
|
||||
/**
|
||||
\brief Alias for var_shifter class.
|
||||
|
@ -31,7 +32,7 @@ typedef var_shifter shift_vars;
|
|||
\brief Variable substitution functor. It substitutes variables by expressions.
|
||||
The expressions may contain variables.
|
||||
*/
|
||||
class var_subst {
|
||||
class var_subst {
|
||||
beta_reducer m_reducer;
|
||||
bool m_std_order;
|
||||
public:
|
||||
|
@ -39,7 +40,7 @@ public:
|
|||
bool std_order() const { return m_std_order; }
|
||||
|
||||
/**
|
||||
When std_order() == true,
|
||||
When std_order() == true,
|
||||
I'm using the same standard used in quantifier instantiation.
|
||||
(VAR 0) is stored in the last position of the array.
|
||||
...
|
||||
|
@ -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.
|
||||
|
@ -86,7 +89,7 @@ class expr_free_vars {
|
|||
expr_sparse_mark m_mark;
|
||||
ptr_vector<sort> m_sorts;
|
||||
ptr_vector<expr> m_todo;
|
||||
public:
|
||||
public:
|
||||
void reset();
|
||||
void operator()(expr* e);
|
||||
void accumulate(expr* e);
|
||||
|
@ -96,7 +99,7 @@ public:
|
|||
bool contains(unsigned idx) const { return idx < m_sorts.size() && m_sorts[idx] != 0; }
|
||||
void set_default_sort(sort* s);
|
||||
void reverse() { m_sorts.reverse(); }
|
||||
sort*const* c_ptr() const { return m_sorts.c_ptr(); }
|
||||
sort*const* c_ptr() const { return m_sorts.c_ptr(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,7 +14,7 @@ Author:
|
|||
Leonardo de Moura (leonardo) 2010-04-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
Christoph Wintersteiger 2010-04-06: Added implementation.
|
||||
|
||||
--*/
|
||||
|
@ -40,7 +40,7 @@ bool distribute_forall::visit_children(expr * n) {
|
|||
bool visited = true;
|
||||
unsigned j;
|
||||
switch(n->get_kind()) {
|
||||
case AST_VAR:
|
||||
case AST_VAR:
|
||||
break;
|
||||
case AST_APP:
|
||||
j = to_app(n)->get_num_args();
|
||||
|
@ -86,15 +86,15 @@ void distribute_forall::reduce1_app(app * a) {
|
|||
SASSERT(is_cached(a->get_arg(j)));
|
||||
expr * c = get_cached(a->get_arg(j));
|
||||
SASSERT(c!=0);
|
||||
if (c != a->get_arg(j))
|
||||
if (c != a->get_arg(j))
|
||||
reduced = true;
|
||||
m_new_args[j] = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (reduced) {
|
||||
na = m_manager.mk_app(a->get_decl(), num_args, m_new_args.c_ptr());
|
||||
}
|
||||
|
||||
|
||||
cache_result(a, na);
|
||||
}
|
||||
|
||||
|
@ -126,11 +126,11 @@ 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);
|
||||
// m_bsimp.mk_and actually constructs a (not (or ...)) formula,
|
||||
// m_bsimp.mk_and actually constructs a (not (or ...)) formula,
|
||||
// it will also apply basic simplifications.
|
||||
m_bsimp.mk_and(new_args.size(), new_args.c_ptr(), result);
|
||||
cache_result(q, result);
|
||||
|
@ -148,15 +148,15 @@ void distribute_forall::operator()(expr * f, expr_ref & result) {
|
|||
|
||||
while (!m_todo.empty()) {
|
||||
expr * e = m_todo.back();
|
||||
if (visit_children(e)) {
|
||||
if (visit_children(e)) {
|
||||
m_todo.pop_back();
|
||||
reduce1(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = get_cached(f);
|
||||
SASSERT(result!=0);
|
||||
TRACE("distribute_forall", tout << mk_ll_pp(f, m_manager) << "======>\n"
|
||||
TRACE("distribute_forall", tout << mk_ll_pp(f, m_manager) << "======>\n"
|
||||
<< mk_ll_pp(result, m_manager););
|
||||
}
|
||||
|
||||
|
@ -166,5 +166,5 @@ expr * distribute_forall::get_cached(expr * n) const {
|
|||
|
||||
void distribute_forall::cache_result(expr * n, expr * r) {
|
||||
SASSERT(r != 0);
|
||||
m_cache.insert(n, r);
|
||||
m_cache.insert(n, r);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ elim_bounds::elim_bounds(ast_manager & m):
|
|||
|
||||
(<= x k)
|
||||
(<= (+ x (* -1 y)) k)
|
||||
(<= (+ x (* -1 t)) k)
|
||||
(<= (+ x (* -1 t)) k)
|
||||
(<= (+ t (* -1 x)) k)
|
||||
|
||||
x and y are a bound variables, t is a ground term and k is a numeral
|
||||
|
@ -65,14 +65,14 @@ bool elim_bounds::is_bound(expr * n, var * & lower, var * & upper) {
|
|||
|
||||
if (neg)
|
||||
le = !le;
|
||||
|
||||
|
||||
if (is_var(n)) {
|
||||
upper = to_var(n);
|
||||
}
|
||||
else if (m_util.is_add(n) && to_app(n)->get_num_args() == 2) {
|
||||
expr * arg1 = to_app(n)->get_arg(0);
|
||||
expr * arg2 = to_app(n)->get_arg(1);
|
||||
if (is_var(arg1))
|
||||
if (is_var(arg1))
|
||||
upper = to_var(arg1);
|
||||
else if (!is_ground(arg1))
|
||||
return false;
|
||||
|
@ -95,7 +95,7 @@ bool elim_bounds::is_bound(expr * n, var * & lower, var * & upper) {
|
|||
|
||||
if (!le)
|
||||
std::swap(upper, lower);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -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";);
|
||||
}
|
||||
|
||||
|
@ -199,10 +199,10 @@ bool elim_bounds_star::visit_quantifier(quantifier * q) {
|
|||
visit(q->get_expr(), visited);
|
||||
return visited;
|
||||
}
|
||||
|
||||
|
||||
void elim_bounds_star::reduce1_quantifier(quantifier * q) {
|
||||
if (!q->is_forall() || q->get_num_patterns() != 0) {
|
||||
cache_result(q, q, 0);
|
||||
cache_result(q, q, 0);
|
||||
return;
|
||||
}
|
||||
quantifier_ref new_q(m);
|
||||
|
|
|
@ -33,8 +33,8 @@ simplifier::simplifier(ast_manager & m):
|
|||
m_ac_support(true) {
|
||||
}
|
||||
|
||||
void simplifier::register_plugin(plugin * p) {
|
||||
m_plugins.register_plugin(p);
|
||||
void simplifier::register_plugin(plugin * p) {
|
||||
m_plugins.register_plugin(p);
|
||||
}
|
||||
|
||||
simplifier::~simplifier() {
|
||||
|
@ -46,13 +46,13 @@ void simplifier::enable_ac_support(bool flag) {
|
|||
ptr_vector<plugin>::const_iterator it = m_plugins.begin();
|
||||
ptr_vector<plugin>::const_iterator end = m_plugins.end();
|
||||
for (; it != end; ++it) {
|
||||
if (*it != 0)
|
||||
if (*it != 0)
|
||||
(*it)->enable_ac_support(flag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief External interface for the simplifier.
|
||||
\brief External interface for the simplifier.
|
||||
A client will invoke operator()(s, r, p) to simplify s.
|
||||
The result is stored in r.
|
||||
When proof generation is enabled, a proof for the equivalence (or equisatisfiability)
|
||||
|
@ -69,14 +69,14 @@ void simplifier::operator()(expr * s, expr_ref & r, proof_ref & p) {
|
|||
proof * result_proof;
|
||||
switch (m.proof_mode()) {
|
||||
case PGM_DISABLED: // proof generation is disabled.
|
||||
reduce_core(s);
|
||||
reduce_core(s);
|
||||
// after executing reduce_core, the result of the simplification is in the cache
|
||||
get_cached(s, result, result_proof);
|
||||
r = result;
|
||||
p = m.mk_undef_proof();
|
||||
break;
|
||||
case PGM_COARSE: // coarse proofs... in this case, we do not produce a step by step (fine grain) proof to show the equivalence (or equisatisfiability) of s an r.
|
||||
m_subst_proofs.reset(); // m_subst_proofs is an auxiliary vector that is used to justify substitutions. See comment on method get_subst.
|
||||
m_subst_proofs.reset(); // m_subst_proofs is an auxiliary vector that is used to justify substitutions. See comment on method get_subst.
|
||||
reduce_core(s);
|
||||
get_cached(s, result, result_proof);
|
||||
r = result;
|
||||
|
@ -163,7 +163,7 @@ bool simplifier::visit_children(expr * n) {
|
|||
// The method ast_manager::mk_app is used to create the flat version of an AC operator.
|
||||
// In Z3 1.x, we used multi-ary operators. This creates problems for the superposition engine.
|
||||
// So, starting at Z3 2.x, only boolean operators can be multi-ary.
|
||||
// Example:
|
||||
// Example:
|
||||
// (and (and a b) (and c d)) --> (and a b c d)
|
||||
// (+ (+ a b) (+ c d)) --> (+ a (+ b (+ c d)))
|
||||
// Remark: The flattening is only applied if m_ac_support is true.
|
||||
|
@ -178,7 +178,7 @@ bool simplifier::visit_children(expr * n) {
|
|||
}
|
||||
return visited;
|
||||
}
|
||||
case AST_QUANTIFIER:
|
||||
case AST_QUANTIFIER:
|
||||
return visit_quantifier(to_quantifier(n));
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -188,7 +188,7 @@ bool simplifier::visit_children(expr * n) {
|
|||
|
||||
/**
|
||||
\brief Visit the children of n assuming it is an AC (associative-commutative) operator.
|
||||
|
||||
|
||||
For example, if n is of the form (+ (+ a b) (+ c d)), this method
|
||||
will return true if the nodes a, b, c and d have been already simplified.
|
||||
The nodes (+ a b) and (+ c d) are not really checked.
|
||||
|
@ -216,7 +216,7 @@ bool simplifier::visit_ac(app * n) {
|
|||
expr * arg = n->get_arg(i);
|
||||
if (is_app_of(arg, decl))
|
||||
todo.push_back(to_app(arg));
|
||||
else
|
||||
else
|
||||
visit(arg, visited);
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ void simplifier::reduce1_app_core(app * n) {
|
|||
proof * p;
|
||||
if (n == r)
|
||||
p = 0;
|
||||
else if (r != s)
|
||||
else if (r != s)
|
||||
// we use a "theory rewrite generic proof" to justify the step
|
||||
// s = (decl arg_0' ... arg_{n-1}') --> r
|
||||
p = m.mk_transitivity(p1, m.mk_rewrite(s, r));
|
||||
|
@ -368,7 +368,7 @@ void simplifier::reduce1_ac_app_core(app * n) {
|
|||
proof_ref p1(m);
|
||||
mk_ac_congruent_term(n, n_c, p1);
|
||||
TRACE("ac", tout << "expr:\n" << mk_pp(n, m) << "\ncongruent term:\n" << mk_pp(n_c, m) << "\n";);
|
||||
expr_ref r(m);
|
||||
expr_ref r(m);
|
||||
func_decl * decl = n->get_decl();
|
||||
family_id fid = decl->get_family_id();
|
||||
plugin * p = get_plugin(fid);
|
||||
|
@ -415,7 +415,7 @@ void simplifier::reduce1_ac_app_core(app * n) {
|
|||
proof * p;
|
||||
if (n == r.get())
|
||||
p = 0;
|
||||
else if (r.get() != n_c.get())
|
||||
else if (r.get() != n_c.get())
|
||||
p = m.mk_transitivity(p1, m.mk_rewrite(n_c, r));
|
||||
else
|
||||
p = p1;
|
||||
|
@ -434,7 +434,7 @@ void simplifier::dump_rewrite_lemma(func_decl * decl, unsigned num_args, expr *
|
|||
sprintf_s(buffer, ARRAYSIZE(buffer), "lemma_%d.smt", g_rewrite_lemma_id);
|
||||
#else
|
||||
sprintf(buffer, "rewrite_lemma_%d.smt", g_rewrite_lemma_id);
|
||||
#endif
|
||||
#endif
|
||||
ast_smt_pp pp(m);
|
||||
pp.set_benchmark_name("rewrite_lemma");
|
||||
pp.set_status("unsat");
|
||||
|
@ -450,7 +450,7 @@ void simplifier::dump_rewrite_lemma(func_decl * decl, unsigned num_args, expr *
|
|||
/**
|
||||
\brief Return in \c result an expression \c e equivalent to <tt>(f args[0] ... args[num_args - 1])</tt>, and
|
||||
store in \c pr a proof for <tt>(= (f args[0] ... args[num_args - 1]) e)</tt>
|
||||
|
||||
|
||||
If e is identical to (f args[0] ... args[num_args - 1]), then pr is set to 0.
|
||||
*/
|
||||
void simplifier::mk_app(func_decl * decl, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
|
@ -474,7 +474,7 @@ void simplifier::mk_app(func_decl * decl, unsigned num_args, expr * const * args
|
|||
//dump_rewrite_lemma(decl, num_args, args, result.get());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
result = m.mk_app(decl, num_args, args);
|
||||
}
|
||||
|
||||
|
@ -494,17 +494,17 @@ void simplifier::mk_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
|||
proof * arg_proof;
|
||||
get_cached(arg, new_arg, arg_proof);
|
||||
|
||||
CTRACE("simplifier_bug", (arg != new_arg) != (arg_proof != 0),
|
||||
CTRACE("simplifier_bug", (arg != new_arg) != (arg_proof != 0),
|
||||
tout << mk_ll_pp(arg, m) << "\n---->\n" << mk_ll_pp(new_arg, m) << "\n";
|
||||
tout << "#" << arg->get_id() << " #" << new_arg->get_id() << "\n";
|
||||
tout << arg << " " << new_arg << "\n";);
|
||||
|
||||
|
||||
|
||||
|
||||
if (arg != new_arg) {
|
||||
has_new_args = true;
|
||||
proofs.push_back(arg_proof);
|
||||
SASSERT(arg_proof);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SASSERT(arg_proof == 0);
|
||||
}
|
||||
|
@ -526,10 +526,10 @@ void simplifier::mk_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
|||
/**
|
||||
\brief Store the new arguments of \c n in result. Store in p a proof for
|
||||
(= n (f result[0] ... result[num_args - 1])), where f is the function symbol of n.
|
||||
|
||||
|
||||
If there are no new arguments or fine grain proofs are disabled, then p is set to 0.
|
||||
|
||||
Return true there are new arguments.
|
||||
Return true there are new arguments.
|
||||
*/
|
||||
bool simplifier::get_args(app * n, ptr_vector<expr> & result, proof_ref & p) {
|
||||
bool has_new_args = false;
|
||||
|
@ -565,10 +565,10 @@ bool simplifier::get_args(app * n, ptr_vector<expr> & result, proof_ref & p) {
|
|||
void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
||||
SASSERT(m_ac_support);
|
||||
func_decl * f = n->get_decl();
|
||||
|
||||
|
||||
m_ac_cache.reset();
|
||||
m_ac_pr_cache.reset();
|
||||
|
||||
|
||||
ptr_buffer<app> todo;
|
||||
ptr_buffer<expr> new_args;
|
||||
ptr_buffer<proof> new_arg_prs;
|
||||
|
@ -621,7 +621,7 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
|||
todo.pop_back();
|
||||
if (!has_new_arg) {
|
||||
m_ac_cache.insert(curr, curr);
|
||||
if (m.fine_grain_proofs())
|
||||
if (m.fine_grain_proofs())
|
||||
m_ac_pr_cache.insert(curr, 0);
|
||||
}
|
||||
else {
|
||||
|
@ -634,7 +634,7 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SASSERT(m_ac_cache.contains(n));
|
||||
app * new_n = 0;
|
||||
m_ac_cache.find(n, new_n);
|
||||
|
@ -646,7 +646,7 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
|||
}
|
||||
}
|
||||
|
||||
#define White 0
|
||||
#define White 0
|
||||
#define Grey 1
|
||||
#define Black 2
|
||||
|
||||
|
@ -688,7 +688,7 @@ void simplifier::ac_top_sort(app * n, ptr_buffer<expr> & result) {
|
|||
while (!todo.empty()) {
|
||||
expr * curr = todo.back();
|
||||
int color;
|
||||
obj_map<expr, int>::obj_map_entry * entry = colors.insert_if_not_there2(curr, White);
|
||||
obj_map<expr, int>::obj_map_entry * entry = colors.insert_if_not_there2(curr, White);
|
||||
SASSERT(entry);
|
||||
color = entry->get_data().m_value;
|
||||
switch (color) {
|
||||
|
@ -731,7 +731,7 @@ void simplifier::get_ac_args(app * n, ptr_vector<expr> & args, vector<rational>
|
|||
ac_top_sort(n, sorted_exprs);
|
||||
SASSERT(!sorted_exprs.empty());
|
||||
SASSERT(sorted_exprs[sorted_exprs.size()-1] == n);
|
||||
|
||||
|
||||
TRACE("ac", tout << mk_ll_pp(n, m, true, false) << "#" << n->get_id() << "\nsorted expressions...\n";
|
||||
for (unsigned i = 0; i < sorted_exprs.size(); i++) {
|
||||
tout << "#" << sorted_exprs[i]->get_id() << " ";
|
||||
|
@ -747,7 +747,7 @@ void simplifier::get_ac_args(app * n, ptr_vector<expr> & args, vector<rational>
|
|||
expr * curr = sorted_exprs[j];
|
||||
rational mult;
|
||||
m_ac_mults.find(curr, mult);
|
||||
SASSERT(!mult.is_zero());
|
||||
SASSERT(!mult.is_zero());
|
||||
if (is_app_of(curr, decl)) {
|
||||
unsigned num_args = to_app(curr)->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
|
@ -772,16 +772,16 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
|
||||
quantifier_ref q1(m);
|
||||
proof * p1 = 0;
|
||||
|
||||
if (is_quantifier(new_body) &&
|
||||
|
||||
if (is_quantifier(new_body) &&
|
||||
to_quantifier(new_body)->is_forall() == q->is_forall() &&
|
||||
!to_quantifier(q)->has_patterns() &&
|
||||
!to_quantifier(new_body)->has_patterns()) {
|
||||
|
||||
|
||||
quantifier * nested_q = to_quantifier(new_body);
|
||||
|
||||
ptr_buffer<sort> sorts;
|
||||
buffer<symbol> names;
|
||||
buffer<symbol> names;
|
||||
sorts.append(q->get_num_decls(), q->get_decl_sorts());
|
||||
names.append(q->get_num_decls(), q->get_decl_names());
|
||||
sorts.append(nested_q->get_num_decls(), nested_q->get_decl_sorts());
|
||||
|
@ -797,7 +797,7 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
q->get_skid(),
|
||||
0, 0, 0, 0);
|
||||
SASSERT(is_well_sorted(m, q1));
|
||||
|
||||
|
||||
if (m.fine_grain_proofs()) {
|
||||
quantifier * q0 = m.update_quantifier(q, new_body);
|
||||
proof * p0 = q == q0 ? 0 : m.mk_quant_intro(q, q0, new_body_pr);
|
||||
|
@ -817,13 +817,13 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
get_cached(q->get_pattern(i), new_pattern, new_pattern_pr);
|
||||
if (m.is_pattern(new_pattern)) {
|
||||
new_patterns.push_back(new_pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
num = q->get_num_no_patterns();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
get_cached(q->get_no_pattern(i), new_pattern, new_pattern_pr);
|
||||
new_no_patterns.push_back(new_pattern);
|
||||
}
|
||||
}
|
||||
|
||||
remove_duplicates(new_patterns);
|
||||
remove_duplicates(new_no_patterns);
|
||||
|
@ -833,7 +833,7 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
new_body,
|
||||
q->get_weight(),
|
||||
q->get_weight(),
|
||||
q->get_qid(),
|
||||
q->get_skid(),
|
||||
new_patterns.size(),
|
||||
|
@ -850,10 +850,10 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
p1 = q == q1 ? 0 : m.mk_quant_intro(q, q1, new_body_pr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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()) {
|
||||
proof * p2 = 0;
|
||||
|
@ -871,7 +871,7 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
void simplifier::borrow_plugins(simplifier const & s) {
|
||||
ptr_vector<plugin>::const_iterator it = s.begin_plugins();
|
||||
ptr_vector<plugin>::const_iterator end = s.end_plugins();
|
||||
for (; it != end; ++it)
|
||||
for (; it != end; ++it)
|
||||
register_plugin(*it);
|
||||
}
|
||||
|
||||
|
@ -882,7 +882,7 @@ void simplifier::enable_presimp() {
|
|||
enable_ac_support(false);
|
||||
ptr_vector<plugin>::const_iterator it = begin_plugins();
|
||||
ptr_vector<plugin>::const_iterator end = end_plugins();
|
||||
for (; it != end; ++it)
|
||||
for (; it != end; ++it)
|
||||
(*it)->enable_presimp(true);
|
||||
}
|
||||
|
||||
|
@ -905,7 +905,7 @@ bool subst_simplifier::get_subst(expr * n, expr_ref & r, proof_ref & p) {
|
|||
m_subst_map->get(n, _r, _p);
|
||||
r = _r;
|
||||
p = _p;
|
||||
if (m.coarse_grain_proofs())
|
||||
if (m.coarse_grain_proofs())
|
||||
m_subst_proofs.push_back(p);
|
||||
return true;
|
||||
}
|
||||
|
@ -917,7 +917,7 @@ static void push_core(ast_manager & m, expr * e, proof * pr, expr_ref_vector & r
|
|||
TRACE("preprocessor",
|
||||
tout << mk_pp(e, m) << "\n";
|
||||
if (pr) tout << mk_ll_pp(pr, m) << "\n\n";);
|
||||
if (m.is_true(e))
|
||||
if (m.is_true(e))
|
||||
return;
|
||||
result.push_back(e);
|
||||
if (m.proofs_enabled())
|
||||
|
@ -952,9 +952,9 @@ void push_assertion(ast_manager & m, expr * e, proof * pr, expr_ref_vector & res
|
|||
CTRACE("push_assertion", !(pr == 0 || m.is_undef_proof(pr) || m.get_fact(pr) == e),
|
||||
tout << mk_pp(e, m) << "\n" << mk_pp(m.get_fact(pr), m) << "\n";);
|
||||
SASSERT(pr == 0 || m.is_undef_proof(pr) || m.get_fact(pr) == e);
|
||||
if (m.is_and(e))
|
||||
if (m.is_and(e))
|
||||
push_and(m, to_app(e), pr, result, result_prs);
|
||||
else if (m.is_not(e) && m.is_or(to_app(e)->get_arg(0)))
|
||||
else if (m.is_not(e) && m.is_or(to_app(e)->get_arg(0)))
|
||||
push_not_or(m, to_app(to_app(e)->get_arg(0)), pr, result, result_prs);
|
||||
else
|
||||
push_core(m, e, pr, result, result_prs);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue