3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-25 20:46:01 +00:00

Merge branch 'opt' of https://github.com/Z3Prover/z3 into unstable

This commit is contained in:
Nikolaj Bjorner 2015-05-14 12:11:17 +01:00
commit ab5022888c
396 changed files with 86387 additions and 3294 deletions

View file

@ -18,12 +18,9 @@ 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;
}
@ -92,16 +89,14 @@ int counter::get_max_counter_value() const {
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]) {
m_fv(pred->get_arg(i));
for (unsigned j = 0; j < m_fv.size(); ++j) {
if (m_fv[j]) {
update(j, coef);
}
}
}
m_fv.reset();
}

View file

@ -27,16 +27,16 @@ Revision History:
#include "ast.h"
#include "map.h"
#include "uint_set.h"
#include "var_subst.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) {}
counter() {}
void reset() { m_data.reset(); }
iterator begin() const { return m_data.begin(); }
@ -69,14 +69,13 @@ public:
class var_counter : public counter {
protected:
ptr_vector<sort> m_sorts;
expr_fast_mark1 m_visited;
expr_free_vars m_fv;
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) {}
var_counter() {}
void count_vars(ast_manager & m, const app * t, int coef = 1);
unsigned get_max_var(expr* e);
unsigned get_next_var(expr* e);
@ -85,11 +84,10 @@ public:
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) {}
ast_counter() {}
iterator begin() const { return m_data.begin(); }
iterator end() const { return m_data.end(); }
@ -99,7 +97,6 @@ class ast_counter {
}
void update(ast * el, int delta){
get(el) += delta;
SASSERT(!m_stay_non_negative || get(el) >= 0);
}
void inc(ast * el) { update(el, 1); }

View file

@ -1041,6 +1041,11 @@ void bit_blaster_tpl<Cfg>::mk_ext_rotate_left_right(unsigned sz, expr * const *
mk_rotate_right(sz, a_bits, static_cast<unsigned>(k.get_uint64()), out_bits);
}
else {
//
// Review: a better tuned implementation is possible by using shifts by power of two.
// e.g., looping over the bits of b_bits, then rotate by a power of two depending
// on the bit-position. This would get rid of the mk_urem.
//
expr_ref_vector sz_bits(m());
expr_ref_vector masked_b_bits(m());
expr_ref_vector eqs(m());

View file

@ -60,6 +60,32 @@ br_status datatype_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr
UNREACHABLE();
break;
}
case OP_DT_UPDATE_FIELD: {
SASSERT(num_args == 2);
if (!is_app(args[0]) || !m_util.is_constructor(to_app(args[0])))
return BR_FAILED;
app * a = to_app(args[0]);
func_decl * c_decl = a->get_decl();
if (c_decl != m_util.get_accessor_constructor(f)) {
result = a;
return BR_DONE;
}
ptr_vector<func_decl> const * acc = m_util.get_constructor_accessors(c_decl);
SASSERT(acc && acc->size() == a->get_num_args());
unsigned num = acc->size();
ptr_buffer<expr> new_args;
for (unsigned i = 0; i < num; ++i) {
if (f == (*acc)[i]) {
new_args.push_back(args[1]);
}
else {
new_args.push_back(a->get_arg(i));
}
}
result = m().mk_app(c_decl, num, new_args.c_ptr());
return BR_DONE;
}
default:
UNREACHABLE();
}

View file

@ -29,43 +29,39 @@ void expr_safe_replace::insert(expr* src, expr* 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);
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();
while (!m_todo.empty()) {
a = m_todo.back();
if (m_cache.contains(a)) {
m_todo.pop_back();
}
else if (m_subst.find(a, b)) {
cache.insert(a, b);
todo.pop_back();
m_cache.insert(a, b);
m_todo.pop_back();
}
else if (is_var(a)) {
cache.insert(a, a);
todo.pop_back();
m_cache.insert(a, a);
m_todo.pop_back();
}
else if (is_app(a)) {
app* c = to_app(a);
unsigned n = c->get_num_args();
args.reset();
m_args.reset();
for (unsigned i = 0; i < n; ++i) {
if (cache.find(c->get_arg(i), d)) {
args.push_back(d);
if (m_cache.find(c->get_arg(i), d)) {
m_args.push_back(d);
}
else {
todo.push_back(c->get_arg(i));
m_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();
if (m_args.size() == n) {
b = m.mk_app(c->get_decl(), m_args.size(), m_args.c_ptr());
m_refs.push_back(b);
m_cache.insert(a, b);
m_todo.pop_back();
}
}
else {
@ -93,12 +89,16 @@ void expr_safe_replace::operator()(expr* e, expr_ref& res) {
}
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();
m_refs.push_back(b);
m_cache.insert(a, b);
m_todo.pop_back();
}
}
res = cache.find(e);
res = m_cache.find(e);
m_cache.reset();
m_todo.reset();
m_args.reset();
m_refs.reset();
}
void expr_safe_replace::reset() {

View file

@ -29,9 +29,12 @@ class expr_safe_replace {
expr_ref_vector m_src;
expr_ref_vector m_dst;
obj_map<expr, expr*> m_subst;
obj_map<expr,expr*> m_cache;
ptr_vector<expr> m_todo, m_args;
expr_ref_vector m_refs;
public:
expr_safe_replace(ast_manager& m): m(m), m_src(m), m_dst(m) {}
expr_safe_replace(ast_manager& m): m(m), m_src(m), m_dst(m), m_refs(m) {}
void insert(expr* src, expr* dst);
@ -42,6 +45,8 @@ public:
void apply_substitution(expr* s, expr* def, expr_ref& t);
void reset();
bool empty() const { return m_subst.empty(); }
};
#endif /* __EXPR_SAFE_REPLACE_H__ */

View file

@ -0,0 +1,275 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
pb_rewriter.cpp
Abstract:
Basic rewriting rules for PB constraints.
Author:
Nikolaj Bjorner (nbjorner) 2013-14-12
Notes:
--*/
#include "pb_rewriter.h"
#include "pb_rewriter_def.h"
#include "ast_pp.h"
#include "ast_smt_pp.h"
class pb_ast_rewriter_util {
ast_manager& m;
expr_ref_vector m_refs;
public:
typedef std::pair<expr*, rational> arg_t;
typedef vector<arg_t> args_t;
typedef rational numeral;
pb_ast_rewriter_util(ast_manager& m): m(m), m_refs(m) {}
expr* negate(expr* e) {
if (m.is_true(e)) {
return m.mk_false();
}
if (m.is_false(e)) {
return m.mk_true();
}
if (m.is_not(e, e)) {
return e;
}
m_refs.push_back(m.mk_not(e));
return m_refs.back();
}
void display(std::ostream& out, expr* e) {
out << mk_pp(e, m);
}
bool is_negated(expr* e) const {
return m.is_not(e);
}
bool is_true(expr* e) const {
return m.is_true(e);
}
bool is_false(expr* e) const {
return m.is_false(e);
}
struct compare {
bool operator()(std::pair<expr*,rational> const& a,
std::pair<expr*,rational> const& b) {
return a.first->get_id() < b.first->get_id();
}
};
};
expr_ref pb_rewriter::translate_pb2lia(obj_map<expr,expr*>& vars, expr* fml) {
pb_util util(m());
arith_util a(m());
expr_ref result(m()), tmp(m());
expr_ref_vector es(m());
expr*const* args = to_app(fml)->get_args();
unsigned sz = to_app(fml)->get_num_args();
for (unsigned i = 0; i < sz; ++i) {
expr* e = args[i];
if (m().is_not(e, e)) {
es.push_back(a.mk_sub(a.mk_numeral(rational(1),true),vars.find(e)));
}
else {
es.push_back(vars.find(e));
}
}
if (util.is_at_most_k(fml) || util.is_at_least_k(fml)) {
if (es.empty()) {
tmp = a.mk_numeral(rational(0), true);
}
else {
tmp = a.mk_add(es.size(), es.c_ptr());
}
if (util.is_at_most_k(fml)) {
result = a.mk_le(tmp, a.mk_numeral(util.get_k(fml), false));
}
else {
result = a.mk_ge(tmp, a.mk_numeral(util.get_k(fml), false));
}
}
else if (util.is_le(fml) || util.is_ge(fml) || util.is_eq(fml)) {
for (unsigned i = 0; i < sz; ++i) {
es[i] = a.mk_mul(a.mk_numeral(util.get_coeff(fml, i),false), es[i].get());
}
if (es.empty()) {
tmp = a.mk_numeral(rational(0), true);
}
else {
tmp = a.mk_add(es.size(), es.c_ptr());
}
if (util.is_le(fml)) {
result = a.mk_le(tmp, a.mk_numeral(util.get_k(fml), false));
}
else if (util.is_ge(fml)) {
result = a.mk_ge(tmp, a.mk_numeral(util.get_k(fml), false));
}
else {
result = m().mk_eq(tmp, a.mk_numeral(util.get_k(fml), false));
}
}
else {
result = fml;
}
return result;
}
expr_ref pb_rewriter::mk_validate_rewrite(app_ref& e1, app_ref& e2) {
ast_manager& m = e1.get_manager();
arith_util a(m);
symbol name;
obj_map<expr,expr*> vars;
expr_ref_vector trail(m), fmls(m);
unsigned sz = to_app(e1)->get_num_args();
expr*const*args = to_app(e1)->get_args();
for (unsigned i = 0; i < sz; ++i) {
expr* e = args[i];
if (m.is_true(e)) {
if (!vars.contains(e)) {
trail.push_back(a.mk_numeral(rational(1), true));
vars.insert(e, trail.back());
}
continue;
}
if (m.is_false(e)) {
if (!vars.contains(e)) {
trail.push_back(a.mk_numeral(rational(0), true));
vars.insert(e, trail.back());
}
continue;
}
std::ostringstream strm;
strm << "x" << i;
name = symbol(strm.str().c_str());
trail.push_back(m.mk_const(name, a.mk_int()));
expr* x = trail.back();
m.is_not(e,e);
vars.insert(e, x);
fmls.push_back(a.mk_le(a.mk_numeral(rational(0), true), x));
fmls.push_back(a.mk_le(x, a.mk_numeral(rational(1), true)));
}
expr_ref tmp(m);
expr_ref fml1 = translate_pb2lia(vars, e1);
expr_ref fml2 = translate_pb2lia(vars, e2);
tmp = m.mk_not(m.mk_eq(fml1, fml2));
fmls.push_back(tmp);
tmp = m.mk_and(fmls.size(), fmls.c_ptr());
return tmp;
}
static unsigned s_lemma = 0;
void pb_rewriter::validate_rewrite(func_decl* f, unsigned sz, expr*const* args, expr_ref& fml) {
ast_manager& m = fml.get_manager();
app_ref tmp1(m), tmp2(m);
tmp1 = m.mk_app(f, sz, args);
tmp2 = to_app(fml);
expr_ref tmp = mk_validate_rewrite(tmp1, tmp2);
dump_pb_rewrite(tmp);
}
void pb_rewriter::dump_pb_rewrite(expr* fml) {
std::ostringstream strm;
strm << "pb_rewrite_" << (s_lemma++) << ".smt2";
std::ofstream out(strm.str().c_str());
ast_smt_pp pp(m());
pp.display_smt2(out, fml);
out.close();
}
br_status pb_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
ast_manager& m = result.get_manager();
rational sum(0), maxsum(0);
for (unsigned i = 0; i < num_args; ++i) {
if (m.is_true(args[i])) {
sum += m_util.get_coeff(f, i);
maxsum += m_util.get_coeff(f, i);
}
else if (!m.is_false(args[i])) {
maxsum += m_util.get_coeff(f, i);
}
}
rational k = m_util.get_k(f);
vector<std::pair<expr*,rational> > vec;
for (unsigned i = 0; i < num_args; ++i) {
vec.push_back(std::make_pair(args[i], m_util.get_coeff(f, i)));
}
switch(f->get_decl_kind()) {
case OP_AT_MOST_K:
case OP_PB_LE:
for (unsigned i = 0; i < num_args; ++i) {
vec[i].second.neg();
}
k.neg();
break;
case OP_AT_LEAST_K:
case OP_PB_GE:
case OP_PB_EQ:
break;
default:
UNREACHABLE();
return BR_FAILED;
}
bool is_eq = f->get_decl_kind() == OP_PB_EQ;
pb_ast_rewriter_util pbu(m);
pb_rewriter_util<pb_ast_rewriter_util> util(pbu);
util.unique(vec, k, is_eq);
lbool is_sat = util.normalize(vec, k, is_eq);
util.prune(vec, k, is_eq);
switch (is_sat) {
case l_true:
result = m.mk_true();
break;
case l_false:
result = m.mk_false();
break;
default:
m_args.reset();
m_coeffs.reset();
for (unsigned i = 0; i < vec.size(); ++i) {
m_args.push_back(vec[i].first);
m_coeffs.push_back(vec[i].second);
}
if (is_eq) {
result = m_util.mk_eq(vec.size(), m_coeffs.c_ptr(), m_args.c_ptr(), k);
}
else {
result = m_util.mk_ge(vec.size(), m_coeffs.c_ptr(), m_args.c_ptr(), k);
}
break;
}
TRACE("pb",
expr_ref tmp(m);
tmp = m.mk_app(f, num_args, args);
tout << tmp << "\n";
tout << result << "\n";
);
TRACE("pb_validate",
validate_rewrite(f, num_args, args, result););
return BR_DONE;
}

View file

@ -0,0 +1,65 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
pb_rewriter.h
Abstract:
Basic rewriting rules for PB constraints.
Author:
Nikolaj Bjorner (nbjorner) 2013-14-12
Notes:
--*/
#ifndef _PB_REWRITER_H_
#define _PB_REWRITER_H_
#include"pb_decl_plugin.h"
#include"rewriter_types.h"
#include"params.h"
#include"lbool.h"
template<typename PBU>
class pb_rewriter_util {
PBU& m_util;
void display(std::ostream& out, typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq);
public:
pb_rewriter_util(PBU& u) : m_util(u) {}
void unique(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq);
lbool normalize(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq);
void prune(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq);
};
/**
\brief Cheap rewrite rules for PB constraints
*/
class pb_rewriter {
pb_util m_util;
vector<rational> m_coeffs;
ptr_vector<expr> m_args;
void validate_rewrite(func_decl* f, unsigned sz, expr*const* args, expr_ref& fml);
public:
pb_rewriter(ast_manager & m, params_ref const & p = params_ref()):
m_util(m) {
}
ast_manager & m() const { return m_util.get_manager(); }
family_id get_fid() const { return m_util.get_family_id(); }
void updt_params(params_ref const & p) {}
static void get_param_descrs(param_descrs & r) {}
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
expr_ref translate_pb2lia(obj_map<expr,expr*>& vars, expr* fml);
expr_ref mk_validate_rewrite(app_ref& e1, app_ref& e2);
void dump_pb_rewrite(expr* fml);
};
#endif

View file

@ -0,0 +1,298 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
pb_rewriter_def.h
Abstract:
Basic rewriting rules for PB constraints.
Author:
Nikolaj Bjorner (nbjorner) 2013-14-12
Notes:
--*/
#ifndef _PB_REWRITER_DEF_H_
#define _PB_REWRITER_DEF_H_
#include"pb_rewriter.h"
template<typename PBU>
void pb_rewriter_util<PBU>::display(std::ostream& out, typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq) {
for (unsigned i = 0; i < args.size(); ++i) {
out << args[i].second << " * ";
m_util.display(out, args[i].first);
out << " ";
if (i+1 < args.size()) out << "+ ";
}
out << (is_eq?" = ":" >= ") << k << "\n";
}
template<typename PBU>
void pb_rewriter_util<PBU>::unique(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq) {
TRACE("pb_verbose", display(tout << "pre-unique:", args, k, is_eq););
for (unsigned i = 0; i < args.size(); ++i) {
if (m_util.is_negated(args[i].first)) {
args[i].first = m_util.negate(args[i].first);
k -= args[i].second;
args[i].second = -args[i].second;
}
}
// remove constants
for (unsigned i = 0; i < args.size(); ++i) {
if (m_util.is_true(args[i].first)) {
k -= args[i].second;
std::swap(args[i], args[args.size()-1]);
args.pop_back();
--i;
}
else if (m_util.is_false(args[i].first)) {
std::swap(args[i], args[args.size()-1]);
args.pop_back();
--i;
}
}
// sort and coalesce arguments:
typename PBU::compare cmp;
std::sort(args.begin(), args.end(), cmp);
// coallesce
unsigned i, j;
for (i = 0, j = 1; j < args.size(); ++j) {
if (args[i].first == args[j].first) {
args[i].second += args[j].second;
}
else {
++i;
args[i] = args[j];
}
}
args.resize(i+1);
// remove 0s.
for (i = 0, j = 0; j < args.size(); ++j) {
if (!args[j].second.is_zero()) {
if (i != j) {
args[i] = args[j];
}
++i;
}
}
args.resize(i);
TRACE("pb_verbose", display(tout << "post-unique:", args, k, is_eq););
}
template<typename PBU>
lbool pb_rewriter_util<PBU>::normalize(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq) {
TRACE("pb_verbose", display(tout << "pre-normalize:", args, k, is_eq););
DEBUG_CODE(
bool found = false;
for (unsigned i = 0; !found && i < args.size(); ++i) {
found = args[i].second.is_zero();
}
if (found) display(verbose_stream(), args, k, is_eq);
SASSERT(!found););
//
// Ensure all coefficients are positive:
// c*l + y >= k
// <=>
// c*(1-~l) + y >= k
// <=>
// c - c*~l + y >= k
// <=>
// -c*~l + y >= k - c
//
typename PBU::numeral sum(0);
for (unsigned i = 0; i < args.size(); ++i) {
typename PBU::numeral c = args[i].second;
if (c.is_neg()) {
args[i].second = -c;
args[i].first = m_util.negate(args[i].first);
k -= c;
}
sum += args[i].second;
}
// detect tautologies:
if (!is_eq && k <= PBU::numeral::zero()) {
args.reset();
k = PBU::numeral::zero();
return l_true;
}
if (is_eq && k.is_zero() && args.empty()) {
return l_true;
}
// detect infeasible constraints:
if (sum < k) {
args.reset();
k = PBU::numeral::one();
return l_false;
}
if (is_eq && k == sum) {
for (unsigned i = 0; i < args.size(); ++i) {
args[i].second = PBU::numeral::one();
}
typename PBU::numeral num(args.size());
k = num;
return l_undef;
}
bool all_int = true;
for (unsigned i = 0; all_int && i < args.size(); ++i) {
all_int = args[i].second.is_int();
}
if (!all_int) {
// normalize to integers.
typename PBU::numeral d(denominator(k));
for (unsigned i = 0; i < args.size(); ++i) {
d = lcm(d, denominator(args[i].second));
}
SASSERT(!d.is_one());
k *= d;
for (unsigned i = 0; i < args.size(); ++i) {
args[i].second *= d;
}
}
if (is_eq) {
TRACE("pb_verbose", display(tout << "post-normalize:", args, k, is_eq););
return l_undef;
}
// Ensure the largest coefficient is not larger than k:
sum = PBU::numeral::zero();
for (unsigned i = 0; i < args.size(); ++i) {
typename PBU::numeral c = args[i].second;
if (c > k) {
args[i].second = k;
}
sum += args[i].second;
}
SASSERT(!args.empty());
// normalize tight inequalities to unit coefficients.
if (sum == k) {
for (unsigned i = 0; i < args.size(); ++i) {
args[i].second = PBU::numeral::one();
}
typename PBU::numeral num(args.size());
k = num;
}
// apply cutting plane reduction:
typename PBU::numeral g(0);
for (unsigned i = 0; !g.is_one() && i < args.size(); ++i) {
typename PBU::numeral c = args[i].second;
if (c != k) {
if (g.is_zero()) {
g = c;
}
else {
g = gcd(g, c);
}
}
}
if (g.is_zero()) {
// all coefficients are equal to k.
for (unsigned i = 0; i < args.size(); ++i) {
SASSERT(args[i].second == k);
args[i].second = PBU::numeral::one();
}
k = PBU::numeral::one();
}
else if (g > PBU::numeral::one()) {
//
// Example 5x + 5y + 2z + 2u >= 5
// becomes 3x + 3y + z + u >= 3
//
typename PBU::numeral k_new = div(k, g);
if (!(k % g).is_zero()) { // k_new is the ceiling of k / g.
k_new++;
}
for (unsigned i = 0; i < args.size(); ++i) {
SASSERT(args[i].second.is_pos());
typename PBU::numeral c = args[i].second;
if (c == k) {
c = k_new;
}
else {
c = div(c, g);
}
args[i].second = c;
SASSERT(args[i].second.is_pos());
}
k = k_new;
}
//
// normalize coefficients that fall within a range
// k/n <= ... < k/(n-1) for some n = 1,2,...
//
// e.g, k/n <= min <= max < k/(n-1)
// k/min <= n, n-1 < k/max
// . floor(k/max) = ceil(k/min) - 1
// . floor(k/max) < k/max
//
// example: k = 5, min = 3, max = 4: 5/3 -> 2 5/4 -> 1, n = 2
// replace all coefficients by 1, and k by 2.
//
if (!k.is_one()) {
typename PBU::numeral min = args[0].second, max = args[0].second;
for (unsigned i = 1; i < args.size(); ++i) {
if (args[i].second < min) min = args[i].second;
if (args[i].second > max) max = args[i].second;
}
SASSERT(min.is_pos());
typename PBU::numeral n0 = k/max;
typename PBU::numeral n1 = floor(n0);
typename PBU::numeral n2 = ceil(k/min) - PBU::numeral::one();
if (n1 == n2 && !n0.is_int()) {
IF_VERBOSE(3, display(verbose_stream() << "set cardinality\n", args, k, is_eq););
for (unsigned i = 0; i < args.size(); ++i) {
args[i].second = PBU::numeral::one();
}
k = n1 + PBU::numeral::one();
}
}
TRACE("pb_verbose", display(tout << "post-normalize:", args, k, is_eq););
return l_undef;
}
template<typename PBU>
void pb_rewriter_util<PBU>::prune(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq) {
if (is_eq) {
return;
}
typename PBU::numeral nlt(0);
unsigned occ = 0;
for (unsigned i = 0; nlt < k && i < args.size(); ++i) {
if (args[i].second < k) {
nlt += args[i].second;
++occ;
}
}
if (0 < occ && nlt < k) {
for (unsigned i = 0; i < args.size(); ++i) {
if (args[i].second < k) {
args[i] = args.back();
args.pop_back();
--i;
}
}
unique(args, k, is_eq);
normalize(args, k, is_eq);
}
}
#endif

View file

@ -31,6 +31,8 @@ void poly_rewriter<Config>::updt_params(params_ref const & _p) {
m_hoist_mul = p.hoist_mul();
m_hoist_cmul = p.hoist_cmul();
m_som_blowup = p.som_blowup();
if (!m_flat) m_som = false;
if (m_som) m_hoist_mul = false;
}
template<typename Config>

View file

@ -25,6 +25,7 @@ Notes:
#include"array_rewriter.h"
#include"fpa_rewriter.h"
#include"dl_rewriter.h"
#include"pb_rewriter.h"
#include"rewriter_def.h"
#include"expr_substitution.h"
#include"ast_smt2_pp.h"
@ -41,6 +42,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
datatype_rewriter m_dt_rw;
fpa_rewriter m_f_rw;
dl_rewriter m_dl_rw;
pb_rewriter m_pb_rw;
arith_util m_a_util;
bv_util m_bv_util;
unsigned long long m_max_memory; // in bytes
@ -196,6 +198,8 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
return m_f_rw.mk_app_core(f, num, args, result);
if (fid == m_dl_rw.get_fid())
return m_dl_rw.mk_app_core(f, num, args, result);
if (fid == m_pb_rw.get_fid())
return m_pb_rw.mk_app_core(f, num, args, result);
return BR_FAILED;
}
@ -645,6 +649,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
m_dt_rw(m),
m_f_rw(m, p),
m_dl_rw(m),
m_pb_rw(m),
m_a_util(m),
m_bv_util(m),
m_used_dependencies(m),

View file

@ -164,7 +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(ast_mark& mark, ptr_vector<expr>& todo, unsigned offset, expr* e, ptr_vector<sort>& sorts) {
static void get_free_vars_offset(expr_sparse_mark& mark, ptr_vector<expr>& todo, unsigned offset, expr* e, ptr_vector<sort>& sorts) {
todo.push_back(e);
while (!todo.empty()) {
e = todo.back();
@ -176,7 +176,7 @@ static void get_free_vars_offset(ast_mark& mark, ptr_vector<expr>& todo, unsigne
switch(e->get_kind()) {
case AST_QUANTIFIER: {
quantifier* q = to_quantifier(e);
ast_mark mark1;
expr_sparse_mark mark1;
ptr_vector<expr> todo1;
get_free_vars_offset(mark1, todo1, offset+q->get_num_decls(), q->get_expr(), sorts);
break;
@ -210,11 +210,33 @@ static void get_free_vars_offset(ast_mark& mark, ptr_vector<expr>& todo, unsigne
void get_free_vars(expr* e, ptr_vector<sort>& sorts) {
ast_mark mark;
expr_sparse_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) {
void get_free_vars(expr_sparse_mark& mark, ptr_vector<expr>& todo, expr* e, ptr_vector<sort>& sorts) {
get_free_vars_offset(mark, todo, 0, e, sorts);
}
void expr_free_vars::reset() {
m_mark.reset();
m_sorts.reset();
SASSERT(m_todo.empty());
}
void expr_free_vars::set_default_sort(sort *s) {
for (unsigned i = 0; i < m_sorts.size(); ++i) {
if (!m_sorts[i]) m_sorts[i] = s;
}
}
void expr_free_vars::operator()(expr* e) {
reset();
get_free_vars_offset(m_mark, m_todo, 0, e, m_sorts);
}
void expr_free_vars::accumulate(expr* e) {
SASSERT(m_todo.empty());
get_free_vars_offset(m_mark, m_todo, 0, e, m_sorts);
}

View file

@ -81,9 +81,23 @@ void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref
Return the sorts of the free variables.
*/
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);
class expr_free_vars {
expr_sparse_mark m_mark;
ptr_vector<sort> m_sorts;
ptr_vector<expr> m_todo;
public:
void reset();
void operator()(expr* e);
void accumulate(expr* e);
bool empty() const { return m_sorts.empty(); }
unsigned size() const { return m_sorts.size(); }
sort* operator[](unsigned idx) const { return m_sorts[idx]; }
bool contains(unsigned idx) const { return idx < m_sorts.size() && m_sorts[idx] != 0; }
void set_default_sort(sort* s);
void reverse() { m_sorts.reverse(); }
sort*const* c_ptr() const { return m_sorts.c_ptr(); }
};
#endif