mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 17:45:32 +00:00
Fu&Malik v1
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
ac97a12bb8
commit
45eda6c6ad
2 changed files with 178 additions and 0 deletions
144
src/opt/fu_malik.cpp
Normal file
144
src/opt/fu_malik.cpp
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
fu_malik.cpp
|
||||
|
||||
Abstract:
|
||||
Fu&Malik built-in optimization method.
|
||||
Adapted from sample code.
|
||||
|
||||
Author:
|
||||
|
||||
Anh-Dung Phan (t-anphan) 2013-10-15
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
|
||||
#include "fu_malik.h"
|
||||
|
||||
/**
|
||||
\brief Fu & Malik procedure for MaxSAT. This procedure is based on
|
||||
unsat core extraction and the at-most-one constraint.
|
||||
|
||||
Return the number of soft-constraints that can be
|
||||
satisfied. Return -1 if the hard-constraints cannot be
|
||||
satisfied. That is, the formula cannot be satisfied even if all
|
||||
soft-constraints are ignored.
|
||||
|
||||
For more information on the Fu & Malik procedure:
|
||||
|
||||
Z. Fu and S. Malik, On solving the partial MAX-SAT problem, in International
|
||||
Conference on Theory and Applications of Satisfiability Testing, 2006.
|
||||
*/
|
||||
namespace opt {
|
||||
|
||||
class fu_malik {
|
||||
ast_manager& m;
|
||||
solver& s;
|
||||
expr_ref_vector& m_soft;
|
||||
expr_ref_vector m_aux;
|
||||
public:
|
||||
fu_malik(ast_manager& m, solver& s, expr_ref_vector& soft):
|
||||
m(m),
|
||||
s(s),
|
||||
m_soft(soft),
|
||||
m_aux_vars(m)
|
||||
{
|
||||
m_aux.reset();
|
||||
for (unsigned i = 0; i < m_soft.size(); i++) {
|
||||
m_aux.push_back(m.mk_fresh_const("p",m.mk_bool()));
|
||||
s.assert_expr(m.mk_or(m_soft[i].get(), m_aux[i].get()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Implement one step of the Fu&Malik algorithm.
|
||||
See fu_malik_maxsat function for more details.
|
||||
|
||||
Input: soft constraints + aux-vars (aka answer literals)
|
||||
Output: done/not-done when not done return updated set of soft-constraints and aux-vars.
|
||||
- if SAT --> terminates
|
||||
- if UNSAT
|
||||
* compute unsat core
|
||||
* add blocking variable to soft-constraints in the core
|
||||
- replace soft-constraint with the one with the blocking variable
|
||||
- we should also add an aux-var
|
||||
- replace aux-var with a new one
|
||||
* add at-most-one constraint with blocking
|
||||
*/
|
||||
|
||||
bool step() {
|
||||
expr_ref_vector assumptions(m), block_vars(m);
|
||||
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
||||
assumptions.push_back(m.mk_not(m_aux[i].get()));
|
||||
}
|
||||
lbool is_sat = s.check_sat(assumptions.size(), assumptions.c_ptr());
|
||||
if (is_sat != l_false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ptr_vector<expr> core;
|
||||
s.get_unsat_core(core);
|
||||
|
||||
// update soft-constraints and aux_vars
|
||||
for (i = 0; i < m_soft.size(); i++) {
|
||||
|
||||
bool found = false;
|
||||
for (unsigned j = 0; !found && j < core.size(); ++j) {
|
||||
found = m_soft[i].get() == core[j];
|
||||
}
|
||||
if (!found) {
|
||||
continue;
|
||||
}
|
||||
expr_ref block_var(m);
|
||||
block_var = m.mk_fresh_const("block_var", m.mk_bool_sort());
|
||||
m_aux[i] = m.mk_fresh_const("aux", m.mk_bool_sort());
|
||||
m_soft[i] = m.mk_or(m_soft[i].get(), block_var);
|
||||
block_vars.push_back(block_var);
|
||||
s.assert_expr(m.mk_or(m_soft[i].get(), m_aux[i].get()));
|
||||
}
|
||||
assert_at_most_one(block_vars);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void assert_at_most_one(expr_ref_vector const& block_vars) {
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
expr_ref mk_at_most_one(unsigned n, expr* const * vars) {
|
||||
if (n <= 1) {
|
||||
return expr_ref(m.mk_true(), m);
|
||||
}
|
||||
unsigned mid = n/2;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
lbool fu_malik_maxsat(solver& s, expr_ref_vector& soft_constraints) {
|
||||
ast_manager m = soft_constraints.get_manager();
|
||||
lbool is_sat = s.check();
|
||||
if (is_sat != l_true) {
|
||||
return is_sat;
|
||||
}
|
||||
if (soft_constraints.empty()) {
|
||||
return is_sat;
|
||||
}
|
||||
s.push();
|
||||
fu_malik fm(m, s, soft_constraints);
|
||||
while (!fm.step());
|
||||
s.pop();
|
||||
// we are done and soft_constraints has been updated with the max-sat assignment.
|
||||
}
|
||||
};
|
||||
|
||||
|
34
src/opt/fu_malik.h
Normal file
34
src/opt/fu_malik.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
fu_malik.h
|
||||
|
||||
Abstract:
|
||||
Fu&Malik built-in optimization method.
|
||||
Adapted from sample code.
|
||||
|
||||
Author:
|
||||
|
||||
Anh-Dung Phan (t-anphan) 2013-10-15
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _OPT_FU_MALIK_H_
|
||||
#define _OPT_FU_MALIK_H_
|
||||
|
||||
#include "solver.h"
|
||||
|
||||
namespace opt {
|
||||
/**
|
||||
takes solver with hard constraints added.
|
||||
Returns a maximal satisfying subset of soft_constraints
|
||||
that are still consistent with the solver state.
|
||||
*/
|
||||
|
||||
lbool fu_malik_maxsat(solver& s, expr_ref_vector& soft_constraints);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue