mirror of
https://github.com/Z3Prover/z3
synced 2026-04-26 13:53:33 +00:00
Merge remote-tracking branch 'origin/master' into poly
This commit is contained in:
commit
94955e3fae
67 changed files with 2698 additions and 806 deletions
|
|
@ -1314,7 +1314,7 @@ namespace sat {
|
|||
}
|
||||
|
||||
bool solver::should_cancel() {
|
||||
if (limit_reached() || memory_exceeded()) {
|
||||
if (limit_reached() || memory_exceeded() || m_solver_canceled) {
|
||||
return true;
|
||||
}
|
||||
if (m_config.m_restart_max <= m_restarts) {
|
||||
|
|
@ -1959,6 +1959,7 @@ namespace sat {
|
|||
|
||||
void solver::init_search() {
|
||||
m_model_is_current = false;
|
||||
m_solver_canceled = false;
|
||||
m_phase_counter = 0;
|
||||
m_search_state = s_unsat;
|
||||
m_search_unsat_conflicts = m_config.m_search_unsat_conflicts;
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ namespace sat {
|
|||
clause_wrapper_vector m_clauses_to_reinit;
|
||||
std::string m_reason_unknown;
|
||||
bool m_trim = false;
|
||||
bool m_solver_canceled = false;
|
||||
|
||||
visit_helper m_visited;
|
||||
|
||||
|
|
@ -287,6 +288,7 @@ namespace sat {
|
|||
random_gen& rand() { return m_rand; }
|
||||
|
||||
void set_trim() { m_trim = true; }
|
||||
void set_canceled() { m_solver_canceled = true; }
|
||||
|
||||
protected:
|
||||
void reset_var(bool_var v, bool ext, bool dvar);
|
||||
|
|
|
|||
|
|
@ -197,10 +197,16 @@ public:
|
|||
case l_false:
|
||||
extract_core();
|
||||
break;
|
||||
default:
|
||||
default: {
|
||||
auto* ext = get_euf();
|
||||
if (ext && ext->get_sls_model()) {
|
||||
r = l_true;
|
||||
break;
|
||||
}
|
||||
set_reason_unknown(m_solver.get_reason_unknown());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -576,6 +582,7 @@ private:
|
|||
void add_assumption(expr* a) {
|
||||
init_goal2sat();
|
||||
m_dep.insert(a, m_goal2sat.internalize(a));
|
||||
get_euf()->add_assertion(a);
|
||||
}
|
||||
|
||||
void internalize_assumptions(expr_ref_vector const& asms) {
|
||||
|
|
@ -632,6 +639,11 @@ private:
|
|||
void get_model_core(model_ref & mdl) override {
|
||||
TRACE("sat", tout << "retrieve model " << (m_solver.model_is_current()?"present":"absent") << "\n";);
|
||||
mdl = nullptr;
|
||||
auto ext = get_euf();
|
||||
if (ext)
|
||||
mdl = ext->get_sls_model();
|
||||
if (mdl)
|
||||
return;
|
||||
if (!m_solver.model_is_current())
|
||||
return;
|
||||
if (m_fmls.size() > m_qhead)
|
||||
|
|
|
|||
|
|
@ -525,4 +525,8 @@ namespace euf {
|
|||
return n;
|
||||
}
|
||||
|
||||
void solver::add_assertion(expr* f) {
|
||||
m_assertions.push_back(f);
|
||||
m_trail.push(push_back_vector(m_assertions));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ Author:
|
|||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "sat/smt/euf_solver.h"
|
||||
#include "sat/smt/sls_solver.h"
|
||||
#include "model/value_factory.h"
|
||||
|
||||
namespace euf {
|
||||
|
|
@ -67,6 +68,14 @@ namespace euf {
|
|||
m_qmodel = mdl;
|
||||
}
|
||||
|
||||
model_ref solver::get_sls_model() {
|
||||
model_ref mdl;
|
||||
auto s = get_solver(m.mk_family_id("sls"), nullptr);
|
||||
if (s)
|
||||
mdl = dynamic_cast<sls::solver*>(s)->get_model();
|
||||
return mdl;
|
||||
}
|
||||
|
||||
void solver::update_model(model_ref& mdl, bool validate) {
|
||||
TRACE("model", tout << "create model\n";);
|
||||
if (m_qmodel) {
|
||||
|
|
@ -318,7 +327,7 @@ namespace euf {
|
|||
out << mdl << "\n";
|
||||
}
|
||||
|
||||
void solver::validate_model(model& mdl) {
|
||||
void solver::validate_model(model& mdl) {
|
||||
if (!m_unhandled_functions.empty())
|
||||
return;
|
||||
if (get_config().m_arith_ignore_int)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ Author:
|
|||
#include "sat/smt/q_solver.h"
|
||||
#include "sat/smt/fpa_solver.h"
|
||||
#include "sat/smt/dt_solver.h"
|
||||
#include "sat/smt/sls_solver.h"
|
||||
#include "sat/smt/recfun_solver.h"
|
||||
#include "sat/smt/specrel_solver.h"
|
||||
|
||||
|
|
@ -55,6 +56,7 @@ namespace euf {
|
|||
m_smt_proof_checker(m, p),
|
||||
m_clause(m),
|
||||
m_expr_args(m),
|
||||
m_assertions(m),
|
||||
m_values(m)
|
||||
{
|
||||
updt_params(p);
|
||||
|
|
@ -78,6 +80,7 @@ namespace euf {
|
|||
};
|
||||
m_egraph.set_on_merge(on_merge);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void solver::updt_params(params_ref const& p) {
|
||||
|
|
@ -186,7 +189,9 @@ namespace euf {
|
|||
IF_VERBOSE(0, verbose_stream() << mk_pp(f, m) << " not handled\n");
|
||||
}
|
||||
|
||||
void solver::init_search() {
|
||||
void solver::init_search() {
|
||||
if (get_config().m_sls_enable)
|
||||
add_solver(alloc(sls::solver, *this));
|
||||
TRACE("before_search", s().display(tout););
|
||||
m_reason_unknown.clear();
|
||||
for (auto* s : m_solvers)
|
||||
|
|
@ -218,7 +223,7 @@ namespace euf {
|
|||
mark_relevant(lit);
|
||||
s().assign(lit, sat::justification::mk_ext_justification(s().scope_lvl(), idx));
|
||||
}
|
||||
|
||||
|
||||
lbool solver::resolve_conflict() {
|
||||
for (auto* s : m_solvers) {
|
||||
lbool r = s->resolve_conflict();
|
||||
|
|
@ -665,7 +670,9 @@ namespace euf {
|
|||
if (give_up)
|
||||
return sat::check_result::CR_GIVEUP;
|
||||
if (m_qsolver && m_config.m_arith_ignore_int)
|
||||
return sat::check_result::CR_GIVEUP;
|
||||
return sat::check_result::CR_GIVEUP;
|
||||
for (auto s : m_solvers)
|
||||
s->finalize();
|
||||
return sat::check_result::CR_DONE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ namespace euf {
|
|||
svector<scope> m_scopes;
|
||||
scoped_ptr_vector<th_solver> m_solvers;
|
||||
ptr_vector<th_solver> m_id2solver;
|
||||
|
||||
|
||||
constraint* m_conflict = nullptr;
|
||||
constraint* m_eq = nullptr;
|
||||
|
|
@ -173,6 +174,7 @@ namespace euf {
|
|||
symbol m_smt = symbol("smt");
|
||||
expr_ref_vector m_clause;
|
||||
expr_ref_vector m_expr_args;
|
||||
expr_ref_vector m_assertions;
|
||||
|
||||
|
||||
// internalization
|
||||
|
|
@ -482,6 +484,10 @@ namespace euf {
|
|||
bool enable_ackerman_axioms(expr* n) const;
|
||||
bool is_fixed(euf::enode* n, expr_ref& val, sat::literal_vector& explain);
|
||||
|
||||
void add_assertion(expr* f);
|
||||
expr_ref_vector const& get_assertions() { return m_assertions; }
|
||||
model_ref get_sls_model();
|
||||
|
||||
// relevancy
|
||||
|
||||
bool relevancy_enabled() const { return m_relevancy.enabled(); }
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ namespace intblast {
|
|||
sat::literal lit = expr2literal(e);
|
||||
if (sign)
|
||||
lit.neg();
|
||||
TRACE("bv", tout << mk_pp(e, m) << " -> " << literal2expr(lit) << "\n");
|
||||
return lit;
|
||||
}
|
||||
|
||||
|
|
@ -102,6 +103,7 @@ namespace intblast {
|
|||
set_translated(e, m.mk_eq(umod(x, 0), a.mk_int(0)));
|
||||
}
|
||||
m_preds.push_back(e);
|
||||
TRACE("bv", tout << mk_pp(e, m) << " " << mk_pp(translated(e), m) << "\n");
|
||||
ctx.push(push_back_vector(m_preds));
|
||||
}
|
||||
|
||||
|
|
@ -476,6 +478,8 @@ namespace intblast {
|
|||
continue;
|
||||
if (sib->get_arg(0)->get_root() == r1)
|
||||
continue;
|
||||
if (bv.get_bv_size(r1->get_expr()) != bv.get_bv_size(sib->get_arg(0)->get_expr()))
|
||||
continue;
|
||||
auto a = eq_internalize(n, sib);
|
||||
auto b = eq_internalize(sib->get_arg(0), n->get_arg(0));
|
||||
ctx.mark_relevant(a);
|
||||
|
|
@ -626,12 +630,12 @@ namespace intblast {
|
|||
}
|
||||
|
||||
void solver::translate_quantifier(quantifier* q) {
|
||||
if (is_lambda(q))
|
||||
throw default_exception("lambdas are not supported in intblaster");
|
||||
if (m_is_plugin) {
|
||||
set_translated(q, q);
|
||||
return;
|
||||
}
|
||||
if (is_lambda(q))
|
||||
throw default_exception("lambdas are not supported in intblaster");
|
||||
expr* b = q->get_expr();
|
||||
unsigned nd = q->get_num_decls();
|
||||
ptr_vector<sort> sorts;
|
||||
|
|
@ -642,7 +646,6 @@ namespace intblast {
|
|||
sorts.push_back(a.mk_int());
|
||||
}
|
||||
else
|
||||
|
||||
sorts.push_back(s);
|
||||
}
|
||||
b = translated(b);
|
||||
|
|
@ -767,6 +770,7 @@ namespace intblast {
|
|||
r = a.mk_le(smod(bv_expr, 0), smod(bv_expr, 1));
|
||||
break;
|
||||
case OP_SGEQ:
|
||||
bv_expr = e->get_arg(0);
|
||||
r = a.mk_ge(smod(bv_expr, 0), smod(bv_expr, 1));
|
||||
break;
|
||||
case OP_SLT:
|
||||
|
|
@ -815,13 +819,13 @@ namespace intblast {
|
|||
case OP_BUREM:
|
||||
case OP_BUREM_I: {
|
||||
expr* x = umod(e, 0), * y = umod(e, 1);
|
||||
r = m.mk_ite(m.mk_eq(y, a.mk_int(0)), x, a.mk_mod(x, y));
|
||||
r = if_eq(y, 0, x, a.mk_mod(x, y));
|
||||
break;
|
||||
}
|
||||
case OP_BUDIV:
|
||||
case OP_BUDIV_I: {
|
||||
expr* x = arg(0), * y = umod(e, 1);
|
||||
r = m.mk_ite(m.mk_eq(y, a.mk_int(0)), a.mk_int(-1), a.mk_idiv(x, y));
|
||||
expr* x = umod(e, 0), * y = umod(e, 1);
|
||||
r = if_eq(y, 0, a.mk_int(-1), a.mk_idiv(x, y));
|
||||
break;
|
||||
}
|
||||
case OP_BUMUL_NO_OVFL: {
|
||||
|
|
@ -863,7 +867,7 @@ namespace intblast {
|
|||
r = a.mk_int(0);
|
||||
IF_VERBOSE(2, verbose_stream() << "shl " << mk_bounded_pp(e, m) << " " << bv.get_bv_size(e) << "\n");
|
||||
for (unsigned i = 0; i < bv.get_bv_size(e); ++i)
|
||||
r = m.mk_ite(m.mk_eq(y, a.mk_int(i)), mul(x, a.mk_int(rational::power_of_two(i))), r);
|
||||
r = if_eq(y, i, mul(x, a.mk_int(rational::power_of_two(i))), r);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -878,7 +882,7 @@ namespace intblast {
|
|||
r = a.mk_int(0);
|
||||
IF_VERBOSE(2, verbose_stream() << "lshr " << mk_bounded_pp(e, m) << " " << bv.get_bv_size(e) << "\n");
|
||||
for (unsigned i = 0; i < bv.get_bv_size(e); ++i)
|
||||
r = m.mk_ite(m.mk_eq(y, a.mk_int(i)), a.mk_idiv(x, a.mk_int(rational::power_of_two(i))), r);
|
||||
r = if_eq(y, i, a.mk_idiv(x, a.mk_int(rational::power_of_two(i))), r);
|
||||
}
|
||||
break;
|
||||
case OP_BASHR:
|
||||
|
|
@ -899,20 +903,19 @@ namespace intblast {
|
|||
IF_VERBOSE(1, verbose_stream() << "ashr " << mk_bounded_pp(e, m) << " " << bv.get_bv_size(e) << "\n");
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
expr* d = a.mk_idiv(x, a.mk_int(rational::power_of_two(i)));
|
||||
r = m.mk_ite(m.mk_eq(y, a.mk_int(i)),
|
||||
r = if_eq(y, i,
|
||||
m.mk_ite(signx, add(d, a.mk_int(- rational::power_of_two(sz-i))), d),
|
||||
r);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OP_BOR: {
|
||||
case OP_BOR:
|
||||
// p | q := (p + q) - band(p, q)
|
||||
IF_VERBOSE(2, verbose_stream() << "bor " << mk_bounded_pp(e, m) << " " << bv.get_bv_size(e) << "\n");
|
||||
r = arg(0);
|
||||
for (unsigned i = 1; i < args.size(); ++i)
|
||||
r = a.mk_sub(add(r, arg(i)), a.mk_band(bv.get_bv_size(e), r, arg(i)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OP_BNAND:
|
||||
r = bnot(band(args));
|
||||
break;
|
||||
|
|
@ -982,8 +985,8 @@ namespace intblast {
|
|||
r = m.mk_ite(m.mk_and(m.mk_not(signx), signy), add(u, y), r);
|
||||
r = m.mk_ite(m.mk_and(signx, m.mk_not(signy)), a.mk_sub(y, u), r);
|
||||
r = m.mk_ite(m.mk_and(m.mk_not(signx), m.mk_not(signy)), u, r);
|
||||
r = m.mk_ite(m.mk_eq(u, a.mk_int(0)), a.mk_int(0), r);
|
||||
r = m.mk_ite(m.mk_eq(y, a.mk_int(0)), x, r);
|
||||
r = if_eq(u, 0, a.mk_int(0), r);
|
||||
r = if_eq(y, 0, x, r);
|
||||
break;
|
||||
}
|
||||
case OP_BSDIV_I:
|
||||
|
|
@ -1004,7 +1007,7 @@ namespace intblast {
|
|||
y = m.mk_ite(signy, a.mk_sub(a.mk_int(N), y), y);
|
||||
expr* d = a.mk_idiv(x, y);
|
||||
r = m.mk_ite(m.mk_iff(signx, signy), d, a.mk_uminus(d));
|
||||
r = m.mk_ite(m.mk_eq(y, a.mk_int(0)), m.mk_ite(signx, a.mk_int(1), a.mk_int(-1)), r);
|
||||
r = if_eq(y, 0, m.mk_ite(signx, a.mk_int(1), a.mk_int(-1)), r);
|
||||
break;
|
||||
}
|
||||
case OP_BSREM_I:
|
||||
|
|
@ -1020,7 +1023,7 @@ namespace intblast {
|
|||
expr* d = a.mk_idiv(absx, absy);
|
||||
d = m.mk_ite(m.mk_iff(signx, signy), d, a.mk_uminus(d));
|
||||
r = a.mk_sub(x, mul(d, y));
|
||||
r = m.mk_ite(m.mk_eq(y, a.mk_int(0)), x, r);
|
||||
r = if_eq(y, 0, x, r);
|
||||
break;
|
||||
}
|
||||
case OP_ROTATE_LEFT: {
|
||||
|
|
@ -1039,7 +1042,7 @@ namespace intblast {
|
|||
expr* y = umod(e, 1);
|
||||
r = a.mk_int(0);
|
||||
for (unsigned i = 0; i < sz; ++i)
|
||||
r = m.mk_ite(m.mk_eq(a.mk_int(i), y), rotate_left(i), r);
|
||||
r = if_eq(y, i, rotate_left(i), r);
|
||||
break;
|
||||
}
|
||||
case OP_EXT_ROTATE_RIGHT: {
|
||||
|
|
@ -1047,7 +1050,7 @@ namespace intblast {
|
|||
expr* y = umod(e, 1);
|
||||
r = a.mk_int(0);
|
||||
for (unsigned i = 0; i < sz; ++i)
|
||||
r = m.mk_ite(m.mk_eq(a.mk_int(i), y), rotate_left(sz - i), r);
|
||||
r = if_eq(y, i, rotate_left(sz - i), r);
|
||||
break;
|
||||
}
|
||||
case OP_REPEAT: {
|
||||
|
|
@ -1078,6 +1081,18 @@ namespace intblast {
|
|||
set_translated(e, r);
|
||||
}
|
||||
|
||||
expr_ref solver::if_eq(expr* n, unsigned k, expr* th, expr* el) {
|
||||
rational r;
|
||||
expr_ref _th(th, m), _el(el, m);
|
||||
if (bv.is_numeral(n, r)) {
|
||||
if (r == k)
|
||||
return expr_ref(th, m);
|
||||
else
|
||||
return expr_ref(el, m);
|
||||
}
|
||||
return expr_ref(m.mk_ite(m.mk_eq(n, a.mk_int(k)), th, el), m);
|
||||
}
|
||||
|
||||
void solver::translate_basic(app* e) {
|
||||
if (m.is_eq(e)) {
|
||||
bool has_bv_arg = any_of(*e, [&](expr* arg) { return bv.is_bv(arg); });
|
||||
|
|
@ -1136,7 +1151,7 @@ namespace intblast {
|
|||
if (e->get_family_id() != bv.get_family_id())
|
||||
return false;
|
||||
for (euf::enode* arg : euf::enode_args(n))
|
||||
dep.add(n, arg->get_root());
|
||||
dep.add(n, arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1191,6 +1206,27 @@ namespace intblast {
|
|||
TRACE("model", tout << "add_value " << ctx.bpp(n) << " := " << value << "\n");
|
||||
}
|
||||
|
||||
void solver::finalize_model(model& mdl) {
|
||||
return;
|
||||
for (auto n : ctx.get_egraph().nodes()) {
|
||||
auto e = n->get_expr();
|
||||
if (!is_translated(e))
|
||||
continue;
|
||||
if (!bv.is_bv(e))
|
||||
continue;
|
||||
auto t = translated(e);
|
||||
|
||||
expr_ref ei(bv.mk_bv2int(e), m);
|
||||
expr_ref ti(a.mk_mod(t, a.mk_int(rational::power_of_two(bv.get_bv_size(e)))), m);
|
||||
auto ev = mdl(ei);
|
||||
auto tv = mdl(ti);
|
||||
if (ev != tv) {
|
||||
IF_VERBOSE(0, verbose_stream() << mk_pp(e, m) << " <- " << ev << "\n");
|
||||
IF_VERBOSE(0, verbose_stream() << mk_pp(t, m) << " <- " << tv << "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sat::literal_vector const& solver::unsat_core() {
|
||||
return m_core;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ namespace intblast {
|
|||
bool is_non_negative(expr* bv_expr, expr* e);
|
||||
expr_ref mul(expr* x, expr* y);
|
||||
expr_ref add(expr* x, expr* y);
|
||||
expr_ref if_eq(expr* n, unsigned k, expr* th, expr* el);
|
||||
expr* amod(expr* bv_expr, expr* x, rational const& N);
|
||||
rational bv_size(expr* bv_expr);
|
||||
|
||||
|
|
@ -147,6 +148,7 @@ namespace intblast {
|
|||
|
||||
rational get_value(expr* e) const;
|
||||
|
||||
void finalize_model(model& mdl) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,6 +148,8 @@ namespace euf {
|
|||
|
||||
virtual void set_bounds(enode* n) {}
|
||||
|
||||
virtual void finalize() {}
|
||||
|
||||
};
|
||||
|
||||
class th_proof_hint : public sat::proof_hint {
|
||||
|
|
@ -223,6 +225,7 @@ namespace euf {
|
|||
void push() override { m_num_scopes++; }
|
||||
void pop(unsigned n) override;
|
||||
|
||||
|
||||
unsigned random();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -22,109 +22,145 @@ Author:
|
|||
|
||||
namespace sls {
|
||||
|
||||
#ifdef SINGLE_THREAD
|
||||
|
||||
solver::solver(euf::solver& ctx) :
|
||||
th_euf_solver(ctx, symbol("sls"), ctx.get_manager().mk_family_id("sls"))
|
||||
{}
|
||||
|
||||
#else
|
||||
solver::solver(euf::solver& ctx):
|
||||
th_euf_solver(ctx, symbol("sls"), ctx.get_manager().mk_family_id("sls")) {}
|
||||
th_euf_solver(ctx, symbol("sls"), ctx.get_manager().mk_family_id("sls"))
|
||||
{}
|
||||
|
||||
solver::~solver() {
|
||||
if (m_bvsls) {
|
||||
m_bvsls->cancel();
|
||||
finalize();
|
||||
}
|
||||
|
||||
void solver::finalize() {
|
||||
if (!m_completed && m_sls) {
|
||||
m_sls->cancel();
|
||||
m_thread.join();
|
||||
m_sls->collect_statistics(m_st);
|
||||
m_sls = nullptr;
|
||||
m_shared = nullptr;
|
||||
m_slsm = nullptr;
|
||||
m_units = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void solver::push_core() {
|
||||
if (s().scope_lvl() == s().search_lvl() + 1)
|
||||
init_local_search();
|
||||
sat::check_result solver::check() {
|
||||
return sat::check_result::CR_DONE;
|
||||
}
|
||||
|
||||
|
||||
bool solver::unit_propagate() {
|
||||
force_push();
|
||||
sample_local_search();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool solver::is_unit(expr* e) {
|
||||
if (!e)
|
||||
return false;
|
||||
m.is_not(e, e);
|
||||
if (is_uninterp_const(e))
|
||||
return true;
|
||||
bv_util bu(m);
|
||||
expr* s;
|
||||
if (bu.is_bit2bool(e, s))
|
||||
return is_uninterp_const(s);
|
||||
return false;
|
||||
}
|
||||
|
||||
void solver::pop_core(unsigned n) {
|
||||
if (s().scope_lvl() - n <= s().search_lvl())
|
||||
sample_local_search();
|
||||
}
|
||||
|
||||
void solver::simplify() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void solver::init_local_search() {
|
||||
if (m_bvsls) {
|
||||
m_bvsls->cancel();
|
||||
m_thread.join();
|
||||
if (m_result == l_true) {
|
||||
verbose_stream() << "Found model using local search - INIT\n";
|
||||
exit(1);
|
||||
for (; m_trail_lim < s().init_trail_size(); ++m_trail_lim) {
|
||||
auto lit = s().trail_literal(m_trail_lim);
|
||||
auto e = ctx.literal2expr(lit);
|
||||
if (is_unit(e)) {
|
||||
// IF_VERBOSE(1, verbose_stream() << "add unit " << mk_pp(e, m) << "\n");
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
ast_translation tr(m, *m_shared);
|
||||
m_units->push_back(tr(e.get()));
|
||||
m_has_units = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void solver::init_search() {
|
||||
if (m_sls) {
|
||||
m_sls->cancel();
|
||||
m_thread.join();
|
||||
m_result = l_undef;
|
||||
m_completed = false;
|
||||
m_has_units = false;
|
||||
m_model = nullptr;
|
||||
m_units = nullptr;
|
||||
}
|
||||
// set up state for local search solver here
|
||||
|
||||
m_m = alloc(ast_manager, m);
|
||||
ast_translation tr(m, *m_m);
|
||||
m_shared = alloc(ast_manager);
|
||||
m_slsm = alloc(ast_manager);
|
||||
m_units = alloc(expr_ref_vector, *m_shared);
|
||||
ast_translation tr(m, *m_slsm);
|
||||
|
||||
m_completed = false;
|
||||
m_result = l_undef;
|
||||
m_bvsls = alloc(bv::sls, *m_m);
|
||||
// walk clauses, add them
|
||||
// walk trail stack until search level, add units
|
||||
// encapsulate bvsls within the arguments of run-local-search.
|
||||
// ensure bvsls does not touch ast-manager.
|
||||
m_model = nullptr;
|
||||
m_sls = alloc(bv::sls, *m_slsm, s().params());
|
||||
|
||||
for (expr* a : ctx.get_assertions())
|
||||
m_sls->assert_expr(tr(a));
|
||||
|
||||
unsigned trail_sz = s().trail_size();
|
||||
for (unsigned i = 0; i < trail_sz; ++i) {
|
||||
auto lit = s().trail_literal(i);
|
||||
if (s().lvl(lit) > s().search_lvl())
|
||||
break;
|
||||
expr_ref fml = literal2expr(lit);
|
||||
m_bvsls->assert_expr(tr(fml.get()));
|
||||
}
|
||||
unsigned num_vars = s().num_vars();
|
||||
for (unsigned i = 0; i < 2*num_vars; ++i) {
|
||||
auto l1 = ~sat::to_literal(i);
|
||||
auto const& wlist = s().get_wlist(l1);
|
||||
for (sat::watched const& w : wlist) {
|
||||
if (!w.is_binary_non_learned_clause())
|
||||
continue;
|
||||
sat::literal l2 = w.get_literal();
|
||||
if (l1.index() > l2.index())
|
||||
continue;
|
||||
expr_ref fml(m.mk_or(literal2expr(l1), literal2expr(l2)), m);
|
||||
m_bvsls->assert_expr(tr(fml.get()));
|
||||
}
|
||||
}
|
||||
for (auto clause : s().clauses()) {
|
||||
expr_ref_vector cls(m);
|
||||
for (auto lit : *clause)
|
||||
cls.push_back(literal2expr(lit));
|
||||
expr_ref fml(m.mk_or(cls), m);
|
||||
m_bvsls->assert_expr(tr(fml.get()));
|
||||
}
|
||||
|
||||
// use phase assignment from literals?
|
||||
std::function<bool(expr*, unsigned)> eval = [&](expr* e, unsigned r) {
|
||||
return false;
|
||||
};
|
||||
|
||||
m_bvsls->init();
|
||||
m_bvsls->init_eval(eval);
|
||||
m_bvsls->updt_params(s().params());
|
||||
|
||||
m_sls->init();
|
||||
m_sls->init_eval(eval);
|
||||
m_sls->updt_params(s().params());
|
||||
m_sls->init_unit([&]() {
|
||||
if (!m_has_units)
|
||||
return expr_ref(*m_slsm);
|
||||
expr_ref e(*m_slsm);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (m_units->empty())
|
||||
return expr_ref(*m_slsm);
|
||||
ast_translation tr(*m_shared, *m_slsm);
|
||||
e = tr(m_units->back());
|
||||
m_units->pop_back();
|
||||
}
|
||||
return e;
|
||||
});
|
||||
m_sls->set_model([&](model& mdl) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
ast_translation tr(*m_shared, m);
|
||||
m_model = mdl.translate(tr);
|
||||
});
|
||||
|
||||
m_thread = std::thread([this]() { run_local_search(); });
|
||||
}
|
||||
|
||||
void solver::sample_local_search() {
|
||||
if (m_completed) {
|
||||
m_thread.join();
|
||||
if (m_result == l_true) {
|
||||
verbose_stream() << "Found model using local search\n";
|
||||
exit(1);
|
||||
}
|
||||
if (!m_completed)
|
||||
return;
|
||||
m_thread.join();
|
||||
m_completed = false;
|
||||
m_sls->collect_statistics(m_st);
|
||||
if (m_result == l_true) {
|
||||
IF_VERBOSE(2, verbose_stream() << "(sat.sls :model-completed)\n";);
|
||||
auto mdl = m_sls->get_model();
|
||||
ast_translation tr(*m_slsm, m);
|
||||
m_model = mdl->translate(tr);
|
||||
s().set_canceled();
|
||||
}
|
||||
m_sls = nullptr;
|
||||
}
|
||||
|
||||
void solver::run_local_search() {
|
||||
lbool r = (*m_bvsls)();
|
||||
m_result = r;
|
||||
m_result = (*m_sls)();
|
||||
m_completed = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,12 +16,45 @@ Author:
|
|||
--*/
|
||||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "util/rlimit.h"
|
||||
#include "ast/sls/bv_sls.h"
|
||||
#include "sat/smt/sat_th.h"
|
||||
|
||||
|
||||
#ifdef SINGLE_THREAD
|
||||
|
||||
|
||||
namespace euf {
|
||||
class solver;
|
||||
}
|
||||
|
||||
namespace sls {
|
||||
|
||||
class solver : public euf::th_euf_solver {
|
||||
public:
|
||||
solver(euf::solver& ctx);
|
||||
|
||||
sat::literal internalize(expr* e, bool sign, bool root) override { UNREACHABLE(); return sat::null_literal; }
|
||||
void internalize(expr* e) override { UNREACHABLE(); }
|
||||
th_solver* clone(euf::solver& ctx) override { return alloc(solver, ctx); }
|
||||
|
||||
model_ref get_model() { return model_ref(nullptr); }
|
||||
bool unit_propagate() override { return false; }
|
||||
void get_antecedents(sat::literal l, sat::ext_justification_idx idx, sat::literal_vector& r, bool probing) override { UNREACHABLE(); }
|
||||
sat::check_result check() override { return sat::check_result::CR_DONE;}
|
||||
std::ostream& display(std::ostream& out) const override { return out; }
|
||||
std::ostream& display_justification(std::ostream& out, sat::ext_justification_idx idx) const override { UNREACHABLE(); return out; }
|
||||
std::ostream& display_constraint(std::ostream& out, sat::ext_constraint_idx idx) const override { UNREACHABLE(); return out; }
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
namespace euf {
|
||||
class solver;
|
||||
}
|
||||
|
|
@ -30,30 +63,41 @@ namespace sls {
|
|||
|
||||
class solver : public euf::th_euf_solver {
|
||||
std::atomic<lbool> m_result;
|
||||
std::atomic<bool> m_completed;
|
||||
std::atomic<bool> m_completed, m_has_units;
|
||||
std::thread m_thread;
|
||||
scoped_ptr<ast_manager> m_m;
|
||||
scoped_ptr<bv::sls> m_bvsls;
|
||||
std::mutex m_mutex;
|
||||
// m is accessed by the main thread
|
||||
// m_slsm is accessed by the sls thread
|
||||
// m_shared is only accessed at synchronization points
|
||||
scoped_ptr<ast_manager> m_shared, m_slsm;
|
||||
scoped_ptr<bv::sls> m_sls;
|
||||
scoped_ptr<expr_ref_vector> m_units;
|
||||
model_ref m_model;
|
||||
unsigned m_trail_lim = 0;
|
||||
statistics m_st;
|
||||
|
||||
void run_local_search();
|
||||
void init_local_search();
|
||||
void sample_local_search();
|
||||
bool is_unit(expr*);
|
||||
|
||||
public:
|
||||
solver(euf::solver& ctx);
|
||||
~solver();
|
||||
|
||||
void push_core() override;
|
||||
model_ref get_model() { return m_model; }
|
||||
|
||||
void init_search() override;
|
||||
void push_core() override {}
|
||||
void pop_core(unsigned n) override;
|
||||
void simplify() override;
|
||||
th_solver* clone(euf::solver& ctx) override { return alloc(solver, ctx); }
|
||||
void collect_statistics(statistics& st) const override { st.copy(m_st); }
|
||||
void finalize() override;
|
||||
bool unit_propagate() override;
|
||||
|
||||
sat::literal internalize(expr* e, bool sign, bool root) override { UNREACHABLE(); return sat::null_literal; }
|
||||
void internalize(expr* e) override { UNREACHABLE(); }
|
||||
th_solver* clone(euf::solver& ctx) override { return alloc(solver, ctx); }
|
||||
|
||||
|
||||
bool unit_propagate() override { return false; }
|
||||
void get_antecedents(sat::literal l, sat::ext_justification_idx idx, sat::literal_vector & r, bool probing) override { UNREACHABLE(); }
|
||||
sat::check_result check() override { return sat::check_result::CR_DONE; }
|
||||
sat::check_result check() override;
|
||||
std::ostream & display(std::ostream & out) const override { return out; }
|
||||
std::ostream & display_justification(std::ostream & out, sat::ext_justification_idx idx) const override { UNREACHABLE(); return out; }
|
||||
std::ostream & display_constraint(std::ostream & out, sat::ext_constraint_idx idx) const override { UNREACHABLE(); return out; }
|
||||
|
|
@ -61,3 +105,5 @@ namespace sls {
|
|||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -895,6 +895,7 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
|||
process(n, true);
|
||||
CTRACE("goal2sat", !m_result_stack.empty(), tout << m_result_stack << "\n";);
|
||||
SASSERT(m_result_stack.empty());
|
||||
add_assertion(n);
|
||||
}
|
||||
|
||||
void insert_dep(expr* dep0, expr* dep, bool sign) {
|
||||
|
|
@ -989,6 +990,12 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
|||
}
|
||||
}
|
||||
|
||||
void add_assertion(expr* f) {
|
||||
auto* ext = dynamic_cast<euf::solver*>(m_solver.get_extension());
|
||||
if (ext)
|
||||
ext->add_assertion(f);
|
||||
}
|
||||
|
||||
void update_model(model_ref& mdl) {
|
||||
auto* ext = dynamic_cast<euf::solver*>(m_solver.get_extension());
|
||||
if (ext)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue