3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-10-04 15:03:57 +00:00

initial integration of opt

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-04-27 19:13:00 -07:00
commit 8205b45839
114 changed files with 3680 additions and 1370 deletions

View file

@ -35,7 +35,7 @@ struct arith_decl_plugin::algebraic_numbers_wrapper {
~algebraic_numbers_wrapper() {
}
unsigned mk_id(algebraic_numbers::anum const & val) {
SASSERT(!m_amanager.is_rational(val));
unsigned new_id = m_id_gen.mk();
@ -121,7 +121,7 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
m_int_decl = m->mk_sort(symbol("Int"), sort_info(id, INT_SORT));
m->inc_ref(m_int_decl);
sort * i = m_int_decl;
sort * b = m->mk_bool_sort();
#define MK_PRED(FIELD, NAME, KIND, SORT) { \
@ -140,7 +140,7 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
MK_PRED(m_i_ge_decl, ">=", OP_GE, i);
MK_PRED(m_i_lt_decl, "<", OP_LT, i);
MK_PRED(m_i_gt_decl, ">", OP_GT, i);
#define MK_AC_OP(FIELD, NAME, KIND, SORT) { \
func_decl_info info(id, KIND); \
info.set_associative(); \
@ -205,7 +205,7 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
MK_UNARY(m_asinh_decl, "asinh", OP_ASINH, r);
MK_UNARY(m_acosh_decl, "acosh", OP_ACOSH, r);
MK_UNARY(m_atanh_decl, "atanh", OP_ATANH, r);
func_decl * pi_decl = m->mk_const_decl(symbol("pi"), r, func_decl_info(id, OP_PI));
m_pi = m->mk_const(pi_decl);
m->inc_ref(m_pi);
@ -213,7 +213,7 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
func_decl * e_decl = m->mk_const_decl(symbol("euler"), r, func_decl_info(id, OP_E));
m_e = m->mk_const(e_decl);
m->inc_ref(m_e);
func_decl * z_pw_z_int = m->mk_const_decl(symbol("0^0-int"), i, func_decl_info(id, OP_0_PW_0_INT));
m_0_pw_0_int = m->mk_const(z_pw_z_int);
m->inc_ref(m_0_pw_0_int);
@ -221,7 +221,7 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
func_decl * z_pw_z_real = m->mk_const_decl(symbol("0^0-real"), r, func_decl_info(id, OP_0_PW_0_REAL));
m_0_pw_0_real = m->mk_const(z_pw_z_real);
m->inc_ref(m_0_pw_0_real);
MK_OP(m_neg_root_decl, "neg-root", OP_NEG_ROOT, r);
MK_UNARY(m_div_0_decl, "/0", OP_DIV_0, r);
MK_UNARY(m_idiv_0_decl, "div0", OP_IDIV_0, i);
@ -285,7 +285,8 @@ arith_decl_plugin::arith_decl_plugin():
m_idiv_0_decl(0),
m_mod_0_decl(0),
m_u_asin_decl(0),
m_u_acos_decl(0) {
m_u_acos_decl(0),
m_convert_int_numerals_to_real(false) {
}
arith_decl_plugin::~arith_decl_plugin() {
@ -418,7 +419,7 @@ app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) {
if (val.is_unsigned()) {
unsigned u_val = val.get_unsigned();
if (u_val < MAX_SMALL_NUM_TO_CACHE) {
if (is_int) {
if (is_int && !m_convert_int_numerals_to_real) {
app * r = m_small_ints.get(u_val, 0);
if (r == 0) {
parameter p[2] = { parameter(val), parameter(1) };
@ -442,7 +443,7 @@ app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) {
}
parameter p[2] = { parameter(val), parameter(static_cast<int>(is_int)) };
func_decl * decl;
if (is_int)
if (is_int && !m_convert_int_numerals_to_real)
decl = m_manager->mk_const_decl(m_intv_sym, m_int_decl, func_decl_info(m_family_id, OP_NUM, 2, p));
else
decl = m_manager->mk_const_decl(m_realv_sym, m_real_decl, func_decl_info(m_family_id, OP_NUM, 2, p));
@ -479,14 +480,14 @@ static bool has_real_arg(ast_manager * m, unsigned num_args, expr * const * args
}
static bool is_const_op(decl_kind k) {
return
k == OP_PI ||
return
k == OP_PI ||
k == OP_E ||
k == OP_0_PW_0_INT ||
k == OP_0_PW_0_REAL;
}
func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (k == OP_NUM)
return mk_num_decl(num_parameters, parameters, arity);
@ -503,7 +504,7 @@ func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
}
}
func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned num_args, expr * const * args, sort * range) {
if (k == OP_NUM)
return mk_num_decl(num_parameters, parameters, num_args);
@ -521,9 +522,17 @@ func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
}
void arith_decl_plugin::get_sort_names(svector<builtin_name>& sort_names, symbol const & logic) {
// TODO: only define Int and Real in the right logics
sort_names.push_back(builtin_name("Int", INT_SORT));
sort_names.push_back(builtin_name("Real", REAL_SORT));
if (logic == "NRA" ||
logic == "QF_NRA" ||
logic == "QF_UFNRA") {
m_convert_int_numerals_to_real = true;
sort_names.push_back(builtin_name("Real", REAL_SORT));
}
else {
// TODO: only define Int and Real in the right logics
sort_names.push_back(builtin_name("Int", INT_SORT));
sort_names.push_back(builtin_name("Real", REAL_SORT));
}
}
void arith_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol const & logic) {
@ -563,16 +572,16 @@ void arith_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol con
}
bool arith_decl_plugin::is_value(app * e) const {
return
is_app_of(e, m_family_id, OP_NUM) ||
return
is_app_of(e, m_family_id, OP_NUM) ||
is_app_of(e, m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM) ||
is_app_of(e, m_family_id, OP_PI) ||
is_app_of(e, m_family_id, OP_E);
}
bool arith_decl_plugin::is_unique_value(app * e) const {
return
is_app_of(e, m_family_id, OP_NUM) ||
return
is_app_of(e, m_family_id, OP_NUM) ||
is_app_of(e, m_family_id, OP_PI) ||
is_app_of(e, m_family_id, OP_E);
}
@ -671,7 +680,7 @@ expr_ref arith_util::mk_mul_simplify(expr_ref_vector const& args) {
}
expr_ref arith_util::mk_mul_simplify(unsigned sz, expr* const* args) {
expr_ref result(m_manager);
switch (sz) {
case 0:
result = mk_numeral(rational(1), true);
@ -681,7 +690,7 @@ expr_ref arith_util::mk_mul_simplify(unsigned sz, expr* const* args) {
break;
default:
result = mk_mul(sz, args);
break;
break;
}
return result;
}
@ -692,7 +701,7 @@ expr_ref arith_util::mk_add_simplify(expr_ref_vector const& args) {
}
expr_ref arith_util::mk_add_simplify(unsigned sz, expr* const* args) {
expr_ref result(m_manager);
switch (sz) {
case 0:
result = mk_numeral(rational(0), true);
@ -702,7 +711,7 @@ expr_ref arith_util::mk_add_simplify(unsigned sz, expr* const* args) {
break;
default:
result = mk_add(sz, args);
break;
break;
}
return result;
}

View file

@ -152,6 +152,8 @@ protected:
ptr_vector<app> m_small_ints;
ptr_vector<app> m_small_reals;
bool m_convert_int_numerals_to_real;
func_decl * mk_func_decl(decl_kind k, bool is_real);
virtual void set_manager(ast_manager * m, family_id id);
decl_kind fix_kind(decl_kind k, unsigned arity);

View file

@ -1002,14 +1002,6 @@ class smt2_printer {
reset_stacks();
SASSERT(&(r.get_manager()) == &(fm()));
m_soccs(n);
TRACE("smt2_pp_shared",
tout << "shared terms for:\n" << mk_pp(n, m()) << "\n";
tout << "------>\n";
shared_occs::iterator it = m_soccs.begin_shared();
shared_occs::iterator end = m_soccs.end_shared();
for (; it != end; ++it) {
tout << mk_pp(*it, m()) << "\n";
});
m_root = n;
push_frame(n, true);
while (!m_frame_stack.empty()) {

View file

@ -406,11 +406,11 @@ public:
app * mk_bv_not(expr * arg) { return m_manager.mk_app(get_fid(), OP_BNOT, arg); }
app * mk_bv_xor(unsigned num, expr * const * args) { return m_manager.mk_app(get_fid(), OP_BXOR, num, args); }
app * mk_bv_neg(expr * arg) { return m_manager.mk_app(get_fid(), OP_BNEG, arg); }
app * mk_bv_urem(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_BUREM, arg1, arg2); }
app * mk_bv_srem(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_BSREM, arg1, arg2); }
app * mk_bv_add(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_BADD, arg1, arg2); }
app * mk_bv_sub(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_BSUB, arg1, arg2); }
app * mk_bv_mul(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_BMUL, arg1, arg2); }
app * mk_bv_urem(expr * arg1, expr * arg2) const { return m_manager.mk_app(get_fid(), OP_BUREM, arg1, arg2); }
app * mk_bv_srem(expr * arg1, expr * arg2) const { return m_manager.mk_app(get_fid(), OP_BSREM, arg1, arg2); }
app * mk_bv_add(expr * arg1, expr * arg2) const { return m_manager.mk_app(get_fid(), OP_BADD, arg1, arg2); }
app * mk_bv_sub(expr * arg1, expr * arg2) const { return m_manager.mk_app(get_fid(), OP_BSUB, arg1, arg2); }
app * mk_bv_mul(expr * arg1, expr * arg2) const { return m_manager.mk_app(get_fid(), OP_BMUL, arg1, arg2); }
app * mk_zero_extend(unsigned n, expr* e) {
parameter p(n);
return m_manager.mk_app(get_fid(), OP_ZERO_EXT, 1, &p, 1, &e);

View file

@ -23,8 +23,21 @@ void decl_collector::visit_sort(sort * n) {
family_id fid = n->get_family_id();
if (m().is_uninterp(n))
m_sorts.push_back(n);
if (fid == m_dt_fid)
if (fid == m_dt_fid) {
m_sorts.push_back(n);
unsigned num_cnstr = m_dt_util.get_datatype_num_constructors(n);
for (unsigned i = 0; i < num_cnstr; i++) {
func_decl * cnstr = m_dt_util.get_datatype_constructors(n)->get(i);
m_decls.push_back(cnstr);
ptr_vector<func_decl> const & cnstr_acc = *m_dt_util.get_constructor_accessors(cnstr);
unsigned num_cas = cnstr_acc.size();
for (unsigned j = 0; j < num_cas; j++) {
func_decl * accsr = cnstr_acc.get(j);
m_decls.push_back(accsr);
}
}
}
}
bool decl_collector::is_bool(sort * s) {
@ -38,14 +51,15 @@ void decl_collector::visit_func(func_decl * n) {
m_preds.push_back(n);
else
m_decls.push_back(n);
}
}
}
decl_collector::decl_collector(ast_manager & m, bool preds):
m_manager(m),
m_sep_preds(preds) {
m_sep_preds(preds),
m_dt_util(m) {
m_basic_fid = m_manager.get_basic_family_id();
m_dt_fid = m_manager.mk_family_id("datatype");
m_dt_fid = m_dt_util.get_family_id();
}
void decl_collector::visit(ast* n) {
@ -55,7 +69,7 @@ void decl_collector::visit(ast* n) {
n = todo.back();
todo.pop_back();
if (!m_visited.is_marked(n)) {
m_visited.mark(n, true);
m_visited.mark(n, true);
switch(n->get_kind()) {
case AST_APP: {
app * a = to_app(n);
@ -64,7 +78,7 @@ void decl_collector::visit(ast* n) {
}
todo.push_back(a->get_decl());
break;
}
}
case AST_QUANTIFIER: {
quantifier * q = to_quantifier(n);
unsigned num_decls = q->get_num_decls();
@ -77,7 +91,7 @@ void decl_collector::visit(ast* n) {
}
break;
}
case AST_SORT:
case AST_SORT:
visit_sort(to_sort(n));
break;
case AST_FUNC_DECL: {

View file

@ -21,6 +21,7 @@ Revision History:
#define SMT_DECL_COLLECTOR_H_
#include"ast.h"
#include"datatype_decl_plugin.h"
class decl_collector {
ast_manager & m_manager;
@ -28,9 +29,10 @@ class decl_collector {
ptr_vector<sort> m_sorts;
ptr_vector<func_decl> m_decls;
ptr_vector<func_decl> m_preds;
ast_mark m_visited;
family_id m_basic_fid;
family_id m_dt_fid;
ast_mark m_visited;
family_id m_basic_fid;
family_id m_dt_fid;
datatype_util m_dt_util;
void visit_sort(sort* n);
bool is_bool(sort* s);

View file

@ -19,22 +19,22 @@ Revision History:
--*/
#include"macro_util.h"
#include"occurs.h"
#include"ast_util.h"
#include"arith_simplifier_plugin.h"
#include"basic_simplifier_plugin.h"
#include"bv_simplifier_plugin.h"
#include"var_subst.h"
#include"ast_pp.h"
#include"ast_ll_pp.h"
#include"ast_util.h"
#include"for_each_expr.h"
#include"well_sorted.h"
#include"bool_rewriter.h"
macro_util::macro_util(ast_manager & m, simplifier & s):
m_manager(m),
m_bv(m),
m_simplifier(s),
m_arith_simp(0),
m_bv_simp(0),
m_basic_simp(0),
m_forbidden_set(0),
m_curr_clause(0) {
}
@ -55,24 +55,17 @@ bv_simplifier_plugin * macro_util::get_bv_simp() const {
return m_bv_simp;
}
basic_simplifier_plugin * macro_util::get_basic_simp() const {
if (m_basic_simp == 0) {
const_cast<macro_util*>(this)->m_basic_simp = static_cast<basic_simplifier_plugin*>(m_simplifier.get_plugin(m_manager.get_basic_family_id()));
}
SASSERT(m_basic_simp != 0);
return m_basic_simp;
}
bool macro_util::is_bv(expr * n) const {
return get_bv_simp()->is_bv(n);
return m_bv.is_bv(n);
}
bool macro_util::is_bv_sort(sort * s) const {
return get_bv_simp()->is_bv_sort(s);
return m_bv.is_bv_sort(s);
}
bool macro_util::is_add(expr * n) const {
return get_arith_simp()->is_add(n) || get_bv_simp()->is_add(n);
return get_arith_simp()->is_add(n) || m_bv.is_bv_add(n);
}
bool macro_util::is_times_minus_one(expr * n, expr * & arg) const {
@ -80,11 +73,11 @@ bool macro_util::is_times_minus_one(expr * n, expr * & arg) const {
}
bool macro_util::is_le(expr * n) const {
return get_arith_simp()->is_le(n) || get_bv_simp()->is_le(n);
return get_arith_simp()->is_le(n) || m_bv.is_bv_ule(n) || m_bv.is_bv_sle(n);
}
bool macro_util::is_le_ge(expr * n) const {
return get_arith_simp()->is_le_ge(n) || get_bv_simp()->is_le_ge(n);
return get_arith_simp()->is_le_ge(n) || m_bv.is_bv_ule(n) || m_bv.is_bv_sle(n);
}
poly_simplifier_plugin * macro_util::get_poly_simp_for(sort * s) const {
@ -102,7 +95,7 @@ app * macro_util::mk_zero(sort * s) const {
void macro_util::mk_sub(expr * t1, expr * t2, expr_ref & r) const {
if (is_bv(t1)) {
get_bv_simp()->mk_sub(t1, t2, r);
r = m_bv.mk_bv_sub(t1, t2);
}
else {
get_arith_simp()->mk_sub(t1, t2, r);
@ -111,7 +104,7 @@ void macro_util::mk_sub(expr * t1, expr * t2, expr_ref & r) const {
void macro_util::mk_add(expr * t1, expr * t2, expr_ref & r) const {
if (is_bv(t1)) {
get_bv_simp()->mk_add(t1, t2, r);
r = m_bv.mk_bv_add(t1, t2);
}
else {
get_arith_simp()->mk_add(t1, t2, r);
@ -429,7 +422,7 @@ void macro_util::quasi_macro_head_to_macro_head(app * qhead, unsigned & num_decl
new_args.push_back(new_var);
new_conds.push_back(new_cond);
}
get_basic_simp()->mk_and(new_conds.size(), new_conds.c_ptr(), cond);
bool_rewriter(m_manager).mk_and(new_conds.size(), new_conds.c_ptr(), cond);
head = m_manager.mk_app(qhead->get_decl(), new_args.size(), new_args.c_ptr());
num_decls = next_var_idx;
}
@ -687,7 +680,7 @@ void macro_util::insert_quasi_macro(app * head, unsigned num_decls, expr * def,
if (cond == 0)
new_cond = extra_cond;
else
get_basic_simp()->mk_and(cond, extra_cond, new_cond);
bool_rewriter(m_manager).mk_and(cond, extra_cond, new_cond);
}
else {
hint_to_macro_head(m_manager, head, num_decls, new_head);
@ -719,20 +712,19 @@ void macro_util::get_rest_clause_as_cond(expr * except_lit, expr_ref & extra_con
if (m_curr_clause == 0)
return;
SASSERT(is_clause(m_manager, m_curr_clause));
basic_simplifier_plugin * bs = get_basic_simp();
expr_ref_buffer neg_other_lits(m_manager);
unsigned num_lits = get_clause_num_literals(m_manager, m_curr_clause);
for (unsigned i = 0; i < num_lits; i++) {
expr * l = get_clause_literal(m_manager, m_curr_clause, i);
if (l != except_lit) {
expr_ref neg_l(m_manager);
bs->mk_not(l, neg_l);
bool_rewriter(m_manager).mk_not(l, neg_l);
neg_other_lits.push_back(neg_l);
}
}
if (neg_other_lits.empty())
return;
get_basic_simp()->mk_and(neg_other_lits.size(), neg_other_lits.c_ptr(), extra_cond);
bool_rewriter(m_manager).mk_and(neg_other_lits.size(), neg_other_lits.c_ptr(), extra_cond);
}
void macro_util::collect_poly_args(expr * n, expr * exception, ptr_buffer<expr> & args) {

View file

@ -62,10 +62,10 @@ public:
private:
ast_manager & m_manager;
bv_util m_bv;
simplifier & m_simplifier;
arith_simplifier_plugin * m_arith_simp;
bv_simplifier_plugin * m_bv_simp;
basic_simplifier_plugin * m_basic_simp;
obj_hashtable<func_decl> * m_forbidden_set;
bool is_forbidden(func_decl * f) const { return m_forbidden_set != 0 && m_forbidden_set->contains(f); }
@ -99,7 +99,6 @@ public:
arith_simplifier_plugin * get_arith_simp() const;
bv_simplifier_plugin * get_bv_simp() const;
basic_simplifier_plugin * get_basic_simp() const;
bool is_macro_head(expr * n, unsigned num_decls) const;
bool is_left_simple_macro(expr * n, unsigned num_decls, app_ref & head, expr_ref & def) const;

View file

@ -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);

View file

@ -194,7 +194,7 @@ bool arith_rewriter::is_bound(expr * arg1, expr * arg2, op_kind kind, expr_ref &
}
}
expr* t1, *t2;
bool is_int;
bool is_int = false;
if (m_util.is_mod(arg2)) {
std::swap(arg1, arg2);
switch (kind) {

View file

@ -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) {

View file

@ -315,6 +315,8 @@ protected:
template<bool ProofGen>
void process_app(app * t, frame & fr);
bool constant_fold(app* t, frame& fr);
template<bool ProofGen>
void process_quantifier(quantifier * q, frame & fr);

View file

@ -174,6 +174,37 @@ bool rewriter_tpl<Config>::visit(expr * t, unsigned max_depth) {
}
}
template<typename Config>
bool rewriter_tpl<Config>::constant_fold(app * t, frame & fr) {
if (fr.m_i == 1 && m().is_ite(t)) {
expr * cond = result_stack()[fr.m_spos].get();
expr* arg = 0;
if (m().is_true(cond)) {
arg = t->get_arg(1);
}
else if (m().is_false(cond)) {
arg = t->get_arg(2);
}
if (arg) {
result_stack().shrink(fr.m_spos);
result_stack().push_back(arg);
fr.m_state = REWRITE_BUILTIN;
if (visit<false>(arg, fr.m_max_depth)) {
m_r = result_stack().back();
result_stack().pop_back();
result_stack().pop_back();
result_stack().push_back(m_r);
cache_result<false>(t, m_r, m_pr, fr.m_cache_result);
frame_stack().pop_back();
set_new_child_flag(t);
}
m_r = 0;
return true;
}
}
return false;
}
template<typename Config>
template<bool ProofGen>
void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
@ -183,16 +214,10 @@ void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
case PROCESS_CHILDREN: {
unsigned num_args = t->get_num_args();
while (fr.m_i < num_args) {
expr * arg = t->get_arg(fr.m_i);
if (fr.m_i >= 1 && m().is_ite(t) && !ProofGen) {
expr * cond = result_stack()[fr.m_spos].get();
if (m().is_true(cond)) {
arg = t->get_arg(1);
}
else if (m().is_false(cond)) {
arg = t->get_arg(2);
}
if (!ProofGen && constant_fold(t, fr)) {
return;
}
expr * arg = t->get_arg(fr.m_i);
fr.m_i++;
if (!visit<ProofGen>(arg, fr.m_max_depth))
return;

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

@ -12,6 +12,7 @@ Abstract:
Author:
Nikolaj Bjorner (nbjorner) 2015-12-5
Murphy Berzish 2017-02-21
Notes:
@ -59,7 +60,12 @@ expr_ref sym_expr::accept(expr* e) {
}
std::ostream& sym_expr::display(std::ostream& out) const {
return out << m_t;
switch (m_ty) {
case t_char: return out << m_t;
case t_range: return out << m_t << ":" << m_s;
case t_pred: return out << m_t;
}
return out << "expression type not recognized";
}
struct display_expr1 {
@ -236,6 +242,7 @@ eautomaton* re2automaton::re2aut(expr* e) {
unsigned nb = s1.num_bits();
expr_ref _start(bv.mk_numeral(start, nb), m);
expr_ref _stop(bv.mk_numeral(stop, nb), m);
TRACE("seq", tout << "Range: " << start << " " << stop << "\n";);
a = alloc(eautomaton, sm, sym_expr::mk_range(_start, _stop));
return a.detach();
}
@ -509,15 +516,66 @@ br_status seq_rewriter::mk_seq_length(expr* a, expr_ref& result) {
br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& result) {
zstring s;
rational pos, len;
if (m_util.str.is_string(a, s) && m_autil.is_numeral(b, pos) && m_autil.is_numeral(c, len) &&
pos.is_unsigned() && len.is_unsigned() && pos.get_unsigned() + len.get_unsigned() <= s.length()) {
unsigned _pos = pos.get_unsigned();
unsigned _len = len.get_unsigned();
result = m_util.str.mk_string(s.extract(_pos, _len));
bool constantBase = m_util.str.is_string(a, s);
bool constantPos = m_autil.is_numeral(b, pos);
bool constantLen = m_autil.is_numeral(c, len);
// case 1: pos<0 or len<=0
// rewrite to ""
if ( (constantPos && pos.is_neg()) || (constantLen && !len.is_pos()) ) {
result = m_util.str.mk_empty(m().get_sort(a));
return BR_DONE;
}
// case 1.1: pos >= length(base)
// rewrite to ""
if (constantBase && constantPos && pos >= rational(s.length())) {
result = m_util.str.mk_empty(m().get_sort(a));
return BR_DONE;
}
constantPos &= pos.is_unsigned();
constantLen &= len.is_unsigned();
if (constantBase && constantPos && constantLen) {
if (pos.get_unsigned() + len.get_unsigned() >= s.length()) {
// case 2: pos+len goes past the end of the string
unsigned _len = s.length() - pos.get_unsigned() + 1;
result = m_util.str.mk_string(s.extract(pos.get_unsigned(), _len));
} else {
// case 3: pos+len still within string
result = m_util.str.mk_string(s.extract(pos.get_unsigned(), len.get_unsigned()));
}
return BR_DONE;
}
if (constantPos && constantLen) {
unsigned _pos = pos.get_unsigned();
unsigned _len = len.get_unsigned();
SASSERT(_len > 0);
expr_ref_vector as(m()), bs(m());
m_util.str.get_concat(a, as);
for (unsigned i = 0; i < as.size() && _len > 0; ++i) {
if (m_util.str.is_unit(as[i].get())) {
if (_pos == 0) {
bs.push_back(as[i].get());
--_len;
}
else {
--_pos;
}
}
else {
return BR_FAILED;
}
}
result = m_util.str.mk_concat(bs);
return BR_DONE;
}
return BR_FAILED;
}
br_status seq_rewriter::mk_seq_contains(expr* a, expr* b, expr_ref& result) {
zstring c, d;
if (m_util.str.is_string(a, c) && m_util.str.is_string(b, d)) {
@ -594,19 +652,77 @@ br_status seq_rewriter::mk_seq_contains(expr* a, expr* b, expr_ref& result) {
result = m().mk_true();
return BR_DONE;
}
bool all_units = true;
for (unsigned i = 0; i < bs.size(); ++i) {
all_units = m_util.str.is_unit(bs[i].get());
}
for (unsigned i = 0; i < as.size(); ++i) {
all_units = m_util.str.is_unit(as[i].get());
}
if (all_units) {
if (as.size() < bs.size()) {
result = m().mk_false();
return BR_DONE;
}
expr_ref_vector ors(m());
for (unsigned i = 0; i < as.size() - bs.size() + 1; ++i) {
expr_ref_vector ands(m());
for (unsigned j = 0; j < bs.size(); ++j) {
ands.push_back(m().mk_eq(as[i + j].get(), bs[j].get()));
}
ors.push_back(::mk_and(ands));
}
result = ::mk_or(ors);
return BR_REWRITE_FULL;
}
return BR_FAILED;
}
/*
* (str.at s i), constants s/i, i < 0 or i >= |s| ==> (str.at s i) = ""
*/
br_status seq_rewriter::mk_seq_at(expr* a, expr* b, expr_ref& result) {
zstring c;
rational r;
if (m_util.str.is_string(a, c) && m_autil.is_numeral(b, r) && r.is_unsigned()) {
unsigned j = r.get_unsigned();
if (j < c.length()) {
result = m_util.str.mk_string(c.extract(j, 1));
if (m_autil.is_numeral(b, r)) {
if (r.is_neg()) {
result = m_util.str.mk_empty(m().get_sort(a));
return BR_DONE;
}
unsigned len = 0;
bool bounded = min_length(1, &a, len);
if (bounded && r >= rational(len)) {
result = m_util.str.mk_empty(m().get_sort(a));
return BR_DONE;
}
if (m_util.str.is_string(a, c)) {
if (r.is_unsigned() && r < rational(c.length())) {
result = m_util.str.mk_string(c.extract(r.get_unsigned(), 1));
}
else {
result = m_util.str.mk_empty(m().get_sort(a));
}
return BR_DONE;
}
if (r.is_unsigned()) {
len = r.get_unsigned();
expr_ref_vector as(m());
m_util.str.get_concat(a, as);
for (unsigned i = 0; i < as.size(); ++i) {
if (m_util.str.is_unit(as[i].get())) {
if (len == 0) {
result = as[i].get();
return BR_DONE;
}
--len;
}
else {
return BR_FAILED;
}
}
}
}
return BR_FAILED;
}
@ -664,6 +780,7 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
bool isc2 = m_util.str.is_string(b, s2);
if (isc1 && isc2) {
result = m().mk_bool_val(s1.prefixof(s2));
TRACE("seq", tout << result << "\n";);
return BR_DONE;
}
if (m_util.str.is_empty(a)) {
@ -677,6 +794,7 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
expr_ref_vector as(m()), bs(m());
if (a1 != b1 && isc1 && isc2) {
TRACE("seq", tout << s1 << " " << s2 << "\n";);
if (s1.length() <= s2.length()) {
if (s1.prefixof(s2)) {
if (a == a1) {
@ -721,26 +839,27 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
m_util.str.get_concat(a, as);
m_util.str.get_concat(b, bs);
unsigned i = 0;
bool all_values = true;
expr_ref_vector eqs(m());
for (; i < as.size() && i < bs.size(); ++i) {
expr* a = as[i].get(), *b = bs[i].get();
if (a == b) {
continue;
}
all_values &= m().is_value(a) && m().is_value(b);
if (all_values) {
result = m().mk_false();
return BR_DONE;
}
if (m_util.str.is_unit(a) && m_util.str.is_unit(b)) {
eqs.push_back(m().mk_eq(a, b));
continue;
}
if (m().is_value(a) && m().is_value(b) && m_util.str.is_string(a) && m_util.str.is_string(b)) {
TRACE("seq", tout << mk_pp(a, m()) << " != " << mk_pp(b, m()) << "\n";);
result = m().mk_false();
return BR_DONE;
}
break;
}
if (i == as.size()) {
result = mk_and(eqs);
TRACE("seq", tout << result << "\n";);
if (m().is_true(result)) {
return BR_DONE;
}
@ -752,6 +871,7 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
eqs.push_back(m().mk_eq(m_util.str.mk_empty(m().get_sort(a)), as[j].get()));
}
result = mk_and(eqs);
TRACE("seq", tout << result << "\n";);
return BR_REWRITE3;
}
if (i > 0) {
@ -759,6 +879,7 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
a = m_util.str.mk_concat(as.size() - i, as.c_ptr() + i);
b = m_util.str.mk_concat(bs.size() - i, bs.c_ptr() + i);
result = m_util.str.mk_prefix(a, b);
TRACE("seq", tout << result << "\n";);
return BR_DONE;
}
else {
@ -1343,6 +1464,7 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
zstring s;
bool lchange = false;
SASSERT(lhs.empty());
TRACE("seq", tout << ls << "\n"; tout << rs << "\n";);
// solve from back
while (true) {
while (!rs.empty() && m_util.str.is_empty(rs.back())) {
@ -1460,9 +1582,11 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
head2 < rs.size() &&
m_util.str.is_string(ls[head1].get(), s1) &&
m_util.str.is_string(rs[head2].get(), s2)) {
TRACE("seq", tout << s1 << " - " << s2 << " " << s1.length() << " " << s2.length() << "\n";);
unsigned l = std::min(s1.length(), s2.length());
for (unsigned i = 0; i < l; ++i) {
if (s1[i] != s2[i]) {
TRACE("seq", tout << "different at position " << i << " " << s1[i] << " " << s2[i] << "\n";);
return false;
}
}

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,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() {

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.
@ -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

View file

@ -126,13 +126,14 @@ static bool is_escape_char(char const *& s, unsigned& result) {
zstring::zstring(encoding enc): m_encoding(enc) {}
zstring::zstring(char const* s, encoding enc): m_encoding(enc) {
unsigned mask = 0xFF; // TBD for UTF
while (*s) {
unsigned ch;
if (is_escape_char(s, ch)) {
m_buffer.push_back(ch);
m_buffer.push_back(ch & mask);
}
else {
m_buffer.push_back(*s);
m_buffer.push_back(*s & mask);
++s;
}
}

View file

@ -304,6 +304,7 @@ public:
app* mk_to_re(expr* s) { return m.mk_app(m_fid, OP_SEQ_TO_RE, 1, &s); }
app* mk_in_re(expr* s, expr* r) { return m.mk_app(m_fid, OP_SEQ_IN_RE, s, r); }
app* mk_range(expr* s1, expr* s2) { return m.mk_app(m_fid, OP_RE_RANGE, s1, s2); }
app* mk_concat(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_CONCAT, r1, r2); }
app* mk_union(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_UNION, r1, r2); }
app* mk_inter(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_INTERSECT, r1, r2); }

View file

@ -1517,13 +1517,24 @@ void bv_simplifier_plugin::mk_bv2int(expr * arg, sort* range, expr_ref & result)
result = m_arith.mk_add(tmp1, tmp2);
}
// commented out to reproduce bug in reduction of int2bv/bv2int
else if (m_util.is_concat(arg)) {
expr_ref tmp1(m_manager), tmp2(m_manager);
unsigned sz2 = get_bv_size(to_app(arg)->get_arg(1));
mk_bv2int(to_app(arg)->get_arg(0), range, tmp1);
mk_bv2int(to_app(arg)->get_arg(1), range, tmp2);
tmp1 = m_arith.mk_mul(m_arith.mk_numeral(power(numeral(2), sz2), true), tmp1);
result = m_arith.mk_add(tmp1, tmp2);
else if (m_util.is_concat(arg) && to_app(arg)->get_num_args() > 0) {
expr_ref_vector args(m_manager);
unsigned num_args = to_app(arg)->get_num_args();
for (unsigned i = 0; i < num_args; ++i) {
expr_ref tmp(m_manager);
mk_bv2int(to_app(arg)->get_arg(i), range, tmp);
args.push_back(tmp);
}
unsigned sz = get_bv_size(to_app(arg)->get_arg(num_args-1));
for (unsigned i = num_args - 1; i > 0; ) {
expr_ref tmp(m_manager);
--i;
tmp = args[i].get();
tmp = m_arith.mk_mul(m_arith.mk_numeral(power(numeral(2), sz), true), tmp);
args[i] = tmp;
sz += get_bv_size(to_app(arg)->get_arg(i));
}
result = m_arith.mk_add(args.size(), args.c_ptr());
}
else {
parameter parameter(range);

View file

@ -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);
}

View file

@ -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);

View file

@ -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);