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:
parent
1f7c994e43
commit
236b2d2ff3
12 changed files with 1419 additions and 912 deletions
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue