3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-02-06 17:22:13 +00:00

v2 of dual maxres engine

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2014-08-03 18:50:21 -07:00
parent 622d8b5cd1
commit d429e72e92
6 changed files with 253 additions and 139 deletions

View file

@ -27,35 +27,74 @@ Notes:
namespace opt {
mss::mss(solver& s, ast_manager& m): s(s), m(m), m_cancel(false) {
mss::mss(ref<solver>& s, ast_manager& m): m_s(s), m(m), m_cancel(false) {
}
mss::~mss() {
}
}
void mss::check_parameters(vector<exprs > const& cores, exprs& literals) {
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(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(vector<exprs>& cores, 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");
}
}
// cores are disjoint
// cores are a subset of literals
// literals not in cores evaluate to true in current model
}
/**
\brief Move literals satisfied in todo into mss.
Precondition: the solver state is satisfiable.
*/
void mss::update_model() {
exprs rest_core;
expr_ref tmp(m);
s.get_model(m_model);
update_set(m_todo);
//
// 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 < cores.size(); ++i) {
exprs const& core = cores[i];
for (unsigned j = 0; j < core.size(); ++j) {
expr* n = core[j];
if (!core_lits.contains(n)) {
core_lits.insert(n);
VERIFY(m_model->eval(n, tmp));
if (m.is_true(tmp)) {
m_mss.push_back(n);
}
}
}
}
for (unsigned i = 0; i < literals.size(); ++i) {
expr* n = literals[i];
if (!core_lits.contains(n)) {
VERIFY(m_model->eval(n, tmp));
if (m.is_true(tmp)) {
m_mss.push_back(n);
}
else {
rest_core.push_back(n);
core_lits.insert(n);
}
}
}
cores.push_back(rest_core);
}
void mss::update_set(exprs& lits) {
@ -69,7 +108,7 @@ namespace opt {
continue;
}
VERIFY(m_model->eval(n, tmp));
if (m.is_false(tmp)) {
if (!m.is_true(tmp)) {
if (j != i) {
lits[j] = lits[i];
}
@ -83,33 +122,44 @@ namespace opt {
}
lbool mss::operator()(vector<exprs> const& cores, exprs& literals) {
lbool mss::operator()(vector<exprs> const& _cores, exprs& literals) {
m_mss.reset();
m_mcs.reset();
m_todo.reset();
m_todo.append(literals);
check_parameters(cores, literals);
update_model();
m_s->get_model(m_model);
SASSERT(m_model);
vector<exprs> cores(_cores);
TRACE("opt",
for (unsigned i = 0; i < cores.size(); ++i) {
display_vec(tout << "core: ", cores[i].size(), cores[i].c_ptr());
}
display_vec(tout << "lits: ", literals.size(), literals.c_ptr());
);
initialize(cores, literals);
TRACE("opt", display(tout););
lbool is_sat = l_true;
for (unsigned i = 0; is_sat == l_true && i < cores.size(); ++i) {
is_sat = process_core(cores[i]);
bool has_mcs = false;
bool is_last = i + 1 < cores.size();
SASSERT(check_invariant());
update_set(cores[i]);
is_sat = process_core(1, cores[i], has_mcs, is_last);
}
if (is_sat == l_true) {
SASSERT(check_invariant());
TRACE("opt", display(tout););
literals.reset();
literals.append(m_mss);
SASSERT(check_result());
}
return is_sat;
}
lbool mss::process_core(exprs const& _core) {
// at least one literal in core is false in current model.
// pick literals in core that are not yet in mss.
exprs core(_core);
update_set(core);
return process_core(1, core);
}
lbool mss::process_core(unsigned sz, exprs& core) {
//
// 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) {
TRACE("opt", tout << "process: " << sz << " out of " << core.size() << " literals\n";);
SASSERT(sz > 0);
if (core.empty()) {
@ -118,18 +168,25 @@ namespace opt {
if (m_cancel) {
return l_undef;
}
if (sz == 1 && is_last && !has_mcs) {
// there has to be at least one false
// literal in the core.
m_mcs.insert(core[0]);
return l_true;
}
sz = std::min(sz, core.size());
unsigned sz_save = m_mss.size();
m_mss.append(sz, core.c_ptr());
lbool is_sat = s.check_sat(m_mss.size(), m_mss.c_ptr());
lbool is_sat = m_s->check_sat(m_mss.size(), m_mss.c_ptr());
m_mss.resize(sz_save);
switch (is_sat) {
case l_true:
update_model();
m_s->get_model(m_model);
update_set(core);
return process_core(2*sz, 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();
@ -138,12 +195,12 @@ namespace opt {
exprs core2;
core2.append(core.size()-sz, core.c_ptr()+sz);
core.resize(sz);
is_sat = process_core(sz, core2);
is_sat = process_core(sz, core2, has_mcs, false);
if (is_sat != l_true) {
return is_sat;
}
}
return process_core(1, core);
return process_core(1, core, has_mcs, is_last);
case l_undef:
return l_undef;
}
@ -151,8 +208,41 @@ namespace opt {
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 {
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];
VERIFY(m_model->eval(n, tmp));
CTRACE("opt", !m.is_true(tmp), tout << mk_pp(n, m) << " |-> " << mk_pp(tmp, m) << "\n";);
SASSERT(!m.is_false(tmp));
}
return true;
}
}