mirror of
https://github.com/Z3Prover/z3
synced 2025-04-07 09:55:19 +00:00
reorg sls
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
bab7ca2b70
commit
9a681b1a37
|
@ -438,6 +438,7 @@ public:
|
||||||
MATCH_BINARY(is_bv_xor);
|
MATCH_BINARY(is_bv_xor);
|
||||||
MATCH_BINARY(is_bv_nand);
|
MATCH_BINARY(is_bv_nand);
|
||||||
MATCH_BINARY(is_bv_nor);
|
MATCH_BINARY(is_bv_nor);
|
||||||
|
MATCH_BINARY(is_concat);
|
||||||
|
|
||||||
|
|
||||||
MATCH_BINARY(is_bv_uremi);
|
MATCH_BINARY(is_bv_uremi);
|
||||||
|
|
|
@ -56,18 +56,13 @@ namespace bv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto* t : m_terms.terms()) {
|
for (auto* t : m_terms.terms()) {
|
||||||
if (t && !re_eval_is_correct(t))
|
if (t && !m_eval.re_eval_is_correct(t))
|
||||||
m_repair_roots.insert(t->get_id());
|
m_repair_roots.insert(t->get_id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sls::init_repair_goal(app* t) {
|
void sls::init_repair_goal(app* t) {
|
||||||
if (m.is_bool(t))
|
m_eval.init_eval(t);
|
||||||
m_eval.set(t, m_eval.bval1(t));
|
|
||||||
else if (bv.is_bv(t)) {
|
|
||||||
auto& v = m_eval.wval(t);
|
|
||||||
v.bits().copy_to(v.nw, v.eval);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sls::init_repair_candidates() {
|
void sls::init_repair_candidates() {
|
||||||
|
@ -149,7 +144,7 @@ namespace bv {
|
||||||
SASSERT(m_eval.bval0(e));
|
SASSERT(m_eval.bval0(e));
|
||||||
return { true, e };
|
return { true, e };
|
||||||
}
|
}
|
||||||
if (!re_eval_is_correct(e)) {
|
if (!m_eval.re_eval_is_correct(e)) {
|
||||||
init_repair_goal(e);
|
init_repair_goal(e);
|
||||||
return { true, e };
|
return { true, e };
|
||||||
}
|
}
|
||||||
|
@ -162,7 +157,7 @@ namespace bv {
|
||||||
lbool sls::search1() {
|
lbool sls::search1() {
|
||||||
// init and init_eval were invoked
|
// init and init_eval were invoked
|
||||||
unsigned n = 0;
|
unsigned n = 0;
|
||||||
for (; n < m_config.m_max_repairs && m.inc(); ) {
|
for (; n < m_config.m_max_repairs && m.inc(); ++n) {
|
||||||
auto [down, e] = next_to_repair();
|
auto [down, e] = next_to_repair();
|
||||||
if (!e)
|
if (!e)
|
||||||
return l_true;
|
return l_true;
|
||||||
|
@ -170,10 +165,8 @@ namespace bv {
|
||||||
IF_VERBOSE(20, trace_repair(down, e));
|
IF_VERBOSE(20, trace_repair(down, e));
|
||||||
|
|
||||||
++m_stats.m_moves;
|
++m_stats.m_moves;
|
||||||
if (down) {
|
if (down)
|
||||||
try_repair_down(e);
|
try_repair_down(e);
|
||||||
++n;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
try_repair_up(e);
|
try_repair_up(e);
|
||||||
}
|
}
|
||||||
|
@ -219,12 +212,7 @@ namespace bv {
|
||||||
void sls::try_repair_down(app* e) {
|
void sls::try_repair_down(app* e) {
|
||||||
unsigned n = e->get_num_args();
|
unsigned n = e->get_num_args();
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
if (m.is_bool(e)) {
|
m_eval.commit_eval(e);
|
||||||
m_eval.set(e, m_eval.bval1(e));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
VERIFY(m_eval.wval(e).commit_eval());
|
|
||||||
}
|
|
||||||
|
|
||||||
IF_VERBOSE(3, verbose_stream() << "done\n");
|
IF_VERBOSE(3, verbose_stream() << "done\n");
|
||||||
for (auto p : m_terms.parents(e))
|
for (auto p : m_terms.parents(e))
|
||||||
|
@ -271,44 +259,24 @@ namespace bv {
|
||||||
m_repair_roots.insert(e->get_id());
|
m_repair_roots.insert(e->get_id());
|
||||||
else if (!m_eval.repair_up(e)) {
|
else if (!m_eval.repair_up(e)) {
|
||||||
IF_VERBOSE(2, verbose_stream() << "repair-up "; trace_repair(true, e));
|
IF_VERBOSE(2, verbose_stream() << "repair-up "; trace_repair(true, e));
|
||||||
init_repair();
|
if (m_rand(10) != 0) {
|
||||||
|
m_eval.set_random(e);
|
||||||
|
|
||||||
|
m_repair_roots.insert(e->get_id());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
init_repair();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!eval_is_correct(e)) {
|
if (!m_eval.eval_is_correct(e)) {
|
||||||
verbose_stream() << "incorrect eval #" << e->get_id() << " " << mk_bounded_pp(e, m) << "\n";
|
verbose_stream() << "incorrect eval #" << e->get_id() << " " << mk_bounded_pp(e, m) << "\n";
|
||||||
}
|
}
|
||||||
SASSERT(eval_is_correct(e));
|
SASSERT(m_eval.eval_is_correct(e));
|
||||||
for (auto p : m_terms.parents(e))
|
for (auto p : m_terms.parents(e))
|
||||||
m_repair_up.insert(p->get_id());
|
m_repair_up.insert(p->get_id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls::eval_is_correct(app* e) {
|
|
||||||
if (!m_eval.can_eval1(e))
|
|
||||||
return false;
|
|
||||||
if (m.is_bool(e))
|
|
||||||
return m_eval.bval0(e) == m_eval.bval1(e);
|
|
||||||
if (bv.is_bv(e)) {
|
|
||||||
auto const& v = m_eval.wval(e);
|
|
||||||
return v.eval == v.bits();
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool sls::re_eval_is_correct(app* e) {
|
|
||||||
if (!m_eval.can_eval1(e))
|
|
||||||
return false;
|
|
||||||
if (m.is_bool(e))
|
|
||||||
return m_eval.bval0(e) == m_eval.bval1(e);
|
|
||||||
if (bv.is_bv(e)) {
|
|
||||||
auto const& v = m_eval.eval(e);
|
|
||||||
return v.eval == v.bits();
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
model_ref sls::get_model() {
|
model_ref sls::get_model() {
|
||||||
if (m_engine_model)
|
if (m_engine_model)
|
||||||
|
@ -317,24 +285,17 @@ namespace bv {
|
||||||
model_ref mdl = alloc(model, m);
|
model_ref mdl = alloc(model, m);
|
||||||
auto& terms = m_eval.sort_assertions(m_terms.assertions());
|
auto& terms = m_eval.sort_assertions(m_terms.assertions());
|
||||||
for (expr* e : terms) {
|
for (expr* e : terms) {
|
||||||
if (!re_eval_is_correct(to_app(e))) {
|
if (!m_eval.re_eval_is_correct(to_app(e))) {
|
||||||
verbose_stream() << "missed evaluation #" << e->get_id() << " " << mk_bounded_pp(e, m) << "\n";
|
verbose_stream() << "missed evaluation #" << e->get_id() << " " << mk_bounded_pp(e, m) << "\n";
|
||||||
if (bv.is_bv(e)) {
|
m_eval.display_value(verbose_stream(), e) << "\n";
|
||||||
auto const& v = m_eval.wval(e);
|
|
||||||
verbose_stream() << v << "\n" << v.eval << "\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!is_uninterp_const(e))
|
if (!is_uninterp_const(e))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto f = to_app(e)->get_decl();
|
auto f = to_app(e)->get_decl();
|
||||||
if (m.is_bool(e))
|
auto v = m_eval.get_value(to_app(e));
|
||||||
mdl->register_decl(f, m.mk_bool_val(m_eval.bval0(e)));
|
if (v)
|
||||||
else if (bv.is_bv(e)) {
|
mdl->register_decl(f, v);
|
||||||
auto const& v = m_eval.wval(e);
|
|
||||||
rational n = v.get_value();
|
|
||||||
mdl->register_decl(f, bv.mk_numeral(n, v.bw));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
terms.reset();
|
terms.reset();
|
||||||
return mdl;
|
return mdl;
|
||||||
|
@ -350,10 +311,7 @@ namespace bv {
|
||||||
out << "u ";
|
out << "u ";
|
||||||
if (m_repair_roots.contains(e->get_id()))
|
if (m_repair_roots.contains(e->get_id()))
|
||||||
out << "r ";
|
out << "r ";
|
||||||
if (bv.is_bv(e))
|
m_eval.display_value(out, e);
|
||||||
out << m_eval.wval(e);
|
|
||||||
else if (m.is_bool(e))
|
|
||||||
out << (m_eval.bval0(e)?"T":"F");
|
|
||||||
out << "\n";
|
out << "\n";
|
||||||
}
|
}
|
||||||
terms.reset();
|
terms.reset();
|
||||||
|
@ -372,12 +330,10 @@ namespace bv {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& sls::trace_repair(bool down, expr* e) {
|
std::ostream& sls::trace_repair(bool down, expr* e) {
|
||||||
verbose_stream() << (down ? "d #" : "u #")
|
verbose_stream() << (down ? "d #" : "u #")
|
||||||
<< e->get_id() << ": "
|
<< e->get_id() << ": "
|
||||||
<< mk_bounded_pp(e, m, 1) << " ";
|
<< mk_bounded_pp(e, m, 1) << " ";
|
||||||
if (bv.is_bv(e)) verbose_stream() << m_eval.wval(e) << " " << (m_eval.is_fixed0(e) ? "fixed " : " ");
|
m_eval.display_value(verbose_stream(), e) << "\n";
|
||||||
if (m.is_bool(e)) verbose_stream() << m_eval.bval0(e) << " ";
|
|
||||||
verbose_stream() << "\n";
|
|
||||||
return verbose_stream();
|
return verbose_stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,6 @@ namespace bv {
|
||||||
|
|
||||||
std::pair<bool, app*> next_to_repair();
|
std::pair<bool, app*> next_to_repair();
|
||||||
|
|
||||||
bool eval_is_correct(app* e);
|
|
||||||
bool re_eval_is_correct(app* e);
|
|
||||||
void init_repair_goal(app* e);
|
void init_repair_goal(app* e);
|
||||||
void try_repair_down(app* e);
|
void try_repair_down(app* e);
|
||||||
void try_repair_up(app* e);
|
void try_repair_up(app* e);
|
||||||
|
|
|
@ -914,15 +914,14 @@ namespace bv {
|
||||||
|
|
||||||
bool sls_eval::try_repair_eq(bool is_true, bvval& a, bvval const& b) {
|
bool sls_eval::try_repair_eq(bool is_true, bvval& a, bvval const& b) {
|
||||||
if (is_true) {
|
if (is_true) {
|
||||||
if (m_rand() % 20 != 0)
|
if (m_rand(20) != 0)
|
||||||
if (a.try_set(b.bits()))
|
if (a.try_set(b.bits()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
a.get_variant(m_tmp, m_rand);
|
return a.set_random(m_rand);
|
||||||
return a.set_repair(random_bool(), m_tmp);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bool try_above = m_rand() % 2 == 0;
|
bool try_above = m_rand(2) == 0;
|
||||||
if (try_above) {
|
if (try_above) {
|
||||||
a.set_add(m_tmp, b.bits(), m_one);
|
a.set_add(m_tmp, b.bits(), m_one);
|
||||||
if (!a.is_zero(m_tmp) && a.set_random_at_least(m_tmp, m_tmp2, m_rand))
|
if (!a.is_zero(m_tmp) && a.set_random_at_least(m_tmp, m_tmp2, m_rand))
|
||||||
|
@ -1018,17 +1017,16 @@ namespace bv {
|
||||||
// If this fails, set a to a random value
|
// If this fails, set a to a random value
|
||||||
//
|
//
|
||||||
bool sls_eval::try_repair_add(bvect const& e, bvval& a, bvval const& b) {
|
bool sls_eval::try_repair_add(bvect const& e, bvval& a, bvval const& b) {
|
||||||
if (m_rand() % 20 != 0) {
|
if (m_rand(20) != 0) {
|
||||||
a.set_sub(m_tmp, e, b.bits());
|
a.set_sub(m_tmp, e, b.bits());
|
||||||
if (a.try_set(m_tmp))
|
if (a.try_set(m_tmp))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
a.get_variant(m_tmp, m_rand);
|
return a.set_random(m_rand);
|
||||||
return a.set_repair(random_bool(), m_tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls_eval::try_repair_sub(bvect const& e, bvval& a, bvval & b, unsigned i) {
|
bool sls_eval::try_repair_sub(bvect const& e, bvval& a, bvval & b, unsigned i) {
|
||||||
if (m_rand() % 20 != 0) {
|
if (m_rand(20) != 0) {
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
// e = a - b -> a := e + b
|
// e = a - b -> a := e + b
|
||||||
a.set_add(m_tmp, e, b.bits());
|
a.set_add(m_tmp, e, b.bits());
|
||||||
|
@ -1039,8 +1037,7 @@ namespace bv {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// fall back to a random value
|
// fall back to a random value
|
||||||
a.get_variant(m_tmp, m_rand);
|
return a.set_random(m_rand);
|
||||||
return a.set_repair(random_bool(), m_tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1058,15 +1055,11 @@ namespace bv {
|
||||||
return a.set_repair(random_bool(), m_tmp);
|
return a.set_repair(random_bool(), m_tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b.is_zero()) {
|
if (b.is_zero())
|
||||||
a.get_variant(m_tmp, m_rand);
|
return a.set_random(m_rand);
|
||||||
return a.set_repair(random_bool(), m_tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_rand() % 20 == 0) {
|
if (m_rand(20) == 0)
|
||||||
a.get_variant(m_tmp, m_rand);
|
return a.set_random(m_rand);
|
||||||
return a.set_repair(random_bool(), m_tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
verbose_stream() << "solve for " << e << "\n";
|
verbose_stream() << "solve for " << e << "\n";
|
||||||
|
@ -1096,7 +1089,7 @@ namespace bv {
|
||||||
b.shift_right(y, parity_b);
|
b.shift_right(y, parity_b);
|
||||||
#if 0
|
#if 0
|
||||||
for (unsigned i = parity_b; i < b.bw; ++i)
|
for (unsigned i = parity_b; i < b.bw; ++i)
|
||||||
y.set(i, m_rand() % 2 == 0);
|
y.set(i, m_rand(2) == 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1151,8 +1144,7 @@ namespace bv {
|
||||||
if (a.set_repair(random_bool(), m_tmp))
|
if (a.set_repair(random_bool(), m_tmp))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
a.get_variant(m_tmp, m_rand);
|
return a.set_random(m_rand);
|
||||||
return a.set_repair(random_bool(), m_tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls_eval::try_repair_bnot(bvect const& e, bvval& a) {
|
bool sls_eval::try_repair_bnot(bvect const& e, bvval& a) {
|
||||||
|
@ -1236,7 +1228,7 @@ namespace bv {
|
||||||
bool sls_eval::try_repair_sle(bvval& a, bvect const& b, bvect const& p2) {
|
bool sls_eval::try_repair_sle(bvval& a, bvect const& b, bvect const& p2) {
|
||||||
bool r = false;
|
bool r = false;
|
||||||
if (b < p2) {
|
if (b < p2) {
|
||||||
bool coin = m_rand() % 2 == 0;
|
bool coin = m_rand(2) == 0;
|
||||||
if (coin)
|
if (coin)
|
||||||
r = a.set_random_at_least(p2, m_tmp3, m_rand);
|
r = a.set_random_at_least(p2, m_tmp3, m_rand);
|
||||||
if (!r)
|
if (!r)
|
||||||
|
@ -1268,7 +1260,7 @@ namespace bv {
|
||||||
r = a.set_random_in_range(b, p2_1, m_tmp3, m_rand);
|
r = a.set_random_in_range(b, p2_1, m_tmp3, m_rand);
|
||||||
else {
|
else {
|
||||||
// random b <= x or x < p2
|
// random b <= x or x < p2
|
||||||
bool coin = m_rand() % 2 == 0;
|
bool coin = m_rand(2) == 0;
|
||||||
if (coin)
|
if (coin)
|
||||||
r = a.set_random_at_most(p2_1, m_tmp3, m_rand);
|
r = a.set_random_at_most(p2_1, m_tmp3, m_rand);
|
||||||
if (!r)
|
if (!r)
|
||||||
|
@ -1657,12 +1649,9 @@ namespace bv {
|
||||||
return a.set_repair(true, m_tmp3);
|
return a.set_repair(true, m_tmp3);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (a.is_one(e) && a.is_zero()) {
|
if (a.is_one(e) && a.is_zero())
|
||||||
for (unsigned i = 0; i < a.nw; ++i)
|
return b.set_random(m_rand);
|
||||||
m_tmp[i] = random_bits();
|
|
||||||
a.clear_overflow_bits(m_tmp);
|
|
||||||
return b.set_repair(true, m_tmp);
|
|
||||||
}
|
|
||||||
if (a.is_one(e)) {
|
if (a.is_one(e)) {
|
||||||
a.set(m_tmp, a.bits());
|
a.set(m_tmp, a.bits());
|
||||||
return b.set_repair(true, m_tmp);
|
return b.set_repair(true, m_tmp);
|
||||||
|
@ -1859,7 +1848,6 @@ namespace bv {
|
||||||
b.clear_overflow_bits(m_tmp);
|
b.clear_overflow_bits(m_tmp);
|
||||||
r = b.try_set(m_tmp);
|
r = b.try_set(m_tmp);
|
||||||
}
|
}
|
||||||
//verbose_stream() << e << " := " << a << " " << b << "\n";
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1869,15 +1857,15 @@ namespace bv {
|
||||||
// set a outside of [hi:lo] to random values with preference to 0 or 1 bits
|
// set a outside of [hi:lo] to random values with preference to 0 or 1 bits
|
||||||
//
|
//
|
||||||
bool sls_eval::try_repair_extract(bvect const& e, bvval& a, unsigned lo) {
|
bool sls_eval::try_repair_extract(bvect const& e, bvval& a, unsigned lo) {
|
||||||
if (m_rand() % m_config.m_prob_randomize_extract <= 100) {
|
if (m_rand(m_config.m_prob_randomize_extract) <= 100) {
|
||||||
a.get_variant(m_tmp, m_rand);
|
a.get_variant(m_tmp, m_rand);
|
||||||
if (0 == (m_rand() % 2)) {
|
if (0 == (m_rand(2))) {
|
||||||
auto bit = 0 == (m_rand() % 2);
|
auto bit = 0 == (m_rand(2));
|
||||||
if (!a.try_set_range(m_tmp, 0, lo, bit))
|
if (!a.try_set_range(m_tmp, 0, lo, bit))
|
||||||
a.try_set_range(m_tmp, 0, lo, !bit);
|
a.try_set_range(m_tmp, 0, lo, !bit);
|
||||||
}
|
}
|
||||||
if (0 == (m_rand() % 2)) {
|
if (0 == (m_rand(2))) {
|
||||||
auto bit = 0 == (m_rand() % 2);
|
auto bit = 0 == (m_rand(2));
|
||||||
if (!a.try_set_range(m_tmp, lo + e.bw, a.bw, bit))
|
if (!a.try_set_range(m_tmp, lo + e.bw, a.bw, bit))
|
||||||
a.try_set_range(m_tmp, lo + e.bw, a.bw, !bit);
|
a.try_set_range(m_tmp, lo + e.bw, a.bw, !bit);
|
||||||
}
|
}
|
||||||
|
@ -1888,10 +1876,7 @@ namespace bv {
|
||||||
m_tmp.set(i + lo, e.get(i));
|
m_tmp.set(i + lo, e.get(i));
|
||||||
if (a.try_set(m_tmp))
|
if (a.try_set(m_tmp))
|
||||||
return true;
|
return true;
|
||||||
a.get_variant(m_tmp, m_rand);
|
return a.set_random(m_rand);
|
||||||
bool res = a.set_repair(random_bool(), m_tmp);
|
|
||||||
// verbose_stream() << "try set " << res << " " << m_tmp[0] << " " << a << "\n";
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sls_eval::set_div(bvect const& a, bvect const& b, unsigned bw,
|
void sls_eval::set_div(bvect const& a, bvect const& b, unsigned bw,
|
||||||
|
@ -1945,6 +1930,66 @@ namespace bv {
|
||||||
return *m_values[e->get_id()];
|
return *m_values[e->get_id()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sls_eval::init_eval(app* t) {
|
||||||
|
if (m.is_bool(t))
|
||||||
|
set(t, bval1(t));
|
||||||
|
else if (bv.is_bv(t)) {
|
||||||
|
auto& v = wval(t);
|
||||||
|
v.bits().copy_to(v.nw, v.eval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sls_eval::commit_eval(app* e) {
|
||||||
|
if (m.is_bool(e)) {
|
||||||
|
set(e, bval1(e));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VERIFY(wval(e).commit_eval());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sls_eval::set_random(app* e) {
|
||||||
|
if (bv.is_bv(e))
|
||||||
|
eval(e).set_random(m_rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sls_eval::eval_is_correct(app* e) {
|
||||||
|
if (!can_eval1(e))
|
||||||
|
return false;
|
||||||
|
if (m.is_bool(e))
|
||||||
|
return bval0(e) == bval1(e);
|
||||||
|
if (bv.is_bv(e)) {
|
||||||
|
auto const& v = wval(e);
|
||||||
|
return v.eval == v.bits();
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sls_eval::re_eval_is_correct(app* e) {
|
||||||
|
if (!can_eval1(e))
|
||||||
|
return false;
|
||||||
|
if (m.is_bool(e))
|
||||||
|
return bval0(e) ==bval1(e);
|
||||||
|
if (bv.is_bv(e)) {
|
||||||
|
auto const& v = eval(e);
|
||||||
|
return v.eval == v.bits();
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_ref sls_eval::get_value(app* e) {
|
||||||
|
if (m.is_bool(e))
|
||||||
|
return expr_ref(m.mk_bool_val(bval0(e)), m);
|
||||||
|
else if (bv.is_bv(e)) {
|
||||||
|
auto const& v = wval(e);
|
||||||
|
rational n = v.get_value();
|
||||||
|
return expr_ref(bv.mk_numeral(n, v.bw), m);
|
||||||
|
}
|
||||||
|
return expr_ref(m);
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& sls_eval::display(std::ostream& out, expr_ref_vector const& es) {
|
std::ostream& sls_eval::display(std::ostream& out, expr_ref_vector const& es) {
|
||||||
auto& terms = sort_assertions(es);
|
auto& terms = sort_assertions(es);
|
||||||
for (expr* e : terms) {
|
for (expr* e : terms) {
|
||||||
|
@ -1960,4 +2005,12 @@ namespace bv {
|
||||||
terms.reset();
|
terms.reset();
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream& sls_eval::display_value(std::ostream& out, expr* e) {
|
||||||
|
if (bv.is_bv(e))
|
||||||
|
return out << wval(e);
|
||||||
|
if (m.is_bool(e))
|
||||||
|
return out << (bval0(e)?"T":"F");
|
||||||
|
return out << "?";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,18 @@ namespace bv {
|
||||||
|
|
||||||
sls_valuation& eval(app* e) const;
|
sls_valuation& eval(app* e) const;
|
||||||
|
|
||||||
|
void commit_eval(app* e);
|
||||||
|
|
||||||
|
void init_eval(app* e);
|
||||||
|
|
||||||
|
void set_random(app* e);
|
||||||
|
|
||||||
|
bool eval_is_correct(app* e);
|
||||||
|
|
||||||
|
bool re_eval_is_correct(app* e);
|
||||||
|
|
||||||
|
expr_ref get_value(app* e);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override evaluaton.
|
* Override evaluaton.
|
||||||
*/
|
*/
|
||||||
|
@ -178,5 +190,7 @@ namespace bv {
|
||||||
|
|
||||||
|
|
||||||
std::ostream& display(std::ostream& out, expr_ref_vector const& es);
|
std::ostream& display(std::ostream& out, expr_ref_vector const& es);
|
||||||
|
|
||||||
|
std::ostream& display_value(std::ostream& out, expr* e);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,8 @@ namespace bv {
|
||||||
else
|
else
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
ev.m_todo.reset();
|
|
||||||
init_ranges(es);
|
init_ranges(es);
|
||||||
|
ev.m_todo.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,6 +49,44 @@ namespace bv {
|
||||||
if (is_app(e))
|
if (is_app(e))
|
||||||
init_range(to_app(e), sign);
|
init_range(to_app(e), sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (expr* e : ev.m_todo)
|
||||||
|
propagate_range_up(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sls_fixed::propagate_range_up(expr* e) {
|
||||||
|
expr* t, * s;
|
||||||
|
rational v;
|
||||||
|
if (bv.is_concat(e, t, s)) {
|
||||||
|
auto& val = wval(s);
|
||||||
|
if (val.lo() != val.hi() && (val.lo() < val.hi() || val.hi() == 0))
|
||||||
|
// lo <= e
|
||||||
|
add_range(e, val.lo(), rational::zero(), false);
|
||||||
|
auto valt = wval(t);
|
||||||
|
#if 0
|
||||||
|
if (val.lo() < val.hi())
|
||||||
|
// e < (2^|s|) * hi
|
||||||
|
add_range(e, rational::zero(), val.hi() * rational::power_of_two(bv.get_bv_size(s)), false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (bv.is_bv_add(e, s, t) && bv.is_numeral(s, v)) {
|
||||||
|
auto& val = wval(t);
|
||||||
|
if (val.lo() != val.hi())
|
||||||
|
add_range(e, v + val.lo(), v + val.hi(), false);
|
||||||
|
}
|
||||||
|
else if (bv.is_bv_add(e, t, s) && bv.is_numeral(s, v)) {
|
||||||
|
auto& val = wval(t);
|
||||||
|
if (val.lo() != val.hi())
|
||||||
|
add_range(e, v + val.lo(), v + val.hi(), false);
|
||||||
|
}
|
||||||
|
// x in [1, 4[ => -x in [-3, 0[
|
||||||
|
// x in [lo, hi[ => -x in [-hi + 1, -lo + 1[
|
||||||
|
else if (bv.is_bv_mul(e, s, t) && bv.is_numeral(s, v) &&
|
||||||
|
v + 1 == rational::power_of_two(bv.get_bv_size(e))) {
|
||||||
|
auto& val = wval(t);
|
||||||
|
if (val.lo() != val.hi())
|
||||||
|
add_range(e, -val.hi() + 1, - val.lo() + 1, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// s <=s t <=> s + K <= t + K, K = 2^{bw-1}
|
// s <=s t <=> s + K <= t + K, K = 2^{bw-1}
|
||||||
|
@ -117,6 +155,7 @@ namespace bv {
|
||||||
val.tighten_range();
|
val.tighten_range();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,9 +177,8 @@ namespace bv {
|
||||||
init_eq(s, b, false);
|
init_eq(s, b, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!sign && bv.is_concat(t) && to_app(t)->get_num_args() == 2) {
|
expr* x, * y;
|
||||||
auto x = to_app(t)->get_arg(0);
|
if (!sign && bv.is_concat(t, x, y)) {
|
||||||
auto y = to_app(t)->get_arg(1);
|
|
||||||
auto sz = bv.get_bv_size(y);
|
auto sz = bv.get_bv_size(y);
|
||||||
auto k = rational::power_of_two(sz);
|
auto k = rational::power_of_two(sz);
|
||||||
init_eq(y, mod(a, k), false);
|
init_eq(y, mod(a, k), false);
|
||||||
|
@ -206,9 +244,8 @@ namespace bv {
|
||||||
if (sign)
|
if (sign)
|
||||||
std::swap(lo, hi);
|
std::swap(lo, hi);
|
||||||
v.add_range(lo, hi);
|
v.add_range(lo, hi);
|
||||||
if (v.lo() == 0 && bv.is_concat(e) && to_app(e)->get_num_args() == 2) {
|
expr* x, * y;
|
||||||
auto x = to_app(e)->get_arg(0);
|
if (v.lo() == 0 && bv.is_concat(e, x, y)) {
|
||||||
auto y = to_app(e)->get_arg(1);
|
|
||||||
auto sz = bv.get_bv_size(y);
|
auto sz = bv.get_bv_size(y);
|
||||||
auto k = rational::power_of_two(sz);
|
auto k = rational::power_of_two(sz);
|
||||||
lo = v.lo();
|
lo = v.lo();
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace bv {
|
||||||
|
|
||||||
void init_ranges(expr_ref_vector const& es);
|
void init_ranges(expr_ref_vector const& es);
|
||||||
bool init_range(app* e, bool sign);
|
bool init_range(app* e, bool sign);
|
||||||
|
void propagate_range_up(expr* e);
|
||||||
bool init_range(expr* x, rational const& a, expr* y, rational const& b, 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);
|
void get_offset(expr* e, expr*& x, rational& offset);
|
||||||
bool init_eq(expr* e, rational const& v, bool sign);
|
bool init_eq(expr* e, rational const& v, bool sign);
|
||||||
|
|
|
@ -153,6 +153,7 @@ namespace bv {
|
||||||
m_lo.set_bw(bw);
|
m_lo.set_bw(bw);
|
||||||
m_hi.set_bw(bw);
|
m_hi.set_bw(bw);
|
||||||
m_bits.set_bw(bw);
|
m_bits.set_bw(bw);
|
||||||
|
m_tmp.set_bw(bw);
|
||||||
fixed.set_bw(bw);
|
fixed.set_bw(bw);
|
||||||
eval.set_bw(bw);
|
eval.set_bw(bw);
|
||||||
// have lo, hi bits, fixed point to memory allocated within this of size num_bytes each allocated
|
// have lo, hi bits, fixed point to memory allocated within this of size num_bytes each allocated
|
||||||
|
@ -440,6 +441,11 @@ namespace bv {
|
||||||
clear_overflow_bits(dst);
|
clear_overflow_bits(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sls_valuation::set_random(random_gen& r) {
|
||||||
|
get_variant(m_tmp, r);
|
||||||
|
return set_repair(r(2) == 0, m_tmp);
|
||||||
|
}
|
||||||
|
|
||||||
void sls_valuation::repair_sign_bits(bvect& dst) const {
|
void sls_valuation::repair_sign_bits(bvect& dst) const {
|
||||||
if (m_signed_prefix == 0)
|
if (m_signed_prefix == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -489,7 +495,7 @@ namespace bv {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sls_valuation::add_range(rational l, rational h) {
|
void sls_valuation::add_range(rational l, rational h) {
|
||||||
return;
|
//return;
|
||||||
//verbose_stream() << *this << " " << l << " " << h << " --> \n";
|
//verbose_stream() << *this << " " << l << " " << h << " --> \n";
|
||||||
|
|
||||||
l = mod(l, rational::power_of_two(bw));
|
l = mod(l, rational::power_of_two(bw));
|
||||||
|
@ -622,7 +628,7 @@ namespace bv {
|
||||||
|
|
||||||
inf_feasible(m_lo);
|
inf_feasible(m_lo);
|
||||||
|
|
||||||
bvect hi1(nw);
|
bvect& hi1 = m_tmp;
|
||||||
hi1.set_bw(bw);
|
hi1.set_bw(bw);
|
||||||
m_hi.copy_to(nw, hi1);
|
m_hi.copy_to(nw, hi1);
|
||||||
sub1(hi1);
|
sub1(hi1);
|
||||||
|
|
|
@ -110,6 +110,7 @@ namespace bv {
|
||||||
protected:
|
protected:
|
||||||
bvect m_bits;
|
bvect m_bits;
|
||||||
bvect m_lo, m_hi; // range assignment to bit-vector, as wrap-around interval
|
bvect m_lo, m_hi; // range assignment to bit-vector, as wrap-around interval
|
||||||
|
bvect m_tmp;
|
||||||
unsigned m_signed_prefix = 0;
|
unsigned m_signed_prefix = 0;
|
||||||
|
|
||||||
unsigned mask;
|
unsigned mask;
|
||||||
|
@ -123,6 +124,7 @@ namespace bv {
|
||||||
bvect fixed; // bit assignment and don't care bit
|
bvect fixed; // bit assignment and don't care bit
|
||||||
bvect eval; // current evaluation
|
bvect eval; // current evaluation
|
||||||
|
|
||||||
|
|
||||||
sls_valuation(unsigned bw);
|
sls_valuation(unsigned bw);
|
||||||
|
|
||||||
void set_bw(unsigned bw);
|
void set_bw(unsigned bw);
|
||||||
|
@ -231,6 +233,7 @@ namespace bv {
|
||||||
bool set_repair(bool try_down, bvect& dst);
|
bool set_repair(bool try_down, bvect& dst);
|
||||||
void set_random_above(bvect& dst, random_gen& r);
|
void set_random_above(bvect& dst, random_gen& r);
|
||||||
void set_random_below(bvect& dst, random_gen& r);
|
void set_random_below(bvect& dst, random_gen& r);
|
||||||
|
bool set_random(random_gen& r);
|
||||||
void round_down(bvect& dst, std::function<bool(bvect const&)> const& is_feasible);
|
void round_down(bvect& dst, std::function<bool(bvect const&)> const& is_feasible);
|
||||||
void round_up(bvect& dst, std::function<bool(bvect const&)> const& is_feasible);
|
void round_up(bvect& dst, std::function<bool(bvect const&)> const& is_feasible);
|
||||||
|
|
||||||
|
@ -238,6 +241,7 @@ namespace bv {
|
||||||
static digit_t random_bits(random_gen& r);
|
static digit_t random_bits(random_gen& r);
|
||||||
void get_variant(bvect& dst, random_gen& r) const;
|
void get_variant(bvect& dst, random_gen& r) const;
|
||||||
|
|
||||||
|
|
||||||
bool try_set(bvect const& src) {
|
bool try_set(bvect const& src) {
|
||||||
if (!can_set(src))
|
if (!can_set(src))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1062,6 +1062,8 @@ new_lemma::~new_lemma() {
|
||||||
if (current().is_conflict()) {
|
if (current().is_conflict()) {
|
||||||
c.m_conflicts++;
|
c.m_conflicts++;
|
||||||
}
|
}
|
||||||
|
IF_VERBOSE(4, verbose_stream() << name << "\n");
|
||||||
|
IF_VERBOSE(4, verbose_stream() << *this << "\n");
|
||||||
TRACE("nla_solver", tout << name << " " << (++i) << "\n" << *this; );
|
TRACE("nla_solver", tout << name << " " << (++i) << "\n" << *this; );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1520,6 +1522,12 @@ lbool core::check() {
|
||||||
return l_false;
|
return l_false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (no_effect() && params().arith_nl_nra()) {
|
||||||
|
ret = m_nra.check();
|
||||||
|
lp_settings().stats().m_nra_calls++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (no_effect() && should_run_bounded_nlsat())
|
if (no_effect() && should_run_bounded_nlsat())
|
||||||
ret = bounded_nlsat();
|
ret = bounded_nlsat();
|
||||||
|
|
||||||
|
@ -1532,10 +1540,14 @@ lbool core::check() {
|
||||||
if (no_effect())
|
if (no_effect())
|
||||||
m_divisions.check();
|
m_divisions.check();
|
||||||
|
|
||||||
if (no_effect()) {
|
|
||||||
std::function<void(void)> check1 = [&]() { m_order.order_lemma(); };
|
if (false && no_effect()) {
|
||||||
std::function<void(void)> check2 = [&]() { m_monotone.monotonicity_lemma(); };
|
std::function<void(void)> check1 = [&]() { m_order.order_lemma();
|
||||||
std::function<void(void)> check3 = [&]() { m_tangents.tangent_lemma(); };
|
};
|
||||||
|
std::function<void(void)> check2 = [&]() { m_monotone.monotonicity_lemma();
|
||||||
|
};
|
||||||
|
std::function<void(void)> check3 = [&]() { m_tangents.tangent_lemma();
|
||||||
|
};
|
||||||
|
|
||||||
std::pair<unsigned, std::function<void(void)>> checks[] =
|
std::pair<unsigned, std::function<void(void)>> checks[] =
|
||||||
{ { 6, check1 },
|
{ { 6, check1 },
|
||||||
|
|
Loading…
Reference in a new issue