mirror of
https://github.com/Z3Prover/z3
synced 2025-10-03 14:33:56 +00:00
Merge branch 'unstable' into contrib
This commit is contained in:
commit
f773f35517
177 changed files with 8165 additions and 2548 deletions
|
@ -1,160 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
ast_list.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Quick hack to have lists of ASTs.
|
||||
The lists have hash-consing.
|
||||
This is a substitute for the old expr_lists implemented on top of the ASTs.
|
||||
The new lists live in a different manager and do not affect the ast_manager.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-01-06.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _AST_LIST_H_
|
||||
#define _AST_LIST_H_
|
||||
|
||||
#include"ast.h"
|
||||
|
||||
template<typename AST>
|
||||
class ast_list_manager_tpl;
|
||||
|
||||
template<typename AST>
|
||||
class ast_list_tpl {
|
||||
public:
|
||||
typedef ast_list_tpl list;
|
||||
private:
|
||||
unsigned m_id;
|
||||
unsigned m_is_nil:1;
|
||||
unsigned m_ref_count:31;
|
||||
AST * m_head;
|
||||
list * m_tail;
|
||||
|
||||
ast_list_tpl():
|
||||
m_is_nil(true),
|
||||
m_ref_count(0),
|
||||
m_head(0),
|
||||
m_tail(0) {
|
||||
}
|
||||
|
||||
ast_list_tpl(AST * h, list * t):
|
||||
m_is_nil(false),
|
||||
m_ref_count(0),
|
||||
m_head(h),
|
||||
m_tail(t) {
|
||||
}
|
||||
|
||||
friend class ast_list_manager_tpl<AST>;
|
||||
|
||||
struct hash_proc;
|
||||
friend struct hash_proc;
|
||||
|
||||
struct hash_proc {
|
||||
unsigned operator()(ast_list_tpl * l) const {
|
||||
unsigned h1 = l->m_head ? l->m_head->get_id() : 5;
|
||||
unsigned h2 = l->m_tail ? l->m_tail->get_id() : 7;
|
||||
return hash_u_u(h1, h2);
|
||||
}
|
||||
};
|
||||
|
||||
struct eq_proc;
|
||||
friend struct eq_proc;
|
||||
|
||||
struct eq_proc {
|
||||
bool operator()(ast_list_tpl * l1, ast_list_tpl * l2) const {
|
||||
return l1->m_head == l2->m_head && l1->m_tail == l2->m_tail;
|
||||
}
|
||||
};
|
||||
|
||||
typedef ptr_hashtable<list, hash_proc, eq_proc> table; // for hash consing
|
||||
|
||||
public:
|
||||
unsigned get_id() const { return m_id; }
|
||||
unsigned get_ref_count() const { return m_ref_count; }
|
||||
unsigned hash() const { return m_id; }
|
||||
|
||||
friend inline bool is_nil(list const * l) { return l->m_is_nil == true; }
|
||||
friend inline bool is_cons(list const * l) { return !is_nil(l); }
|
||||
friend inline AST * head(list const * l) { SASSERT(is_cons(l)); return l->m_head; }
|
||||
friend inline list * tail(list const * l) { SASSERT(is_cons(l)); return l->m_tail; }
|
||||
};
|
||||
|
||||
template<typename AST>
|
||||
class ast_list_manager_tpl {
|
||||
public:
|
||||
typedef ast_list_tpl<AST> list;
|
||||
typedef obj_hashtable<list> list_set;
|
||||
private:
|
||||
typedef typename list::table table;
|
||||
ast_manager & m_manager;
|
||||
small_object_allocator m_allocator;
|
||||
table m_table;
|
||||
id_gen m_id_gen;
|
||||
list m_nil;
|
||||
|
||||
public:
|
||||
ast_list_manager_tpl(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_nil() {
|
||||
m_nil.m_id = m_id_gen.mk();
|
||||
m_nil.m_ref_count = 1;
|
||||
}
|
||||
|
||||
void inc_ref(list * l) {
|
||||
if (l != 0) {
|
||||
l->m_ref_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void dec_ref(list * l) {
|
||||
while (l != 0) {
|
||||
SASSERT(l->m_ref_count > 0);
|
||||
l->m_ref_count--;
|
||||
if (l->m_ref_count > 0)
|
||||
return;
|
||||
SASSERT(l != &m_nil);
|
||||
m_table.erase(l);
|
||||
m_manager.dec_ref(l->m_head);
|
||||
m_id_gen.recycle(l->m_id);
|
||||
list * old_l = l;
|
||||
l = l->m_tail;
|
||||
m_allocator.deallocate(sizeof(list), old_l);
|
||||
}
|
||||
}
|
||||
|
||||
list * mk_nil() { return &m_nil; }
|
||||
|
||||
list * mk_cons(AST * h, list * l) {
|
||||
list tmp(h, l);
|
||||
list * r = 0;
|
||||
if (m_table.find(&tmp, r))
|
||||
return r;
|
||||
r = new (m_allocator.allocate(sizeof(list))) list(h, l);
|
||||
m_manager.inc_ref(h);
|
||||
inc_ref(l);
|
||||
r->m_id = m_id_gen.mk();
|
||||
m_table.insert(r);
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
typedef ast_list_tpl<expr> expr_list;
|
||||
typedef ast_list_manager_tpl<expr> expr_list_manager;
|
||||
|
||||
typedef ast_list_tpl<quantifier> quantifier_list;
|
||||
typedef ast_list_manager_tpl<quantifier> quantifier_list_manager;
|
||||
|
||||
typedef obj_ref<expr_list, expr_list_manager> expr_list_ref;
|
||||
typedef obj_ref<quantifier_list, quantifier_list_manager> quantifier_list_ref;
|
||||
typedef ref_vector<expr_list, expr_list_manager> expr_list_ref_vector;
|
||||
typedef ref_vector<quantifier_list, quantifier_list_manager> quantifier_list_ref_vector;
|
||||
|
||||
#endif
|
|
@ -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); }
|
||||
|
|
|
@ -766,7 +766,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 +774,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); }
|
||||
|
|
|
@ -151,6 +151,10 @@ sort * float_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, paramete
|
|||
if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) {
|
||||
m_manager->raise_exception("expecting two integer parameters to floating point sort");
|
||||
}
|
||||
if (parameters[0].get_int() <= 1 || parameters[1].get_int() <= 1)
|
||||
m_manager->raise_exception("floating point sorts need parameters > 1");
|
||||
if (parameters[0].get_int() > parameters[1].get_int())
|
||||
m_manager->raise_exception("floating point sorts with ebits > sbits are currently not supported");
|
||||
return mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
case ROUNDING_MODE_SORT:
|
||||
return mk_rm_sort();
|
||||
|
@ -349,27 +353,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)
|
||||
m_manager->raise_exception("invalid number of arguments to asFloat operator");
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,6 +491,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;
|
||||
|
|
|
@ -140,6 +140,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); }
|
||||
|
||||
|
|
|
@ -596,8 +596,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";);
|
||||
|
@ -791,7 +792,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();
|
||||
|
@ -809,7 +813,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -981,14 +981,6 @@ br_status arith_rewriter::mk_to_real_core(expr * arg, expr_ref & result) {
|
|||
result = m_util.mk_numeral(a, false);
|
||||
return BR_DONE;
|
||||
}
|
||||
#if 0
|
||||
// The following rewriting rule is not correct.
|
||||
// It is used only for making experiments.
|
||||
if (m_util.is_to_int(arg)) {
|
||||
result = to_app(arg)->get_arg(0);
|
||||
return BR_DONE;
|
||||
}
|
||||
#endif
|
||||
// push to_real over OP_ADD, OP_MUL
|
||||
if (m_push_to_real) {
|
||||
if (m_util.is_add(arg) || m_util.is_mul(arg)) {
|
||||
|
|
165
src/ast/rewriter/ast_counter.cpp
Normal file
165
src/ast/rewriter/ast_counter.cpp
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*++
|
||||
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();
|
||||
::get_free_vars(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;
|
||||
while (!m_todo.empty()) {
|
||||
expr* e = m_todo.back();
|
||||
unsigned scope = m_scopes.back();
|
||||
m_todo.pop_back();
|
||||
m_scopes.pop_back();
|
||||
if (m_visited.is_marked(e)) {
|
||||
continue;
|
||||
}
|
||||
m_visited.mark(e, true);
|
||||
switch(e->get_kind()) {
|
||||
case AST_QUANTIFIER: {
|
||||
quantifier* q = to_quantifier(e);
|
||||
m_todo.push_back(q->get_expr());
|
||||
m_scopes.push_back(scope + q->get_num_decls());
|
||||
break;
|
||||
}
|
||||
case AST_VAR: {
|
||||
if (to_var(e)->get_idx() >= scope + max_var) {
|
||||
has_var = true;
|
||||
max_var = to_var(e)->get_idx() - scope;
|
||||
}
|
||||
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));
|
||||
m_scopes.push_back(scope);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_visited.reset();
|
||||
return max_var;
|
||||
}
|
||||
|
||||
|
||||
unsigned var_counter::get_max_var(expr* e) {
|
||||
bool has_var = false;
|
||||
m_todo.push_back(e);
|
||||
m_scopes.push_back(0);
|
||||
return get_max_var(has_var);
|
||||
}
|
||||
|
||||
unsigned var_counter::get_next_var(expr* e) {
|
||||
bool has_var = false;
|
||||
m_todo.push_back(e);
|
||||
m_scopes.push_back(0);
|
||||
unsigned mv = get_max_var(has_var);
|
||||
if (has_var) mv++;
|
||||
return mv;
|
||||
}
|
||||
|
107
src/ast/rewriter/ast_counter.h
Normal file
107
src/ast/rewriter/ast_counter.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*++
|
||||
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) {}
|
||||
|
||||
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;
|
||||
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")
|
||||
))
|
||||
|
|
108
src/ast/rewriter/expr_safe_replace.cpp
Normal file
108
src/ast/rewriter/expr_safe_replace.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*++
|
||||
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();
|
||||
}
|
45
src/ast/rewriter/expr_safe_replace.h
Normal file
45
src/ast/rewriter/expr_safe_replace.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*++
|
||||
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 reset();
|
||||
};
|
||||
|
||||
#endif /* __EXPR_SAFE_REPLACE_H__ */
|
|
@ -77,14 +77,23 @@ 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)) {
|
||||
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 (m_util.is_value(args[1], q_mpf)) {
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q_mpf);
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
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])) &&
|
||||
|
@ -217,8 +226,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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
@ -465,7 +466,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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue