mirror of
https://github.com/Z3Prover/z3
synced 2025-06-23 06:13:40 +00:00
adding options to maxres for experiments, include option to pretty print module parameters in smt2 style
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
b45b2872d8
commit
83a7d1a658
14 changed files with 249 additions and 131 deletions
|
@ -62,6 +62,7 @@ Notes:
|
||||||
#include "inc_sat_solver.h"
|
#include "inc_sat_solver.h"
|
||||||
#include "opt_context.h"
|
#include "opt_context.h"
|
||||||
#include "pb_decl_plugin.h"
|
#include "pb_decl_plugin.h"
|
||||||
|
#include "opt_params.hpp"
|
||||||
|
|
||||||
|
|
||||||
using namespace opt;
|
using namespace opt;
|
||||||
|
@ -85,9 +86,14 @@ private:
|
||||||
expr_ref_vector m_trail;
|
expr_ref_vector m_trail;
|
||||||
strategy_t m_st;
|
strategy_t m_st;
|
||||||
rational m_max_upper;
|
rational m_max_upper;
|
||||||
bool m_hill_climb;
|
bool m_hill_climb; // prefer large weight soft clauses for cores
|
||||||
bool m_all_cores;
|
bool m_add_upper_bound_block; // restrict upper bound with constraint
|
||||||
bool m_add_upper_bound_block;
|
unsigned m_max_num_cores; // max number of cores per round.
|
||||||
|
unsigned m_max_core_size; // max core size per round.
|
||||||
|
bool m_maximize_assignment; // maximize assignment to find MCS
|
||||||
|
unsigned m_max_correction_set_size;// maximal set of correction set that is tolerated.
|
||||||
|
bool m_wmax; // Block upper bound using wmax
|
||||||
|
// this option is disabled if SAT core is used.
|
||||||
|
|
||||||
typedef ptr_vector<expr> exprs;
|
typedef ptr_vector<expr> exprs;
|
||||||
|
|
||||||
|
@ -102,8 +108,11 @@ public:
|
||||||
m_trail(m),
|
m_trail(m),
|
||||||
m_st(st),
|
m_st(st),
|
||||||
m_hill_climb(true),
|
m_hill_climb(true),
|
||||||
m_all_cores(false),
|
m_add_upper_bound_block(false),
|
||||||
m_add_upper_bound_block(false)
|
m_max_num_cores(UINT_MAX),
|
||||||
|
m_max_core_size(3),
|
||||||
|
m_maximize_assignment(false),
|
||||||
|
m_max_correction_set_size(3)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,14 +210,11 @@ public:
|
||||||
return l_true;
|
return l_true;
|
||||||
case l_true:
|
case l_true:
|
||||||
SASSERT(cores.empty() || mcs.empty());
|
SASSERT(cores.empty() || mcs.empty());
|
||||||
for (unsigned i = 0; is_sat == l_true && i < cores.size(); ++i) {
|
for (unsigned i = 0; i < cores.size(); ++i) {
|
||||||
is_sat = process_unsat(cores[i]);
|
process_unsat(cores[i]);
|
||||||
}
|
}
|
||||||
if (is_sat == l_true && cores.empty()) {
|
if (cores.empty()) {
|
||||||
is_sat = process_sat(mcs);
|
process_sat(mcs);
|
||||||
}
|
|
||||||
if (is_sat != l_true) {
|
|
||||||
return is_sat;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -233,7 +239,7 @@ public:
|
||||||
mcs.reset();
|
mcs.reset();
|
||||||
s().get_model(mdl);
|
s().get_model(mdl);
|
||||||
update_assignment(mdl.get());
|
update_assignment(mdl.get());
|
||||||
is_sat = get_mss(cores, mss, mcs);
|
is_sat = get_mss(mdl.get(), cores, mss, mcs);
|
||||||
|
|
||||||
switch (is_sat) {
|
switch (is_sat) {
|
||||||
case l_undef:
|
case l_undef:
|
||||||
|
@ -242,11 +248,8 @@ public:
|
||||||
m_lower = m_upper;
|
m_lower = m_upper;
|
||||||
return l_true;
|
return l_true;
|
||||||
case l_true: {
|
case l_true: {
|
||||||
is_sat = process_sat(mcs);
|
process_sat(mcs);
|
||||||
if (is_sat != l_true) {
|
get_mss_model();
|
||||||
return is_sat;
|
|
||||||
}
|
|
||||||
update_mss_model();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,11 +285,14 @@ public:
|
||||||
- suppose that cost of cores adds up to current upper bound.
|
- suppose that cost of cores adds up to current upper bound.
|
||||||
-> it means that each core is a unit (?)
|
-> it means that each core is a unit (?)
|
||||||
|
|
||||||
|
TBD:
|
||||||
|
- Block upper bound using wmax or pb constraint, or in case of
|
||||||
|
unweighted constraints using incremental tricks.
|
||||||
|
- Throttle when correction set gets added based on its size.
|
||||||
|
Suppose correction set is huge. Do we really need it?
|
||||||
|
|
||||||
*/
|
*/
|
||||||
lbool mus_mss2_solver() {
|
lbool mus_mss2_solver() {
|
||||||
// m_all_cores = true;
|
|
||||||
// m_add_upper_bound_block = true;
|
|
||||||
bool maximize_assignment = false;
|
|
||||||
init();
|
init();
|
||||||
init_local();
|
init_local();
|
||||||
sls();
|
sls();
|
||||||
|
@ -324,39 +330,43 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// There is a best model,
|
// There is a best model, retrieve
|
||||||
// retrieve it from the previous
|
// it from the previous core calls.
|
||||||
// core calls.
|
|
||||||
//
|
//
|
||||||
update_mus_model();
|
model_ref mdl;
|
||||||
|
get_mus_model(mdl);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Extend the current model to a (maximal)
|
// Extend the current model to a (maximal)
|
||||||
// assignment extracting the ss and cs.
|
// assignment extracting the ss and cs.
|
||||||
// ss - satisfying subset
|
// ss - satisfying subset
|
||||||
// cs - correction set (complement of ss).
|
// cs - correction set (complement of ss).
|
||||||
//
|
//
|
||||||
if (maximize_assignment) {
|
if (m_maximize_assignment && mdl.get()) {
|
||||||
exprs ss, cs;
|
exprs ss, cs;
|
||||||
// TBD: current model has to evaluate all auxiliary predicates.
|
is_sat = get_mss(mdl.get(), cores, ss, cs);
|
||||||
is_sat = get_mss(cores, ss, cs);
|
|
||||||
if (is_sat != l_true) return is_sat;
|
if (is_sat != l_true) return is_sat;
|
||||||
update_mss_model();
|
get_mss_model();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// block the hard constraints corresponding to the cores.
|
// block the hard constraints corresponding to the cores.
|
||||||
// block the soft constraints corresponding to the cs
|
// block the soft constraints corresponding to the cs
|
||||||
// obtained from the current best model.
|
// obtained from the current best model.
|
||||||
//
|
//
|
||||||
// TBD: model must be updated with definitions for the
|
|
||||||
// fresh variables.
|
|
||||||
//
|
//
|
||||||
is_sat = process_unsat(cores);
|
// TBD: throttle blocking on correction sets if they are too big.
|
||||||
if (is_sat != l_true) return is_sat;
|
// likewise, if the cores are too big, don't block the cores.
|
||||||
|
//
|
||||||
|
|
||||||
|
process_unsat(cores);
|
||||||
|
|
||||||
exprs cs;
|
exprs cs;
|
||||||
get_current_correction_set(cs);
|
get_current_correction_set(cs);
|
||||||
is_sat = process_sat(cs);
|
unsigned max_core = max_core_size(cores);
|
||||||
if (is_sat != l_true) return is_sat;
|
if (cs.size() <= std::max(max_core, m_max_correction_set_size)) {
|
||||||
|
process_sat(cs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lower = m_upper;
|
m_lower = m_upper;
|
||||||
|
@ -404,8 +414,15 @@ public:
|
||||||
if (is_sat != l_true) {
|
if (is_sat != l_true) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (core.empty()) {
|
||||||
|
cores.reset();
|
||||||
|
return l_false;
|
||||||
|
}
|
||||||
cores.push_back(core);
|
cores.push_back(core);
|
||||||
if (!m_all_cores && core.size() >= 3) {
|
if (core.size() >= m_max_core_size) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cores.size() >= m_max_num_cores) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
remove_soft(core, asms);
|
remove_soft(core, asms);
|
||||||
|
@ -442,7 +459,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_current_correction_set(exprs& cs) {
|
void get_current_correction_set(exprs& cs) {
|
||||||
TRACE("opt", display_vec(tout << "old correction set: ", cs.size(), cs.c_ptr()););
|
|
||||||
cs.reset();
|
cs.reset();
|
||||||
for (unsigned i = 0; i < m_asms.size(); ++i) {
|
for (unsigned i = 0; i < m_asms.size(); ++i) {
|
||||||
if (!is_true(m_asms[i].get())) {
|
if (!is_true(m_asms[i].get())) {
|
||||||
|
@ -482,13 +498,12 @@ public:
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool process_sat(exprs const& corr_set) {
|
void process_sat(exprs const& corr_set) {
|
||||||
expr_ref fml(m), tmp(m);
|
expr_ref fml(m), tmp(m);
|
||||||
TRACE("opt", display_vec(tout << "corr_set: ", corr_set.size(), corr_set.c_ptr()););
|
TRACE("opt", display_vec(tout << "corr_set: ", corr_set.size(), corr_set.c_ptr()););
|
||||||
remove_core(corr_set);
|
remove_core(corr_set);
|
||||||
rational w = split_core(corr_set);
|
rational w = split_core(corr_set);
|
||||||
cs_max_resolve(corr_set, w);
|
cs_max_resolve(corr_set, w);
|
||||||
return l_true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool process_unsat() {
|
lbool process_unsat() {
|
||||||
|
@ -501,19 +516,26 @@ public:
|
||||||
return l_false;
|
return l_false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return process_unsat(cores);
|
process_unsat(cores);
|
||||||
|
return l_true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool process_unsat(vector<exprs>& cores) {
|
unsigned max_core_size(vector<exprs> const& cores) {
|
||||||
lbool is_sat = l_true;
|
unsigned result = 0;
|
||||||
for (unsigned i = 0; is_sat == l_true && i < cores.size(); ++i) {
|
for (unsigned i = 0; i < cores.size(); ++i) {
|
||||||
is_sat = process_unsat(cores[i]);
|
result = std::max(cores[i].size(), result);
|
||||||
}
|
}
|
||||||
return is_sat;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool process_unsat(exprs const& core) {
|
void process_unsat(vector<exprs> const& cores) {
|
||||||
|
for (unsigned i = 0; i < cores.size(); ++i) {
|
||||||
|
process_unsat(cores[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_unsat(exprs const& core) {
|
||||||
expr_ref fml(m);
|
expr_ref fml(m);
|
||||||
remove_core(core);
|
remove_core(core);
|
||||||
SASSERT(!core.empty());
|
SASSERT(!core.empty());
|
||||||
|
@ -524,31 +546,35 @@ public:
|
||||||
s().assert_expr(fml);
|
s().assert_expr(fml);
|
||||||
m_lower += w;
|
m_lower += w;
|
||||||
IF_VERBOSE(1, verbose_stream() << "(opt.maxres [" << m_lower << ":" << m_upper << "])\n";);
|
IF_VERBOSE(1, verbose_stream() << "(opt.maxres [" << m_lower << ":" << m_upper << "])\n";);
|
||||||
return l_true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_mus_model() {
|
void get_mus_model(model_ref& mdl) {
|
||||||
if (!m_c.sat_enabled()) {
|
rational w(0);
|
||||||
model_ref mdl;
|
if (m_c.sat_enabled()) {
|
||||||
rational w = m_mus.get_best_model(mdl);
|
// SAT solver core extracts some model
|
||||||
if (mdl.get() && w < m_upper) {
|
// during unsat core computation.
|
||||||
update_assignment(mdl.get());
|
s().get_model(mdl);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
w = m_mus.get_best_model(mdl);
|
||||||
|
}
|
||||||
|
if (mdl.get() && w < m_upper) {
|
||||||
|
update_assignment(mdl.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_mss_model() {
|
void get_mss_model() {
|
||||||
model_ref mdl;
|
model_ref mdl;
|
||||||
m_mss.get_model(mdl); // last model is best way to reduce search space.
|
m_mss.get_model(mdl); // last model is best way to reduce search space.
|
||||||
update_assignment(mdl.get());
|
update_assignment(mdl.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool get_mss(vector<exprs> const& cores, exprs& literals, exprs& mcs) {
|
lbool get_mss(model* mdl, vector<exprs> const& cores, exprs& literals, exprs& mcs) {
|
||||||
literals.reset();
|
literals.reset();
|
||||||
mcs.reset();
|
mcs.reset();
|
||||||
literals.append(m_asms.size(), m_asms.c_ptr());
|
literals.append(m_asms.size(), m_asms.c_ptr());
|
||||||
set_mus(false);
|
set_mus(false);
|
||||||
lbool is_sat = m_mss(m_model.get(), cores, literals, mcs);
|
lbool is_sat = m_mss(mdl, cores, literals, mcs);
|
||||||
set_mus(true);
|
set_mus(true);
|
||||||
return is_sat;
|
return is_sat;
|
||||||
}
|
}
|
||||||
|
@ -735,7 +761,7 @@ public:
|
||||||
if (is_sat != l_true) {
|
if (is_sat != l_true) {
|
||||||
return is_sat;
|
return is_sat;
|
||||||
}
|
}
|
||||||
update_mss_model();
|
get_mss_model();
|
||||||
if (!cores.empty() && mcs.size() > cores.back().size()) {
|
if (!cores.empty() && mcs.size() > cores.back().size()) {
|
||||||
mcs.reset();
|
mcs.reset();
|
||||||
}
|
}
|
||||||
|
@ -804,16 +830,19 @@ public:
|
||||||
IF_VERBOSE(1, verbose_stream() <<
|
IF_VERBOSE(1, verbose_stream() <<
|
||||||
"(opt.maxres [" << m_lower << ":" << m_upper << "])\n";);
|
"(opt.maxres [" << m_lower << ":" << m_upper << "])\n";);
|
||||||
|
|
||||||
if (m_add_upper_bound_block) {
|
add_upper_bound_block();
|
||||||
pb_util u(m);
|
}
|
||||||
expr_ref_vector nsoft(m);
|
|
||||||
expr_ref fml(m);
|
void add_upper_bound_block() {
|
||||||
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
if (!m_add_upper_bound_block) return;
|
||||||
nsoft.push_back(m.mk_not(m_soft[i].get()));
|
pb_util u(m);
|
||||||
}
|
expr_ref_vector nsoft(m);
|
||||||
fml = u.mk_lt(nsoft.size(), m_weights.c_ptr(), nsoft.c_ptr(), m_upper);
|
expr_ref fml(m);
|
||||||
s().assert_expr(fml);
|
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
||||||
|
nsoft.push_back(m.mk_not(m_soft[i].get()));
|
||||||
}
|
}
|
||||||
|
fml = u.mk_lt(nsoft.size(), m_weights.c_ptr(), nsoft.c_ptr(), m_upper);
|
||||||
|
s().assert_expr(fml);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_true(expr* e) {
|
bool is_true(expr* e) {
|
||||||
|
@ -845,6 +874,19 @@ public:
|
||||||
m_mus.set_cancel(f);
|
m_mus.set_cancel(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void updt_params(params_ref& p) {
|
||||||
|
maxsmt_solver_base::updt_params(p);
|
||||||
|
opt_params _p(p);
|
||||||
|
|
||||||
|
m_hill_climb = _p.maxres_hill_climb();
|
||||||
|
m_add_upper_bound_block = _p.maxres_add_upper_bound_block();
|
||||||
|
m_max_num_cores = _p.maxres_max_num_cores();
|
||||||
|
m_max_core_size = _p.maxres_max_core_size();
|
||||||
|
m_maximize_assignment = _p.maxres_maximize_assignment();
|
||||||
|
m_max_correction_set_size = _p.maxres_max_correction_set_size();
|
||||||
|
m_wmax = _p.maxres_wmax();
|
||||||
|
}
|
||||||
|
|
||||||
void init_local() {
|
void init_local() {
|
||||||
m_upper.reset();
|
m_upper.reset();
|
||||||
m_lower.reset();
|
m_lower.reset();
|
||||||
|
@ -853,6 +895,7 @@ public:
|
||||||
add_soft(m_soft[i].get(), m_weights[i]);
|
add_soft(m_soft[i].get(), m_weights[i]);
|
||||||
}
|
}
|
||||||
m_max_upper = m_upper;
|
m_max_upper = m_upper;
|
||||||
|
add_upper_bound_block();
|
||||||
}
|
}
|
||||||
|
|
||||||
void verify_assignment() {
|
void verify_assignment() {
|
||||||
|
|
|
@ -30,6 +30,7 @@ Notes:
|
||||||
#include "ast_pp.h"
|
#include "ast_pp.h"
|
||||||
#include "uint_set.h"
|
#include "uint_set.h"
|
||||||
#include "opt_context.h"
|
#include "opt_context.h"
|
||||||
|
#include "theory_wmaxsat.h"
|
||||||
|
|
||||||
|
|
||||||
namespace opt {
|
namespace opt {
|
||||||
|
@ -108,6 +109,40 @@ namespace opt {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
smt::theory_wmaxsat* maxsmt_solver_base::get_wmax_theory() const {
|
||||||
|
smt::theory_id th_id = m.get_family_id("weighted_maxsat");
|
||||||
|
smt::theory* th = m_c.smt_context().get_theory(th_id);
|
||||||
|
if (th) {
|
||||||
|
return dynamic_cast<smt::theory_wmaxsat*>(th);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
smt::theory_wmaxsat* maxsmt_solver_base::ensure_wmax_theory() {
|
||||||
|
smt::theory_wmaxsat* wth = get_wmax_theory();
|
||||||
|
if (wth) {
|
||||||
|
wth->reset_local();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wth = alloc(smt::theory_wmaxsat, m, m_c.fm());
|
||||||
|
m_c.smt_context().register_plugin(wth);
|
||||||
|
}
|
||||||
|
return wth;
|
||||||
|
}
|
||||||
|
|
||||||
|
maxsmt_solver_base::scoped_ensure_theory::scoped_ensure_theory(maxsmt_solver_base& s) {
|
||||||
|
m_wth = s.ensure_wmax_theory();
|
||||||
|
}
|
||||||
|
maxsmt_solver_base::scoped_ensure_theory::~scoped_ensure_theory() {
|
||||||
|
//m_wth->reset();
|
||||||
|
}
|
||||||
|
smt::theory_wmaxsat& maxsmt_solver_base::scoped_ensure_theory::operator()() { return *m_wth; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
maxsmt::maxsmt(context& c):
|
maxsmt::maxsmt(context& c):
|
||||||
m_s(c.get_solver()), m(c.get_manager()), m_c(c), m_cancel(false),
|
m_s(c.get_solver()), m(c.get_manager()), m_c(c), m_cancel(false),
|
||||||
m_soft_constraints(m), m_answer(m) {}
|
m_soft_constraints(m), m_answer(m) {}
|
||||||
|
@ -160,6 +195,7 @@ namespace opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_msolver) {
|
if (m_msolver) {
|
||||||
|
m_msolver->updt_params(m_params);
|
||||||
is_sat = (*m_msolver)();
|
is_sat = (*m_msolver)();
|
||||||
if (is_sat != l_false) {
|
if (is_sat != l_false) {
|
||||||
m_msolver->get_model(m_model);
|
m_msolver->get_model(m_model);
|
||||||
|
|
|
@ -24,6 +24,9 @@ Notes:
|
||||||
#include"solver.h"
|
#include"solver.h"
|
||||||
#include"filter_model_converter.h"
|
#include"filter_model_converter.h"
|
||||||
#include"statistics.h"
|
#include"statistics.h"
|
||||||
|
#include"smt_context.h"
|
||||||
|
#include"smt_theory.h"
|
||||||
|
#include"theory_wmaxsat.h"
|
||||||
|
|
||||||
namespace opt {
|
namespace opt {
|
||||||
|
|
||||||
|
@ -82,6 +85,18 @@ namespace opt {
|
||||||
expr* mk_not(expr* e);
|
expr* mk_not(expr* e);
|
||||||
void set_mus(bool f);
|
void set_mus(bool f);
|
||||||
app* mk_fresh_bool(char const* name);
|
app* mk_fresh_bool(char const* name);
|
||||||
|
|
||||||
|
class smt::theory_wmaxsat* get_wmax_theory() const;
|
||||||
|
smt::theory_wmaxsat* ensure_wmax_theory();
|
||||||
|
class scoped_ensure_theory {
|
||||||
|
smt::theory_wmaxsat* m_wth;
|
||||||
|
public:
|
||||||
|
scoped_ensure_theory(maxsmt_solver_base& s);
|
||||||
|
~scoped_ensure_theory();
|
||||||
|
smt::theory_wmaxsat& operator()();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void enable_sls(expr_ref_vector const& soft, weights_t& ws);
|
void enable_sls(expr_ref_vector const& soft, weights_t& ws);
|
||||||
void set_enable_sls(bool f);
|
void set_enable_sls(bool f);
|
||||||
|
|
|
@ -1157,6 +1157,11 @@ namespace opt {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
param_descrs descrs;
|
||||||
|
collect_param_descrs(descrs);
|
||||||
|
m_params.display_smt2(out, "opt", descrs);
|
||||||
|
|
||||||
out << "(check-sat)\n";
|
out << "(check-sat)\n";
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,14 @@ def_module_params('opt',
|
||||||
('enable_sls', BOOL, False, 'enable SLS tuning during weighted maxsast'),
|
('enable_sls', BOOL, False, 'enable SLS tuning during weighted maxsast'),
|
||||||
('enable_sat', BOOL, False, 'enable the new SAT core for propositional constraints'),
|
('enable_sat', BOOL, False, 'enable the new SAT core for propositional constraints'),
|
||||||
('elim_01', BOOL, True, 'eliminate 01 variables'),
|
('elim_01', BOOL, True, 'eliminate 01 variables'),
|
||||||
('pb.compile_equality', BOOL, False, 'compile arithmetical equalities into pseudo-Boolean equality (instead of two inequalites)')
|
('pb.compile_equality', BOOL, False, 'compile arithmetical equalities into pseudo-Boolean equality (instead of two inequalites)'),
|
||||||
|
('maxres.hill_climb', BOOL, True, 'give preference for large weight cores'),
|
||||||
|
('maxres.add_upper_bound_block', BOOL, False, 'restict upper bound with constraint'),
|
||||||
|
('maxres.max_num_cores', UINT, UINT_MAX, 'maximal number of cores per round'),
|
||||||
|
('maxres.max_core_size', UINT, 3, 'break batch of generated cores if size reaches this number'),
|
||||||
|
('maxres.maximize_assignment', BOOL, False, 'find an MSS/MCS to improve current assignment'),
|
||||||
|
('maxres.max_correction_set_size', UINT, 3, 'allow generating correction set constraints up to maximal size'),
|
||||||
|
('maxres.wmax', BOOL, False, 'use weighted theory solver to constrain upper bounds')
|
||||||
|
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
@ -26,59 +26,15 @@ Notes:
|
||||||
#include "opt_context.h"
|
#include "opt_context.h"
|
||||||
|
|
||||||
namespace opt {
|
namespace opt {
|
||||||
class maxsmt_solver_wbase : public maxsmt_solver_base {
|
|
||||||
smt::context& ctx;
|
|
||||||
public:
|
|
||||||
maxsmt_solver_wbase(context& c,
|
|
||||||
vector<rational> const& ws, expr_ref_vector const& soft):
|
|
||||||
maxsmt_solver_base(c, ws, soft), ctx(c.smt_context()) {}
|
|
||||||
~maxsmt_solver_wbase() {}
|
|
||||||
|
|
||||||
class scoped_ensure_theory {
|
|
||||||
smt::theory_wmaxsat* m_wth;
|
|
||||||
public:
|
|
||||||
scoped_ensure_theory(maxsmt_solver_wbase& s) {
|
|
||||||
m_wth = s.ensure_theory();
|
|
||||||
}
|
|
||||||
~scoped_ensure_theory() {
|
|
||||||
m_wth->reset();
|
|
||||||
}
|
|
||||||
smt::theory_wmaxsat& operator()() { return *m_wth; }
|
|
||||||
};
|
|
||||||
|
|
||||||
smt::theory_wmaxsat* ensure_theory() {
|
|
||||||
smt::theory_wmaxsat* wth = get_theory();
|
|
||||||
if (wth) {
|
|
||||||
wth->reset();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
wth = alloc(smt::theory_wmaxsat, m, m_c.fm());
|
|
||||||
ctx.register_plugin(wth);
|
|
||||||
}
|
|
||||||
return wth;
|
|
||||||
}
|
|
||||||
smt::theory_wmaxsat* get_theory() const {
|
|
||||||
smt::theory_id th_id = m.get_family_id("weighted_maxsat");
|
|
||||||
smt::theory* th = ctx.get_theory(th_id);
|
|
||||||
if (th) {
|
|
||||||
return dynamic_cast<smt::theory_wmaxsat*>(th);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
||||||
// weighted max-sat using a custom theory solver for max-sat.
|
// weighted max-sat using a custom theory solver for max-sat.
|
||||||
// NB. it is quite similar to pseudo-Boolean propagation.
|
// NB. it is quite similar to pseudo-Boolean propagation.
|
||||||
|
|
||||||
|
|
||||||
class wmax : public maxsmt_solver_wbase {
|
class wmax : public maxsmt_solver_base {
|
||||||
public:
|
public:
|
||||||
wmax(context& c,
|
wmax(context& c, weights_t& ws, expr_ref_vector const& soft):
|
||||||
vector<rational> const& ws, expr_ref_vector const& soft):
|
maxsmt_solver_base(c, ws, soft) {}
|
||||||
maxsmt_solver_wbase(c, ws, soft) {}
|
|
||||||
virtual ~wmax() {}
|
virtual ~wmax() {}
|
||||||
|
|
||||||
lbool operator()() {
|
lbool operator()() {
|
||||||
|
@ -90,7 +46,6 @@ namespace opt {
|
||||||
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
||||||
wth().assert_weighted(m_soft[i].get(), m_weights[i]);
|
wth().assert_weighted(m_soft[i].get(), m_weights[i]);
|
||||||
}
|
}
|
||||||
solver::scoped_push _s2(s());
|
|
||||||
while (l_true == is_sat) {
|
while (l_true == is_sat) {
|
||||||
is_sat = s().check_sat(0,0);
|
is_sat = s().check_sat(0,0);
|
||||||
if (m_cancel) {
|
if (m_cancel) {
|
||||||
|
@ -122,8 +77,7 @@ namespace opt {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
maxsmt_solver_base* mk_wmax(context& c,
|
maxsmt_solver_base* mk_wmax(context& c, weights_t& ws, expr_ref_vector const& soft) {
|
||||||
vector<rational> const& ws, expr_ref_vector const& soft) {
|
|
||||||
return alloc(wmax, c, ws, soft);
|
return alloc(wmax, c, ws, soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,7 @@ Notes:
|
||||||
#include "maxsmt.h"
|
#include "maxsmt.h"
|
||||||
|
|
||||||
namespace opt {
|
namespace opt {
|
||||||
maxsmt_solver_base* mk_wmax(context& c,
|
maxsmt_solver_base* mk_wmax(context& c, weights_t & ws, expr_ref_vector const& soft);
|
||||||
vector<rational> const& ws, expr_ref_vector const& soft);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace sat {
|
||||||
void mus::reset() {
|
void mus::reset() {
|
||||||
m_core.reset();
|
m_core.reset();
|
||||||
m_mus.reset();
|
m_mus.reset();
|
||||||
|
m_model.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mus::set_core() {
|
void mus::set_core() {
|
||||||
|
@ -88,6 +89,9 @@ namespace sat {
|
||||||
if (!core.empty()) {
|
if (!core.empty()) {
|
||||||
// mr(); // TBD: measure
|
// mr(); // TBD: measure
|
||||||
}
|
}
|
||||||
|
if (m_model.empty()) {
|
||||||
|
m_model.append(s.m_model);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case l_false:
|
case l_false:
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace sat {
|
||||||
literal_vector m_core;
|
literal_vector m_core;
|
||||||
literal_vector m_mus;
|
literal_vector m_mus;
|
||||||
bool m_is_active;
|
bool m_is_active;
|
||||||
|
model m_model; // model obtained during minimal unsat core
|
||||||
|
|
||||||
|
|
||||||
solver& s;
|
solver& s;
|
||||||
public:
|
public:
|
||||||
|
@ -31,6 +33,7 @@ namespace sat {
|
||||||
~mus();
|
~mus();
|
||||||
lbool operator()();
|
lbool operator()();
|
||||||
bool is_active() const { return m_is_active; }
|
bool is_active() const { return m_is_active; }
|
||||||
|
model const& get_model() const { return m_model; }
|
||||||
private:
|
private:
|
||||||
lbool mus2();
|
lbool mus2();
|
||||||
void mr();
|
void mr();
|
||||||
|
|
|
@ -1736,6 +1736,8 @@ namespace sat {
|
||||||
// initial experiment suggests it has no effect.
|
// initial experiment suggests it has no effect.
|
||||||
|
|
||||||
m_mus(); // ignore return value on cancelation.
|
m_mus(); // ignore return value on cancelation.
|
||||||
|
m_model.reset();
|
||||||
|
m_model.append(m_mus.get_model());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,6 +164,10 @@ final_check_status theory_wmaxsat::final_check_eh() {
|
||||||
|
|
||||||
void theory_wmaxsat::reset_eh() {
|
void theory_wmaxsat::reset_eh() {
|
||||||
theory::reset_eh();
|
theory::reset_eh();
|
||||||
|
reset_local();
|
||||||
|
}
|
||||||
|
|
||||||
|
void theory_wmaxsat::reset_local() {
|
||||||
m_vars.reset();
|
m_vars.reset();
|
||||||
m_fmls.reset();
|
m_fmls.reset();
|
||||||
m_rweights.reset();
|
m_rweights.reset();
|
||||||
|
|
|
@ -17,6 +17,9 @@ Notes:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
#ifndef _THEORY_WMAXSAT_H_
|
||||||
|
#define _THEORY_WMAXSAT_H_
|
||||||
|
|
||||||
#include "smt_theory.h"
|
#include "smt_theory.h"
|
||||||
#include "smt_clause.h"
|
#include "smt_clause.h"
|
||||||
#include "filter_model_converter.h"
|
#include "filter_model_converter.h"
|
||||||
|
@ -84,9 +87,7 @@ namespace smt {
|
||||||
virtual bool build_models() const {
|
virtual bool build_models() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void reset() {
|
void reset_local();
|
||||||
reset_eh();
|
|
||||||
}
|
|
||||||
virtual void reset_eh();
|
virtual void reset_eh();
|
||||||
virtual theory * mk_fresh(context * new_ctx) { return 0; }
|
virtual theory * mk_fresh(context * new_ctx) { return 0; }
|
||||||
virtual bool internalize_atom(app * atom, bool gate_ctx) { return false; }
|
virtual bool internalize_atom(app * atom, bool gate_ctx) { return false; }
|
||||||
|
@ -123,3 +124,5 @@ namespace smt {
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -351,7 +351,7 @@ public:
|
||||||
out << " " << it->first;
|
out << " " << it->first;
|
||||||
switch (it->second.m_kind) {
|
switch (it->second.m_kind) {
|
||||||
case CPK_BOOL:
|
case CPK_BOOL:
|
||||||
out << " " << it->second.m_bool_value;
|
out << " " << (it->second.m_bool_value?"true":"false");
|
||||||
break;
|
break;
|
||||||
case CPK_UINT:
|
case CPK_UINT:
|
||||||
out << " " <<it->second.m_uint_value;
|
out << " " <<it->second.m_uint_value;
|
||||||
|
@ -376,6 +376,41 @@ public:
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void display_smt2(std::ostream & out, char const* module, param_descrs& descrs) const {
|
||||||
|
svector<params::entry>::const_iterator it = m_entries.begin();
|
||||||
|
svector<params::entry>::const_iterator end = m_entries.end();
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
if (!descrs.contains(it->first)) continue;
|
||||||
|
out << "(set-option :";
|
||||||
|
out << module << ".";
|
||||||
|
out << it->first;
|
||||||
|
switch (it->second.m_kind) {
|
||||||
|
case CPK_BOOL:
|
||||||
|
out << " " << (it->second.m_bool_value?"true":"false");
|
||||||
|
break;
|
||||||
|
case CPK_UINT:
|
||||||
|
out << " " <<it->second.m_uint_value;
|
||||||
|
break;
|
||||||
|
case CPK_DOUBLE:
|
||||||
|
out << " " << it->second.m_double_value;
|
||||||
|
break;
|
||||||
|
case CPK_NUMERAL:
|
||||||
|
out << " " << *(it->second.m_rat_value);
|
||||||
|
break;
|
||||||
|
case CPK_SYMBOL:
|
||||||
|
out << " " << symbol::mk_symbol_from_c_ptr(it->second.m_sym_value);
|
||||||
|
break;
|
||||||
|
case CPK_STRING:
|
||||||
|
out << " " << it->second.m_str_value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out << ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void display(std::ostream & out, symbol const & k) const {
|
void display(std::ostream & out, symbol const & k) const {
|
||||||
svector<params::entry>::const_iterator it = m_entries.begin();
|
svector<params::entry>::const_iterator it = m_entries.begin();
|
||||||
svector<params::entry>::const_iterator end = m_entries.end();
|
svector<params::entry>::const_iterator end = m_entries.end();
|
||||||
|
@ -427,6 +462,13 @@ void params_ref::display(std::ostream & out) const {
|
||||||
out << "(params)";
|
out << "(params)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void params_ref::display_smt2(std::ostream& out, char const* module, param_descrs& descrs) const {
|
||||||
|
if (m_params)
|
||||||
|
m_params->display_smt2(out, module, descrs);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void params_ref::display(std::ostream & out, char const * k) const {
|
void params_ref::display(std::ostream & out, char const * k) const {
|
||||||
display(out, symbol(k));
|
display(out, symbol(k));
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ public:
|
||||||
void set_sym(char const * k, symbol const & v);
|
void set_sym(char const * k, symbol const & v);
|
||||||
|
|
||||||
void display(std::ostream & out) const;
|
void display(std::ostream & out) const;
|
||||||
|
void display_smt2(std::ostream& out, char const* module, param_descrs& module_desc) const;
|
||||||
|
|
||||||
void validate(param_descrs const & p) const;
|
void validate(param_descrs const & p) const;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue