mirror of
https://github.com/Z3Prover/z3
synced 2025-04-07 18:05:21 +00:00
adding lns
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
64954cc551
commit
4375f54c45
|
@ -5,6 +5,7 @@ z3_add_component(opt
|
|||
mss.cpp
|
||||
opt_cmds.cpp
|
||||
opt_context.cpp
|
||||
opt_lns.cpp
|
||||
opt_pareto.cpp
|
||||
opt_parse.cpp
|
||||
optsmt.cpp
|
||||
|
|
|
@ -145,9 +145,8 @@ namespace opt {
|
|||
}
|
||||
|
||||
void context::reset_maxsmts() {
|
||||
map_t::iterator it = m_maxsmts.begin(), end = m_maxsmts.end();
|
||||
for (; it != end; ++it) {
|
||||
dealloc(it->m_value);
|
||||
for (auto& kv : m_maxsmts) {
|
||||
dealloc(kv.m_value);
|
||||
}
|
||||
m_maxsmts.reset();
|
||||
}
|
||||
|
@ -255,6 +254,9 @@ namespace opt {
|
|||
if (m_pareto) {
|
||||
return execute_pareto();
|
||||
}
|
||||
if (m_lns) {
|
||||
return execute_lns();
|
||||
}
|
||||
if (m_box_index != UINT_MAX) {
|
||||
return execute_box();
|
||||
}
|
||||
|
@ -271,10 +273,16 @@ namespace opt {
|
|||
#endif
|
||||
solver& s = get_solver();
|
||||
s.assert_expr(m_hard_constraints);
|
||||
IF_VERBOSE(1, verbose_stream() << "(optimize:check-sat)\n";);
|
||||
|
||||
opt_params optp(m_params);
|
||||
symbol pri = optp.priority();
|
||||
if (pri == symbol("lns")) {
|
||||
return execute_lns();
|
||||
}
|
||||
|
||||
IF_VERBOSE(1, verbose_stream() << "(optimize:check-sat)\n");
|
||||
lbool is_sat = s.check_sat(0,0);
|
||||
TRACE("opt", tout << "initial search result: " << is_sat << "\n";
|
||||
s.display(tout););
|
||||
TRACE("opt", s.display(tout << "initial search result: " << is_sat << "\n"););
|
||||
if (is_sat != l_false) {
|
||||
s.get_model(m_model);
|
||||
s.get_labels(m_labels);
|
||||
|
@ -286,7 +294,7 @@ namespace opt {
|
|||
TRACE("opt", tout << m_hard_constraints << "\n";);
|
||||
return is_sat;
|
||||
}
|
||||
IF_VERBOSE(1, verbose_stream() << "(optimize:sat)\n";);
|
||||
IF_VERBOSE(1, verbose_stream() << "(optimize:sat)\n");
|
||||
TRACE("opt", model_smt2_pp(tout, m, *m_model, 0););
|
||||
m_optsmt.setup(*m_opt_solver.get());
|
||||
update_lower();
|
||||
|
@ -303,6 +311,9 @@ namespace opt {
|
|||
if (pri == symbol("pareto")) {
|
||||
is_sat = execute_pareto();
|
||||
}
|
||||
else if (pri == symbol("lns")) {
|
||||
is_sat = execute_lns();
|
||||
}
|
||||
else if (pri == symbol("box")) {
|
||||
is_sat = execute_box();
|
||||
}
|
||||
|
@ -525,7 +536,12 @@ namespace opt {
|
|||
}
|
||||
|
||||
void context::yield() {
|
||||
m_pareto->get_model(m_model, m_labels);
|
||||
if (m_pareto) {
|
||||
m_pareto->get_model(m_model, m_labels);
|
||||
}
|
||||
else if (m_lns) {
|
||||
m_lns->get_model(m_model, m_labels);
|
||||
}
|
||||
update_bound(true);
|
||||
update_bound(false);
|
||||
}
|
||||
|
@ -536,7 +552,7 @@ namespace opt {
|
|||
}
|
||||
lbool is_sat = (*(m_pareto.get()))();
|
||||
if (is_sat != l_true) {
|
||||
set_pareto(0);
|
||||
set_pareto(nullptr);
|
||||
}
|
||||
if (is_sat == l_true) {
|
||||
yield();
|
||||
|
@ -544,6 +560,20 @@ namespace opt {
|
|||
return is_sat;
|
||||
}
|
||||
|
||||
lbool context::execute_lns() {
|
||||
if (!m_lns) {
|
||||
m_lns = alloc(lns, *this, m_solver.get());
|
||||
}
|
||||
lbool is_sat = (*(m_lns.get()))();
|
||||
if (is_sat != l_true) {
|
||||
m_lns = nullptr;
|
||||
}
|
||||
if (is_sat == l_true) {
|
||||
yield();
|
||||
}
|
||||
return l_undef;
|
||||
}
|
||||
|
||||
std::string context::reason_unknown() const {
|
||||
if (m.canceled()) {
|
||||
return Z3_CANCELED_MSG;
|
||||
|
@ -990,6 +1020,24 @@ namespace opt {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief retrieve literals used by the neighborhood search feature.
|
||||
*/
|
||||
|
||||
void context::get_lns_literals(expr_ref_vector& lits) {
|
||||
for (objective & obj : m_objectives) {
|
||||
switch(obj.m_type) {
|
||||
case O_MAXSMT:
|
||||
for (expr* f : obj.m_terms) {
|
||||
lits.push_back(f);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool context::verify_model(unsigned index, model* md, rational const& _v) {
|
||||
rational r;
|
||||
app_ref term = m_objectives[index].m_term;
|
||||
|
@ -1352,7 +1400,8 @@ namespace opt {
|
|||
}
|
||||
|
||||
void context::clear_state() {
|
||||
set_pareto(0);
|
||||
m_pareto = nullptr;
|
||||
m_lns = nullptr;
|
||||
m_box_index = UINT_MAX;
|
||||
m_model.reset();
|
||||
}
|
||||
|
@ -1388,9 +1437,8 @@ namespace opt {
|
|||
m_solver->updt_params(m_params);
|
||||
}
|
||||
m_optsmt.updt_params(m_params);
|
||||
map_t::iterator it = m_maxsmts.begin(), end = m_maxsmts.end();
|
||||
for (; it != end; ++it) {
|
||||
it->m_value->updt_params(m_params);
|
||||
for (auto & kv : m_maxsmts) {
|
||||
kv.m_value->updt_params(m_params);
|
||||
}
|
||||
opt_params _p(p);
|
||||
m_enable_sat = _p.enable_sat();
|
||||
|
|
|
@ -19,16 +19,18 @@ Notes:
|
|||
#define OPT_CONTEXT_H_
|
||||
|
||||
#include "ast/ast.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "tactic/model_converter.h"
|
||||
#include "tactic/tactic.h"
|
||||
#include "qe/qsat.h"
|
||||
#include "opt/opt_solver.h"
|
||||
#include "opt/opt_pareto.h"
|
||||
#include "opt/optsmt.h"
|
||||
#include "opt/opt_lns.h"
|
||||
#include "opt/maxsmt.h"
|
||||
#include "tactic/model_converter.h"
|
||||
#include "tactic/tactic.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "cmd_context/cmd_context.h"
|
||||
#include "qe/qsat.h"
|
||||
|
||||
|
||||
namespace opt {
|
||||
|
||||
|
@ -145,6 +147,7 @@ namespace opt {
|
|||
ref<solver> m_solver;
|
||||
ref<solver> m_sat_solver;
|
||||
scoped_ptr<pareto_base> m_pareto;
|
||||
scoped_ptr<lns> m_lns;
|
||||
scoped_ptr<qe::qmax> m_qmax;
|
||||
sref_vector<model> m_box_models;
|
||||
unsigned m_box_index;
|
||||
|
@ -231,6 +234,8 @@ namespace opt {
|
|||
|
||||
virtual bool verify_model(unsigned id, model* mdl, rational const& v);
|
||||
|
||||
void get_lns_literals(expr_ref_vector& lits);
|
||||
|
||||
private:
|
||||
lbool execute(objective const& obj, bool committed, bool scoped);
|
||||
lbool execute_min_max(unsigned index, bool committed, bool scoped, bool is_max);
|
||||
|
@ -238,6 +243,7 @@ namespace opt {
|
|||
lbool execute_lex();
|
||||
lbool execute_box();
|
||||
lbool execute_pareto();
|
||||
lbool execute_lns();
|
||||
lbool adjust_unknown(lbool r);
|
||||
bool scoped_lex();
|
||||
expr_ref to_expr(inf_eps const& n);
|
||||
|
@ -282,7 +288,7 @@ namespace opt {
|
|||
void setup_arith_solver();
|
||||
void add_maxsmt(symbol const& id, unsigned index);
|
||||
void set_simplify(tactic *simplify);
|
||||
void set_pareto(pareto_base* p);
|
||||
void set_pareto(pareto_base* p);
|
||||
void clear_state();
|
||||
|
||||
bool is_numeral(expr* e, rational& n) const;
|
||||
|
|
115
src/opt/opt_lns.cpp
Normal file
115
src/opt/opt_lns.cpp
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*++
|
||||
Copyright (c) 2018 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
opt_lns.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Large neighborhood search default implementation
|
||||
based on phase saving and assumptions
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2018-3-13
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "opt/opt_lns.h"
|
||||
#include "opt/opt_context.h"
|
||||
|
||||
namespace opt {
|
||||
|
||||
lns::lns(context& ctx, solver* s):
|
||||
m(ctx.get_manager()),
|
||||
m_ctx(ctx),
|
||||
m_solver(s),
|
||||
m_models_trail(m)
|
||||
{}
|
||||
|
||||
lns::~lns() {}
|
||||
|
||||
void lns::display(std::ostream & out) const {
|
||||
for (auto const& q : m_queue) {
|
||||
out << q.m_index << ": " << q.m_assignment << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
lbool lns::operator()() {
|
||||
|
||||
if (m_queue.empty()) {
|
||||
expr_ref_vector lits(m);
|
||||
m_ctx.get_lns_literals(lits);
|
||||
m_queue.push_back(queue_elem(lits));
|
||||
m_qhead = 0;
|
||||
}
|
||||
|
||||
params_ref p;
|
||||
p.set_uint("sat.inprocess.max", 3);
|
||||
p.set_uint("smt.max_conflicts", 10000);
|
||||
m_solver->updt_params(p);
|
||||
|
||||
while (m_qhead < m_queue.size()) {
|
||||
unsigned index = m_queue[m_qhead].m_index;
|
||||
if (index > m_queue[m_qhead].m_assignment.size()) {
|
||||
++m_qhead;
|
||||
continue;
|
||||
}
|
||||
IF_VERBOSE(2, verbose_stream() << "(opt.lns :queue " << m_qhead << " :index " << index << ")\n");
|
||||
|
||||
// recalibrate state to an initial satisfying assignment
|
||||
lbool is_sat = m_solver->check_sat(m_queue[m_qhead].m_assignment);
|
||||
IF_VERBOSE(2, verbose_stream() << "(opt.lns :calibrate-status " << is_sat << ")\n");
|
||||
|
||||
expr_ref lit(m_queue[m_qhead].m_assignment[index].get(), m);
|
||||
lit = mk_not(m, lit);
|
||||
expr* lits[1] = { lit };
|
||||
++m_queue[m_qhead].m_index;
|
||||
if (!m.limit().inc()) {
|
||||
return l_undef;
|
||||
}
|
||||
|
||||
// Update configuration for local search:
|
||||
// p.set_uint("sat.local_search_threads", 2);
|
||||
// p.set_uint("sat.unit_walk_threads", 1);
|
||||
|
||||
is_sat = m_solver->check_sat(1, lits);
|
||||
IF_VERBOSE(2, verbose_stream() << "(opt.lns :status " << is_sat << ")\n");
|
||||
if (is_sat == l_true && add_assignment()) {
|
||||
return l_true;
|
||||
}
|
||||
}
|
||||
return l_false;
|
||||
}
|
||||
|
||||
bool lns::add_assignment() {
|
||||
model_ref mdl;
|
||||
m_solver->get_model(mdl);
|
||||
m_ctx.fix_model(mdl);
|
||||
expr_ref tmp(m);
|
||||
expr_ref_vector fmls(m);
|
||||
for (expr* f : m_queue[0].m_assignment) {
|
||||
mdl->eval(f, tmp);
|
||||
if (m.is_false(tmp)) {
|
||||
fmls.push_back(mk_not(m, tmp));
|
||||
}
|
||||
else {
|
||||
fmls.push_back(tmp);
|
||||
}
|
||||
}
|
||||
tmp = mk_and(fmls);
|
||||
if (m_models.contains(tmp)) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
m_models.insert(tmp);
|
||||
m_models_trail.push_back(tmp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
66
src/opt/opt_lns.h
Normal file
66
src/opt/opt_lns.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*++
|
||||
Copyright (c) 2018 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
opt_lns.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Large neighborhood seearch
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2018-3-13
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
--*/
|
||||
#ifndef OPT_LNS_H_
|
||||
#define OPT_LNS_H_
|
||||
|
||||
#include "solver/solver.h"
|
||||
#include "model/model.h"
|
||||
|
||||
namespace opt {
|
||||
|
||||
class context;
|
||||
|
||||
class lns {
|
||||
struct queue_elem {
|
||||
expr_ref_vector m_assignment;
|
||||
unsigned m_index;
|
||||
queue_elem(expr_ref_vector& assign):
|
||||
m_assignment(assign),
|
||||
m_index(0)
|
||||
{}
|
||||
};
|
||||
ast_manager& m;
|
||||
context& m_ctx;
|
||||
ref<solver> m_solver;
|
||||
model_ref m_model;
|
||||
svector<symbol> m_labels;
|
||||
vector<queue_elem> m_queue;
|
||||
unsigned m_qhead;
|
||||
expr_ref_vector m_models_trail;
|
||||
obj_hashtable<expr> m_models;
|
||||
|
||||
bool add_assignment();
|
||||
public:
|
||||
lns(context& ctx, solver* s);
|
||||
|
||||
~lns();
|
||||
|
||||
void display(std::ostream & out) const;
|
||||
|
||||
lbool operator()();
|
||||
|
||||
void get_model(model_ref& mdl, svector<symbol>& labels) {
|
||||
mdl = m_model;
|
||||
labels = m_labels;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -3,7 +3,7 @@ def_module_params('opt',
|
|||
export=True,
|
||||
params=(('optsmt_engine', SYMBOL, 'basic', "select optimization engine: 'basic', 'farkas', 'symba'"),
|
||||
('maxsat_engine', SYMBOL, 'maxres', "select engine for maxsat: 'core_maxsat', 'wmax', 'maxres', 'pd-maxres'"),
|
||||
('priority', SYMBOL, 'lex', "select how to priortize objectives: 'lex' (lexicographic), 'pareto', or 'box'"),
|
||||
('priority', SYMBOL, 'lex', "select how to priortize objectives: 'lex' (lexicographic), 'pareto', 'box', or 'lns' (large neighborhood search)"),
|
||||
('dump_benchmarks', BOOL, False, 'dump benchmarks for profiling'),
|
||||
('timeout', UINT, UINT_MAX, 'timeout (in milliseconds) (UINT_MAX and 0 mean no timeout)'),
|
||||
('rlimit', UINT, 0, 'resource limit (0 means no limit)'),
|
||||
|
|
|
@ -222,7 +222,7 @@ namespace sat {
|
|||
}
|
||||
}
|
||||
TRACE("scc", for (unsigned i = 0; i < roots.size(); i++) { tout << i << " -> " << roots[i] << "\n"; }
|
||||
tout << "to_elim: "; for (literal l : to_elim) tout << l << " "; tout << "\n";);
|
||||
tout << "to_elim: "; for (unsigned v : to_elim) tout << v << " "; tout << "\n";);
|
||||
m_num_elim += to_elim.size();
|
||||
elim_eqs eliminator(m_solver);
|
||||
eliminator(roots, to_elim);
|
||||
|
|
Loading…
Reference in a new issue