mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 08:35:31 +00:00
arithmetic
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
33c43a474d
commit
93be3d2b2c
4 changed files with 53 additions and 22 deletions
|
@ -22,7 +22,8 @@ Author:
|
|||
namespace polysat {
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, fi_record const& fi) {
|
||||
out << "fi_record(bw = " << fi.bit_width << ", coeff = " << fi.coeff << ", " << fi.interval << ", " << fi.src << fi.side_cond << fi.deps << ")";
|
||||
out << "fi_record(bw = " << fi.bit_width << ", coeff = " << fi.coeff << ", " << fi.interval << ", "
|
||||
<< fi.src << (fi.src.empty()?"": " ") << fi.side_cond << (fi.side_cond.empty()?"":" ") << fi.deps << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
@ -643,9 +643,15 @@ namespace polysat {
|
|||
// Then value is chosen, min x . coeff * x >= t.
|
||||
// In other words:
|
||||
//
|
||||
// coeff * (value - 1) <= t < coeff*value + 1
|
||||
//
|
||||
auto vlo = c.value(mod((e.value - 1) * p2eb, p2b), bw);
|
||||
// x >= t div coeff
|
||||
// => t <= coeff * x
|
||||
|
||||
// (x - 1) * coeff < t <= x * coeff
|
||||
|
||||
// a < x <= b <=>
|
||||
// a + 1 <= x < b + 1
|
||||
|
||||
auto vlo = c.value(mod((e.value - 1) * p2eb + 1, p2b), bw);
|
||||
auto vhi = c.value(mod(e.value * p2eb + 1, p2b), bw);
|
||||
|
||||
#if 0
|
||||
|
@ -655,6 +661,7 @@ namespace polysat {
|
|||
verbose_stream() << "before bw " << ebw << " " << bw << " " << *e.e << "\nafter bw " << abw << " " << aw << " " << *after.e << "\n";
|
||||
if (!t.is_val())
|
||||
IF_VERBOSE(0, verbose_stream() << "symbolic t : " << t << "\n");
|
||||
|
||||
#endif
|
||||
auto sc = cs.ult(t - vlo, vhi - vlo);
|
||||
CTRACE("bv", sc.is_always_false(), c.display(tout));
|
||||
|
|
|
@ -531,12 +531,12 @@ namespace polysat {
|
|||
|
||||
// Axioms for quotient/remainder
|
||||
//
|
||||
// a = b*q + r
|
||||
// x = y*q + r
|
||||
// multiplication does not overflow in b*q
|
||||
// addition does not overflow in (b*q) + r; for now expressed as: r <= bq+r
|
||||
// b ≠ 0 ==> r < b
|
||||
// b = 0 ==> q = -1
|
||||
// TODO: when a,b become evaluable, can we actually propagate q,r? doesn't seem like it.
|
||||
// addition does not overflow in (y*q) + r; for now expressed as: r <= yq+r
|
||||
// y ≠ 0 ==> r < y
|
||||
// y = 0 ==> q = -1
|
||||
// TODO: when x,y become evaluable, can we actually propagate q,r? doesn't seem like it.
|
||||
// Maybe we need something like an op_constraint for better propagation.
|
||||
|
||||
add_axiom("quot-rem", { eq_internalize(bv.mk_bv_add(bv.mk_bv_mul(y, quot), rem), x)}, false);
|
||||
|
@ -545,12 +545,11 @@ namespace polysat {
|
|||
// { apply equivalence: p <= q <=> q-p <= -p-1 }
|
||||
// b*q <= -r-1
|
||||
auto minus_one = bv.mk_numeral(rational::power_of_two(sz) - 1, sz);
|
||||
auto one = bv.mk_numeral(1, sz);
|
||||
auto zero = bv.mk_numeral(0, sz);
|
||||
add_axiom("quot-rem", { mk_literal(bv.mk_ule(bv.mk_bv_mul(y, quot), bv.mk_bv_sub(minus_one, rem))) }, false);
|
||||
auto c_eq = eq_internalize(y, zero);
|
||||
add_axiom("quot-rem", { c_eq, ~mk_literal(bv.mk_ule(y, rem)) }, false);
|
||||
add_axiom("quot-rem", { ~c_eq, eq_internalize(bv.mk_bv_add(quot, one), zero) }, false);
|
||||
add_axiom("quot-rem", { ~c_eq, eq_internalize(quot, minus_one) }, false);
|
||||
}
|
||||
|
||||
void solver::internalize_sign_extend(app* e) {
|
||||
|
|
|
@ -459,18 +459,42 @@ namespace polysat {
|
|||
}
|
||||
|
||||
expr_ref solver::pdd2expr(pdd const& p) {
|
||||
if (p.is_val()) {
|
||||
expr* n = bv.mk_numeral(p.val(), p.power_of_2());
|
||||
return expr_ref(n, m);
|
||||
}
|
||||
auto v = var2enode(m_pddvar2var[p.var()]);
|
||||
|
||||
auto mk_num = [&](rational const& c) {
|
||||
return bv.mk_numeral(c, p.power_of_2());
|
||||
};
|
||||
|
||||
auto mk_var = [&](pvar v) {
|
||||
return var2expr(m_pddvar2var[v]);
|
||||
};
|
||||
|
||||
if (p.is_val())
|
||||
return expr_ref(mk_num(p.val()), m);
|
||||
|
||||
expr_ref_vector args(m);
|
||||
for (auto const& mon : p) {
|
||||
auto c = mon.coeff;
|
||||
if (mon.vars.empty())
|
||||
args.push_back(mk_num(c));
|
||||
else if (mon.coeff == 1 && mon.vars.size() == 1)
|
||||
args.push_back(mk_var(mon.vars[0]));
|
||||
else if (mon.vars.size() == 1)
|
||||
args.push_back(bv.mk_bv_mul(mk_num(c), mk_var(mon.vars[0])));
|
||||
else {
|
||||
expr_ref_vector args2(m);
|
||||
for (auto v : mon.vars)
|
||||
args2.push_back(mk_var(v));
|
||||
if (c == 1)
|
||||
args.push_back(bv.mk_bv_mul(args2));
|
||||
else
|
||||
args.push_back(bv.mk_bv_mul(mk_num(c), bv.mk_bv_mul(args2)));
|
||||
}
|
||||
}
|
||||
expr_ref r(m);
|
||||
r = v->get_expr();
|
||||
if (!p.hi().is_one())
|
||||
r = bv.mk_bv_mul(r, pdd2expr(p.hi()));
|
||||
if (!p.lo().is_zero())
|
||||
r = bv.mk_bv_add(r, pdd2expr(p.lo()));
|
||||
ctx.get_rewriter()(r);
|
||||
if (args.size() == 1)
|
||||
r = args.get(0);
|
||||
else
|
||||
r = bv.mk_bv_add(args);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue