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