mirror of
https://github.com/Z3Prover/z3
synced 2025-06-28 08:58:44 +00:00
Merge branch 'master' of https://github.com/Z3Prover/z3
This commit is contained in:
commit
d47b2bae4d
41 changed files with 758 additions and 454 deletions
|
@ -30,6 +30,17 @@ Revision History:
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
Z3_model Z3_API Z3_mk_model(Z3_context c) {
|
||||||
|
Z3_TRY;
|
||||||
|
LOG_Z3_mk_model(c);
|
||||||
|
RESET_ERROR_CODE();
|
||||||
|
Z3_model_ref * m_ref = alloc(Z3_model_ref, *mk_c(c));
|
||||||
|
m_ref->m_model = alloc(model, mk_c(c)->m());
|
||||||
|
mk_c(c)->save_object(m_ref);
|
||||||
|
RETURN_Z3(of_model(m_ref));
|
||||||
|
Z3_CATCH_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
void Z3_API Z3_model_inc_ref(Z3_context c, Z3_model m) {
|
void Z3_API Z3_model_inc_ref(Z3_context c, Z3_model m) {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_model_inc_ref(c, m);
|
LOG_Z3_model_inc_ref(c, m);
|
||||||
|
@ -224,6 +235,31 @@ extern "C" {
|
||||||
Z3_CATCH_RETURN(0);
|
Z3_CATCH_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Z3_func_interp Z3_API Z3_add_func_interp(Z3_context c, Z3_model m, Z3_func_decl f, Z3_ast else_val) {
|
||||||
|
Z3_TRY;
|
||||||
|
LOG_Z3_add_func_interp(c, m, f, else_val);
|
||||||
|
RESET_ERROR_CODE();
|
||||||
|
func_decl* d = to_func_decl(f);
|
||||||
|
model* mdl = to_model_ref(m);
|
||||||
|
Z3_func_interp_ref * f_ref = alloc(Z3_func_interp_ref, *mk_c(c), mdl);
|
||||||
|
f_ref->m_func_interp = alloc(func_interp, mk_c(c)->m(), d->get_arity());
|
||||||
|
mk_c(c)->save_object(f_ref);
|
||||||
|
mdl->register_decl(d, f_ref->m_func_interp);
|
||||||
|
f_ref->m_func_interp->set_else(to_expr(else_val));
|
||||||
|
RETURN_Z3(of_func_interp(f_ref));
|
||||||
|
Z3_CATCH_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Z3_API Z3_add_const_interp(Z3_context c, Z3_model m, Z3_func_decl f, Z3_ast a) {
|
||||||
|
Z3_TRY;
|
||||||
|
LOG_Z3_add_const_interp(c, m, f, a);
|
||||||
|
RESET_ERROR_CODE();
|
||||||
|
func_decl* d = to_func_decl(f);
|
||||||
|
model* mdl = to_model_ref(m);
|
||||||
|
mdl->register_decl(d, to_expr(a));
|
||||||
|
Z3_CATCH;
|
||||||
|
}
|
||||||
|
|
||||||
void Z3_API Z3_func_interp_inc_ref(Z3_context c, Z3_func_interp f) {
|
void Z3_API Z3_func_interp_inc_ref(Z3_context c, Z3_func_interp f) {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_func_interp_inc_ref(c, f);
|
LOG_Z3_func_interp_inc_ref(c, f);
|
||||||
|
@ -283,6 +319,15 @@ extern "C" {
|
||||||
Z3_CATCH_RETURN(0);
|
Z3_CATCH_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Z3_API Z3_func_interp_set_else(Z3_context c, Z3_func_interp f, Z3_ast else_value) {
|
||||||
|
Z3_TRY;
|
||||||
|
LOG_Z3_func_interp_set_else(c, f, else_value);
|
||||||
|
RESET_ERROR_CODE();
|
||||||
|
// CHECK_NON_NULL(f, 0);
|
||||||
|
to_func_interp_ref(f)->set_else(to_expr(else_value));
|
||||||
|
Z3_CATCH;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned Z3_API Z3_func_interp_get_arity(Z3_context c, Z3_func_interp f) {
|
unsigned Z3_API Z3_func_interp_get_arity(Z3_context c, Z3_func_interp f) {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_func_interp_get_arity(c, f);
|
LOG_Z3_func_interp_get_arity(c, f);
|
||||||
|
@ -292,6 +337,24 @@ extern "C" {
|
||||||
Z3_CATCH_RETURN(0);
|
Z3_CATCH_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Z3_API Z3_func_interp_add_entry(Z3_context c, Z3_func_interp fi, Z3_ast_vector args, Z3_ast value) {
|
||||||
|
Z3_TRY;
|
||||||
|
LOG_Z3_func_interp_add_entry(c, fi, args, value);
|
||||||
|
//CHECK_NON_NULL(fi, void);
|
||||||
|
//CHECK_NON_NULL(args, void);
|
||||||
|
//CHECK_NON_NULL(value, void);
|
||||||
|
func_interp* _fi = to_func_interp_ref(fi);
|
||||||
|
expr* _value = to_expr(value);
|
||||||
|
if (to_ast_vector_ref(args).size() != _fi->get_arity()) {
|
||||||
|
SET_ERROR_CODE(Z3_IOB);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// check sorts of value
|
||||||
|
expr* const* _args = (expr* const*) to_ast_vector_ref(args).c_ptr();
|
||||||
|
_fi->insert_entry(_args, _value);
|
||||||
|
Z3_CATCH;
|
||||||
|
}
|
||||||
|
|
||||||
void Z3_API Z3_func_entry_inc_ref(Z3_context c, Z3_func_entry e) {
|
void Z3_API Z3_func_entry_inc_ref(Z3_context c, Z3_func_entry e) {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_func_entry_inc_ref(c, e);
|
LOG_Z3_func_entry_inc_ref(c, e);
|
||||||
|
|
|
@ -1731,6 +1731,14 @@ namespace z3 {
|
||||||
expr else_value() const { Z3_ast r = Z3_func_interp_get_else(ctx(), m_interp); check_error(); return expr(ctx(), r); }
|
expr else_value() const { Z3_ast r = Z3_func_interp_get_else(ctx(), m_interp); check_error(); return expr(ctx(), r); }
|
||||||
unsigned num_entries() const { unsigned r = Z3_func_interp_get_num_entries(ctx(), m_interp); check_error(); return r; }
|
unsigned num_entries() const { unsigned r = Z3_func_interp_get_num_entries(ctx(), m_interp); check_error(); return r; }
|
||||||
func_entry entry(unsigned i) const { Z3_func_entry e = Z3_func_interp_get_entry(ctx(), m_interp, i); check_error(); return func_entry(ctx(), e); }
|
func_entry entry(unsigned i) const { Z3_func_entry e = Z3_func_interp_get_entry(ctx(), m_interp, i); check_error(); return func_entry(ctx(), e); }
|
||||||
|
void add_entry(expr_vector const& args, expr& value) {
|
||||||
|
Z3_func_interp_add_entry(ctx(), m_interp, args, value);
|
||||||
|
check_error();
|
||||||
|
}
|
||||||
|
void set_else(expr& value) {
|
||||||
|
Z3_func_interp_set_else(ctx(), m_interp, value);
|
||||||
|
check_error();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class model : public object {
|
class model : public object {
|
||||||
|
@ -1740,6 +1748,7 @@ namespace z3 {
|
||||||
Z3_model_inc_ref(ctx(), m);
|
Z3_model_inc_ref(ctx(), m);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
model(context & c):object(c) { init(Z3_mk_model(c)); }
|
||||||
model(context & c, Z3_model m):object(c) { init(m); }
|
model(context & c, Z3_model m):object(c) { init(m); }
|
||||||
model(model const & s):object(s) { init(s.m_model); }
|
model(model const & s):object(s) { init(s.m_model); }
|
||||||
~model() { Z3_model_dec_ref(ctx(), m_model); }
|
~model() { Z3_model_dec_ref(ctx(), m_model); }
|
||||||
|
@ -1795,6 +1804,17 @@ namespace z3 {
|
||||||
return 0 != Z3_model_has_interp(ctx(), m_model, f);
|
return 0 != Z3_model_has_interp(ctx(), m_model, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func_interp add_func_interp(func_decl& f, expr& else_val) {
|
||||||
|
Z3_func_interp r = Z3_add_func_interp(ctx(), m_model, f, else_val);
|
||||||
|
check_error();
|
||||||
|
return func_interp(ctx(), r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_const_interp(func_decl& f, expr& value) {
|
||||||
|
Z3_add_const_interp(ctx(), m_model, f, value);
|
||||||
|
check_error();
|
||||||
|
}
|
||||||
|
|
||||||
friend std::ostream & operator<<(std::ostream & out, model const & m);
|
friend std::ostream & operator<<(std::ostream & out, model const & m);
|
||||||
};
|
};
|
||||||
inline std::ostream & operator<<(std::ostream & out, model const & m) { out << Z3_model_to_string(m.ctx(), m); return out; }
|
inline std::ostream & operator<<(std::ostream & out, model const & m) { out << Z3_model_to_string(m.ctx(), m); return out; }
|
||||||
|
|
|
@ -4680,6 +4680,14 @@ extern "C" {
|
||||||
|
|
||||||
/** @name Models */
|
/** @name Models */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Create a fresh model object. It has reference count 0.
|
||||||
|
|
||||||
|
def_API('Z3_mk_model', MODEL, (_in(CONTEXT),))
|
||||||
|
*/
|
||||||
|
Z3_model Z3_API Z3_mk_model(Z3_context c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Increment the reference counter of the given model.
|
\brief Increment the reference counter of the given model.
|
||||||
|
|
||||||
|
@ -4850,6 +4858,26 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
Z3_func_decl Z3_API Z3_get_as_array_func_decl(Z3_context c, Z3_ast a);
|
Z3_func_decl Z3_API Z3_get_as_array_func_decl(Z3_context c, Z3_ast a);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Create a fresh func_interp object, add it to a model for a specified function.
|
||||||
|
It has reference count 0.
|
||||||
|
|
||||||
|
\param c context
|
||||||
|
\param m model
|
||||||
|
\param f function declaration
|
||||||
|
\param default_value default value for function interpretation
|
||||||
|
|
||||||
|
def_API('Z3_add_func_interp', FUNC_INTERP, (_in(CONTEXT), _in(MODEL), _in(FUNC_DECL), _in(AST)))
|
||||||
|
*/
|
||||||
|
Z3_func_interp Z3_API Z3_add_func_interp(Z3_context c, Z3_model m, Z3_func_decl f, Z3_ast default_value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Add a constant interpretation.
|
||||||
|
|
||||||
|
def_API('Z3_add_const_interp', VOID, (_in(CONTEXT), _in(MODEL), _in(FUNC_DECL), _in(AST)))
|
||||||
|
*/
|
||||||
|
void Z3_API Z3_add_const_interp(Z3_context c, Z3_model m, Z3_func_decl f, Z3_ast a);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Increment the reference counter of the given Z3_func_interp object.
|
\brief Increment the reference counter of the given Z3_func_interp object.
|
||||||
|
|
||||||
|
@ -4897,6 +4925,16 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
Z3_ast Z3_API Z3_func_interp_get_else(Z3_context c, Z3_func_interp f);
|
Z3_ast Z3_API Z3_func_interp_get_else(Z3_context c, Z3_func_interp f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Return the 'else' value of the given function interpretation.
|
||||||
|
|
||||||
|
A function interpretation is represented as a finite map and an 'else' value.
|
||||||
|
This procedure can be used to update the 'else' value.
|
||||||
|
|
||||||
|
def_API('Z3_func_interp_set_else', VOID, (_in(CONTEXT), _in(FUNC_INTERP), _in(AST)))
|
||||||
|
*/
|
||||||
|
void Z3_API Z3_func_interp_set_else(Z3_context c, Z3_func_interp f, Z3_ast else_value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Return the arity (number of arguments) of the given function interpretation.
|
\brief Return the arity (number of arguments) of the given function interpretation.
|
||||||
|
|
||||||
|
@ -4904,6 +4942,22 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
unsigned Z3_API Z3_func_interp_get_arity(Z3_context c, Z3_func_interp f);
|
unsigned Z3_API Z3_func_interp_get_arity(Z3_context c, Z3_func_interp f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief add a function entry to a function interpretation.
|
||||||
|
|
||||||
|
\param c logical context
|
||||||
|
\param fi a function interpregation to be updated.
|
||||||
|
\param args list of arguments. They should be constant values (such as integers) and be of the same types as the domain of the function.
|
||||||
|
\param value value of the function when the parameters match args.
|
||||||
|
|
||||||
|
It is assumed that entries added to a function cover disjoint arguments.
|
||||||
|
If an two entries are added with the same arguments, only the second insertion survives and the
|
||||||
|
first inserted entry is removed.
|
||||||
|
|
||||||
|
def_API('Z3_func_interp_add_entry', VOID, (_in(CONTEXT), _in(FUNC_INTERP), _in(AST_VECTOR), _in(AST)))
|
||||||
|
*/
|
||||||
|
void Z3_API Z3_func_interp_add_entry(Z3_context c, Z3_func_interp fi, Z3_ast_vector args, Z3_ast value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Increment the reference counter of the given Z3_func_entry object.
|
\brief Increment the reference counter of the given Z3_func_entry object.
|
||||||
|
|
||||||
|
|
|
@ -215,18 +215,8 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
|
||||||
m_e = m->mk_const(e_decl);
|
m_e = m->mk_const(e_decl);
|
||||||
m->inc_ref(m_e);
|
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);
|
|
||||||
|
|
||||||
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_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);
|
|
||||||
MK_UNARY(m_mod_0_decl, "mod0", OP_MOD_0, i);
|
|
||||||
MK_UNARY(m_u_asin_decl, "asin-u", OP_U_ASIN, r);
|
MK_UNARY(m_u_asin_decl, "asin-u", OP_U_ASIN, r);
|
||||||
MK_UNARY(m_u_acos_decl, "acos-u", OP_U_ACOS, r);
|
MK_UNARY(m_u_acos_decl, "acos-u", OP_U_ACOS, r);
|
||||||
}
|
}
|
||||||
|
@ -279,12 +269,7 @@ arith_decl_plugin::arith_decl_plugin():
|
||||||
m_atanh_decl(0),
|
m_atanh_decl(0),
|
||||||
m_pi(0),
|
m_pi(0),
|
||||||
m_e(0),
|
m_e(0),
|
||||||
m_0_pw_0_int(0),
|
|
||||||
m_0_pw_0_real(0),
|
|
||||||
m_neg_root_decl(0),
|
m_neg_root_decl(0),
|
||||||
m_div_0_decl(0),
|
|
||||||
m_idiv_0_decl(0),
|
|
||||||
m_mod_0_decl(0),
|
|
||||||
m_u_asin_decl(0),
|
m_u_asin_decl(0),
|
||||||
m_u_acos_decl(0),
|
m_u_acos_decl(0),
|
||||||
m_convert_int_numerals_to_real(false) {
|
m_convert_int_numerals_to_real(false) {
|
||||||
|
@ -339,12 +324,7 @@ void arith_decl_plugin::finalize() {
|
||||||
DEC_REF(m_atanh_decl);
|
DEC_REF(m_atanh_decl);
|
||||||
DEC_REF(m_pi);
|
DEC_REF(m_pi);
|
||||||
DEC_REF(m_e);
|
DEC_REF(m_e);
|
||||||
DEC_REF(m_0_pw_0_int);
|
|
||||||
DEC_REF(m_0_pw_0_real);
|
|
||||||
DEC_REF(m_neg_root_decl);
|
DEC_REF(m_neg_root_decl);
|
||||||
DEC_REF(m_div_0_decl);
|
|
||||||
DEC_REF(m_idiv_0_decl);
|
|
||||||
DEC_REF(m_mod_0_decl);
|
|
||||||
DEC_REF(m_u_asin_decl);
|
DEC_REF(m_u_asin_decl);
|
||||||
DEC_REF(m_u_acos_decl);
|
DEC_REF(m_u_acos_decl);
|
||||||
m_manager->dec_array_ref(m_small_ints.size(), m_small_ints.c_ptr());
|
m_manager->dec_array_ref(m_small_ints.size(), m_small_ints.c_ptr());
|
||||||
|
@ -392,12 +372,12 @@ inline func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, bool is_real) {
|
||||||
case OP_ATANH: return m_atanh_decl;
|
case OP_ATANH: return m_atanh_decl;
|
||||||
case OP_PI: return m_pi->get_decl();
|
case OP_PI: return m_pi->get_decl();
|
||||||
case OP_E: return m_e->get_decl();
|
case OP_E: return m_e->get_decl();
|
||||||
case OP_0_PW_0_INT: return m_0_pw_0_int->get_decl();
|
//case OP_0_PW_0_INT: return m_0_pw_0_int->get_decl();
|
||||||
case OP_0_PW_0_REAL: return m_0_pw_0_real->get_decl();
|
//case OP_0_PW_0_REAL: return m_0_pw_0_real->get_decl();
|
||||||
case OP_NEG_ROOT: return m_neg_root_decl;
|
case OP_NEG_ROOT: return m_neg_root_decl;
|
||||||
case OP_DIV_0: return m_div_0_decl;
|
//case OP_DIV_0: return m_div_0_decl;
|
||||||
case OP_IDIV_0: return m_idiv_0_decl;
|
//case OP_IDIV_0: return m_idiv_0_decl;
|
||||||
case OP_MOD_0: return m_mod_0_decl;
|
//case OP_MOD_0: return m_mod_0_decl;
|
||||||
case OP_U_ASIN: return m_u_asin_decl;
|
case OP_U_ASIN: return m_u_asin_decl;
|
||||||
case OP_U_ACOS: return m_u_acos_decl;
|
case OP_U_ACOS: return m_u_acos_decl;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
|
@ -489,9 +469,9 @@ static bool has_real_arg(ast_manager * m, unsigned num_args, expr * const * args
|
||||||
static bool is_const_op(decl_kind k) {
|
static bool is_const_op(decl_kind k) {
|
||||||
return
|
return
|
||||||
k == OP_PI ||
|
k == OP_PI ||
|
||||||
k == OP_E ||
|
k == OP_E;
|
||||||
k == OP_0_PW_0_INT ||
|
//k == OP_0_PW_0_INT ||
|
||||||
k == OP_0_PW_0_REAL;
|
//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,
|
||||||
|
|
|
@ -70,12 +70,7 @@ enum arith_op_kind {
|
||||||
OP_PI,
|
OP_PI,
|
||||||
OP_E,
|
OP_E,
|
||||||
// under-specified symbols
|
// under-specified symbols
|
||||||
OP_0_PW_0_INT, // 0^0 for integers
|
|
||||||
OP_0_PW_0_REAL, // 0^0 for reals
|
|
||||||
OP_NEG_ROOT, // x^n when n is even and x is negative
|
OP_NEG_ROOT, // x^n when n is even and x is negative
|
||||||
OP_DIV_0, // x/0
|
|
||||||
OP_IDIV_0, // x div 0
|
|
||||||
OP_MOD_0, // x mod 0
|
|
||||||
OP_U_ASIN, // asin(x) for x < -1 or x > 1
|
OP_U_ASIN, // asin(x) for x < -1 or x > 1
|
||||||
OP_U_ACOS, // acos(x) for x < -1 or x > 1
|
OP_U_ACOS, // acos(x) for x < -1 or x > 1
|
||||||
LAST_ARITH_OP
|
LAST_ARITH_OP
|
||||||
|
@ -141,12 +136,7 @@ protected:
|
||||||
app * m_pi;
|
app * m_pi;
|
||||||
app * m_e;
|
app * m_e;
|
||||||
|
|
||||||
app * m_0_pw_0_int;
|
|
||||||
app * m_0_pw_0_real;
|
|
||||||
func_decl * m_neg_root_decl;
|
func_decl * m_neg_root_decl;
|
||||||
func_decl * m_div_0_decl;
|
|
||||||
func_decl * m_idiv_0_decl;
|
|
||||||
func_decl * m_mod_0_decl;
|
|
||||||
func_decl * m_u_asin_decl;
|
func_decl * m_u_asin_decl;
|
||||||
func_decl * m_u_acos_decl;
|
func_decl * m_u_acos_decl;
|
||||||
ptr_vector<app> m_small_ints;
|
ptr_vector<app> m_small_ints;
|
||||||
|
@ -207,10 +197,6 @@ public:
|
||||||
|
|
||||||
app * mk_e() const { return m_e; }
|
app * mk_e() const { return m_e; }
|
||||||
|
|
||||||
app * mk_0_pw_0_int() const { return m_0_pw_0_int; }
|
|
||||||
|
|
||||||
app * mk_0_pw_0_real() const { return m_0_pw_0_real; }
|
|
||||||
|
|
||||||
virtual expr * get_some_value(sort * s);
|
virtual expr * get_some_value(sort * s);
|
||||||
|
|
||||||
virtual bool is_considered_uninterpreted(func_decl * f) {
|
virtual bool is_considered_uninterpreted(func_decl * f) {
|
||||||
|
@ -218,12 +204,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
switch (f->get_decl_kind())
|
switch (f->get_decl_kind())
|
||||||
{
|
{
|
||||||
case OP_0_PW_0_INT:
|
|
||||||
case OP_0_PW_0_REAL:
|
|
||||||
case OP_NEG_ROOT:
|
case OP_NEG_ROOT:
|
||||||
case OP_DIV_0:
|
|
||||||
case OP_IDIV_0:
|
|
||||||
case OP_MOD_0:
|
|
||||||
case OP_U_ASIN:
|
case OP_U_ASIN:
|
||||||
case OP_U_ACOS:
|
case OP_U_ACOS:
|
||||||
return true;
|
return true;
|
||||||
|
@ -276,9 +257,9 @@ public:
|
||||||
bool is_uminus(expr const * n) const { return is_app_of(n, m_afid, OP_UMINUS); }
|
bool is_uminus(expr const * n) const { return is_app_of(n, m_afid, OP_UMINUS); }
|
||||||
bool is_mul(expr const * n) const { return is_app_of(n, m_afid, OP_MUL); }
|
bool is_mul(expr const * n) const { return is_app_of(n, m_afid, OP_MUL); }
|
||||||
bool is_div(expr const * n) const { return is_app_of(n, m_afid, OP_DIV); }
|
bool is_div(expr const * n) const { return is_app_of(n, m_afid, OP_DIV); }
|
||||||
bool is_div0(expr const * n) const { return is_app_of(n, m_afid, OP_DIV_0); }
|
//bool is_div0(expr const * n) const { return is_app_of(n, m_afid, OP_DIV_0); }
|
||||||
bool is_idiv(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV); }
|
bool is_idiv(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV); }
|
||||||
bool is_idiv0(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV_0); }
|
//bool is_idiv0(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV_0); }
|
||||||
bool is_mod(expr const * n) const { return is_app_of(n, m_afid, OP_MOD); }
|
bool is_mod(expr const * n) const { return is_app_of(n, m_afid, OP_MOD); }
|
||||||
bool is_rem(expr const * n) const { return is_app_of(n, m_afid, OP_REM); }
|
bool is_rem(expr const * n) const { return is_app_of(n, m_afid, OP_REM); }
|
||||||
bool is_to_real(expr const * n) const { return is_app_of(n, m_afid, OP_TO_REAL); }
|
bool is_to_real(expr const * n) const { return is_app_of(n, m_afid, OP_TO_REAL); }
|
||||||
|
@ -389,16 +370,16 @@ public:
|
||||||
app * mk_lt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_LT, arg1, arg2); }
|
app * mk_lt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_LT, arg1, arg2); }
|
||||||
app * mk_gt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_GT, arg1, arg2); }
|
app * mk_gt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_GT, arg1, arg2); }
|
||||||
|
|
||||||
app * mk_add(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_ADD, num_args, args); }
|
app * mk_add(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_ADD, num_args, args); }
|
||||||
app * mk_add(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2); }
|
app * mk_add(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2); }
|
||||||
app * mk_add(expr * arg1, expr * arg2, expr* arg3) { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2, arg3); }
|
app * mk_add(expr * arg1, expr * arg2, expr* arg3) const { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2, arg3); }
|
||||||
|
|
||||||
app * mk_sub(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_SUB, arg1, arg2); }
|
app * mk_sub(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_SUB, arg1, arg2); }
|
||||||
app * mk_sub(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_SUB, num_args, args); }
|
app * mk_sub(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_SUB, num_args, args); }
|
||||||
app * mk_mul(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2); }
|
app * mk_mul(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2); }
|
||||||
app * mk_mul(expr * arg1, expr * arg2, expr* arg3) { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2, arg3); }
|
app * mk_mul(expr * arg1, expr * arg2, expr* arg3) const { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2, arg3); }
|
||||||
app * mk_mul(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_MUL, num_args, args); }
|
app * mk_mul(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_MUL, num_args, args); }
|
||||||
app * mk_uminus(expr * arg) { return m_manager.mk_app(m_afid, OP_UMINUS, arg); }
|
app * mk_uminus(expr * arg) const { return m_manager.mk_app(m_afid, OP_UMINUS, arg); }
|
||||||
app * mk_div(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_DIV, arg1, arg2); }
|
app * mk_div(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_DIV, arg1, arg2); }
|
||||||
app * mk_idiv(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_IDIV, arg1, arg2); }
|
app * mk_idiv(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_IDIV, arg1, arg2); }
|
||||||
app * mk_rem(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_REM, arg1, arg2); }
|
app * mk_rem(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_REM, arg1, arg2); }
|
||||||
|
@ -425,11 +406,6 @@ public:
|
||||||
app * mk_pi() { return plugin().mk_pi(); }
|
app * mk_pi() { return plugin().mk_pi(); }
|
||||||
app * mk_e() { return plugin().mk_e(); }
|
app * mk_e() { return plugin().mk_e(); }
|
||||||
|
|
||||||
app * mk_0_pw_0_int() { return plugin().mk_0_pw_0_int(); }
|
|
||||||
app * mk_0_pw_0_real() { return plugin().mk_0_pw_0_real(); }
|
|
||||||
app * mk_div0(expr * arg) { return m_manager.mk_app(m_afid, OP_DIV_0, arg); }
|
|
||||||
app * mk_idiv0(expr * arg) { return m_manager.mk_app(m_afid, OP_IDIV_0, arg); }
|
|
||||||
app * mk_mod0(expr * arg) { return m_manager.mk_app(m_afid, OP_MOD_0, arg); }
|
|
||||||
app * mk_neg_root(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_NEG_ROOT, arg1, arg2); }
|
app * mk_neg_root(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_NEG_ROOT, arg1, arg2); }
|
||||||
app * mk_u_asin(expr * arg) { return m_manager.mk_app(m_afid, OP_U_ASIN, arg); }
|
app * mk_u_asin(expr * arg) { return m_manager.mk_app(m_afid, OP_U_ASIN, arg); }
|
||||||
app * mk_u_acos(expr * arg) { return m_manager.mk_app(m_afid, OP_U_ACOS, arg); }
|
app * mk_u_acos(expr * arg) { return m_manager.mk_app(m_afid, OP_U_ACOS, arg); }
|
||||||
|
|
|
@ -1727,7 +1727,6 @@ ast * ast_manager::register_node_core(ast * n) {
|
||||||
|
|
||||||
n->m_id = is_decl(n) ? m_decl_id_gen.mk() : m_expr_id_gen.mk();
|
n->m_id = is_decl(n) ? m_decl_id_gen.mk() : m_expr_id_gen.mk();
|
||||||
|
|
||||||
|
|
||||||
TRACE("ast", tout << "Object " << n->m_id << " was created.\n";);
|
TRACE("ast", tout << "Object " << n->m_id << " was created.\n";);
|
||||||
TRACE("mk_var_bug", tout << "mk_ast: " << n->m_id << "\n";);
|
TRACE("mk_var_bug", tout << "mk_ast: " << n->m_id << "\n";);
|
||||||
// increment reference counters
|
// increment reference counters
|
||||||
|
|
|
@ -45,7 +45,7 @@ bool macro_finder::is_macro(expr * n, app_ref & head, expr_ref & def) {
|
||||||
|
|
||||||
For case 2 & 3, the new quantifiers are stored in new_exprs and new_prs.
|
For case 2 & 3, the new quantifiers are stored in new_exprs and new_prs.
|
||||||
*/
|
*/
|
||||||
bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_dependency * dep, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
|
||||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||||
return false;
|
return false;
|
||||||
arith_simplifier_plugin * as = get_arith_simp();
|
arith_simplifier_plugin * as = get_arith_simp();
|
||||||
|
@ -78,8 +78,9 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_ex
|
||||||
proof * rw = m_manager.mk_rewrite(n, new_q);
|
proof * rw = m_manager.mk_rewrite(n, new_q);
|
||||||
new_pr = m_manager.mk_modus_ponens(pr, rw);
|
new_pr = m_manager.mk_modus_ponens(pr, rw);
|
||||||
}
|
}
|
||||||
|
expr_dependency * new_dep = dep;
|
||||||
if (m_manager.is_eq(body)) {
|
if (m_manager.is_eq(body)) {
|
||||||
return m_macro_manager.insert(head->get_decl(), new_q, new_pr);
|
return m_macro_manager.insert(head->get_decl(), new_q, new_pr, new_dep);
|
||||||
}
|
}
|
||||||
// is ge or le
|
// is ge or le
|
||||||
//
|
//
|
||||||
|
@ -111,6 +112,10 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_ex
|
||||||
new_prs.push_back(pr1);
|
new_prs.push_back(pr1);
|
||||||
new_prs.push_back(pr2);
|
new_prs.push_back(pr2);
|
||||||
}
|
}
|
||||||
|
if (dep) {
|
||||||
|
new_deps.push_back(new_dep);
|
||||||
|
new_deps.push_back(new_dep);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,8 +131,8 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_ex
|
||||||
|
|
||||||
The new quantifiers and proofs are stored in new_exprs and new_prs
|
The new quantifiers and proofs are stored in new_exprs and new_prs
|
||||||
*/
|
*/
|
||||||
static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, expr * def, quantifier * q, proof * pr,
|
static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, expr * def, quantifier * q, proof * pr, expr_dependency * dep,
|
||||||
expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps ) {
|
||||||
func_decl * f = head->get_decl();
|
func_decl * f = head->get_decl();
|
||||||
func_decl * k = m.mk_fresh_func_decl(f->get_name(), symbol::null, f->get_arity(), f->get_domain(), f->get_range());
|
func_decl * k = m.mk_fresh_func_decl(f->get_name(), symbol::null, f->get_arity(), f->get_domain(), f->get_range());
|
||||||
app * k_app = m.mk_app(k, head->get_num_args(), head->get_args());
|
app * k_app = m.mk_app(k, head->get_num_args(), head->get_args());
|
||||||
|
@ -153,6 +158,8 @@ static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, e
|
||||||
new_prs.push_back(pr1);
|
new_prs.push_back(pr1);
|
||||||
new_prs.push_back(pr2);
|
new_prs.push_back(pr2);
|
||||||
}
|
}
|
||||||
|
new_deps.push_back(dep);
|
||||||
|
new_deps.push_back(dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_finder::macro_finder(ast_manager & m, macro_manager & mm):
|
macro_finder::macro_finder(ast_manager & m, macro_manager & mm):
|
||||||
|
@ -164,57 +171,67 @@ macro_finder::macro_finder(ast_manager & m, macro_manager & mm):
|
||||||
macro_finder::~macro_finder() {
|
macro_finder::~macro_finder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool macro_finder::expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
bool macro_finder::expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
|
||||||
TRACE("macro_finder", tout << "starting expand_macros:\n";
|
TRACE("macro_finder", tout << "starting expand_macros:\n";
|
||||||
m_macro_manager.display(tout););
|
m_macro_manager.display(tout););
|
||||||
bool found_new_macro = false;
|
bool found_new_macro = false;
|
||||||
for (unsigned i = 0; i < num; i++) {
|
for (unsigned i = 0; i < num; i++) {
|
||||||
expr * n = exprs[i];
|
expr * n = exprs[i];
|
||||||
proof * pr = m_manager.proofs_enabled() ? prs[i] : 0;
|
proof * pr = m_manager.proofs_enabled() ? prs[i] : 0;
|
||||||
|
expr_dependency * depi = deps != 0 ? deps[i] : 0;
|
||||||
expr_ref new_n(m_manager), def(m_manager);
|
expr_ref new_n(m_manager), def(m_manager);
|
||||||
proof_ref new_pr(m_manager);
|
proof_ref new_pr(m_manager);
|
||||||
m_macro_manager.expand_macros(n, pr, new_n, new_pr);
|
expr_dependency_ref new_dep(m_manager);
|
||||||
|
m_macro_manager.expand_macros(n, pr, depi, new_n, new_pr, new_dep);
|
||||||
app_ref head(m_manager), t(m_manager);
|
app_ref head(m_manager), t(m_manager);
|
||||||
if (is_macro(new_n, head, def) && m_macro_manager.insert(head->get_decl(), to_quantifier(new_n.get()), new_pr)) {
|
if (is_macro(new_n, head, def) && m_macro_manager.insert(head->get_decl(), to_quantifier(new_n.get()), new_pr, new_dep)) {
|
||||||
TRACE("macro_finder_found", tout << "found new macro: " << head->get_decl()->get_name() << "\n" << new_n << "\n";);
|
TRACE("macro_finder_found", tout << "found new macro: " << head->get_decl()->get_name() << "\n" << new_n << "\n";);
|
||||||
found_new_macro = true;
|
found_new_macro = true;
|
||||||
}
|
}
|
||||||
else if (is_arith_macro(new_n, new_pr, new_exprs, new_prs)) {
|
else if (is_arith_macro(new_n, new_pr, new_dep, new_exprs, new_prs, new_deps)) {
|
||||||
TRACE("macro_finder_found", tout << "found new arith macro:\n" << new_n << "\n";);
|
TRACE("macro_finder_found", tout << "found new arith macro:\n" << new_n << "\n";);
|
||||||
found_new_macro = true;
|
found_new_macro = true;
|
||||||
}
|
}
|
||||||
else if (m_util.is_pseudo_predicate_macro(new_n, head, t, def)) {
|
else if (m_util.is_pseudo_predicate_macro(new_n, head, t, def)) {
|
||||||
TRACE("macro_finder_found", tout << "found new pseudo macro:\n" << head << "\n" << t << "\n" << def << "\n";);
|
TRACE("macro_finder_found", tout << "found new pseudo macro:\n" << head << "\n" << t << "\n" << def << "\n";);
|
||||||
pseudo_predicate_macro2macro(m_manager, head, t, def, to_quantifier(new_n), new_pr, new_exprs, new_prs);
|
pseudo_predicate_macro2macro(m_manager, head, t, def, to_quantifier(new_n), new_pr, new_dep, new_exprs, new_prs, new_deps);
|
||||||
found_new_macro = true;
|
found_new_macro = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
new_exprs.push_back(new_n);
|
new_exprs.push_back(new_n);
|
||||||
if (m_manager.proofs_enabled())
|
if (m_manager.proofs_enabled())
|
||||||
new_prs.push_back(new_pr);
|
new_prs.push_back(new_pr);
|
||||||
|
if (deps != 0)
|
||||||
|
new_deps.push_back(new_dep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return found_new_macro;
|
return found_new_macro;
|
||||||
}
|
}
|
||||||
|
|
||||||
void macro_finder::operator()(unsigned num, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
void macro_finder::operator()(unsigned num, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
|
||||||
TRACE("macro_finder", tout << "processing macros...\n";);
|
TRACE("macro_finder", tout << "processing macros...\n";);
|
||||||
expr_ref_vector _new_exprs(m_manager);
|
expr_ref_vector _new_exprs(m_manager);
|
||||||
proof_ref_vector _new_prs(m_manager);
|
proof_ref_vector _new_prs(m_manager);
|
||||||
if (expand_macros(num, exprs, prs, _new_exprs, _new_prs)) {
|
expr_dependency_ref_vector _new_deps(m_manager);
|
||||||
|
if (expand_macros(num, exprs, prs, deps, _new_exprs, _new_prs, _new_deps)) {
|
||||||
while (true) {
|
while (true) {
|
||||||
expr_ref_vector old_exprs(m_manager);
|
expr_ref_vector old_exprs(m_manager);
|
||||||
proof_ref_vector old_prs(m_manager);
|
proof_ref_vector old_prs(m_manager);
|
||||||
|
expr_dependency_ref_vector old_deps(m_manager);
|
||||||
_new_exprs.swap(old_exprs);
|
_new_exprs.swap(old_exprs);
|
||||||
_new_prs.swap(old_prs);
|
_new_prs.swap(old_prs);
|
||||||
|
_new_deps.swap(old_deps);
|
||||||
SASSERT(_new_exprs.empty());
|
SASSERT(_new_exprs.empty());
|
||||||
SASSERT(_new_prs.empty());
|
SASSERT(_new_prs.empty());
|
||||||
if (!expand_macros(old_exprs.size(), old_exprs.c_ptr(), old_prs.c_ptr(), _new_exprs, _new_prs))
|
SASSERT(_new_deps.empty());
|
||||||
|
if (!expand_macros(old_exprs.size(), old_exprs.c_ptr(), old_prs.c_ptr(), old_deps.c_ptr(),
|
||||||
|
_new_exprs, _new_prs, _new_deps))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_exprs.append(_new_exprs);
|
new_exprs.append(_new_exprs);
|
||||||
new_prs.append(_new_prs);
|
new_prs.append(_new_prs);
|
||||||
|
new_deps.append(_new_deps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,6 @@ Revision History:
|
||||||
#include "ast/simplifier/arith_simplifier_plugin.h"
|
#include "ast/simplifier/arith_simplifier_plugin.h"
|
||||||
|
|
||||||
|
|
||||||
bool is_macro_head(expr * n, unsigned num_decls);
|
|
||||||
bool is_simple_macro(ast_manager & m, expr * n, unsigned num_decls, obj_hashtable<func_decl> const * forbidden_set, app * & head, expr * & def);
|
|
||||||
inline bool is_simple_macro(ast_manager & m, expr * n, unsigned num_decls, app * & head, expr * & def) {
|
|
||||||
return is_simple_macro(m, n, num_decls, 0, head, def);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Macro finder is responsible for finding universally quantified sub-formulas that can be used
|
\brief Macro finder is responsible for finding universally quantified sub-formulas that can be used
|
||||||
as macros.
|
as macros.
|
||||||
|
@ -38,17 +32,14 @@ class macro_finder {
|
||||||
macro_manager & m_macro_manager;
|
macro_manager & m_macro_manager;
|
||||||
macro_util & m_util;
|
macro_util & m_util;
|
||||||
arith_simplifier_plugin * get_arith_simp() { return m_util.get_arith_simp(); }
|
arith_simplifier_plugin * get_arith_simp() { return m_util.get_arith_simp(); }
|
||||||
bool expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
bool expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps);
|
||||||
bool is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
bool is_arith_macro(expr * n, proof * pr, expr_dependency * dep, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps);
|
||||||
|
|
||||||
bool is_macro(expr * n, app_ref & head, expr_ref & def);
|
bool is_macro(expr * n, app_ref & head, expr_ref & def);
|
||||||
bool is_pseudo_head(expr * n, unsigned num_decls, app * & head, app * & t);
|
|
||||||
bool is_pseudo_predicate_macro(expr * n, app * & head, app * & t, expr * & def);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
macro_finder(ast_manager & m, macro_manager & mm);
|
macro_finder(ast_manager & m, macro_manager & mm);
|
||||||
~macro_finder();
|
~macro_finder();
|
||||||
void operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
void operator()(unsigned num, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MACRO_FINDER_H_ */
|
#endif /* MACRO_FINDER_H_ */
|
||||||
|
|
|
@ -25,13 +25,14 @@ Revision History:
|
||||||
#include "ast/ast_pp.h"
|
#include "ast/ast_pp.h"
|
||||||
#include "ast/recurse_expr_def.h"
|
#include "ast/recurse_expr_def.h"
|
||||||
|
|
||||||
macro_manager::macro_manager(ast_manager & m, simplifier & s):
|
macro_manager::macro_manager(ast_manager & m, simplifier & s) :
|
||||||
m_manager(m),
|
m_manager(m),
|
||||||
m_simplifier(s),
|
m_simplifier(s),
|
||||||
m_util(m, s),
|
m_util(m, s),
|
||||||
m_decls(m),
|
m_decls(m),
|
||||||
m_macros(m),
|
m_macros(m),
|
||||||
m_macro_prs(m),
|
m_macro_prs(m),
|
||||||
|
m_macro_deps(m),
|
||||||
m_forbidden(m),
|
m_forbidden(m),
|
||||||
m_deps(m) {
|
m_deps(m) {
|
||||||
m_util.set_forbidden_set(&m_forbidden_set);
|
m_util.set_forbidden_set(&m_forbidden_set);
|
||||||
|
@ -60,13 +61,16 @@ void macro_manager::restore_decls(unsigned old_sz) {
|
||||||
for (unsigned i = old_sz; i < sz; i++) {
|
for (unsigned i = old_sz; i < sz; i++) {
|
||||||
m_decl2macro.erase(m_decls.get(i));
|
m_decl2macro.erase(m_decls.get(i));
|
||||||
m_deps.erase(m_decls.get(i));
|
m_deps.erase(m_decls.get(i));
|
||||||
if (m_manager.proofs_enabled())
|
if (m_manager.proofs_enabled()) {
|
||||||
m_decl2macro_pr.erase(m_decls.get(i));
|
m_decl2macro_pr.erase(m_decls.get(i));
|
||||||
|
m_decl2macro_dep.erase(m_decls.get(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_decls.shrink(old_sz);
|
m_decls.shrink(old_sz);
|
||||||
m_macros.shrink(old_sz);
|
m_macros.shrink(old_sz);
|
||||||
if (m_manager.proofs_enabled())
|
if (m_manager.proofs_enabled())
|
||||||
m_macro_prs.shrink(old_sz);
|
m_macro_prs.shrink(old_sz);
|
||||||
|
m_macro_deps.shrink(old_sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void macro_manager::restore_forbidden(unsigned old_sz) {
|
void macro_manager::restore_forbidden(unsigned old_sz) {
|
||||||
|
@ -79,16 +83,18 @@ void macro_manager::restore_forbidden(unsigned old_sz) {
|
||||||
void macro_manager::reset() {
|
void macro_manager::reset() {
|
||||||
m_decl2macro.reset();
|
m_decl2macro.reset();
|
||||||
m_decl2macro_pr.reset();
|
m_decl2macro_pr.reset();
|
||||||
|
m_decl2macro_dep.reset();
|
||||||
m_decls.reset();
|
m_decls.reset();
|
||||||
m_macros.reset();
|
m_macros.reset();
|
||||||
m_macro_prs.reset();
|
m_macro_prs.reset();
|
||||||
|
m_macro_deps.reset();
|
||||||
m_scopes.reset();
|
m_scopes.reset();
|
||||||
m_forbidden_set.reset();
|
m_forbidden_set.reset();
|
||||||
m_forbidden.reset();
|
m_forbidden.reset();
|
||||||
m_deps.reset();
|
m_deps.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool macro_manager::insert(func_decl * f, quantifier * m, proof * pr) {
|
bool macro_manager::insert(func_decl * f, quantifier * m, proof * pr, expr_dependency * dep) {
|
||||||
TRACE("macro_insert", tout << "trying to create macro: " << f->get_name() << "\n" << mk_pp(m, m_manager) << "\n";);
|
TRACE("macro_insert", tout << "trying to create macro: " << f->get_name() << "\n" << mk_pp(m, m_manager) << "\n";);
|
||||||
|
|
||||||
// if we already have a macro for f then return false;
|
// if we already have a macro for f then return false;
|
||||||
|
@ -115,6 +121,8 @@ bool macro_manager::insert(func_decl * f, quantifier * m, proof * pr) {
|
||||||
m_macro_prs.push_back(pr);
|
m_macro_prs.push_back(pr);
|
||||||
m_decl2macro_pr.insert(f, pr);
|
m_decl2macro_pr.insert(f, pr);
|
||||||
}
|
}
|
||||||
|
m_macro_deps.push_back(dep);
|
||||||
|
m_decl2macro_dep.insert(f, dep);
|
||||||
|
|
||||||
TRACE("macro_insert", tout << "A macro was successfully created for: " << f->get_name() << "\n";);
|
TRACE("macro_insert", tout << "A macro was successfully created for: " << f->get_name() << "\n";);
|
||||||
|
|
||||||
|
@ -195,7 +203,8 @@ func_decl * macro_manager::get_macro_interpretation(unsigned i, expr_ref & inter
|
||||||
|
|
||||||
macro_manager::macro_expander::macro_expander(ast_manager & m, macro_manager & mm, simplifier & s):
|
macro_manager::macro_expander::macro_expander(ast_manager & m, macro_manager & mm, simplifier & s):
|
||||||
simplifier(m),
|
simplifier(m),
|
||||||
m_macro_manager(mm) {
|
m_macro_manager(mm),
|
||||||
|
m_used_macro_dependencies(m) {
|
||||||
// REMARK: theory simplifier should not be used by macro_expander...
|
// REMARK: theory simplifier should not be used by macro_expander...
|
||||||
// is_arith_macro rewrites a quantifer such as:
|
// is_arith_macro rewrites a quantifer such as:
|
||||||
// forall (x Int) (= (+ x (+ (f x) 1)) 2)
|
// forall (x Int) (= (+ x (+ (f x) 1)) 2)
|
||||||
|
@ -286,34 +295,41 @@ bool macro_manager::macro_expander::get_subst(expr * _n, expr_ref & r, proof_ref
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p = 0;
|
p = 0;
|
||||||
|
expr_dependency * ed = m_macro_manager.m_decl2macro_dep.find(d);
|
||||||
|
m_used_macro_dependencies = m.mk_join(m_used_macro_dependencies, ed);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void macro_manager::expand_macros(expr * n, proof * pr, expr_ref & r, proof_ref & new_pr) {
|
void macro_manager::expand_macros(expr * n, proof * pr, expr_dependency * dep, expr_ref & r, proof_ref & new_pr, expr_dependency_ref & new_dep) {
|
||||||
if (has_macros()) {
|
if (has_macros()) {
|
||||||
// Expand macros with "real" proof production support (NO rewrite*)
|
// Expand macros with "real" proof production support (NO rewrite*)
|
||||||
expr_ref old_n(m_manager);
|
expr_ref old_n(m_manager);
|
||||||
proof_ref old_pr(m_manager);
|
proof_ref old_pr(m_manager);
|
||||||
|
expr_dependency_ref old_dep(m_manager);
|
||||||
old_n = n;
|
old_n = n;
|
||||||
old_pr = pr;
|
old_pr = pr;
|
||||||
|
old_dep = dep;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
macro_expander proc(m_manager, *this, m_simplifier);
|
macro_expander proc(m_manager, *this, m_simplifier);
|
||||||
proof_ref n_eq_r_pr(m_manager);
|
proof_ref n_eq_r_pr(m_manager);
|
||||||
TRACE("macro_manager_bug", tout << "expand_macros:\n" << mk_pp(n, m_manager) << "\n";);
|
TRACE("macro_manager_bug", tout << "expand_macros:\n" << mk_pp(n, m_manager) << "\n";);
|
||||||
proc(old_n, r, n_eq_r_pr);
|
proc(old_n, r, n_eq_r_pr);
|
||||||
new_pr = m_manager.mk_modus_ponens(old_pr, n_eq_r_pr);
|
new_pr = m_manager.mk_modus_ponens(old_pr, n_eq_r_pr);
|
||||||
|
new_dep = m_manager.mk_join(old_dep, proc.m_used_macro_dependencies);
|
||||||
if (r.get() == old_n.get())
|
if (r.get() == old_n.get())
|
||||||
return;
|
return;
|
||||||
old_n = r;
|
old_n = r;
|
||||||
old_pr = new_pr;
|
old_pr = new_pr;
|
||||||
|
old_dep = new_dep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r = n;
|
r = n;
|
||||||
new_pr = pr;
|
new_pr = pr;
|
||||||
|
new_dep = dep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,9 +42,11 @@ class macro_manager {
|
||||||
|
|
||||||
obj_map<func_decl, quantifier *> m_decl2macro; // func-decl -> quantifier
|
obj_map<func_decl, quantifier *> m_decl2macro; // func-decl -> quantifier
|
||||||
obj_map<func_decl, proof *> m_decl2macro_pr; // func-decl -> quantifier_proof
|
obj_map<func_decl, proof *> m_decl2macro_pr; // func-decl -> quantifier_proof
|
||||||
|
obj_map<func_decl, expr_dependency *> m_decl2macro_dep; // func-decl -> unsat core dependency
|
||||||
func_decl_ref_vector m_decls;
|
func_decl_ref_vector m_decls;
|
||||||
quantifier_ref_vector m_macros;
|
quantifier_ref_vector m_macros;
|
||||||
proof_ref_vector m_macro_prs;
|
proof_ref_vector m_macro_prs;
|
||||||
|
expr_dependency_ref_vector m_macro_deps;
|
||||||
obj_hashtable<func_decl> m_forbidden_set;
|
obj_hashtable<func_decl> m_forbidden_set;
|
||||||
func_decl_ref_vector m_forbidden;
|
func_decl_ref_vector m_forbidden;
|
||||||
struct scope {
|
struct scope {
|
||||||
|
@ -64,6 +66,7 @@ class macro_manager {
|
||||||
virtual bool get_subst(expr * n, expr_ref & r, proof_ref & p);
|
virtual bool get_subst(expr * n, expr_ref & r, proof_ref & p);
|
||||||
virtual void reduce1_quantifier(quantifier * q);
|
virtual void reduce1_quantifier(quantifier * q);
|
||||||
public:
|
public:
|
||||||
|
expr_dependency_ref m_used_macro_dependencies;
|
||||||
macro_expander(ast_manager & m, macro_manager & mm, simplifier & s);
|
macro_expander(ast_manager & m, macro_manager & mm, simplifier & s);
|
||||||
~macro_expander();
|
~macro_expander();
|
||||||
};
|
};
|
||||||
|
@ -74,7 +77,7 @@ public:
|
||||||
~macro_manager();
|
~macro_manager();
|
||||||
ast_manager & get_manager() const { return m_manager; }
|
ast_manager & get_manager() const { return m_manager; }
|
||||||
macro_util & get_util() { return m_util; }
|
macro_util & get_util() { return m_util; }
|
||||||
bool insert(func_decl * f, quantifier * m, proof * pr);
|
bool insert(func_decl * f, quantifier * m, proof * pr, expr_dependency * dep);
|
||||||
bool has_macros() const { return !m_macros.empty(); }
|
bool has_macros() const { return !m_macros.empty(); }
|
||||||
void push_scope();
|
void push_scope();
|
||||||
void pop_scope(unsigned num_scopes);
|
void pop_scope(unsigned num_scopes);
|
||||||
|
@ -90,7 +93,7 @@ public:
|
||||||
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const;
|
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const;
|
||||||
quantifier * get_macro_quantifier(func_decl * f) const { quantifier * q = 0; m_decl2macro.find(f, q); return q; }
|
quantifier * get_macro_quantifier(func_decl * f) const { quantifier * q = 0; m_decl2macro.find(f, q); return q; }
|
||||||
void get_head_def(quantifier * q, func_decl * d, app * & head, expr * & def) const;
|
void get_head_def(quantifier * q, func_decl * d, app * & head, expr * & def) const;
|
||||||
void expand_macros(expr * n, proof * pr, expr_ref & r, proof_ref & new_pr);
|
void expand_macros(expr * n, proof * pr, expr_dependency * dep, expr_ref & r, proof_ref & new_pr, expr_dependency_ref & new_dep);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -264,17 +264,16 @@ bool quasi_macros::find_macros(unsigned n, expr * const * exprs) {
|
||||||
|
|
||||||
|
|
||||||
// Find out how many non-ground appearences for each uninterpreted function there are
|
// Find out how many non-ground appearences for each uninterpreted function there are
|
||||||
for ( unsigned i = 0 ; i < n ; i++ )
|
for (unsigned i = 0 ; i < n ; i++)
|
||||||
find_occurrences(exprs[i]);
|
find_occurrences(exprs[i]);
|
||||||
|
|
||||||
TRACE("quasi_macros", tout << "Occurrences: " << std::endl;
|
TRACE("quasi_macros",
|
||||||
for (occurrences_map::iterator it = m_occurrences.begin();
|
tout << "Occurrences: " << std::endl;
|
||||||
it != m_occurrences.end();
|
for (auto & kd : m_occurrences)
|
||||||
it++)
|
tout << kd.m_key->get_name() << ": " << kd.m_value << std::endl; );
|
||||||
tout << it->m_key->get_name() << ": " << it->m_value << std::endl; );
|
|
||||||
|
|
||||||
// Find all macros
|
// Find all macros
|
||||||
for ( unsigned i = 0 ; i < n ; i++ ) {
|
for (unsigned i = 0 ; i < n ; i++) {
|
||||||
app_ref a(m_manager);
|
app_ref a(m_manager);
|
||||||
expr_ref t(m_manager);
|
expr_ref t(m_manager);
|
||||||
if (is_quasi_macro(exprs[i], a, t)) {
|
if (is_quasi_macro(exprs[i], a, t)) {
|
||||||
|
@ -285,7 +284,8 @@ bool quasi_macros::find_macros(unsigned n, expr * const * exprs) {
|
||||||
proof * pr = 0;
|
proof * pr = 0;
|
||||||
if (m_manager.proofs_enabled())
|
if (m_manager.proofs_enabled())
|
||||||
pr = m_manager.mk_def_axiom(macro);
|
pr = m_manager.mk_def_axiom(macro);
|
||||||
if (m_macro_manager.insert(a->get_decl(), macro, pr))
|
expr_dependency * dep = 0;
|
||||||
|
if (m_macro_manager.insert(a->get_decl(), macro, pr, dep))
|
||||||
res = true;
|
res = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,21 +293,24 @@ bool quasi_macros::find_macros(unsigned n, expr * const * exprs) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void quasi_macros::apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
void quasi_macros::apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
|
||||||
for ( unsigned i = 0 ; i < n ; i++ ) {
|
for (unsigned i = 0 ; i < n ; i++) {
|
||||||
expr_ref r(m_manager), rs(m_manager);
|
expr_ref r(m_manager), rs(m_manager);
|
||||||
proof_ref pr(m_manager), ps(m_manager);
|
proof_ref pr(m_manager), ps(m_manager);
|
||||||
proof * p = m_manager.proofs_enabled() ? prs[i] : 0;
|
proof * p = m_manager.proofs_enabled() ? prs[i] : 0;
|
||||||
m_macro_manager.expand_macros(exprs[i], p, r, pr);
|
expr_dependency * dep = deps[i];
|
||||||
|
expr_dependency_ref new_dep(m_manager);
|
||||||
|
m_macro_manager.expand_macros(exprs[i], p, dep, r, pr, new_dep);
|
||||||
m_simplifier(r, rs, ps);
|
m_simplifier(r, rs, ps);
|
||||||
new_exprs.push_back(rs);
|
new_exprs.push_back(rs);
|
||||||
new_prs.push_back(ps);
|
new_prs.push_back(ps);
|
||||||
|
new_deps.push_back(new_dep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool quasi_macros::operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
bool quasi_macros::operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
|
||||||
if (find_macros(n, exprs)) {
|
if (find_macros(n, exprs)) {
|
||||||
apply_macros(n, exprs, prs, new_exprs, new_prs);
|
apply_macros(n, exprs, prs, deps, new_exprs, new_prs, new_deps);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// just copy them over
|
// just copy them over
|
||||||
|
|
|
@ -54,7 +54,7 @@ class quasi_macros {
|
||||||
|
|
||||||
void find_occurrences(expr * e);
|
void find_occurrences(expr * e);
|
||||||
bool find_macros(unsigned n, expr * const * exprs);
|
bool find_macros(unsigned n, expr * const * exprs);
|
||||||
void apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
void apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s);
|
quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s);
|
||||||
|
@ -63,7 +63,7 @@ public:
|
||||||
/**
|
/**
|
||||||
\brief Find pure function macros and apply them.
|
\brief Find pure function macros and apply them.
|
||||||
*/
|
*/
|
||||||
bool operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
bool operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -680,8 +680,7 @@ br_status arith_rewriter::mk_div_core(expr * arg1, expr * arg2, expr_ref & resul
|
||||||
if (m_util.is_numeral(arg2, v2, is_int)) {
|
if (m_util.is_numeral(arg2, v2, is_int)) {
|
||||||
SASSERT(!is_int);
|
SASSERT(!is_int);
|
||||||
if (v2.is_zero()) {
|
if (v2.is_zero()) {
|
||||||
result = m_util.mk_div0(arg1);
|
return BR_FAILED;
|
||||||
return BR_REWRITE1;
|
|
||||||
}
|
}
|
||||||
else if (m_util.is_numeral(arg1, v1, is_int)) {
|
else if (m_util.is_numeral(arg1, v1, is_int)) {
|
||||||
result = m_util.mk_numeral(v1/v2, false);
|
result = m_util.mk_numeral(v1/v2, false);
|
||||||
|
@ -734,10 +733,6 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu
|
||||||
result = m_util.mk_numeral(div(v1, v2), is_int);
|
result = m_util.mk_numeral(div(v1, v2), is_int);
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
if (m_util.is_numeral(arg2, v2, is_int) && v2.is_zero()) {
|
|
||||||
result = m_util.mk_idiv0(arg1);
|
|
||||||
return BR_REWRITE1;
|
|
||||||
}
|
|
||||||
return BR_FAILED;
|
return BR_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -402,11 +402,9 @@ bool arith_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * co
|
||||||
case OP_TO_REAL: SASSERT(num_args == 1); mk_to_real(args[0], result); break;
|
case OP_TO_REAL: SASSERT(num_args == 1); mk_to_real(args[0], result); break;
|
||||||
case OP_TO_INT: SASSERT(num_args == 1); mk_to_int(args[0], result); break;
|
case OP_TO_INT: SASSERT(num_args == 1); mk_to_int(args[0], result); break;
|
||||||
case OP_IS_INT: SASSERT(num_args == 1); mk_is_int(args[0], result); break;
|
case OP_IS_INT: SASSERT(num_args == 1); mk_is_int(args[0], result); break;
|
||||||
case OP_POWER: return false;
|
case OP_POWER: SASSERT(num_args == 2); mk_power(args[0], args[1], result); break;
|
||||||
case OP_ABS: SASSERT(num_args == 1); mk_abs(args[0], result); break;
|
case OP_ABS: SASSERT(num_args == 1); mk_abs(args[0], result); break;
|
||||||
case OP_IRRATIONAL_ALGEBRAIC_NUM: return false;
|
case OP_IRRATIONAL_ALGEBRAIC_NUM: return false;
|
||||||
case OP_DIV_0: return false;
|
|
||||||
case OP_IDIV_0: return false;
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -414,6 +412,25 @@ bool arith_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * co
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void arith_simplifier_plugin::mk_power(expr* x, expr* y, expr_ref& result) {
|
||||||
|
rational a, b;
|
||||||
|
if (is_numeral(y, b) && b.is_one()) {
|
||||||
|
result = x;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (is_numeral(x, a) && is_numeral(y, b) && b.is_unsigned()) {
|
||||||
|
if (b.is_zero() && !a.is_zero()) {
|
||||||
|
result = m_util.mk_numeral(rational(1), m_manager.get_sort(x));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!b.is_zero()) {
|
||||||
|
result = m_util.mk_numeral(power(a, b.get_unsigned()), m_manager.get_sort(x));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = m_util.mk_power(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
void arith_simplifier_plugin::mk_abs(expr * arg, expr_ref & result) {
|
void arith_simplifier_plugin::mk_abs(expr * arg, expr_ref & result) {
|
||||||
expr_ref c(m_manager);
|
expr_ref c(m_manager);
|
||||||
expr_ref m_arg(m_manager);
|
expr_ref m_arg(m_manager);
|
||||||
|
|
|
@ -82,6 +82,7 @@ public:
|
||||||
void mk_to_real(expr * arg, expr_ref & result);
|
void mk_to_real(expr * arg, expr_ref & result);
|
||||||
void mk_to_int(expr * arg, expr_ref & result);
|
void mk_to_int(expr * arg, expr_ref & result);
|
||||||
void mk_is_int(expr * arg, expr_ref & result);
|
void mk_is_int(expr * arg, expr_ref & result);
|
||||||
|
void mk_power(expr* x, expr* y, expr_ref& result);
|
||||||
void mk_abs(expr * arg, expr_ref & result);
|
void mk_abs(expr * arg, expr_ref & result);
|
||||||
|
|
||||||
virtual bool reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
virtual bool reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||||
|
|
|
@ -37,6 +37,7 @@ protected:
|
||||||
tout << mk_pp(n, m) << "\n";
|
tout << mk_pp(n, m) << "\n";
|
||||||
tout << mk_pp(r, m) << "\n";
|
tout << mk_pp(r, m) << "\n";
|
||||||
tout << mk_pp(p, m) << "\n";);
|
tout << mk_pp(p, m) << "\n";);
|
||||||
|
TRACE("cache", tout << mk_pp(n, m) << " -> " << mk_pp(r, m) << "\n";);
|
||||||
SASSERT(is_rewrite_proof(n, r, p));
|
SASSERT(is_rewrite_proof(n, r, p));
|
||||||
}
|
}
|
||||||
void reset_cache() { m_cache.reset(); }
|
void reset_cache() { m_cache.reset(); }
|
||||||
|
|
|
@ -591,8 +591,10 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
||||||
if (m_ac_cache.find(to_app(arg), new_arg)) {
|
if (m_ac_cache.find(to_app(arg), new_arg)) {
|
||||||
SASSERT(new_arg != 0);
|
SASSERT(new_arg != 0);
|
||||||
new_args.push_back(new_arg);
|
new_args.push_back(new_arg);
|
||||||
if (arg != new_arg)
|
if (arg != new_arg) {
|
||||||
|
TRACE("ac", tout << mk_pp(arg, m) << " -> " << mk_pp(new_arg, m) << "\n";);
|
||||||
has_new_arg = true;
|
has_new_arg = true;
|
||||||
|
}
|
||||||
if (m.fine_grain_proofs()) {
|
if (m.fine_grain_proofs()) {
|
||||||
proof * pr = 0;
|
proof * pr = 0;
|
||||||
m_ac_pr_cache.find(to_app(arg), pr);
|
m_ac_pr_cache.find(to_app(arg), pr);
|
||||||
|
@ -610,8 +612,10 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
||||||
proof * pr;
|
proof * pr;
|
||||||
get_cached(arg, new_arg, pr);
|
get_cached(arg, new_arg, pr);
|
||||||
new_args.push_back(new_arg);
|
new_args.push_back(new_arg);
|
||||||
if (arg != new_arg)
|
if (arg != new_arg) {
|
||||||
|
TRACE("ac", tout << "cached: " << mk_pp(arg, m) << " -> " << mk_pp(new_arg, m) << "\n";);
|
||||||
has_new_arg = true;
|
has_new_arg = true;
|
||||||
|
}
|
||||||
if (m.fine_grain_proofs() && pr != 0)
|
if (m.fine_grain_proofs() && pr != 0)
|
||||||
new_arg_prs.push_back(pr);
|
new_arg_prs.push_back(pr);
|
||||||
}
|
}
|
||||||
|
@ -627,6 +631,7 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
||||||
else {
|
else {
|
||||||
app * new_curr = m.mk_app(f, new_args.size(), new_args.c_ptr());
|
app * new_curr = m.mk_app(f, new_args.size(), new_args.c_ptr());
|
||||||
m_ac_cache.insert(curr, new_curr);
|
m_ac_cache.insert(curr, new_curr);
|
||||||
|
TRACE("ac", tout << mk_pp(curr, m) << " -> " << mk_pp(new_curr, m) << "\n";);
|
||||||
if (m.fine_grain_proofs()) {
|
if (m.fine_grain_proofs()) {
|
||||||
proof * p = m.mk_congruence(curr, new_curr, new_arg_prs.size(), new_arg_prs.c_ptr());
|
proof * p = m.mk_congruence(curr, new_curr, new_arg_prs.size(), new_arg_prs.c_ptr());
|
||||||
m_ac_pr_cache.insert(curr, p);
|
m_ac_pr_cache.insert(curr, p);
|
||||||
|
|
|
@ -229,6 +229,28 @@ func_decl * func_decls::find(ast_manager & m, unsigned num_args, expr * const *
|
||||||
return find(num_args, sorts.c_ptr(), range);
|
return find(num_args, sorts.c_ptr(), range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned func_decls::get_num_entries() const {
|
||||||
|
if (!more_than_one())
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
func_decl_set * fs = UNTAG(func_decl_set *, m_decls);
|
||||||
|
return fs->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
func_decl * func_decls::get_entry(unsigned inx) {
|
||||||
|
if (!more_than_one()) {
|
||||||
|
SASSERT(inx == 0);
|
||||||
|
return first();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
func_decl_set * fs = UNTAG(func_decl_set *, m_decls);
|
||||||
|
auto b = fs->begin();
|
||||||
|
for (unsigned i = 0; i < inx; i++)
|
||||||
|
b++;
|
||||||
|
return *b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void macro_decls::finalize(ast_manager& m) {
|
void macro_decls::finalize(ast_manager& m) {
|
||||||
for (auto v : *m_decls) m.dec_ref(v.m_body);
|
for (auto v : *m_decls) m.dec_ref(v.m_body);
|
||||||
dealloc(m_decls);
|
dealloc(m_decls);
|
||||||
|
@ -1488,6 +1510,7 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
|
||||||
}
|
}
|
||||||
display_sat_result(r);
|
display_sat_result(r);
|
||||||
if (r == l_true) {
|
if (r == l_true) {
|
||||||
|
complete_model();
|
||||||
validate_model();
|
validate_model();
|
||||||
}
|
}
|
||||||
validate_check_sat_result(r);
|
validate_check_sat_result(r);
|
||||||
|
@ -1632,6 +1655,65 @@ struct contains_array_op_proc {
|
||||||
void operator()(quantifier * n) {}
|
void operator()(quantifier * n) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Complete the model if necessary.
|
||||||
|
*/
|
||||||
|
void cmd_context::complete_model() {
|
||||||
|
if (!is_model_available() ||
|
||||||
|
gparams::get_value("model.completion") != "true")
|
||||||
|
return;
|
||||||
|
|
||||||
|
model_ref md;
|
||||||
|
get_check_sat_result()->get_model(md);
|
||||||
|
SASSERT(md.get() != 0);
|
||||||
|
params_ref p;
|
||||||
|
p.set_uint("max_degree", UINT_MAX); // evaluate algebraic numbers of any degree.
|
||||||
|
p.set_uint("sort_store", true);
|
||||||
|
p.set_bool("completion", true);
|
||||||
|
model_evaluator evaluator(*(md.get()), p);
|
||||||
|
evaluator.set_expand_array_equalities(false);
|
||||||
|
|
||||||
|
scoped_rlimit _rlimit(m().limit(), 0);
|
||||||
|
cancel_eh<reslimit> eh(m().limit());
|
||||||
|
expr_ref r(m());
|
||||||
|
scoped_ctrl_c ctrlc(eh);
|
||||||
|
|
||||||
|
for (auto kd : m_psort_decls) {
|
||||||
|
symbol const & k = kd.m_key;
|
||||||
|
psort_decl * v = kd.m_value;
|
||||||
|
if (v->is_user_decl()) {
|
||||||
|
SASSERT(!v->has_var_params());
|
||||||
|
IF_VERBOSE(12, verbose_stream() << "(model.completion " << k << ")\n"; );
|
||||||
|
ptr_vector<sort> param_sorts(v->get_num_params(), m().mk_bool_sort());
|
||||||
|
sort * srt = v->instantiate(*m_pmanager, param_sorts.size(), param_sorts.c_ptr());
|
||||||
|
if (!md->has_uninterpreted_sort(srt)) {
|
||||||
|
expr * singleton = m().get_some_value(srt);
|
||||||
|
md->register_usort(srt, 1, &singleton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto kd : m_func_decls) {
|
||||||
|
symbol const & k = kd.m_key;
|
||||||
|
func_decls & v = kd.m_value;
|
||||||
|
IF_VERBOSE(12, verbose_stream() << "(model.completion " << k << ")\n"; );
|
||||||
|
for (unsigned i = 0; i < v.get_num_entries(); i++) {
|
||||||
|
func_decl * f = v.get_entry(i);
|
||||||
|
if (!md->has_interpretation(f)) {
|
||||||
|
sort * range = f->get_range();
|
||||||
|
expr * some_val = m().get_some_value(range);
|
||||||
|
if (f->get_arity() > 0) {
|
||||||
|
func_interp * fi = alloc(func_interp, m(), f->get_arity());
|
||||||
|
fi->set_else(some_val);
|
||||||
|
md->register_decl(f, fi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
md->register_decl(f, some_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Check if the current model satisfies the quantifier free formulas.
|
\brief Check if the current model satisfies the quantifier free formulas.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -58,6 +58,8 @@ public:
|
||||||
func_decl * first() const;
|
func_decl * first() const;
|
||||||
func_decl * find(unsigned arity, sort * const * domain, sort * range) const;
|
func_decl * find(unsigned arity, sort * const * domain, sort * range) const;
|
||||||
func_decl * find(ast_manager & m, unsigned num_args, expr * const * args, sort * range) const;
|
func_decl * find(ast_manager & m, unsigned num_args, expr * const * args, sort * range) const;
|
||||||
|
unsigned get_num_entries() const;
|
||||||
|
func_decl * get_entry(unsigned inx);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct macro_decl {
|
struct macro_decl {
|
||||||
|
@ -360,6 +362,7 @@ public:
|
||||||
void set_check_sat_result(check_sat_result * r) { m_check_sat_result = r; }
|
void set_check_sat_result(check_sat_result * r) { m_check_sat_result = r; }
|
||||||
check_sat_result * get_check_sat_result() const { return m_check_sat_result.get(); }
|
check_sat_result * get_check_sat_result() const { return m_check_sat_result.get(); }
|
||||||
check_sat_state cs_state() const;
|
check_sat_state cs_state() const;
|
||||||
|
void complete_model();
|
||||||
void validate_model();
|
void validate_model();
|
||||||
void display_model(model_ref& mdl);
|
void display_model(model_ref& mdl);
|
||||||
|
|
||||||
|
|
|
@ -268,6 +268,7 @@ public:
|
||||||
|
|
||||||
psort_decl::psort_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n):
|
psort_decl::psort_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n):
|
||||||
pdecl(id, num_params),
|
pdecl(id, num_params),
|
||||||
|
m_psort_kind(PSORT_BASE),
|
||||||
m_name(n),
|
m_name(n),
|
||||||
m_inst_cache(0) {
|
m_inst_cache(0) {
|
||||||
}
|
}
|
||||||
|
@ -314,9 +315,10 @@ void psort_dt_decl::display(std::ostream & out) const {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
psort_user_decl::psort_user_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n, psort * p):
|
psort_user_decl::psort_user_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n, psort * p) :
|
||||||
psort_decl(id, num_params, m, n),
|
psort_decl(id, num_params, m, n),
|
||||||
m_def(p) {
|
m_def(p) {
|
||||||
|
m_psort_kind = PSORT_USER;
|
||||||
m.inc_ref(p);
|
m.inc_ref(p);
|
||||||
SASSERT(p == 0 || num_params == p->get_num_params());
|
SASSERT(p == 0 || num_params == p->get_num_params());
|
||||||
}
|
}
|
||||||
|
@ -369,6 +371,7 @@ psort_builtin_decl::psort_builtin_decl(unsigned id, pdecl_manager & m, symbol co
|
||||||
psort_decl(id, PSORT_DECL_VAR_PARAMS, m, n),
|
psort_decl(id, PSORT_DECL_VAR_PARAMS, m, n),
|
||||||
m_fid(fid),
|
m_fid(fid),
|
||||||
m_kind(k) {
|
m_kind(k) {
|
||||||
|
m_psort_kind = PSORT_BUILTIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
sort * psort_builtin_decl::instantiate(pdecl_manager & m, unsigned n, sort * const * s) {
|
sort * psort_builtin_decl::instantiate(pdecl_manager & m, unsigned n, sort * const * s) {
|
||||||
|
|
|
@ -86,10 +86,13 @@ typedef ptr_hashtable<psort, psort_hash_proc, psort_eq_proc> psort_table;
|
||||||
|
|
||||||
#define PSORT_DECL_VAR_PARAMS UINT_MAX
|
#define PSORT_DECL_VAR_PARAMS UINT_MAX
|
||||||
|
|
||||||
|
typedef enum { PSORT_BASE = 0, PSORT_USER, PSORT_BUILTIN } psort_decl_kind;
|
||||||
|
|
||||||
class psort_decl : public pdecl {
|
class psort_decl : public pdecl {
|
||||||
protected:
|
protected:
|
||||||
friend class pdecl_manager;
|
friend class pdecl_manager;
|
||||||
symbol m_name;
|
symbol m_name;
|
||||||
|
psort_decl_kind m_psort_kind;
|
||||||
psort_inst_cache * m_inst_cache;
|
psort_inst_cache * m_inst_cache;
|
||||||
void cache(pdecl_manager & m, sort * const * s, sort * r);
|
void cache(pdecl_manager & m, sort * const * s, sort * r);
|
||||||
sort * find(sort * const * s);
|
sort * find(sort * const * s);
|
||||||
|
@ -105,6 +108,8 @@ public:
|
||||||
bool has_var_params() const { return m_num_params == PSORT_DECL_VAR_PARAMS; }
|
bool has_var_params() const { return m_num_params == PSORT_DECL_VAR_PARAMS; }
|
||||||
symbol const & get_name() const { return m_name; }
|
symbol const & get_name() const { return m_name; }
|
||||||
virtual void reset_cache(pdecl_manager& m);
|
virtual void reset_cache(pdecl_manager& m);
|
||||||
|
bool is_user_decl() const { return m_psort_kind == PSORT_USER; }
|
||||||
|
bool is_builtin_decl() const { return m_psort_kind == PSORT_BUILTIN; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class psort_user_decl : public psort_decl {
|
class psort_user_decl : public psort_decl {
|
||||||
|
|
|
@ -25,6 +25,7 @@ Revision History:
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "util/vector.h"
|
#include "util/vector.h"
|
||||||
#include "util/uint_set.h"
|
#include "util/uint_set.h"
|
||||||
|
#include "util/trace.h"
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class default_value_manager {
|
class default_value_manager {
|
||||||
|
@ -107,11 +108,10 @@ public:
|
||||||
m_init = init;
|
m_init = init;
|
||||||
m_delta.push_back(moves());
|
m_delta.push_back(moves());
|
||||||
m_delta_inv.push_back(moves());
|
m_delta_inv.push_back(moves());
|
||||||
for (unsigned i = 0; i < final.size(); ++i) {
|
for (unsigned f : final) {
|
||||||
add_to_final_states(final[i]);
|
add_to_final_states(f);
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < mvs.size(); ++i) {
|
for (move const& mv : mvs) {
|
||||||
move const& mv = mvs[i];
|
|
||||||
unsigned n = std::max(mv.src(), mv.dst());
|
unsigned n = std::max(mv.src(), mv.dst());
|
||||||
if (n >= m_delta.size()) {
|
if (n >= m_delta.size()) {
|
||||||
m_delta.resize(n+1, moves());
|
m_delta.resize(n+1, moves());
|
||||||
|
@ -280,8 +280,8 @@ public:
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
init = a.num_states();
|
init = a.num_states();
|
||||||
for (unsigned i = 0; i < a.m_final_states.size(); ++i) {
|
for (unsigned st : a.m_final_states) {
|
||||||
mvs.push_back(move(m, init, a.m_final_states[i]));
|
mvs.push_back(move(m, init, st));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return alloc(automaton, m, init, final, mvs);
|
return alloc(automaton, m, init, final, mvs);
|
||||||
|
@ -301,6 +301,16 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_sink_state(unsigned s) const {
|
||||||
|
if (is_final_state(s)) return false;
|
||||||
|
moves mvs;
|
||||||
|
get_moves_from(s, mvs);
|
||||||
|
for (move const& m : mvs) {
|
||||||
|
if (s != m.dst()) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void add_init_to_final_states() {
|
void add_init_to_final_states() {
|
||||||
add_to_final_states(init());
|
add_to_final_states(init());
|
||||||
}
|
}
|
||||||
|
@ -374,12 +384,12 @@ public:
|
||||||
else if (1 == in_degree(dst) && (!is_final_state(dst) || is_final_state(src)) && init() != dst) {
|
else if (1 == in_degree(dst) && (!is_final_state(dst) || is_final_state(src)) && init() != dst) {
|
||||||
moves const& mvs = m_delta[dst];
|
moves const& mvs = m_delta[dst];
|
||||||
moves mvs1;
|
moves mvs1;
|
||||||
for (unsigned k = 0; k < mvs.size(); ++k) {
|
for (move const& mv : mvs) {
|
||||||
mvs1.push_back(move(m, src, mvs[k].dst(), mvs[k].t()));
|
mvs1.push_back(move(m, src, mv.dst(), mv.t()));
|
||||||
}
|
}
|
||||||
for (unsigned k = 0; k < mvs1.size(); ++k) {
|
for (move const& mv : mvs1) {
|
||||||
remove(dst, mvs1[k].dst(), mvs1[k].t());
|
remove(dst, mv.dst(), mv.t());
|
||||||
add(mvs1[k]);
|
add(mv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -392,13 +402,13 @@ public:
|
||||||
unsigned_vector src0s;
|
unsigned_vector src0s;
|
||||||
moves const& mvs = m_delta_inv[dst];
|
moves const& mvs = m_delta_inv[dst];
|
||||||
moves mvs1;
|
moves mvs1;
|
||||||
for (unsigned k = 0; k < mvs.size(); ++k) {
|
for (move const& mv1 : mvs) {
|
||||||
SASSERT(mvs[k].is_epsilon());
|
SASSERT(mv1.is_epsilon());
|
||||||
mvs1.push_back(move(m, mvs[k].src(), dst1, t));
|
mvs1.push_back(move(m, mv1.src(), dst1, t));
|
||||||
}
|
}
|
||||||
for (unsigned k = 0; k < mvs1.size(); ++k) {
|
for (move const& mv1 : mvs1) {
|
||||||
remove(mvs1[k].src(), dst, 0);
|
remove(mv1.src(), dst, 0);
|
||||||
add(mvs1[k]);
|
add(mv1);
|
||||||
}
|
}
|
||||||
remove(dst, dst1, t);
|
remove(dst, dst1, t);
|
||||||
--j;
|
--j;
|
||||||
|
@ -410,12 +420,12 @@ public:
|
||||||
else if (1 == out_degree(src) && init() != src && (!is_final_state(src) || is_final_state(dst))) {
|
else if (1 == out_degree(src) && init() != src && (!is_final_state(src) || is_final_state(dst))) {
|
||||||
moves const& mvs = m_delta_inv[src];
|
moves const& mvs = m_delta_inv[src];
|
||||||
moves mvs1;
|
moves mvs1;
|
||||||
for (unsigned k = 0; k < mvs.size(); ++k) {
|
for (move const& mv : mvs) {
|
||||||
mvs1.push_back(move(m, mvs[k].src(), dst, mvs[k].t()));
|
mvs1.push_back(move(m, mv.src(), dst, mv.t()));
|
||||||
}
|
}
|
||||||
for (unsigned k = 0; k < mvs1.size(); ++k) {
|
for (move const& mv : mvs1) {
|
||||||
remove(mvs1[k].src(), src, mvs1[k].t());
|
remove(mv.src(), src, mv.t());
|
||||||
add(mvs1[k]);
|
add(mv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -438,6 +448,7 @@ public:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sinkify_dead_states();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_sequence(unsigned& length) const {
|
bool is_sequence(unsigned& length) const {
|
||||||
|
@ -472,17 +483,16 @@ public:
|
||||||
bool initial_state_is_source() const { return m_delta_inv[m_init].empty(); }
|
bool initial_state_is_source() const { return m_delta_inv[m_init].empty(); }
|
||||||
bool is_final_state(unsigned s) const { return m_final_set.contains(s); }
|
bool is_final_state(unsigned s) const { return m_final_set.contains(s); }
|
||||||
bool is_final_configuration(uint_set s) const {
|
bool is_final_configuration(uint_set s) const {
|
||||||
for (uint_set::iterator it = s.begin(), end = s.end(); it != end; ++it) {
|
for (unsigned i : s) {
|
||||||
if (is_final_state(*it))
|
if (is_final_state(i))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool is_epsilon_free() const {
|
bool is_epsilon_free() const {
|
||||||
for (unsigned i = 0; i < m_delta.size(); ++i) {
|
for (moves const& mvs : m_delta) {
|
||||||
moves const& mvs = m_delta[i];
|
for (move const & m : mvs) {
|
||||||
for (unsigned j = 0; j < mvs.size(); ++j) {
|
if (!m.t()) return false;
|
||||||
if (!mvs[j].t()) return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -490,8 +500,8 @@ public:
|
||||||
|
|
||||||
bool all_epsilon_in(unsigned s) {
|
bool all_epsilon_in(unsigned s) {
|
||||||
moves const& mvs = m_delta_inv[s];
|
moves const& mvs = m_delta_inv[s];
|
||||||
for (unsigned j = 0; j < mvs.size(); ++j) {
|
for (move const& m : mvs) {
|
||||||
if (mvs[j].t()) return false;
|
if (m.t()) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -504,15 +514,15 @@ public:
|
||||||
bool is_loop_state(unsigned s) const {
|
bool is_loop_state(unsigned s) const {
|
||||||
moves mvs;
|
moves mvs;
|
||||||
get_moves_from(s, mvs);
|
get_moves_from(s, mvs);
|
||||||
for (unsigned i = 0; i < mvs.size(); ++i) {
|
for (move const& m : mvs) {
|
||||||
if (s == mvs[i].dst()) return true;
|
if (s == m.dst()) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned move_count() const {
|
unsigned move_count() const {
|
||||||
unsigned result = 0;
|
unsigned result = 0;
|
||||||
for (unsigned i = 0; i < m_delta.size(); result += m_delta[i].size(), ++i) {}
|
for (moves const& mvs : m_delta) result += mvs.size();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
void get_epsilon_closure(unsigned state, unsigned_vector& states) {
|
void get_epsilon_closure(unsigned state, unsigned_vector& states) {
|
||||||
|
@ -525,9 +535,9 @@ public:
|
||||||
get_moves(state, m_delta, mvs, epsilon_closure);
|
get_moves(state, m_delta, mvs, epsilon_closure);
|
||||||
}
|
}
|
||||||
void get_moves_from_states(uint_set states, moves& mvs, bool epsilon_closure = true) const {
|
void get_moves_from_states(uint_set states, moves& mvs, bool epsilon_closure = true) const {
|
||||||
for (uint_set::iterator it = states.begin(), end = states.end(); it != end; ++it) {
|
for (unsigned i : states) {
|
||||||
moves curr;
|
moves curr;
|
||||||
get_moves(*it, m_delta, curr, epsilon_closure);
|
get_moves(i, m_delta, curr, epsilon_closure);
|
||||||
mvs.append(curr);
|
mvs.append(curr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -543,8 +553,7 @@ public:
|
||||||
out << "\n";
|
out << "\n";
|
||||||
for (unsigned i = 0; i < m_delta.size(); ++i) {
|
for (unsigned i = 0; i < m_delta.size(); ++i) {
|
||||||
moves const& mvs = m_delta[i];
|
moves const& mvs = m_delta[i];
|
||||||
for (unsigned j = 0; j < mvs.size(); ++j) {
|
for (move const& mv : mvs) {
|
||||||
move const& mv = mvs[j];
|
|
||||||
out << i << " -> " << mv.dst() << " ";
|
out << i << " -> " << mv.dst() << " ";
|
||||||
if (mv.t()) {
|
if (mv.t()) {
|
||||||
out << "if ";
|
out << "if ";
|
||||||
|
@ -557,6 +566,40 @@ public:
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void sinkify_dead_states() {
|
||||||
|
uint_set dead_states;
|
||||||
|
for (unsigned i = 0; i < m_delta.size(); ++i) {
|
||||||
|
if (!m_final_states.contains(i)) {
|
||||||
|
dead_states.insert(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool change = true;
|
||||||
|
unsigned_vector to_remove;
|
||||||
|
while (change) {
|
||||||
|
change = false;
|
||||||
|
to_remove.reset();
|
||||||
|
for (unsigned s : dead_states) {
|
||||||
|
moves const& mvs = m_delta[s];
|
||||||
|
for (move const& mv : mvs) {
|
||||||
|
if (!dead_states.contains(mv.dst())) {
|
||||||
|
to_remove.push_back(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
change = !to_remove.empty();
|
||||||
|
for (unsigned s : to_remove) {
|
||||||
|
dead_states.remove(s);
|
||||||
|
}
|
||||||
|
to_remove.reset();
|
||||||
|
}
|
||||||
|
TRACE("seq", tout << "remove: " << dead_states << "\n";);
|
||||||
|
for (unsigned s : dead_states) {
|
||||||
|
CTRACE("seq", !m_delta[s].empty(), tout << "live state " << s << "\n";);
|
||||||
|
m_delta[s].reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void remove_dead_states() {
|
void remove_dead_states() {
|
||||||
unsigned_vector remap;
|
unsigned_vector remap;
|
||||||
for (unsigned i = 0; i < m_delta.size(); ++i) {
|
for (unsigned i = 0; i < m_delta.size(); ++i) {
|
||||||
|
@ -662,8 +705,8 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void append_final(unsigned offset, automaton const& a, unsigned_vector& final) {
|
static void append_final(unsigned offset, automaton const& a, unsigned_vector& final) {
|
||||||
for (unsigned i = 0; i < a.m_final_states.size(); ++i) {
|
for (unsigned s : a.m_final_states) {
|
||||||
final.push_back(a.m_final_states[i]+offset);
|
final.push_back(s+offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,8 @@ private:
|
||||||
|
|
||||||
//false case
|
//false case
|
||||||
curr_bv.push_back(false);
|
curr_bv.push_back(false);
|
||||||
ref_t new_pred_neg(m_ba.mk_and(curr_pred, m_ba.mk_not(constraints[i])), m);
|
ref_t neg(m_ba.mk_not(constraints[i]), m);
|
||||||
|
ref_t new_pred_neg(m_ba.mk_and(curr_pred, neg), m);
|
||||||
generate_min_terms_rec(constraints, min_terms, i + 1, curr_bv, new_pred_neg);
|
generate_min_terms_rec(constraints, min_terms, i + 1, curr_bv, new_pred_neg);
|
||||||
curr_bv.pop_back();
|
curr_bv.pop_back();
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,12 +297,17 @@ symbolic_automata<T, M>::mk_determinstic_param(automaton_t& a, bool flip_accepta
|
||||||
unsigned_vector new_final_states; // new final states
|
unsigned_vector new_final_states; // new final states
|
||||||
unsigned p_state_id = 0; // next state identifier
|
unsigned p_state_id = 0; // next state identifier
|
||||||
|
|
||||||
// adds non-final states of a to final if flipping and and final otherwise
|
TRACE("seq", tout << "mk-deterministic " << flip_acceptance << " " << set << " " << a.is_final_configuration(set) << "\n";);
|
||||||
|
// adds non-final states of a to final if flipping and final otherwise
|
||||||
|
unsigned_vector init_states;
|
||||||
|
a.get_epsilon_closure(a.init(), init_states);
|
||||||
|
for (unsigned s : init_states) {
|
||||||
|
set.insert(s);
|
||||||
|
}
|
||||||
if (a.is_final_configuration(set) != flip_acceptance) {
|
if (a.is_final_configuration(set) != flip_acceptance) {
|
||||||
new_final_states.push_back(p_state_id);
|
new_final_states.push_back(p_state_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
set.insert(a.init()); // Initial state as aset
|
|
||||||
s2id.insert(set, p_state_id++); // the index to the initial state is 0
|
s2id.insert(set, p_state_id++); // the index to the initial state is 0
|
||||||
id2s.push_back(set);
|
id2s.push_back(set);
|
||||||
|
|
||||||
|
@ -342,6 +347,7 @@ symbolic_automata<T, M>::mk_determinstic_param(automaton_t& a, bool flip_accepta
|
||||||
|
|
||||||
bool is_new = !s2id.contains(set);
|
bool is_new = !s2id.contains(set);
|
||||||
if (is_new) {
|
if (is_new) {
|
||||||
|
TRACE("seq", tout << "mk-deterministic " << flip_acceptance << " " << set << " " << a.is_final_configuration(set) << "\n";);
|
||||||
if (a.is_final_configuration(set) != flip_acceptance) {
|
if (a.is_final_configuration(set) != flip_acceptance) {
|
||||||
new_final_states.push_back(p_state_id);
|
new_final_states.push_back(p_state_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,5 +4,6 @@ def_module_params('model',
|
||||||
('v1', BOOL, False, 'use Z3 version 1.x pretty printer'),
|
('v1', BOOL, False, 'use Z3 version 1.x pretty printer'),
|
||||||
('v2', BOOL, False, 'use Z3 version 2.x (x <= 16) pretty printer'),
|
('v2', BOOL, False, 'use Z3 version 2.x (x <= 16) pretty printer'),
|
||||||
('compact', BOOL, False, 'try to compact function graph (i.e., function interpretations that are lookup tables)'),
|
('compact', BOOL, False, 'try to compact function graph (i.e., function interpretations that are lookup tables)'),
|
||||||
|
('completion', BOOL, False, 'enable/disable model completion'),
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
@ -444,16 +444,12 @@ namespace qe {
|
||||||
div_rewriter_cfg(nlqsat& s): m(s.m), a(s.m), m_zero(a.mk_real(0), m) {}
|
div_rewriter_cfg(nlqsat& s): m(s.m), a(s.m), m_zero(a.mk_real(0), m) {}
|
||||||
~div_rewriter_cfg() {}
|
~div_rewriter_cfg() {}
|
||||||
br_status reduce_app(func_decl* f, unsigned sz, expr* const* args, expr_ref& result, proof_ref& pr) {
|
br_status reduce_app(func_decl* f, unsigned sz, expr* const* args, expr_ref& result, proof_ref& pr) {
|
||||||
if (is_decl_of(f, a.get_family_id(), OP_DIV) && sz == 2 && !a.is_numeral(args[1])) {
|
rational r;
|
||||||
|
if (is_decl_of(f, a.get_family_id(), OP_DIV) && sz == 2 && (!a.is_numeral(args[1], r) || r.is_zero())) {
|
||||||
result = m.mk_fresh_const("div", a.mk_real());
|
result = m.mk_fresh_const("div", a.mk_real());
|
||||||
m_divs.push_back(div(m, args[0], args[1], to_app(result)));
|
m_divs.push_back(div(m, args[0], args[1], to_app(result)));
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
if (is_decl_of(f, a.get_family_id(), OP_DIV_0) && sz == 1 && !a.is_numeral(args[0])) {
|
|
||||||
result = m.mk_fresh_const("div", a.mk_real());
|
|
||||||
m_divs.push_back(div(m, args[0], m_zero, to_app(result)));
|
|
||||||
return BR_DONE;
|
|
||||||
}
|
|
||||||
return BR_FAILED;
|
return BR_FAILED;
|
||||||
}
|
}
|
||||||
vector<div> const& divs() const { return m_divs; }
|
vector<div> const& divs() const { return m_divs; }
|
||||||
|
@ -507,10 +503,6 @@ namespace qe {
|
||||||
m_has_divs = true;
|
m_has_divs = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (a.is_div0(n) && s.m_mode == qsat_t) {
|
|
||||||
m_has_divs = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TRACE("qe", tout << "not NRA: " << mk_pp(n, s.m) << "\n";);
|
TRACE("qe", tout << "not NRA: " << mk_pp(n, s.m) << "\n";);
|
||||||
throw tactic_exception("not NRA");
|
throw tactic_exception("not NRA");
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,6 +388,9 @@ private:
|
||||||
m_subgoals.reset();
|
m_subgoals.reset();
|
||||||
init_preprocess();
|
init_preprocess();
|
||||||
SASSERT(g->models_enabled());
|
SASSERT(g->models_enabled());
|
||||||
|
if (g->proofs_enabled()) {
|
||||||
|
throw default_exception("generation of proof objects is not supported in this mode");
|
||||||
|
}
|
||||||
SASSERT(!g->proofs_enabled());
|
SASSERT(!g->proofs_enabled());
|
||||||
TRACE("sat", g->display(tout););
|
TRACE("sat", g->display(tout););
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -387,8 +387,12 @@ void asserted_formulas::find_macros_core() {
|
||||||
expr_ref_vector new_exprs(m);
|
expr_ref_vector new_exprs(m);
|
||||||
proof_ref_vector new_prs(m);
|
proof_ref_vector new_prs(m);
|
||||||
unsigned sz = m_asserted_formulas.size();
|
unsigned sz = m_asserted_formulas.size();
|
||||||
m_macro_finder->operator()(sz - m_asserted_qhead, m_asserted_formulas.c_ptr() + m_asserted_qhead,
|
expr_dependency_ref_vector new_deps(m);
|
||||||
m_asserted_formula_prs.c_ptr() + m_asserted_qhead, new_exprs, new_prs);
|
m_macro_finder->operator()(sz - m_asserted_qhead,
|
||||||
|
m_asserted_formulas.c_ptr() + m_asserted_qhead,
|
||||||
|
m_asserted_formula_prs.c_ptr() + m_asserted_qhead,
|
||||||
|
0, // 0 == No dependency tracking
|
||||||
|
new_exprs, new_prs, new_deps);
|
||||||
swap_asserted_formulas(new_exprs, new_prs);
|
swap_asserted_formulas(new_exprs, new_prs);
|
||||||
reduce_and_solve();
|
reduce_and_solve();
|
||||||
}
|
}
|
||||||
|
@ -411,10 +415,12 @@ void asserted_formulas::apply_quasi_macros() {
|
||||||
expr_ref_vector new_exprs(m);
|
expr_ref_vector new_exprs(m);
|
||||||
proof_ref_vector new_prs(m);
|
proof_ref_vector new_prs(m);
|
||||||
quasi_macros proc(m, m_macro_manager, m_simplifier);
|
quasi_macros proc(m, m_macro_manager, m_simplifier);
|
||||||
|
expr_dependency_ref_vector new_deps(m);
|
||||||
while (proc(m_asserted_formulas.size() - m_asserted_qhead,
|
while (proc(m_asserted_formulas.size() - m_asserted_qhead,
|
||||||
m_asserted_formulas.c_ptr() + m_asserted_qhead,
|
m_asserted_formulas.c_ptr() + m_asserted_qhead,
|
||||||
m_asserted_formula_prs.c_ptr() + m_asserted_qhead,
|
m_asserted_formula_prs.c_ptr() + m_asserted_qhead,
|
||||||
new_exprs, new_prs)) {
|
0, // 0 == No dependency tracking
|
||||||
|
new_exprs, new_prs, new_deps)) {
|
||||||
swap_asserted_formulas(new_exprs, new_prs);
|
swap_asserted_formulas(new_exprs, new_prs);
|
||||||
new_exprs.reset();
|
new_exprs.reset();
|
||||||
new_prs.reset();
|
new_prs.reset();
|
||||||
|
@ -639,7 +645,7 @@ void asserted_formulas::propagate_values() {
|
||||||
new_prs2.push_back(pr);
|
new_prs2.push_back(pr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRACE("propagate_values", tout << "found: " << found << "\n";);
|
TRACE("propagate_values", tout << "found: " << found << "\n" << new_exprs2 << "\n";);
|
||||||
// If C is not empty, then reduce R using the updated simplifier cache with entries
|
// If C is not empty, then reduce R using the updated simplifier cache with entries
|
||||||
// x -> n for each constraint 'x = n' in C.
|
// x -> n for each constraint 'x = n' in C.
|
||||||
if (found) {
|
if (found) {
|
||||||
|
@ -650,6 +656,7 @@ void asserted_formulas::propagate_values() {
|
||||||
expr_ref new_n(m);
|
expr_ref new_n(m);
|
||||||
proof_ref new_pr(m);
|
proof_ref new_pr(m);
|
||||||
m_simplifier(n, new_n, new_pr);
|
m_simplifier(n, new_n, new_pr);
|
||||||
|
TRACE("propagate_values", tout << mk_pp(n, m) << " -> " << new_n << "\n";);
|
||||||
if (n == new_n.get()) {
|
if (n == new_n.get()) {
|
||||||
push_assertion(n, pr, new_exprs1, new_prs1);
|
push_assertion(n, pr, new_exprs1, new_prs1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,9 +141,7 @@ public:
|
||||||
func_decl * get_macro_func_decl(unsigned i) const { return m_macro_manager.get_macro_func_decl(i); }
|
func_decl * get_macro_func_decl(unsigned i) const { return m_macro_manager.get_macro_func_decl(i); }
|
||||||
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const { return m_macro_manager.get_macro_interpretation(i, interp); }
|
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const { return m_macro_manager.get_macro_interpretation(i, interp); }
|
||||||
quantifier * get_macro_quantifier(func_decl * f) const { return m_macro_manager.get_macro_quantifier(f); }
|
quantifier * get_macro_quantifier(func_decl * f) const { return m_macro_manager.get_macro_quantifier(f); }
|
||||||
// auxiliary function used to create a logic context based on a model.
|
void insert_macro(func_decl * f, quantifier * m, proof * pr, expr_dependency * dep) { m_macro_manager.insert(f, m, pr, dep); }
|
||||||
void insert_macro(func_decl * f, quantifier * m, proof * pr) { m_macro_manager.insert(f, m, pr); }
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ASSERTED_FORMULAS_H_ */
|
#endif /* ASSERTED_FORMULAS_H_ */
|
||||||
|
|
|
@ -22,6 +22,8 @@ Revision History:
|
||||||
void preprocessor_params::updt_local_params(params_ref const & _p) {
|
void preprocessor_params::updt_local_params(params_ref const & _p) {
|
||||||
smt_params_helper p(_p);
|
smt_params_helper p(_p);
|
||||||
m_macro_finder = p.macro_finder();
|
m_macro_finder = p.macro_finder();
|
||||||
|
m_quasi_macros = p.quasi_macros();
|
||||||
|
m_restricted_quasi_macros = p.restricted_quasi_macros();
|
||||||
m_pull_nested_quantifiers = p.pull_nested_quantifiers();
|
m_pull_nested_quantifiers = p.pull_nested_quantifiers();
|
||||||
m_refine_inj_axiom = p.refine_inj_axioms();
|
m_refine_inj_axiom = p.refine_inj_axioms();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ def_module_params(module_name='smt',
|
||||||
('random_seed', UINT, 0, 'random seed for the smt solver'),
|
('random_seed', UINT, 0, 'random seed for the smt solver'),
|
||||||
('relevancy', UINT, 2, 'relevancy propagation heuristic: 0 - disabled, 1 - relevancy is tracked by only affects quantifier instantiation, 2 - relevancy is tracked, and an atom is only asserted if it is relevant'),
|
('relevancy', UINT, 2, 'relevancy propagation heuristic: 0 - disabled, 1 - relevancy is tracked by only affects quantifier instantiation, 2 - relevancy is tracked, and an atom is only asserted if it is relevant'),
|
||||||
('macro_finder', BOOL, False, 'try to find universally quantified formulas that can be viewed as macros'),
|
('macro_finder', BOOL, False, 'try to find universally quantified formulas that can be viewed as macros'),
|
||||||
|
('quasi_macros', BOOL, False, 'try to find universally quantified formulas that are quasi-macros'),
|
||||||
|
('restricted_quasi_macros', BOOL, False, 'try to find universally quantified formulas that are restricted quasi-macros'),
|
||||||
('ematching', BOOL, True, 'E-Matching based quantifier instantiation'),
|
('ematching', BOOL, True, 'E-Matching based quantifier instantiation'),
|
||||||
('phase_selection', UINT, 3, 'phase selection heuristic: 0 - always false, 1 - always true, 2 - phase caching, 3 - phase caching conservative, 4 - phase caching conservative 2, 5 - random, 6 - number of occurrences'),
|
('phase_selection', UINT, 3, 'phase selection heuristic: 0 - always false, 1 - always true, 2 - phase caching, 3 - phase caching conservative, 4 - phase caching conservative 2, 5 - random, 6 - number of occurrences'),
|
||||||
('restart_strategy', UINT, 1, '0 - geometric, 1 - inner-outer-geometric, 2 - luby, 3 - fixed, 4 - arithmetic'),
|
('restart_strategy', UINT, 1, '0 - geometric, 1 - inner-outer-geometric, 2 - luby, 3 - fixed, 4 - arithmetic'),
|
||||||
|
|
|
@ -1568,7 +1568,7 @@ namespace smt {
|
||||||
func_decl * get_macro_func_decl(unsigned i) const { return m_asserted_formulas.get_macro_func_decl(i); }
|
func_decl * get_macro_func_decl(unsigned i) const { return m_asserted_formulas.get_macro_func_decl(i); }
|
||||||
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const { return m_asserted_formulas.get_macro_interpretation(i, interp); }
|
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const { return m_asserted_formulas.get_macro_interpretation(i, interp); }
|
||||||
quantifier * get_macro_quantifier(func_decl * f) const { return m_asserted_formulas.get_macro_quantifier(f); }
|
quantifier * get_macro_quantifier(func_decl * f) const { return m_asserted_formulas.get_macro_quantifier(f); }
|
||||||
void insert_macro(func_decl * f, quantifier * m, proof * pr) { m_asserted_formulas.insert_macro(f, m, pr); }
|
void insert_macro(func_decl * f, quantifier * m, proof * pr, expr_dependency * dep) { m_asserted_formulas.insert_macro(f, m, pr, dep); }
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -492,6 +492,7 @@ namespace smt {
|
||||||
|
|
||||||
virtual void assign_eh(quantifier * q) {
|
virtual void assign_eh(quantifier * q) {
|
||||||
m_active = true;
|
m_active = true;
|
||||||
|
ast_manager& m = m_context->get_manager();
|
||||||
if (!m_fparams->m_ematching) {
|
if (!m_fparams->m_ematching) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -514,7 +515,11 @@ namespace smt {
|
||||||
app * mp = to_app(q->get_pattern(i));
|
app * mp = to_app(q->get_pattern(i));
|
||||||
SASSERT(m_context->get_manager().is_pattern(mp));
|
SASSERT(m_context->get_manager().is_pattern(mp));
|
||||||
bool unary = (mp->get_num_args() == 1);
|
bool unary = (mp->get_num_args() == 1);
|
||||||
if (!unary && j >= num_eager_multi_patterns) {
|
if (m.is_rec_fun_def(q) && i > 0) {
|
||||||
|
// add only the first pattern
|
||||||
|
TRACE("quantifier", tout << "skip recursive function body " << mk_ismt2_pp(mp, m) << "\n";);
|
||||||
|
}
|
||||||
|
else if (!unary && j >= num_eager_multi_patterns) {
|
||||||
TRACE("quantifier", tout << "delaying (too many multipatterns):\n" << mk_ismt2_pp(mp, m_context->get_manager()) << "\n"
|
TRACE("quantifier", tout << "delaying (too many multipatterns):\n" << mk_ismt2_pp(mp, m_context->get_manager()) << "\n"
|
||||||
<< "j: " << j << " unary: " << unary << " m_params.m_qi_max_eager_multipatterns: " << m_fparams->m_qi_max_eager_multipatterns
|
<< "j: " << j << " unary: " << unary << " m_params.m_qi_max_eager_multipatterns: " << m_fparams->m_qi_max_eager_multipatterns
|
||||||
<< " num_eager_multi_patterns: " << num_eager_multi_patterns << "\n";);
|
<< " num_eager_multi_patterns: " << num_eager_multi_patterns << "\n";);
|
||||||
|
|
|
@ -395,7 +395,8 @@ namespace smt {
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
theory_var theory_arith<Ext>::internalize_div(app * n) {
|
theory_var theory_arith<Ext>::internalize_div(app * n) {
|
||||||
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
|
rational r;
|
||||||
|
if (!m_util.is_numeral(n->get_arg(1), r) || r.is_zero()) found_underspecified_op(n);
|
||||||
found_underspecified_op(n);
|
found_underspecified_op(n);
|
||||||
theory_var s = mk_binary_op(n);
|
theory_var s = mk_binary_op(n);
|
||||||
context & ctx = get_context();
|
context & ctx = get_context();
|
||||||
|
@ -406,7 +407,8 @@ namespace smt {
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
theory_var theory_arith<Ext>::internalize_idiv(app * n) {
|
theory_var theory_arith<Ext>::internalize_idiv(app * n) {
|
||||||
found_underspecified_op(n);
|
rational r;
|
||||||
|
if (!m_util.is_numeral(n->get_arg(1), r) || r.is_zero()) found_underspecified_op(n);
|
||||||
theory_var s = mk_binary_op(n);
|
theory_var s = mk_binary_op(n);
|
||||||
context & ctx = get_context();
|
context & ctx = get_context();
|
||||||
app * mod = m_util.mk_mod(n->get_arg(0), n->get_arg(1));
|
app * mod = m_util.mk_mod(n->get_arg(0), n->get_arg(1));
|
||||||
|
@ -419,7 +421,8 @@ namespace smt {
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
theory_var theory_arith<Ext>::internalize_mod(app * n) {
|
theory_var theory_arith<Ext>::internalize_mod(app * n) {
|
||||||
TRACE("arith_mod", tout << "internalizing...\n" << mk_pp(n, get_manager()) << "\n";);
|
TRACE("arith_mod", tout << "internalizing...\n" << mk_pp(n, get_manager()) << "\n";);
|
||||||
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
|
rational r;
|
||||||
|
if (!m_util.is_numeral(n->get_arg(1), r) || r.is_zero()) found_underspecified_op(n);
|
||||||
theory_var s = mk_binary_op(n);
|
theory_var s = mk_binary_op(n);
|
||||||
context & ctx = get_context();
|
context & ctx = get_context();
|
||||||
if (!ctx.relevancy())
|
if (!ctx.relevancy())
|
||||||
|
@ -429,7 +432,8 @@ namespace smt {
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
theory_var theory_arith<Ext>::internalize_rem(app * n) {
|
theory_var theory_arith<Ext>::internalize_rem(app * n) {
|
||||||
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
|
rational r;
|
||||||
|
if (!m_util.is_numeral(n->get_arg(1), r) || r.is_zero()) found_underspecified_op(n);
|
||||||
theory_var s = mk_binary_op(n);
|
theory_var s = mk_binary_op(n);
|
||||||
context & ctx = get_context();
|
context & ctx = get_context();
|
||||||
if (!ctx.relevancy()) {
|
if (!ctx.relevancy()) {
|
||||||
|
@ -734,11 +738,6 @@ namespace smt {
|
||||||
return internalize_div(n);
|
return internalize_div(n);
|
||||||
else if (m_util.is_idiv(n))
|
else if (m_util.is_idiv(n))
|
||||||
return internalize_idiv(n);
|
return internalize_idiv(n);
|
||||||
else if (is_app_of(n, get_id(), OP_IDIV_0) || is_app_of(n, get_id(), OP_DIV_0)) {
|
|
||||||
ctx.internalize(n->get_arg(0), false);
|
|
||||||
enode * e = mk_enode(n);
|
|
||||||
return mk_var(e);
|
|
||||||
}
|
|
||||||
else if (m_util.is_mod(n))
|
else if (m_util.is_mod(n))
|
||||||
return internalize_mod(n);
|
return internalize_mod(n);
|
||||||
else if (m_util.is_rem(n))
|
else if (m_util.is_rem(n))
|
||||||
|
|
|
@ -292,9 +292,6 @@ namespace smt {
|
||||||
}
|
}
|
||||||
|
|
||||||
void found_not_handled(expr* n) {
|
void found_not_handled(expr* n) {
|
||||||
if (a.is_div0(n)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_not_handled = n;
|
m_not_handled = n;
|
||||||
if (is_app(n) && is_underspecified(to_app(n))) {
|
if (is_app(n) && is_underspecified(to_app(n))) {
|
||||||
m_underspecified.push_back(to_app(n));
|
m_underspecified.push_back(to_app(n));
|
||||||
|
@ -379,7 +376,12 @@ namespace smt {
|
||||||
}
|
}
|
||||||
else if (is_app(n) && a.get_family_id() == to_app(n)->get_family_id()) {
|
else if (is_app(n) && a.get_family_id() == to_app(n)->get_family_id()) {
|
||||||
app* t = to_app(n);
|
app* t = to_app(n);
|
||||||
|
if (a.is_div(n, n1, n2) && is_numeral(n2, r)) {
|
||||||
|
// skip
|
||||||
|
}
|
||||||
|
else {
|
||||||
found_not_handled(n);
|
found_not_handled(n);
|
||||||
|
}
|
||||||
internalize_args(t);
|
internalize_args(t);
|
||||||
mk_enode(t);
|
mk_enode(t);
|
||||||
theory_var v = mk_var(n);
|
theory_var v = mk_var(n);
|
||||||
|
|
|
@ -19,11 +19,12 @@ Revision History:
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
#include "ast/ast_pp.h"
|
||||||
|
#include "ast/ast_trail.h"
|
||||||
#include "smt/proto_model/value_factory.h"
|
#include "smt/proto_model/value_factory.h"
|
||||||
#include "smt/smt_context.h"
|
#include "smt/smt_context.h"
|
||||||
#include "smt/smt_model_generator.h"
|
#include "smt/smt_model_generator.h"
|
||||||
#include "smt/theory_seq.h"
|
#include "smt/theory_seq.h"
|
||||||
#include "ast/ast_trail.h"
|
|
||||||
#include "smt/theory_arith.h"
|
#include "smt/theory_arith.h"
|
||||||
#include "smt/smt_kernel.h"
|
#include "smt/smt_kernel.h"
|
||||||
|
|
||||||
|
@ -150,9 +151,8 @@ void theory_seq::solution_map::pop_scope(unsigned num_scopes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void theory_seq::solution_map::display(std::ostream& out) const {
|
void theory_seq::solution_map::display(std::ostream& out) const {
|
||||||
eqdep_map_t::iterator it = m_map.begin(), end = m_map.end();
|
for (auto const& kv : m_map) {
|
||||||
for (; it != end; ++it) {
|
out << mk_pp(kv.m_key, m) << " |-> " << mk_pp(kv.m_value.first, m) << "\n";
|
||||||
out << mk_pp(it->m_key, m) << " |-> " << mk_pp(it->m_value.first, m) << "\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,9 +186,8 @@ void theory_seq::exclusion_table::pop_scope(unsigned num_scopes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void theory_seq::exclusion_table::display(std::ostream& out) const {
|
void theory_seq::exclusion_table::display(std::ostream& out) const {
|
||||||
table_t::iterator it = m_table.begin(), end = m_table.end();
|
for (auto const& kv : m_table) {
|
||||||
for (; it != end; ++it) {
|
out << mk_pp(kv.first, m) << " != " << mk_pp(kv.second, m) << "\n";
|
||||||
out << mk_pp(it->first, m) << " != " << mk_pp(it->second, m) << "\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +212,7 @@ theory_seq::theory_seq(ast_manager& m):
|
||||||
m_trail_stack(*this),
|
m_trail_stack(*this),
|
||||||
m_ls(m), m_rs(m),
|
m_ls(m), m_rs(m),
|
||||||
m_lhs(m), m_rhs(m),
|
m_lhs(m), m_rhs(m),
|
||||||
|
m_res(m),
|
||||||
m_atoms_qhead(0),
|
m_atoms_qhead(0),
|
||||||
m_new_solution(false),
|
m_new_solution(false),
|
||||||
m_new_propagation(false),
|
m_new_propagation(false),
|
||||||
|
@ -936,18 +936,14 @@ bool theory_seq::check_length_coherence0(expr* e) {
|
||||||
|
|
||||||
bool theory_seq::check_length_coherence() {
|
bool theory_seq::check_length_coherence() {
|
||||||
|
|
||||||
obj_hashtable<expr>::iterator it = m_length.begin(), end = m_length.end();
|
|
||||||
#if 1
|
#if 1
|
||||||
for (; it != end; ++it) {
|
for (expr* e : m_length) {
|
||||||
expr* e = *it;
|
|
||||||
if (check_length_coherence0(e)) {
|
if (check_length_coherence0(e)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
it = m_length.begin();
|
|
||||||
#endif
|
#endif
|
||||||
for (; it != end; ++it) {
|
for (expr* e : m_length) {
|
||||||
expr* e = *it;
|
|
||||||
if (check_length_coherence(e)) {
|
if (check_length_coherence(e)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -956,10 +952,9 @@ bool theory_seq::check_length_coherence() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool theory_seq::fixed_length() {
|
bool theory_seq::fixed_length() {
|
||||||
obj_hashtable<expr>::iterator it = m_length.begin(), end = m_length.end();
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (; it != end; ++it) {
|
for (expr* e : m_length) {
|
||||||
if (fixed_length(*it)) {
|
if (fixed_length(e)) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2501,12 +2496,11 @@ void theory_seq::display(std::ostream & out) const {
|
||||||
}
|
}
|
||||||
if (!m_re2aut.empty()) {
|
if (!m_re2aut.empty()) {
|
||||||
out << "Regex\n";
|
out << "Regex\n";
|
||||||
obj_map<expr, eautomaton*>::iterator it = m_re2aut.begin(), end = m_re2aut.end();
|
for (auto const& kv : m_re2aut) {
|
||||||
for (; it != end; ++it) {
|
out << mk_pp(kv.m_key, m) << "\n";
|
||||||
out << mk_pp(it->m_key, m) << "\n";
|
|
||||||
display_expr disp(m);
|
display_expr disp(m);
|
||||||
if (it->m_value) {
|
if (kv.m_value) {
|
||||||
it->m_value->display(out, disp);
|
kv.m_value->display(out, disp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2520,9 +2514,7 @@ void theory_seq::display(std::ostream & out) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_length.empty()) {
|
if (!m_length.empty()) {
|
||||||
obj_hashtable<expr>::iterator it = m_length.begin(), end = m_length.end();
|
for (expr* e : m_length) {
|
||||||
for (; it != end; ++it) {
|
|
||||||
expr* e = *it;
|
|
||||||
rational lo(-1), hi(-1);
|
rational lo(-1), hi(-1);
|
||||||
lower_bound(e, lo);
|
lower_bound(e, lo);
|
||||||
upper_bound(e, hi);
|
upper_bound(e, hi);
|
||||||
|
@ -2635,6 +2627,12 @@ void theory_seq::collect_statistics(::statistics & st) const {
|
||||||
st.update("seq int.to.str", m_stats.m_int_string);
|
st.update("seq int.to.str", m_stats.m_int_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void theory_seq::init_search_eh() {
|
||||||
|
m_re2aut.reset();
|
||||||
|
m_res.reset();
|
||||||
|
m_automata.reset();
|
||||||
|
}
|
||||||
|
|
||||||
void theory_seq::init_model(expr_ref_vector const& es) {
|
void theory_seq::init_model(expr_ref_vector const& es) {
|
||||||
expr_ref new_s(m);
|
expr_ref new_s(m);
|
||||||
for (expr* e : es) {
|
for (expr* e : es) {
|
||||||
|
@ -3391,15 +3389,21 @@ void theory_seq::propagate_in_re(expr* n, bool is_true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
eautomaton* a = get_automaton(e2);
|
expr_ref e3(e2, m);
|
||||||
|
context& ctx = get_context();
|
||||||
|
literal lit = ctx.get_literal(n);
|
||||||
|
if (!is_true) {
|
||||||
|
e3 = m_util.re.mk_complement(e2);
|
||||||
|
lit.neg();
|
||||||
|
}
|
||||||
|
eautomaton* a = get_automaton(e3);
|
||||||
if (!a) return;
|
if (!a) return;
|
||||||
|
|
||||||
context& ctx = get_context();
|
|
||||||
|
|
||||||
expr_ref len(m_util.str.mk_length(e1), m);
|
expr_ref len(m_util.str.mk_length(e1), m);
|
||||||
for (unsigned i = 0; i < a->num_states(); ++i) {
|
for (unsigned i = 0; i < a->num_states(); ++i) {
|
||||||
literal acc = mk_accept(e1, len, e2, i);
|
literal acc = mk_accept(e1, len, e3, i);
|
||||||
literal rej = mk_reject(e1, len, e2, i);
|
literal rej = mk_reject(e1, len, e3, i);
|
||||||
add_axiom(a->is_final_state(i)?acc:~acc);
|
add_axiom(a->is_final_state(i)?acc:~acc);
|
||||||
add_axiom(a->is_final_state(i)?~rej:rej);
|
add_axiom(a->is_final_state(i)?~rej:rej);
|
||||||
}
|
}
|
||||||
|
@ -3408,20 +3412,11 @@ void theory_seq::propagate_in_re(expr* n, bool is_true) {
|
||||||
unsigned_vector states;
|
unsigned_vector states;
|
||||||
a->get_epsilon_closure(a->init(), states);
|
a->get_epsilon_closure(a->init(), states);
|
||||||
literal_vector lits;
|
literal_vector lits;
|
||||||
literal lit = ctx.get_literal(n);
|
|
||||||
if (is_true) {
|
|
||||||
lits.push_back(~lit);
|
lits.push_back(~lit);
|
||||||
}
|
|
||||||
for (unsigned i = 0; i < states.size(); ++i) {
|
for (unsigned i = 0; i < states.size(); ++i) {
|
||||||
if (is_true) {
|
lits.push_back(mk_accept(e1, zero, e3, states[i]));
|
||||||
lits.push_back(mk_accept(e1, zero, e2, states[i]));
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
literal nlit = ~lit;
|
|
||||||
propagate_lit(0, 1, &nlit, mk_reject(e1, zero, e2, states[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (is_true) {
|
|
||||||
if (lits.size() == 2) {
|
if (lits.size() == 2) {
|
||||||
propagate_lit(0, 1, &lit, lits[1]);
|
propagate_lit(0, 1, &lit, lits[1]);
|
||||||
}
|
}
|
||||||
|
@ -3429,7 +3424,6 @@ void theory_seq::propagate_in_re(expr* n, bool is_true) {
|
||||||
TRACE("seq", ctx.display_literals_verbose(tout, lits); tout << "\n";);
|
TRACE("seq", ctx.display_literals_verbose(tout, lits); tout << "\n";);
|
||||||
ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr());
|
ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4173,10 +4167,8 @@ eautomaton* theory_seq::get_automaton(expr* re) {
|
||||||
TRACE("seq", result->display(tout, disp););
|
TRACE("seq", result->display(tout, disp););
|
||||||
}
|
}
|
||||||
m_automata.push_back(result);
|
m_automata.push_back(result);
|
||||||
m_trail_stack.push(push_back_vector<theory_seq, scoped_ptr_vector<eautomaton> >(m_automata));
|
|
||||||
|
|
||||||
m_re2aut.insert(re, result);
|
m_re2aut.insert(re, result);
|
||||||
m_trail_stack.push(insert_obj_map<theory_seq, expr, eautomaton*>(m_re2aut, re));
|
m_res.push_back(re);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4257,6 +4249,10 @@ void theory_seq::propagate_acc_rej_length(literal lit, expr* e) {
|
||||||
if (m_util.str.is_length(idx)) return;
|
if (m_util.str.is_length(idx)) return;
|
||||||
SASSERT(m_autil.is_numeral(idx));
|
SASSERT(m_autil.is_numeral(idx));
|
||||||
SASSERT(get_context().get_assignment(lit) == l_true);
|
SASSERT(get_context().get_assignment(lit) == l_true);
|
||||||
|
if (aut->is_sink_state(src)) {
|
||||||
|
propagate_lit(0, 1, &lit, false_literal);
|
||||||
|
return;
|
||||||
|
}
|
||||||
bool is_final = aut->is_final_state(src);
|
bool is_final = aut->is_final_state(src);
|
||||||
if (is_final == is_acc) {
|
if (is_final == is_acc) {
|
||||||
propagate_lit(0, 1, &lit, mk_literal(m_autil.mk_ge(m_util.str.mk_length(s), idx)));
|
propagate_lit(0, 1, &lit, mk_literal(m_autil.mk_ge(m_util.str.mk_length(s), idx)));
|
||||||
|
|
|
@ -328,6 +328,7 @@ namespace smt {
|
||||||
// maintain automata with regular expressions.
|
// maintain automata with regular expressions.
|
||||||
scoped_ptr_vector<eautomaton> m_automata;
|
scoped_ptr_vector<eautomaton> m_automata;
|
||||||
obj_map<expr, eautomaton*> m_re2aut;
|
obj_map<expr, eautomaton*> m_re2aut;
|
||||||
|
expr_ref_vector m_res;
|
||||||
|
|
||||||
// queue of asserted atoms
|
// queue of asserted atoms
|
||||||
ptr_vector<expr> m_atoms;
|
ptr_vector<expr> m_atoms;
|
||||||
|
@ -361,6 +362,7 @@ namespace smt {
|
||||||
virtual void collect_statistics(::statistics & st) const;
|
virtual void collect_statistics(::statistics & st) const;
|
||||||
virtual model_value_proc * mk_value(enode * n, model_generator & mg);
|
virtual model_value_proc * mk_value(enode * n, model_generator & mg);
|
||||||
virtual void init_model(model_generator & mg);
|
virtual void init_model(model_generator & mg);
|
||||||
|
virtual void init_search_eh();
|
||||||
|
|
||||||
void init_model(expr_ref_vector const& es);
|
void init_model(expr_ref_vector const& es);
|
||||||
// final check
|
// final check
|
||||||
|
|
|
@ -297,11 +297,11 @@ struct purify_arith_proc {
|
||||||
push_cnstr(OR(EQ(y, mk_real_zero()),
|
push_cnstr(OR(EQ(y, mk_real_zero()),
|
||||||
EQ(u().mk_mul(y, k), x)));
|
EQ(u().mk_mul(y, k), x)));
|
||||||
push_cnstr_pr(result_pr);
|
push_cnstr_pr(result_pr);
|
||||||
|
rational r;
|
||||||
if (complete()) {
|
if (complete() && (!u().is_numeral(y, r) || r.is_zero())) {
|
||||||
// y != 0 \/ k = div-0(x)
|
// y != 0 \/ k = div-0(x)
|
||||||
push_cnstr(OR(NOT(EQ(y, mk_real_zero())),
|
push_cnstr(OR(NOT(EQ(y, mk_real_zero())),
|
||||||
EQ(k, u().mk_div0(x))));
|
EQ(k, u().mk_div(x, mk_real_zero()))));
|
||||||
push_cnstr_pr(result_pr);
|
push_cnstr_pr(result_pr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,11 +348,12 @@ struct purify_arith_proc {
|
||||||
push_cnstr(OR(u().mk_ge(y, zero), u().mk_lt(k2, u().mk_mul(u().mk_numeral(rational(-1), true), y))));
|
push_cnstr(OR(u().mk_ge(y, zero), u().mk_lt(k2, u().mk_mul(u().mk_numeral(rational(-1), true), y))));
|
||||||
push_cnstr_pr(mod_pr);
|
push_cnstr_pr(mod_pr);
|
||||||
|
|
||||||
if (complete()) {
|
rational r;
|
||||||
push_cnstr(OR(NOT(EQ(y, zero)), EQ(k1, u().mk_idiv0(x))));
|
if (complete() && (!u().is_numeral(y, r) || r.is_zero())) {
|
||||||
|
push_cnstr(OR(NOT(EQ(y, zero)), EQ(k1, u().mk_idiv(x, zero))));
|
||||||
push_cnstr_pr(result_pr);
|
push_cnstr_pr(result_pr);
|
||||||
|
|
||||||
push_cnstr(OR(NOT(EQ(y, zero)), EQ(k2, u().mk_mod0(x))));
|
push_cnstr(OR(NOT(EQ(y, zero)), EQ(k2, u().mk_mod(x, zero))));
|
||||||
push_cnstr_pr(mod_pr);
|
push_cnstr_pr(mod_pr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -414,7 +415,7 @@ struct purify_arith_proc {
|
||||||
// (^ x 0) --> k | x != 0 implies k = 1, x = 0 implies k = 0^0
|
// (^ x 0) --> k | x != 0 implies k = 1, x = 0 implies k = 0^0
|
||||||
push_cnstr(OR(EQ(x, zero), EQ(k, one)));
|
push_cnstr(OR(EQ(x, zero), EQ(k, one)));
|
||||||
push_cnstr_pr(result_pr);
|
push_cnstr_pr(result_pr);
|
||||||
push_cnstr(OR(NOT(EQ(x, zero)), EQ(k, is_int ? u().mk_0_pw_0_int() : u().mk_0_pw_0_real())));
|
push_cnstr(OR(NOT(EQ(x, zero)), EQ(k, u().mk_power(zero, zero))));
|
||||||
push_cnstr_pr(result_pr);
|
push_cnstr_pr(result_pr);
|
||||||
}
|
}
|
||||||
else if (!is_int) {
|
else if (!is_int) {
|
||||||
|
|
|
@ -93,7 +93,7 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const
|
||||||
return mk_qffpbv_tactic(m, p);
|
return mk_qffpbv_tactic(m, p);
|
||||||
else if (logic=="HORN")
|
else if (logic=="HORN")
|
||||||
return mk_horn_tactic(m, p);
|
return mk_horn_tactic(m, p);
|
||||||
else if (logic == "QF_FD" || logic == "SAT")
|
else if ((logic == "QF_FD" || logic == "SAT") && !m.proofs_enabled())
|
||||||
return mk_solver2tactic(mk_fd_solver(m, p));
|
return mk_solver2tactic(mk_fd_solver(m, p));
|
||||||
//else if (logic=="QF_UFNRA")
|
//else if (logic=="QF_UFNRA")
|
||||||
// return mk_qfufnra_tactic(m, p);
|
// return mk_qfufnra_tactic(m, p);
|
||||||
|
@ -102,7 +102,7 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const
|
||||||
}
|
}
|
||||||
|
|
||||||
static solver* mk_special_solver_for_logic(ast_manager & m, params_ref const & p, symbol const& logic) {
|
static solver* mk_special_solver_for_logic(ast_manager & m, params_ref const & p, symbol const& logic) {
|
||||||
if (logic == "QF_FD" || logic == "SAT")
|
if ((logic == "QF_FD" || logic == "SAT") && !m.proofs_enabled())
|
||||||
return mk_fd_solver(m, p);
|
return mk_fd_solver(m, p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,9 @@ class macro_finder_tactic : public tactic {
|
||||||
SASSERT(g->is_well_sorted());
|
SASSERT(g->is_well_sorted());
|
||||||
mc = 0; pc = 0; core = 0;
|
mc = 0; pc = 0; core = 0;
|
||||||
tactic_report report("macro-finder", *g);
|
tactic_report report("macro-finder", *g);
|
||||||
fail_if_unsat_core_generation("macro-finder", g);
|
|
||||||
|
|
||||||
bool produce_proofs = g->proofs_enabled();
|
bool produce_proofs = g->proofs_enabled();
|
||||||
|
bool unsat_core_enabled = g->unsat_core_enabled();
|
||||||
|
|
||||||
simplifier simp(m_manager);
|
simplifier simp(m_manager);
|
||||||
basic_simplifier_plugin * bsimp = alloc(basic_simplifier_plugin, m_manager);
|
basic_simplifier_plugin * bsimp = alloc(basic_simplifier_plugin, m_manager);
|
||||||
|
@ -69,17 +69,21 @@ class macro_finder_tactic : public tactic {
|
||||||
|
|
||||||
expr_ref_vector forms(m_manager), new_forms(m_manager);
|
expr_ref_vector forms(m_manager), new_forms(m_manager);
|
||||||
proof_ref_vector proofs(m_manager), new_proofs(m_manager);
|
proof_ref_vector proofs(m_manager), new_proofs(m_manager);
|
||||||
|
expr_dependency_ref_vector deps(m_manager), new_deps(m_manager);
|
||||||
unsigned size = g->size();
|
unsigned size = g->size();
|
||||||
for (unsigned idx = 0; idx < size; idx++) {
|
for (unsigned idx = 0; idx < size; idx++) {
|
||||||
forms.push_back(g->form(idx));
|
forms.push_back(g->form(idx));
|
||||||
proofs.push_back(g->pr(idx));
|
proofs.push_back(g->pr(idx));
|
||||||
|
deps.push_back(g->dep(idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
mf(forms.size(), forms.c_ptr(), proofs.c_ptr(), new_forms, new_proofs);
|
mf(forms.size(), forms.c_ptr(), proofs.c_ptr(), deps.c_ptr(), new_forms, new_proofs, new_deps);
|
||||||
|
|
||||||
g->reset();
|
g->reset();
|
||||||
for (unsigned i = 0; i < new_forms.size(); i++)
|
for (unsigned i = 0; i < new_forms.size(); i++)
|
||||||
g->assert_expr(new_forms.get(i), produce_proofs ? new_proofs.get(i) : 0, 0);
|
g->assert_expr(new_forms.get(i),
|
||||||
|
produce_proofs ? new_proofs.get(i) : 0,
|
||||||
|
unsat_core_enabled ? new_deps.get(i) : 0);
|
||||||
|
|
||||||
extension_model_converter * evmc = alloc(extension_model_converter, mm.get_manager());
|
extension_model_converter * evmc = alloc(extension_model_converter, mm.get_manager());
|
||||||
unsigned num = mm.get_num_macros();
|
unsigned num = mm.get_num_macros();
|
||||||
|
|
|
@ -47,9 +47,9 @@ class quasi_macros_tactic : public tactic {
|
||||||
SASSERT(g->is_well_sorted());
|
SASSERT(g->is_well_sorted());
|
||||||
mc = 0; pc = 0; core = 0;
|
mc = 0; pc = 0; core = 0;
|
||||||
tactic_report report("quasi-macros", *g);
|
tactic_report report("quasi-macros", *g);
|
||||||
fail_if_unsat_core_generation("quasi-macros", g);
|
|
||||||
|
|
||||||
bool produce_proofs = g->proofs_enabled();
|
bool produce_proofs = g->proofs_enabled();
|
||||||
|
bool produce_unsat_cores = g->unsat_core_enabled();
|
||||||
|
|
||||||
simplifier simp(m_manager);
|
simplifier simp(m_manager);
|
||||||
basic_simplifier_plugin * bsimp = alloc(basic_simplifier_plugin, m_manager);
|
basic_simplifier_plugin * bsimp = alloc(basic_simplifier_plugin, m_manager);
|
||||||
|
@ -68,11 +68,13 @@ class quasi_macros_tactic : public tactic {
|
||||||
|
|
||||||
expr_ref_vector forms(m_manager), new_forms(m_manager);
|
expr_ref_vector forms(m_manager), new_forms(m_manager);
|
||||||
proof_ref_vector proofs(m_manager), new_proofs(m_manager);
|
proof_ref_vector proofs(m_manager), new_proofs(m_manager);
|
||||||
|
expr_dependency_ref_vector deps(m_manager), new_deps(m_manager);
|
||||||
|
|
||||||
unsigned size = g->size();
|
unsigned size = g->size();
|
||||||
for (unsigned i = 0; i < size; i++) {
|
for (unsigned i = 0; i < size; i++) {
|
||||||
forms.push_back(g->form(i));
|
forms.push_back(g->form(i));
|
||||||
proofs.push_back(g->pr(i));
|
proofs.push_back(g->pr(i));
|
||||||
|
deps.push_back(g->dep(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (more) { // CMW: use repeat(...) ?
|
while (more) { // CMW: use repeat(...) ?
|
||||||
|
@ -81,14 +83,18 @@ class quasi_macros_tactic : public tactic {
|
||||||
|
|
||||||
new_forms.reset();
|
new_forms.reset();
|
||||||
new_proofs.reset();
|
new_proofs.reset();
|
||||||
more = qm(forms.size(), forms.c_ptr(), proofs.c_ptr(), new_forms, new_proofs);
|
new_deps.reset();
|
||||||
|
more = qm(forms.size(), forms.c_ptr(), proofs.c_ptr(), deps.c_ptr(), new_forms, new_proofs, new_deps);
|
||||||
forms.swap(new_forms);
|
forms.swap(new_forms);
|
||||||
proofs.swap(new_proofs);
|
proofs.swap(new_proofs);
|
||||||
|
deps.swap(new_deps);
|
||||||
}
|
}
|
||||||
|
|
||||||
g->reset();
|
g->reset();
|
||||||
for (unsigned i = 0; i < new_forms.size(); i++)
|
for (unsigned i = 0; i < new_forms.size(); i++)
|
||||||
g->assert_expr(new_forms.get(i), produce_proofs ? new_proofs.get(i) : 0, 0);
|
g->assert_expr(forms.get(i),
|
||||||
|
produce_proofs ? proofs.get(i) : 0,
|
||||||
|
produce_unsat_cores ? deps.get(i) : 0);
|
||||||
|
|
||||||
extension_model_converter * evmc = alloc(extension_model_converter, mm.get_manager());
|
extension_model_converter * evmc = alloc(extension_model_converter, mm.get_manager());
|
||||||
unsigned num = mm.get_num_macros();
|
unsigned num = mm.get_num_macros();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue