3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 09:35:32 +00:00

working on incremtal PB theory

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2014-01-13 10:12:45 -08:00
parent 1f7c994e43
commit 236b2d2ff3
12 changed files with 1419 additions and 912 deletions

View file

@ -26,10 +26,12 @@ Notes:
#include"model_smt2_pp.h"
class bool2int_model_converter : public model_converter {
ast_manager& m;
arith_util a;
func_decl_ref_vector m_refs;
obj_map<func_decl, func_decl*> m_bool2int;
ast_manager& m;
arith_util a;
func_decl_ref_vector m_refs;
obj_hashtable<func_decl> m_bools;
vector<ptr_vector<func_decl> > m_nums_as_bool;
ptr_vector<func_decl> m_nums_as_int;
public:
bool2int_model_converter(ast_manager& m):
@ -42,26 +44,34 @@ public:
SASSERT(goal_idx == 0);
model * new_model = alloc(model, m);
unsigned num = old_model->get_num_constants();
for (unsigned i = 0; i < m_nums_as_int.size(); ++i) {
func_decl* f_old = m_nums_as_int[i];
rational val(0);
rational po(1);
bool is_value = true;
for (unsigned j = 0; is_value && j < m_nums_as_bool[i].size(); ++j) {
func_decl* f = m_nums_as_bool[i][j];
expr* fi = old_model->get_const_interp(f);
if (!fi) {
is_value = false;
}
else if (m.is_true(fi)) {
val += po;
}
else if (!m.is_false(fi)) {
is_value = false;
}
po *= rational(2);
}
if (is_value) {
expr* fi = a.mk_numeral(val, true);
new_model->register_decl(f_old, fi);
}
}
for (unsigned i = 0; i < num; ++i) {
func_decl* f = old_model->get_constant(i);
expr* fi = old_model->get_const_interp(f);
func_decl* f_old;
if (m_bool2int.find(f, f_old)) {
if (!fi) {
// no-op
}
else if (m.is_false(fi)) {
fi = a.mk_numeral(rational(0), true);
}
else if (m.is_true(fi)) {
fi = a.mk_numeral(rational(1), true);
}
else {
fi = 0;
}
new_model->register_decl(f_old, fi);
}
else {
if (!m_bools.contains(f)) {
new_model->register_decl(f, fi);
}
}
@ -78,15 +88,27 @@ public:
void insert(func_decl* x_new, func_decl* x_old) {
m_refs.push_back(x_new);
m_refs.push_back(x_old);
m_bool2int.insert(x_new, x_old);
m_bools.insert(x_new);
m_nums_as_int.push_back(x_old);
m_nums_as_bool.push_back(ptr_vector<func_decl>());
m_nums_as_bool.back().push_back(x_new);
}
void insert(func_decl* x_old, unsigned sz, func_decl * const* x_new) {
m_nums_as_int.push_back(x_old);
m_nums_as_bool.push_back(ptr_vector<func_decl>());
m_refs.push_back(x_old);
for (unsigned i = 0; i < sz; ++i) {
m_refs.push_back(x_new[i]);
m_nums_as_bool.back().push_back(x_new[i]);
m_bools.insert(x_new[i]);
}
}
virtual model_converter * translate(ast_translation & translator) {
bool2int_model_converter* mc = alloc(bool2int_model_converter, translator.to());
obj_map<func_decl, func_decl*>::iterator it = m_bool2int.begin(), end = m_bool2int.end();
for (; it != end; ++it) {
mc->insert(translator(it->m_key), translator(it->m_value));
for (unsigned i = 0; i < m_nums_as_int.size(); ++i) {
mc->insert(m_nums_as_int[i], m_nums_as_bool[i].size(), m_nums_as_bool[i].c_ptr());
}
return mc;
}
@ -99,10 +121,14 @@ public:
ast_manager & m;
arith_util a;
params_ref m_params;
unsigned m_max_hi_default;
rational m_max_hi;
elim01_tactic(ast_manager & _m, params_ref const & p):
m(_m),
a(m) {
a(m),
m_max_hi_default(8),
m_max_hi(rational(m_max_hi_default)) {
}
virtual ~elim01_tactic() {
@ -111,9 +137,15 @@ public:
void set_cancel(bool f) {
}
void updt_params(params_ref const & p) {
virtual void updt_params(params_ref const & p) {
m_max_hi = rational(p.get_uint("max_coefficient", m_max_hi_default));
m_params = p;
}
virtual void collect_param_descrs(param_descrs & r) {
r.insert("max_coefficient", CPK_UINT, "(default: 1) maximal upper bound for finite range -> Bool conversion");
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
@ -129,6 +161,7 @@ public:
bool2int_model_converter* b2i = alloc(bool2int_model_converter, m);
mc = b2i;
bound_manager bounds(m);
expr_ref_vector axioms(m);
bounds(*g);
bound_manager::iterator bit = bounds.begin(), bend = bounds.end();
@ -139,11 +172,8 @@ public:
rational lo, hi;
if (a.is_int(x) &&
bounds.has_lower(x, lo, s1) && !s1 && lo.is_zero() &&
bounds.has_upper(x, hi, s2) && !s2 && hi.is_one()) {
app* x_new = m.mk_fresh_const(x->get_decl()->get_name().str().c_str(), m.mk_bool_sort());
sub.insert(x, m.mk_ite(x_new, a.mk_numeral(rational(1), true),
a.mk_numeral(rational(0), true)));
b2i->insert(x_new->get_decl(), x->get_decl());
bounds.has_upper(x, hi, s2) && !s2 && hi <= m_max_hi) {
add_variable(b2i, sub, x, hi.get_unsigned(), axioms);
}
}
@ -155,6 +185,9 @@ public:
sub(curr, new_curr);
g->update(i, new_curr, new_pr, g->dep(i));
}
for (unsigned i = 0; i < axioms.size(); ++i) {
g->assert_expr(axioms[i].get());
}
g->inc_depth();
result.push_back(g.get());
TRACE("pb", g->display(tout););
@ -166,10 +199,41 @@ public:
virtual tactic * translate(ast_manager & m) {
return alloc(elim01_tactic, m, m_params);
}
virtual void collect_param_descrs(param_descrs & r) {}
virtual void cleanup() {}
void add_variable(bool2int_model_converter* b2i,
expr_safe_replace& sub,
app* x,
unsigned max_value,
expr_ref_vector& axioms) {
std::string name = x->get_decl()->get_name().str();
unsigned sh = 0;
app_ref_vector xs(m), ites(m);
func_decl_ref_vector xfs(m);
app_ref zero(m), sum(m);
zero = a.mk_numeral(rational(0), true);
while (max_value >= (1ul << sh)) {
xs.push_back(m.mk_fresh_const(name.c_str(), m.mk_bool_sort()));
xfs.push_back(xs.back()->get_decl());
ites.push_back(m.mk_ite(xs.back(), a.mk_numeral(rational(1 << sh), true), zero));
++sh;
}
if (ites.size() == 1) {
sum = ites[0].get();
}
else {
sum = a.mk_add(ites.size(), (expr*const*)ites.c_ptr());
}
sub.insert(x, sum);
b2i->insert(x->get_decl(), xfs.size(), xfs.c_ptr());
// if max_value+1 is not a power of two:
if ((max_value & (max_value + 1)) != 0) {
axioms.push_back(a.mk_le(sum, a.mk_numeral(rational(max_value), true)));
}
}
};
tactic * mk_elim01_tactic(ast_manager & m, params_ref const & p) {

View file

@ -155,8 +155,7 @@ public:
else if (m.is_eq(fml, x, y) &&
get_pb_sum(x, rational::one(), args, coeffs, coeff) &&
get_pb_sum(y, -rational::one(), args, coeffs, coeff)) {
result = m.mk_and(mk_le(coeffs.size(), coeffs.c_ptr(), args.c_ptr(), -coeff),
mk_ge(coeffs.size(), coeffs.c_ptr(), args.c_ptr(), -coeff));
result = mk_eq(coeffs.size(), coeffs.c_ptr(), args.c_ptr(), -coeff);
return true;
}
return false;
@ -174,6 +173,14 @@ public:
}
return m_pb.mk_le(sz, weights, args, w);
}
expr* mk_eq(unsigned sz, rational const* weights, expr* const* args, rational const& w) {
#if 1
return m.mk_and(mk_ge(sz, weights, args, w), mk_le(sz, weights, args, w));
#else
return m_pb.mk_eq(sz, weights, args, w);
#endif
}
expr* mk_ge(unsigned sz, rational const* weights, expr* const* args, rational const& w) {
if (sz == 0) {