3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-17 08:42:15 +00:00

merge with master

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2018-03-25 14:57:01 -07:00
commit c513f3ca09
883 changed files with 13979 additions and 16480 deletions

View file

@ -2,7 +2,6 @@ z3_add_component(opt
SOURCES
maxres.cpp
maxsmt.cpp
mss.cpp
opt_cmds.cpp
opt_context.cpp
opt_lns.cpp

View file

@ -64,7 +64,7 @@ Notes:
#include "opt/opt_params.hpp"
#include "opt/maxsmt.h"
#include "opt/maxres.h"
#include "opt/mss.h"
// #include "opt/mss.h"
using namespace opt;
@ -91,7 +91,6 @@ private:
obj_map<expr, rational> m_asm2weight;
ptr_vector<expr> m_new_core;
mus m_mus;
mss m_mss;
expr_ref_vector m_trail;
strategy_t m_st;
rational m_max_upper;
@ -122,7 +121,6 @@ public:
m_index(index),
m_B(m), m_asms(m), m_defs(m),
m_mus(c.get_solver()),
m_mss(c.get_solver(), m),
m_trail(m),
m_st(st),
m_correction_set_size(0),
@ -244,7 +242,7 @@ public:
case l_true:
get_current_correction_set(cs);
if (cs.empty()) {
m_found_feasible_optimum = m_model.get() != 0;
m_found_feasible_optimum = m_model.get() != nullptr;
m_lower = m_upper;
}
else {
@ -448,7 +446,7 @@ public:
rational w = split_core(corr_set);
cs_max_resolve(corr_set, w);
IF_VERBOSE(2, verbose_stream() << "(opt.maxres.correction-set " << corr_set.size() << ")\n";);
m_csmodel = 0;
m_csmodel = nullptr;
m_correction_set_size = 0;
}
@ -493,7 +491,7 @@ public:
}
void process_unsat(exprs const& core) {
IF_VERBOSE(3, verbose_stream() << "(maxres cs model valid: " << (m_csmodel.get() != 0) << " cs size:" << m_correction_set_size << " core: " << core.size() << ")\n";);
IF_VERBOSE(3, verbose_stream() << "(maxres cs model valid: " << (m_csmodel.get() != nullptr) << " cs size:" << m_correction_set_size << " core: " << core.size() << ")\n";);
expr_ref fml(m);
remove_core(core);
SASSERT(!core.empty());
@ -529,7 +527,7 @@ public:
if (m_c.sat_enabled()) {
// SAT solver core extracts some model
// during unsat core computation.
mdl = 0;
mdl = nullptr;
s().get_model(mdl);
}
else {
@ -538,7 +536,7 @@ public:
if (mdl.get() && w < m_upper) {
update_assignment(mdl.get());
}
return 0 != mdl.get();
return nullptr != mdl.get();
}
lbool minimize_core(exprs& core) {
@ -728,7 +726,7 @@ public:
}
}
if (upper >= m_upper) {
if (upper > m_upper) {
return;
}
@ -737,6 +735,7 @@ public:
}
m_model = mdl;
m_c.model_updated(mdl);
TRACE("opt", model_smt2_pp(tout << "updated model\n", m, *m_model, 0););
@ -834,7 +833,7 @@ public:
m_found_feasible_optimum = false;
m_last_index = 0;
add_upper_bound_block();
m_csmodel = 0;
m_csmodel = nullptr;
m_correction_set_size = 0;
return l_true;
}
@ -858,7 +857,7 @@ public:
smt_solver->assert_expr(s().get_assertion(i));
}
smt_solver->assert_expr(core);
lbool is_sat = smt_solver->check_sat(0, 0);
lbool is_sat = smt_solver->check_sat(0, nullptr);
if (is_sat == l_true) {
IF_VERBOSE(0, verbose_stream() << "not a core\n";);
}
@ -878,7 +877,7 @@ public:
}
smt_solver->assert_expr(n);
}
lbool is_sat = smt_solver->check_sat(0, 0);
lbool is_sat = smt_solver->check_sat(0, nullptr);
if (is_sat == l_false) {
IF_VERBOSE(0, verbose_stream() << "assignment is infeasible\n";);
}

View file

@ -116,7 +116,7 @@ namespace opt {
return dynamic_cast<smt::theory_wmaxsat*>(th);
}
else {
return 0;
return nullptr;
}
}
@ -155,7 +155,7 @@ namespace opt {
rational l = m_adjust_value(m_lower);
rational u = m_adjust_value(m_upper);
if (l > u) std::swap(l, u);
verbose_stream() << "(opt." << solver << " [" << l << ":" << u << "])\n";);
verbose_stream() << "(opt." << solver << " [" << l << ":" << u << "])\n";);
}
lbool maxsmt_solver_base::find_mutexes(obj_map<expr, rational>& new_soft) {
@ -228,7 +228,7 @@ namespace opt {
lbool maxsmt::operator()() {
lbool is_sat = l_undef;
m_msolver = 0;
m_msolver = nullptr;
symbol const& maxsat_engine = m_c.maxsat_engine();
IF_VERBOSE(1, verbose_stream() << "(maxsmt)\n";);
TRACE("opt", tout << "maxsmt\n";
@ -405,6 +405,10 @@ namespace opt {
return m_c.get_solver();
}
void maxsmt::model_updated(model* mdl) {
m_c.model_updated(mdl);
}
};

View file

@ -72,15 +72,15 @@ namespace opt {
public:
maxsmt_solver_base(maxsat_context& c, weights_t& ws, expr_ref_vector const& soft);
virtual ~maxsmt_solver_base() {}
virtual rational get_lower() const { return m_lower; }
virtual rational get_upper() const { return m_upper; }
virtual bool get_assignment(unsigned index) const { return m_assignment[index]; }
virtual void collect_statistics(statistics& st) const { }
virtual void get_model(model_ref& mdl, svector<symbol>& labels) { mdl = m_model.get(); labels = m_labels;}
~maxsmt_solver_base() override {}
rational get_lower() const override { return m_lower; }
rational get_upper() const override { return m_upper; }
bool get_assignment(unsigned index) const override { return m_assignment[index]; }
void collect_statistics(statistics& st) const override { }
void get_model(model_ref& mdl, svector<symbol>& labels) override { mdl = m_model.get(); labels = m_labels;}
virtual void commit_assignment();
void set_model() { s().get_model(m_model); s().get_labels(m_labels); }
virtual void updt_params(params_ref& p);
void updt_params(params_ref& p) override;
solver& s();
bool init();
void set_mus(bool f);
@ -146,6 +146,7 @@ namespace opt {
bool get_assignment(unsigned index) const;
void display_answer(std::ostream& out) const;
void collect_statistics(statistics& st) const;
void model_updated(model* mdl);
private:
bool is_maxsat_problem(weights_t& ws) const;
void verify_assignment();

View file

@ -1,285 +0,0 @@
/*++
Copyright (c) 2014 Microsoft Corporation
Module Name:
mss.cpp
Abstract:
MSS/MCS extraction.
Author:
Nikolaj Bjorner (nbjorner) 2014-2-8
Notes:
--*/
#include "solver/solver.h"
#include "opt/mss.h"
#include "ast/ast_pp.h"
#include "model/model_smt2_pp.h"
namespace opt {
mss::mss(solver& s, ast_manager& m): m_s(s), m(m) {
}
mss::~mss() {
}
bool mss::check_result() {
lbool is_sat = m_s.check_sat(m_mss.size(), m_mss.c_ptr());
if (is_sat == l_undef) return true;
SASSERT(m_mss.empty() || is_sat == l_true);
if (is_sat == l_false) return false;
expr_set::iterator it = m_mcs.begin(), end = m_mcs.end();
for (; it != end; ++it) {
m_mss.push_back(*it);
is_sat = m_s.check_sat(m_mss.size(), m_mss.c_ptr());
m_mss.pop_back();
if (is_sat == l_undef) return true;
SASSERT(is_sat == l_false);
if (is_sat == l_true) return false;
}
return true;
}
void mss::initialize(exprs& literals) {
expr* n;
expr_set lits, core_lits;
for (unsigned i = 0; i < literals.size(); ++i) {
n = literals[i];
lits.insert(n);
m.is_not(n, n);
if (!is_uninterp_const(n)) {
throw default_exception("arguments have to be uninterpreted literals");
}
}
exprs rest_core;
expr_ref tmp(m);
//
// the last core is a dummy core. It contains literals that
// did not occur in previous cores and did not evaluate to true
// in the current model.
//
for (unsigned i = 0; i < m_cores.size(); ++i) {
exprs const& core = m_cores[i];
for (unsigned j = 0; j < core.size(); ++j) {
expr* n = core[j];
if (!core_lits.contains(n)) {
core_lits.insert(n);
if (m_model->eval(n, tmp) && m.is_true(tmp)) {
add_mss(n);
}
else {
m_todo.push_back(n);
}
}
}
}
for (unsigned i = 0; i < literals.size(); ++i) {
expr* n = literals[i];
if (!core_lits.contains(n)) {
if (m_model->eval(n, tmp) && m.is_true(tmp)) {
m_mss.push_back(n);
}
else {
rest_core.push_back(n);
core_lits.insert(n);
m_todo.push_back(n);
}
}
}
m_cores.push_back(rest_core);
}
void mss::add_mss(expr* n) {
if (!m_mss_set.contains(n)) {
m_mss_set.insert(n);
m_mss.push_back(n);
}
}
void mss::update_core(exprs& core) {
unsigned j = 0;
for (unsigned i = 0; i < core.size(); ++i) {
expr* n = core[i];
if (!m_mss_set.contains(n)) {
if (i != j) {
core[j] = core[i];
}
++j;
}
}
core.resize(j);
}
void mss::update_mss() {
expr_ref tmp(m);
unsigned j = 0;
for (unsigned i = 0; i < m_todo.size(); ++i) {
expr* n = m_todo[i];
SASSERT(!m_mss_set.contains(n));
if (m_mcs.contains(n)) {
continue; // remove from cores.
}
if (m_model->eval(n, tmp) && m.is_true(tmp)) {
add_mss(n);
}
else {
if (j != i) {
m_todo[j] = m_todo[i];
}
++j;
}
}
m_todo.resize(j);
}
lbool mss::operator()(model* initial_model, vector<exprs> const& _cores, exprs& literals, exprs& mcs) {
m_mss.reset();
m_todo.reset();
m_model = initial_model;
m_cores.reset();
SASSERT(m_model);
m_cores.append(_cores);
initialize(literals);
TRACE("opt",
display_vec(tout << "lits: ", literals.size(), literals.c_ptr());
display(tout););
lbool is_sat = l_true;
for (unsigned i = 0; is_sat == l_true && i < m_cores.size(); ++i) {
bool has_mcs = false;
bool is_last = i + 1 < m_cores.size();
SASSERT(check_invariant());
update_core(m_cores[i]); // remove members of mss
is_sat = process_core(1, m_cores[i], has_mcs, is_last);
}
if (is_sat == l_true) {
SASSERT(check_invariant());
TRACE("opt", display(tout););
literals.reset();
literals.append(m_mss);
mcs.reset();
expr_set::iterator it = m_mcs.begin(), end = m_mcs.end();
for (; it != end; ++it) {
mcs.push_back(*it);
}
SASSERT(check_result());
}
m_mcs.reset();
m_mss_set.reset();
IF_VERBOSE(2, display_vec(verbose_stream() << "mcs: ", mcs.size(), mcs.c_ptr()););
return is_sat;
}
//
// at least one literal in core is false in current model.
// pick literals in core that are not yet in mss.
//
lbool mss::process_core(unsigned sz, exprs& core, bool& has_mcs, bool is_last) {
SASSERT(sz > 0);
if (core.empty()) {
return l_true;
}
if (m.canceled()) {
return l_undef;
}
if (sz == 1 && core.size() == 1 && is_last && !has_mcs) {
// there has to be at least one false
// literal in the core.
TRACE("opt", tout << "mcs: " << mk_pp(core[0], m) << "\n";);
m_mcs.insert(core[0]);
return l_true;
}
sz = std::min(sz, core.size());
TRACE("opt", display_vec(tout << "process (total " << core.size() << ") :", sz, core.c_ptr()););
unsigned sz_save = m_mss.size();
m_mss.append(sz, core.c_ptr());
lbool is_sat = m_s.check_sat(m_mss.size(), m_mss.c_ptr());
IF_VERBOSE(3, display_vec(verbose_stream() << "mss: ", m_mss.size(), m_mss.c_ptr()););
m_mss.resize(sz_save);
switch (is_sat) {
case l_true:
m_s.get_model(m_model);
update_mss();
DEBUG_CODE(
for (unsigned i = 0; i < sz; ++i) {
SASSERT(m_mss_set.contains(core[i]));
});
update_core(core);
return process_core(2*sz, core, has_mcs, is_last);
case l_false:
if (sz == 1) {
has_mcs = true;
m_mcs.insert(core[0]);
core[0] = core.back();
core.pop_back();
}
else {
exprs core2;
core2.append(core.size()-sz, core.c_ptr()+sz);
core.resize(sz);
is_sat = process_core(sz, core2, has_mcs, false);
if (is_sat != l_true) {
return is_sat;
}
update_core(core);
}
return process_core(1, core, has_mcs, is_last);
case l_undef:
return l_undef;
}
return l_true;
}
void mss::display_vec(std::ostream& out, unsigned sz, expr* const* args) const {
for (unsigned i = 0; i < sz; ++i) {
out << mk_pp(args[i], m) << " ";
}
out << "\n";
}
void mss::display(std::ostream& out) const {
for (unsigned i = 0; i < m_cores.size(); ++i) {
display_vec(out << "core: ", m_cores[i].size(), m_cores[i].c_ptr());
}
expr_set::iterator it = m_mcs.begin(), end = m_mcs.end();
out << "mcs:\n";
for (; it != end; ++it) {
out << mk_pp(*it, m) << "\n";
}
out << "\n";
out << "mss:\n";
for (unsigned i = 0; i < m_mss.size(); ++i) {
out << mk_pp(m_mss[i], m) << "\n";
}
out << "\n";
if (m_model) {
model_smt2_pp(out, m, *(m_model.get()), 0);
}
}
bool mss::check_invariant() const {
if (!m_model) return true;
expr_ref tmp(m);
for (unsigned i = 0; i < m_mss.size(); ++i) {
expr* n = m_mss[i];
if (!m_model->eval(n, tmp)) return true;
CTRACE("opt", !m.is_true(tmp), tout << mk_pp(n, m) << " |-> " << mk_pp(tmp, m) << "\n";);
SASSERT(!m.is_false(tmp));
}
return true;
}
}

View file

@ -1,57 +0,0 @@
/*++
Copyright (c) 2014 Microsoft Corporation
Module Name:
mss.h
Abstract:
Maximal satisfying subset/minimal correction sets: MSS/MCS
Author:
Nikolaj Bjorner (nbjorner) 2014-2-8
Notes:
--*/
#ifndef MSS_H_
#define MSS_H_
namespace opt {
class mss {
solver& m_s;
ast_manager& m;
typedef ptr_vector<expr> exprs;
typedef obj_hashtable<expr> expr_set;
exprs m_mss;
expr_set m_mcs;
expr_set m_mss_set;
vector<exprs> m_cores;
exprs m_todo;
model_ref m_model;
public:
mss(solver& s, ast_manager& m);
~mss();
lbool operator()(model* initial_model, vector<exprs> const& cores, exprs& literals, exprs& mcs);
void get_model(model_ref& mdl) { mdl = m_model; }
private:
void initialize(exprs& literals);
bool check_result();
void add_mss(expr* n);
void update_mss();
void update_core(exprs& core);
lbool process_core(unsigned sz, exprs& core, bool& has_mcs, bool is_last);
void display(std::ostream& out) const;
void display_vec(std::ostream& out, unsigned sz, expr* const* args) const;
bool check_invariant() const;
};
};
#endif

View file

@ -52,7 +52,7 @@ public:
assert_soft_cmd(opt::context* opt):
parametric_cmd("assert-soft"),
m_idx(0),
m_formula(0),
m_formula(nullptr),
m_opt(opt)
{}
@ -61,7 +61,7 @@ public:
virtual void reset(cmd_context & ctx) {
m_idx = 0;
m_formula = 0;
m_formula = nullptr;
}
virtual char const * get_usage() const { return "<formula> [:weight <rational-weight>] [:id <symbol>]"; }

View file

@ -23,7 +23,7 @@ Notes:
class cmd_context;
void install_opt_cmds(cmd_context & ctx, opt::context* opt = 0);
void install_opt_cmds(cmd_context & ctx, opt::context* opt = nullptr);
#endif

View file

@ -122,7 +122,8 @@ namespace opt {
m_arith(m),
m_bv(m),
m_hard_constraints(m),
m_solver(0),
m_solver(nullptr),
m_pareto1(false),
m_box_index(UINT_MAX),
m_optsmt(m),
m_scoped_state(m),
@ -138,6 +139,7 @@ namespace opt {
p.set_bool("unsat_core", true);
p.set_bool("elim_to_real", true);
updt_params(p);
m_model_counter = 0;
}
context::~context() {
@ -279,16 +281,15 @@ namespace opt {
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", s.display(tout << "initial search result: " << is_sat << "\n"););
display_benchmark();
IF_VERBOSE(1, verbose_stream() << "(optimize:check-sat)\n";);
lbool is_sat = s.check_sat(0,nullptr);
TRACE("opt", tout << "initial search result: " << is_sat << "\n";
s.display(tout););
if (is_sat != l_false) {
s.get_model(m_model);
s.get_labels(m_labels);
if (is_sat == l_true) {
validate_model();
}
model_updated(m_model.get());
}
if (is_sat != l_true) {
TRACE("opt", tout << m_hard_constraints << "\n";);
@ -303,7 +304,14 @@ namespace opt {
case 0:
break;
case 1:
is_sat = execute(m_objectives[0], true, false);
if (m_pareto1) {
is_sat = l_false;
m_pareto1 = false;
}
else {
m_pareto1 = (pri == symbol("pareto"));
is_sat = execute(m_objectives[0], true, false);
}
break;
default: {
opt_params optp(m_params);
@ -318,9 +326,9 @@ namespace opt {
is_sat = execute_box();
}
else {
is_sat = execute_lex();
m_pareto1 = (pri == symbol("pareto"));
is_sat = execute(m_objectives[0], true, false);
}
break;
}
}
if (is_sat == l_true) validate_model();
@ -358,12 +366,24 @@ namespace opt {
fix_model(mdl);
}
bool context::contains_quantifiers() const {
for (expr* f : m_hard_constraints) {
if (has_quantifiers(f)) return true;
}
return false;
}
lbool context::execute_min_max(unsigned index, bool committed, bool scoped, bool is_max) {
if (scoped) get_solver().push();
lbool result = m_optsmt.lex(index, is_max);
if (result == l_true) m_optsmt.get_model(m_model, m_labels);
if (scoped) get_solver().pop(1);
if (result == l_true && committed) m_optsmt.commit_assignment(index);
if (result == l_true && m_optsmt.is_unbounded(index, is_max) && contains_quantifiers()) {
throw default_exception("unbounded objectives on quantified constraints is not supported");
result = l_undef;
}
return result;
}
@ -396,8 +416,8 @@ namespace opt {
*/
bool context::scoped_lex() {
if (m_maxsat_engine == symbol("maxres")) {
for (unsigned i = 0; i < m_objectives.size(); ++i) {
if (m_objectives[i].m_type != O_MAXSMT) return true;
for (auto const& o : m_objectives) {
if (o.m_type != O_MAXSMT) return true;
}
return false;
}
@ -407,14 +427,16 @@ namespace opt {
lbool context::execute_lex() {
lbool r = l_true;
bool sc = scoped_lex();
IF_VERBOSE(1, verbose_stream() << "(optsmt:lex)\n";);
for (unsigned i = 0; r == l_true && i < m_objectives.size(); ++i) {
bool is_last = i + 1 == m_objectives.size();
r = execute(m_objectives[i], i + 1 < m_objectives.size(), sc && !is_last);
IF_VERBOSE(1, verbose_stream() << "(opt :lex)\n";);
unsigned sz = m_objectives.size();
for (unsigned i = 0; r == l_true && i < sz; ++i) {
objective const& o = m_objectives[i];
bool is_last = i + 1 == sz;
r = execute(o, i + 1 < sz, sc && !is_last && o.m_type != O_MAXSMT);
if (r == l_true && !get_lower_as_num(i).is_finite()) {
return r;
}
if (r == l_true && i + 1 < m_objectives.size()) {
if (r == l_true && i + 1 < sz) {
update_lower();
}
}
@ -429,7 +451,7 @@ namespace opt {
return l_true;
}
if (m_box_index < m_objectives.size()) {
m_model = 0;
m_model = nullptr;
++m_box_index;
return l_undef;
}
@ -678,8 +700,7 @@ namespace opt {
expr_fast_mark1 visited;
is_bv proc(m);
try {
for (unsigned i = 0; i < m_objectives.size(); ++i) {
objective & obj = m_objectives[i];
for (objective& obj : m_objectives) {
if (obj.m_type != O_MAXSMT) return false;
maxsmt& ms = *m_maxsmts.find(obj.m_id);
for (unsigned j = 0; j < ms.size(); ++j) {
@ -690,8 +711,8 @@ namespace opt {
for (unsigned i = 0; i < sz; i++) {
quick_for_each_expr(proc, visited, get_solver().get_assertion(i));
}
for (unsigned i = 0; i < m_hard_constraints.size(); ++i) {
quick_for_each_expr(proc, visited, m_hard_constraints[i].get());
for (expr* f : m_hard_constraints) {
quick_for_each_expr(proc, visited, f);
}
}
catch (is_bv::found) {
@ -937,7 +958,7 @@ namespace opt {
func_decl* f = m.mk_fresh_func_decl(name,"", domain.size(), domain.c_ptr(), m.mk_bool_sort());
m_objective_fns.insert(f, index);
m_objective_refs.push_back(f);
m_objective_orig.insert(f, sz > 0 ? args[0] : 0);
m_objective_orig.insert(f, sz > 0 ? args[0] : nullptr);
return m.mk_app(f, sz, args);
}
@ -979,7 +1000,7 @@ namespace opt {
}
mk_atomic(terms);
SASSERT(obj.m_id == id);
obj.m_term = orig_term?to_app(orig_term):0;
obj.m_term = orig_term?to_app(orig_term):nullptr;
obj.m_terms.reset();
obj.m_terms.append(terms);
obj.m_weights.reset();
@ -1038,6 +1059,22 @@ namespace opt {
}
}
void context::model_updated(model* md) {
opt_params optp(m_params);
symbol prefix = optp.solution_prefix();
if (prefix == symbol::null || prefix == symbol("")) return;
model_ref mdl = md->copy();
fix_model(mdl);
std::ostringstream buffer;
buffer << prefix << (m_model_counter++) << ".smt2";
std::ofstream out(buffer.str());
if (out) {
model_smt2_pp(out, m, *mdl, 0);
out.close();
}
}
bool context::verify_model(unsigned index, model* md, rational const& _v) {
rational r;
app_ref term = m_objectives[index].m_term;
@ -1046,10 +1083,6 @@ namespace opt {
}
rational v = m_objectives[index].m_adjust_value(_v);
expr_ref val(m);
//
// we have to clone the model so that maxsat solver can use
// internal variables that are otherwise deleted from the model.
//
model_ref mdl = md->copy();
fix_model(mdl);
@ -1277,6 +1310,9 @@ namespace opt {
}
void context::display_assignment(std::ostream& out) {
if (m_scoped_state.m_objectives.size() != m_objectives.size()) {
throw default_exception("check-sat has not been called with latest objectives");
}
out << "(objectives\n";
for (unsigned i = 0; i < m_scoped_state.m_objectives.size(); ++i) {
objective const& obj = m_scoped_state.m_objectives[i];
@ -1408,6 +1444,7 @@ namespace opt {
void context::set_pareto(pareto_base* p) {
m_pareto = p;
m_pareto1 = p != nullptr;
}
void context::collect_statistics(statistics& stats) const {

View file

@ -59,6 +59,7 @@ namespace opt {
virtual unsigned num_objectives() = 0;
virtual bool verify_model(unsigned id, model* mdl, rational const& v) = 0;
virtual void set_model(model_ref& _m) = 0;
virtual void model_updated(model* mdl) = 0;
};
/**
@ -146,8 +147,9 @@ namespace opt {
ref<opt_solver> m_opt_solver;
ref<solver> m_solver;
ref<solver> m_sat_solver;
scoped_ptr<pareto_base> m_pareto;
scoped_ptr<pareto_base> m_pareto;
scoped_ptr<lns> m_lns;
bool m_pareto1;
scoped_ptr<qe::qmax> m_qmax;
sref_vector<model> m_box_models;
unsigned m_box_index;
@ -156,9 +158,10 @@ namespace opt {
map_t m_maxsmts;
scoped_state m_scoped_state;
vector<objective> m_objectives;
model_ref m_model;
model_ref m_model;
model_converter_ref m_model_converter;
generic_model_converter_ref m_fm;
unsigned m_model_counter;
obj_map<func_decl, unsigned> m_objective_fns;
obj_map<func_decl, expr*> m_objective_orig;
func_decl_ref_vector m_objective_refs;
@ -173,7 +176,7 @@ namespace opt {
std::string m_unknown;
public:
context(ast_manager& m);
virtual ~context();
~context() override;
unsigned add_soft_constraint(expr* f, rational const& w, symbol const& id);
unsigned add_objective(app* t, bool is_max);
void add_hard_constraint(expr* f);
@ -181,6 +184,7 @@ namespace opt {
void get_hard_constraints(expr_ref_vector& hard);
expr_ref get_objective(unsigned i);
#if 0
virtual void push();
virtual void pop(unsigned n);
virtual bool empty() { return m_scoped_state.m_objectives.empty(); }
@ -200,11 +204,32 @@ namespace opt {
virtual void display_assignment(std::ostream& out);
virtual bool is_pareto() { return m_pareto.get() != 0; }
virtual void set_logic(symbol const& s) { m_logic = s; }
#endif
void push() override;
void pop(unsigned n) override;
bool empty() override { return m_scoped_state.m_objectives.empty(); }
void set_hard_constraints(ptr_vector<expr> & hard) override;
lbool optimize() override;
void set_model(model_ref& _m) override { m_model = _m; }
void get_model_core(model_ref& _m) override;
void get_box_model(model_ref& _m, unsigned index) override;
void fix_model(model_ref& _m) override;
void collect_statistics(statistics& stats) const override;
proof* get_proof() override { return nullptr; }
void get_labels(svector<symbol> & r) override;
void get_unsat_core(ptr_vector<expr> & r) override;
std::string reason_unknown() const override;
void set_reason_unknown(char const* msg) override { m_unknown = msg; }
void display_assignment(std::ostream& out) override;
bool is_pareto() override { return m_pareto.get() != nullptr; }
void set_logic(symbol const& s) override { m_logic = s; }
void set_clausal(bool f) { m_is_clausal = f; }
void display(std::ostream& out);
static void collect_param_descrs(param_descrs & r);
virtual void updt_params(params_ref const& p);
void updt_params(params_ref const& p) override;
params_ref& get_params() { return m_params; }
expr_ref get_lower(unsigned idx);
@ -216,13 +241,13 @@ namespace opt {
std::string to_string() const;
virtual unsigned num_objectives() { return m_scoped_state.m_objectives.size(); }
virtual expr_ref mk_gt(unsigned i, model_ref& model);
virtual expr_ref mk_ge(unsigned i, model_ref& model);
virtual expr_ref mk_le(unsigned i, model_ref& model);
unsigned num_objectives() override { return m_scoped_state.m_objectives.size(); }
expr_ref mk_gt(unsigned i, model_ref& model) override;
expr_ref mk_ge(unsigned i, model_ref& model) override;
expr_ref mk_le(unsigned i, model_ref& model) override;
#if 0
virtual smt::context& smt_context() { return m_opt_solver->get_context(); }
virtual generic_model_converter& fm() { return *m_fm; }
virtual bool sat_enabled() const { return 0 != m_sat_solver.get(); }
virtual solver& get_solver();
virtual ast_manager& get_manager() const { return this->m; }
@ -230,15 +255,27 @@ namespace opt {
virtual void enable_sls(bool force);
virtual symbol const& maxsat_engine() const { return m_maxsat_engine; }
virtual void get_base_model(model_ref& _m);
#endif
generic_model_converter& fm() override { return *m_fm; }
smt::context& smt_context() override { return m_opt_solver->get_context(); }
bool sat_enabled() const override { return nullptr != m_sat_solver.get(); }
solver& get_solver() override;
ast_manager& get_manager() const override { return this->m; }
params_ref& params() override { return m_params; }
void enable_sls(bool force) override;
symbol const& maxsat_engine() const override { return m_maxsat_engine; }
void get_base_model(model_ref& _m) override;
virtual bool verify_model(unsigned id, model* mdl, rational const& v);
bool verify_model(unsigned id, model* mdl, rational const& v) override;
void model_updated(model* mdl) override;
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);
lbool execute_min_max(unsigned index, bool committed, bool scoped, bool is_max);
lbool execute_maxsat(symbol const& s, bool committed, bool scoped);
lbool execute_lex();
lbool execute_box();
@ -246,6 +283,7 @@ namespace opt {
lbool execute_lns();
lbool adjust_unknown(lbool r);
bool scoped_lex();
bool contains_quantifiers() const;
expr_ref to_expr(inf_eps const& n);
void to_exprs(inf_eps const& n, expr_ref_vector& es);

View file

@ -5,6 +5,7 @@ def_module_params('opt',
('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', 'box', or 'lns' (large neighborhood search)"),
('dump_benchmarks', BOOL, False, 'dump benchmarks for profiling'),
('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'),

View file

@ -29,7 +29,7 @@ namespace opt {
lbool gia_pareto::operator()() {
expr_ref fml(m);
lbool is_sat = m_solver->check_sat(0, 0);
lbool is_sat = m_solver->check_sat(0, nullptr);
if (is_sat == l_true) {
{
solver::scoped_push _s(*m_solver.get());
@ -45,7 +45,7 @@ namespace opt {
model_smt2_pp(verbose_stream() << "new model:\n", m, *mdl, 0););
// TBD: we can also use local search to tune solution coordinate-wise.
mk_dominates();
is_sat = m_solver->check_sat(0, 0);
is_sat = m_solver->check_sat(0, nullptr);
}
}
if (is_sat == l_undef) {
@ -91,7 +91,7 @@ namespace opt {
lbool oia_pareto::operator()() {
solver::scoped_push _s(*m_solver.get());
lbool is_sat = m_solver->check_sat(0, 0);
lbool is_sat = m_solver->check_sat(0, nullptr);
if (m.canceled()) {
is_sat = l_undef;
}

View file

@ -87,9 +87,9 @@ namespace opt {
params_ref & p):
pareto_base(m, cb, s, p) {
}
virtual ~gia_pareto() {}
~gia_pareto() override {}
virtual lbool operator()();
lbool operator()() override;
};
// opportunistic improvement algorithm.
@ -101,9 +101,9 @@ namespace opt {
params_ref & p):
pareto_base(m, cb, s, p) {
}
virtual ~oia_pareto() {}
~oia_pareto() override {}
virtual lbool operator()();
lbool operator()() override;
};
}

View file

@ -66,7 +66,6 @@ public:
bool opt_stream_buffer::parse_token(char const* token) {
skip_whitespace();
char const* t = token;

View file

@ -69,7 +69,7 @@ namespace opt {
solver* opt_solver::translate(ast_manager& m, params_ref const& p) {
UNREACHABLE();
return 0;
return nullptr;
}
void opt_solver::collect_param_descrs(param_descrs & r) {
@ -227,9 +227,13 @@ namespace opt {
smt::theory_var v = m_objective_vars[i];
bool has_shared = false;
inf_eps val = get_optimizer().maximize(v, blocker, has_shared);
get_model(m_model);
inf_eps val2;
m_valid_objectives[i] = true;
TRACE("opt", tout << (has_shared?"has shared":"non-shared") << "\n";);
if (!m_models[i]) {
set_model(i);
}
if (m_context.get_context().update_model(has_shared)) {
if (has_shared && val != current_objective_value(i)) {
decrement_value(i, val);
@ -247,7 +251,7 @@ namespace opt {
tout << "objective: " << mk_pp(m_objective_terms[i].get(), m) << "\n";
tout << "maximal value: " << val << "\n";
tout << "new condition: " << blocker << "\n";
model_smt2_pp(tout << "update model:\n", m, *m_models[i], 0); });
if (m_models[i]) model_smt2_pp(tout << "update model:\n", m, *m_models[i], 0); });
}
void opt_solver::set_model(unsigned i) {
@ -261,7 +265,7 @@ namespace opt {
expr_ref ge = mk_ge(i, val);
TRACE("opt", tout << ge << "\n";);
assert_expr(ge);
lbool is_sat = m_context.check(0, 0);
lbool is_sat = m_context.check(0, nullptr);
is_sat = adjust_result(is_sat);
if (is_sat == l_true) {
set_model(i);
@ -299,6 +303,7 @@ namespace opt {
void opt_solver::get_model_core(model_ref & m) {
m_context.get_model(m);
if (!m) m = m_model; else m_model = m;
}
proof * opt_solver::get_proof() {
@ -316,7 +321,7 @@ namespace opt {
void opt_solver::get_labels(svector<symbol> & r) {
r.reset();
buffer<symbol> tmp;
m_context.get_relevant_labels(0, tmp);
m_context.get_relevant_labels(nullptr, tmp);
r.append(tmp.size(), tmp.c_ptr());
}
@ -340,7 +345,7 @@ namespace opt {
m_objective_values.push_back(inf_eps(rational(-1), inf_rational()));
m_objective_terms.push_back(term);
m_valid_objectives.push_back(true);
m_models.push_back(0);
m_models.push_back(nullptr);
return v;
}

View file

@ -73,6 +73,7 @@ namespace opt {
generic_model_converter& m_fm;
progress_callback * m_callback;
symbol m_logic;
model_ref m_model;
svector<smt::theory_var> m_objective_vars;
vector<inf_eps> m_objective_values;
sref_vector<model> m_models;
@ -85,6 +86,31 @@ namespace opt {
bool m_was_unknown;
public:
opt_solver(ast_manager & m, params_ref const & p, generic_model_converter& fm);
~opt_solver() override;
solver* translate(ast_manager& m, params_ref const& p) override;
void updt_params(params_ref const& p) override;
void collect_param_descrs(param_descrs & r) override;
void collect_statistics(statistics & st) const override;
void assert_expr_core(expr * t) override;
void push_core() override;
void pop_core(unsigned n) override;
lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) override;
void get_unsat_core(ptr_vector<expr> & r) override;
void get_model_core(model_ref & _m) override;
proof * get_proof() override;
std::string reason_unknown() const override;
void set_reason_unknown(char const* msg) override;
void get_labels(svector<symbol> & r) override;
void set_progress_callback(progress_callback * callback) override;
unsigned get_num_assertions() const override;
expr * get_assertion(unsigned idx) const override;
ast_manager& get_manager() const override { return m; }
lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) override;
lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores) override;
expr_ref_vector cube(expr_ref_vector&, unsigned) override { return expr_ref_vector(m); }
#if 0
virtual ~opt_solver();
virtual solver* translate(ast_manager& m, params_ref const& p);
@ -108,7 +134,7 @@ namespace opt {
virtual ast_manager& get_manager() const { return m; }
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes);
virtual lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores);
virtual expr_ref_vector cube(expr_ref_vector&, unsigned) { return expr_ref_vector(m); }
#endif
void set_logic(symbol const& logic);
smt::theory_var add_objective(app* term);

View file

@ -112,7 +112,7 @@ namespace opt {
while (!m.canceled()) {
SASSERT(delta_per_step.is_int());
SASSERT(delta_per_step.is_pos());
is_sat = m_s->check_sat(0, 0);
is_sat = m_s->check_sat(0, nullptr);
if (is_sat == l_true) {
bound = update_lower();
if (!get_max_delta(lower, delta_index)) {
@ -161,6 +161,14 @@ namespace opt {
return l_true;
}
bool optsmt::is_unbounded(unsigned obj_index, bool is_maximize) {
if (is_maximize) {
return !m_upper[obj_index].is_finite();
}
else {
return !m_lower[obj_index].is_finite();
}
}
lbool optsmt::geometric_lex(unsigned obj_index, bool is_maximize) {
arith_util arith(m);
@ -180,7 +188,7 @@ namespace opt {
while (!m.canceled()) {
SASSERT(delta_per_step.is_int());
SASSERT(delta_per_step.is_pos());
is_sat = m_s->check_sat(0, 0);
is_sat = m_s->check_sat(0, nullptr);
if (is_sat == l_true) {
m_s->maximize_objective(obj_index, bound);
m_s->get_model(m_model);
@ -408,7 +416,7 @@ namespace opt {
bounds.push_back(bound);
}
else {
bounds.push_back(0);
bounds.push_back(nullptr);
mid.push_back(inf_eps());
}
}
@ -421,7 +429,7 @@ namespace opt {
case l_true:
IF_VERBOSE(2, verbose_stream() << "(optsmt lower bound for v" << m_vars[i] << " := " << m_upper[i] << ")\n";);
m_lower[i] = mid[i];
th.enable_record_conflict(0);
th.enable_record_conflict(nullptr);
m_s->assert_expr(update_lower());
break;
case l_false:
@ -436,10 +444,10 @@ namespace opt {
}
break;
default:
th.enable_record_conflict(0);
th.enable_record_conflict(nullptr);
return l_undef;
}
th.enable_record_conflict(0);
th.enable_record_conflict(nullptr);
progress = true;
}
}
@ -497,7 +505,7 @@ namespace opt {
commit_assignment(i);
}
while (is_sat == l_true && !m.canceled()) {
is_sat = m_s->check_sat(0, 0);
is_sat = m_s->check_sat(0, nullptr);
if (is_sat != l_true) break;
m_s->maximize_objective(obj_index, bound);
@ -591,7 +599,7 @@ namespace opt {
m_lower.push_back(inf_eps(rational(-1),inf_rational(0)));
m_upper.push_back(inf_eps(rational(1), inf_rational(0)));
m_lower_fmls.push_back(m.mk_true());
m_models.push_back(0);
m_models.push_back(nullptr);
return m_objs.size()-1;
}
@ -607,7 +615,7 @@ namespace opt {
m_vars.reset();
m_model.reset();
m_lower_fmls.reset();
m_s = 0;
m_s = nullptr;
}
}

View file

@ -41,7 +41,7 @@ namespace opt {
sref_vector<model> m_models;
public:
optsmt(ast_manager& m):
m(m), m_s(0), m_objs(m), m_lower_fmls(m) {}
m(m), m_s(nullptr), m_objs(m), m_lower_fmls(m) {}
void setup(opt_solver& solver);
@ -49,6 +49,8 @@ namespace opt {
lbool lex(unsigned obj_index, bool is_maximize);
bool is_unbounded(unsigned obj_index, bool is_maximize);
unsigned add(app* t);
void updt_params(params_ref& p);

View file

@ -89,7 +89,7 @@ namespace opt {
while (l_true == is_sat && first < out.size() && m_lower < m_upper) {
trace_bounds("sortmax");
s().assert_expr(out[first]);
is_sat = s().check_sat(0, 0);
is_sat = s().check_sat(0, nullptr);
TRACE("opt", tout << is_sat << "\n"; s().display(tout); tout << "\n";);
if (m.canceled()) {
is_sat = l_undef;

View file

@ -80,7 +80,7 @@ namespace opt {
while (!m.canceled() && m_lower < m_upper) {
//mk_assumptions(asms);
//is_sat = s().preferred_sat(asms, cores);
is_sat = s().check_sat(0, 0);
is_sat = s().check_sat(0, nullptr);
if (m.canceled()) {
is_sat = l_undef;
}
@ -162,7 +162,7 @@ namespace opt {
void verify_core(expr_ref_vector const& core) {
s().push();
s().assert_expr(core);
VERIFY(l_false == s().check_sat(0, 0));
VERIFY(l_false == s().check_sat(0, nullptr));
s().pop(1);
}
@ -216,7 +216,7 @@ namespace opt {
rational remove_negations(smt::theory_wmaxsat& th, expr_ref_vector const& core, ptr_vector<expr>& keys, vector<rational>& weights) {
rational min_weight(-1);
for (unsigned i = 0; i < core.size(); ++i) {
expr* e = 0;
expr* e = nullptr;
VERIFY(m.is_not(core[i], e));
keys.push_back(m_keys[e]);
rational weight = m_weights[e];