3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 13:28:47 +00:00
- avoid more platform specific behavior when using m_mk_extract,
- rename mk_eq in bool_rewriter to mk_eq_plain to distinguish it from mk_eq_rw
- rework bv_lookahead to be more closely based on sls_engine, which has much better heuristic behavior than attempt 1.
This commit is contained in:
Nikolaj Bjorner 2024-12-28 17:40:15 -08:00
parent a5bc5ed813
commit f41134d1b6
17 changed files with 506 additions and 257 deletions

View file

@ -671,12 +671,12 @@ br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result)
expr* cond2 = nullptr, *t2 = nullptr, *e2 = nullptr; expr* cond2 = nullptr, *t2 = nullptr, *e2 = nullptr;
if (m().is_ite(t, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2) && if (m().is_ite(t, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2) &&
BR_FAILED != try_ite_value(to_app(t), val, result)) { BR_FAILED != try_ite_value(to_app(t), val, result)) {
result = m().mk_ite(cond, result, mk_eq(e, val)); result = m().mk_ite(cond, result, mk_eq_plain(e, val));
return BR_REWRITE2; return BR_REWRITE2;
} }
if (m().is_ite(e, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2) && if (m().is_ite(e, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2) &&
BR_FAILED != try_ite_value(to_app(e), val, result)) { BR_FAILED != try_ite_value(to_app(e), val, result)) {
result = m().mk_ite(cond, mk_eq(t, val), result); result = m().mk_ite(cond, mk_eq_plain(t, val), result);
return BR_REWRITE2; return BR_REWRITE2;
} }
@ -684,11 +684,15 @@ br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result)
} }
app* bool_rewriter::mk_eq(expr* lhs, expr* rhs) { app* bool_rewriter::mk_eq_plain(expr* lhs, expr* rhs) {
if (m().are_equal(lhs, rhs)) if (m().are_equal(lhs, rhs))
return m().mk_true(); return m().mk_true();
if (m().are_distinct(lhs, rhs)) if (m().are_distinct(lhs, rhs))
return m().mk_false(); return m().mk_false();
if (m().is_false(rhs)) {
verbose_stream() << "here\n";
}
VERIFY(!m().is_false(rhs));
return m().mk_eq(lhs, rhs); return m().mk_eq(lhs, rhs);
} }
@ -775,7 +779,8 @@ br_status bool_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) {
std::swap(lhs, rhs); std::swap(lhs, rhs);
if (m().is_not(lhs, lhs)) { if (m().is_not(lhs, lhs)) {
result = m().mk_not(m().mk_eq(lhs, rhs)); mk_eq(lhs, rhs, result);
mk_not(result, result);
return BR_REWRITE2; return BR_REWRITE2;
} }

View file

@ -135,11 +135,11 @@ public:
br_status mk_ite_core(expr * c, expr * t, expr * e, expr_ref & result); br_status mk_ite_core(expr * c, expr * t, expr * e, expr_ref & result);
br_status mk_not_core(expr * t, expr_ref & result); br_status mk_not_core(expr * t, expr_ref & result);
app* mk_eq(expr* lhs, expr* rhs); app* mk_eq_plain(expr* lhs, expr* rhs);
void mk_eq(expr * lhs, expr * rhs, expr_ref & result) { void mk_eq(expr * lhs, expr * rhs, expr_ref & result) {
if (mk_eq_core(lhs, rhs, result) == BR_FAILED) if (mk_eq_core(lhs, rhs, result) == BR_FAILED)
result = mk_eq(lhs, rhs); result = mk_eq_plain(lhs, rhs);
} }
expr_ref mk_eq_rw(expr* lhs, expr* rhs) { expr_ref mk_eq_rw(expr* lhs, expr* rhs) {
expr_ref r(m()), _lhs(lhs, m()), _rhs(rhs, m()); expr_ref r(m()), _lhs(lhs, m()), _rhs(rhs, m());

View file

@ -640,8 +640,13 @@ br_status bv_rewriter::mk_leq_core(bool is_signed, expr * a, expr * b, expr_ref
// use the equivalence to simplify: // use the equivalence to simplify:
// #x000f <=_u b <=> b[sz-1:lnz+1] != 0 or #xf <= b[lnz:0]) // #x000f <=_u b <=> b[sz-1:lnz+1] != 0 or #xf <= b[lnz:0])
result = m.mk_implies(m.mk_eq(m_mk_extract(bv_sz - 1, lnz + 1, b), mk_zero(bv_sz - lnz - 1)), expr_ref e1(m_mk_extract(bv_sz - 1, lnz + 1, b), m);
m_util.mk_ule(m_mk_extract(lnz, 0, a), m_mk_extract(lnz, 0, b))); expr_ref e2(mk_zero(bv_sz - lnz - 1), m);
e1 = m.mk_eq(e1, e2);
expr_ref e3(m_mk_extract(lnz, 0, a), m);
expr_ref e4(m_mk_extract(lnz, 0, b), m);
e2 = m_util.mk_ule(e3, e4);
result = m.mk_implies(e1, e2);
return BR_REWRITE_FULL; return BR_REWRITE_FULL;
} }
} }
@ -866,6 +871,13 @@ br_status bv_rewriter::mk_extract(unsigned high, unsigned low, expr * arg, expr_
return BR_REWRITE2; return BR_REWRITE2;
} }
// [....][xx] -> [yy][....] hi <= |[....]| then can extract [hi + k:lo + k]
// (ashr t k)[hi:0] -> t[hi+k:k]
if (low == 0 && m_util.is_bv_ashr(arg, t, c) && m_util.is_numeral(c, v, sz) && high < sz - v) {
result = m_mk_extract(high + v.get_unsigned(), low + v.get_unsigned(), t);
return BR_REWRITE1;
}
return BR_FAILED; return BR_FAILED;
} }
@ -2498,8 +2510,8 @@ br_status bv_rewriter::mk_bit2bool(expr * lhs, expr * rhs, expr_ref & result) {
expr* a = nullptr, *b = nullptr, *c = nullptr; expr* a = nullptr, *b = nullptr, *c = nullptr;
if (m.is_ite(lhs, a, b, c)) { if (m.is_ite(lhs, a, b, c)) {
bool_rewriter rw(m); bool_rewriter rw(m);
expr_ref e1(rw.mk_eq(b, rhs), m); expr_ref e1(rw.mk_eq_rw(b, rhs), m);
expr_ref e2(rw.mk_eq(c, rhs), m); expr_ref e2(rw.mk_eq_rw(c, rhs), m);
result = rw.mk_ite(a, e1, e2); result = rw.mk_ite(a, e1, e2);
return BR_REWRITE2; return BR_REWRITE2;
} }

View file

@ -29,7 +29,7 @@ namespace sls {
bool basic_plugin::is_basic(expr* e) const { bool basic_plugin::is_basic(expr* e) const {
if (!e || !is_app(e)) if (!e || !is_app(e))
return false; return false;
if (m.is_ite(e) && !m.is_bool(e) && false) if (m.is_ite(e) && !m.is_bool(e))
return true; return true;
if (m.is_xor(e) && to_app(e)->get_num_args() != 2) if (m.is_xor(e) && to_app(e)->get_num_args() != 2)
return true; return true;
@ -149,7 +149,6 @@ namespace sls {
if (m.is_value(child)) if (m.is_value(child))
return false; return false;
bool r = ctx.set_value(child, ctx.get_value(e)); bool r = ctx.set_value(child, ctx.get_value(e));
verbose_stream() << "repair-ite-down " << mk_bounded_pp(e, m) << " @ " << mk_bounded_pp(child, m) << " := " << ctx.get_value(e) << " success " << r << "\n";
return r; return r;
} }
@ -166,7 +165,6 @@ namespace sls {
val = eval_distinct(e); val = eval_distinct(e);
else else
return; return;
verbose_stream() << "repair-up " << mk_bounded_pp(e, m) << " " << val << "\n";
if (!ctx.set_value(e, val)) if (!ctx.set_value(e, val))
ctx.new_value_eh(e); ctx.new_value_eh(e);
} }
@ -176,14 +174,14 @@ namespace sls {
bool basic_plugin::repair_down(app* e) { bool basic_plugin::repair_down(app* e) {
if (!is_basic(e)) if (!is_basic(e))
return true; return true;
if (m.is_xor(e) && eval_xor(e) == ctx.get_value(e)) if (m.is_xor(e) && eval_xor(e) == ctx.get_value(e))
return true; return true;
if (m.is_ite(e) && eval_ite(e) == ctx.get_value(e)) if (m.is_ite(e) && eval_ite(e) == ctx.get_value(e))
return true; return true;
if (m.is_distinct(e) && eval_distinct(e) == ctx.get_value(e)) if (m.is_distinct(e) && eval_distinct(e) == ctx.get_value(e))
return true; return true;
verbose_stream() << "basic repair down " << mk_bounded_pp(e, m) << "\n";
unsigned n = e->get_num_args(); unsigned n = e->get_num_args();
unsigned s = ctx.rand(n); unsigned s = ctx.rand(n);
for (unsigned i = 0; i < n; ++i) { for (unsigned i = 0; i < n; ++i) {

View file

@ -477,9 +477,7 @@ lbool sls_engine::search() {
// update assertion weights if a weighting is enabled (sp < 1024) // update assertion weights if a weighting is enabled (sp < 1024)
if (m_paws) if (m_paws)
{ {
for (unsigned i = 0; i < sz; i++) for (auto q : m_assertions) {
{
expr * q = m_assertions[i];
// smooth weights with probability sp / 1024 // smooth weights with probability sp / 1024
if (m_tracker.get_random_uint(10) < m_paws_sp) if (m_tracker.get_random_uint(10) < m_paws_sp)
{ {

View file

@ -48,6 +48,10 @@ namespace sls {
} }
} }
void bv_eval::start_propagation() {
m_lookahead.start_propagation();
}
void bv_eval::add_bit_vector(app* e) { void bv_eval::add_bit_vector(app* e) {
if (!bv.is_bv(e)) if (!bv.is_bv(e))
return; return;
@ -688,8 +692,6 @@ namespace sls {
expr* arg = e->get_arg(i); expr* arg = e->get_arg(i);
if (m.is_value(arg)) if (m.is_value(arg))
return false; return false;
if (m.is_bool(e) && is_lookahead_phase() && m_lookahead.try_repair_down(e))
return true;
if (e->get_family_id() == bv.get_family_id() && try_repair_bv(e, i)) { if (e->get_family_id() == bv.get_family_id() && try_repair_bv(e, i)) {
commit_eval(e, to_app(arg)); commit_eval(e, to_app(arg));
IF_VERBOSE(11, verbose_stream() << "repair " << mk_bounded_pp(e, m) << " : " << mk_bounded_pp(arg, m) << " := " << wval(arg) << "\n";); IF_VERBOSE(11, verbose_stream() << "repair " << mk_bounded_pp(e, m) << " : " << mk_bounded_pp(arg, m) << " := " << wval(arg) << "\n";);
@ -702,8 +704,6 @@ namespace sls {
ctx.new_value_eh(arg); ctx.new_value_eh(arg);
return true; return true;
} }
if (m.is_bool(e) && m_lookahead.try_repair_down(e))
return true;
return false; return false;
} }

View file

@ -156,6 +156,8 @@ namespace sls {
void init() { m_fix.init(); } void init() { m_fix.init(); }
void start_propagation();
void register_term(expr* e); void register_term(expr* e);
/** /**

View file

@ -658,6 +658,7 @@ public:
} }
void serious_update(func_decl * fd, const mpz & new_value) { void serious_update(func_decl * fd, const mpz & new_value) {
TRACE("sls", tout << "set: " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << std::endl;);
m_tracker.set_value(fd, new_value); m_tracker.set_value(fd, new_value);
expr * ep = m_tracker.get_entry_point(fd); expr * ep = m_tracker.get_entry_point(fd);
unsigned cur_depth = m_tracker.get_distance(ep); unsigned cur_depth = m_tracker.get_distance(ep);

View file

@ -29,6 +29,8 @@ namespace sls {
void bv_fixed::init() { void bv_fixed::init() {
return;
for (auto e : ctx.subterms()) for (auto e : ctx.subterms())
set_fixed(e); set_fixed(e);

View file

@ -3,11 +3,13 @@ Copyright (c) 2024 Microsoft Corporation
Module Name: Module Name:
sls_bv_lookahead.h sls_bv_lookahead
Abstract: Abstract:
Lookahead solver for BV, modeled after sls_engine/sls_tracker/sls_evaluator. Lookahead solver for BV, modeled after
sls_bv_engine/sls_bv_tracker/sls_bv_evaluator
by Froelich and Wintersteiger.
Author: Author:
@ -18,57 +20,86 @@ Author:
#include "ast/sls/sls_bv_lookahead.h" #include "ast/sls/sls_bv_lookahead.h"
#include "ast/sls/sls_bv_eval.h" #include "ast/sls/sls_bv_eval.h"
#include "ast/sls/sls_bv_terms.h" #include "ast/sls/sls_bv_terms.h"
#include "params/sls_params.hpp"
#include "ast/ast_pp.h" #include "ast/ast_pp.h"
#include <cmath> #include <cmath>
namespace sls { namespace sls {
bv_lookahead::bv_lookahead(bv_eval& ev) : bv_lookahead::bv_lookahead(bv_eval& ev) :
bv(ev.m), bv(ev.m),
m_ev(ev), m_ev(ev),
ctx(ev.ctx), ctx(ev.ctx),
m(ev.m) {} m(ev.m) {
bool bv_lookahead::try_repair_down(app* e) {
if (!m.is_bool(e))
return false;
if (m_ev.bval1(e) == m_ev.bval0(e))
return true;
auto const& uninterp = m_ev.terms.uninterp_occurs(e);
if (uninterp.empty())
return false;
if (false && ctx.rand(10) == 0 && apply_random_update(uninterp))
return true;
reset_updates();
TRACE("sls", tout << mk_bounded_pp(e, m) << " contains ";
for (auto e : uninterp)
tout << mk_bounded_pp(e, m) << " ";
tout << "\n";);
for (auto e : uninterp)
add_updates(e);
m_stats.m_num_lookahead += 1;
m_stats.m_num_updates += m_num_updates;
TRACE("sls", display_updates(tout));
if (apply_update())
return true;
return apply_random_update(uninterp);
} }
void bv_lookahead::display_updates(std::ostream& out) { void bv_lookahead::init_updates() {
for (unsigned i = 0; i < m_num_updates; ++i) { m_best_expr = nullptr;
auto const& [e, score, new_value] = m_updates[i]; }
out << mk_bounded_pp(e, m) << " " << new_value << " score: " << score << "\n";
lbool bv_lookahead::search() {
updt_params(ctx.get_params());
rescore();
m_config.max_moves = m_stats.m_moves + m_config.max_moves_base;
while (m.inc() && m_stats.m_moves < m_config.max_moves) {
m_stats.m_moves++;
check_restart();
// get candidate variables
auto& vars = get_candidate_uninterp();
if (vars.empty())
return l_true;
// random walk with probability 1000/wp
if (ctx.rand(10) < m_config.wp && apply_random_update(vars))
continue;
if (apply_guided_update(vars))
continue;
apply_random_update(vars);
recalibrate_weights();
} }
m_config.max_moves_base += 100;
return l_undef;
} }
bool bv_lookahead::apply_guided_update(ptr_vector<expr> const& vars) {
init_updates();
double old_top_score = m_top_score;
for (auto u : vars)
add_updates(u);
m_top_score = old_top_score;
return apply_update();
}
ptr_vector<expr> const& bv_lookahead::get_candidate_uninterp() {
auto const& lits = ctx.root_literals();
unsigned start = ctx.rand(lits.size());
for (unsigned i = 0; i < lits.size(); ++i) {
auto lit = lits[(i + start) % lits.size()];
auto e = ctx.atom(lit.var());
if (!e || !is_app(e))
continue;
app* a = to_app(e);
if (!m_ev.can_eval1(a))
continue;
if (m_ev.bval0(a) == m_ev.bval1(a))
continue;
auto const& vars = m_ev.terms.uninterp_occurs(a);
VERIFY(!vars.empty());
TRACE("bv", tout << "candidates " << mk_bounded_pp(e, m) << ": ";
for (auto e : vars)
tout << mk_bounded_pp(e, m) << " ";
tout << "\n";);
return vars;
}
return m_vars;
}
bool bv_lookahead::apply_random_update(ptr_vector<expr> const& vars) { bool bv_lookahead::apply_random_update(ptr_vector<expr> const& vars) {
while (true) { while (true) {
expr* e = vars[ctx.rand(vars.size())]; expr* e = vars[ctx.rand(vars.size())];
@ -76,22 +107,135 @@ namespace sls {
m_v_updated.set_bw(v.bw); m_v_updated.set_bw(v.bw);
v.get_variant(m_v_updated, m_ev.m_rand); v.get_variant(m_v_updated, m_ev.m_rand);
v.eval = m_v_updated; v.eval = m_v_updated;
if (!v.commit_eval()) if (!v.commit_eval())
continue; continue;
apply_update(e, m_v_updated); apply_update(e, m_v_updated);
break; break;
} }
return true; return true;
} }
void bv_lookahead::check_restart() {
if (m_stats.m_moves % m_config.restart_base == 0)
// ucb_forget();
rescore();
if (m_stats.m_moves < m_config.restart_next)
return;
if (m_stats.m_restarts & 1)
m_config.restart_next += m_config.restart_base;
else
m_config.restart_next += (2 << (m_stats.m_restarts >> 1)) * m_config.restart_base;
m_stats.m_restarts++;
// TODO: reset values of uninterpreted to 0
}
void bv_lookahead::updt_params(params_ref const& _p) {
sls_params p(_p);
//m_config.max_restarts = p.max_restarts();
m_config.walksat = p.walksat();
m_config.walksat_repick = p.walksat_repick();
m_config.paws_sp = p.paws_sp();
m_config.paws = m_config.paws_sp < 1024;
m_config.wp = p.wp();
m_config.restart_base = p.restart_base();
m_config.restart_next = m_config.restart_base;
m_config.restart_init = p.restart_init();
m_config.early_prune = p.early_prune();
}
double bv_lookahead::new_score(app* a) {
bool is_true = ctx.is_true(a);
bool is_true_new = m_ev.bval1(a);
if (!ctx.is_relevant(a))
return 0;
if (is_true == is_true_new)
return 1;
expr* x, * y;
if (is_true && m.is_eq(a, x, y) && bv.is_bv(x)) {
auto const& vx = wval(x);
auto const& vy = wval(y);
// hamming distance between vx.bits() and vy.bits():
double delta = 0;
for (unsigned i = 0; i < vx.bw; ++i)
if (vx.bits().get(i) != vy.bits().get(i))
++delta;
return 1 - (delta / vx.bw);
}
else if (bv.is_ule(a, x, y)) {
auto const& vx = wval(x);
auto const& vy = wval(y);
if (is_true)
// x > y as unsigned.
// x - y > 0
// score = (x - y) / 2^bw
vx.set_sub(m_ev.m_tmp, vx.bits(), vy.bits());
else {
// x <= y as unsigned.
// y - x >= 0
// score = (y - x + 1) / 2^bw
vx.set_sub(m_ev.m_tmp, vy.bits(), vx.bits());
vx.add1(m_ev.m_tmp);
}
rational n = m_ev.m_tmp.get_value(vx.nw);
n /= rational(rational::power_of_two(vx.bw));
double dbl = n.get_double();
return (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
}
else if (bv.is_sle(a, x, y)) {
auto const& vx = wval(x);
auto const& vy = wval(y);
// x += 2^bw-1
// y += 2^bw-1
vy.bits().copy_to(vy.nw, m_ev.m_tmp);
vx.bits().copy_to(vx.nw, m_ev.m_tmp2);
m_ev.m_tmp.set(vy.bw - 1, !m_ev.m_tmp.get(vy.bw - 1));
m_ev.m_tmp2.set(vx.bw - 1, !m_ev.m_tmp2.get(vx.bw - 1));
if (is_true) {
// x >s y
// x' - y' > 0
vx.set_sub(m_ev.m_tmp3, m_ev.m_tmp2, m_ev.m_tmp);
}
else {
// x <=s y
// y' - x' >= 0
vx.set_sub(m_ev.m_tmp3, m_ev.m_tmp, m_ev.m_tmp2);
vx.add1(m_ev.m_tmp3);
}
rational n = m_ev.m_tmp3.get_value(vx.nw);
n /= rational(rational::power_of_two(vx.bw));
double dbl = n.get_double();
return (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
}
else if (is_true && m.is_distinct(a) && bv.is_bv(a->get_arg(0))) {
double np = 0, nd = 0;
for (unsigned i = 0; i < a->get_num_args(); ++i) {
auto const& vi = wval(a->get_arg(i));
for (unsigned j = i + 1; j < a->get_num_args(); ++j) {
++np;
auto const& vj = wval(a->get_arg(j));
if (vi.bits() != vj.bits())
nd++;
}
}
return nd / np;
}
return 0;
}
double bv_lookahead::lookahead(expr* e, bvect const& new_value) { double bv_lookahead::lookahead(expr* e, bvect const& new_value) {
SASSERT(bv.is_bv(e)); SASSERT(bv.is_bv(e));
SASSERT(is_uninterp(e)); SASSERT(is_uninterp(e));
SASSERT(m_restore.empty()); SASSERT(m_restore.empty());
bool has_tabu = false; bool has_tabu = false;
int result = 0;
int breaks = 0;
wval(e).eval = new_value; wval(e).eval = new_value;
if (!insert_update(e)) { if (!insert_update(e)) {
@ -115,20 +259,8 @@ namespace sls {
has_tabu = true; has_tabu = true;
} }
else if (m.is_bool(a) && m_ev.can_eval1(a)) { else if (m.is_bool(a) && m_ev.can_eval1(a)) {
if (!ctx.is_relevant(a))
continue; rescore(a);
bool is_true = ctx.is_true(a);
bool is_true_new = m_ev.bval1(a);
bool is_true_old = m_ev.bval1_tmp(a);
TRACE("sls_verbose", tout << mk_bounded_pp(a, m) << " " << is_true << " " << is_true_new << " " << is_true_old << "\n");
if (is_true_new == is_true_old)
continue;
if (is_true == is_true_new)
++result;
if (is_true == is_true_old) {
--result;
++breaks;
}
} }
else { else {
IF_VERBOSE(1, verbose_stream() << "skipping " << mk_bounded_pp(a, m) << "\n"); IF_VERBOSE(1, verbose_stream() << "skipping " << mk_bounded_pp(a, m) << "\n");
@ -140,46 +272,55 @@ namespace sls {
m_in_update_stack.reset(); m_in_update_stack.reset();
restore_lookahead(); restore_lookahead();
TRACE("sls_verbose", tout << mk_bounded_pp(e, m) << " " << new_value << " " << result << " " << breaks << "\n"); TRACE("sls_verbose", tout << mk_bounded_pp(e, m) << " := " << new_value << " score: " << m_top_score << "\n");
if (has_tabu) if (has_tabu)
return -10000; return -10000;
if (result < 0) if (m_top_score <= 0.000001)
return 0.0000001; return -10000;
else if (result == 0) return m_top_score;
return 0.000002;
for (int i = m_prob_break.size(); i <= breaks; ++i)
m_prob_break.push_back(std::pow(m_config.cb, -i));
return m_prob_break[breaks];
} }
void bv_lookahead::try_set(expr* e, bvect const& new_value) { void bv_lookahead::try_set(expr* u, bvect const& new_value) {
if (!wval(e).can_set(new_value)) if (!wval(u).can_set(new_value))
return; return;
auto d = lookahead(e, new_value); auto score = lookahead(u, new_value);
if (d > 0) ++m_stats.m_num_updates;
add_update(d, e, new_value); verbose_stream() << mk_bounded_pp(u, m) << " " << new_value << " score: " << score << "\n";
if (score > m_best_score) {
m_best_score = score;
m_best_expr = u;
m_best_value.set_bw(new_value.bw);
new_value.copy_to(new_value.nw, m_best_value);
}
} }
void bv_lookahead::add_updates(expr* e) { void bv_lookahead::add_updates(expr* u) {
SASSERT(bv.is_bv(e)); SASSERT(bv.is_bv(u));
auto& v = wval(e); auto& v = wval(u);
while (m_v_saved.size() < v.bits().size()) { while (m_v_saved.size() < v.bits().size()) {
m_v_saved.push_back(0); m_v_saved.push_back(0);
m_v_updated.push_back(0); m_v_updated.push_back(0);
m_best_value.push_back(0);
} }
m_v_saved.set_bw(v.bw); m_v_saved.set_bw(v.bw);
m_v_updated.set_bw(v.bw); m_v_updated.set_bw(v.bw);
v.bits().copy_to(v.nw, m_v_saved); v.bits().copy_to(v.nw, m_v_saved);
m_v_saved.copy_to(v.nw, m_v_updated); m_v_saved.copy_to(v.nw, m_v_updated);
// flip a single bit // flip a single bit
for (unsigned i = 0; i < v.bw; ++i) { for (unsigned i = 0; i < v.bw && i <= 32; ++i) {
m_v_updated.set(i, !m_v_updated.get(i)); m_v_updated.set(i, !m_v_updated.get(i));
try_set(e, m_v_updated); try_set(u, m_v_updated);
//verbose_stream() << "flip " << d << " " << m_v_updated << "\n";
m_v_updated.set(i, !m_v_updated.get(i)); m_v_updated.set(i, !m_v_updated.get(i));
} }
if (v.bw > 32) {
unsigned j = ctx.rand(v.bw - 32) + 32;
m_v_updated.set(j, !m_v_updated.get(j));
try_set(u, m_v_updated);
m_v_updated.set(j, !m_v_updated.get(j));
}
if (v.bw <= 1) if (v.bw <= 1)
return; return;
@ -187,47 +328,39 @@ namespace sls {
for (unsigned i = 0; i < v.nw; ++i) for (unsigned i = 0; i < v.nw; ++i)
m_v_updated[i] = ~m_v_updated[i]; m_v_updated[i] = ~m_v_updated[i];
v.clear_overflow_bits(m_v_updated); v.clear_overflow_bits(m_v_updated);
try_set(e, m_v_updated); try_set(u, m_v_updated);
// increment // increment
m_v_saved.copy_to(v.nw, m_v_updated); m_v_saved.copy_to(v.nw, m_v_updated);
v.add1(m_v_updated); v.add1(m_v_updated);
try_set(e, m_v_updated); try_set(u, m_v_updated);
// decrement // decrement
m_v_saved.copy_to(v.nw, m_v_updated); m_v_saved.copy_to(v.nw, m_v_updated);
v.sub1(m_v_updated); v.sub1(m_v_updated);
try_set(e, m_v_updated); try_set(u, m_v_updated);
// random, deffered to failure path // reset to original value
// v.get_variant(m_v_updated, m_ev.m_rand); try_set(u, m_v_saved);
// try_set(e, m_v_updated);
} }
bool bv_lookahead::apply_update() { bool bv_lookahead::apply_update() {
double sum_score = 0; CTRACE("bv", !m_best_expr, tout << "no update\n");
for (unsigned i = 0; i < m_num_updates; ++i) if (!m_best_expr)
sum_score += m_updates[i].score; return false;
double pos = (sum_score * m_ev.m_rand()) / (double)m_ev.m_rand.max_value(); apply_update(m_best_expr, m_best_value);
for (unsigned i = 0; i < m_num_updates; ++i) { return true;
auto const& [e, score, new_value] = m_updates[i];
pos -= score;
if (pos <= 0.00000000001) {
TRACE("sls", tout << "apply " << mk_bounded_pp(e, m) << " new value " << new_value << " " << score << "\n");
apply_update(e, new_value);
return true;
}
}
TRACE("sls", tout << "no update " << m_num_updates << "\n");
return false;
} }
void bv_lookahead::apply_update(expr* e, bvect const& new_value) { void bv_lookahead::apply_update(expr* e, bvect const& new_value) {
TRACE("bv", tout << "apply " << mk_bounded_pp(e, m) << " new value " << new_value << "\n");
SASSERT(bv.is_bv(e)); SASSERT(bv.is_bv(e));
SASSERT(is_uninterp(e)); SASSERT(is_uninterp(e));
SASSERT(m_restore.empty()); SASSERT(m_restore.empty());
wval(e).eval = new_value; wval(e).eval = new_value;
//verbose_stream() << mk_bounded_pp(e, m) << " := " << new_value << "\n";
VERIFY(wval(e).commit_eval()); VERIFY(wval(e).commit_eval());
insert_update_stack(e); insert_update_stack(e);
unsigned max_depth = get_depth(e); unsigned max_depth = get_depth(e);
@ -237,25 +370,25 @@ namespace sls {
if (bv.is_bv(e)) { if (bv.is_bv(e)) {
m_ev.eval(e); // updates wval(e).eval m_ev.eval(e); // updates wval(e).eval
if (!wval(e).commit_eval()) { if (!wval(e).commit_eval()) {
TRACE("sls", tout << "failed to commit " << mk_bounded_pp(e, m) << " " << wval(e) << "\n"); TRACE("bv", tout << "failed to commit " << mk_bounded_pp(e, m) << " " << wval(e) << "\n");
// bv_plugin::is_sat picks up discrepancies // bv_plugin::is_sat picks up discrepancies
continue; continue;
} }
for (auto p : ctx.parents(e)) { for (auto p : ctx.parents(e)) {
insert_update_stack(p); insert_update_stack(p);
max_depth = std::max(max_depth, get_depth(p)); max_depth = std::max(max_depth, get_depth(p));
} }
} }
else if (m.is_bool(e) && m_ev.can_eval1(e)) { else if (m.is_bool(e) && m_ev.can_eval1(e)) {
VERIFY(m_ev.repair_up(e)); rescore(e);
} }
else { else {
UNREACHABLE(); UNREACHABLE();
} }
} }
m_update_stack[depth].reset(); m_update_stack[depth].reset();
} }
m_in_update_stack.reset(); m_in_update_stack.reset();
} }
bool bv_lookahead::insert_update(expr* e) { bool bv_lookahead::insert_update(expr* e) {
@ -273,7 +406,7 @@ namespace sls {
if (!m_in_update_stack.is_marked(e) && is_app(e)) { if (!m_in_update_stack.is_marked(e) && is_app(e)) {
m_in_update_stack.mark(e); m_in_update_stack.mark(e);
m_update_stack[depth].push_back(to_app(e)); m_update_stack[depth].push_back(to_app(e));
} }
} }
void bv_lookahead::restore_lookahead() { void bv_lookahead::restore_lookahead() {
@ -293,8 +426,75 @@ namespace sls {
return m_on_restore.is_marked(e); return m_on_restore.is_marked(e);
} }
unsigned bv_lookahead::get_weight(expr* e) {
return m_bool_info.insert_if_not_there(e, { m_config.paws_init, 0 }).weight;
}
void bv_lookahead::inc_weight(expr* e) {
m_bool_info.insert_if_not_there(e, { m_config.paws_init, 0 }).weight += 1;
}
void bv_lookahead::dec_weight(expr* e) {
auto& w = m_bool_info.insert_if_not_there(e, { m_config.paws_init, 0 }).weight;
w = w > m_config.paws_init ? w - 1 : m_config.paws_init;
}
void bv_lookahead::set_score(app* a, double d) {
m_bool_info.insert_if_not_there(a, { m_config.paws_init, 0 }).score = d;
}
double bv_lookahead::old_score(app* a) {
return m_bool_info.insert_if_not_there(a, { m_config.paws_init, 0 }).score;
}
void bv_lookahead::rescore() {
m_top_score = 0;
m_rescore = false;
for (auto lit : ctx.root_literals()) {
auto e = ctx.atom(lit.var());
if (!e || !is_app(e))
continue;
app* a = to_app(e);
if (!m_ev.can_eval1(a))
continue;
double score = new_score(a);
set_score(a, score);
m_top_score += score;
}
verbose_stream() << "top score " << m_top_score << "\n";
}
void bv_lookahead::rescore(app* e) {
double score = new_score(e);
m_top_score += get_weight(e) * (score - old_score(e));
set_score(e, score);
}
void bv_lookahead::recalibrate_weights() {
for (auto lit : ctx.root_literals()) {
auto e = ctx.atom(lit.var());
if (!e || !is_app(e))
continue;
app* a = to_app(e);
if (!m_ev.can_eval1(a))
continue;
bool is_true = ctx.is_true(lit);
bool is_true_a = m_ev.bval1(a);
if (ctx.rand(10) < m_config.paws_sp) {
if (is_true == is_true_a)
dec_weight(a);
}
else if (is_true != is_true_a)
inc_weight(a);
}
m_best_score = 0;
}
void bv_lookahead::collect_statistics(statistics& st) const { void bv_lookahead::collect_statistics(statistics& st) const {
st.update("sls-bv-lookahead", m_stats.m_num_lookahead); st.update("sls-bv-lookahead", m_stats.m_num_lookahead);
st.update("sls-bv-updates", m_stats.m_num_updates); st.update("sls-bv-updates", m_stats.m_num_updates);
st.update("sls-bv-moves", m_stats.m_moves);
} }
} }

View file

@ -24,21 +24,34 @@ namespace sls {
class bv_eval; class bv_eval;
class bv_lookahead { class bv_lookahead {
struct config { struct config {
double cb = 2.85; double cb = 2.85;
}; unsigned paws_init = 40;
unsigned paws_sp = 52;
struct update { bool paws = true;
expr* e; bool walksat = true;
double score; bool walksat_repick = false;
bvect value; unsigned wp = 100;
unsigned restart_base = 1000;
unsigned restart_next = 1000;
unsigned restart_init = 1000;
bool early_prune = true;
unsigned max_moves = 0;
unsigned max_moves_base = 200;
}; };
struct stats { struct stats {
unsigned m_num_lookahead = 0; unsigned m_num_lookahead = 0;
unsigned m_num_updates = 0; unsigned m_num_updates = 0;
unsigned m_moves = 0;
unsigned m_restarts = 0;
}; };
struct bool_info {
unsigned weight = 0;
double score = 0;
};
bv_util bv; bv_util bv;
bv_eval& m_ev; bv_eval& m_ev;
@ -47,49 +60,56 @@ namespace sls {
config m_config; config m_config;
stats m_stats; stats m_stats;
bvect m_v_saved, m_v_updated; bvect m_v_saved, m_v_updated;
svector<double> m_prob_break;
ptr_vector<expr> m_restore; ptr_vector<expr> m_restore;
vector<ptr_vector<app>> m_update_stack; vector<ptr_vector<app>> m_update_stack;
expr_mark m_on_restore, m_in_update_stack; expr_mark m_on_restore, m_in_update_stack;
vector<update> m_updates; double m_best_score = 0, m_top_score = 0;
unsigned m_num_updates = 0; bvect m_best_value;
expr* m_best_expr = nullptr;
bool m_rescore = true;
ptr_vector<expr> m_vars;
void reset_updates() { m_num_updates = 0; } void init_updates();
void add_update(double score, expr* e, bvect const& value) {
if (m_num_updates == m_updates.size())
m_updates.push_back({ e, score, value });
else {
auto& u = m_updates[m_num_updates];
u.e = e;
u.score = score;
u.value = value;
}
m_num_updates++;
}
bv_valuation& wval(expr* e) const; bv_valuation& wval(expr* e) const;
void insert_update_stack(expr* e); void insert_update_stack(expr* e);
bool insert_update(expr* e); bool insert_update(expr* e);
void restore_lookahead(); void restore_lookahead();
double lookahead(expr* e, bvect const& new_value); double lookahead(expr* u, bvect const& new_value);
double old_score(app* c);
double new_score(app* c);
void set_score(app* c, double d);
void rescore(app* c);
void try_set(expr* e, bvect const& new_value); void rescore();
void add_updates(expr* e);
obj_map<expr, bool_info> m_bool_info;
unsigned get_weight(expr* e);
void inc_weight(expr* e);
void dec_weight(expr* e);
void recalibrate_weights();
void try_set(expr* u, bvect const& new_value);
void add_updates(expr* u);
void apply_update(expr* e, bvect const& new_value); void apply_update(expr* e, bvect const& new_value);
bool apply_update(); bool apply_update();
bool apply_random_update(ptr_vector<expr> const& vars); bool apply_random_update(ptr_vector<expr> const& vars);
bool apply_guided_update(ptr_vector<expr> const& vars);
ptr_vector<expr> const& get_candidate_uninterp();
void display_updates(std::ostream& out); void check_restart();
public: public:
bv_lookahead(bv_eval& ev); bv_lookahead(bv_eval& ev);
bool on_restore(expr* e) const; void updt_params(params_ref const& p);
bool try_repair_down(app* e); lbool search();
void start_propagation() { m_rescore = true; }
bool on_restore(expr* e) const;
void collect_statistics(statistics& st) const; void collect_statistics(statistics& st) const;

View file

@ -50,6 +50,10 @@ namespace sls {
return false; return false;
} }
void bv_plugin::start_propagation() {
m_eval.start_propagation();
}
void bv_plugin::propagate_literal(sat::literal lit) { void bv_plugin::propagate_literal(sat::literal lit) {
SASSERT(ctx.is_true(lit)); SASSERT(ctx.is_true(lit));
auto e = ctx.atom(lit.var()); auto e = ctx.atom(lit.var());

View file

@ -41,6 +41,7 @@ namespace sls {
~bv_plugin() override {} ~bv_plugin() override {}
void register_term(expr* e) override; void register_term(expr* e) override;
expr_ref get_value(expr* e) override; expr_ref get_value(expr* e) override;
void start_propagation() override;
void initialize() override; void initialize() override;
void propagate_literal(sat::literal lit) override; void propagate_literal(sat::literal lit) override;
bool propagate() override; bool propagate() override;

View file

@ -16,6 +16,7 @@ Author:
--*/ --*/
#include "ast/ast_ll_pp.h" #include "ast/ast_ll_pp.h"
#include "ast/ast_pp.h"
#include "ast/sls/sls_bv_terms.h" #include "ast/sls/sls_bv_terms.h"
#include "ast/rewriter/bool_rewriter.h" #include "ast/rewriter/bool_rewriter.h"
#include "ast/rewriter/bv_rewriter.h" #include "ast/rewriter/bv_rewriter.h"
@ -23,15 +24,17 @@ Author:
namespace sls { namespace sls {
bv_terms::bv_terms(sls::context& ctx): bv_terms::bv_terms(sls::context& ctx):
ctx(ctx),
m(ctx.get_manager()), m(ctx.get_manager()),
bv(m), bv(m),
m_axioms(m) {} m_axioms(m) {}
void bv_terms::register_term(expr* e) { void bv_terms::register_term(expr* e) {
auto r = ensure_binary(e); auto r = ensure_binary(e);
if (r != e) if (r != e) {
m_axioms.push_back(m.mk_eq(e, r)); bool_rewriter br(m);
register_uninterp(e); m_axioms.push_back(br.mk_eq_rw(e, r));
}
} }
expr_ref bv_terms::ensure_binary(expr* e) { expr_ref bv_terms::ensure_binary(expr* e) {
@ -69,10 +72,10 @@ namespace sls {
expr_ref absx = br.mk_ite(signx, bvr.mk_bv_neg(x), x); expr_ref absx = br.mk_ite(signx, bvr.mk_bv_neg(x), x);
expr_ref absy = br.mk_ite(signy, bvr.mk_bv_neg(y), y); expr_ref absy = br.mk_ite(signy, bvr.mk_bv_neg(y), y);
expr_ref d = expr_ref(bv.mk_bv_udiv(absx, absy), m); expr_ref d = expr_ref(bv.mk_bv_udiv(absx, absy), m);
expr_ref r = br.mk_ite(br.mk_eq(signx, signy), d, bvr.mk_bv_neg(d)); expr_ref r = br.mk_ite(br.mk_eq_rw(signx, signy), d, bvr.mk_bv_neg(d));
r = br.mk_ite(br.mk_eq(z, y), r = br.mk_ite(br.mk_eq_rw(z, y),
br.mk_ite(signx, o, n1), br.mk_ite(signx, o, n1),
br.mk_ite(br.mk_eq(x, z), z, r)); br.mk_ite(br.mk_eq_rw(x, z), z, r));
return r; return r;
} }
@ -92,8 +95,8 @@ namespace sls {
expr_ref abs_y = br.mk_ite(bvr.mk_sle(z, y), y, bvr.mk_bv_neg(y)); expr_ref abs_y = br.mk_ite(bvr.mk_sle(z, y), y, bvr.mk_bv_neg(y));
expr_ref u = bvr.mk_bv_urem(abs_x, abs_y); expr_ref u = bvr.mk_bv_urem(abs_x, abs_y);
expr_ref r(m); expr_ref r(m);
r = br.mk_ite(br.mk_eq(u, z), z, r = br.mk_ite(br.mk_eq_rw(u, z), z,
br.mk_ite(br.mk_eq(y, z), x, br.mk_ite(br.mk_eq_rw(y, z), x,
br.mk_ite(br.mk_and(bvr.mk_sle(z, x), bvr.mk_sle(z, x)), u, br.mk_ite(br.mk_and(bvr.mk_sle(z, x), bvr.mk_sle(z, x)), u,
br.mk_ite(bvr.mk_sle(z, x), bvr.mk_bv_add(y, u), br.mk_ite(bvr.mk_sle(z, x), bvr.mk_bv_add(y, u),
br.mk_ite(bv.mk_sle(z, y), bvr.mk_bv_sub(y, u), bvr.mk_bv_neg(u)))))); br.mk_ite(bv.mk_sle(z, y), bvr.mk_bv_sub(y, u), bvr.mk_bv_neg(u))))));
@ -107,10 +110,28 @@ namespace sls {
bool_rewriter br(m); bool_rewriter br(m);
bv_rewriter bvr(m); bv_rewriter bvr(m);
expr_ref z(bv.mk_zero(bv.get_bv_size(x)), m); expr_ref z(bv.mk_zero(bv.get_bv_size(x)), m);
r = br.mk_ite(br.mk_eq(y, z), x, bvr.mk_bv_sub(x, bvr.mk_bv_mul(y, mk_sdiv(x, y)))); r = br.mk_ite(br.mk_eq_rw(y, z), x, bvr.mk_bv_sub(x, bvr.mk_bv_mul(y, mk_sdiv(x, y))));
return r; return r;
} }
ptr_vector<expr> const& bv_terms::uninterp_occurs(expr* e) {
unsigned id = e->get_id();
m_uninterp_occurs.reserve(id + 1);
if (!m_uninterp_occurs[id].empty())
return m_uninterp_occurs[id];
register_uninterp(e);
return m_uninterp_occurs[id];
}
ptr_vector<expr> const& bv_terms::condition_occurs(expr* e) {
unsigned id = e->get_id();
m_condition_occurs.reserve(id + 1);
if (!m_condition_occurs[id].empty())
return m_condition_occurs[id];
register_uninterp(e);
return m_condition_occurs[id];
}
void bv_terms::register_uninterp(expr* e) { void bv_terms::register_uninterp(expr* e) {
if (!m.is_bool(e)) if (!m.is_bool(e))
return; return;
@ -123,7 +144,9 @@ namespace sls {
else else
return; return;
m_uninterp_occurs.reserve(e->get_id() + 1); m_uninterp_occurs.reserve(e->get_id() + 1);
m_condition_occurs.reserve(e->get_id() + 1);
auto& occs = m_uninterp_occurs[e->get_id()]; auto& occs = m_uninterp_occurs[e->get_id()];
auto& cond_occs = m_condition_occurs[e->get_id()];
ptr_vector<expr> todo; ptr_vector<expr> todo;
todo.append(to_app(e)->get_num_args(), to_app(e)->get_args()); todo.append(to_app(e)->get_num_args(), to_app(e)->get_args());
expr_mark marked; expr_mark marked;
@ -138,8 +161,11 @@ namespace sls {
todo.push_back(arg); todo.push_back(arg);
} }
else if (m.is_ite(e, c, th, el)) { else if (m.is_ite(e, c, th, el)) {
todo.push_back(th); cond_occs.push_back(c);
todo.push_back(el); if (ctx.is_true(c))
todo.push_back(th);
else
todo.push_back(el);
} }
else if (bv.is_bv(e)) else if (bv.is_bv(e))
occs.push_back(e); occs.push_back(e);

View file

@ -29,10 +29,12 @@ Author:
namespace sls { namespace sls {
class bv_terms { class bv_terms {
context& ctx;
ast_manager& m; ast_manager& m;
bv_util bv; bv_util bv;
expr_ref_vector m_axioms; expr_ref_vector m_axioms;
vector<ptr_vector<expr>> m_uninterp_occurs; vector<ptr_vector<expr>> m_uninterp_occurs;
vector<ptr_vector<expr>> m_condition_occurs;
expr_ref ensure_binary(expr* e); expr_ref ensure_binary(expr* e);
@ -43,12 +45,16 @@ namespace sls {
void register_uninterp(expr* e); void register_uninterp(expr* e);
public: public:
bv_terms(sls::context& ctx); bv_terms(context& ctx);
void register_term(expr* e); void register_term(expr* e);
expr_ref_vector& axioms() { return m_axioms; } expr_ref_vector& axioms() { return m_axioms; }
ptr_vector<expr> const& uninterp_occurs(expr* e) { m_uninterp_occurs.reserve(e->get_id() + 1); return m_uninterp_occurs[e->get_id()]; } ptr_vector<expr> const& uninterp_occurs(expr* e);
ptr_vector<expr> const& condition_occurs(expr* e);
}; };
} }

View file

@ -23,6 +23,7 @@ Notes:
#include "ast/for_each_expr.h" #include "ast/for_each_expr.h"
#include "ast/ast_smt2_pp.h" #include "ast/ast_smt2_pp.h"
#include "ast/bv_decl_plugin.h" #include "ast/bv_decl_plugin.h"
#include "ast/ast_ll_pp.h"
#include "model/model.h" #include "model/model.h"
#include "params/sls_params.hpp" #include "params/sls_params.hpp"
@ -34,23 +35,23 @@ class sls_tracker {
bv_util & m_bv_util; bv_util & m_bv_util;
powers & m_powers; powers & m_powers;
random_gen m_rng; random_gen m_rng;
unsigned m_random_bits; unsigned m_random_bits = 0;
unsigned m_random_bits_cnt; unsigned m_random_bits_cnt = 0;
mpz m_zero, m_one, m_two; mpz m_zero, m_one, m_two;
struct value_score { struct value_score {
value_score() : m(nullptr), value(unsynch_mpz_manager::mk_z(0)), score(0.0), score_prune(0.0), has_pos_occ(0), has_neg_occ(0), distance(0), touched(1) {}; value_score() : value(unsynch_mpz_manager::mk_z(0)) {};
value_score(value_score&&) noexcept = default; value_score(value_score&&) noexcept = default;
~value_score() { if (m) m->del(value); } ~value_score() { if (m) m->del(value); }
value_score& operator=(value_score&&) = default; value_score& operator=(value_score&&) = default;
unsynch_mpz_manager * m; unsynch_mpz_manager * m = nullptr;
mpz value; mpz value;
double score; double score = 0.0;
double score_prune; double score_prune = 0.0;
unsigned has_pos_occ; unsigned has_pos_occ = 0;
unsigned has_neg_occ; unsigned has_neg_occ = 0;
unsigned distance; // max distance from any root unsigned distance = 0; // max distance from any root
unsigned touched; unsigned touched = 1;
}; };
public: public:
@ -67,21 +68,21 @@ private:
ptr_vector<func_decl> m_constants; ptr_vector<func_decl> m_constants;
ptr_vector<func_decl> m_temp_constants; ptr_vector<func_decl> m_temp_constants;
occ_type m_constants_occ; occ_type m_constants_occ;
unsigned m_last_pos; unsigned m_last_pos = 0;
unsigned m_walksat; unsigned m_walksat = 0;
unsigned m_ucb; unsigned m_ucb = 0;
double m_ucb_constant; double m_ucb_constant = 0;
unsigned m_ucb_init; unsigned m_ucb_init = 0;
double m_ucb_forget; double m_ucb_forget = 0;
double m_ucb_noise; double m_ucb_noise = 0;
unsigned m_touched; unsigned m_touched = 0;
double m_scale_unsat; double m_scale_unsat = 0;
unsigned m_paws_init; unsigned m_paws_init = 0;
obj_map<expr, unsigned> m_where_false; obj_map<expr, unsigned> m_where_false;
expr** m_list_false; expr** m_list_false = nullptr;
unsigned m_track_unsat; unsigned m_track_unsat = 0;
obj_map<expr, unsigned> m_weights; obj_map<expr, unsigned> m_weights;
double m_top_sum; double m_top_sum = 0;
obj_hashtable<expr> m_temp_seen; obj_hashtable<expr> m_temp_seen;
public: public:
@ -89,8 +90,7 @@ public:
m_manager(m), m_manager(m),
m_mpz_manager(mm), m_mpz_manager(mm),
m_bv_util(bvu), m_bv_util(bvu),
m_powers(p), m_powers(p),
m_random_bits_cnt(0),
m_zero(m_mpz_manager.mk_z(0)), m_zero(m_mpz_manager.mk_z(0)),
m_one(m_mpz_manager.mk_z(1)), m_one(m_mpz_manager.mk_z(1)),
m_two(m_mpz_manager.mk_z(2)) { m_two(m_mpz_manager.mk_z(2)) {
@ -144,7 +144,7 @@ public:
}*/ }*/
inline void adapt_top_sum(expr * e, double add, double sub) { inline void adapt_top_sum(expr * e, double add, double sub) {
m_top_sum += m_weights.find(e) * (add - sub); m_top_sum += get_weight(e) * (add - sub);
} }
inline void set_top_sum(double new_score) { inline void set_top_sum(double new_score) {
@ -160,12 +160,7 @@ public:
} }
inline bool is_sat() { inline bool is_sat() {
for (obj_hashtable<expr>::iterator it = m_top_expr.begin(); return all_of(m_top_expr, [this](expr* e) { return m_mpz_manager.is_one(get_value(e)); });
it != m_top_expr.end();
it++)
if (!m_mpz_manager.is_one(get_value(*it)))
return false;
return true;
} }
inline void set_value(expr * n, const mpz & r) { inline void set_value(expr * n, const mpz & r) {
@ -290,12 +285,9 @@ public:
} }
// Update uplinks // Update uplinks
unsigned na = n->get_num_args(); for (auto c : *n)
for (unsigned i = 0; i < na; i++) {
expr * c = n->get_arg(i);
m_uplinks.insert_if_not_there(c, ptr_vector<expr>()).push_back(n); m_uplinks.insert_if_not_there(c, ptr_vector<expr>()).push_back(n);
}
func_decl * d = n->get_decl(); func_decl * d = n->get_decl();
if (n->get_num_args() == 0) { if (n->get_num_args() == 0) {
@ -414,8 +406,7 @@ public:
init_proc proc(m_manager, *this); init_proc proc(m_manager, *this);
expr_mark visited; expr_mark visited;
unsigned sz = as.size(); unsigned sz = as.size();
for (unsigned i = 0; i < sz; i++) { for (auto e : as) {
expr * e = as[i];
if (!m_top_expr.contains(e)) if (!m_top_expr.contains(e))
m_top_expr.insert(e); m_top_expr.insert(e);
for_each_expr(proc, visited, e); for_each_expr(proc, visited, e);
@ -423,8 +414,7 @@ public:
visited.reset(); visited.reset();
for (unsigned i = 0; i < sz; i++) { for (auto e : as) {
expr * e = as[i];
ptr_vector<func_decl> t; ptr_vector<func_decl> t;
m_constants_occ.insert_if_not_there(e, t); m_constants_occ.insert_if_not_there(e, t);
find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
@ -447,16 +437,14 @@ public:
} }
m_temp_seen.reset(); m_temp_seen.reset();
for (unsigned i = 0; i < sz; i++) for (auto e : as) {
{
expr * e = as[i];
// initialize weights // initialize weights
if (!m_weights.contains(e)) if (!m_weights.contains(e))
m_weights.insert(e, m_paws_init); m_weights.insert(e, m_paws_init);
// positive/negative occurrences used for early pruning // positive/negative occurrences used for early pruning
setup_occs(as[i]); setup_occs(e);
} }
// initialize ucb total touched value (individual ones are always initialized to 1) // initialize ucb total touched value (individual ones are always initialized to 1)
@ -629,7 +617,7 @@ public:
} }
void randomize(ptr_vector<expr> const & as) { void randomize(ptr_vector<expr> const & as) {
TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); TRACE("sls_verbose", tout << "Abandoned model:" << std::endl; show_model(tout); );
for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
func_decl * fd = it->m_key; func_decl * fd = it->m_key;
@ -643,7 +631,7 @@ public:
} }
void reset(ptr_vector<expr> const & as) { void reset(ptr_vector<expr> const & as) {
TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); TRACE("sls_verbose", tout << "Abandoned model:" << std::endl; show_model(tout); );
for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
set_value(it->m_value, m_zero); set_value(it->m_value, m_zero);
@ -656,11 +644,7 @@ public:
if (m_manager.is_and(n) || m_manager.is_or(n)) if (m_manager.is_and(n) || m_manager.is_or(n))
{ {
SASSERT(!negated); SASSERT(!negated);
app * a = to_app(n); for (auto child : *to_app(n)) {
expr * const * args = a->get_args();
for (unsigned i = 0; i < a->get_num_args(); i++)
{
expr * child = args[i];
if (!m_temp_seen.contains(child)) if (!m_temp_seen.contains(child))
{ {
setup_occs(child, false); setup_occs(child, false);
@ -706,29 +690,22 @@ public:
} }
else if (m_manager.is_and(n)) { else if (m_manager.is_and(n)) {
SASSERT(!negated); SASSERT(!negated);
app * a = to_app(n);
expr * const * args = a->get_args();
/* Andreas: Seems to have no effect. But maybe you want to try it again at some point. /* Andreas: Seems to have no effect. But maybe you want to try it again at some point.
double sum = 0.0; double sum = 0.0;
for (unsigned i = 0; i < a->get_num_args(); i++) for (unsigned i = 0; i < a->get_num_args(); i++)
sum += get_score(args[i]); sum += get_score(args[i]);
res = sum / (double) a->get_num_args(); */ res = sum / (double) a->get_num_args(); */
double min = 1.0; double min = 1.0;
for (unsigned i = 0; i < a->get_num_args(); i++) { for (auto arg : *to_app(n))
double cur = get_score(args[i]); min = std::min(get_score(arg), min);
if (cur < min) min = cur;
}
res = min; res = min;
} }
else if (m_manager.is_or(n)) { else if (m_manager.is_or(n)) {
SASSERT(!negated); SASSERT(!negated);
app * a = to_app(n);
expr * const * args = a->get_args();
double max = 0.0; double max = 0.0;
for (unsigned i = 0; i < a->get_num_args(); i++) { for (auto arg : *to_app(n))
double cur = get_score(args[i]); max = std::max(get_score(arg), max);
if (cur > max) max = cur;
}
res = max; res = max;
} }
else if (m_manager.is_ite(n)) { else if (m_manager.is_ite(n)) {
@ -776,6 +753,7 @@ public:
" ; SZ = " << bv_sz << std::endl; ); " ; SZ = " << bv_sz << std::endl; );
m_mpz_manager.del(diff); m_mpz_manager.del(diff);
m_mpz_manager.del(diff_m1); m_mpz_manager.del(diff_m1);
//verbose_stream() << "hamming distance: " << mk_bounded_pp(n, m_manager) << " := " << res << "\n";
} }
else else
NOT_IMPLEMENTED_YET(); NOT_IMPLEMENTED_YET();
@ -967,39 +945,35 @@ public:
ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as) { ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as) {
unsigned sz = as.size(); unsigned sz = as.size();
if (sz == 1) { if (sz == 1 && m_mpz_manager.neq(get_value(as[0]), m_one))
if (m_mpz_manager.neq(get_value(as[0]), m_one)) return get_constants();
return get_constants();
}
m_temp_constants.reset(); m_temp_constants.reset();
for (unsigned i = 0; i < sz; i++) { for (auto q : as) {
expr * q = as[i];
if (m_mpz_manager.eq(get_value(q), m_one)) if (m_mpz_manager.eq(get_value(q), m_one))
continue; continue;
ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q); ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
unsigned sz2 = this_decls.size(); for (auto fd : this_decls)
for (unsigned j = 0; j < sz2; j++) {
func_decl * fd = this_decls[j];
if (!m_temp_constants.contains(fd)) if (!m_temp_constants.contains(fd))
m_temp_constants.push_back(fd); m_temp_constants.push_back(fd);
}
} }
TRACE("sls", tout << "candidates "; for (auto f : m_temp_constants) tout << f->get_name() << " "; tout << std::endl;);
return m_temp_constants; return m_temp_constants;
} }
ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) { ptr_vector<func_decl>& get_unsat_constants_walksat(expr* e) {
if (!e || !m_temp_constants.empty()) if (!e || !m_temp_constants.empty())
return m_temp_constants;
ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
unsigned sz = this_decls.size();
for (unsigned j = 0; j < sz; j++) {
func_decl * fd = this_decls[j];
if (!m_temp_constants.contains(fd))
m_temp_constants.push_back(fd);
}
return m_temp_constants; return m_temp_constants;
ptr_vector<func_decl> const& this_decls = m_constants_occ.find(e);
for (auto fd : this_decls)
if (!m_temp_constants.contains(fd))
m_temp_constants.push_back(fd);
TRACE("sls", tout << "candidates " << mk_bounded_pp(e, m_manager) << " ";
for (auto f : m_temp_constants) tout << f->get_name() << " "; tout << std::endl;);
return m_temp_constants;
} }
ptr_vector<func_decl> & get_unsat_constants(ptr_vector<expr> const & as) { ptr_vector<func_decl> & get_unsat_constants(ptr_vector<expr> const & as) {

View file

@ -327,7 +327,7 @@ namespace sls {
m_constraint_trail.push_back(e); m_constraint_trail.push_back(e);
add_clause(e); add_clause(e);
m_new_constraint = true; m_new_constraint = true;
verbose_stream() << "add constraint\n"; IF_VERBOSE(3, verbose_stream() << "add constraint " << mk_bounded_pp(e, m) << "\n");
++m_stats.m_num_constraints; ++m_stats.m_num_constraints;
} }