diff --git a/src/ast/sls/bv_sls.cpp b/src/ast/sls/bv_sls.cpp index b94d762cf4..f799d3cfee 100644 --- a/src/ast/sls/bv_sls.cpp +++ b/src/ast/sls/bv_sls.cpp @@ -124,6 +124,7 @@ namespace bv { }; m_eval.init_eval(m_terms.assertions(), eval); init_repair(); + // m_engine_init = false; } std::pair 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() { diff --git a/src/ast/sls/bv_sls.h b/src/ast/sls/bv_sls.h index b1a7f51dfe..01ccbc41f5 100644 --- a/src/ast/sls/bv_sls.h +++ b/src/ast/sls/bv_sls.h @@ -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(); diff --git a/src/ast/sls/bv_sls_eval.cpp b/src/ast/sls/bv_sls_eval.cpp index 2e83f17298..b69cec867d 100644 --- a/src/ast/sls/bv_sls_eval.cpp +++ b/src/ast/sls/bv_sls_eval.cpp @@ -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(b), 0); diff --git a/src/ast/sls/bv_sls_fixed.cpp b/src/ast/sls/bv_sls_fixed.cpp index e2b29b1fe0..18518ed09b 100644 --- a/src/ast/sls/bv_sls_fixed.cpp +++ b/src/ast/sls/bv_sls_fixed.cpp @@ -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: { diff --git a/src/ast/sls/bv_sls_fixed.h b/src/ast/sls/bv_sls_fixed.h index 14970c20c6..73dd5a52c3 100644 --- a/src/ast/sls/bv_sls_fixed.h +++ b/src/ast/sls/bv_sls_fixed.h @@ -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); diff --git a/src/ast/sls/sls_valuation.cpp b/src/ast/sls/sls_valuation.cpp index 6ce1c1df28..1f3674e932 100644 --- a/src/ast/sls/sls_valuation.cpp +++ b/src/ast/sls/sls_valuation.cpp @@ -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]); - - // - // 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); + src.copy_to(nw, dst); + dst.set_bw(bw); + inf_feasible(dst); + if (in_range(dst)) { + SASSERT(can_set(dst)); + return true; } - 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)) - 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) + if (is_zero(tmp) || (0 != r(10))) return try_set(tmp); - // for simplicity, bail out if we were not lucky - return get_at_most(src, tmp) && try_set(tmp); + // random value below 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 // - void sls_valuation::tighten_range() { - - if (m_lo == m_hi) - return; - bvect hi1(nw); - hi1.set_bw(bw); - m_hi.copy_to(nw, hi1); - sub1(hi1); - unsigned lo_index = 0, hi_index = 0; + unsigned sls_valuation::diff_index(bvect const& a) const { + unsigned 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); + 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(m_lo.get(lo_index) != m_bits.get(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)) - m_lo.set(i, false); + a.set(i, false); else if (fixed.get(i)) - m_lo.set(i, m_bits.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; + } } - for (unsigned i = lo_index + 1; i < bw; ++i) - if (!fixed.get(i) && !m_lo.get(i)) { - m_lo.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(hi1.get(hi_index) != m_bits.get(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)) - hi1.set(i, true); + a.set(i, true); else if (fixed.get(i)) - hi1.set(i, m_bits.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; + } } - 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); } + } + + 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); + sup_feasible(hi1); + add1(hi1); + hi1.copy_to(nw, m_hi); if (has_range() && !in_range(m_bits)) m_bits = m_lo; diff --git a/src/ast/sls/sls_valuation.h b/src/ast/sls/sls_valuation.h index 90794bfe2b..04efec24a5 100644 --- a/src/ast/sls/sls_valuation.h +++ b/src/ast/sls/sls_valuation.h @@ -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); diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 520682d1bc..f484372c8b 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -175,8 +175,8 @@ class bv_sls_tactic : public tactic { 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()) {