OpenGM  2.3.x
Discrete Graphical Model Library
permutable_label_fusion_mover.hxx
Go to the documentation of this file.
1 #ifndef OPENGM_PERMUTABLE_LABEL_FUSION_MOVER_HXX
2 #define OPENGM_PERMUTABLE_LABEL_FUSION_MOVER_HXX
3 
4 
6 #ifdef WITH_CPLEX
9 #endif
11 
12 #if defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5))
13 #include <opengm/inference/cgc.hxx>
14 #endif
15 
19 
20 
21 #ifndef NOVIGRA
22 
23 #ifdef WITH_BOOST
24  #ifndef WITH_BOOST_GRAPH
25  #define WITH_BOOST_GRAPH
26  #endif
27 #endif
28 
29 #include <vigra/adjacency_list_graph.hxx>
30 #include <vigra/merge_graph_adaptor.hxx>
31 #include <vigra/hierarchical_clustering.hxx>
32 #include <vigra/priority_queue.hxx>
33 #include <vigra/random.hxx>
34 #include <vigra/graph_algorithms.hxx>
35 
36 #endif
37 
38 namespace opengm{
39 
40 
41 
42 
43 
44 
45 
46  #ifndef NOVIGRA
47  template<class GM, class ACC >
48  class McClusterOp{
49  public:
50  typedef ACC AccumulationType;
51  typedef GM GraphicalModelType;
53 
54  typedef vigra::AdjacencyListGraph Graph;
55  typedef vigra::MergeGraphAdaptor< Graph > MergeGraph;
56 
57 
58  typedef typename MergeGraph::Edge Edge;
59  typedef ValueType WeightType;
60  typedef IndexType index_type;
61  struct Parameter
62  {
63 
64 
65 
67  const float stopWeight = 0.0
68  )
69  :
70  stopWeight_(stopWeight){
71  }
72  float stopWeight_;
73  };
74 
75 
76  McClusterOp(const Graph & graph ,
77  MergeGraph & mergegraph,
78  const Parameter & param,
79  std::vector<ValueType> & weights
80  )
81  :
82  graph_(graph),
83  mergeGraph_(mergegraph),
84  pq_(graph.edgeNum()),
85  param_(param),
86  weights_(weights){
87 
88  for(size_t i=0; i<graph_.edgeNum(); ++i){
89  size_t u = graph_.id(graph_.u(graph_.edgeFromId(i)));
90  size_t v = graph_.id(graph_.v(graph_.edgeFromId(i)));
91  pq_.push(i, weights_[i]);
92  }
93  }
94 
95 
96 
97 
98  void reset(){
99  pq_.reset();
100  }
101 
102 
103 
105  index_type minLabel = pq_.top();
106  while(mergeGraph_.hasEdgeId(minLabel)==false){
107  pq_.deleteItem(minLabel);
108  minLabel = pq_.top();
109  }
110  return Edge(minLabel);
111  }
112 
114  WeightType contractionWeight(){
115  index_type minLabel = pq_.top();
116  while(mergeGraph_.hasEdgeId(minLabel)==false){
117  pq_.deleteItem(minLabel);
118  minLabel = pq_.top();
119  }
120  return pq_.topPriority();
121 
122  }
123 
125  MergeGraph & mergeGraph(){
126  return mergeGraph_;
127  }
128 
129  bool done()const{
130  return pq_.topPriority()<=ValueType(param_.stopWeight_);
131  }
132 
133  void mergeEdges(const Edge & a,const Edge & b){
134  weights_[a.id()]+=weights_[b.id()];
135  pq_.push(a.id(), weights_[a.id()]);
136  pq_.deleteItem(b.id());
137  }
138 
139  void eraseEdge(const Edge & edge){
140  pq_.deleteItem(edge.id());
141  }
142 
143  const Graph & graph_;
144  MergeGraph & mergeGraph_;
145  vigra::ChangeablePriorityQueue< ValueType ,std::greater<ValueType> > pq_;
147  std::vector<ValueType> & weights_;
148  };
149 
150 
151  #endif
152 
153 
154 
155 
156 
157 template<class GM, class ACC>
159 
160 public:
161 
162  typedef GM GraphicalModelType;
163  typedef ACC AccumulationType;
165  typedef std::map<UInt64Type, ValueType> MapType;
166  typedef typename MapType::iterator MapIter;
167  typedef typename MapType::const_iterator MapCIter;
168 
169 
171 
179  ClassicFusion
180  };
181 
182  struct Parameter{
184  const FusionSolver fusionSolver = SelfType::DefaultSolver,
185  const bool planar = false,
186  const std::string workflow = std::string(),
187  const int nThreads = 1,
188  const bool decompose = false,
189  const std::vector<bool> & allowCutsWithin = std::vector<bool>()
190  )
191  :
192  fusionSolver_(fusionSolver),
193  planar_(planar),
194  workflow_(workflow),
195  nThreads_(nThreads),
196  decompose_(decompose),
197  allowCutsWithin_(allowCutsWithin)
198  {
199 
200  }
202  bool planar_;
203  std::string workflow_;
206  std::vector<bool> allowCutsWithin_;
207 
208  };
209 
214 
215 
216  PermutableLabelFusionMove(const GraphicalModelType & gm, const Parameter & param = Parameter())
217  :
218  gm_(gm),
219  param_(param)
220  {
221  if(param_.fusionSolver_ == DefaultSolver){
222 
223  #ifdef WITH_CPLEX
224  param_.fusionSolver_ = MulticutSolver;
225  #endif
226 
227  if(param_.fusionSolver_ == DefaultSolver){
228  #if defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5))
229  param_.fusionSolver_ = CgcSolver;
230  #endif
231  }
232  if(param_.fusionSolver_ == DefaultSolver){
233  #ifndef NOVIGRA
234  if(param_.planar_){
235  param_.fusionSolver_ = HierachicalClusteringSolver;
236  }
237  #endif
238  }
239  if(param_.fusionSolver_ == DefaultSolver){
240  throw RuntimeError("WITH_CLEX || defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5)) must be enabled");
241  }
242  }
243  else if(param_.fusionSolver_ == MulticutSolver){
244  #ifndef WITH_CPLEX
245  throw RuntimeError("WITH_CLEX must be enabled for this fusionSolver");
246  #endif
247  }
248  else if(param_.fusionSolver_ == CgcSolver){
249  #if ! (defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5)) )
250  throw RuntimeError("defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5)) must be enabled for this fusionSolver");
251  #endif
252  }
253  else if(param_.fusionSolver_ == HierachicalClusteringSolver){
254  #ifndef WITH_VIGRA
255  throw RuntimeError("WITH_VIGRA must be enabled for this fusionSolver");
256  #endif
257  }
258  }
259 
260 
261 
262  void printArg(const std::vector<LabelType> arg) {
263  const size_t nx = 3; // width of the grid
264  const size_t ny = 3; // height of the grid
265  const size_t numberOfLabels = nx*ny;
266 
267  size_t i=0;
268  for(size_t y = 0; y < ny; ++y){
269 
270  for(size_t x = 0; x < nx; ++x) {
271  std::cout<<arg[i]<<" ";
272  }
273  std::cout<<"\n";
274  ++i;
275  }
276 
277  }
278 
279 
280  size_t intersect(
281  const std::vector<LabelType> & a,
282  const std::vector<LabelType> & b,
283  std::vector<LabelType> & res
284  ){
285  Partition<LabelType> ufd(gm_.numberOfVariables());
286  for(size_t fi=0; fi< gm_.numberOfFactors(); ++fi){
287  if(gm_[fi].numberOfVariables()==2){
288 
289  const size_t vi0 = gm_[fi].variableIndex(0);
290  const size_t vi1 = gm_[fi].variableIndex(1);
291 
292 
293 
294  if(a[vi0] == a[vi1] && b[vi0] == b[vi1]){
295  ufd.merge(vi0, vi1);
296  }
297  }
298  else if(gm_[fi].numberOfVariables()==1){
299 
300  }
301  else{
302  throw RuntimeError("only implemented for second order");
303  }
304  }
305  std::map<LabelType, LabelType> repr;
306  ufd.representativeLabeling(repr);
307  for(size_t vi=0; vi<gm_.numberOfVariables(); ++vi){
308  res[vi]=repr[ufd.find(vi)];
309  }
310  //std::cout<<" A\n";
311  //printArg(a);
312  //std::cout<<" B\n";
313  //printArg(b);
314  //std::cout<<" RES\n";
315  //printArg(res);
316 
317  return ufd.numberOfSets();
318  }
319 
320  bool fuse(
321  const std::vector<LabelType> & a,
322  const std::vector<LabelType> & b,
323  std::vector<LabelType> & res,
324  const ValueType valA,
325  const ValueType valB,
326  ValueType & valRes
327  ){
328 
329  if(param_.fusionSolver_ == ClassicFusion)
330  return fuseClassic(a,b,res,valA,valB,valRes);
331 
332  std::vector<LabelType> ab(gm_.numberOfVariables());
333  IndexType numNewVar = this->intersect(a, b, ab);
334  //std::cout<<"numNewVar "<<numNewVar<<"\n";
335 
336  if(numNewVar==1){
337  return false;
338  }
339 
340  const ValueType intersectedVal = gm_.evaluate(ab);
341 
342 
343 
344  // get the new smaller graph
345 
346 
347  MapType accWeights;
348  size_t erasedEdges = 0;
349  size_t notErasedEdges = 0;
350 
351 
352  LabelType lAA[2]={0, 0};
353  LabelType lAB[2]={0, 1};
354 
355 
356 
357 
358  for(size_t fi=0; fi< gm_.numberOfFactors(); ++fi){
359  if(gm_[fi].numberOfVariables()==2){
360  const size_t vi0 = gm_[fi].variableIndex(0);
361  const size_t vi1 = gm_[fi].variableIndex(1);
362 
363  const size_t cVi0 = ab[vi0] < ab[vi1] ? ab[vi0] : ab[vi1];
364  const size_t cVi1 = ab[vi0] < ab[vi1] ? ab[vi1] : ab[vi0];
365 
366  OPENGM_CHECK_OP(cVi0,<,gm_.numberOfVariables(),"");
367  OPENGM_CHECK_OP(cVi1,<,gm_.numberOfVariables(),"");
368 
369 
370  if(cVi0 == cVi1){
371  ++erasedEdges;
372  }
373  else{
374  ++notErasedEdges;
375 
376  // get the weight
377  ValueType val00 = gm_[fi](lAA);
378  ValueType val01 = gm_[fi](lAB);
379  ValueType weight = val01 - val00;
380 
381  //std::cout<<"vAA"<<val00<<" vAB "<<val01<<" w "<<weight<<"\n";
382 
383  // compute key
384  const UInt64Type key = cVi0 + numNewVar*cVi1;
385 
386  // check if key is in map
387  MapIter iter = accWeights.find(key);
388 
389  // key not yet in map
390  if(iter == accWeights.end()){
391  accWeights[key] = weight;
392  }
393  // key is in map
394  else{
395  iter->second += weight;
396  }
397 
398  }
399 
400  }
401  }
402  OPENGM_CHECK_OP(erasedEdges+notErasedEdges, == , gm_.numberOfFactors(),"something wrong");
403  //std::cout<<"erased edges "<<erasedEdges<<"\n";
404  //std::cout<<"not erased edges "<<notErasedEdges<<"\n";
405  //std::cout<<"LEFT OVER FACTORS "<<accWeights.size()<<"\n";
406 
407 
408 
409  //std::cout<<"INTERSECTED SIZE "<<numNewVar<<"\n";
410 
411  if(param_.fusionSolver_ == CgcSolver){
412  return doMoveCgc(accWeights,ab,numNewVar, a, b, res, valA, valB, valRes);
413  }
414  else if(param_.fusionSolver_ == MulticutSolver){
415  return doMoveMulticut(accWeights,ab,numNewVar, a, b, res, valA, valB, valRes);
416  }
417  else if(param_.fusionSolver_ == MulticutNativeSolver){
418  return doMoveMulticutNative(accWeights,ab,numNewVar, a, b, res, valA, valB, valRes);
419  }
420  else if(param_.fusionSolver_ == HierachicalClusteringSolver){
421  return doMoveHierachicalClustering(accWeights,ab,numNewVar, a, b, res, valA, valB, valRes);
422  }
423  else if(param_.fusionSolver_ == BaseSolver){
424  return doMoveBase(accWeights,ab,numNewVar, a, b, res, valA, valB, valRes);
425  }
426  else{
427  throw RuntimeError("unknown fusionSolver");
428  return false;
429  }
430 
431  }
432 
433 
435  const std::vector<LabelType> & a,
436  const std::vector<LabelType> & b,
437  std::vector<LabelType> & res,
438  const ValueType valA,
439  const ValueType valB,
440  ValueType & valRes
441  ){
442  LabelType maxL = *std::max_element(a.begin(), a.end());
443  std::vector<LabelType> bb = b;
444  for(size_t i=0; i<bb.size(); ++i){
445  bb[i] += maxL;
446  }
448  HlFusionMover<GM, ACC> hlf(gm_,p);
449  hlf.fuse(a,b,res, valA, valB, valRes);
450  // make dense
451  std::map<LabelType, LabelType> mdense;
452 
453  LabelType dl=0;
454  for(size_t i=0;i<res.size(); ++i){
455  const LabelType resL = res[i];
456  if(mdense.find(resL) == mdense.end()){
457  res[i] = dl;
458  ++dl;
459  }
460  else{
461  res[i] = mdense[res[i]];
462  }
463  }
464  valRes = gm_.evaluate(res);
465  if(valRes< std::min(valA,valB)){
466  // make dense
467  std::map<LabelType, LabelType> mdense;
468 
469  LabelType dl=0;
470  for(size_t i=0;i<res.size(); ++i){
471  const LabelType resL = res[i];
472  if(mdense.find(resL) == mdense.end()){
473  res[i] = dl;
474  ++dl;
475  }
476  else{
477  res[i] = mdense[res[i]];
478  }
479  }
480  }
481  else if(valA<valRes){
482  valRes=valA;
483  res = a;
484  }
485  else{
486  valRes=valB;
487  res = b;
488  }
489  assert(false); // FIXME: the return of this function was missing, just added something arbitrary
490  return false;
491  }
492 
493 
494 
495  bool doMoveCgc(
496  const MapType & accWeights,
497  const std::vector<LabelType> & ab,
498  const IndexType numNewVar,
499  const std::vector<LabelType> & a,
500  const std::vector<LabelType> & b,
501  std::vector<LabelType> & res,
502  const ValueType valA,
503  const ValueType valB,
504  ValueType & valRes
505  ){
506  #if defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5))
507 
508  // make the actual sub graphical model
509  SubSpace subSpace(numNewVar, numNewVar);
510  SubModel subGm(subSpace);
511 
512  // reserve space
513  subGm. template reserveFunctions<PFunction>(accWeights.size());
514  subGm.reserveFactors(accWeights.size());
515  subGm.reserveFactorsVarialbeIndices(accWeights.size()*2);
516 
517  for(MapCIter i = accWeights.begin(); i!=accWeights.end(); ++i){
518  const UInt64Type key = i->first;
519  const ValueType weight = i->second;
520 
521  const UInt64Type cVi1 = key/numNewVar;
522  const UInt64Type cVi0 = key - cVi1*numNewVar;
523  const UInt64Type vis[2] = {cVi0, cVi1};
524 
525  PFunction pf(numNewVar, numNewVar, 0.0, weight);
526  subGm.addFactor(subGm.addFunction(pf), vis, vis+2);
527  }
528 
529  std::vector<LabelType> subArg;
530 
531  //::cout<<"WITH MC\n";
532  typedef CGC<SubModel, Minimizer> Inf;
533  typedef typename Inf::Parameter Param;
534 
535  Param p;
536  p.planar_ = param_.planar_;
537 
538  Inf inf(subGm,p);
539  inf.infer();
540  inf.arg(subArg);
541 
542  for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
543  res[vi] = subArg[ab[vi]];
544  }
545  const ValueType resultVal = subGm.evaluate(subArg);
546  const ValueType projectedResultVal = gm_.evaluate(res);
547  const std::vector<LabelType> & bestArg = valA < valB ? a : b;
548  const ValueType bestProposalVal = valA < valB ? valA : valB;
549 
550  valRes = bestProposalVal < projectedResultVal ? bestProposalVal : projectedResultVal;
551  if(projectedResultVal < bestProposalVal){
552  //for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
553  // res[vi] = subArg[ab[vi]];
554  //}
555  }
556  else{
557  for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
558  res[vi] = bestArg[vi];
559  }
560  }
561  return true;
562  #else
563  throw RuntimeError("defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5))");
564  return false;
565  #endif
566  }
567 
569  const MapType & accWeights,
570  const std::vector<LabelType> & ab,
571  const IndexType numNewVar,
572  const std::vector<LabelType> & a,
573  const std::vector<LabelType> & b,
574  std::vector<LabelType> & res,
575  const ValueType valA,
576  const ValueType valB,
577  ValueType & valRes
578  ){
579  const std::vector<LabelType> & bestArg = valA < valB ? a : b;
580  valRes = valA < valB ? valA : valB;
581  for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
582  res[vi] = bestArg[vi];
583  }
584  return true;
585  }
586 
588  const MapType & accWeights,
589  const std::vector<LabelType> & ab,
590  const IndexType numNewVar,
591  const std::vector<LabelType> & a,
592  const std::vector<LabelType> & b,
593  std::vector<LabelType> & res,
594  const ValueType valA,
595  const ValueType valB,
596  ValueType & valRes
597  ){
598  #ifdef WITH_CPLEX
599  // make the actual sub graphical model
600  SubSpace subSpace(numNewVar, numNewVar);
601  SubModel subGm(subSpace);
602 
603  // reserve space
604  subGm. template reserveFunctions<PFunction>(accWeights.size());
605  subGm.reserveFactors(accWeights.size());
606  subGm.reserveFactorsVarialbeIndices(accWeights.size()*2);
607 
608  for(MapCIter i = accWeights.begin(); i!=accWeights.end(); ++i){
609  const UInt64Type key = i->first;
610  const ValueType weight = i->second;
611 
612  const UInt64Type cVi1 = key/numNewVar;
613  const UInt64Type cVi0 = key - cVi1*numNewVar;
614  const UInt64Type vis[2] = {cVi0, cVi1};
615 
616  PFunction pf(numNewVar, numNewVar, 0.0, weight);
617  subGm.addFactor(subGm.addFunction(pf), vis, vis+2);
618  }
619 
620  std::vector<LabelType> subArg;
621 
622  //try{
623  //::cout<<"WITH MC\n";
624  typedef Multicut<SubModel, Minimizer> McInf;
625  typedef typename McInf::Parameter McParam;
626  McParam pmc(0,0.0);
627 
628  if(param_.nThreads_ <= 0){
629  pmc.numThreads_ = 0;
630  }
631  else{
632  pmc.numThreads_ = param_.nThreads_;
633  }
634  pmc.workFlow_ = param_.workflow_;
635 
636 
637  if(param_.decompose_ == false){
638  McInf inf(subGm,pmc);
639  inf.infer();
640  inf.arg(subArg);
641  }
642  else{
643  typedef DMC<SubModel, McInf> DmcInf;
644  typedef typename DmcInf::Parameter DmcParam;
645  typedef typename DmcInf::InfParam DmcInfParam;
646  DmcParam dmcParam;
647  DmcInfParam dmcInfParam(pmc);
648 
649  dmcParam.infParam_ = dmcInfParam;
650 
651  DmcInf inf(subGm, dmcParam);
652  inf.infer();
653  inf.arg(subArg);
654  }
655  //}
656  //catch(...){
657  // std::cout<<"error from cplex\n....\n";
658  //}
659 
660  for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
661  res[vi] = subArg[ab[vi]];
662  }
663  const ValueType resultVal = subGm.evaluate(subArg);
664  const ValueType projectedResultVal = gm_.evaluate(res);
665  const std::vector<LabelType> & bestArg = valA < valB ? a : b;
666  const ValueType bestProposalVal = valA < valB ? valA : valB;
667 
668  valRes = bestProposalVal < projectedResultVal ? bestProposalVal : projectedResultVal;
669  if(projectedResultVal < bestProposalVal){
670  //for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
671  // res[vi] = subArg[ab[vi]];
672  //}
673  }
674  else{
675  for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
676  res[vi] = bestArg[vi];
677  }
678  }
679  return true;
680  #else
681  throw RuntimeError("needs WITH_CPLEX");
682  return false;
683  #endif
684  }
685 
686 
688  const MapType & accWeights,
689  const std::vector<LabelType> & ab,
690  const IndexType numNewVar,
691  const std::vector<LabelType> & a,
692  const std::vector<LabelType> & b,
693  std::vector<LabelType> & res,
694  const ValueType valA,
695  const ValueType valB,
696  ValueType & valRes
697  ){
698  #ifdef WITH_CPLEX
699  std::vector<LabelType> subArg;
700 
701  //::cout<<"WITH MC\n";
702  typedef Multicut<SubModel, Minimizer> Inf;
703  typedef typename Inf::Parameter Param;
704  Param p(0,0.0);
705 
706  if(param_.nThreads_ <= 0){
707  p.numThreads_ = 0;
708  }
709  else{
710  p.numThreads_ = param_.nThreads_;
711  }
712  p.workFlow_ = param_.workflow_;
713 
714  Inf inf(numNewVar, accWeights, p);
715  inf.infer();
716  inf.arg(subArg);
717 
718 
719 
720  for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
721  res[vi] = subArg[ab[vi]];
722  }
723 
724  const ValueType projectedResultVal = gm_.evaluate(res);
725  const std::vector<LabelType> & bestArg = valA < valB ? a : b;
726  const ValueType bestProposalVal = valA < valB ? valA : valB;
727 
728  valRes = bestProposalVal < projectedResultVal ? bestProposalVal : projectedResultVal;
729  if(projectedResultVal < bestProposalVal){
730  //for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
731  // res[vi] = subArg[ab[vi]];
732  //}
733  }
734  else{
735  for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
736  res[vi] = bestArg[vi];
737  }
738  }
739  return true;
740  #else
741  throw RuntimeError("needs WITH_CPLEX");
742  return false;
743  #endif
744  }
745 
747  const MapType & accWeights,
748  const std::vector<LabelType> & ab,
749  const IndexType numNewVar,
750  const std::vector<LabelType> & a,
751  const std::vector<LabelType> & b,
752  std::vector<LabelType> & res,
753  const ValueType valA,
754  const ValueType valB,
755  ValueType & valRes
756  ){
757  #ifndef NOVIGRA
758  typedef vigra::AdjacencyListGraph Graph;
759  typedef typename Graph::Edge Edge;
760  typedef vigra::MergeGraphAdaptor< Graph > MergeGraph;
761  typedef McClusterOp<GM,ACC> ClusterOp;
762  typedef typename ClusterOp::Parameter ClusterOpParam;
763  typedef vigra::HierarchicalClusteringImpl< ClusterOp > HC;
764  typedef typename HC::Parameter HcParam;
765 
766  std::vector<ValueType> weights(accWeights.size(),0.0);
767 
768  Graph graph(numNewVar, accWeights.size());
769  for(MapCIter i = accWeights.begin(); i!=accWeights.end(); ++i){
770  const UInt64Type key = i->first;
771  const ValueType weight = i->second;
772 
773  const UInt64Type cVi1 = key/numNewVar;
774  const UInt64Type cVi0 = key - cVi1*numNewVar;
775 
776  const Edge e = graph.addEdge(cVi0, cVi1);
777  weights[graph.id(e)] = weight;
778  }
779 
780  MergeGraph mg(graph);
781 
782 
783 
784 
785  const ClusterOpParam clusterOpParam;
786  ClusterOp clusterOp(graph, mg, clusterOpParam, weights);
787 
788 
789 
790 
791  HcParam p;
792  HC hc(clusterOp,p);
793 
794  //std::cout<<"start\n";
795  hc.cluster();
796 
797 
798 
799  for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
800  res[vi] = hc.reprNodeId(ab[vi]);
801  }
802 
803  const ValueType projectedResultVal = gm_.evaluate(res);
804  const std::vector<LabelType> & bestArg = valA < valB ? a : b;
805  const ValueType bestProposalVal = valA < valB ? valA : valB;
806 
807  valRes = bestProposalVal < projectedResultVal ? bestProposalVal : projectedResultVal;
808  if(projectedResultVal < bestProposalVal){
809  //for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
810  // res[vi] = subArg[ab[vi]];
811  //}
812  }
813  else{
814  for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
815  res[vi] = bestArg[vi];
816  }
817  }
818  return true;
819  #else
820  throw RuntimeError("needs VIGRA");
821  return false;
822  #endif
823  }
824 
825 private:
826  const GM & gm_;
828 };
829 
830 
831 
832 
833 
834 }
835 
836 
837 #endif /* OPENGM_PERMUTABLE_LABEL_FUSION_MOVER_HXX */
IndexType addFactor(const FunctionIdentifier &, ITERATOR, ITERATOR)
add a factor to the graphical model
The OpenGM namespace.
Definition: config.hxx:43
MergeGraph & mergeGraph()
get a reference to the merge
McClusterOp(const Graph &graph, MergeGraph &mergegraph, const Parameter &param, std::vector< ValueType > &weights)
PermutableLabelFusionMove< GM, ACC > SelfType
vigra::AdjacencyListGraph Graph
SimpleDiscreteSpace< IndexType, LabelType > SubSpace
size_t intersect(const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res)
FunctionIdentifier addFunction(const FUNCTION_TYPE &)
add a function to the graphical model
void merge(value_type, value_type)
Merge two sets.
Definition: partition.hxx:147
Discrete space in which all variables have the same number of labels.
void printArg(const std::vector< LabelType > arg)
void reserveFactors(const size_t numF)
bool doMoveHierachicalClustering(const MapType &accWeights, const std::vector< LabelType > &ab, const IndexType numNewVar, const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
detail_types::UInt64Type UInt64Type
uint64
Definition: config.hxx:300
Experimental Multicut.
Definition: cgc.hxx:121
PermutableLabelFusionMove(const GraphicalModelType &gm, const Parameter &param=Parameter())
void mergeEdges(const Edge &a, const Edge &b)
PottsFunction< ValueType, IndexType, LabelType > PFunction
Parameter(const FusionSolver fusionSolver=SelfType::DefaultSolver, const bool planar=false, const std::string workflow=std::string(), const int nThreads=1, const bool decompose=false, const std::vector< bool > &allowCutsWithin=std::vector< bool >())
bool doMoveBase(const MapType &accWeights, const std::vector< LabelType > &ab, const IndexType numNewVar, const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
WeightType contractionWeight()
get the edge weight of the edge which should be contracted next
bool doMoveMulticut(const MapType &accWeights, const std::vector< LabelType > &ab, const IndexType numNewVar, const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
void reserveFactorsVarialbeIndices(const size_t size)
vigra::MergeGraphAdaptor< Graph > MergeGraph
bool doMoveMulticutNative(const MapType &accWeights, const std::vector< LabelType > &ab, const IndexType numNewVar, const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
bool doMoveCgc(const MapType &accWeights, const std::vector< LabelType > &ab, const IndexType numNewVar, const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
bool fuse(const LabelVector &argA, const LabelVector argB, LabelVector &argRes, const ValueType valA, const ValueType valB, ValueType &valRes)
ExplicitFunction< ValueType, IndexType, LabelType > EFunction
std::map< UInt64Type, ValueType > MapType
#define OPENGM_CHECK_OP(A, OP, B, TXT)
Definition: submodel2.hxx:24
Potts function for two variables.
Definition: potts.hxx:19
std::vector< ValueType > & weights_
Disjoint set data structure with path compression.
Definition: partition.hxx:13
bool fuse(const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
ValueType evaluate(ITERATOR) const
evaluate the modeled function for a given labeling
GraphicalModel< ValueType, Adder, OPENGM_TYPELIST_2(EFunction, PFunction), SubSpace > SubModel
OpenGM runtime error.
Definition: opengm.hxx:100
bool fuseClassic(const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
vigra::ChangeablePriorityQueue< ValueType,std::greater< ValueType > > pq_