2 #ifndef OPENGM_PARTITIONMOVE_HXX
3 #define OPENGM_PARTITIONMOVE_HXX
15 #include <boost/unordered_map.hpp>
16 #include <boost/unordered_set.hpp>
18 #include <ext/hash_map>
19 #include <ext/hash_set>
38 template<
class GM,
class ACC>
50 typedef boost::unordered_map<IndexType, LPIndexType>
EdgeMapType;
53 typedef __gnu_cxx::hash_map<IndexType, LPIndexType>
EdgeMapType;
63 PartitionMove(
const GraphicalModelType&, Parameter para=Parameter());
64 virtual std::string
name()
const {
return "PartitionMove";}
71 enum ProblemType {INVALID, MC, MWC};
73 const GraphicalModelType& gm_;
74 ProblemType problemType_;
78 LPIndexType numberOfInternalEdges_;
83 std::vector<EdgeMapType > neighbours_;
84 std::vector<double> edgeWeight_;
86 std::vector<LabelType> states_;
89 double solveBinaryKL(VariableSetType&, VariableSetType&);
94 template<
class GM,
class ACC>
99 template<
class GM,
class ACC>
102 const GraphicalModelType& gm,
104 ) : gm_(gm), parameter_(para)
107 throw RuntimeError(
"This implementation does only supports Min-Plus-Semiring.");
113 numberOfInternalEdges_ = 0;
114 numberOfTerminals_ = gm_.numberOfLabels(0);
115 for(
size_t i=0; i<gm_.numberOfVariables(); ++i){
116 if(gm_.numberOfLabels(i)<gm_.numberOfVariables()) {
118 numberOfTerminals_ = std::max(numberOfTerminals_ ,gm_.numberOfLabels(i));
121 for(
size_t f=0; f<gm_.numberOfFactors();++f) {
122 if(gm_[f].numberOfVariables()==0) {
125 else if(gm_[f].numberOfVariables()==1) {
128 else if(gm_[f].numberOfVariables()==2) {
129 ++numberOfInternalEdges_;
130 if(!gm_[f].isPotts()) {
131 problemType_ = INVALID;
136 problemType_ = INVALID;
141 if(problemType_ == INVALID)
142 throw RuntimeError(
"Invalid Model for Multicut-Solver! Solver requires a potts model!");
143 if(problemType_ == MWC)
144 throw RuntimeError(
"Invalid Model for Multicut-Solver! Solver currently do not support first order terms!");
148 neighbours_.resize(gm_.numberOfVariables());
149 edgeWeight_.resize(numberOfInternalEdges_,0);
151 LPIndexType numberOfInternalEdges=0;
153 for(
size_t f=0; f<gm_.numberOfFactors(); ++f) {
154 if(gm_[f].numberOfVariables()==0) {
156 constant_+=gm_[f](&l);
158 else if(gm_[f].numberOfVariables()==2) {
161 edgeWeight_[numberOfInternalEdges] += gm_[f](cc1) - gm_[f](cc0);
162 constant_ += gm_[f](cc0);
165 neighbours_[u][v] = numberOfInternalEdges;
166 neighbours_[v][u] = numberOfInternalEdges;
167 ++numberOfInternalEdges;
170 throw RuntimeError(
"Only supports second order Potts functions!");
173 OPENGM_ASSERT(numberOfInternalEdges==numberOfInternalEdges_);
175 states_.resize(gm_.numberOfVariables(),0);
179 for(
size_t i=0; i<states_.size();++i){
180 states_[i]=rand()%10;
186 std::vector<bool> assigned(states_.size(),
false);
187 for(
IndexType node=0; node<states_.size(); ++node) {
191 std::list<IndexType> nodeList;
193 assigned[node] =
true;
194 nodeList.push_back(node);
195 while(!nodeList.empty()) {
196 size_t n=nodeList.front(); nodeList.pop_front();
197 for(
typename EdgeMapType::const_iterator it=neighbours_[n].begin() ; it != neighbours_[n].end(); ++it) {
199 if(!assigned[node2] && edgeWeight_[(*it).second]>0) {
201 assigned[node2] =
true;
202 nodeList.push_back(node2);
212 for(
size_t i=0; i<states_.size();++i){
221 template <
class GM,
class ACC>
225 EmptyVisitorType visitor;
226 return infer(visitor);
230 template <
class GM,
class ACC>
231 template<
class VisitorType>
235 visitor.begin(*
this);
241 template <
class GM,
class ACC>
242 template<
class VisitorType>
247 std::vector<VariableSetType> partitionSets;
251 for(
size_t i=0; i<states_.size(); ++i)
252 if(states_[i]+1>numberOfPartitions) numberOfPartitions=states_[i]+1;
253 partitionSets.resize(numberOfPartitions);
254 for(IndexType i=0; i<states_.size(); ++i){
255 partitionSets[states_[i]].insert(i);
262 std::vector<size_t> pruneSets;
264 for(
size_t part0=0; part0<numberOfPartitions; ++part0){
267 std::set<size_t> neighbordSets;
268 for(
typename VariableSetType::const_iterator it=partitionSets[part0].begin(); it!=partitionSets[part0].end(); ++it){
269 const IndexType node = (*it);
270 for(
typename EdgeMapType::const_iterator nit=neighbours_[node].begin() ; nit != neighbours_[node].end(); ++nit) {
271 const IndexType node2 = (*nit).first;
272 if(states_[node2]>part0){
273 neighbordSets.insert(states_[node2]);
277 for(std::set<size_t>::const_iterator it=neighbordSets.begin(); it!=neighbordSets.end();++it){
280 if(partitionSets[part0].size()==0 || partitionSets[part1].size()==0)
282 double improvement = solveBinaryKL(partitionSets[part0],partitionSets[part1]);
285 if(-1e-8>improvement){
291 for(
size_t part0=0; part0<numberOfPartitions; ++part0){
293 if(partitionSets[part0].size()==0){
295 pruneSets.push_back(part0);
298 else if(partitionSets[part0].size()>1){
301 VariableSetType emptySet(partitionSets[part0].size());
302 double improvement = solveBinaryKL(partitionSets[part0], emptySet);
303 if(emptySet.size()>0){
305 partitionSets.push_back(emptySet);
312 for(
size_t i=0; i<pruneSets.size(); ++i){
313 size_t part = pruneSets[pruneSets.size()-1-i];
314 partitionSets.erase( partitionSets.begin()+part);
317 numberOfPartitions = partitionSets.size();
318 for(
size_t part=0; part<numberOfPartitions; ++part){
319 for(
typename VariableSetType::const_iterator it=partitionSets[part].begin(); it!=partitionSets[part].end(); ++it){
330 template <
class GM,
class ACC>
331 double PartitionMove<GM,ACC>::solveBinaryKL
333 VariableSetType& set0,
334 VariableSetType& set1
337 double improvement = 0.0;
340 for(
size_t outerIt=0; outerIt<100;++outerIt){
342 std::vector<double> D(gm_.numberOfVariables(),0);
343 for(
typename VariableSetType::const_iterator it=set0.begin(); it!=set0.end(); ++it){
346 const IndexType node = *it;
347 for (
typename EdgeMapType::const_iterator eit=neighbours_[node].begin(); eit!=neighbours_[node].end(); ++eit){
348 const IndexType node2 = (*eit).first;
349 const double weight = edgeWeight_[(*eit).second];
351 if (set0.find(node2) != set0.end()) {
354 else if(set1.find(node2) != set1.end()){
358 D[node] = -(E_a - I_a);
360 for(
typename VariableSetType::const_iterator it=set1.begin(); it!=set1.end(); ++it){
363 const IndexType node = *it;
364 for(
typename EdgeMapType::const_iterator eit=neighbours_[node].begin(); eit!=neighbours_[node].end(); ++eit){
365 const IndexType node2 = (*eit).first;
366 const double weight = edgeWeight_[(*eit).second];
368 if (set1.find(node2) != set1.end()) {
371 else if(set0.find(node2) != set0.end()){
375 D[node] = -(E_a - I_a);
379 for(
size_t i=0; i<D.size(); ++i){
386 std::vector<bool> isMovedNode(gm_.numberOfVariables(),
false);
387 std::vector<IndexType> nodeSequence;
388 std::vector<double> improveSequence;
389 std::vector<double> improveSumSequence(1,0.0);
393 for(
size_t innerIt=0; innerIt<1000; ++innerIt){
394 double improve = std::numeric_limits<double>::infinity();
398 for(
typename VariableSetType::const_iterator it=set0.begin(); it!=set0.end(); ++it){
399 if(isMovedNode[*it]){
411 for(
typename VariableSetType::const_iterator it=set1.begin(); it!=set1.end(); ++it){
412 if(isMovedNode[*it]){
431 isMovedNode[node]=
true;
432 nodeSequence.push_back(node);
433 improveSumSequence.push_back(improveSumSequence.back()+improve);
434 improveSequence.push_back(improve);
435 if (improveSumSequence[bestMove]>improveSumSequence.back()) {
436 bestMove = improveSumSequence.size()-1;
439 VariableSetType& mySet = set0.find(node) != set0.end() ? set0 : set1;
440 for(
typename EdgeMapType::const_iterator eit=neighbours_[node].begin(); eit!=neighbours_[node].end(); ++eit){
441 IndexType node2 = (*eit).first;
442 double weight = edgeWeight_[(*eit).second];
443 if(mySet.find(node2) != mySet.end()){
444 D[node2] -= 2.0 * weight;
447 D[node2] += 2.0 * weight;
454 if(improveSumSequence[bestMove]>-1e-10)
457 improvement += improveSumSequence[bestMove];
458 for (
size_t i = 0; i < bestMove; ++i) {
459 int node = nodeSequence[i];
460 if (set0.find(node) != set0.end()) {
475 template <
class GM,
class ACC>
487 x.resize(gm_.numberOfVariables());
488 for(
size_t i=0; i<gm_.numberOfVariables(); ++i)
PartitionMove(const GraphicalModelType &, Parameter para=Parameter())
visitors::TimingVisitor< PartitionMove< GM, ACC > > TimingVisitorType
Addition as a binary operation.
virtual InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
output a solution
#define OPENGM_ASSERT(expression)
GraphicalModelType::OperatorType OperatorType
__gnu_cxx::hash_set< IndexType > VariableSetType
visitors::EmptyVisitor< PartitionMove< GM, ACC > > EmptyVisitorType
GraphicalModelType::IndexType IndexType
__gnu_cxx::hash_map< IndexType, LPIndexType > EdgeMapType
visitors::VerboseVisitor< PartitionMove< GM, ACC > > VerboseVisitorType
Inference algorithm interface.
const GraphicalModelType & graphicalModel() const
virtual InferenceTermination infer()
GraphicalModelType::LabelType LabelType
Minimization as a unary accumulation.
virtual std::string name() const
static const size_t ContinueInf
Partition Move Currently Partition Move only implements the Kernighan-Lin-Algorithm.