mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
move to get_sort as method, add opt_lns pass, disable xor simplification unless configured, fix perf bug in model converter update trail
This commit is contained in:
parent
c623e2db28
commit
4455f6caf8
36 changed files with 391 additions and 90 deletions
|
@ -5,6 +5,7 @@ z3_add_component(opt
|
|||
maxsmt.cpp
|
||||
opt_cmds.cpp
|
||||
opt_context.cpp
|
||||
opt_lns.cpp
|
||||
opt_pareto.cpp
|
||||
opt_parse.cpp
|
||||
optsmt.cpp
|
||||
|
|
|
@ -62,6 +62,7 @@ Notes:
|
|||
#include "smt/smt_solver.h"
|
||||
#include "opt/opt_context.h"
|
||||
#include "opt/opt_params.hpp"
|
||||
#include "opt/opt_lns.h"
|
||||
#include "opt/maxsmt.h"
|
||||
#include "opt/maxres.h"
|
||||
|
||||
|
@ -107,9 +108,9 @@ private:
|
|||
// this option is disabled if SAT core is used.
|
||||
bool m_pivot_on_cs; // prefer smaller correction set to core.
|
||||
bool m_dump_benchmarks; // display benchmarks (into wcnf format)
|
||||
|
||||
bool m_enable_lns { false }; // enable LNS improvements
|
||||
unsigned m_lns_conflicts { 1000 }; // number of conflicts used for LNS improvement
|
||||
|
||||
|
||||
std::string m_trace_id;
|
||||
typedef ptr_vector<expr> exprs;
|
||||
|
||||
|
@ -201,6 +202,7 @@ public:
|
|||
if (!init()) return l_undef;
|
||||
is_sat = init_local();
|
||||
trace();
|
||||
improve_model();
|
||||
if (is_sat != l_true) return is_sat;
|
||||
while (m_lower < m_upper) {
|
||||
TRACE("opt_verbose",
|
||||
|
@ -730,7 +732,29 @@ public:
|
|||
add(fml);
|
||||
}
|
||||
|
||||
void improve_model() {
|
||||
if (!m_enable_lns)
|
||||
return;
|
||||
model_ref mdl;
|
||||
s().get_model(mdl);
|
||||
if (mdl)
|
||||
update_assignment(mdl);
|
||||
}
|
||||
|
||||
void improve_model(model_ref& mdl) {
|
||||
if (!m_enable_lns)
|
||||
return;
|
||||
flet<bool> _disable_lns(m_enable_lns, false);
|
||||
std::function<void(model_ref&)> update_model = [&](model_ref& mdl) {
|
||||
update_assignment(mdl);
|
||||
};
|
||||
lns lns(s(), update_model);
|
||||
lns.set_conflicts(m_lns_conflicts);
|
||||
lns.climb(mdl, m_asms);
|
||||
}
|
||||
|
||||
void update_assignment(model_ref & mdl) {
|
||||
improve_model(mdl);
|
||||
mdl->set_model_completion(true);
|
||||
unsigned correction_set_size = 0;
|
||||
for (expr* a : m_asms) {
|
||||
|
@ -818,6 +842,8 @@ public:
|
|||
m_pivot_on_cs = p.maxres_pivot_on_correction_set();
|
||||
m_wmax = p.maxres_wmax();
|
||||
m_dump_benchmarks = p.dump_benchmarks();
|
||||
m_enable_lns = p.enable_lns() && m_c.sat_enabled();
|
||||
m_lns_conflicts = p.lns_conflicts();
|
||||
}
|
||||
|
||||
lbool init_local() {
|
||||
|
|
|
@ -73,9 +73,6 @@ namespace opt {
|
|||
rational m_upper;
|
||||
model_ref m_model;
|
||||
svector<symbol> m_labels;
|
||||
//const expr_ref_vector m_soft;
|
||||
//vector<rational> m_weights;
|
||||
//bool_vector m_assignment; // truth assignment to soft constraints
|
||||
params_ref m_params; // config
|
||||
|
||||
public:
|
||||
|
|
168
src/opt/opt_lns.cpp
Normal file
168
src/opt/opt_lns.cpp
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*++
|
||||
Copyright (c) 2014 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
opt_lns.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
"large" neighborhood search for maxsat problem instances.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2021-02-01
|
||||
|
||||
--*/
|
||||
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "opt/maxsmt.h"
|
||||
#include "opt/opt_lns.h"
|
||||
#include "sat/sat_params.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace opt {
|
||||
|
||||
lns::lns(solver& s, std::function<void(model_ref& mdl)>& update_model)
|
||||
: m(s.get_manager()),
|
||||
s(s),
|
||||
m_hardened(m),
|
||||
m_soft(m),
|
||||
m_update_model(update_model)
|
||||
{}
|
||||
|
||||
void lns::set_lns_params() {
|
||||
params_ref p;
|
||||
p.set_sym("phase", symbol("frozen"));
|
||||
p.set_uint("restart.initial", 1000000);
|
||||
p.set_uint("max_conflicts", m_max_conflicts);
|
||||
p.set_uint("simplify.delay", 1000000);
|
||||
s.updt_params(p);
|
||||
}
|
||||
|
||||
void lns::save_defaults(params_ref& p) {
|
||||
sat_params sp(p);
|
||||
p.set_sym("phase", sp.phase());
|
||||
p.set_uint("restart.initial", sp.restart_initial());
|
||||
p.set_uint("max_conflicts", sp.max_conflicts());
|
||||
p.set_uint("simplify.delay", sp.simplify_delay());
|
||||
}
|
||||
|
||||
unsigned lns::climb(model_ref& mdl, expr_ref_vector const& asms) {
|
||||
m_num_improves = 0;
|
||||
params_ref old_p(s.get_params());
|
||||
save_defaults(old_p);
|
||||
set_lns_params();
|
||||
setup_assumptions(mdl, asms);
|
||||
unsigned num_improved = improve_linear(mdl);
|
||||
// num_improved += improve_rotate(mdl, asms);
|
||||
s.updt_params(old_p);
|
||||
IF_VERBOSE(1, verbose_stream() << "(opt.lns :num-improves " << m_num_improves << " :remaining-soft " << m_soft.size() << ")\n");
|
||||
return num_improved;
|
||||
}
|
||||
|
||||
void lns::setup_assumptions(model_ref& mdl, expr_ref_vector const& asms) {
|
||||
m_hardened.reset();
|
||||
m_soft.reset();
|
||||
for (expr* a : asms) {
|
||||
if (mdl->is_true(a))
|
||||
m_hardened.push_back(a);
|
||||
else
|
||||
m_soft.push_back(a);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned lns::improve_rotate(model_ref& mdl, expr_ref_vector const& asms) {
|
||||
unsigned num_improved = 0;
|
||||
repeat:
|
||||
setup_assumptions(mdl, asms);
|
||||
unsigned sz = m_hardened.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
expr_ref tmp(m_hardened.get(i), m);
|
||||
m_hardened[i] = m.mk_not(tmp);
|
||||
unsigned reward = improve_linear(mdl);
|
||||
if (reward > 1) {
|
||||
num_improved += (reward - 1);
|
||||
goto repeat;
|
||||
}
|
||||
setup_assumptions(mdl, asms);
|
||||
}
|
||||
return num_improved;
|
||||
}
|
||||
|
||||
unsigned lns::improve_linear(model_ref& mdl) {
|
||||
unsigned num_improved = 0;
|
||||
unsigned max_conflicts = m_max_conflicts;
|
||||
while (m.inc()) {
|
||||
unsigned reward = improve_step(mdl);
|
||||
if (reward == 0)
|
||||
break;
|
||||
num_improved += reward;
|
||||
m_max_conflicts *= 3;
|
||||
m_max_conflicts /= 2;
|
||||
set_lns_params();
|
||||
}
|
||||
m_max_conflicts = max_conflicts;
|
||||
return num_improved;
|
||||
}
|
||||
|
||||
unsigned lns::improve_step(model_ref& mdl) {
|
||||
unsigned num_improved = 0;
|
||||
for (unsigned i = 0; m.inc() && i < m_soft.size(); ++i) {
|
||||
switch (improve_step(mdl, soft(i))) {
|
||||
case l_undef:
|
||||
break;
|
||||
case l_false:
|
||||
TRACE("opt", tout << "pruned " << mk_bounded_pp(soft(i), m) << "\n";);
|
||||
m_hardened.push_back(m.mk_not(soft(i)));
|
||||
for (unsigned k = i; k + 1 < m_soft.size(); ++k)
|
||||
m_soft[k] = soft(k + 1);
|
||||
m_soft.pop_back();
|
||||
--i;
|
||||
break;
|
||||
case l_true: {
|
||||
unsigned k = 0, offset = 0;
|
||||
for (unsigned j = 0; j < m_soft.size(); ++j) {
|
||||
if (mdl->is_true(soft(j))) {
|
||||
if (j <= i)
|
||||
++offset;
|
||||
++m_num_improves;
|
||||
TRACE("opt", tout << "improved " << mk_bounded_pp(soft(j), m) << "\n";);
|
||||
m_hardened.push_back(soft(j));
|
||||
++num_improved;
|
||||
}
|
||||
else {
|
||||
m_soft[k++] = soft(j);
|
||||
}
|
||||
}
|
||||
m_soft.shrink(k);
|
||||
i -= offset;
|
||||
IF_VERBOSE(1, verbose_stream() << "(opt.lns :num-improves " << m_num_improves << " :remaining-soft " << m_soft.size() << ")\n");
|
||||
m_update_model(mdl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return num_improved;
|
||||
}
|
||||
|
||||
lbool lns::improve_step(model_ref& mdl, expr* e) {
|
||||
m_hardened.push_back(e);
|
||||
lbool r = s.check_sat(m_hardened);
|
||||
m_hardened.pop_back();
|
||||
if (r == l_true)
|
||||
s.get_model(mdl);
|
||||
#if 0
|
||||
if (r == l_false) {
|
||||
expr_ref_vector core(m);
|
||||
s.get_unsat_core(core);
|
||||
std::cout << "core size " << core.size() << "\n";
|
||||
if (core.size() == 4)
|
||||
std::cout << core << "\n";
|
||||
}
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
};
|
52
src/opt/opt_lns.h
Normal file
52
src/opt/opt_lns.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*++
|
||||
Copyright (c) 2014 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
opt_lns.h
|
||||
|
||||
Abstract:
|
||||
|
||||
"large" neighborhood search for maxsat problem instances.
|
||||
|
||||
Start with a model that we assume satisfies at least one of the soft constraint assumptions.
|
||||
Attempt to improve the model locally by invoking the SAT solver with a phase
|
||||
fixed to be the assignment that solved the previous instance.
|
||||
Local improvement is performed by hardening each soft constraint in turn.
|
||||
The soft constraints are assumed sorted by weight, such that the highest
|
||||
weight soft constraint is first, followed by soft constraints of lower weight.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2021-02-01
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace opt {
|
||||
|
||||
class lns {
|
||||
ast_manager& m;
|
||||
solver& s;
|
||||
expr_ref_vector m_hardened;
|
||||
expr_ref_vector m_soft;
|
||||
unsigned m_max_conflicts { 1000 };
|
||||
unsigned m_num_improves { 0 };
|
||||
std::function<void(model_ref& m)> m_update_model;
|
||||
|
||||
expr* soft(unsigned i) const { return m_soft[i]; }
|
||||
void set_lns_params();
|
||||
void save_defaults(params_ref& p);
|
||||
unsigned improve_step(model_ref& mdl);
|
||||
lbool improve_step(model_ref& mdl, expr* e);
|
||||
unsigned improve_linear(model_ref& mdl);
|
||||
unsigned improve_rotate(model_ref& mdl, expr_ref_vector const& asms);
|
||||
void setup_assumptions(model_ref& mdl, expr_ref_vector const& asms);
|
||||
|
||||
public:
|
||||
lns(solver& s, std::function<void(model_ref&)>& update_model);
|
||||
void set_conflicts(unsigned c) { m_max_conflicts = c; }
|
||||
unsigned climb(model_ref& mdl, expr_ref_vector const& asms);
|
||||
};
|
||||
};
|
|
@ -9,7 +9,9 @@ def_module_params('opt',
|
|||
('solution_prefix', SYMBOL, '', "path prefix to dump intermediary, but non-optimal, solutions"),
|
||||
('timeout', UINT, UINT_MAX, 'timeout (in milliseconds) (UINT_MAX and 0 mean no timeout)'),
|
||||
('rlimit', UINT, 0, 'resource limit (0 means no limit)'),
|
||||
('enable_sls', BOOL, False, 'enable SLS tuning during weighted maxsast'),
|
||||
('enable_sls', BOOL, False, 'enable SLS tuning during weighted maxsat'),
|
||||
('enable_lns', BOOL, False, 'enable LNS during weighted maxsat'),
|
||||
('lns_conflicts', UINT, 1000, 'initial conflict count for LNS search'),
|
||||
('enable_sat', BOOL, True, 'enable the new SAT core for propositional constraints'),
|
||||
('elim_01', BOOL, True, 'eliminate 01 variables'),
|
||||
('pp.neat', BOOL, True, 'use neat (as opposed to less readable, but faster) pretty printer when displaying context'),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue