mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +00:00
merged with unstable
This commit is contained in:
commit
3a0947b3ba
413 changed files with 31618 additions and 17204 deletions
|
@ -268,6 +268,8 @@ public:
|
|||
bool is_int_real(expr const * n) const { return is_int_real(get_sort(n)); }
|
||||
|
||||
MATCH_UNARY(is_uminus);
|
||||
MATCH_UNARY(is_to_real);
|
||||
MATCH_UNARY(is_to_int);
|
||||
MATCH_BINARY(is_sub);
|
||||
MATCH_BINARY(is_add);
|
||||
MATCH_BINARY(is_mul);
|
||||
|
|
|
@ -300,7 +300,7 @@ std::ostream & operator<<(std::ostream & out, func_decl_info const & info) {
|
|||
//
|
||||
// -----------------------------------
|
||||
|
||||
char const * g_ast_kind_names[] = {"application", "variable", "quantifier", "sort", "function declaration" };
|
||||
static char const * g_ast_kind_names[] = {"application", "variable", "quantifier", "sort", "function declaration" };
|
||||
|
||||
char const * get_ast_kind_name(ast_kind k) {
|
||||
return g_ast_kind_names[k];
|
||||
|
@ -2765,7 +2765,7 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
|
|||
app const * cls = to_app(f1);
|
||||
unsigned num_args = cls->get_num_args();
|
||||
#ifdef Z3DEBUG
|
||||
vector<bool> found;
|
||||
svector<bool> found;
|
||||
#endif
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * lit = cls->get_arg(i);
|
||||
|
|
|
@ -1194,7 +1194,6 @@ enum pattern_op_kind {
|
|||
heurisitic quantifier instantiation.
|
||||
*/
|
||||
class pattern_decl_plugin : public decl_plugin {
|
||||
sort * m_list;
|
||||
public:
|
||||
virtual decl_plugin * mk_fresh() { return alloc(pattern_decl_plugin); }
|
||||
|
||||
|
|
|
@ -134,6 +134,16 @@ bool lt(ast * n1, ast * n2) {
|
|||
}
|
||||
}
|
||||
|
||||
bool is_sorted(unsigned num, expr * const * ns) {
|
||||
for (unsigned i = 1; i < num; i++) {
|
||||
ast * prev = ns[i-1];
|
||||
ast * curr = ns[i];
|
||||
if (lt(curr, prev))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lex_lt(unsigned num, ast * const * n1, ast * const * n2) {
|
||||
for (unsigned i = 0; i < num; i ++) {
|
||||
if (n1[i] == n2[i])
|
||||
|
|
|
@ -22,6 +22,7 @@ Revision History:
|
|||
class ast;
|
||||
|
||||
bool lt(ast * n1, ast * n2);
|
||||
bool is_sorted(unsigned num, expr * const * ns);
|
||||
|
||||
struct ast_to_lt {
|
||||
bool operator()(ast * n1, ast * n2) const { return lt(n1, n2); }
|
||||
|
|
|
@ -260,6 +260,7 @@ class smt_printer {
|
|||
else {
|
||||
m_out << sym << "[";
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < num_params; ++i) {
|
||||
parameter const& p = params[i];
|
||||
if (p.is_ast()) {
|
||||
|
@ -642,9 +643,7 @@ class smt_printer {
|
|||
m_out << m_var_names[m_num_var_names - idx - 1];
|
||||
}
|
||||
else {
|
||||
if (!m_is_smt2) {
|
||||
m_out << "?" << idx;
|
||||
}
|
||||
m_out << "?" << idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
ast_util.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Helper functions
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2007-06-08.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "ast_util.h"
|
||||
|
||||
app * mk_list_assoc_app(ast_manager & m, func_decl * f, unsigned num_args, expr * const * args) {
|
||||
|
@ -138,3 +156,38 @@ expr * get_clause_literal(ast_manager & m, expr * cls, unsigned idx) {
|
|||
SASSERT(m.is_or(cls));
|
||||
return to_app(cls)->get_arg(idx);
|
||||
}
|
||||
|
||||
expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
if (num_args == 0)
|
||||
return m.mk_true();
|
||||
else if (num_args == 1)
|
||||
return args[0];
|
||||
else
|
||||
return m.mk_and(num_args, args);
|
||||
}
|
||||
|
||||
expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
if (num_args == 0)
|
||||
return m.mk_false();
|
||||
else if (num_args == 1)
|
||||
return args[0];
|
||||
else
|
||||
return m.mk_or(num_args, args);
|
||||
}
|
||||
|
||||
expr * mk_not(ast_manager & m, expr * arg) {
|
||||
expr * atom;
|
||||
if (m.is_not(arg, atom))
|
||||
return atom;
|
||||
else
|
||||
return m.mk_not(arg);
|
||||
}
|
||||
|
||||
expr * expand_distinct(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
expr_ref_buffer new_diseqs(m);
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
for (unsigned j = i + 1; j < num_args; j++)
|
||||
new_diseqs.push_back(m.mk_not(m.mk_eq(args[i], args[j])));
|
||||
}
|
||||
return mk_and(m, new_diseqs.size(), new_diseqs.c_ptr());
|
||||
}
|
||||
|
|
|
@ -95,5 +95,36 @@ bool is_clause(ast_manager & m, expr * n);
|
|||
unsigned get_clause_num_literals(ast_manager & m, expr * cls);
|
||||
expr * get_clause_literal(ast_manager & m, expr * cls, unsigned idx);
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Goodies for creating Boolean expressions
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
/**
|
||||
Return (and args[0] ... args[num_args-1]) if num_args >= 2
|
||||
Return args[0] if num_args == 1
|
||||
Return true if num_args == 0
|
||||
*/
|
||||
expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
|
||||
/**
|
||||
Return (or args[0] ... args[num_args-1]) if num_args >= 2
|
||||
Return args[0] if num_args == 1
|
||||
Return false if num_args == 0
|
||||
*/
|
||||
expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
|
||||
/**
|
||||
Return a if arg = (not a)
|
||||
Retur (not arg) otherwise
|
||||
*/
|
||||
expr * mk_not(ast_manager & m, expr * arg);
|
||||
|
||||
/**
|
||||
Return the expression (and (not (= args[0] args[1])) (not (= args[0] args[2])) ... (not (= args[num_args-2] args[num_args-1])))
|
||||
*/
|
||||
expr * expand_distinct(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
|
||||
#endif /* _AST_UTIL_H_ */
|
||||
|
||||
|
|
|
@ -210,6 +210,10 @@ func_decl * bv_decl_plugin::mk_unary(ptr_vector<func_decl> & decls, decl_kind k,
|
|||
|
||||
func_decl * bv_decl_plugin::mk_int2bv(unsigned bv_size, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain) {
|
||||
if (bv_size == 0) {
|
||||
m_manager->raise_exception("bit-vector size must be greater than zero");
|
||||
}
|
||||
|
||||
force_ptr_array_size(m_int2bv, bv_size + 1);
|
||||
|
||||
if (arity != 1) {
|
||||
|
@ -415,6 +419,9 @@ func_decl * bv_decl_plugin::mk_num_decl(unsigned num_parameters, parameter const
|
|||
return 0;
|
||||
}
|
||||
unsigned bv_size = parameters[1].get_int();
|
||||
if (bv_size == 0) {
|
||||
m_manager->raise_exception("bit-vector size must be greater than zero");
|
||||
}
|
||||
// TODO: sign an error if the parameters[0] is out of range, that is, it is a value not in [0, 2^{bv_size})
|
||||
// This cannot be enforced now, since some Z3 modules try to generate these invalid numerals.
|
||||
// After SMT-COMP, I should find all offending modules.
|
||||
|
@ -766,7 +773,7 @@ bool bv_recognizers::is_zero(expr const * n) const {
|
|||
return decl->get_parameter(0).get_rational().is_zero();
|
||||
}
|
||||
|
||||
bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, expr*& b) {
|
||||
bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, expr*& b) const {
|
||||
if (!is_extract(e)) return false;
|
||||
low = get_extract_low(e);
|
||||
high = get_extract_high(e);
|
||||
|
@ -774,7 +781,7 @@ bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, ex
|
|||
return true;
|
||||
}
|
||||
|
||||
bool bv_recognizers::is_bv2int(expr const* e, expr*& r) {
|
||||
bool bv_recognizers::is_bv2int(expr const* e, expr*& r) const {
|
||||
if (!is_bv2int(e)) return false;
|
||||
r = to_app(e)->get_arg(0);
|
||||
return true;
|
||||
|
|
|
@ -288,10 +288,10 @@ public:
|
|||
bool is_extract(expr const * e) const { return is_app_of(e, get_fid(), OP_EXTRACT); }
|
||||
unsigned get_extract_high(func_decl const * f) const { return f->get_parameter(0).get_int(); }
|
||||
unsigned get_extract_low(func_decl const * f) const { return f->get_parameter(1).get_int(); }
|
||||
unsigned get_extract_high(expr const * n) { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); }
|
||||
unsigned get_extract_low(expr const * n) { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); }
|
||||
bool is_extract(expr const * e, unsigned & low, unsigned & high, expr * & b);
|
||||
bool is_bv2int(expr const * e, expr * & r);
|
||||
unsigned get_extract_high(expr const * n) const { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); }
|
||||
unsigned get_extract_low(expr const * n) const { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); }
|
||||
bool is_extract(expr const * e, unsigned & low, unsigned & high, expr * & b) const;
|
||||
bool is_bv2int(expr const * e, expr * & r) const;
|
||||
bool is_bv_add(expr const * e) const { return is_app_of(e, get_fid(), OP_BADD); }
|
||||
bool is_bv_sub(expr const * e) const { return is_app_of(e, get_fid(), OP_BSUB); }
|
||||
bool is_bv_mul(expr const * e) const { return is_app_of(e, get_fid(), OP_BMUL); }
|
||||
|
|
|
@ -84,7 +84,8 @@ class datatype_decl {
|
|||
ptr_vector<constructor_decl> m_constructors;
|
||||
public:
|
||||
datatype_decl(const symbol & n, unsigned num_constructors, constructor_decl * const * constructors):
|
||||
m_name(n), m_constructors(num_constructors, constructors) {}
|
||||
m_name(n), m_constructors(num_constructors, constructors) {
|
||||
}
|
||||
~datatype_decl() {
|
||||
std::for_each(m_constructors.begin(), m_constructors.end(), delete_proc<constructor_decl>());
|
||||
}
|
||||
|
|
|
@ -326,6 +326,7 @@ namespace datalog {
|
|||
}
|
||||
unsigned index0;
|
||||
sort* last_sort = 0;
|
||||
SASSERT(num_params > 0);
|
||||
for (unsigned i = 0; i < num_params; ++i) {
|
||||
parameter const& p = params[i];
|
||||
if (!p.is_int()) {
|
||||
|
@ -636,9 +637,13 @@ namespace datalog {
|
|||
|
||||
app* dl_decl_util::mk_numeral(uint64 value, sort* s) {
|
||||
if (is_finite_sort(s)) {
|
||||
uint64 sz = 0;
|
||||
if (try_get_size(s, sz) && sz <= value) {
|
||||
m.raise_exception("value is out of bounds");
|
||||
}
|
||||
parameter params[2] = { parameter(rational(value, rational::ui64())), parameter(s) };
|
||||
return m.mk_const(m.mk_func_decl(m_fid, OP_DL_CONSTANT, 2, params, 0, (sort*const*)0));
|
||||
}
|
||||
}
|
||||
if (m_arith.is_int(s) || m_arith.is_real(s)) {
|
||||
return m_arith.mk_numeral(rational(value, rational::ui64()), s);
|
||||
}
|
||||
|
@ -652,13 +657,15 @@ namespace datalog {
|
|||
SASSERT(value == 1);
|
||||
return m.mk_true();
|
||||
}
|
||||
m.raise_exception("unrecognized sort");
|
||||
std::stringstream strm;
|
||||
strm << "sort '" << mk_pp(s, m) << "' is not recognized as a sort that contains numeric values.\nUse Bool, BitVec, Int, Real, or a Finite domain sort";
|
||||
m.raise_exception(strm.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool dl_decl_util::is_numeral(expr* e, uint64& v) const {
|
||||
bool dl_decl_util::is_numeral(const expr* e, uint64& v) const {
|
||||
if (is_numeral(e)) {
|
||||
app* c = to_app(e);
|
||||
const app* c = to_app(e);
|
||||
SASSERT(c->get_decl()->get_num_parameters() == 2);
|
||||
parameter const& p = c->get_decl()->get_parameter(0);
|
||||
SASSERT(p.is_rational());
|
||||
|
|
|
@ -169,11 +169,11 @@ namespace datalog {
|
|||
|
||||
app* mk_le(expr* a, expr* b);
|
||||
|
||||
bool is_lt(expr* a) { return is_app_of(a, m_fid, OP_DL_LT); }
|
||||
bool is_lt(const expr* a) const { return is_app_of(a, m_fid, OP_DL_LT); }
|
||||
|
||||
bool is_numeral(expr* c) const { return is_app_of(c, m_fid, OP_DL_CONSTANT); }
|
||||
bool is_numeral(const expr* c) const { return is_app_of(c, m_fid, OP_DL_CONSTANT); }
|
||||
|
||||
bool is_numeral(expr* e, uint64& v) const;
|
||||
bool is_numeral(const expr* e, uint64& v) const;
|
||||
|
||||
//
|
||||
// Utilities for extracting constants
|
||||
|
|
|
@ -20,52 +20,50 @@ Notes:
|
|||
#include "expr_abstract.h"
|
||||
#include "map.h"
|
||||
|
||||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
|
||||
ast_ref_vector pinned(m);
|
||||
ptr_vector<expr> stack;
|
||||
obj_map<expr, expr*> map;
|
||||
void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
|
||||
|
||||
expr * curr = 0, *b = 0;
|
||||
SASSERT(n->get_ref_count() > 0);
|
||||
|
||||
stack.push_back(n);
|
||||
m_stack.push_back(n);
|
||||
|
||||
for (unsigned i = 0; i < num_bound; ++i) {
|
||||
b = bound[i];
|
||||
expr* v = m.mk_var(base + num_bound - i - 1, m.get_sort(b));
|
||||
pinned.push_back(v);
|
||||
map.insert(b, v);
|
||||
m_pinned.push_back(v);
|
||||
m_map.insert(b, v);
|
||||
}
|
||||
|
||||
while(!stack.empty()) {
|
||||
curr = stack.back();
|
||||
if (map.contains(curr)) {
|
||||
stack.pop_back();
|
||||
while(!m_stack.empty()) {
|
||||
curr = m_stack.back();
|
||||
if (m_map.contains(curr)) {
|
||||
m_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
switch(curr->get_kind()) {
|
||||
case AST_VAR: {
|
||||
map.insert(curr, curr);
|
||||
stack.pop_back();
|
||||
m_map.insert(curr, curr);
|
||||
m_stack.pop_back();
|
||||
break;
|
||||
}
|
||||
case AST_APP: {
|
||||
app* a = to_app(curr);
|
||||
bool all_visited = true;
|
||||
ptr_vector<expr> args;
|
||||
m_args.reset();
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
if (!map.find(a->get_arg(i), b)) {
|
||||
stack.push_back(a->get_arg(i));
|
||||
if (!m_map.find(a->get_arg(i), b)) {
|
||||
m_stack.push_back(a->get_arg(i));
|
||||
all_visited = false;
|
||||
}
|
||||
else {
|
||||
args.push_back(b);
|
||||
m_args.push_back(b);
|
||||
}
|
||||
}
|
||||
if (all_visited) {
|
||||
b = m.mk_app(a->get_decl(), args.size(), args.c_ptr());
|
||||
pinned.push_back(b);
|
||||
map.insert(curr, b);
|
||||
stack.pop_back();
|
||||
b = m.mk_app(a->get_decl(), m_args.size(), m_args.c_ptr());
|
||||
m_pinned.push_back(b);
|
||||
m_map.insert(curr, b);
|
||||
m_stack.pop_back();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -81,17 +79,24 @@ void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* cons
|
|||
}
|
||||
expr_abstract(m, new_base, num_bound, bound, q->get_expr(), result1);
|
||||
b = m.update_quantifier(q, patterns.size(), patterns.c_ptr(), result1.get());
|
||||
pinned.push_back(b);
|
||||
map.insert(curr, b);
|
||||
stack.pop_back();
|
||||
m_pinned.push_back(b);
|
||||
m_map.insert(curr, b);
|
||||
m_stack.pop_back();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (!map.find(n, b)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
VERIFY (m_map.find(n, b));
|
||||
result = b;
|
||||
m_pinned.reset();
|
||||
m_map.reset();
|
||||
m_stack.reset();
|
||||
m_args.reset();
|
||||
}
|
||||
|
||||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
|
||||
expr_abstractor abs(m);
|
||||
abs(base, num_bound, bound, n, result);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,17 @@ Notes:
|
|||
|
||||
#include"ast.h"
|
||||
|
||||
class expr_abstractor {
|
||||
ast_manager& m;
|
||||
expr_ref_vector m_pinned;
|
||||
ptr_vector<expr> m_stack, m_args;
|
||||
obj_map<expr, expr*> m_map;
|
||||
|
||||
public:
|
||||
expr_abstractor(ast_manager& m): m(m), m_pinned(m) {}
|
||||
void operator()(unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result);
|
||||
};
|
||||
|
||||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -200,6 +200,7 @@ func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_par
|
|||
}
|
||||
else {
|
||||
m_manager->raise_exception("sort of floating point constant was not specified");
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
SASSERT(is_sort_of(s, m_family_id, FLOAT_SORT));
|
||||
|
@ -254,7 +255,11 @@ func_decl * float_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_param
|
|||
case OP_FLOAT_IS_ZERO: name = "isZero"; break;
|
||||
case OP_FLOAT_IS_NZERO: name = "isNZero"; break;
|
||||
case OP_FLOAT_IS_PZERO: name = "isPZero"; break;
|
||||
case OP_FLOAT_IS_SIGN_MINUS: name = "isSignMinus"; break;
|
||||
case OP_FLOAT_IS_SIGN_MINUS: name = "isSignMinus"; break;
|
||||
case OP_FLOAT_IS_NAN: name = "isNaN"; break;
|
||||
case OP_FLOAT_IS_INF: name = "isInfinite"; break;
|
||||
case OP_FLOAT_IS_NORMAL: name = "isNormal"; break;
|
||||
case OP_FLOAT_IS_SUBNORMAL: name = "isSubnormal"; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -353,27 +358,22 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters,
|
|||
sort * fp = mk_float_sort(domain[2]->get_parameter(0).get_int(), domain[1]->get_parameter(0).get_int()+1);
|
||||
symbol name("asFloat");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// .. Otherwise we only know how to convert rationals/reals.
|
||||
if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
|
||||
m_manager->raise_exception("expecting two integer parameters to asFloat");
|
||||
if (arity != 2 && arity != 3)
|
||||
m_manager->raise_exception("invalid number of arguments to asFloat operator");
|
||||
if (!is_rm_sort(domain[0]) || domain[1] != m_real_sort)
|
||||
if (arity == 3 && domain[2] != m_int_sort)
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
if (!is_rm_sort(domain[0]) ||
|
||||
!(domain[1] == m_real_sort || is_sort_of(domain[1], m_family_id, FLOAT_SORT)))
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
if (arity == 2) {
|
||||
sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
symbol name("asFloat");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
else {
|
||||
if (domain[2] != m_int_sort)
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
symbol name("asFloat");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
symbol name("asFloat");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,6 +419,10 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
case OP_FLOAT_IS_NZERO:
|
||||
case OP_FLOAT_IS_PZERO:
|
||||
case OP_FLOAT_IS_SIGN_MINUS:
|
||||
case OP_FLOAT_IS_NAN:
|
||||
case OP_FLOAT_IS_INF:
|
||||
case OP_FLOAT_IS_NORMAL:
|
||||
case OP_FLOAT_IS_SUBNORMAL:
|
||||
return mk_unary_rel_decl(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FLOAT_ABS:
|
||||
case OP_FLOAT_UMINUS:
|
||||
|
@ -477,9 +481,13 @@ void float_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol co
|
|||
op_names.push_back(builtin_name("<=", OP_FLOAT_LE));
|
||||
op_names.push_back(builtin_name(">=", OP_FLOAT_GE));
|
||||
|
||||
op_names.push_back(builtin_name("isNaN", OP_FLOAT_IS_NAN));
|
||||
op_names.push_back(builtin_name("isInfinite", OP_FLOAT_IS_INF));
|
||||
op_names.push_back(builtin_name("isZero", OP_FLOAT_IS_ZERO));
|
||||
op_names.push_back(builtin_name("isNZero", OP_FLOAT_IS_NZERO));
|
||||
op_names.push_back(builtin_name("isPZero", OP_FLOAT_IS_PZERO));
|
||||
op_names.push_back(builtin_name("isNormal", OP_FLOAT_IS_NORMAL));
|
||||
op_names.push_back(builtin_name("isSubnormal", OP_FLOAT_IS_SUBNORMAL));
|
||||
op_names.push_back(builtin_name("isSignMinus", OP_FLOAT_IS_SIGN_MINUS));
|
||||
|
||||
op_names.push_back(builtin_name("min", OP_FLOAT_MIN));
|
||||
|
@ -496,6 +504,15 @@ void float_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbo
|
|||
sort_names.push_back(builtin_name("RoundingMode", ROUNDING_MODE_SORT));
|
||||
}
|
||||
|
||||
expr * float_decl_plugin::get_some_value(sort * s) {
|
||||
SASSERT(s->is_sort_of(m_family_id, FLOAT_SORT));
|
||||
mpf tmp;
|
||||
m_fm.mk_nan(s->get_parameter(0).get_int(), s->get_parameter(1).get_int(), tmp);
|
||||
expr * res = this->mk_value(tmp);
|
||||
m_fm.del(tmp);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool float_decl_plugin::is_value(app * e) const {
|
||||
if (e->get_family_id() != m_family_id)
|
||||
return false;
|
||||
|
|
|
@ -61,9 +61,13 @@ enum float_op_kind {
|
|||
OP_FLOAT_GT,
|
||||
OP_FLOAT_LE,
|
||||
OP_FLOAT_GE,
|
||||
OP_FLOAT_IS_NAN,
|
||||
OP_FLOAT_IS_INF,
|
||||
OP_FLOAT_IS_ZERO,
|
||||
OP_FLOAT_IS_NZERO,
|
||||
OP_FLOAT_IS_NORMAL,
|
||||
OP_FLOAT_IS_SUBNORMAL,
|
||||
OP_FLOAT_IS_PZERO,
|
||||
OP_FLOAT_IS_NZERO,
|
||||
OP_FLOAT_IS_SIGN_MINUS,
|
||||
|
||||
OP_TO_FLOAT,
|
||||
|
@ -140,6 +144,7 @@ public:
|
|||
unsigned arity, sort * const * domain, sort * range);
|
||||
virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic);
|
||||
virtual void get_sort_names(svector<builtin_name> & sort_names, symbol const & logic);
|
||||
virtual expr * get_some_value(sort * s);
|
||||
virtual bool is_value(app* e) const;
|
||||
virtual bool is_unique_value(app* e) const { return is_value(e); }
|
||||
|
||||
|
@ -222,7 +227,7 @@ public:
|
|||
app * mk_rem(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_REM, arg1, arg2); }
|
||||
app * mk_max(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MAX, arg1, arg2); }
|
||||
app * mk_min(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MIN, arg1, arg2); }
|
||||
app * mk_abs(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1, arg2); }
|
||||
app * mk_abs(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1); }
|
||||
app * mk_sqrt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_SQRT, arg1, arg2); }
|
||||
app * mk_round(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ROUND_TO_INTEGRAL, arg1, arg2); }
|
||||
app * mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) {
|
||||
|
@ -236,7 +241,11 @@ public:
|
|||
app * mk_le(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_LE, arg1, arg2); }
|
||||
app * mk_ge(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_GE, arg1, arg2); }
|
||||
|
||||
app * mk_is_nan(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NAN, arg1); }
|
||||
app * mk_is_inf(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_INF, arg1); }
|
||||
app * mk_is_zero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_ZERO, arg1); }
|
||||
app * mk_is_normal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NORMAL, arg1); }
|
||||
app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SUBNORMAL, arg1); }
|
||||
app * mk_is_nzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NZERO, arg1); }
|
||||
app * mk_is_pzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_PZERO, arg1); }
|
||||
app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SIGN_MINUS, arg1); }
|
||||
|
|
|
@ -79,7 +79,6 @@ void func_decl_dependencies::collect_ng_func_decls(expr * n, func_decl_set * s)
|
|||
*/
|
||||
class func_decl_dependencies::top_sort {
|
||||
enum color { OPEN, IN_PROGRESS, CLOSED };
|
||||
ast_manager & m_manager;
|
||||
dependency_graph & m_deps;
|
||||
|
||||
typedef obj_map<func_decl, color> color_map;
|
||||
|
@ -177,7 +176,7 @@ class func_decl_dependencies::top_sort {
|
|||
}
|
||||
|
||||
public:
|
||||
top_sort(ast_manager & m, dependency_graph & deps):m_manager(m), m_deps(deps) {}
|
||||
top_sort(dependency_graph & deps) : m_deps(deps) {}
|
||||
|
||||
bool operator()(func_decl * new_decl) {
|
||||
|
||||
|
@ -198,7 +197,7 @@ bool func_decl_dependencies::insert(func_decl * f, func_decl_set * s) {
|
|||
|
||||
m_deps.insert(f, s);
|
||||
|
||||
top_sort cycle_detector(m_manager, m_deps);
|
||||
top_sort cycle_detector(m_deps);
|
||||
if (cycle_detector(f)) {
|
||||
m_deps.erase(f);
|
||||
dealloc(s);
|
||||
|
|
|
@ -597,8 +597,9 @@ void hint_to_macro_head(ast_manager & m, app * head, unsigned num_decls, app_ref
|
|||
is_hint_head(head, vars) must also return true
|
||||
*/
|
||||
bool macro_util::is_poly_hint(expr * n, app * head, expr * exception) {
|
||||
TRACE("macro_util_hint", tout << "is_poly_hint n:\n" << mk_pp(n, m_manager) << "\nhead:\n" << mk_pp(head, m_manager) << "\nexception:\n"
|
||||
<< mk_pp(exception, m_manager) << "\n";);
|
||||
TRACE("macro_util_hint", tout << "is_poly_hint n:\n" << mk_pp(n, m_manager) << "\nhead:\n" << mk_pp(head, m_manager) << "\nexception:\n";
|
||||
if (exception) tout << mk_pp(exception, m_manager); else tout << "<null>";
|
||||
tout << "\n";);
|
||||
ptr_buffer<var> vars;
|
||||
if (!is_hint_head(head, vars)) {
|
||||
TRACE("macro_util_hint", tout << "failed because head is not hint head\n";);
|
||||
|
@ -792,7 +793,10 @@ void macro_util::collect_arith_macro_candidates(expr * lhs, expr * rhs, expr * a
|
|||
mk_add(args.size(), args.c_ptr(), m_manager.get_sort(arg), rest);
|
||||
expr_ref def(m_manager);
|
||||
mk_sub(rhs, rest, def);
|
||||
add_arith_macro_candidate(to_app(arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
|
||||
// If is_poly_hint, rhs may contain variables that do not occur in to_app(arg).
|
||||
// So, we should re-check.
|
||||
if (!_is_poly_hint || is_poly_hint(def, to_app(arg), 0))
|
||||
add_arith_macro_candidate(to_app(arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
|
||||
}
|
||||
else if (is_times_minus_one(arg, neg_arg) && is_app(neg_arg)) {
|
||||
f = to_app(neg_arg)->get_decl();
|
||||
|
@ -810,7 +814,10 @@ void macro_util::collect_arith_macro_candidates(expr * lhs, expr * rhs, expr * a
|
|||
mk_add(args.size(), args.c_ptr(), m_manager.get_sort(arg), rest);
|
||||
expr_ref def(m_manager);
|
||||
mk_sub(rest, rhs, def);
|
||||
add_arith_macro_candidate(to_app(neg_arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
|
||||
// If is_poly_hint, rhs may contain variables that do not occur in to_app(neg_arg).
|
||||
// So, we should re-check.
|
||||
if (!_is_poly_hint || is_poly_hint(def, to_app(neg_arg), 0))
|
||||
add_arith_macro_candidate(to_app(neg_arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,10 +22,9 @@ Revision History:
|
|||
#include"uint_set.h"
|
||||
#include"var_subst.h"
|
||||
|
||||
quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm, basic_simplifier_plugin & p, simplifier & s) :
|
||||
quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s) :
|
||||
m_manager(m),
|
||||
m_macro_manager(mm),
|
||||
m_bsimp(p),
|
||||
m_simplifier(s),
|
||||
m_new_vars(m),
|
||||
m_new_eqs(m),
|
||||
|
|
|
@ -32,7 +32,6 @@ class quasi_macros {
|
|||
|
||||
ast_manager & m_manager;
|
||||
macro_manager & m_macro_manager;
|
||||
basic_simplifier_plugin & m_bsimp;
|
||||
simplifier & m_simplifier;
|
||||
occurrences_map m_occurrences;
|
||||
ptr_vector<expr> m_todo;
|
||||
|
@ -57,7 +56,7 @@ class quasi_macros {
|
|||
void apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
|
||||
public:
|
||||
quasi_macros(ast_manager & m, macro_manager & mm, basic_simplifier_plugin & p, simplifier & s);
|
||||
quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s);
|
||||
~quasi_macros();
|
||||
|
||||
/**
|
||||
|
|
|
@ -119,13 +119,13 @@
|
|||
:pattern (?select (?select (?asElems e) a) i))))
|
||||
(assert (forall ((x Int) (f Int) (a0 Int))
|
||||
(!
|
||||
(or (<= (+ a0 (* -1 (?fClosedTime f))) 0)
|
||||
(or (<= (+ a0 (* (- 1) (?fClosedTime f))) 0)
|
||||
(not (= (?isAllocated x a0) 1))
|
||||
(= (?isAllocated (?select f x) a0) 1))
|
||||
:pattern (?isAllocated (?select f x) a0))))
|
||||
(assert (forall ((a Int) (e Int) (i Int) (a0 Int))
|
||||
(!
|
||||
(or (<= (+ a0 (* -1 (?eClosedTime e))) 0)
|
||||
(or (<= (+ a0 (* (- 1) (?eClosedTime e))) 0)
|
||||
(not (= (?isAllocated a a0) 1))
|
||||
(= (?isAllocated (?select (?select e a) i) a0) 1))
|
||||
:pattern (?isAllocated (?select (?select e a) i) a0))))
|
||||
|
@ -281,13 +281,13 @@
|
|||
:pattern (IntsAllocated h (?StructGet_ s f)))))
|
||||
(assert (forall ((x Int) (f Int) (a0 Int))
|
||||
(!
|
||||
(or (<= (+ a0 (* -1 (?fClosedTime f))) 0)
|
||||
(or (<= (+ a0 (* (- 1) (?fClosedTime f))) 0)
|
||||
(not (?isAllocated_ x a0))
|
||||
(?isAllocated_ (?select f x) a0))
|
||||
:pattern (?isAllocated_ (?select f x) a0))))
|
||||
(assert (forall ((a Int) (e Int) (i Int) (a0 Int))
|
||||
(!
|
||||
(or (<= (+ a0 (* -1 (?eClosedTime e))) 0)
|
||||
(or (<= (+ a0 (* (- 1) (?eClosedTime e))) 0)
|
||||
(not (?isAllocated_ a a0))
|
||||
(?isAllocated_ (?select (?select e a) i) a0))
|
||||
:pattern (?isAllocated_ (?select (?select e a) i) a0))))
|
||||
|
|
|
@ -30,7 +30,7 @@ class recurse_expr : public Visitor {
|
|||
vector<T, CallDestructors> m_results2;
|
||||
|
||||
bool is_cached(expr * n) const { T c; return m_cache.find(n, c); }
|
||||
T get_cached(expr * n) const { T c; m_cache.find(n, c); return c; }
|
||||
T get_cached(expr * n) const { return m_cache.find(n); }
|
||||
void cache_result(expr * n, T c) { m_cache.insert(n, c); }
|
||||
|
||||
void visit(expr * n, bool & visited);
|
||||
|
|
|
@ -118,7 +118,7 @@ public:
|
|||
|
||||
void mk_eq(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_eq_core(arg1, arg2, result) == BR_FAILED)
|
||||
result = m_util.mk_le(arg1, arg2);
|
||||
result = m_util.mk_eq(arg1, arg2);
|
||||
}
|
||||
void mk_le(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_le_core(arg1, arg2, result) == BR_FAILED)
|
||||
|
|
|
@ -25,6 +25,7 @@ void array_rewriter::updt_params(params_ref const & _p) {
|
|||
array_rewriter_params p(_p);
|
||||
m_sort_store = p.sort_store();
|
||||
m_expand_select_store = p.expand_select_store();
|
||||
m_expand_store_eq = p.expand_store_eq();
|
||||
}
|
||||
|
||||
void array_rewriter::get_param_descrs(param_descrs & r) {
|
||||
|
@ -365,3 +366,40 @@ br_status array_rewriter::mk_set_subset(expr * arg1, expr * arg2, expr_ref & res
|
|||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
br_status array_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) {
|
||||
if (!m_expand_store_eq) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
expr* lhs1 = lhs;
|
||||
while (m_util.is_store(lhs1)) {
|
||||
lhs1 = to_app(lhs1)->get_arg(0);
|
||||
}
|
||||
expr* rhs1 = rhs;
|
||||
while (m_util.is_store(rhs1)) {
|
||||
rhs1 = to_app(rhs1)->get_arg(0);
|
||||
}
|
||||
if (lhs1 != rhs1) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
ptr_buffer<expr> fmls, args;
|
||||
expr* e;
|
||||
expr_ref tmp1(m()), tmp2(m());
|
||||
#define MK_EQ() \
|
||||
while (m_util.is_store(e)) { \
|
||||
args.push_back(lhs); \
|
||||
args.append(to_app(e)->get_num_args()-2,to_app(e)->get_args()+1); \
|
||||
mk_select(args.size(), args.c_ptr(), tmp1); \
|
||||
args[0] = rhs; \
|
||||
mk_select(args.size(), args.c_ptr(), tmp2); \
|
||||
fmls.push_back(m().mk_eq(tmp1, tmp2)); \
|
||||
e = to_app(e)->get_arg(0); \
|
||||
args.reset(); \
|
||||
} \
|
||||
|
||||
e = lhs;
|
||||
MK_EQ();
|
||||
e = rhs;
|
||||
MK_EQ();
|
||||
result = m().mk_and(fmls.size(), fmls.c_ptr());
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
|
|
|
@ -31,12 +31,14 @@ class array_rewriter {
|
|||
array_util m_util;
|
||||
bool m_sort_store;
|
||||
bool m_expand_select_store;
|
||||
bool m_expand_store_eq;
|
||||
template<bool CHECK_DISEQ>
|
||||
lbool compare_args(unsigned num_args, expr * const * args1, expr * const * args2);
|
||||
public:
|
||||
array_rewriter(ast_manager & m, params_ref const & p = params_ref()):
|
||||
m_util(m) {
|
||||
updt_params(p);
|
||||
|
||||
}
|
||||
ast_manager & m() const { return m_util.get_manager(); }
|
||||
family_id get_fid() const { return m_util.get_family_id(); }
|
||||
|
@ -60,6 +62,7 @@ public:
|
|||
br_status mk_set_complement(expr * arg, expr_ref & result);
|
||||
br_status mk_set_difference(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_set_subset(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_eq_core(expr * lhs, expr * rhs, expr_ref & result);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,4 +2,5 @@ def_module_params(module_name='rewriter',
|
|||
class_name='array_rewriter_params',
|
||||
export=True,
|
||||
params=(("expand_select_store", BOOL, False, "replace a (select (store ...) ...) term by an if-then-else term"),
|
||||
("expand_store_eq", BOOL, False, "reduce (store ...) = (store ...) with a common base into selects"),
|
||||
("sort_store", BOOL, False, "sort nested stores when the indices are known to be different")))
|
||||
|
|
175
src/ast/rewriter/ast_counter.cpp
Normal file
175
src/ast/rewriter/ast_counter.cpp
Normal file
|
@ -0,0 +1,175 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
ast_counter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Routines for counting features of terms, such as free variables.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-03-18.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "ast_counter.h"
|
||||
#include "var_subst.h"
|
||||
|
||||
void counter::update(unsigned el, int delta) {
|
||||
int & counter = get(el);
|
||||
SASSERT(!m_stay_non_negative || counter>=0);
|
||||
SASSERT(!m_stay_non_negative || static_cast<int>(counter)>=-delta);
|
||||
counter += delta;
|
||||
}
|
||||
|
||||
int & counter::get(unsigned el) {
|
||||
return m_data.insert_if_not_there2(el, 0)->get_data().m_value;
|
||||
}
|
||||
|
||||
counter & counter::count(unsigned sz, const unsigned * els, int delta) {
|
||||
for(unsigned i=0; i<sz; i++) {
|
||||
update(els[i], delta);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned counter::get_positive_count() const {
|
||||
unsigned cnt = 0;
|
||||
iterator eit = begin();
|
||||
iterator eend = end();
|
||||
for(; eit!=eend; ++eit) {
|
||||
if( eit->m_value>0 ) {
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void counter::collect_positive(uint_set & acc) const {
|
||||
iterator eit = begin();
|
||||
iterator eend = end();
|
||||
for(; eit!=eend; ++eit) {
|
||||
if(eit->m_value>0) { acc.insert(eit->m_key); }
|
||||
}
|
||||
}
|
||||
|
||||
bool counter::get_max_positive(unsigned & res) const {
|
||||
bool found = false;
|
||||
iterator eit = begin();
|
||||
iterator eend = end();
|
||||
for(; eit!=eend; ++eit) {
|
||||
if( eit->m_value>0 && (!found || eit->m_key>res) ) {
|
||||
found = true;
|
||||
res = eit->m_key;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
unsigned counter::get_max_positive() const {
|
||||
unsigned max_pos;
|
||||
VERIFY(get_max_positive(max_pos));
|
||||
return max_pos;
|
||||
}
|
||||
|
||||
int counter::get_max_counter_value() const {
|
||||
int res = 0;
|
||||
iterator eit = begin();
|
||||
iterator eend = end();
|
||||
for (; eit!=eend; ++eit) {
|
||||
if( eit->m_value>res ) {
|
||||
res = eit->m_value;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void var_counter::count_vars(ast_manager & m, const app * pred, int coef) {
|
||||
unsigned n = pred->get_num_args();
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
m_sorts.reset();
|
||||
m_todo.reset();
|
||||
m_mark.reset();
|
||||
::get_free_vars(m_mark, m_todo, pred->get_arg(i), m_sorts);
|
||||
for (unsigned j = 0; j < m_sorts.size(); ++j) {
|
||||
if (m_sorts[j]) {
|
||||
update(j, coef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned var_counter::get_max_var(bool& has_var) {
|
||||
has_var = false;
|
||||
unsigned max_var = 0;
|
||||
ptr_vector<quantifier> qs;
|
||||
while (!m_todo.empty()) {
|
||||
expr* e = m_todo.back();
|
||||
m_todo.pop_back();
|
||||
if (m_visited.is_marked(e)) {
|
||||
continue;
|
||||
}
|
||||
m_visited.mark(e, true);
|
||||
switch(e->get_kind()) {
|
||||
case AST_QUANTIFIER: {
|
||||
qs.push_back(to_quantifier(e));
|
||||
break;
|
||||
}
|
||||
case AST_VAR: {
|
||||
if (to_var(e)->get_idx() >= max_var) {
|
||||
has_var = true;
|
||||
max_var = to_var(e)->get_idx();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AST_APP: {
|
||||
app* a = to_app(e);
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
m_todo.push_back(a->get_arg(i));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_visited.reset();
|
||||
|
||||
while (!qs.empty()) {
|
||||
var_counter aux_counter;
|
||||
quantifier* q = qs.back();
|
||||
qs.pop_back();
|
||||
aux_counter.m_todo.push_back(q->get_expr());
|
||||
bool has_var1 = false;
|
||||
unsigned max_v = aux_counter.get_max_var(has_var1);
|
||||
if (max_v >= max_var + q->get_num_decls()) {
|
||||
max_var = max_v - q->get_num_decls();
|
||||
has_var = has_var || has_var1;
|
||||
}
|
||||
}
|
||||
|
||||
return max_var;
|
||||
}
|
||||
|
||||
|
||||
unsigned var_counter::get_max_var(expr* e) {
|
||||
bool has_var = false;
|
||||
m_todo.push_back(e);
|
||||
return get_max_var(has_var);
|
||||
}
|
||||
|
||||
unsigned var_counter::get_next_var(expr* e) {
|
||||
bool has_var = false;
|
||||
m_todo.push_back(e);
|
||||
unsigned mv = get_max_var(has_var);
|
||||
if (has_var) mv++;
|
||||
return mv;
|
||||
}
|
||||
|
109
src/ast/rewriter/ast_counter.h
Normal file
109
src/ast/rewriter/ast_counter.h
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
ast_counter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Routines for counting features of terms, such as free variables.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-03-18.
|
||||
Krystof Hoder (t-khoder) 2010-10-10.
|
||||
|
||||
Revision History:
|
||||
|
||||
Hoisted from dl_util.h 2013-03-18.
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#ifndef _AST_COUNTER_H_
|
||||
#define _AST_COUNTER_H_
|
||||
|
||||
#include "ast.h"
|
||||
#include "map.h"
|
||||
#include "uint_set.h"
|
||||
|
||||
class counter {
|
||||
protected:
|
||||
typedef u_map<int> map_impl;
|
||||
map_impl m_data;
|
||||
const bool m_stay_non_negative;
|
||||
public:
|
||||
typedef map_impl::iterator iterator;
|
||||
|
||||
counter(bool stay_non_negative = true) : m_stay_non_negative(stay_non_negative) {}
|
||||
|
||||
void reset() { m_data.reset(); }
|
||||
iterator begin() const { return m_data.begin(); }
|
||||
iterator end() const { return m_data.end(); }
|
||||
void update(unsigned el, int delta);
|
||||
int & get(unsigned el);
|
||||
|
||||
/**
|
||||
\brief Increase values of elements in \c els by \c delta.
|
||||
|
||||
The function returns a reference to \c *this to allow for expressions like
|
||||
counter().count(sz, arr).get_positive_count()
|
||||
*/
|
||||
counter & count(unsigned sz, const unsigned * els, int delta = 1);
|
||||
counter & count(const unsigned_vector & els, int delta = 1) {
|
||||
return count(els.size(), els.c_ptr(), delta);
|
||||
}
|
||||
|
||||
void collect_positive(uint_set & acc) const;
|
||||
unsigned get_positive_count() const;
|
||||
|
||||
bool get_max_positive(unsigned & res) const;
|
||||
unsigned get_max_positive() const;
|
||||
|
||||
/**
|
||||
Since the default counter value of a counter is zero, the result is never negative.
|
||||
*/
|
||||
int get_max_counter_value() const;
|
||||
};
|
||||
|
||||
class var_counter : public counter {
|
||||
protected:
|
||||
ptr_vector<sort> m_sorts;
|
||||
expr_fast_mark1 m_visited;
|
||||
ptr_vector<expr> m_todo;
|
||||
ast_mark m_mark;
|
||||
unsigned_vector m_scopes;
|
||||
unsigned get_max_var(bool & has_var);
|
||||
public:
|
||||
var_counter(bool stay_non_negative = true): counter(stay_non_negative) {}
|
||||
void count_vars(ast_manager & m, const app * t, int coef = 1);
|
||||
unsigned get_max_var(expr* e);
|
||||
unsigned get_next_var(expr* e);
|
||||
};
|
||||
|
||||
class ast_counter {
|
||||
typedef obj_map<ast, int> map_impl;
|
||||
map_impl m_data;
|
||||
bool m_stay_non_negative;
|
||||
public:
|
||||
typedef map_impl::iterator iterator;
|
||||
|
||||
ast_counter(bool stay_non_negative = true) : m_stay_non_negative(stay_non_negative) {}
|
||||
|
||||
iterator begin() const { return m_data.begin(); }
|
||||
iterator end() const { return m_data.end(); }
|
||||
|
||||
int & get(ast * el) {
|
||||
return m_data.insert_if_not_there2(el, 0)->get_data().m_value;
|
||||
}
|
||||
void update(ast * el, int delta){
|
||||
get(el) += delta;
|
||||
SASSERT(!m_stay_non_negative || get(el) >= 0);
|
||||
}
|
||||
|
||||
void inc(ast * el) { update(el, 1); }
|
||||
void dec(ast * el) { update(el, -1); }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -64,6 +64,7 @@ void bv_rewriter::updt_local_params(params_ref const & _p) {
|
|||
m_split_concat_eq = p.split_concat_eq();
|
||||
m_udiv2mul = p.udiv2mul();
|
||||
m_bvnot2arith = p.bvnot2arith();
|
||||
m_bv_sort_ac = p.bv_sort_ac();
|
||||
m_mkbv2num = _p.get_bool("mkbv2num", false);
|
||||
}
|
||||
|
||||
|
@ -1315,7 +1316,7 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re
|
|||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
if (!flattened && !merged && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero()))) {
|
||||
if (!flattened && !merged && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero())) && (!m_bv_sort_ac || is_sorted(num, args))) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
@ -1331,6 +1332,8 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re
|
|||
result = new_args[0];
|
||||
return BR_DONE;
|
||||
default:
|
||||
if (m_bv_sort_ac)
|
||||
std::sort(new_args.begin(), new_args.end(), ast_to_lt());
|
||||
result = m_util.mk_bv_or(new_args.size(), new_args.c_ptr());
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -1456,7 +1459,8 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r
|
|||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (rational::power_of_two(sz) - numeral(1)))))
|
||||
if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (rational::power_of_two(sz) - numeral(1)))) &&
|
||||
(!m_bv_sort_ac || is_sorted(num, args)))
|
||||
return BR_FAILED;
|
||||
|
||||
ptr_buffer<expr> new_args;
|
||||
|
@ -1497,6 +1501,8 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r
|
|||
}
|
||||
__fallthrough;
|
||||
default:
|
||||
if (m_bv_sort_ac)
|
||||
std::sort(new_args.begin(), new_args.end(), ast_to_lt());
|
||||
result = m_util.mk_bv_xor(new_args.size(), new_args.c_ptr());
|
||||
return BR_DONE;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> {
|
|||
bool m_split_concat_eq;
|
||||
bool m_udiv2mul;
|
||||
bool m_bvnot2arith;
|
||||
bool m_bv_sort_ac;
|
||||
|
||||
bool is_zero_bit(expr * x, unsigned idx);
|
||||
|
||||
|
|
|
@ -8,5 +8,6 @@ def_module_params(module_name='rewriter',
|
|||
("elim_sign_ext", BOOL, True, "expand sign-ext operator using concat and extract"),
|
||||
("hi_div0", BOOL, True, "use the 'hardware interpretation' for division by zero (for bit-vector terms)"),
|
||||
("mul2concat", BOOL, False, "replace multiplication by a power of two into a concatenation"),
|
||||
("bvnot2arith", BOOL, False, "replace (bvnot x) with (bvsub -1 x)")
|
||||
("bvnot2arith", BOOL, False, "replace (bvnot x) with (bvsub -1 x)"),
|
||||
("bv_sort_ac", BOOL, False, "sort the arguments of all AC operators")
|
||||
))
|
||||
|
|
115
src/ast/rewriter/expr_safe_replace.cpp
Normal file
115
src/ast/rewriter/expr_safe_replace.cpp
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
expr_safe_replace.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Version of expr_replace/expr_substitution that is safe for quantifiers.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-11-30
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "expr_safe_replace.h"
|
||||
#include "rewriter.h"
|
||||
|
||||
|
||||
void expr_safe_replace::insert(expr* src, expr* dst) {
|
||||
m_src.push_back(src);
|
||||
m_dst.push_back(dst);
|
||||
m_subst.insert(src, dst);
|
||||
}
|
||||
|
||||
void expr_safe_replace::operator()(expr* e, expr_ref& res) {
|
||||
obj_map<expr,expr*> cache;
|
||||
ptr_vector<expr> todo, args;
|
||||
expr_ref_vector refs(m);
|
||||
todo.push_back(e);
|
||||
expr* a, *b, *d;
|
||||
todo.push_back(e);
|
||||
|
||||
while (!todo.empty()) {
|
||||
a = todo.back();
|
||||
if (cache.contains(a)) {
|
||||
todo.pop_back();
|
||||
}
|
||||
else if (m_subst.find(a, b)) {
|
||||
cache.insert(a, b);
|
||||
todo.pop_back();
|
||||
}
|
||||
else if (is_var(a)) {
|
||||
cache.insert(a, a);
|
||||
todo.pop_back();
|
||||
}
|
||||
else if (is_app(a)) {
|
||||
app* c = to_app(a);
|
||||
unsigned n = c->get_num_args();
|
||||
args.reset();
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
if (cache.find(c->get_arg(i), d)) {
|
||||
args.push_back(d);
|
||||
}
|
||||
else {
|
||||
todo.push_back(c->get_arg(i));
|
||||
}
|
||||
}
|
||||
if (args.size() == n) {
|
||||
b = m.mk_app(c->get_decl(), args.size(), args.c_ptr());
|
||||
refs.push_back(b);
|
||||
cache.insert(a, b);
|
||||
todo.pop_back();
|
||||
}
|
||||
}
|
||||
else {
|
||||
SASSERT(is_quantifier(a));
|
||||
quantifier* q = to_quantifier(a);
|
||||
expr_safe_replace replace(m);
|
||||
var_shifter shift(m);
|
||||
expr_ref new_body(m), src(m), dst(m), tmp(m);
|
||||
expr_ref_vector pats(m), nopats(m);
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
for (unsigned i = 0; i < m_src.size(); ++i) {
|
||||
shift(m_src[i].get(), num_decls, src);
|
||||
shift(m_dst[i].get(), num_decls, dst);
|
||||
replace.insert(src, dst);
|
||||
}
|
||||
unsigned np = q->get_num_patterns();
|
||||
for (unsigned i = 0; i < np; ++i) {
|
||||
replace(q->get_pattern(i), tmp);
|
||||
pats.push_back(tmp);
|
||||
}
|
||||
np = q->get_num_no_patterns();
|
||||
for (unsigned i = 0; i < np; ++i) {
|
||||
replace(q->get_no_pattern(i), tmp);
|
||||
nopats.push_back(tmp);
|
||||
}
|
||||
replace(q->get_expr(), new_body);
|
||||
b = m.update_quantifier(q, pats.size(), pats.c_ptr(), nopats.size(), nopats.c_ptr(), new_body);
|
||||
refs.push_back(b);
|
||||
cache.insert(a, b);
|
||||
todo.pop_back();
|
||||
}
|
||||
}
|
||||
res = cache.find(e);
|
||||
}
|
||||
|
||||
void expr_safe_replace::reset() {
|
||||
m_src.reset();
|
||||
m_dst.reset();
|
||||
m_subst.reset();
|
||||
}
|
||||
|
||||
void expr_safe_replace::apply_substitution(expr* s, expr* def, expr_ref& t) {
|
||||
reset();
|
||||
insert(s, def);
|
||||
(*this)(t, t);
|
||||
reset();
|
||||
}
|
47
src/ast/rewriter/expr_safe_replace.h
Normal file
47
src/ast/rewriter/expr_safe_replace.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
expr_safe_replace.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Version of expr_replace/expr_substitution that is safe for quantifiers.
|
||||
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-11-30
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __EXPR_SAFE_REPLACE_H__
|
||||
#define __EXPR_SAFE_REPLACE_H__
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
class expr_safe_replace {
|
||||
ast_manager& m;
|
||||
expr_ref_vector m_src;
|
||||
expr_ref_vector m_dst;
|
||||
obj_map<expr, expr*> m_subst;
|
||||
|
||||
public:
|
||||
expr_safe_replace(ast_manager& m): m(m), m_src(m), m_dst(m) {}
|
||||
|
||||
void insert(expr* src, expr* dst);
|
||||
|
||||
void operator()(expr_ref& e) { (*this)(e.get(), e); }
|
||||
|
||||
void operator()(expr* src, expr_ref& e);
|
||||
|
||||
void apply_substitution(expr* s, expr* def, expr_ref& t);
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
#endif /* __EXPR_SAFE_REPLACE_H__ */
|
|
@ -58,6 +58,10 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
|
|||
case OP_FLOAT_IS_ZERO: SASSERT(num_args == 1); st = mk_is_zero(args[0], result); break;
|
||||
case OP_FLOAT_IS_NZERO: SASSERT(num_args == 1); st = mk_is_nzero(args[0], result); break;
|
||||
case OP_FLOAT_IS_PZERO: SASSERT(num_args == 1); st = mk_is_pzero(args[0], result); break;
|
||||
case OP_FLOAT_IS_NAN: SASSERT(num_args == 1); st = mk_is_nan(args[0], result); break;
|
||||
case OP_FLOAT_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break;
|
||||
case OP_FLOAT_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break;
|
||||
case OP_FLOAT_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break;
|
||||
case OP_FLOAT_IS_SIGN_MINUS: SASSERT(num_args == 1); st = mk_is_sign_minus(args[0], result); break;
|
||||
case OP_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break;
|
||||
}
|
||||
|
@ -77,14 +81,27 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
|
|||
return BR_FAILED;
|
||||
|
||||
rational q;
|
||||
if (!m_util.au().is_numeral(args[1], q))
|
||||
mpf q_mpf;
|
||||
if (m_util.au().is_numeral(args[1], q)) {
|
||||
TRACE("fp_rewriter", tout << "q: " << q << std::endl; );
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq());
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (m_util.is_value(args[1], q_mpf)) {
|
||||
TRACE("fp_rewriter", tout << "q: " << m_util.fm().to_string(q_mpf) << std::endl; );
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q_mpf);
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
|
||||
return BR_DONE;
|
||||
}
|
||||
else
|
||||
return BR_FAILED;
|
||||
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq());
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (num_args == 3 &&
|
||||
m_util.is_rm(m().get_sort(args[0])) &&
|
||||
|
@ -104,11 +121,11 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
|
|||
return BR_FAILED;
|
||||
|
||||
TRACE("fp_rewriter", tout << "q: " << q << ", e: " << e << "\n";);
|
||||
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq(), e.to_mpq().numerator());
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
m_util.fm().del(v);
|
||||
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
|
@ -217,8 +234,7 @@ br_status float_rewriter::mk_abs(expr * arg1, expr_ref & result) {
|
|||
result = arg1;
|
||||
return BR_DONE;
|
||||
}
|
||||
sort * s = m().get_sort(arg1);
|
||||
result = m().mk_ite(m_util.mk_lt(arg1, m_util.mk_pzero(s)),
|
||||
result = m().mk_ite(m_util.mk_is_sign_minus(arg1),
|
||||
m_util.mk_uminus(arg1),
|
||||
arg1);
|
||||
return BR_REWRITE2;
|
||||
|
@ -234,13 +250,13 @@ br_status float_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
return BR_DONE;
|
||||
}
|
||||
// expand as using ite's
|
||||
result = m().mk_ite(mk_eq_nan(arg1),
|
||||
result = m().mk_ite(m().mk_or(mk_eq_nan(arg1), m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2))),
|
||||
arg2,
|
||||
m().mk_ite(mk_eq_nan(arg2),
|
||||
arg1,
|
||||
m().mk_ite(m_util.mk_lt(arg1, arg2),
|
||||
arg1,
|
||||
arg2)));
|
||||
arg1,
|
||||
arg2)));
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
|
||||
|
@ -254,7 +270,7 @@ br_status float_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
return BR_DONE;
|
||||
}
|
||||
// expand as using ite's
|
||||
result = m().mk_ite(mk_eq_nan(arg1),
|
||||
result = m().mk_ite(m().mk_or(mk_eq_nan(arg1), m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2))),
|
||||
arg2,
|
||||
m().mk_ite(mk_eq_nan(arg2),
|
||||
arg1,
|
||||
|
@ -420,6 +436,46 @@ br_status float_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) {
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_nan(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_nan(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_inf(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_inf(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_normal(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_normal(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_denormal(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_sign_minus(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
|
|
|
@ -66,6 +66,10 @@ public:
|
|||
br_status mk_is_zero(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_nzero(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_pzero(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_nan(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_inf(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_normal(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_subnormal(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_sign_minus(expr * arg1, expr_ref & result);
|
||||
|
||||
br_status mk_to_ieee_bv(expr * arg1, expr_ref & result);
|
||||
|
|
|
@ -62,6 +62,8 @@ struct mk_simplified_app::imp {
|
|||
st = m_dt_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_f_rw.get_fid())
|
||||
st = m_f_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_ar_rw.get_fid())
|
||||
st = m_ar_rw.mk_eq_core(args[0], args[1], result);
|
||||
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,7 +25,8 @@ Revision History:
|
|||
#include "bool_rewriter.h"
|
||||
#include "var_subst.h"
|
||||
#include "ast_pp.h"
|
||||
|
||||
#include "ast_counter.h"
|
||||
#include "expr_safe_replace.h"
|
||||
|
||||
//
|
||||
// Bring quantifiers of common type into prenex form.
|
||||
|
@ -42,7 +43,7 @@ public:
|
|||
|
||||
void operator()(expr* fml, app_ref_vector& vars, bool& is_fa, expr_ref& result) {
|
||||
quantifier_type qt = Q_none_pos;
|
||||
pull_quantifiers(fml, qt, vars, result);
|
||||
pull_quantifier(fml, qt, vars, result);
|
||||
TRACE("qe_verbose",
|
||||
tout << mk_pp(fml, m) << "\n";
|
||||
tout << mk_pp(result, m) << "\n";);
|
||||
|
@ -52,7 +53,7 @@ public:
|
|||
|
||||
void pull_exists(expr* fml, app_ref_vector& vars, expr_ref& result) {
|
||||
quantifier_type qt = Q_exists_pos;
|
||||
pull_quantifiers(fml, qt, vars, result);
|
||||
pull_quantifier(fml, qt, vars, result);
|
||||
TRACE("qe_verbose",
|
||||
tout << mk_pp(fml, m) << "\n";
|
||||
tout << mk_pp(result, m) << "\n";);
|
||||
|
@ -61,7 +62,7 @@ public:
|
|||
void pull_quantifier(bool is_forall, expr_ref& fml, app_ref_vector& vars) {
|
||||
quantifier_type qt = is_forall?Q_forall_pos:Q_exists_pos;
|
||||
expr_ref result(m);
|
||||
pull_quantifiers(fml, qt, vars, result);
|
||||
pull_quantifier(fml, qt, vars, result);
|
||||
TRACE("qe_verbose",
|
||||
tout << mk_pp(fml, m) << "\n";
|
||||
tout << mk_pp(result, m) << "\n";);
|
||||
|
@ -78,7 +79,57 @@ public:
|
|||
expr * const * exprs = (expr* const*) (vars.c_ptr() + vars.size()- nd);
|
||||
instantiate(m, q, exprs, result);
|
||||
}
|
||||
|
||||
|
||||
unsigned pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names) {
|
||||
unsigned index = var_counter().get_next_var(fml);
|
||||
while (is_quantifier(fml) && (is_forall == to_quantifier(fml)->is_forall())) {
|
||||
quantifier* q = to_quantifier(fml);
|
||||
index += q->get_num_decls();
|
||||
if (names) {
|
||||
names->append(q->get_num_decls(), q->get_decl_names());
|
||||
}
|
||||
if (sorts) {
|
||||
sorts->append(q->get_num_decls(), q->get_decl_sorts());
|
||||
}
|
||||
fml = q->get_expr();
|
||||
}
|
||||
if (!has_quantifiers(fml)) {
|
||||
return index;
|
||||
}
|
||||
app_ref_vector vars(m);
|
||||
pull_quantifier(is_forall, fml, vars);
|
||||
if (vars.empty()) {
|
||||
return index;
|
||||
}
|
||||
// replace vars by de-bruijn indices
|
||||
expr_safe_replace rep(m);
|
||||
svector<symbol> bound_names;
|
||||
ptr_vector<sort> bound_sorts;
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
app* v = vars[i].get();
|
||||
if (names) {
|
||||
bound_names.push_back(v->get_decl()->get_name());
|
||||
}
|
||||
if (sorts) {
|
||||
bound_sorts.push_back(m.get_sort(v));
|
||||
}
|
||||
rep.insert(v, m.mk_var(index++, m.get_sort(v)));
|
||||
}
|
||||
if (names && !bound_names.empty()) {
|
||||
bound_names.reverse();
|
||||
bound_names.append(*names);
|
||||
names->reset();
|
||||
names->append(bound_names);
|
||||
}
|
||||
if (sorts && !bound_sorts.empty()) {
|
||||
bound_sorts.reverse();
|
||||
bound_sorts.append(*sorts);
|
||||
sorts->reset();
|
||||
sorts->append(bound_sorts);
|
||||
}
|
||||
rep(fml);
|
||||
return index;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
@ -143,7 +194,7 @@ private:
|
|||
}
|
||||
|
||||
|
||||
void pull_quantifiers(expr* fml, quantifier_type& qt, app_ref_vector& vars, expr_ref& result) {
|
||||
void pull_quantifier(expr* fml, quantifier_type& qt, app_ref_vector& vars, expr_ref& result) {
|
||||
|
||||
if (!has_quantifiers(fml)) {
|
||||
result = fml;
|
||||
|
@ -159,7 +210,7 @@ private:
|
|||
if (m.is_and(fml)) {
|
||||
num_args = a->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
pull_quantifiers(a->get_arg(i), qt, vars, tmp);
|
||||
pull_quantifier(a->get_arg(i), qt, vars, tmp);
|
||||
args.push_back(tmp);
|
||||
}
|
||||
m_rewriter.mk_and(args.size(), args.c_ptr(), result);
|
||||
|
@ -167,25 +218,25 @@ private:
|
|||
else if (m.is_or(fml)) {
|
||||
num_args = to_app(fml)->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
pull_quantifiers(to_app(fml)->get_arg(i), qt, vars, tmp);
|
||||
pull_quantifier(to_app(fml)->get_arg(i), qt, vars, tmp);
|
||||
args.push_back(tmp);
|
||||
}
|
||||
m_rewriter.mk_or(args.size(), args.c_ptr(), result);
|
||||
}
|
||||
else if (m.is_not(fml)) {
|
||||
pull_quantifiers(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
|
||||
pull_quantifier(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
|
||||
negate(qt);
|
||||
result = m.mk_not(tmp);
|
||||
}
|
||||
else if (m.is_implies(fml)) {
|
||||
pull_quantifiers(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
|
||||
pull_quantifier(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
|
||||
negate(qt);
|
||||
pull_quantifiers(to_app(fml)->get_arg(1), qt, vars, result);
|
||||
pull_quantifier(to_app(fml)->get_arg(1), qt, vars, result);
|
||||
result = m.mk_implies(tmp, result);
|
||||
}
|
||||
else if (m.is_ite(fml)) {
|
||||
pull_quantifiers(to_app(fml)->get_arg(1), qt, vars, tmp);
|
||||
pull_quantifiers(to_app(fml)->get_arg(2), qt, vars, result);
|
||||
pull_quantifier(to_app(fml)->get_arg(1), qt, vars, tmp);
|
||||
pull_quantifier(to_app(fml)->get_arg(2), qt, vars, result);
|
||||
result = m.mk_ite(to_app(fml)->get_arg(0), tmp, result);
|
||||
}
|
||||
else {
|
||||
|
@ -203,7 +254,7 @@ private:
|
|||
}
|
||||
set_quantifier_type(qt, q->is_forall());
|
||||
extract_quantifier(q, vars, tmp);
|
||||
pull_quantifiers(tmp, qt, vars, result);
|
||||
pull_quantifier(tmp, qt, vars, result);
|
||||
break;
|
||||
}
|
||||
case AST_VAR:
|
||||
|
@ -215,6 +266,7 @@ private:
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
quantifier_hoister::quantifier_hoister(ast_manager& m) {
|
||||
|
@ -237,3 +289,6 @@ void quantifier_hoister::pull_quantifier(bool is_forall, expr_ref& fml, app_ref_
|
|||
m_impl->pull_quantifier(is_forall, fml, vars);
|
||||
}
|
||||
|
||||
unsigned quantifier_hoister::pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names) {
|
||||
return m_impl->pull_quantifier(is_forall, fml, sorts, names);
|
||||
}
|
||||
|
|
|
@ -59,6 +59,15 @@ public:
|
|||
The list of variables is empty if there are no top-level universal/existential quantifier.
|
||||
*/
|
||||
void pull_quantifier(bool is_forall, expr_ref& fml, app_ref_vector& vars);
|
||||
|
||||
/**
|
||||
\brief Pull top-most universal (is_forall true) or existential (is_forall=false) quantifier up.
|
||||
Return an expression with de-Bruijn indices and the list of names that were used.
|
||||
Return index of maximal variable.
|
||||
*/
|
||||
|
||||
unsigned pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -169,7 +169,9 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
st = m_dt_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_f_rw.get_fid())
|
||||
st = m_f_rw.mk_eq_core(args[0], args[1], result);
|
||||
|
||||
else if (s_fid == m_ar_rw.get_fid())
|
||||
st = m_ar_rw.mk_eq_core(args[0], args[1], result);
|
||||
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ Notes:
|
|||
|
||||
--*/
|
||||
#include"var_subst.h"
|
||||
#include"used_vars.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
@ -40,7 +39,7 @@ void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, exp
|
|||
tout << mk_ismt2_pp(result, m_reducer.m()) << "\n";);
|
||||
}
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
||||
void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
||||
SASSERT(is_well_sorted(m, q));
|
||||
if (is_ground(q->get_expr())) {
|
||||
// ignore patterns if the body is a ground formula.
|
||||
|
@ -51,17 +50,17 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
result = q;
|
||||
return;
|
||||
}
|
||||
used_vars used;
|
||||
used.process(q->get_expr());
|
||||
m_used.reset();
|
||||
m_used.process(q->get_expr());
|
||||
unsigned num_patterns = q->get_num_patterns();
|
||||
for (unsigned i = 0; i < num_patterns; i++)
|
||||
used.process(q->get_pattern(i));
|
||||
m_used.process(q->get_pattern(i));
|
||||
unsigned num_no_patterns = q->get_num_no_patterns();
|
||||
for (unsigned i = 0; i < num_no_patterns; i++)
|
||||
used.process(q->get_no_pattern(i));
|
||||
m_used.process(q->get_no_pattern(i));
|
||||
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
if (used.uses_all_vars(num_decls)) {
|
||||
if (m_used.uses_all_vars(num_decls)) {
|
||||
q->set_no_unused_vars();
|
||||
result = q;
|
||||
return;
|
||||
|
@ -70,7 +69,7 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
ptr_buffer<sort> used_decl_sorts;
|
||||
buffer<symbol> used_decl_names;
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
if (used.contains(num_decls - i - 1)) {
|
||||
if (m_used.contains(num_decls - i - 1)) {
|
||||
used_decl_sorts.push_back(q->get_decl_sort(i));
|
||||
used_decl_names.push_back(q->get_decl_name(i));
|
||||
}
|
||||
|
@ -79,10 +78,10 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
unsigned num_removed = 0;
|
||||
expr_ref_buffer var_mapping(m);
|
||||
int next_idx = 0;
|
||||
unsigned sz = used.get_max_found_var_idx_plus_1();
|
||||
unsigned sz = m_used.get_max_found_var_idx_plus_1();
|
||||
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
sort * s = used.contains(i);
|
||||
sort * s = m_used.contains(i);
|
||||
if (s) {
|
||||
var_mapping.push_back(m.mk_var(next_idx, s));
|
||||
next_idx++;
|
||||
|
@ -95,7 +94,7 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
// (VAR 0) is in the first position of var_mapping.
|
||||
|
||||
for (unsigned i = num_decls; i < sz; i++) {
|
||||
sort * s = used.contains(i);
|
||||
sort * s = m_used.contains(i);
|
||||
if (s)
|
||||
var_mapping.push_back(m.mk_var(i - num_removed, s));
|
||||
else
|
||||
|
@ -110,9 +109,8 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
std::reverse(var_mapping.c_ptr(), var_mapping.c_ptr() + var_mapping.size());
|
||||
|
||||
expr_ref new_expr(m);
|
||||
var_subst subst(m);
|
||||
|
||||
subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr(), new_expr);
|
||||
m_subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr(), new_expr);
|
||||
|
||||
if (num_removed == num_decls) {
|
||||
result = new_expr;
|
||||
|
@ -124,11 +122,11 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
expr_ref_buffer new_no_patterns(m);
|
||||
|
||||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
m_subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
new_patterns.push_back(tmp);
|
||||
}
|
||||
for (unsigned i = 0; i < num_no_patterns; i++) {
|
||||
subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
m_subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
new_no_patterns.push_back(tmp);
|
||||
}
|
||||
|
||||
|
@ -145,7 +143,12 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
num_no_patterns,
|
||||
new_no_patterns.c_ptr());
|
||||
to_quantifier(result)->set_no_unused_vars();
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
||||
unused_vars_eliminator el(m);
|
||||
el(q, result);
|
||||
}
|
||||
|
||||
void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref & result) {
|
||||
|
@ -161,9 +164,7 @@ void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref
|
|||
tout << "\n----->\n" << mk_ismt2_pp(result, m) << "\n";);
|
||||
}
|
||||
|
||||
static void get_free_vars_offset(expr* e, unsigned offset, ptr_vector<sort>& sorts) {
|
||||
ast_mark mark;
|
||||
ptr_vector<expr> todo;
|
||||
static void get_free_vars_offset(ast_mark& mark, ptr_vector<expr>& todo, unsigned offset, expr* e, ptr_vector<sort>& sorts) {
|
||||
todo.push_back(e);
|
||||
while (!todo.empty()) {
|
||||
e = todo.back();
|
||||
|
@ -175,7 +176,9 @@ static void get_free_vars_offset(expr* e, unsigned offset, ptr_vector<sort>& sor
|
|||
switch(e->get_kind()) {
|
||||
case AST_QUANTIFIER: {
|
||||
quantifier* q = to_quantifier(e);
|
||||
get_free_vars_offset(q->get_expr(), offset+q->get_num_decls(), sorts);
|
||||
ast_mark mark1;
|
||||
ptr_vector<expr> todo1;
|
||||
get_free_vars_offset(mark1, todo1, offset+q->get_num_decls(), q->get_expr(), sorts);
|
||||
break;
|
||||
}
|
||||
case AST_VAR: {
|
||||
|
@ -207,5 +210,11 @@ static void get_free_vars_offset(expr* e, unsigned offset, ptr_vector<sort>& sor
|
|||
|
||||
|
||||
void get_free_vars(expr* e, ptr_vector<sort>& sorts) {
|
||||
get_free_vars_offset(e, 0, sorts);
|
||||
ast_mark mark;
|
||||
ptr_vector<expr> todo;
|
||||
get_free_vars_offset(mark, todo, 0, e, sorts);
|
||||
}
|
||||
|
||||
void get_free_vars(ast_mark& mark, ptr_vector<expr>& todo, expr* e, ptr_vector<sort>& sorts) {
|
||||
get_free_vars_offset(mark, todo, 0, e, sorts);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ Notes:
|
|||
#define _VAR_SUBST_H_
|
||||
|
||||
#include"rewriter.h"
|
||||
#include"used_vars.h"
|
||||
|
||||
/**
|
||||
\brief Alias for var_shifter class.
|
||||
|
@ -53,6 +54,15 @@ public:
|
|||
/**
|
||||
\brief Eliminate the unused variables from \c q. Store the result in \c r.
|
||||
*/
|
||||
class unused_vars_eliminator {
|
||||
ast_manager& m;
|
||||
var_subst m_subst;
|
||||
used_vars m_used;
|
||||
public:
|
||||
unused_vars_eliminator(ast_manager& m): m(m), m_subst(m) {}
|
||||
void operator()(quantifier* q, expr_ref& r);
|
||||
};
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & r);
|
||||
|
||||
/**
|
||||
|
@ -73,6 +83,8 @@ void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref
|
|||
*/
|
||||
void get_free_vars(expr* e, ptr_vector<sort>& sorts);
|
||||
|
||||
void get_free_vars(ast_mark& mark, ptr_vector<expr>& todo, expr* e, ptr_vector<sort>& sorts);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
55
src/ast/scoped_proof.h
Normal file
55
src/ast/scoped_proof.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
scoped_proof.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Scoped proof environments. Toggles enabling proofs.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-08-28
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SCOPED_PROOF__H_
|
||||
#define _SCOPED_PROOF_H_
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
class scoped_proof_mode {
|
||||
ast_manager& m;
|
||||
proof_gen_mode m_mode;
|
||||
public:
|
||||
scoped_proof_mode(ast_manager& m, proof_gen_mode mode): m(m) {
|
||||
m_mode = m.proof_mode();
|
||||
m.toggle_proof_mode(mode);
|
||||
}
|
||||
~scoped_proof_mode() {
|
||||
m.toggle_proof_mode(m_mode);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class scoped_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_proof(ast_manager& m): scoped_proof_mode(m, PGM_FINE) {}
|
||||
};
|
||||
|
||||
class scoped_no_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_no_proof(ast_manager& m): scoped_proof_mode(m, PGM_DISABLED) {}
|
||||
};
|
||||
|
||||
class scoped_restore_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_restore_proof(ast_manager& m): scoped_proof_mode(m, m.proof_mode()) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -179,7 +179,7 @@ bool bv_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * const
|
|||
}
|
||||
SASSERT(result.get());
|
||||
|
||||
TRACE("bv_simplifier",
|
||||
TRACE("bv_simplifier",
|
||||
tout << mk_pp(f, m_manager) << "\n";
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
tout << mk_pp(args[i], m_manager) << " ";
|
||||
|
@ -636,7 +636,31 @@ bool bv_simplifier_plugin::try_mk_extract(unsigned high, unsigned low, expr * ar
|
|||
if (!all_found) {
|
||||
return false;
|
||||
}
|
||||
result = m_manager.mk_app(m_fid, a->get_decl_kind(), new_args.size(), new_args.c_ptr());
|
||||
// We should not use mk_app because it does not guarantee that the result would be in simplified form.
|
||||
// result = m_manager.mk_app(m_fid, a->get_decl_kind(), new_args.size(), new_args.c_ptr());
|
||||
if (is_app_of(a, m_fid, OP_BAND))
|
||||
mk_bv_and(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BOR))
|
||||
mk_bv_or(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BXOR))
|
||||
mk_bv_xor(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BNOR))
|
||||
mk_bv_nor(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BNAND))
|
||||
mk_bv_nand(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BNOT)) {
|
||||
SASSERT(new_args.size() == 1);
|
||||
mk_bv_not(new_args[0], result);
|
||||
}
|
||||
else if (is_app_of(a, m_fid, OP_BADD))
|
||||
mk_add(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BMUL))
|
||||
mk_mul(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BSUB))
|
||||
mk_sub(new_args.size(), new_args.c_ptr(), result);
|
||||
else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (m_manager.is_ite(a)) {
|
||||
|
@ -747,16 +771,16 @@ void bv_simplifier_plugin::mk_bv_eq(expr* a1, expr* a2, expr_ref& result) {
|
|||
expr * arg1 = *it1;
|
||||
expr * arg2 = *it2;
|
||||
TRACE("expr_bv_util", tout << "low1: " << low1 << " low2: " << low2 << "\n";
|
||||
ast_ll_pp(tout, m_manager, arg1);
|
||||
ast_ll_pp(tout, m_manager, arg2););
|
||||
tout << mk_pp(arg1, m_manager) << "\n";
|
||||
tout << mk_pp(arg2, m_manager) << "\n";);
|
||||
unsigned sz1 = get_bv_size(arg1);
|
||||
unsigned sz2 = get_bv_size(arg2);
|
||||
SASSERT(low1 < sz1 && low2 < sz2);
|
||||
unsigned rsz1 = sz1 - low1;
|
||||
unsigned rsz2 = sz2 - low2;
|
||||
TRACE("expr_bv_util", tout << "rsz1: " << rsz1 << " rsz2: " << rsz2 << "\n";
|
||||
ast_ll_pp(tout, m_manager, arg1); ast_ll_pp(tout, m_manager, arg2););
|
||||
|
||||
tout << mk_pp(arg1, m_manager) << "\n";
|
||||
tout << mk_pp(arg2, m_manager) << "\n";);
|
||||
|
||||
if (rsz1 == rsz2) {
|
||||
mk_extract(sz1 - 1, low1, arg1, lhs);
|
||||
|
@ -826,9 +850,9 @@ void bv_simplifier_plugin::mk_eq_core(expr * arg1, expr * arg2, expr_ref & resul
|
|||
}
|
||||
m_bsimp.mk_and(tmps.size(), tmps.c_ptr(), result);
|
||||
TRACE("mk_eq_bb",
|
||||
ast_ll_pp(tout, m_manager, arg1);
|
||||
ast_ll_pp(tout, m_manager, arg2);
|
||||
ast_ll_pp(tout, m_manager, result););
|
||||
tout << mk_pp(arg1, m_manager) << "\n";
|
||||
tout << mk_pp(arg2, m_manager) << "\n";
|
||||
tout << mk_pp(result, m_manager) << "\n";);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@ Author:
|
|||
#include"ast_pp.h"
|
||||
#include"ast_util.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
|
||||
poly_simplifier_plugin::poly_simplifier_plugin(symbol const & fname, ast_manager & m, decl_kind add, decl_kind mul, decl_kind uminus, decl_kind sub,
|
||||
decl_kind num):
|
||||
|
@ -173,7 +174,7 @@ void poly_simplifier_plugin::mk_monomial(unsigned num_args, expr * * args, expr_
|
|||
result = args[0];
|
||||
break;
|
||||
default:
|
||||
std::sort(args, args + num_args, monomial_element_lt_proc(*this));
|
||||
std::stable_sort(args, args + num_args, monomial_element_lt_proc(*this));
|
||||
result = mk_mul(num_args, args);
|
||||
SASSERT(wf_monomial(result));
|
||||
break;
|
||||
|
@ -284,6 +285,7 @@ bool poly_simplifier_plugin::merge_monomials(bool inv, expr * n1, expr * n2, exp
|
|||
else
|
||||
result = m_manager.mk_app(m_fid, m_MUL, mk_numeral(k1), b);
|
||||
}
|
||||
TRACE("merge_monomials", tout << mk_pp(n1, m_manager) << "\n" << mk_pp(n2, m_manager) << "\n" << mk_pp(result, m_manager) << "\n";);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -465,7 +467,9 @@ void poly_simplifier_plugin::mk_sum_of_monomials(expr_ref_vector & monomials, ex
|
|||
result = monomials.get(0);
|
||||
break;
|
||||
default: {
|
||||
std::sort(monomials.c_ptr(), monomials.c_ptr() + monomials.size(), monomial_lt_proc(*this));
|
||||
TRACE("mk_sum_sort", tout << "before\n"; for (unsigned i = 0; i < monomials.size(); i++) tout << mk_ll_pp(monomials.get(i), m_manager) << "\n";);
|
||||
std::stable_sort(monomials.c_ptr(), monomials.c_ptr() + monomials.size(), monomial_lt_proc(*this));
|
||||
TRACE("mk_sum_sort", tout << "after\n"; for (unsigned i = 0; i < monomials.size(); i++) tout << mk_ll_pp(monomials.get(i), m_manager) << "\n";);
|
||||
if (is_simple_sum_of_monomials(monomials)) {
|
||||
mk_sum_of_monomials_core(monomials.size(), monomials.c_ptr(), result);
|
||||
return;
|
||||
|
|
|
@ -18,10 +18,6 @@ Revision History:
|
|||
--*/
|
||||
#include"matcher.h"
|
||||
|
||||
matcher::matcher(ast_manager & m):
|
||||
m_manager(m) {
|
||||
}
|
||||
|
||||
bool matcher::operator()(expr * e1, expr * e2, substitution & s) {
|
||||
reset();
|
||||
m_subst = &s;
|
||||
|
|
|
@ -30,7 +30,6 @@ class matcher {
|
|||
typedef pair_hash<obj_ptr_hash<expr>, obj_ptr_hash<expr> > expr_pair_hash;
|
||||
typedef hashtable<expr_pair, expr_pair_hash, default_eq<expr_pair> > cache;
|
||||
|
||||
ast_manager & m_manager;
|
||||
substitution * m_subst;
|
||||
// cache m_cache;
|
||||
svector<expr_pair> m_todo;
|
||||
|
@ -38,7 +37,7 @@ class matcher {
|
|||
void reset();
|
||||
|
||||
public:
|
||||
matcher(ast_manager & m);
|
||||
matcher() {}
|
||||
|
||||
/**
|
||||
\brief Return true if e2 is an instance of e1.
|
||||
|
|
|
@ -148,7 +148,7 @@ void substitution::apply(unsigned num_actual_offsets, unsigned const * deltas, e
|
|||
expr * arg = to_app(e)->get_arg(i);
|
||||
expr * new_arg;
|
||||
|
||||
m_apply_cache.find(expr_offset(arg, off), new_arg);
|
||||
VERIFY(m_apply_cache.find(expr_offset(arg, off), new_arg));
|
||||
new_args.push_back(new_arg);
|
||||
if (arg != new_arg)
|
||||
has_new_args = true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue