mirror of
https://github.com/Z3Prover/z3
synced 2025-04-15 13:28:47 +00:00
Complete Fu & Malik MAXSAT implementation
Mistakes: (1) ast_manager shouldn't be replicated. (2) assumptions should be used to compare with unsat cores
This commit is contained in:
parent
8ae0b06912
commit
3da47a280e
|
@ -6,8 +6,8 @@ Module Name:
|
||||||
fu_malik.cpp
|
fu_malik.cpp
|
||||||
|
|
||||||
Abstract:
|
Abstract:
|
||||||
Fu&Malik built-in optimization method.
|
Fu & Malik built-in optimization method.
|
||||||
Adapted from sample code.
|
Adapted from sample code in C.
|
||||||
|
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
|
@ -40,16 +40,18 @@ namespace opt {
|
||||||
solver& s;
|
solver& s;
|
||||||
expr_ref_vector m_soft;
|
expr_ref_vector m_soft;
|
||||||
expr_ref_vector m_aux;
|
expr_ref_vector m_aux;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
fu_malik(ast_manager& m, solver& s, expr_ref_vector const& soft):
|
fu_malik(ast_manager& m, solver& s, expr_ref_vector const& soft):
|
||||||
m(m),
|
m(m),
|
||||||
s(s),
|
s(s),
|
||||||
m_soft(soft),
|
m_soft(soft),
|
||||||
m_aux(m)
|
m_aux(m)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < m_soft.size(); i++) {
|
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
||||||
m_aux.push_back(m.mk_fresh_const("p", m.mk_bool_sort()));
|
m_aux.push_back(m.mk_fresh_const("p", m.mk_bool_sort()));
|
||||||
s.assert_expr(m.mk_or(soft[i], m_aux[i].get()));
|
s.assert_expr(m.mk_or(m_soft[i].get(), m_aux[i].get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,12 +84,12 @@ namespace opt {
|
||||||
ptr_vector<expr> core;
|
ptr_vector<expr> core;
|
||||||
s.get_unsat_core(core);
|
s.get_unsat_core(core);
|
||||||
|
|
||||||
// update soft-constraints and aux_vars
|
// Update soft-constraints and aux_vars
|
||||||
for (unsigned i = 0; i < m_soft.size(); i++) {
|
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (unsigned j = 0; !found && j < core.size(); ++j) {
|
for (unsigned j = 0; !found && j < core.size(); ++j) {
|
||||||
found = m_soft[i].get() == core[j];
|
found = assumptions[i].get() == core[j];
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -106,46 +108,57 @@ namespace opt {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void assert_at_most_one(expr_ref_vector const& block_vars) {
|
void assert_at_most_one(expr_ref_vector const& block_vars) {
|
||||||
expr_ref has_one(m), no_one(m), at_most_one(m);
|
expr_ref has_one(m), has_zero(m), at_most_one(m);
|
||||||
mk_at_most_one(block_vars.size(), block_vars.c_ptr(), has_one, no_one);
|
mk_at_most_one(block_vars.size(), block_vars.c_ptr(), has_one, has_zero);
|
||||||
at_most_one = m.mk_or(has_one, no_one);
|
at_most_one = m.mk_or(has_one, has_zero);
|
||||||
s.assert_expr(at_most_one);
|
s.assert_expr(at_most_one);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mk_at_most_one(unsigned n, expr* const * vars, expr_ref& has_one, expr_ref& no_one) {
|
void mk_at_most_one(unsigned n, expr* const * vars, expr_ref& has_one, expr_ref& has_zero) {
|
||||||
|
SASSERT(n != 0);
|
||||||
if (n == 1) {
|
if (n == 1) {
|
||||||
has_one = vars[0];
|
has_one = vars[0];
|
||||||
no_one = m.mk_not(vars[0]);
|
has_zero = m.mk_not(vars[0]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unsigned mid = n/2;
|
unsigned mid = n/2;
|
||||||
expr_ref has_one1(m), has_one2(m), no_one1(m), no_one2(m);
|
expr_ref has_one1(m), has_one2(m), has_zero1(m), has_zero2(m);
|
||||||
mk_at_most_one(mid, vars, has_one1, no_one1);
|
mk_at_most_one(mid, vars, has_one1, has_zero1);
|
||||||
mk_at_most_one(n-mid, vars+mid, has_one2, no_one2);
|
mk_at_most_one(n-mid, vars+mid, has_one2, has_zero2);
|
||||||
has_one = m.mk_or(m.mk_and(has_one1, no_one2), m.mk_and(has_one2, no_one1));
|
has_one = m.mk_or(m.mk_and(has_one1, has_zero2), m.mk_and(has_one2, has_zero1));
|
||||||
no_one = m.mk_and(no_one1, no_one2);
|
has_zero = m.mk_and(has_zero1, has_zero2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// TBD: the vector of soft constraints gets updated
|
|
||||||
// but we really want to return the maximal set of
|
|
||||||
// original soft constraints that are satisfied.
|
|
||||||
// so we need to read out of the model what soft constraints
|
|
||||||
// were satisfied.
|
|
||||||
|
|
||||||
|
|
||||||
lbool fu_malik_maxsat(solver& s, expr_ref_vector& soft_constraints) {
|
lbool fu_malik_maxsat(solver& s, expr_ref_vector& soft_constraints) {
|
||||||
ast_manager m = soft_constraints.get_manager();
|
ast_manager& m = soft_constraints.get_manager();
|
||||||
lbool is_sat = s.check_sat(0,0);
|
lbool is_sat = s.check_sat(0,0);
|
||||||
if (!soft_constraints.empty() && is_sat == l_true) {
|
if (!soft_constraints.empty() && is_sat == l_true) {
|
||||||
s.push();
|
s.push();
|
||||||
|
|
||||||
fu_malik fm(m, s, soft_constraints);
|
fu_malik fm(m, s, soft_constraints);
|
||||||
while (!fm.step());
|
while (!fm.step());
|
||||||
|
|
||||||
|
// Get a list of satisfying soft_constraints
|
||||||
|
model_ref model;
|
||||||
|
s.get_model(model);
|
||||||
|
|
||||||
|
expr_ref_vector result(m);
|
||||||
|
for (unsigned i = 0; i < soft_constraints.size(); ++i) {
|
||||||
|
expr_ref val(m);
|
||||||
|
VERIFY(model->eval(soft_constraints[i].get(), val));
|
||||||
|
if (!m.is_false(val)) {
|
||||||
|
result.push_back(soft_constraints[i].get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
soft_constraints.reset();
|
||||||
|
soft_constraints.append(result);
|
||||||
|
|
||||||
s.pop(1);
|
s.pop(1);
|
||||||
}
|
}
|
||||||
// we are done and soft_constraints has
|
// We are done and soft_constraints has
|
||||||
// been updated with the max-sat assignment.
|
// been updated with the max-sat assignment.
|
||||||
|
|
||||||
return is_sat;
|
return is_sat;
|
||||||
|
|
|
@ -7,7 +7,7 @@ Module Name:
|
||||||
|
|
||||||
Abstract:
|
Abstract:
|
||||||
Fu&Malik built-in optimization method.
|
Fu&Malik built-in optimization method.
|
||||||
Adapted from sample code.
|
Adapted from sample code in C.
|
||||||
|
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ Notes:
|
||||||
|
|
||||||
namespace opt {
|
namespace opt {
|
||||||
/**
|
/**
|
||||||
takes solver with hard constraints added.
|
Takes solver with hard constraints added.
|
||||||
Returns a maximal satisfying subset of soft_constraints
|
Returns a maximal satisfying subset of soft_constraints
|
||||||
that are still consistent with the solver state.
|
that are still consistent with the solver state.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue