OpenGM  2.3.x
Discrete Graphical Model Library
lazyflipper.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_LAZYFLIPPER_HXX
3 #define OPENGM_LAZYFLIPPER_HXX
4 
5 #include <vector>
6 #include <set>
7 #include <string>
8 #include <iostream>
9 #include <stdexcept>
10 #include <list>
11 
12 #include "opengm/opengm.hxx"
18 
19 namespace opengm {
20 
22 
23 template<class T>
24 class Tagging {
25 public:
26  typedef T ValueType;
27  typedef std::vector<ValueType> tag_container_type;
28  typedef std::vector<size_t> index_container_type;
29  typedef index_container_type::const_iterator const_iterator;
30 
31  Tagging(const size_t = 0);
32  void append(const size_t);
33  ValueType tag(const size_t) const;
34  void tag(const size_t, const typename Tagging<T>::ValueType);
35  void untag(); // untag all
36  const_iterator begin();
37  const_iterator begin() const;
38  const_iterator end();
39  const_iterator end() const;
40 
41 private:
42  tag_container_type tags_;
43  index_container_type indices_;
44 };
45 
46 // A simple undirected graph
47 class Adjacency {
48 public:
49  typedef std::set<size_t>::const_iterator const_iterator;
50 
51  Adjacency(const size_t = 0);
52  void resize(const size_t);
53  void connect(const size_t, const size_t);
54  bool connected(const size_t, const size_t) const;
55  const_iterator neighborsBegin(const size_t);
56  const_iterator neighborsBegin(const size_t) const;
57  const_iterator neighborsEnd(const size_t);
58  const_iterator neighborsEnd(const size_t) const;
59 
60 private:
61  std::vector<std::set<size_t> > neighbors_;
62 };
63 
64 // Forest with Level Order Traversal.
65 //
66 // - no manipulation after construction.
67 // - level Successors must be set manually
68 // - implementation nor const correct
69 //
70 template<class T>
71 class Forest {
72 public:
73  typedef T Value;
74  typedef size_t NodeIndex;
75  typedef size_t Level;
76 
77  static const NodeIndex NONODE = -1;
78 
79  Forest();
80  size_t size();
81  size_t levels();
82  NodeIndex levelAnchor(const Level&);
83  NodeIndex push_back(const Value&, NodeIndex);
84  size_t testInvariant();
85  std::string asString();
86  Value& value(NodeIndex);
87  Level level(NodeIndex);
88  NodeIndex parent(NodeIndex);
89  NodeIndex levelOrderSuccessor(NodeIndex);
90  size_t numberOfChildren(NodeIndex);
91  NodeIndex child(NodeIndex, const size_t);
92  void setLevelOrderSuccessor(NodeIndex, NodeIndex);
93 
94 private:
95  struct Node {
96  Node(const Value& value)
97  : value_(value), parent_(NONODE),
98  children_(std::vector<NodeIndex>()),
99  level_(0), levelOrderSuccessor_(NONODE)
100  {}
101  Value value_;
102  NodeIndex parent_;
103  std::vector<NodeIndex> children_;
104  Level level_;
105  NodeIndex levelOrderSuccessor_;
106  };
107  std::vector<Node> nodes_;
108  std::vector<NodeIndex> levelAnchors_;
109 };
110 
112 
117 template<class GM, class ACC = Minimizer>
118 class LazyFlipper : public Inference<GM, ACC> {
119 public:
120 
121  template<class _GM>
122  struct RebindGm{
124  };
125 
126  template<class _GM,class _ACC>
129  };
130 
131 
132  typedef ACC AccumulationType;
133  typedef GM GraphicalModelType;
135  typedef Forest<IndexType> SubgraphForest;
136  typedef size_t SubgraphForestNode;
137  static const SubgraphForestNode NONODE = SubgraphForest::NONODE;
141 
142  struct Parameter
143  {
144  template<class StateIterator>
146  const size_t maxSubgraphSize,
147  StateIterator stateBegin,
148  StateIterator stateEnd,
149  const Tribool inferMultilabel = Tribool::Maybe
150  )
151  : maxSubgraphSize_(maxSubgraphSize),
152  startingPoint_(stateBegin, stateEnd),
153  inferMultilabel_(inferMultilabel)
154  {}
155 
157  const size_t maxSubgraphSize = 2,
158  const Tribool inferMultilabel = Tribool::Maybe
159  )
160  : maxSubgraphSize_(maxSubgraphSize),
161  startingPoint_(),
162  inferMultilabel_(inferMultilabel)
163  {}
164 
165  template<class P>
167  const P & p
168  )
169  : maxSubgraphSize_(p.maxSubgraphSize_),
170  startingPoint_(p.startingPoint_),
171  inferMultilabel_(p.inferMultilabel_)
172  {}
173 
175  std::vector<LabelType> startingPoint_;
177  };
178 
179  //LazyFlipper(const GraphicalModelType&, const size_t = 2, const Tribool useMultilabelInference = Tribool::Maybe);
180  LazyFlipper(const GraphicalModelType& gm, Parameter param = Parameter());
181  //template<class StateIterator>
182  //LazyFlipper(const GraphicalModelType&, const size_t, StateIterator, const Tribool useMultilabelInference = Tribool::Maybe);
183  std::string name() const;
184  const GraphicalModelType& graphicalModel() const;
185  const size_t maxSubgraphSize() const;
186  ValueType value() const;
187  void setMaxSubgraphSize(const size_t);
188  void reset();
190  template<class VisitorType>
191  InferenceTermination infer(VisitorType&);
192  void setStartingPoint(typename std::vector<LabelType>::const_iterator);
193  InferenceTermination arg(std::vector<LabelType>&, const size_t = 1)const;
194 
195 private:
196  InferenceTermination inferBinaryLabel();
197  template<class VisitorType>
198  InferenceTermination inferBinaryLabel(VisitorType&);
199  template<class VisitorType>
200  InferenceTermination inferMultiLabel(VisitorType&);
201  InferenceTermination inferMultiLabel();
202 
203  SubgraphForestNode appendVariableToPath(SubgraphForestNode);
204  SubgraphForestNode generateFirstPathOfLength(const size_t);
205  SubgraphForestNode generateNextPathOfSameLength(SubgraphForestNode);
206  void activateInfluencedVariables(SubgraphForestNode, const size_t);
207  void deactivateAllVariables(const size_t);
208  SubgraphForestNode firstActivePath(const size_t);
209  SubgraphForestNode nextActivePath(SubgraphForestNode, const size_t);
210  ValueType energyAfterFlip(SubgraphForestNode);
211  void flip(SubgraphForestNode);
212  const bool flipMultiLabel(SubgraphForestNode); // ???
213 
214  const GraphicalModelType& gm_;
215  Adjacency variableAdjacency_;
217  Tagging<bool> activation_[2];
218  SubgraphForest subgraphForest_;
219  size_t maxSubgraphSize_;
220  Tribool useMultilabelInference_;
221 };
222 
223 // implementation of Tagging
224 
225 template<class T>
226 inline Tagging<T>::Tagging(
227  const size_t size
228 )
229 : tags_(tag_container_type(size)),
230  indices_(index_container_type())
231 {}
232 
233 template<class T>
234 inline void Tagging<T>::append(
235  const size_t number
236 )
237 {
238  tags_.resize(tags_.size() + number);
239 }
240 
241 // runtime complexity: constant
242 template<class T>
243 inline typename Tagging<T>::ValueType
244 Tagging<T>::tag(
245  const size_t index
246 ) const
247 {
248  OPENGM_ASSERT(index < tags_.size());
249  return tags_[index];
250 }
251 
252 // runtime complexity: constant
253 template<class T>
254 inline void
255 Tagging<T>::tag(
256  const size_t index,
257  const typename Tagging<T>::ValueType tag
258 )
259 {
260  OPENGM_ASSERT(index < tags_.size());
261  OPENGM_ASSERT(tag != T()); // no implicit un-tagging
262  if(tags_[index] == T()) { // so far un-tagged
263  indices_.push_back(index);
264  }
265  tags_[index] = tag;
266 }
267 
268 // untag all
269 // runtime complexity: linear in indices_.size()
270 // note the performance gain over linearity in tags_.size()
271 template<class T>
272 inline void
273 Tagging<T>::untag()
274 {
275  for(const_iterator it = indices_.begin(); it != indices_.end(); ++it) {
276  tags_[*it] = T();
277  }
278  indices_.clear();
279 }
280 
281 template<class T>
282 inline typename Tagging<T>::const_iterator
283 Tagging<T>::begin() const
284 {
285  return indices_.begin();
286 }
287 
288 template<class T>
289 inline typename Tagging<T>::const_iterator
290 Tagging<T>::end() const
291 {
292  return indices_.end();
293 }
294 
295 template<class T>
296 inline typename Tagging<T>::const_iterator
297 Tagging<T>::begin()
298 {
299  return indices_.begin();
300 }
301 
302 template<class T>
303 inline typename Tagging<T>::const_iterator
304 Tagging<T>::end()
305 {
306  return indices_.end();
307 }
308 
309 // implementation of Adjacency
310 inline
311 Adjacency::Adjacency(
312  const size_t size
313 )
314 : neighbors_(std::vector<std::set<size_t> >(size))
315 {}
316 
317 inline void
318 Adjacency::resize(
319  const size_t size
320 )
321 {
322  neighbors_.resize(size);
323 }
324 
325 inline void
326 Adjacency::connect
327 (
328  const size_t j,
329  const size_t k
330 )
331 {
332  neighbors_[j].insert(k);
333  neighbors_[k].insert(j);
334 }
335 
336 inline bool
337 Adjacency::connected(
338  const size_t j,
339  const size_t k
340 ) const
341 {
342  if(neighbors_[j].size() < neighbors_[k].size()) {
343  if(neighbors_[j].find(k) == neighbors_[j].end()) {
344  return false;
345  }
346  else {
347  return true;
348  }
349  }
350  else {
351  if(neighbors_[k].find(j) == neighbors_[k].end()) {
352  return false;
353  }
354  else {
355  return true;
356  }
357  }
358 }
359 
360 inline Adjacency::const_iterator
361 Adjacency::neighborsBegin(
362  const size_t index
363 )
364 {
365  return neighbors_[index].begin();
366 }
367 
368 inline Adjacency::const_iterator
369 Adjacency::neighborsBegin(
370  const size_t index
371 ) const
372 {
373  return neighbors_[index].begin();
374 }
375 
376 inline Adjacency::const_iterator
377 Adjacency::neighborsEnd(
378  const size_t index
379 )
380 {
381  return neighbors_[index].end();
382 }
383 
384 inline Adjacency::const_iterator
385 Adjacency::neighborsEnd(
386  const size_t index
387 ) const
388 {
389  return neighbors_[index].end();
390 }
391 
392 // implementation
393 
394 template<class T>
395 inline Forest<T>::Forest()
396 : nodes_(std::vector<typename Forest<T>::Node>()),
397  levelAnchors_(std::vector<typename Forest<T>::NodeIndex>())
398 {}
399 
400 template<class T>
401 inline size_t
402 Forest<T>::levels()
403 {
404  return levelAnchors_.size();
405 }
406 
407 template<class T>
408 inline size_t
409 Forest<T>::size()
410 {
411  return nodes_.size();
412 }
413 
414 template<class T>
415 inline typename Forest<T>::NodeIndex
416 Forest<T>::levelAnchor(
417  const typename Forest<T>::Level& level
418 )
419 {
420  OPENGM_ASSERT(level < levels());
421  return levelAnchors_[level];
422 }
423 
424 template<class T>
425 inline typename Forest<T>::Value&
426 Forest<T>::value(
427  typename Forest<T>::NodeIndex n
428 )
429 {
430  OPENGM_ASSERT(n < nodes_.size());
431  return nodes_[n].value_;
432 }
433 
434 template<class T>
435 inline typename Forest<T>::Level
436 Forest<T>::level(
437  typename Forest<T>::NodeIndex n
438 )
439 {
440  OPENGM_ASSERT(n < nodes_.size());
441  return nodes_[n].level_;
442 }
443 
444 template<class T>
445 inline typename Forest<T>::NodeIndex
446 Forest<T>::parent(
447  typename Forest<T>::NodeIndex n
448 )
449 {
450  OPENGM_ASSERT(n < nodes_.size());
451  return nodes_[n].parent_;
452 }
453 
454 template<class T>
455 inline typename Forest<T>::NodeIndex
456 Forest<T>::levelOrderSuccessor(
457  typename Forest<T>::NodeIndex n
458 )
459 {
460  OPENGM_ASSERT(n < nodes_.size());
461  return nodes_[n].levelOrderSuccessor_;
462 }
463 
464 template<class T>
465 inline size_t
466 Forest<T>::numberOfChildren(
467  typename Forest<T>::NodeIndex n
468 )
469 {
470  OPENGM_ASSERT(n < nodes_.size());
471  return nodes_[n].children_.size();
472 }
473 
474 template<class T>
475 inline typename Forest<T>::NodeIndex
476 Forest<T>::child(
477  typename Forest<T>::NodeIndex n,
478  const size_t j
479 )
480 {
481  OPENGM_ASSERT((n<nodes_.size() && j<nodes_[n].children_.size()));
482  return nodes_[n].children_[j];
483 }
484 
485 template<class T>
486 typename Forest<T>::NodeIndex
487 Forest<T>::push_back(
488  const Value& value,
489  typename Forest<T>::NodeIndex parentNodeIndex
490 )
491 {
492  OPENGM_ASSERT((parentNodeIndex == NONODE || parentNodeIndex < nodes_.size()));
493  // lock here in parallel code
494  NodeIndex nodeIndex = nodes_.size();
495  {
496  Node node(value);
497  nodes_.push_back(node);
498  // unlock here in parallel code
499  OPENGM_ASSERT(nodes_.size() == nodeIndex + 1); // could fail in parallel code
500  }
501  if(parentNodeIndex != NONODE) {
502  nodes_[nodeIndex].parent_ = parentNodeIndex;
503  nodes_[parentNodeIndex].children_.push_back(nodeIndex);
504  nodes_[nodeIndex].level_ = nodes_[parentNodeIndex].level_ + 1;
505  }
506  if(nodes_[nodeIndex].level_ >= levelAnchors_.size()) {
507  OPENGM_ASSERT(levelAnchors_.size() == nodes_[nodeIndex].level_);
508  levelAnchors_.push_back(nodeIndex);
509  }
510  return nodeIndex;
511 }
512 
513 // returns the number of root nodes
514 template<class T>
515 size_t
516 Forest<T>::testInvariant()
517 {
518  if(nodes_.size() == 0) {
519  // tree is empty
520  OPENGM_ASSERT(levelAnchors_.size() == 0);
521  return 0;
522  }
523  else {
524  // tree is not empty
525  OPENGM_ASSERT( levelAnchors_.size() != 0);
526  size_t numberOfRoots = 0;
527  size_t nodesVisited = 0;
528  Level level = 0;
529  NodeIndex p = levelAnchors_[0];
530  while(p != NONODE) {
531  ++nodesVisited;
532  OPENGM_ASSERT(this->level(p) == level);
533  if(level == 0) {
534  // p is a root node index
535  OPENGM_ASSERT(parent(p) == NONODE);
536  ++numberOfRoots;
537  }
538  else {
539  // p is not a root node index
540  OPENGM_ASSERT(parent(p) != NONODE);
541  // test if p is among the children of its parent:
542  bool foundP = false;
543  for(size_t j=0; j<nodes_[parent(p)].children_.size(); ++j) {
544  if(nodes_[parent(p)].children_[j] == p) {
545  foundP = true;
546  break;
547  }
548  }
549  OPENGM_ASSERT(foundP)
550  }
551  // continue traversal in level-order
552  if(levelOrderSuccessor(p) != NONODE) {
553  p = levelOrderSuccessor(p);
554  }
555  else {
556  if(level+1 < levelAnchors_.size()) {
557  // tree has more levels
558  ++level;
559  p = levelAnchors_[level];
560  }
561  else {
562  // tree has no more levels
563  break;
564  }
565  }
566  }
567  OPENGM_ASSERT(nodesVisited == nodes_.size());
568  OPENGM_ASSERT(levels() == level + 1);
569  return numberOfRoots;
570  }
571 }
572 
573 template<class T>
574 std::string
575 Forest<T>::asString()
576 {
577  std::ostringstream out(std::ostringstream::out);
578  for(size_t level=0; level<levels(); ++level) {
579  NodeIndex p = levelAnchor(level);
580  while(p != NONODE) {
581  // print all variable indices on the path to the root
582  NodeIndex q = p;
583  while(q != NONODE) {
584  // out << value(q) << ' ';
585  out << value(q)+1 << ' '; // ??? replace by previous line!!!
586  q = parent(q);
587  }
588  out << std::endl;
589  // proceed
590  p = levelOrderSuccessor(p);
591  }
592  }
593  return out.str();
594 }
595 
596 template<class T>
597 inline void
598 Forest<T>::setLevelOrderSuccessor(
599  typename Forest<T>::NodeIndex nodeIndex,
600  typename Forest<T>::NodeIndex successorNodeIndex
601 )
602 {
603  OPENGM_ASSERT((nodeIndex < nodes_.size() && successorNodeIndex < nodes_.size()));
604  nodes_[nodeIndex].levelOrderSuccessor_ = successorNodeIndex;
605 }
606 
607 // implementation of LazyFlipper
608 
609 //template<class GM, class ACC>
610 //inline
611 //LazyFlipper<GM, ACC>::LazyFlipper(
612 // const GraphicalModelType& gm,
613 // const size_t maxSubgraphSize,
614 // const Tribool useMultilabelInference
615 //)
616 //: gm_(gm),
617 // variableAdjacency_(Adjacency(gm.numberOfVariables())),
618 // movemaker_(Movemaker<GM>(gm)),
619 // subgraphForest_(SubgraphForest()),
620 // maxSubgraphSize_(maxSubgraphSize),
621 // useMultilabelInference_(useMultilabelInference)
622 //{
623 // if(gm_.numberOfVariables() == 0) {
624 // throw RuntimeError("The graphical model has no variables.");
625 // }
626 // setMaxSubgraphSize(maxSubgraphSize);
627 // // initialize activation_
628 // activation_[0].append(gm_.numberOfVariables());
629 // activation_[1].append(gm_.numberOfVariables());
630 // // initialize variableAdjacency_
631 // for(size_t j=0; j<gm_.numberOfFactors(); ++j) {
632 // const FactorType& factor = gm_[j];
633 // for(size_t m=0; m<factor.numberOfVariables(); ++m) {
634 // for(size_t n=m+1; n<factor.numberOfVariables(); ++n) {
635 // variableAdjacency_.connect(factor.variableIndex(m), factor.variableIndex(n));
636 // }
637 // }
638 // }
639 //}
640 
641 template<class GM, class ACC>
642 inline
644  const GraphicalModelType& gm,
645  typename LazyFlipper::Parameter param
646 )
647 : gm_(gm),
648  variableAdjacency_(Adjacency(gm.numberOfVariables())),
649  movemaker_(Movemaker<GM>(gm)),
650  subgraphForest_(SubgraphForest()),
652  useMultilabelInference_(param.inferMultilabel_)
653 {
654  if(gm_.numberOfVariables() == 0) {
655  throw RuntimeError("The graphical model has no variables.");
656  }
658  // initialize activation_
659  activation_[0].append(gm_.numberOfVariables());
660  activation_[1].append(gm_.numberOfVariables());
661  // initialize variableAdjacency_
662  for(size_t j=0; j<gm_.numberOfFactors(); ++j) {
663  const FactorType& factor = gm_[j];
664  for(size_t m=0; m<factor.numberOfVariables(); ++m) {
665  for(size_t n=m+1; n<factor.numberOfVariables(); ++n) {
666  variableAdjacency_.connect(factor.variableIndex(m), factor.variableIndex(n));
667  }
668  }
669  }
670  if(param.startingPoint_.size() == gm_.numberOfVariables()) {
671  movemaker_.initialize(param.startingPoint_.begin());
672  }
673 }
674 
675 template<class GM, class ACC>
676 inline void
678 {}
679 
681 //template<class GM, class ACC>
682 //template<class StateIterator>
683 //inline
684 //LazyFlipper<GM, ACC>::LazyFlipper(
685 // const GraphicalModelType& gm,
686 // const size_t maxSubgraphSize,
687 // StateIterator it,
688 // const Tribool useMultilabelInference
689 //)
690 //: gm_(gm),
691 // variableAdjacency_(Adjacency(gm_.numberOfVariables())),
692 // movemaker_(Movemaker<GM>(gm, it)),
693 // subgraphForest_(SubgraphForest()),
694 // maxSubgraphSize_(2),
695 // useMultilabelInference_(useMultilabelInference)
696 //{
697 // if(gm_.numberOfVariables() == 0) {
698 // throw RuntimeError("The graphical model has no variables.");
699 // }
700 // setMaxSubgraphSize(maxSubgraphSize);
701 // // initialize activation_
702 // activation_[0].append(gm_.numberOfVariables());
703 // activation_[1].append(gm_.numberOfVariables());
704 // // initialize variableAdjacency_
705 // for(size_t j=0; j<gm_.numberOfFactors(); ++j) {
706 // const FactorType& factor = gm_[j];
707 // for(size_t m=0; m<factor.numberOfVariables(); ++m) {
708 // for(size_t n=m+1; n<factor.numberOfVariables(); ++n) {
709 // variableAdjacency_.connect(factor.variableIndex(m), factor.variableIndex(n));
710 // }
711 // }
712 // }
713 //}
714 
715 template<class GM, class ACC>
716 inline void
718  typename std::vector<typename LazyFlipper<GM, ACC>::LabelType>::const_iterator begin
719 ) {
720  movemaker_.initialize(begin);
721 }
722 
723 template<class GM, class ACC>
724 inline std::string
726 {
727  return "LazyFlipper";
728 }
729 
730 template<class GM, class ACC>
731 inline const typename LazyFlipper<GM, ACC>::GraphicalModelType&
733 {
734  return gm_;
735 }
736 
737 template<class GM, class ACC>
738 inline const size_t
740 {
741  return maxSubgraphSize_;
742 }
743 
744 template<class GM, class ACC>
745 inline void
747  const size_t maxSubgraphSize
748 )
749 {
750  if(maxSubgraphSize < 1) {
751  throw RuntimeError("Maximum subgraph size < 1.");
752  }
753  else {
754  maxSubgraphSize_ = maxSubgraphSize;
755  }
756 }
757 
759 template<class GM, class ACC>
760 template<class VisitorType>
763  VisitorType& visitor
764 )
765 {
766  bool multiLabel;
767  if(this->useMultilabelInference_ == true) {
768  multiLabel = true;
769  }
770  else if(this->useMultilabelInference_ == false) {
771  multiLabel = false;
772  }
773  else {
774  multiLabel = false;
775  for(size_t i=0; i<gm_.numberOfVariables(); ++i) {
776  if(gm_.numberOfLabels(i) != 2) {
777  multiLabel = true;
778  break;
779  }
780  }
781  }
782 
783  if(multiLabel) {
784  return this->inferMultiLabel(visitor);
785  }
786  else {
787  return this->inferBinaryLabel(visitor);
788  }
789 }
790 
792 template<class GM, class ACC>
795 {
796  EmptyVisitorType visitor;
797  return this->infer(visitor);
798 }
799 
800 template<class GM, class ACC>
801 template<class VisitorType>
804  VisitorType& visitor
805 )
806 {
807  bool continueInf = true;
808  size_t length = 1;
809  //const ValueType bound = this->bound();
810  //visitor.begin(*this, movemaker_.value(), bound, length, subgraphForest_.size());
811  visitor.begin(*this);
812  while(continueInf) {
813  //visitor(*this, movemaker_.value(), bound, length, subgraphForest_.size());
814  if(visitor(*this)!=0){
815  continueInf=false;
816  break;
817  }
818  SubgraphForestNode p = generateFirstPathOfLength(length);
819  if(p == NONODE) {
820  break;
821  }
822  else {
823  while(p != NONODE) {
824  if(AccumulationType::bop(energyAfterFlip(p), movemaker_.value())) {
825  flip(p);
826  activateInfluencedVariables(p, 0);
827  //visitor(*this, movemaker_.value(), bound, length, subgraphForest_.size());
828  if(visitor(*this)!=0){
829  continueInf=false;
830  break;
831  }
832  }
833  p = generateNextPathOfSameLength(p);
834  }
835  size_t currentActivationList = 0;
836  size_t nextActivationList = 1;
837  while(continueInf) {
838  SubgraphForestNode p2 = firstActivePath(currentActivationList);
839  if(p2 == NONODE) {
840  break;
841  }
842  else {
843  while(p2 != NONODE) {
844  if(AccumulationType::bop(energyAfterFlip(p2), movemaker_.value())) {
845  flip(p2);
846  activateInfluencedVariables(p2, nextActivationList);
847  //visitor(*this, movemaker_.value(), bound, length, subgraphForest_.size());
848  if(visitor(*this)!=0){
849  continueInf=false;
850  break;
851  }
852  }
853  p2 = nextActivePath(p2, currentActivationList);
854  }
855  deactivateAllVariables(currentActivationList);
856  nextActivationList = 1 - nextActivationList;
857  currentActivationList = 1 - currentActivationList;
858  }
859  }
860  }
861  if(length == maxSubgraphSize_) {
862  break;
863  }
864  else {
865  ++length;
866  }
867  }
868  // assertion testing
869  if(!NO_DEBUG) {
870  subgraphForest_.testInvariant();
871  }
872  //visitor.end(*this, movemaker_.value(), bound, length, subgraphForest_.size());
873  visitor.end(*this);
874  // diagnose
875  // std::cout << subgraphForest_.asString();
876  return NORMAL;
877 }
878 
879 template<class GM, class ACC>
882 {
883  EmptyVisitorType v;
884  return infer(v);
885 }
886 
887 template<class GM, class ACC>
888 template<class VisitorType>
891  VisitorType& visitor
892 )
893 {
894  bool continueInf = true;
895  size_t length = 1;
896  //const ValueType bound = this->bound();
897  //visitor.begin(*this, movemaker_.value(), bound, length, subgraphForest_.size());
898  visitor.begin(*this);
899  while(continueInf) {
900  //visitor(*this, movemaker_.value(), bound, length, subgraphForest_.size());
901  if(visitor(*this)!=0){
902  continueInf = false;
903  break;
904  }
905  SubgraphForestNode p = generateFirstPathOfLength(length);
906  if(p == NONODE) {
907  break;
908  }
909  else {
910  while(p != NONODE) {
911  bool flipped = flipMultiLabel(p);
912  if(flipped) {
913  activateInfluencedVariables(p, 0);
914  //visitor(*this, movemaker_.value(), bound, length, subgraphForest_.size());
915  if(visitor(*this)!=0){
916  continueInf = false;
917  break;
918  }
919  }
920  p = generateNextPathOfSameLength(p);
921  }
922  size_t currentActivationList = 0;
923  size_t nextActivationList = 1;
924  while(continueInf) {
925  SubgraphForestNode p2 = firstActivePath(currentActivationList);
926  if(p2 == NONODE) {
927  break;
928  }
929  else {
930  while(p2 != NONODE) {
931  bool flipped = flipMultiLabel(p2);
932  if(flipped) {
933  activateInfluencedVariables(p2, nextActivationList);
934  //visitor(*this, movemaker_.value(), bound, length, subgraphForest_.size());
935  if(visitor(*this)!=0){
936  continueInf = false;
937  break;
938  }
939  }
940  p2 = nextActivePath(p2, currentActivationList);
941  }
942  deactivateAllVariables(currentActivationList);
943  nextActivationList = 1 - nextActivationList;
944  currentActivationList = 1 - currentActivationList;
945  }
946  }
947  }
948  if(length == maxSubgraphSize_) {
949  break;
950  }
951  else {
952  ++length;
953  }
954  }
955  // assertion testing
956  if(!NO_DEBUG) {
957  subgraphForest_.testInvariant();
958  }
959  // diagnose
960  // std::cout << subgraphForest_.asString();
961  //visitor.end(*this, movemaker_.value(), bound, length, subgraphForest_.size());
962  visitor.end(*this);
963  return NORMAL;
964 }
965 
966 template<class GM, class ACC>
969 {
970  EmptyVisitorType visitor;
971  return this->inferMultiLabel(visitor);
972 }
973 
974 template<class GM, class ACC>
977  std::vector<LabelType>& arg,
978  const size_t n
979 ) const
980 {
981  if(n > 1) {
982  return UNKNOWN;
983  }
984  else {
985  arg.resize(gm_.numberOfVariables());
986  for(size_t j=0; j<gm_.numberOfVariables(); ++j) {
987  arg[j] = movemaker_.state(j);
988  }
989  return NORMAL;
990  }
991 }
992 
993 template<class GM, class ACC>
994 inline typename LazyFlipper<GM, ACC>::ValueType
996 {
997  return movemaker_.value();
998 }
999 
1000 // Append the next possible variable to a node in the subgraph tree.
1001 // The null pointer is returned if no variable can be appended.
1002 template<class GM, class ACC>
1005  typename LazyFlipper<GM, ACC>::SubgraphForestNode p // input
1006 )
1007 {
1008  // collect variable indices on path
1009  std::vector<size_t> variableIndicesOnPath(subgraphForest_.level(p) + 1);
1010  {
1011  SubgraphForestNode p2 = p;
1012  for(size_t j=0; j<=subgraphForest_.level(p); ++j) {
1013  OPENGM_ASSERT(p2 != NONODE);
1014  variableIndicesOnPath[subgraphForest_.level(p) - j] = subgraphForest_.value(p2);
1015  p2 = subgraphForest_.parent(p2);
1016  }
1017  OPENGM_ASSERT(p2 == NONODE);
1018  }
1019  // find the mininum and maximum variable index on the path
1020  size_t minVI = variableIndicesOnPath[0];
1021  size_t maxVI = variableIndicesOnPath[0];
1022  for(size_t j=1; j<variableIndicesOnPath.size(); ++j) {
1023  if(variableIndicesOnPath[j] > maxVI) {
1024  maxVI = variableIndicesOnPath[j];
1025  }
1026  }
1027  // find the maximum variable index among the children of p.
1028  // the to be appended variable must have a greater index.
1029  if(subgraphForest_.numberOfChildren(p) > 0) {
1030  size_t maxChildIndex = subgraphForest_.numberOfChildren(p) - 1;
1031  minVI = subgraphForest_.value(subgraphForest_.child(p, maxChildIndex));
1032  }
1033  // build set of candidate variable indices for appending
1034  std::set<size_t> candidateVariableIndices;
1035  {
1036  SubgraphForestNode q = p;
1037  while(q != NONODE) {
1038  for(Adjacency::const_iterator it = variableAdjacency_.neighborsBegin(subgraphForest_.value(q));
1039  it != variableAdjacency_.neighborsEnd(subgraphForest_.value(q)); ++it) {
1040  candidateVariableIndices.insert(*it);
1041  }
1042  q = subgraphForest_.parent(q);
1043  }
1044  }
1045  // append candidate if possible
1046  for(std::set<size_t>::const_iterator it = candidateVariableIndices.begin();
1047  it != candidateVariableIndices.end(); ++it) {
1048  // for all variables adjacenct to the one at node p
1049  if(*it > minVI && std::find(variableIndicesOnPath.begin(), variableIndicesOnPath.end(), *it) == variableIndicesOnPath.end()) {
1050  // the variable index *it is not smaller than the lower bound AND
1051  // greater than the minimum variable index on the path AND
1052  // is not itself on the path (??? consider tagging instead of
1053  // searching in the previous if-condition)
1054  if(*it > maxVI) {
1055  // *it is greater than the largest variable index on the path
1056  return subgraphForest_.push_back(*it, p); // append to path
1057  }
1058  else {
1059  // *it is not the greatest variable index on the path.
1060  for(size_t j=1; j<variableIndicesOnPath.size(); ++j) {
1061  if(variableAdjacency_.connected(variableIndicesOnPath[j-1], *it)) {
1062  // *it could have been added as a child of
1063  // variableIndicesOnPath[j-1]
1064  for(size_t k=j; k<variableIndicesOnPath.size(); ++k) {
1065  if(*it < variableIndicesOnPath[k]) {
1066  // adding *it as a child of variableIndicesOnPath[j-1]
1067  // would have made the path cheaper
1068  goto doNotAppend; // escape loop over j
1069  }
1070  }
1071  }
1072  }
1073  // *it could not have been introduced cheaper
1074  // append to path:
1075  return subgraphForest_.push_back(*it, p);
1076 doNotAppend:;
1077  }
1078  }
1079  }
1080  // no neighbor of p could be appended
1081  return NONODE;
1082 }
1083 
1084 template<class GM, class ACC>
1087  const size_t length
1088 )
1089 {
1090  OPENGM_ASSERT(length > 0);
1091  if(length > gm_.numberOfVariables()) {
1092  return NONODE;
1093  }
1094  else {
1095  if(length == 1) {
1096  SubgraphForestNode p = subgraphForest_.push_back(0, NONODE);
1097  // variable index = 0, parent = NONODE
1098  return p;
1099  }
1100  else {
1101  SubgraphForestNode p = subgraphForest_.levelAnchor(length-2);
1102  while(p != NONODE) {
1103  SubgraphForestNode p2 = appendVariableToPath(p);
1104  if(p2 != NONODE) { // append succeeded
1105  return p2;
1106  }
1107  else { // append failed
1108  p = subgraphForest_.levelOrderSuccessor(p);
1109  }
1110  }
1111  return NONODE;
1112  }
1113  }
1114 }
1115 
1116 template<class GM, class ACC>
1119  SubgraphForestNode predecessor
1120 )
1121 {
1122  if(subgraphForest_.level(predecessor) == 0) {
1123  if(subgraphForest_.value(predecessor) + 1 < gm_.numberOfVariables()) {
1124  SubgraphForestNode newNode =
1125  subgraphForest_.push_back(subgraphForest_.value(predecessor) + 1, NONODE);
1126  subgraphForest_.setLevelOrderSuccessor(predecessor, newNode);
1127  return newNode;
1128  }
1129  else {
1130  // no more variables
1131  return NONODE;
1132  }
1133  }
1134  else {
1135  for(SubgraphForestNode parent = subgraphForest_.parent(predecessor);
1136  parent != NONODE; parent = subgraphForest_.levelOrderSuccessor(parent) ) {
1137  SubgraphForestNode newNode = appendVariableToPath(parent);
1138  if(newNode != NONODE) {
1139  // a variable has been appended
1140  subgraphForest_.setLevelOrderSuccessor(predecessor, newNode);
1141  return newNode;
1142  }
1143  }
1144  return NONODE;
1145  }
1146 }
1147 
1148 template<class GM, class ACC>
1149 void
1151  SubgraphForestNode p,
1152  const size_t activationListIndex
1153 )
1154 {
1155  OPENGM_ASSERT(activationListIndex < 2);
1156  while(p != NONODE) {
1157  activation_[activationListIndex].tag(subgraphForest_.value(p), true);
1158  for(Adjacency::const_iterator it = variableAdjacency_.neighborsBegin(subgraphForest_.value(p));
1159  it != variableAdjacency_.neighborsEnd(subgraphForest_.value(p)); ++it) {
1160  activation_[activationListIndex].tag(*it, true);
1161  }
1162  p = subgraphForest_.parent(p);
1163  }
1164 }
1165 
1166 template<class GM, class ACC>
1167 inline void
1169  const size_t activationListIndex
1170 )
1171 {
1172  OPENGM_ASSERT(activationListIndex < 2);
1173  activation_[activationListIndex].untag();
1174 }
1175 
1176 template<class GM, class ACC>
1179  const size_t activationListIndex
1180 )
1181 {
1182  if(subgraphForest_.levels() == 0) {
1183  return NONODE;
1184  }
1185  else {
1186  // ??? improve code: no search, store reference
1187  SubgraphForestNode p = subgraphForest_.levelAnchor(0);
1188  while(p != NONODE) {
1189  if(activation_[activationListIndex].tag(subgraphForest_.value(p))) {
1190  return p;
1191  }
1192  p = subgraphForest_.levelOrderSuccessor(p);
1193  }
1194  return NONODE;
1195  }
1196 }
1197 
1198 // \todo next version: improve code: searching over all paths and all
1199 // variables of each path for active variables is certainly not the ideal
1200 // way
1201 template<class GM, class ACC>
1204  SubgraphForestNode predecessor,
1205  const size_t activationListIndex
1206 )
1207 {
1208  for(;;) {
1209  if(subgraphForest_.levelOrderSuccessor(predecessor) == NONODE) {
1210  if(subgraphForest_.level(predecessor) + 1 < subgraphForest_.levels()) {
1211  // there are more levels in the tree
1212  predecessor = subgraphForest_.levelAnchor(subgraphForest_.level(predecessor) + 1);
1213  }
1214  else {
1215  // there are no more levels in the tree
1216  return NONODE;
1217  }
1218  }
1219  else {
1220  // predecessor is not the last node on its level
1221  predecessor = subgraphForest_.levelOrderSuccessor(predecessor);
1222  }
1223  SubgraphForestNode p = predecessor;
1224  while(p != NONODE) {
1225  // search along path for active variables:
1226  if(activation_[activationListIndex].tag(subgraphForest_.value(p))) {
1227  return predecessor;
1228  }
1229  p = subgraphForest_.parent(p);
1230  }
1231  }
1232 }
1233 
1234 template<class GM, class ACC>
1235 inline typename LazyFlipper<GM, ACC>::ValueType
1237  SubgraphForestNode node
1238 )
1239 {
1240  size_t numberOfFlippedVariables = subgraphForest_.level(node) + 1;
1241  std::vector<size_t> flippedVariableIndices(numberOfFlippedVariables);
1242  std::vector<LabelType> flippedVariableStates(numberOfFlippedVariables);
1243  for(size_t j=0; j<numberOfFlippedVariables; ++j) {
1244  OPENGM_ASSERT(node != NONODE);
1245  flippedVariableIndices[j] = subgraphForest_.value(node);
1246  // binary flip:
1247  flippedVariableStates[j] = 1 - movemaker_.state(subgraphForest_.value(node));
1248  node = subgraphForest_.parent(node);
1249  }
1250  OPENGM_ASSERT(node == NONODE);
1251  return movemaker_.valueAfterMove(flippedVariableIndices.begin(),
1252  flippedVariableIndices.end(), flippedVariableStates.begin());
1253 
1254 }
1255 
1256 template<class GM, class ACC>
1257 inline void
1259  SubgraphForestNode node
1260 )
1261 {
1262  size_t numberOfFlippedVariables = subgraphForest_.level(node) + 1;
1263  std::vector<size_t> flippedVariableIndices(numberOfFlippedVariables);
1264  std::vector<LabelType> flippedVariableStates(numberOfFlippedVariables);
1265  for(size_t j=0; j<numberOfFlippedVariables; ++j) {
1266  OPENGM_ASSERT(node != NONODE)
1267  flippedVariableIndices[j] = subgraphForest_.value(node);
1268  // binary flip:
1269  flippedVariableStates[j] = 1 - movemaker_.state(subgraphForest_.value(node));
1270  node = subgraphForest_.parent(node);
1271  }
1272  OPENGM_ASSERT(node == NONODE);
1273  movemaker_.move(flippedVariableIndices.begin(),
1274  flippedVariableIndices.end(), flippedVariableStates.begin());
1275 }
1276 
1277 template<class GM, class ACC>
1278 inline const bool
1280  SubgraphForestNode node
1281 )
1282 {
1283  size_t numberOfVariables = subgraphForest_.level(node) + 1;
1284  std::vector<size_t> variableIndices(numberOfVariables);
1285  for(size_t j=0; j<numberOfVariables; ++j) {
1286  OPENGM_ASSERT(node != NONODE);
1287  variableIndices[j] = subgraphForest_.value(node);
1288  node = subgraphForest_.parent(node);
1289  }
1290  OPENGM_ASSERT(node == NONODE);
1291  ValueType energy = movemaker_.value();
1292  movemaker_.template moveOptimallyWithAllLabelsChanging<AccumulationType>(variableIndices.begin(), variableIndices.end());
1293  if(AccumulationType::bop(movemaker_.value(), energy)) {
1294  return true;
1295  }
1296  else {
1297  return false;
1298  }
1299 }
1300 
1301 } // namespace opengm
1302 
1303 #endif // #ifndef OPENGM_LAZYFLIPPER_HXX
std::string name() const
The OpenGM namespace.
Definition: config.hxx:43
const size_t maxSubgraphSize() const
void infer(const typename INF::GraphicalModelType &gm, const typename INF::Parameter &param, std::vector< typename INF::LabelType > &conf)
Definition: inference.hxx:34
Parameter(const size_t maxSubgraphSize, StateIterator stateBegin, StateIterator stateEnd, const Tribool inferMultilabel=Tribool::Maybe)
STL namespace.
ValueType valueAfterMove(IndexIterator, IndexIterator, StateIterator)
Definition: movemaker.hxx:292
void setMaxSubgraphSize(const size_t)
ValueType value() const
Definition: movemaker.hxx:284
visitors::TimingVisitor< LazyFlipper< GM, ACC > > TimingVisitorType
void setStartingPoint(typename std::vector< LabelType >::const_iterator)
set initial labeling
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
LazyFlipper< _GM, ACC > type
InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
output a solution
const LabelType & state(const size_t) const
Definition: movemaker.hxx:606
void initialize(StateIterator)
Definition: movemaker.hxx:262
GraphicalModelType::FactorType FactorType
Definition: inference.hxx:52
const GraphicalModelType & graphicalModel() const
std::vector< LabelType > startingPoint_
LazyFlipper< _GM, _ACC > type
visitors::EmptyVisitor< LazyFlipper< GM, ACC > > EmptyVisitorType
GraphicalModelType::ValueType ValueType
Definition: inference.hxx:50
Inference algorithm interface.
Definition: inference.hxx:43
Parameter(const size_t maxSubgraphSize=2, const Tribool inferMultilabel=Tribool::Maybe)
LazyFlipper(const GraphicalModelType &gm, Parameter param=Parameter())
Forest< IndexType > SubgraphForest
const bool NO_DEBUG
Definition: config.hxx:64
ValueType value() const
return the solution (value)
Variable with three values (true=1, false=0, maybe=-1 )
Definition: tribool.hxx:8
static const SubgraphForestNode NONODE
visitors::VerboseVisitor< LazyFlipper< GM, ACC > > VerboseVisitorType
GraphicalModelType::LabelType LabelType
Definition: inference.hxx:48
ValueType move(IndexIterator, IndexIterator, StateIterator)
Definition: movemaker.hxx:356
A generalization of ICM B. Andres, J. H. Kappes, U. Koethe and Hamprecht F. A., The Lazy Flipper: MA...
OpenGM runtime error.
Definition: opengm.hxx:100
InferenceTermination infer()
start the algorithm
InferenceTermination
Definition: inference.hxx:24