3
0
Fork 0
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:
Nikolaj Bjorner 2021-02-02 03:58:19 -08:00
parent c623e2db28
commit 4455f6caf8
36 changed files with 391 additions and 90 deletions

View file

@ -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

View file

@ -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() {

View file

@ -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
View 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
View 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);
};
};

View file

@ -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'),