mirror of
https://github.com/Z3Prover/z3
synced 2025-04-07 09:55:19 +00:00
updates to sls
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
111fcb9366
commit
51f1e2655c
|
@ -329,6 +329,7 @@ namespace euf {
|
||||||
m_config.m_context_solve = p.get_bool("context_solve", tp.solve_eqs_context_solve());
|
m_config.m_context_solve = p.get_bool("context_solve", tp.solve_eqs_context_solve());
|
||||||
for (auto* ex : m_extract_plugins)
|
for (auto* ex : m_extract_plugins)
|
||||||
ex->updt_params(p);
|
ex->updt_params(p);
|
||||||
|
m_rewriter.updt_params(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void solve_eqs::collect_param_descrs(param_descrs& r) {
|
void solve_eqs::collect_param_descrs(param_descrs& r) {
|
||||||
|
|
|
@ -25,12 +25,15 @@ Author:
|
||||||
|
|
||||||
namespace bv {
|
namespace bv {
|
||||||
|
|
||||||
sls::sls(ast_manager& m):
|
sls::sls(ast_manager& m, params_ref const& p):
|
||||||
m(m),
|
m(m),
|
||||||
bv(m),
|
bv(m),
|
||||||
m_terms(m),
|
m_terms(m),
|
||||||
m_eval(m)
|
m_eval(m),
|
||||||
{}
|
m_engine(m, p)
|
||||||
|
{
|
||||||
|
updt_params(p);
|
||||||
|
}
|
||||||
|
|
||||||
void sls::init() {
|
void sls::init() {
|
||||||
m_terms.init();
|
m_terms.init();
|
||||||
|
@ -67,20 +70,48 @@ namespace bv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sls::init_repair_candidates() {
|
||||||
|
m_to_repair.reset();
|
||||||
|
ptr_vector<expr> todo;
|
||||||
|
expr_fast_mark1 mark;
|
||||||
|
for (auto index : m_repair_roots)
|
||||||
|
todo.push_back(m_terms.term(index));
|
||||||
|
for (unsigned i = 0; i < todo.size(); ++i) {
|
||||||
|
expr* e = todo[i];
|
||||||
|
if (mark.is_marked(e))
|
||||||
|
continue;
|
||||||
|
mark.mark(e);
|
||||||
|
if (!is_app(e))
|
||||||
|
continue;
|
||||||
|
for (expr* arg : *to_app(e))
|
||||||
|
todo.push_back(arg);
|
||||||
|
|
||||||
|
if (is_uninterp_const(e))
|
||||||
|
m_to_repair.insert(e->get_id());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void sls::reinit_eval() {
|
void sls::reinit_eval() {
|
||||||
|
init_repair_candidates();
|
||||||
|
|
||||||
|
if (m_to_repair.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
std::function<bool(expr*, unsigned)> eval = [&](expr* e, unsigned i) {
|
std::function<bool(expr*, unsigned)> eval = [&](expr* e, unsigned i) {
|
||||||
auto should_keep = [&]() {
|
unsigned id = e->get_id();
|
||||||
return m_rand() % 100 <= 92;
|
bool keep = (m_rand() % 100 <= 50) || !m_to_repair.contains(id);
|
||||||
};
|
if (m.is_bool(e) && (m_eval.is_fixed0(e) || keep))
|
||||||
if (m.is_bool(e)) {
|
return m_eval.bval0(e);
|
||||||
if (m_eval.is_fixed0(e) || should_keep())
|
|
||||||
return m_eval.bval0(e);
|
|
||||||
}
|
|
||||||
else if (bv.is_bv(e)) {
|
else if (bv.is_bv(e)) {
|
||||||
auto& w = m_eval.wval(e);
|
auto& w = m_eval.wval(e);
|
||||||
if (w.fixed.get(i) || should_keep())
|
if (w.fixed.get(i) || keep)
|
||||||
return w.get_bit(i);
|
return w.get_bit(i);
|
||||||
}
|
//auto const& z = m_engine.get_value(e);
|
||||||
|
//return rational(z).get_bit(i);
|
||||||
|
}
|
||||||
|
|
||||||
return m_rand() % 2 == 0;
|
return m_rand() % 2 == 0;
|
||||||
};
|
};
|
||||||
m_eval.init_eval(m_terms.assertions(), eval);
|
m_eval.init_eval(m_terms.assertions(), eval);
|
||||||
|
@ -119,7 +150,7 @@ namespace bv {
|
||||||
return { false, nullptr };
|
return { false, nullptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool sls::search() {
|
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(); ) {
|
||||||
|
@ -127,7 +158,6 @@ namespace bv {
|
||||||
if (!e)
|
if (!e)
|
||||||
return l_true;
|
return l_true;
|
||||||
|
|
||||||
|
|
||||||
trace_repair(down, e);
|
trace_repair(down, e);
|
||||||
|
|
||||||
++m_stats.m_moves;
|
++m_stats.m_moves;
|
||||||
|
@ -140,16 +170,32 @@ namespace bv {
|
||||||
return l_undef;
|
return l_undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lbool sls::search2() {
|
||||||
|
lbool res = l_undef;
|
||||||
|
if (m_stats.m_restarts == 0)
|
||||||
|
res = m_engine();
|
||||||
|
else if (m_stats.m_restarts % 1000 == 0)
|
||||||
|
res = m_engine.search_loop();
|
||||||
|
if (res != l_undef)
|
||||||
|
m_engine_model = true;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
lbool sls::operator()() {
|
lbool sls::operator()() {
|
||||||
lbool res = l_undef;
|
lbool res = l_undef;
|
||||||
m_stats.reset();
|
m_stats.reset();
|
||||||
m_stats.m_restarts = 0;
|
m_stats.m_restarts = 0;
|
||||||
|
m_engine_model = false;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
res = search();
|
res = search1();
|
||||||
if (res != l_undef)
|
if (res != l_undef)
|
||||||
break;
|
break;
|
||||||
trace();
|
trace();
|
||||||
|
res = search2();
|
||||||
|
if (res != l_undef)
|
||||||
|
break;
|
||||||
reinit_eval();
|
reinit_eval();
|
||||||
}
|
}
|
||||||
while (m.inc() && m_stats.m_restarts++ < m_config.m_max_restarts);
|
while (m.inc() && m_stats.m_restarts++ < m_config.m_max_restarts);
|
||||||
|
@ -158,34 +204,60 @@ 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))
|
if (m.is_bool(e)) {
|
||||||
m_eval.set(e, m_eval.bval1(e));
|
m_eval.set(e, m_eval.bval1(e));
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
VERIFY(m_eval.wval(e).commit_eval());
|
VERIFY(m_eval.wval(e).commit_eval());
|
||||||
|
}
|
||||||
|
|
||||||
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());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned s = m_rand(n);
|
if (n == 2) {
|
||||||
for (unsigned i = 0; i < n; ++i) {
|
auto d1 = get_depth(e->get_arg(0));
|
||||||
auto j = (i + s) % n;
|
auto d2 = get_depth(e->get_arg(1));
|
||||||
if (m_eval.try_repair(e, j)) {
|
unsigned s = m_rand(d1 + d2 + 2);
|
||||||
set_repair_down(e->get_arg(j));
|
if (s <= d1 && m_eval.try_repair(e, 0)) {
|
||||||
|
set_repair_down(e->get_arg(0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_eval.try_repair(e, 1)) {
|
||||||
|
set_repair_down(e->get_arg(1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_eval.try_repair(e, 0)) {
|
||||||
|
set_repair_down(e->get_arg(0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// search a new root / random walk to repair
|
else {
|
||||||
|
unsigned s = m_rand(n);
|
||||||
|
for (unsigned i = 0; i < n; ++i) {
|
||||||
|
auto j = (i + s) % n;
|
||||||
|
if (m_eval.try_repair(e, j)) {
|
||||||
|
set_repair_down(e->get_arg(j));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// repair was not successful, so reset the state to find a different way to repair
|
||||||
|
init_repair();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sls::try_repair_up(app* e) {
|
void sls::try_repair_up(app* e) {
|
||||||
|
|
||||||
if (m_terms.is_assertion(e) || !m_eval.repair_up(e))
|
if (m_terms.is_assertion(e))
|
||||||
m_repair_roots.insert(e->get_id());
|
m_repair_roots.insert(e->get_id());
|
||||||
|
else if (!m_eval.repair_up(e)) {
|
||||||
|
//m_repair_roots.insert(e->get_id());
|
||||||
|
init_repair();
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (!eval_is_correct(e)) {
|
if (!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";
|
||||||
|
@ -224,7 +296,10 @@ namespace bv {
|
||||||
}
|
}
|
||||||
|
|
||||||
model_ref sls::get_model() {
|
model_ref sls::get_model() {
|
||||||
model_ref mdl = alloc(model, m);
|
if (m_engine_model)
|
||||||
|
return m_engine.get_model();
|
||||||
|
|
||||||
|
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 (!re_eval_is_correct(to_app(e))) {
|
||||||
|
@ -273,7 +348,12 @@ namespace bv {
|
||||||
void sls::updt_params(params_ref const& _p) {
|
void sls::updt_params(params_ref const& _p) {
|
||||||
sls_params p(_p);
|
sls_params p(_p);
|
||||||
m_config.m_max_restarts = p.max_restarts();
|
m_config.m_max_restarts = p.max_restarts();
|
||||||
|
m_config.m_max_repairs = p.max_repairs();
|
||||||
m_rand.set_seed(p.random_seed());
|
m_rand.set_seed(p.random_seed());
|
||||||
|
m_terms.updt_params(_p);
|
||||||
|
params_ref q = _p;
|
||||||
|
q.set_uint("max_restarts", 10);
|
||||||
|
m_engine.updt_params(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sls::trace_repair(bool down, expr* e) {
|
void sls::trace_repair(bool down, expr* e) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ Author:
|
||||||
#include "ast/sls/sls_valuation.h"
|
#include "ast/sls/sls_valuation.h"
|
||||||
#include "ast/sls/bv_sls_terms.h"
|
#include "ast/sls/bv_sls_terms.h"
|
||||||
#include "ast/sls/bv_sls_eval.h"
|
#include "ast/sls/bv_sls_eval.h"
|
||||||
|
#include "ast/sls/sls_engine.h"
|
||||||
#include "ast/bv_decl_plugin.h"
|
#include "ast/bv_decl_plugin.h"
|
||||||
#include "model/model.h"
|
#include "model/model.h"
|
||||||
|
|
||||||
|
@ -49,6 +50,8 @@ namespace bv {
|
||||||
ptr_vector<expr> m_todo;
|
ptr_vector<expr> m_todo;
|
||||||
random_gen m_rand;
|
random_gen m_rand;
|
||||||
config m_config;
|
config m_config;
|
||||||
|
sls_engine m_engine;
|
||||||
|
bool m_engine_model = false;
|
||||||
|
|
||||||
std::pair<bool, app*> next_to_repair();
|
std::pair<bool, app*> next_to_repair();
|
||||||
|
|
||||||
|
@ -59,19 +62,23 @@ namespace bv {
|
||||||
void try_repair_up(app* e);
|
void try_repair_up(app* e);
|
||||||
void set_repair_down(expr* e) { m_repair_down = e->get_id(); }
|
void set_repair_down(expr* e) { m_repair_down = e->get_id(); }
|
||||||
|
|
||||||
lbool search();
|
lbool search1();
|
||||||
|
lbool search2();
|
||||||
void reinit_eval();
|
void reinit_eval();
|
||||||
void init_repair();
|
void init_repair();
|
||||||
void trace();
|
void trace();
|
||||||
void trace_repair(bool down, expr* e);
|
void trace_repair(bool down, expr* e);
|
||||||
|
|
||||||
|
indexed_uint_set m_to_repair;
|
||||||
|
void init_repair_candidates();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sls(ast_manager& m);
|
sls(ast_manager& m, params_ref const& p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add constraints
|
* Add constraints
|
||||||
*/
|
*/
|
||||||
void assert_expr(expr* e) { m_terms.assert_expr(e); }
|
void assert_expr(expr* e) { m_terms.assert_expr(e); m_engine.assert_expr(e); }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invoke init after all expressions are asserted.
|
* Invoke init after all expressions are asserted.
|
||||||
|
@ -91,10 +98,10 @@ namespace bv {
|
||||||
lbool operator()();
|
lbool operator()();
|
||||||
|
|
||||||
void updt_params(params_ref const& p);
|
void updt_params(params_ref const& p);
|
||||||
void collect_statistics(statistics & st) const { m_stats.collect_statistics(st); }
|
void collect_statistics(statistics& st) const { m_stats.collect_statistics(st); m_engine.collect_statistics(st); }
|
||||||
void reset_statistics() { m_stats.reset(); }
|
void reset_statistics() { m_stats.reset(); m_engine.reset_statistics(); }
|
||||||
|
|
||||||
sls_stats const& get_stats() const { return m_stats; }
|
unsigned get_num_moves() { return m_stats.m_moves + m_engine.get_stats().m_moves; }
|
||||||
|
|
||||||
std::ostream& display(std::ostream& out);
|
std::ostream& display(std::ostream& out);
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,8 @@ namespace bv {
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void sls_eval::init_eval(expr_ref_vector const& es, std::function<bool(expr*, unsigned)> const& eval) {
|
void sls_eval::init_eval(expr_ref_vector const& es, std::function<bool(expr*, unsigned)> const& eval) {
|
||||||
sort_assertions(es);
|
auto& terms = sort_assertions(es);
|
||||||
for (expr* e : m_todo) {
|
for (expr* e : terms) {
|
||||||
if (!is_app(e))
|
if (!is_app(e))
|
||||||
continue;
|
continue;
|
||||||
app* a = to_app(e);
|
app* a = to_app(e);
|
||||||
|
@ -49,7 +49,7 @@ namespace bv {
|
||||||
TRACE("sls", tout << "Unhandled expression " << mk_pp(e, m) << "\n");
|
TRACE("sls", tout << "Unhandled expression " << mk_pp(e, m) << "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_todo.reset();
|
terms.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1698,7 +1698,7 @@ namespace bv {
|
||||||
}
|
}
|
||||||
if (bv.is_bv(e)) {
|
if (bv.is_bv(e)) {
|
||||||
auto& v = eval(to_app(e));
|
auto& v = eval(to_app(e));
|
||||||
// verbose_stream() << "committing: " << v << "\n";
|
|
||||||
for (unsigned i = 0; i < v.nw; ++i)
|
for (unsigned i = 0; i < v.nw; ++i)
|
||||||
if (0 != (v.fixed[i] & (v.bits()[i] ^ v.eval[i]))) {
|
if (0 != (v.fixed[i] & (v.bits()[i] ^ v.eval[i]))) {
|
||||||
v.bits().copy_to(v.nw, v.eval);
|
v.bits().copy_to(v.nw, v.eval);
|
||||||
|
|
|
@ -108,6 +108,13 @@ namespace bv {
|
||||||
else if (bv.is_numeral(t, a))
|
else if (bv.is_numeral(t, a))
|
||||||
init_range(s, -a, nullptr, rational(0), false);
|
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);
|
||||||
|
}
|
||||||
else if (bv.is_bit2bool(e, s, idx)) {
|
else if (bv.is_bit2bool(e, s, idx)) {
|
||||||
auto& val = wval(s);
|
auto& val = wval(s);
|
||||||
val.try_set_bit(idx, !sign);
|
val.try_set_bit(idx, !sign);
|
||||||
|
@ -157,7 +164,6 @@ namespace bv {
|
||||||
else
|
else
|
||||||
v.add_range(-b, -a);
|
v.add_range(-b, -a);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sls_fixed::get_offset(expr* e, expr*& x, rational& offset) {
|
void sls_fixed::get_offset(expr* e, expr*& x, rational& offset) {
|
||||||
|
|
|
@ -20,12 +20,14 @@ Author:
|
||||||
|
|
||||||
#include "ast/ast_ll_pp.h"
|
#include "ast/ast_ll_pp.h"
|
||||||
#include "ast/sls/bv_sls.h"
|
#include "ast/sls/bv_sls.h"
|
||||||
|
#include "ast/rewriter/th_rewriter.h"
|
||||||
|
|
||||||
namespace bv {
|
namespace bv {
|
||||||
|
|
||||||
sls_terms::sls_terms(ast_manager& m):
|
sls_terms::sls_terms(ast_manager& m):
|
||||||
m(m),
|
m(m),
|
||||||
bv(m),
|
bv(m),
|
||||||
|
m_rewriter(m),
|
||||||
m_assertions(m),
|
m_assertions(m),
|
||||||
m_pinned(m),
|
m_pinned(m),
|
||||||
m_translated(m),
|
m_translated(m),
|
||||||
|
@ -40,18 +42,20 @@ namespace bv {
|
||||||
expr* top = e;
|
expr* top = e;
|
||||||
m_pinned.push_back(e);
|
m_pinned.push_back(e);
|
||||||
m_todo.push_back(e);
|
m_todo.push_back(e);
|
||||||
expr_fast_mark1 mark;
|
{
|
||||||
for (unsigned i = 0; i < m_todo.size(); ++i) {
|
expr_fast_mark1 mark;
|
||||||
expr* e = m_todo[i];
|
for (unsigned i = 0; i < m_todo.size(); ++i) {
|
||||||
if (!is_app(e))
|
expr* e = m_todo[i];
|
||||||
continue;
|
if (!is_app(e))
|
||||||
if (m_translated.get(e->get_id(), nullptr))
|
continue;
|
||||||
continue;
|
if (m_translated.get(e->get_id(), nullptr))
|
||||||
if (mark.is_marked(e))
|
continue;
|
||||||
continue;
|
if (mark.is_marked(e))
|
||||||
mark.mark(e);
|
continue;
|
||||||
for (auto arg : *to_app(e))
|
mark.mark(e);
|
||||||
m_todo.push_back(arg);
|
for (auto arg : *to_app(e))
|
||||||
|
m_todo.push_back(arg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
std::stable_sort(m_todo.begin(), m_todo.end(), [&](expr* a, expr* b) { return get_depth(a) < get_depth(b); });
|
std::stable_sort(m_todo.begin(), m_todo.end(), [&](expr* a, expr* b) { return get_depth(a) < get_depth(b); });
|
||||||
for (expr* e : m_todo)
|
for (expr* e : m_todo)
|
||||||
|
@ -127,7 +131,7 @@ namespace bv {
|
||||||
m_translated.setx(e->get_id(), r);
|
m_translated.setx(e->get_id(), r);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr* sls_terms::mk_sdiv(expr* x, expr* y) {
|
expr_ref sls_terms::mk_sdiv(expr* x, expr* y) {
|
||||||
// d = udiv(abs(x), abs(y))
|
// d = udiv(abs(x), abs(y))
|
||||||
// y = 0, x >= 0 -> -1
|
// y = 0, x >= 0 -> -1
|
||||||
// y = 0, x < 0 -> 1
|
// y = 0, x < 0 -> 1
|
||||||
|
@ -141,17 +145,18 @@ namespace bv {
|
||||||
expr_ref z(bv.mk_zero(sz), m);
|
expr_ref z(bv.mk_zero(sz), m);
|
||||||
expr* signx = bv.mk_ule(bv.mk_numeral(N / 2, sz), x);
|
expr* signx = bv.mk_ule(bv.mk_numeral(N / 2, sz), x);
|
||||||
expr* signy = bv.mk_ule(bv.mk_numeral(N / 2, sz), y);
|
expr* signy = bv.mk_ule(bv.mk_numeral(N / 2, sz), y);
|
||||||
expr* absx = m.mk_ite(signx, bv.mk_bv_sub(bv.mk_numeral(N - 1, sz), x), x);
|
expr* absx = m.mk_ite(signx, bv.mk_bv_neg(x), x);
|
||||||
expr* absy = m.mk_ite(signy, bv.mk_bv_sub(bv.mk_numeral(N - 1, sz), y), y);
|
expr* absy = m.mk_ite(signy, bv.mk_bv_neg(y), y);
|
||||||
expr* d = bv.mk_bv_udiv(absx, absy);
|
expr* d = bv.mk_bv_udiv(absx, absy);
|
||||||
expr* r = m.mk_ite(m.mk_eq(signx, signy), d, bv.mk_bv_neg(d));
|
expr_ref r(m.mk_ite(m.mk_eq(signx, signy), d, bv.mk_bv_neg(d)), m);
|
||||||
r = m.mk_ite(m.mk_eq(z, y),
|
r = m.mk_ite(m.mk_eq(z, y),
|
||||||
m.mk_ite(signx, bv.mk_one(sz), bv.mk_numeral(N - 1, sz)),
|
m.mk_ite(signx, bv.mk_one(sz), bv.mk_numeral(N - 1, sz)),
|
||||||
m.mk_ite(m.mk_eq(x, z), z, r));
|
m.mk_ite(m.mk_eq(x, z), z, r));
|
||||||
|
m_rewriter(r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
expr* sls_terms::mk_smod(expr* x, expr* y) {
|
expr_ref sls_terms::mk_smod(expr* x, expr* y) {
|
||||||
// u := umod(abs(x), abs(y))
|
// u := umod(abs(x), abs(y))
|
||||||
// u = 0 -> 0
|
// u = 0 -> 0
|
||||||
// y = 0 -> x
|
// y = 0 -> x
|
||||||
|
@ -164,21 +169,24 @@ namespace bv {
|
||||||
expr_ref abs_x(m.mk_ite(bv.mk_sle(z, x), x, bv.mk_bv_neg(x)), m);
|
expr_ref abs_x(m.mk_ite(bv.mk_sle(z, x), x, bv.mk_bv_neg(x)), m);
|
||||||
expr_ref abs_y(m.mk_ite(bv.mk_sle(z, y), y, bv.mk_bv_neg(y)), m);
|
expr_ref abs_y(m.mk_ite(bv.mk_sle(z, y), y, bv.mk_bv_neg(y)), m);
|
||||||
expr_ref u(bv.mk_bv_urem(abs_x, abs_y), m);
|
expr_ref u(bv.mk_bv_urem(abs_x, abs_y), m);
|
||||||
return
|
expr_ref r(m);
|
||||||
m.mk_ite(m.mk_eq(u, z), z,
|
r = m.mk_ite(m.mk_eq(u, z), z,
|
||||||
m.mk_ite(m.mk_eq(y, z), x,
|
m.mk_ite(m.mk_eq(y, z), x,
|
||||||
m.mk_ite(m.mk_and(bv.mk_sle(z, x), bv.mk_sle(z, x)), u,
|
m.mk_ite(m.mk_and(bv.mk_sle(z, x), bv.mk_sle(z, x)), u,
|
||||||
m.mk_ite(bv.mk_sle(z, x), bv.mk_bv_add(y, u),
|
m.mk_ite(bv.mk_sle(z, x), bv.mk_bv_add(y, u),
|
||||||
m.mk_ite(bv.mk_sle(z, y), bv.mk_bv_sub(y, u), bv.mk_bv_neg(u))))));
|
m.mk_ite(bv.mk_sle(z, y), bv.mk_bv_sub(y, u), bv.mk_bv_neg(u))))));
|
||||||
|
m_rewriter(r);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
expr* sls_terms::mk_srem(expr* x, expr* y) {
|
expr_ref sls_terms::mk_srem(expr* x, expr* y) {
|
||||||
// y = 0 -> x
|
// y = 0 -> x
|
||||||
// else x - sdiv(x, y) * y
|
// else x - sdiv(x, y) * y
|
||||||
return
|
expr_ref r(m);
|
||||||
m.mk_ite(m.mk_eq(y, bv.mk_zero(bv.get_bv_size(x))),
|
r = m.mk_ite(m.mk_eq(y, bv.mk_zero(bv.get_bv_size(x))),
|
||||||
x, bv.mk_bv_sub(x, bv.mk_bv_mul(y, mk_sdiv(x, y))));
|
x, bv.mk_bv_sub(x, bv.mk_bv_mul(y, mk_sdiv(x, y))));
|
||||||
|
m_rewriter(r);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,4 +217,11 @@ namespace bv {
|
||||||
m_assertion_set.insert(a->get_id());
|
m_assertion_set.insert(a->get_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sls_terms::updt_params(params_ref const& p) {
|
||||||
|
params_ref q = p;
|
||||||
|
q.set_bool("flat", false);
|
||||||
|
m_rewriter.updt_params(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ Author:
|
||||||
#include "util/scoped_ptr_vector.h"
|
#include "util/scoped_ptr_vector.h"
|
||||||
#include "util/uint_set.h"
|
#include "util/uint_set.h"
|
||||||
#include "ast/ast.h"
|
#include "ast/ast.h"
|
||||||
|
#include "ast/rewriter/th_rewriter.h"
|
||||||
#include "ast/sls/sls_stats.h"
|
#include "ast/sls/sls_stats.h"
|
||||||
#include "ast/sls/sls_powers.h"
|
#include "ast/sls/sls_powers.h"
|
||||||
#include "ast/sls/sls_valuation.h"
|
#include "ast/sls/sls_valuation.h"
|
||||||
|
@ -31,6 +32,7 @@ namespace bv {
|
||||||
class sls_terms {
|
class sls_terms {
|
||||||
ast_manager& m;
|
ast_manager& m;
|
||||||
bv_util bv;
|
bv_util bv;
|
||||||
|
th_rewriter m_rewriter;
|
||||||
ptr_vector<expr> m_todo, m_args;
|
ptr_vector<expr> m_todo, m_args;
|
||||||
expr_ref_vector m_assertions, m_pinned, m_translated;
|
expr_ref_vector m_assertions, m_pinned, m_translated;
|
||||||
app_ref_vector m_terms;
|
app_ref_vector m_terms;
|
||||||
|
@ -40,12 +42,14 @@ namespace bv {
|
||||||
expr* ensure_binary(expr* e);
|
expr* ensure_binary(expr* e);
|
||||||
void ensure_binary_core(expr* e);
|
void ensure_binary_core(expr* e);
|
||||||
|
|
||||||
expr* mk_sdiv(expr* x, expr* y);
|
expr_ref mk_sdiv(expr* x, expr* y);
|
||||||
expr* mk_smod(expr* x, expr* y);
|
expr_ref mk_smod(expr* x, expr* y);
|
||||||
expr* mk_srem(expr* x, expr* y);
|
expr_ref mk_srem(expr* x, expr* y);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sls_terms(ast_manager& m);
|
sls_terms(ast_manager& m);
|
||||||
|
|
||||||
|
void updt_params(params_ref const& p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add constraints
|
* Add constraints
|
||||||
|
|
|
@ -421,6 +421,7 @@ lbool sls_engine::search() {
|
||||||
|
|
||||||
// get candidate variables
|
// get candidate variables
|
||||||
ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
|
ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
|
||||||
|
|
||||||
if (to_evaluate.empty())
|
if (to_evaluate.empty())
|
||||||
{
|
{
|
||||||
res = l_true;
|
res = l_true;
|
||||||
|
@ -514,6 +515,12 @@ lbool sls_engine::operator()() {
|
||||||
if (m_restart_init)
|
if (m_restart_init)
|
||||||
m_tracker.randomize(m_assertions);
|
m_tracker.randomize(m_assertions);
|
||||||
|
|
||||||
|
return search_loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lbool sls_engine::search_loop() {
|
||||||
|
|
||||||
lbool res = l_undef;
|
lbool res = l_undef;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -533,7 +540,6 @@ lbool sls_engine::operator()() {
|
||||||
} while (res != l_true && m_stats.m_restarts++ < m_max_restarts);
|
} while (res != l_true && m_stats.m_restarts++ < m_max_restarts);
|
||||||
|
|
||||||
verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
|
verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,11 @@ public:
|
||||||
void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
|
void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
|
||||||
void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);
|
void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);
|
||||||
|
|
||||||
lbool search();
|
|
||||||
|
|
||||||
|
lbool search();
|
||||||
|
|
||||||
|
lbool search_loop();
|
||||||
|
|
||||||
lbool operator()();
|
lbool operator()();
|
||||||
|
|
||||||
|
|
|
@ -106,10 +106,12 @@ namespace bv {
|
||||||
|
|
||||||
bool sls_valuation::commit_eval() {
|
bool sls_valuation::commit_eval() {
|
||||||
for (unsigned i = 0; i < nw; ++i)
|
for (unsigned i = 0; i < nw; ++i)
|
||||||
if (0 != (fixed[i] & (m_bits[i] ^ eval[i])))
|
if (0 != (fixed[i] & (m_bits[i] ^ eval[i])))
|
||||||
return false;
|
return false;
|
||||||
if (!in_range(eval))
|
|
||||||
|
if (!in_range(eval))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (unsigned i = 0; i < nw; ++i)
|
for (unsigned i = 0; i < nw; ++i)
|
||||||
m_bits[i] = eval[i];
|
m_bits[i] = eval[i];
|
||||||
SASSERT(well_formed());
|
SASSERT(well_formed());
|
||||||
|
@ -491,8 +493,8 @@ namespace bv {
|
||||||
SASSERT(well_formed());
|
SASSERT(well_formed());
|
||||||
}
|
}
|
||||||
|
|
||||||
void sls_valuation::add_range(rational l, rational h) {
|
void sls_valuation::add_range(rational l, rational h) {
|
||||||
|
|
||||||
l = mod(l, rational::power_of_two(bw));
|
l = mod(l, rational::power_of_two(bw));
|
||||||
h = mod(h, rational::power_of_two(bw));
|
h = mod(h, rational::power_of_two(bw));
|
||||||
if (h == l)
|
if (h == l)
|
||||||
|
@ -509,21 +511,28 @@ namespace bv {
|
||||||
auto old_lo = lo();
|
auto old_lo = lo();
|
||||||
auto old_hi = hi();
|
auto old_hi = hi();
|
||||||
if (old_lo < old_hi) {
|
if (old_lo < old_hi) {
|
||||||
if (old_lo < l && l < old_hi)
|
if (old_lo < l && l < old_hi && old_hi <= h)
|
||||||
set_value(m_lo, l),
|
set_value(m_lo, l),
|
||||||
old_lo = l;
|
old_lo = l;
|
||||||
if (old_hi < h && h < old_hi)
|
if (l <= old_lo && old_lo < h && h < old_hi)
|
||||||
set_value(m_hi, h);
|
set_value(m_hi, h);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SASSERT(old_hi < old_lo);
|
SASSERT(old_hi < old_lo);
|
||||||
if (old_lo < l || l < old_hi)
|
if (h <= old_hi && old_lo <= l) {
|
||||||
set_value(m_lo, l),
|
set_value(m_lo, l);
|
||||||
old_lo = l;
|
|
||||||
if (old_lo < h && h < old_hi)
|
|
||||||
set_value(m_hi, h);
|
set_value(m_hi, h);
|
||||||
else if (old_hi < old_lo && (h < old_hi || old_lo < h))
|
}
|
||||||
|
else if (old_lo <= l && l <= h) {
|
||||||
|
set_value(m_lo, l);
|
||||||
set_value(m_hi, h);
|
set_value(m_hi, h);
|
||||||
|
}
|
||||||
|
else if (old_lo + 1 == l) {
|
||||||
|
set_value(m_lo, l);
|
||||||
|
}
|
||||||
|
else if (old_hi == h + 1) {
|
||||||
|
set_value(m_hi, h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,8 +561,7 @@ namespace bv {
|
||||||
// lo < hi, set most significant bits based on hi
|
// lo < hi, set most significant bits based on hi
|
||||||
//
|
//
|
||||||
void sls_valuation::tighten_range() {
|
void sls_valuation::tighten_range() {
|
||||||
|
|
||||||
// verbose_stream() << "tighten " << *this << "\n";
|
|
||||||
if (m_lo == m_hi)
|
if (m_lo == m_hi)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -613,6 +621,9 @@ namespace bv {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (has_range() && !in_range(m_bits))
|
||||||
|
m_bits = m_lo;
|
||||||
|
|
||||||
SASSERT(well_formed());
|
SASSERT(well_formed());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ def_module_params('sls',
|
||||||
description='Experimental Stochastic Local Search Solver (for QFBV only).',
|
description='Experimental Stochastic Local Search Solver (for QFBV only).',
|
||||||
params=(max_memory_param(),
|
params=(max_memory_param(),
|
||||||
('max_restarts', UINT, UINT_MAX, 'maximum number of restarts'),
|
('max_restarts', UINT, UINT_MAX, 'maximum number of restarts'),
|
||||||
|
('max_repairs', UINT, 1000, 'maximum number of repairs before restart'),
|
||||||
('walksat', BOOL, 1, 'use walksat assertion selection (instead of gsat)'),
|
('walksat', BOOL, 1, 'use walksat assertion selection (instead of gsat)'),
|
||||||
('walksat_ucb', BOOL, 1, 'use bandit heuristic for walksat assertion selection (instead of random)'),
|
('walksat_ucb', BOOL, 1, 'use bandit heuristic for walksat assertion selection (instead of random)'),
|
||||||
('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'),
|
('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'),
|
||||||
|
|
|
@ -61,9 +61,10 @@ namespace sls {
|
||||||
m_m = alloc(ast_manager, m);
|
m_m = alloc(ast_manager, m);
|
||||||
ast_translation tr(m, *m_m);
|
ast_translation tr(m, *m_m);
|
||||||
|
|
||||||
|
params_ref p;
|
||||||
m_completed = false;
|
m_completed = false;
|
||||||
m_result = l_undef;
|
m_result = l_undef;
|
||||||
m_bvsls = alloc(bv::sls, *m_m);
|
m_bvsls = alloc(bv::sls, *m_m, p);
|
||||||
// walk clauses, add them
|
// walk clauses, add them
|
||||||
// walk trail stack until search level, add units
|
// walk trail stack until search level, add units
|
||||||
// encapsulate bvsls within the arguments of run-local-search.
|
// encapsulate bvsls within the arguments of run-local-search.
|
||||||
|
|
|
@ -134,7 +134,7 @@ public:
|
||||||
bv_sls_tactic(ast_manager& _m, params_ref const& p) :
|
bv_sls_tactic(ast_manager& _m, params_ref const& p) :
|
||||||
m(_m),
|
m(_m),
|
||||||
m_params(p) {
|
m_params(p) {
|
||||||
m_sls = alloc(bv::sls, m);
|
m_sls = alloc(bv::sls, m, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
tactic* translate(ast_manager& m) override {
|
tactic* translate(ast_manager& m) override {
|
||||||
|
@ -172,12 +172,12 @@ public:
|
||||||
m_sls->init_eval(false_eval);
|
m_sls->init_eval(false_eval);
|
||||||
|
|
||||||
lbool res = m_sls->operator()();
|
lbool res = m_sls->operator()();
|
||||||
auto const& stats = m_sls->get_stats();
|
|
||||||
report_tactic_progress("Number of flips:", stats.m_moves);
|
|
||||||
IF_VERBOSE(20, verbose_stream() << res << "\n");
|
|
||||||
IF_VERBOSE(20, m_sls->display(verbose_stream()));
|
|
||||||
m_st.reset();
|
m_st.reset();
|
||||||
m_sls->collect_statistics(m_st);
|
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 (res == l_true) {
|
if (res == l_true) {
|
||||||
if (g->models_enabled()) {
|
if (g->models_enabled()) {
|
||||||
model_ref mdl = m_sls->get_model();
|
model_ref mdl = m_sls->get_model();
|
||||||
|
@ -207,7 +207,7 @@ public:
|
||||||
|
|
||||||
void cleanup() override {
|
void cleanup() override {
|
||||||
|
|
||||||
auto* d = alloc(bv::sls, m);
|
auto* d = alloc(bv::sls, m, m_params);
|
||||||
std::swap(d, m_sls);
|
std::swap(d, m_sls);
|
||||||
dealloc(d);
|
dealloc(d);
|
||||||
}
|
}
|
||||||
|
@ -235,12 +235,6 @@ tactic* mk_bv_sls_tactic(ast_manager& m, params_ref const& p) {
|
||||||
|
|
||||||
|
|
||||||
static tactic * mk_preamble(ast_manager & m, params_ref const & p) {
|
static tactic * mk_preamble(ast_manager & m, params_ref const & p) {
|
||||||
params_ref main_p;
|
|
||||||
main_p.set_bool("elim_and", true);
|
|
||||||
// main_p.set_bool("pull_cheap_ite", true);
|
|
||||||
main_p.set_bool("push_ite_bv", true);
|
|
||||||
main_p.set_bool("blast_distinct", true);
|
|
||||||
main_p.set_bool("hi_div0", true);
|
|
||||||
|
|
||||||
params_ref simp2_p = p;
|
params_ref simp2_p = p;
|
||||||
simp2_p.set_bool("som", true);
|
simp2_p.set_bool("som", true);
|
||||||
|
@ -249,18 +243,15 @@ static tactic * mk_preamble(ast_manager & m, params_ref const & p) {
|
||||||
simp2_p.set_bool("local_ctx", true);
|
simp2_p.set_bool("local_ctx", true);
|
||||||
simp2_p.set_uint("local_ctx_limit", 10000000);
|
simp2_p.set_uint("local_ctx_limit", 10000000);
|
||||||
|
|
||||||
params_ref hoist_p;
|
params_ref hoist_p = p;
|
||||||
hoist_p.set_bool("hoist_mul", true);
|
hoist_p.set_bool("hoist_mul", true);
|
||||||
hoist_p.set_bool("som", false);
|
hoist_p.set_bool("som", false);
|
||||||
|
|
||||||
params_ref gaussian_p;
|
params_ref gaussian_p = p;
|
||||||
// conservative gaussian elimination.
|
// conservative gaussian elimination.
|
||||||
gaussian_p.set_uint("gaussian_max_occs", 2);
|
gaussian_p.set_uint("gaussian_max_occs", 2);
|
||||||
|
|
||||||
params_ref ctx_p;
|
return and_then(and_then(mk_simplify_tactic(m, p),
|
||||||
ctx_p.set_uint("max_depth", 32);
|
|
||||||
ctx_p.set_uint("max_steps", 5000000);
|
|
||||||
return and_then(and_then(mk_simplify_tactic(m),
|
|
||||||
mk_propagate_values_tactic(m),
|
mk_propagate_values_tactic(m),
|
||||||
using_params(mk_solve_eqs_tactic(m), gaussian_p),
|
using_params(mk_solve_eqs_tactic(m), gaussian_p),
|
||||||
mk_elim_uncnstr_tactic(m),
|
mk_elim_uncnstr_tactic(m),
|
||||||
|
@ -278,7 +269,9 @@ tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tactic* mk_qfbv_new_sls_tactic(ast_manager& m, params_ref const& p) {
|
tactic* mk_qfbv_new_sls_tactic(ast_manager& m, params_ref const& p) {
|
||||||
tactic* t = and_then(mk_preamble(m, p), mk_bv_sls_tactic(m, p));
|
params_ref q = p;
|
||||||
t->updt_params(p);
|
q.set_bool("elim_sign_ext", false);
|
||||||
|
tactic* t = and_then(mk_preamble(m, q), mk_bv_sls_tactic(m, q));
|
||||||
|
t->updt_params(q);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue