mirror of
https://github.com/Z3Prover/z3
synced 2025-06-07 06:33:23 +00:00
Switch between overflow representations with polysat.bvumulo=1/2
This commit is contained in:
parent
11b582cce7
commit
062ca92ebe
4 changed files with 36 additions and 11 deletions
|
@ -298,17 +298,31 @@ namespace polysat {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* encode that the i'th bit of p is 1.
|
* encode that the i'th bit of p is 1.
|
||||||
* It holds if p << (K - i - 1) >= 2^{K-1}, where K is the bit-width.
|
* It holds if 2^(N-1) <= 2^(N - 1 - i) * p, where N is the bit-width.
|
||||||
*/
|
*/
|
||||||
signed_constraint constraint_manager::bit(pdd const& p, unsigned i) {
|
signed_constraint constraint_manager::bit(pdd const& p, unsigned i) {
|
||||||
unsigned K = p.manager().power_of_2();
|
unsigned const N = p.power_of_2();
|
||||||
pdd q = p * rational::power_of_two(K - i - 1);
|
pdd q = p * rational::power_of_two(N - 1 - i);
|
||||||
rational msb = rational::power_of_two(K - 1);
|
rational msb = rational::power_of_two(N - 1);
|
||||||
return ule(p.manager().mk_val(msb), q);
|
return ule(p.manager().mk_val(msb), q);
|
||||||
}
|
}
|
||||||
|
|
||||||
signed_constraint constraint_manager::umul_ovfl(pdd const& a, pdd const& b) {
|
signed_constraint constraint_manager::umul_ovfl(pdd const& p, pdd const& q) {
|
||||||
return { dedup_store(alloc(umul_ovfl_constraint, a, b)), true };
|
switch (s.config().m_bvumulo_repr) {
|
||||||
|
case bvumulo_repr::ovfl_constraint:
|
||||||
|
// Omega^*(p, q)
|
||||||
|
return { dedup_store(alloc(umul_ovfl_constraint, p, q)), true };
|
||||||
|
case bvumulo_repr::double_width: {
|
||||||
|
// ((0_N ++ p) * (0_N ++ q))[2N-1:N] != 0
|
||||||
|
unsigned const N = p.power_of_2();
|
||||||
|
pdd ovfl_bits = extract(zero_ext(p, N) * zero_ext(q, N), 2*N - 1, N);
|
||||||
|
SASSERT_EQ(ovfl_bits.power_of_2(), N);
|
||||||
|
return ~eq(ovfl_bits);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
verbose_stream() << "invalid value for polysat.bvumulo: " << static_cast<unsigned>(s.config().m_bvumulo_repr) << "\n";
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signed_constraint constraint_manager::smul_ovfl(pdd const& a, pdd const& b) {
|
signed_constraint constraint_manager::smul_ovfl(pdd const& a, pdd const& b) {
|
||||||
|
@ -665,6 +679,7 @@ namespace polysat {
|
||||||
s.add_eq(extract(V, p_sz - 1, 0), p);
|
s.add_eq(extract(V, p_sz - 1, 0), p);
|
||||||
// (2) v < 2^|p|
|
// (2) v < 2^|p|
|
||||||
s.add_ule(V, p.manager().max_value());
|
s.add_ule(V, p.manager().max_value());
|
||||||
|
LOG("zero_ext_" << extra_bits << " " << p << " = " << V);
|
||||||
return V;
|
return V;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,12 +693,13 @@ namespace polysat {
|
||||||
auto const it = m_dedup.m_bv_ext_expr.find_iterator(args);
|
auto const it = m_dedup.m_bv_ext_expr.find_iterator(args);
|
||||||
if (it != m_dedup.m_bv_ext_expr.end())
|
if (it != m_dedup.m_bv_ext_expr.end())
|
||||||
return s.var(it->m_value);
|
return s.var(it->m_value);
|
||||||
pdd const v = s.var(s.add_var(v_sz, pvar_kind::internal));
|
pvar const v = s.add_var(v_sz, pvar_kind::internal);
|
||||||
m_dedup.m_bv_ext_expr.insert(args, v.var());
|
pdd const V = s.var(v);
|
||||||
|
m_dedup.m_bv_ext_expr.insert(args, v);
|
||||||
// (1) v[|p|-1:0] = p
|
// (1) v[|p|-1:0] = p
|
||||||
s.add_eq(extract(v, p_sz - 1, 0), p);
|
s.add_eq(extract(V, p_sz - 1, 0), p);
|
||||||
// (2) Let h := v[|v|-1:|p|]
|
// (2) Let h := v[|v|-1:|p|]
|
||||||
pdd const h = extract(v, v_sz - 1, p_sz);
|
pdd const h = extract(V, v_sz - 1, p_sz);
|
||||||
signed_constraint p_negative = s.uge(p, rational::power_of_two(p_sz - 1));
|
signed_constraint p_negative = s.uge(p, rational::power_of_two(p_sz - 1));
|
||||||
// (3) p < 2^(|p|-1) ==> h = 0
|
// (3) p < 2^(|p|-1) ==> h = 0
|
||||||
s.add_clause(p_negative, s.eq(h), false);
|
s.add_clause(p_negative, s.eq(h), false);
|
||||||
|
@ -691,7 +707,8 @@ namespace polysat {
|
||||||
s.add_clause(~p_negative, s.eq(h, h.manager().max_value()), false);
|
s.add_clause(~p_negative, s.eq(h, h.manager().max_value()), false);
|
||||||
// (5) h + 1 <= 1 (i.e., h = b000...0 or h = b111...1) ... implied by (3), (4); maybe better to just exclude h from decisions as it is basically a defined variable
|
// (5) h + 1 <= 1 (i.e., h = b000...0 or h = b111...1) ... implied by (3), (4); maybe better to just exclude h from decisions as it is basically a defined variable
|
||||||
s.add_ule(h + 1, 1);
|
s.add_ule(h + 1, 1);
|
||||||
return v;
|
LOG("sign_ext_" << extra_bits << " " << p << " = " << V);
|
||||||
|
return V;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** unsigned quotient/remainder */
|
/** unsigned quotient/remainder */
|
||||||
|
|
|
@ -8,5 +8,6 @@ def_module_params('polysat',
|
||||||
('log_start', UINT, UINT_MAX, "Enable logging on solver iteration N"),
|
('log_start', UINT, UINT_MAX, "Enable logging on solver iteration N"),
|
||||||
('log_conflicts', BOOL, False, "log conflicts"),
|
('log_conflicts', BOOL, False, "log conflicts"),
|
||||||
('slicing.congruence', BOOL, False, "bitvector slicing: add virtual congruence terms"),
|
('slicing.congruence', BOOL, False, "bitvector slicing: add virtual congruence terms"),
|
||||||
|
('bvumulo', UINT, 1, "multiplication overflow representation: 1 = umul_ovfl_constraint, 2 = extend to double width"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -83,6 +83,7 @@ namespace polysat {
|
||||||
m_config.m_log_start = pp.log_start();
|
m_config.m_log_start = pp.log_start();
|
||||||
m_config.m_log_conflicts = pp.log_conflicts();
|
m_config.m_log_conflicts = pp.log_conflicts();
|
||||||
m_config.m_slicing_congruence = pp.slicing_congruence();
|
m_config.m_slicing_congruence = pp.slicing_congruence();
|
||||||
|
m_config.m_bvumulo_repr = static_cast<bvumulo_repr>(pp.bvumulo());
|
||||||
|
|
||||||
// TODO: log filter to enable/disable based on submodules
|
// TODO: log filter to enable/disable based on submodules
|
||||||
if (m_config.m_log_start == 0)
|
if (m_config.m_log_start == 0)
|
||||||
|
|
|
@ -43,12 +43,18 @@ struct smt_params;
|
||||||
|
|
||||||
namespace polysat {
|
namespace polysat {
|
||||||
|
|
||||||
|
enum class bvumulo_repr : unsigned {
|
||||||
|
ovfl_constraint = 1,
|
||||||
|
double_width = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct config_t {
|
struct config_t {
|
||||||
uint64_t m_max_conflicts = std::numeric_limits<uint64_t>::max();
|
uint64_t m_max_conflicts = std::numeric_limits<uint64_t>::max();
|
||||||
uint64_t m_max_decisions = std::numeric_limits<uint64_t>::max();
|
uint64_t m_max_decisions = std::numeric_limits<uint64_t>::max();
|
||||||
unsigned m_log_start = UINT_MAX;
|
unsigned m_log_start = UINT_MAX;
|
||||||
bool m_log_conflicts = false;
|
bool m_log_conflicts = false;
|
||||||
bool m_slicing_congruence = false;
|
bool m_slicing_congruence = false;
|
||||||
|
bvumulo_repr m_bvumulo_repr = bvumulo_repr::ovfl_constraint;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue