mirror of
https://github.com/Z3Prover/z3
synced 2025-04-06 01:24:08 +00:00
fixes to bv-sls
This commit is contained in:
parent
d7c0e17f96
commit
bab7ca2b70
|
@ -124,6 +124,7 @@ namespace bv {
|
|||
};
|
||||
m_eval.init_eval(m_terms.assertions(), eval);
|
||||
init_repair();
|
||||
// m_engine_init = false;
|
||||
}
|
||||
|
||||
std::pair<bool, app*> sls::next_to_repair() {
|
||||
|
@ -161,17 +162,18 @@ namespace bv {
|
|||
lbool sls::search1() {
|
||||
// init and init_eval were invoked
|
||||
unsigned n = 0;
|
||||
for (; n++ < m_config.m_max_repairs && m.inc(); ) {
|
||||
for (; n < m_config.m_max_repairs && m.inc(); ) {
|
||||
auto [down, e] = next_to_repair();
|
||||
if (!e)
|
||||
return l_true;
|
||||
|
||||
trace_repair(down, e);
|
||||
|
||||
IF_VERBOSE(20, trace_repair(down, e));
|
||||
|
||||
++m_stats.m_moves;
|
||||
|
||||
if (down)
|
||||
if (down) {
|
||||
try_repair_down(e);
|
||||
++n;
|
||||
}
|
||||
else
|
||||
try_repair_up(e);
|
||||
}
|
||||
|
@ -181,12 +183,13 @@ namespace bv {
|
|||
lbool sls::search2() {
|
||||
lbool res = l_undef;
|
||||
if (m_stats.m_restarts == 0)
|
||||
res = m_engine();
|
||||
res = m_engine(),
|
||||
m_engine_init = true;
|
||||
else if (m_stats.m_restarts % 1000 == 0)
|
||||
res = m_engine.search_loop();
|
||||
res = m_engine.search_loop(),
|
||||
m_engine_init = true;
|
||||
if (res != l_undef)
|
||||
m_engine_model = true;
|
||||
m_engine_init = true;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -203,7 +206,7 @@ namespace bv {
|
|||
if (res != l_undef)
|
||||
break;
|
||||
trace();
|
||||
// res = search2();
|
||||
//res = search2();
|
||||
if (res != l_undef)
|
||||
break;
|
||||
reinit_eval();
|
||||
|
@ -223,6 +226,7 @@ namespace bv {
|
|||
VERIFY(m_eval.wval(e).commit_eval());
|
||||
}
|
||||
|
||||
IF_VERBOSE(3, verbose_stream() << "done\n");
|
||||
for (auto p : m_terms.parents(e))
|
||||
m_repair_up.insert(p->get_id());
|
||||
|
||||
|
@ -256,6 +260,7 @@ namespace bv {
|
|||
}
|
||||
}
|
||||
}
|
||||
IF_VERBOSE(3, verbose_stream() << "init-repair " << mk_bounded_pp(e, m) << "\n");
|
||||
// repair was not successful, so reset the state to find a different way to repair
|
||||
init_repair();
|
||||
}
|
||||
|
@ -265,7 +270,7 @@ namespace bv {
|
|||
if (m_terms.is_assertion(e))
|
||||
m_repair_roots.insert(e->get_id());
|
||||
else if (!m_eval.repair_up(e)) {
|
||||
//m_repair_roots.insert(e->get_id());
|
||||
IF_VERBOSE(2, verbose_stream() << "repair-up "; trace_repair(true, e));
|
||||
init_repair();
|
||||
}
|
||||
else {
|
||||
|
@ -366,14 +371,14 @@ namespace bv {
|
|||
m_engine.updt_params(q);
|
||||
}
|
||||
|
||||
void sls::trace_repair(bool down, expr* e) {
|
||||
IF_VERBOSE(20,
|
||||
std::ostream& sls::trace_repair(bool down, expr* e) {
|
||||
verbose_stream() << (down ? "d #" : "u #")
|
||||
<< e->get_id() << ": "
|
||||
<< mk_bounded_pp(e, m, 1) << " ";
|
||||
if (bv.is_bv(e)) verbose_stream() << m_eval.wval(e) << " " << (m_eval.is_fixed0(e) ? "fixed " : " ");
|
||||
if (m.is_bool(e)) verbose_stream() << m_eval.bval0(e) << " ";
|
||||
verbose_stream() << "\n");
|
||||
verbose_stream() << "\n";
|
||||
return verbose_stream();
|
||||
}
|
||||
|
||||
void sls::trace() {
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace bv {
|
|||
void reinit_eval();
|
||||
void init_repair();
|
||||
void trace();
|
||||
void trace_repair(bool down, expr* e);
|
||||
std::ostream& trace_repair(bool down, expr* e);
|
||||
|
||||
indexed_uint_set m_to_repair;
|
||||
void init_repair_candidates();
|
||||
|
|
|
@ -1351,55 +1351,18 @@ namespace bv {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool sls_eval::try_repair_ashr(bvect const& e, bvval & a, bvval& b, unsigned i) {
|
||||
if (true) {
|
||||
bool sls_eval::try_repair_ashr(bvect const& e, bvval & a, bvval& b, unsigned i) {
|
||||
if (i == 0)
|
||||
return try_repair_ashr0(e, a, b);
|
||||
else
|
||||
return try_repair_ashr1(e, a, b);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
unsigned sh = b.to_nat(b.bw);
|
||||
if (sh == 0)
|
||||
return a.try_set(e);
|
||||
else if (sh >= b.bw) {
|
||||
if (e.get(a.bw - 1))
|
||||
return a.try_set_bit(a.bw - 1, true);
|
||||
else
|
||||
return a.try_set_bit(a.bw - 1, false);
|
||||
}
|
||||
else {
|
||||
// e = a >> sh
|
||||
// a[bw-1:sh] = e[bw-sh-1:0]
|
||||
// a[sh-1:0] = a[sh-1:0]
|
||||
// ignore sign
|
||||
for (unsigned i = sh; i < a.bw; ++i)
|
||||
m_tmp.set(i, e.get(i - sh));
|
||||
for (unsigned i = 0; i < sh; ++i)
|
||||
m_tmp.set(i, a.get_bit(i));
|
||||
a.clear_overflow_bits(m_tmp);
|
||||
return a.try_set(m_tmp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// NB. blind sub-range of possible values for b
|
||||
SASSERT(i == 1);
|
||||
unsigned sh = m_rand(a.bw + 1);
|
||||
b.set(m_tmp, sh);
|
||||
return b.try_set(m_tmp);
|
||||
}
|
||||
}
|
||||
|
||||
bool sls_eval::try_repair_lshr(bvect const& e, bvval& a, bvval& b, unsigned i) {
|
||||
#if 0
|
||||
return try_repair_ashr(e, a, b, i);
|
||||
#else
|
||||
if (i == 0)
|
||||
return try_repair_lshr0(e, a, b);
|
||||
else
|
||||
return try_repair_lshr1(e, a, b);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1427,22 +1390,25 @@ namespace bv {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
unsigned sh = b.to_nat(b.bw);
|
||||
if (sh == 0 && a.try_set(e))
|
||||
return true;
|
||||
else if (sh >= b.bw)
|
||||
return true;
|
||||
else if (sh < b.bw && m_rand(20) != 0) {
|
||||
// e = a >> sh
|
||||
// a[bw-1:sh] = e[bw-sh-1:0]
|
||||
// a[sh-1:0] = a[sh-1:0]
|
||||
for (unsigned i = sh; i < a.bw; ++i)
|
||||
t.set(i, e.get(i - sh));
|
||||
for (unsigned i = 0; i < sh; ++i)
|
||||
t.set(i, a.get_bit(i));
|
||||
a.clear_overflow_bits(t);
|
||||
if (a.try_set(t))
|
||||
if (m_rand(20) != 0) {
|
||||
if (sh == 0 && a.try_set(e))
|
||||
return true;
|
||||
else if (sh >= b.bw)
|
||||
return true;
|
||||
else if (sh < b.bw && m_rand(20) != 0) {
|
||||
// e = a >> sh
|
||||
// a[bw-1:sh] = e[bw-sh-1:0]
|
||||
// a[sh-1:0] = a[sh-1:0]
|
||||
for (unsigned i = sh; i < a.bw; ++i)
|
||||
t.set(i, e.get(i - sh));
|
||||
for (unsigned i = 0; i < sh; ++i)
|
||||
t.set(i, a.get_bit(i));
|
||||
a.clear_overflow_bits(t);
|
||||
if (a.try_set(t))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//bool r = try_repair_ashr(e, a, const_cast<bvval&>(b), 0);
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace bv {
|
|||
|
||||
// s <=s t <=> s + K <= t + K, K = 2^{bw-1}
|
||||
|
||||
void sls_fixed::init_range(app* e, bool sign) {
|
||||
bool sls_fixed::init_range(app* e, bool sign) {
|
||||
expr* s, * t, * x, * y;
|
||||
rational a, b;
|
||||
unsigned idx;
|
||||
|
@ -64,63 +64,116 @@ namespace bv {
|
|||
if (bv.is_ule(e, s, t)) {
|
||||
get_offset(s, x, a);
|
||||
get_offset(t, y, b);
|
||||
init_range(x, a, y, b, sign);
|
||||
return init_range(x, a, y, b, sign);
|
||||
}
|
||||
else if (bv.is_ult(e, s, t)) {
|
||||
get_offset(s, x, a);
|
||||
get_offset(t, y, b);
|
||||
init_range(y, b, x, a, !sign);
|
||||
return init_range(y, b, x, a, !sign);
|
||||
}
|
||||
else if (bv.is_uge(e, s, t)) {
|
||||
get_offset(s, x, a);
|
||||
get_offset(t, y, b);
|
||||
init_range(y, b, x, a, sign);
|
||||
return init_range(y, b, x, a, sign);
|
||||
}
|
||||
else if (bv.is_ugt(e, s, t)) {
|
||||
get_offset(s, x, a);
|
||||
get_offset(t, y, b);
|
||||
init_range(x, a, y, b, !sign);
|
||||
return init_range(x, a, y, b, !sign);
|
||||
}
|
||||
else if (bv.is_sle(e, s, t)) {
|
||||
get_offset(s, x, a);
|
||||
get_offset(t, y, b);
|
||||
init_range(x, a + N(s), y, b + N(s), sign);
|
||||
return init_range(x, a + N(s), y, b + N(s), sign);
|
||||
}
|
||||
else if (bv.is_slt(e, s, t)) {
|
||||
get_offset(s, x, a);
|
||||
get_offset(t, y, b);
|
||||
init_range(y, b + N(s), x, a + N(s), !sign);
|
||||
return init_range(y, b + N(s), x, a + N(s), !sign);
|
||||
}
|
||||
else if (bv.is_sge(e, s, t)) {
|
||||
get_offset(s, x, a);
|
||||
get_offset(t, y, b);
|
||||
init_range(y, b + N(s), x, a + N(s), sign);
|
||||
return init_range(y, b + N(s), x, a + N(s), sign);
|
||||
}
|
||||
else if (bv.is_sgt(e, s, t)) {
|
||||
get_offset(s, x, a);
|
||||
get_offset(t, y, b);
|
||||
init_range(x, a + N(s), y, b + N(s), !sign);
|
||||
return init_range(x, a + N(s), y, b + N(s), !sign);
|
||||
}
|
||||
else if (!sign && m.is_eq(e, s, t)) {
|
||||
else if (m.is_eq(e, s, t)) {
|
||||
if (bv.is_numeral(s, a))
|
||||
// t - a <= 0
|
||||
init_range(t, -a, nullptr, rational(0), false);
|
||||
init_eq(t, a, sign);
|
||||
else if (bv.is_numeral(t, a))
|
||||
init_range(s, -a, nullptr, rational(0), false);
|
||||
}
|
||||
else if (sign && m.is_eq(e, s, t)) {
|
||||
if (bv.is_numeral(s, a))
|
||||
// 1 <= t - a
|
||||
init_range(nullptr, rational(1), t, -a, false);
|
||||
else if (bv.is_numeral(t, a))
|
||||
init_range(nullptr, rational(1), s, -a, false);
|
||||
init_eq(s, a, sign);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
else if (bv.is_bit2bool(e, s, idx)) {
|
||||
auto& val = wval(s);
|
||||
val.try_set_bit(idx, !sign);
|
||||
val.fixed.set(idx, true);
|
||||
val.tighten_range();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sls_fixed::init_eq(expr* t, rational const& a, bool sign) {
|
||||
unsigned lo, hi;
|
||||
rational b(0);
|
||||
// verbose_stream() << mk_bounded_pp(t, m) << " == " << a << "\n";
|
||||
expr* s = nullptr;
|
||||
if (sign)
|
||||
// 1 <= t - a
|
||||
init_range(nullptr, rational(1), t, -a, false);
|
||||
else
|
||||
// t - a <= 0
|
||||
init_range(t, -a, nullptr, rational::zero(), false);
|
||||
if (!sign && bv.is_bv_not(t, s)) {
|
||||
for (unsigned i = 0; i < bv.get_bv_size(s); ++i)
|
||||
if (!a.get_bit(i))
|
||||
b += rational::power_of_two(i);
|
||||
init_eq(s, b, false);
|
||||
return true;
|
||||
}
|
||||
if (!sign && bv.is_concat(t) && to_app(t)->get_num_args() == 2) {
|
||||
auto x = to_app(t)->get_arg(0);
|
||||
auto y = to_app(t)->get_arg(1);
|
||||
auto sz = bv.get_bv_size(y);
|
||||
auto k = rational::power_of_two(sz);
|
||||
init_eq(y, mod(a, k), false);
|
||||
init_eq(x, div(a + k - 1, k), false);
|
||||
return true;
|
||||
}
|
||||
if (bv.is_extract(t, lo, hi, s)) {
|
||||
if (hi == lo) {
|
||||
sign = sign ? a == 1 : a == 0;
|
||||
auto& val = wval(s);
|
||||
if (val.try_set_bit(lo, !sign))
|
||||
val.fixed.set(lo, true);
|
||||
val.tighten_range();
|
||||
}
|
||||
else if (!sign) {
|
||||
auto& val = wval(s);
|
||||
for (unsigned i = lo; i <= hi; ++i)
|
||||
if (val.try_set_bit(i, a.get_bit(i - lo)))
|
||||
val.fixed.set(i, true);
|
||||
val.tighten_range();
|
||||
// verbose_stream() << lo << " " << hi << " " << val << " := " << a << "\n";
|
||||
}
|
||||
|
||||
if (!sign && hi + 1 == bv.get_bv_size(s)) {
|
||||
// s < 2^lo * (a + 1)
|
||||
rational b = rational::power_of_two(lo) * (a + 1) - 1;
|
||||
rational offset;
|
||||
get_offset(s, t, offset);
|
||||
// t + offset <= b
|
||||
init_range(t, offset, nullptr, b, false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -132,51 +185,66 @@ namespace bv {
|
|||
// a < x + b <=> ! (x + b <= a) <=> x not in [-a, b - a [ <=> x in [b - a, -a [ a != -1
|
||||
// x + a < x + b <=> ! (x + b <= x + a) <=> x in [-a, -b [ a != b
|
||||
//
|
||||
void sls_fixed::init_range(expr* x, rational const& a, expr* y, rational const& b, bool sign) {
|
||||
bool sls_fixed::init_range(expr* x, rational const& a, expr* y, rational const& b, bool sign) {
|
||||
if (!x && !y)
|
||||
return;
|
||||
if (!x) {
|
||||
// a <= y + b
|
||||
if (a == 0)
|
||||
return;
|
||||
auto& v = wval(y);
|
||||
if (!sign)
|
||||
v.add_range(a - b, -b);
|
||||
else
|
||||
v.add_range(-b, a - b);
|
||||
}
|
||||
else if (!y) {
|
||||
return false;
|
||||
if (!x)
|
||||
return add_range(y, a - b, -b, sign);
|
||||
else if (!y)
|
||||
return add_range(x, -a, b - a + 1, sign);
|
||||
else if (x == y)
|
||||
return add_range(x, -a, -b, sign);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mod(b + 1, rational::power_of_two(bv.get_bv_size(x))) == 0)
|
||||
return;
|
||||
auto& v = wval(x);
|
||||
if (!sign)
|
||||
v.add_range(-a, b - a + 1);
|
||||
else
|
||||
v.add_range(b - a + 1, -a);
|
||||
}
|
||||
else if (x == y) {
|
||||
if (a == b)
|
||||
return;
|
||||
auto& v = wval(x);
|
||||
if (!sign)
|
||||
v.add_range(-a, -b);
|
||||
else
|
||||
v.add_range(-b, -a);
|
||||
bool sls_fixed::add_range(expr* e, rational lo, rational hi, bool sign) {
|
||||
auto& v = wval(e);
|
||||
lo = mod(lo, rational::power_of_two(bv.get_bv_size(e)));
|
||||
hi = mod(hi, rational::power_of_two(bv.get_bv_size(e)));
|
||||
if (lo == hi)
|
||||
return false;
|
||||
if (sign)
|
||||
std::swap(lo, hi);
|
||||
v.add_range(lo, hi);
|
||||
if (v.lo() == 0 && bv.is_concat(e) && to_app(e)->get_num_args() == 2) {
|
||||
auto x = to_app(e)->get_arg(0);
|
||||
auto y = to_app(e)->get_arg(1);
|
||||
auto sz = bv.get_bv_size(y);
|
||||
auto k = rational::power_of_two(sz);
|
||||
lo = v.lo();
|
||||
hi = v.hi();
|
||||
if (hi <= k) {
|
||||
add_range(y, lo, hi, false);
|
||||
init_eq(x, lo, false);
|
||||
}
|
||||
else {
|
||||
hi = div(hi + k - 1, k);
|
||||
add_range(x, lo, hi, false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void sls_fixed::get_offset(expr* e, expr*& x, rational& offset) {
|
||||
expr* s, * t;
|
||||
x = e;
|
||||
offset = 0;
|
||||
if (bv.is_bv_add(e, s, t)) {
|
||||
if (bv.is_numeral(s, offset))
|
||||
rational n;
|
||||
while (true) {
|
||||
if (bv.is_bv_add(x, s, t) && bv.is_numeral(s, n)) {
|
||||
x = t;
|
||||
else if (bv.is_numeral(t, offset))
|
||||
offset += n;
|
||||
continue;
|
||||
}
|
||||
if (bv.is_bv_add(x, s, t) && bv.is_numeral(t, n)) {
|
||||
x = s;
|
||||
offset += n;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (bv.is_numeral(e, offset))
|
||||
if (bv.is_numeral(e, n))
|
||||
offset += n,
|
||||
x = nullptr;
|
||||
}
|
||||
|
||||
|
@ -264,11 +332,6 @@ namespace bv {
|
|||
case OP_BADD: {
|
||||
auto& a = wval(e->get_arg(0));
|
||||
auto& b = wval(e->get_arg(1));
|
||||
rational r;
|
||||
if (bv.is_numeral(e->get_arg(0), r) && b.has_range())
|
||||
v.add_range(r + b.lo(), r + b.hi());
|
||||
else if (bv.is_numeral(e->get_arg(1), r) && a.has_range())
|
||||
v.add_range(r + a.lo(), r + a.hi());
|
||||
bool pfixed = true;
|
||||
for (unsigned i = 0; i < v.bw; ++i) {
|
||||
if (pfixed && a.fixed.get(i) && b.fixed.get(i))
|
||||
|
@ -283,7 +346,6 @@ namespace bv {
|
|||
v.fixed.set(i, false);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case OP_BMUL: {
|
||||
|
|
|
@ -30,9 +30,11 @@ namespace bv {
|
|||
bv_util& bv;
|
||||
|
||||
void init_ranges(expr_ref_vector const& es);
|
||||
void init_range(app* e, bool sign);
|
||||
void init_range(expr* x, rational const& a, expr* y, rational const& b, bool sign);
|
||||
bool init_range(app* e, bool sign);
|
||||
bool init_range(expr* x, rational const& a, expr* y, rational const& b, bool sign);
|
||||
void get_offset(expr* e, expr*& x, rational& offset);
|
||||
bool init_eq(expr* e, rational const& v, bool sign);
|
||||
bool add_range(expr* e, rational lo, rational hi, bool sign);
|
||||
|
||||
void init_fixed_basic(app* e);
|
||||
void init_fixed_bv(app* e);
|
||||
|
|
|
@ -204,139 +204,69 @@ namespace bv {
|
|||
|
||||
//
|
||||
// largest dst <= src and dst is feasible
|
||||
// set dst := src & (~fixed | bits)
|
||||
//
|
||||
// increment dst if dst < src by setting bits below msb(src & ~dst) to 1
|
||||
//
|
||||
// if dst < lo < hi:
|
||||
// return false
|
||||
// if lo < hi <= dst:
|
||||
// set dst := hi - 1
|
||||
// if hi <= dst < lo
|
||||
// set dst := hi - 1
|
||||
//
|
||||
//
|
||||
|
||||
bool sls_valuation::get_at_most(bvect const& src, bvect& dst) const {
|
||||
SASSERT(!has_overflow(src));
|
||||
for (unsigned i = 0; i < nw; ++i)
|
||||
dst[i] = src[i] & (~fixed[i] | m_bits[i]);
|
||||
|
||||
//
|
||||
// If dst < src, then find the most significant
|
||||
// bit where src[idx] = 1, dst[idx] = 0
|
||||
// set dst[j] = bits_j | ~fixed_j for j < idx
|
||||
//
|
||||
for (unsigned i = nw; i-- > 0; ) {
|
||||
if (0 != (~dst[i] & src[i])) {
|
||||
auto idx = log2(~dst[i] & src[i]);
|
||||
auto mask = (1 << idx) - 1;
|
||||
dst[i] = (~fixed[i] & mask) | dst[i];
|
||||
for (unsigned j = i; j-- > 0; )
|
||||
dst[j] = (~fixed[j] | m_bits[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SASSERT(!has_overflow(dst));
|
||||
return round_down(dst);
|
||||
src.copy_to(nw, dst);
|
||||
sup_feasible(dst);
|
||||
if (in_range(dst)) {
|
||||
SASSERT(can_set(dst));
|
||||
return true;
|
||||
}
|
||||
if (dst < m_lo && m_lo < m_hi) // dst < lo < hi
|
||||
return false;
|
||||
if (is_zero(m_hi))
|
||||
return false;
|
||||
m_hi.copy_to(nw, dst); // hi <= dst < lo or lo < hi <= dst
|
||||
sub1(dst);
|
||||
SASSERT(can_set(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// smallest dst >= src and dst is feasible with respect to this.
|
||||
// set dst := (src & ~fixed) | (fixed & bits)
|
||||
//
|
||||
// decrement dst if dst > src by setting bits below msb to 0 unless fixed
|
||||
//
|
||||
// if lo < hi <= dst
|
||||
// return false
|
||||
// if dst < lo < hi:
|
||||
// set dst := lo
|
||||
// if hi <= dst < lo
|
||||
// set dst := lo
|
||||
//
|
||||
bool sls_valuation::get_at_least(bvect const& src, bvect& dst) const {
|
||||
SASSERT(!has_overflow(src));
|
||||
for (unsigned i = 0; i < nw; ++i)
|
||||
dst[i] = (~fixed[i] & src[i]) | (fixed[i] & m_bits[i]);
|
||||
src.copy_to(nw, dst);
|
||||
dst.set_bw(bw);
|
||||
inf_feasible(dst);
|
||||
if (in_range(dst)) {
|
||||
SASSERT(can_set(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// If dst > src, then find the most significant
|
||||
// bit where src[idx] = 0, dst[idx] = 1
|
||||
// set dst[j] = dst[j] & fixed_j for j < idx
|
||||
//
|
||||
for (unsigned i = nw; i-- > 0; ) {
|
||||
if (0 != (dst[i] & ~src[i])) {
|
||||
auto idx = log2(dst[i] & ~src[i]);
|
||||
auto mask = (1 << idx);
|
||||
dst[i] = dst[i] & (fixed[i] | mask);
|
||||
for (unsigned j = i; j-- > 0; )
|
||||
dst[j] = dst[j] & fixed[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
SASSERT(!has_overflow(dst));
|
||||
return round_up(dst);
|
||||
}
|
||||
|
||||
bool sls_valuation::round_up(bvect& dst) const {
|
||||
if (m_lo < m_hi) {
|
||||
if (m_hi <= dst)
|
||||
return false;
|
||||
if (m_lo > dst)
|
||||
set(dst, m_lo);
|
||||
}
|
||||
else if (m_hi <= dst && m_lo > dst)
|
||||
set(dst, m_lo);
|
||||
SASSERT(!has_overflow(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sls_valuation::round_down(bvect& dst) const {
|
||||
if (m_lo < m_hi) {
|
||||
if (m_lo > dst)
|
||||
return false;
|
||||
if (m_hi <= dst) {
|
||||
set(dst, m_hi);
|
||||
sub1(dst);
|
||||
}
|
||||
}
|
||||
else if (m_hi <= dst && m_lo > dst) {
|
||||
set(dst, m_hi);
|
||||
sub1(dst);
|
||||
}
|
||||
SASSERT(well_formed());
|
||||
if (dst > m_lo)
|
||||
return false;
|
||||
m_lo.copy_to(nw, dst);
|
||||
SASSERT(can_set(dst));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sls_valuation::set_random_at_most(bvect const& src, bvect& tmp, random_gen& r) {
|
||||
if (!get_at_most(src, tmp))
|
||||
return false;
|
||||
if (is_zero(tmp) || (0 == r() % 2))
|
||||
|
||||
if (is_zero(tmp) || (0 != r(10)))
|
||||
return try_set(tmp);
|
||||
|
||||
set_random_below(tmp, r);
|
||||
// random value below tmp
|
||||
|
||||
if (m_lo == m_hi || is_zero(m_lo) || m_lo <= tmp)
|
||||
return try_set(tmp);
|
||||
|
||||
// for simplicity, bail out if we were not lucky
|
||||
return get_at_most(src, tmp) && try_set(tmp);
|
||||
set_random_below(tmp, r);
|
||||
|
||||
return (can_set(tmp) || get_at_most(src, tmp)) && try_set(tmp);
|
||||
}
|
||||
|
||||
bool sls_valuation::set_random_at_least(bvect const& src, bvect& tmp, random_gen& r) {
|
||||
if (!get_at_least(src, tmp))
|
||||
return false;
|
||||
if (is_ones(tmp) || (0 == r() % 2))
|
||||
|
||||
if (is_ones(tmp) || (0 != r(10)))
|
||||
return try_set(tmp);
|
||||
|
||||
// random value at least tmp
|
||||
set_random_above(tmp, r);
|
||||
|
||||
if (m_lo == m_hi || is_zero(m_hi) || m_hi > tmp)
|
||||
return try_set(tmp);
|
||||
|
||||
// for simplicity, bail out if we were not lucky
|
||||
return get_at_least(src, tmp) && try_set(tmp);
|
||||
return (can_set(tmp) || get_at_least(src, tmp)) && try_set(tmp);
|
||||
}
|
||||
|
||||
bool sls_valuation::set_random_in_range(bvect const& lo, bvect const& hi, bvect& tmp, random_gen& r) {
|
||||
|
@ -533,7 +463,7 @@ namespace bv {
|
|||
|
||||
//
|
||||
// new_bits != bits => ~fixed
|
||||
// 0 = (new_bits ^ bits) & fixed
|
||||
// 0 = (new_bits ^ bits) & fixedf
|
||||
// also check that new_bits are in range
|
||||
//
|
||||
bool sls_valuation::can_set(bvect const& new_bits) const {
|
||||
|
@ -559,14 +489,16 @@ namespace bv {
|
|||
}
|
||||
|
||||
void sls_valuation::add_range(rational l, rational h) {
|
||||
|
||||
//return;
|
||||
return;
|
||||
//verbose_stream() << *this << " " << l << " " << h << " --> \n";
|
||||
|
||||
l = mod(l, rational::power_of_two(bw));
|
||||
h = mod(h, rational::power_of_two(bw));
|
||||
if (h == l)
|
||||
return;
|
||||
|
||||
// verbose_stream() << *this << " " << l << " " << h << " --> ";
|
||||
|
||||
if (m_lo == m_hi) {
|
||||
set_value(m_lo, l);
|
||||
set_value(m_hi, h);
|
||||
|
@ -591,19 +523,25 @@ namespace bv {
|
|||
set_value(m_lo, l);
|
||||
set_value(m_hi, h);
|
||||
}
|
||||
else if (old_lo + 1 == l) {
|
||||
else if (old_lo + 1 == l)
|
||||
set_value(m_lo, l);
|
||||
else if (old_hi == h + 1)
|
||||
set_value(m_hi, h);
|
||||
else if (old_hi == h && old_lo < l)
|
||||
set_value(m_lo, l);
|
||||
}
|
||||
else if (old_hi == h + 1) {
|
||||
else if (old_lo == l && h < old_hi)
|
||||
set_value(m_hi, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SASSERT(!has_overflow(m_lo));
|
||||
SASSERT(!has_overflow(m_hi));
|
||||
|
||||
//verbose_stream() << *this << " --> ";
|
||||
|
||||
tighten_range();
|
||||
|
||||
//verbose_stream() << *this << "\n";
|
||||
SASSERT(well_formed());
|
||||
}
|
||||
|
||||
|
@ -621,59 +559,76 @@ namespace bv {
|
|||
// lo + 1 = hi -> set bits = lo
|
||||
// lo < hi, set most significant bits based on hi
|
||||
//
|
||||
|
||||
unsigned sls_valuation::diff_index(bvect const& a) const {
|
||||
unsigned index = 0;
|
||||
for (unsigned i = nw; i-- > 0; ) {
|
||||
auto diff = fixed[i] & (m_bits[i] ^ a[i]);
|
||||
if (diff != 0 && index == 0)
|
||||
index = 1 + i * 8 * sizeof(digit_t) + log2(diff);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void sls_valuation::inf_feasible(bvect& a) const {
|
||||
unsigned lo_index = diff_index(a);
|
||||
|
||||
if (lo_index != 0) {
|
||||
lo_index--;
|
||||
SASSERT(a.get(lo_index) != m_bits.get(lo_index));
|
||||
SASSERT(fixed.get(lo_index));
|
||||
for (unsigned i = 0; i <= lo_index; ++i) {
|
||||
if (!fixed.get(i))
|
||||
a.set(i, false);
|
||||
else if (fixed.get(i))
|
||||
a.set(i, m_bits.get(i));
|
||||
}
|
||||
if (!a.get(lo_index)) {
|
||||
for (unsigned i = lo_index + 1; i < bw; ++i)
|
||||
if (!fixed.get(i) && !a.get(i)) {
|
||||
a.set(i, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sls_valuation::sup_feasible(bvect& a) const {
|
||||
unsigned hi_index = diff_index(a);
|
||||
if (hi_index != 0) {
|
||||
hi_index--;
|
||||
SASSERT(a.get(hi_index) != m_bits.get(hi_index));
|
||||
SASSERT(fixed.get(hi_index));
|
||||
for (unsigned i = 0; i <= hi_index; ++i) {
|
||||
if (!fixed.get(i))
|
||||
a.set(i, true);
|
||||
else if (fixed.get(i))
|
||||
a.set(i, m_bits.get(i));
|
||||
}
|
||||
if (a.get(hi_index)) {
|
||||
for (unsigned i = hi_index + 1; i < bw; ++i)
|
||||
if (!fixed.get(i) && a.get(i)) {
|
||||
a.set(i, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sls_valuation::tighten_range() {
|
||||
|
||||
if (m_lo == m_hi)
|
||||
return;
|
||||
|
||||
inf_feasible(m_lo);
|
||||
|
||||
bvect hi1(nw);
|
||||
hi1.set_bw(bw);
|
||||
m_hi.copy_to(nw, hi1);
|
||||
sub1(hi1);
|
||||
unsigned lo_index = 0, hi_index = 0;
|
||||
for (unsigned i = nw; i-- > 0; ) {
|
||||
auto lo_diff = (fixed[i] & (m_bits[i] ^ m_lo[i]));
|
||||
if (lo_diff != 0 && lo_index == 0)
|
||||
lo_index = 1 + i * 8 * sizeof(digit_t) + log2(lo_diff);
|
||||
auto hi_diff = (fixed[i] & (m_bits[i] ^ hi1[i]));
|
||||
if (hi_diff != 0 && hi_index == 0)
|
||||
hi_index = 1 + i * 8 * sizeof(digit_t) + log2(hi_diff);
|
||||
}
|
||||
|
||||
if (lo_index != 0) {
|
||||
lo_index--;
|
||||
SASSERT(m_lo.get(lo_index) != m_bits.get(lo_index));
|
||||
SASSERT(fixed.get(lo_index));
|
||||
for (unsigned i = 0; i <= lo_index; ++i) {
|
||||
if (!fixed.get(i))
|
||||
m_lo.set(i, false);
|
||||
else if (fixed.get(i))
|
||||
m_lo.set(i, m_bits.get(i));
|
||||
}
|
||||
for (unsigned i = lo_index + 1; i < bw; ++i)
|
||||
if (!fixed.get(i) && !m_lo.get(i)) {
|
||||
m_lo.set(i, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hi_index != 0) {
|
||||
hi_index--;
|
||||
SASSERT(hi1.get(hi_index) != m_bits.get(hi_index));
|
||||
SASSERT(fixed.get(hi_index));
|
||||
for (unsigned i = 0; i <= hi_index; ++i) {
|
||||
if (!fixed.get(i))
|
||||
hi1.set(i, true);
|
||||
else if (fixed.get(i))
|
||||
hi1.set(i, m_bits.get(i));
|
||||
}
|
||||
for (unsigned i = hi_index + 1; i < bw; ++i)
|
||||
if (!fixed.get(i) && hi1.get(i)) {
|
||||
hi1.set(i, false);
|
||||
break;
|
||||
}
|
||||
add1(hi1);
|
||||
hi1.copy_to(nw, m_hi);
|
||||
}
|
||||
sup_feasible(hi1);
|
||||
add1(hi1);
|
||||
hi1.copy_to(nw, m_hi);
|
||||
|
||||
if (has_range() && !in_range(m_bits))
|
||||
m_bits = m_lo;
|
||||
|
|
|
@ -113,8 +113,6 @@ namespace bv {
|
|||
unsigned m_signed_prefix = 0;
|
||||
|
||||
unsigned mask;
|
||||
bool round_up(bvect& dst) const;
|
||||
bool round_down(bvect& dst) const;
|
||||
|
||||
void repair_sign_bits(bvect& dst) const;
|
||||
|
||||
|
@ -141,9 +139,11 @@ namespace bv {
|
|||
SASSERT(in_range(m_bits));
|
||||
if (fixed.get(i) && get_bit(i) != b)
|
||||
return false;
|
||||
m_bits.set(i, b);
|
||||
eval.set(i, b);
|
||||
if (in_range(m_bits))
|
||||
return true;
|
||||
m_bits.set(i, !b);
|
||||
eval.set(i, !b);
|
||||
return false;
|
||||
}
|
||||
|
@ -155,6 +155,9 @@ namespace bv {
|
|||
rational lo() const { return m_lo.get_value(nw); }
|
||||
rational hi() const { return m_hi.get_value(nw); }
|
||||
|
||||
unsigned diff_index(bvect const& a) const;
|
||||
void inf_feasible(bvect& a) const;
|
||||
void sup_feasible(bvect& a) const;
|
||||
|
||||
void get(bvect& dst) const;
|
||||
void add_range(rational lo, rational hi);
|
||||
|
|
|
@ -175,8 +175,8 @@ public:
|
|||
m_st.reset();
|
||||
m_sls->collect_statistics(m_st);
|
||||
report_tactic_progress("Number of flips:", m_sls->get_num_moves());
|
||||
IF_VERBOSE(20, verbose_stream() << res << "\n");
|
||||
IF_VERBOSE(20, m_sls->display(verbose_stream()));
|
||||
IF_VERBOSE(10, verbose_stream() << res << "\n");
|
||||
IF_VERBOSE(10, m_sls->display(verbose_stream()));
|
||||
|
||||
if (res == l_true) {
|
||||
if (g->models_enabled()) {
|
||||
|
|
Loading…
Reference in a new issue