OpenGM  2.3.x
Discrete Graphical Model Library
factorgraph.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_FACTORGRAPH_HXX
3 #define OPENGM_FACTORGRAPH_HXX
4 
5 #include <algorithm>
6 #include <limits>
7 
11 
12 #include <typeinfo>
13 namespace opengm {
14 
17 template<class S,class I>
18 class FactorGraph {
19 private:
20  class VariableAccessor;
21  class FactorAccessor;
22  typedef I IndexType;
23 public:
24  typedef S SpecialType;
25  typedef AccessorIterator<VariableAccessor, true> ConstVariableIterator;
26  typedef AccessorIterator<FactorAccessor, true> ConstFactorIterator;
27 
28  // required interface of S (the template parameter)
29  size_t numberOfVariables() const;
30  size_t numberOfVariables(const size_t) const;
31  size_t numberOfFactors() const;
32  size_t numberOfFactors(const size_t) const;
33  size_t variableOfFactor(const size_t, const size_t) const;
34  size_t factorOfVariable(const size_t, const size_t) const;
35 
36  // functions that need not be member functions of S (the template parameter)
37  ConstVariableIterator variablesOfFactorBegin(const size_t) const;
38  ConstVariableIterator variablesOfFactorEnd(const size_t) const;
39  ConstFactorIterator factorsOfVariableBegin(const size_t) const;
40  ConstFactorIterator factorsOfVariableEnd(const size_t) const;
41  bool variableFactorConnection(const size_t, const size_t) const;
42  bool factorVariableConnection(const size_t, const size_t) const;
43  bool variableVariableConnection(const size_t, const size_t) const;
44  bool factorFactorConnection(const size_t, const size_t) const;
45  bool isAcyclic() const;
46  bool isConnected(marray::Vector<size_t>& representatives) const;
47  bool isChain(marray::Vector<size_t>&) const;
48  bool isGrid(marray::Matrix<size_t>&) const;
49 
50  size_t maxFactorOrder() const;
51  bool maxFactorOrder(const size_t maxOrder) const;
52  size_t numberOfNthOrderFactorsOfVariable(const size_t, const size_t) const;
53  size_t numberOfNthOrderFactorsOfVariable(const size_t, const size_t, marray::Vector<size_t>&) const;
54  size_t secondVariableOfSecondOrderFactor(const size_t, const size_t) const;
55 
56  // export functions
58  void variableAdjacencyList(std::vector<std::set<IndexType> >&) const;
59  void variableAdjacencyList(std::vector<RandomAccessSet<IndexType> >&) const;
60  void factorAdjacencyList(std::vector<std::set<IndexType> >&) const;
61  void factorAdjacencyList(std::vector<RandomAccessSet<IndexType> >&) const;
62 
63 protected:
64  // cast operators
65  operator S&()
66  { return static_cast<S&>(*this); }
67  operator S const&() const
68  { return static_cast<const S&>(*this); }
69 
70  template <class LIST>
71  bool shortestPath(const size_t, const size_t, LIST&, const LIST& = LIST()) const;
72  template <class LIST>
73  bool twoHopConnected(const size_t, const size_t, LIST&) const;
74 
75 private:
76  class VariableAccessor {
77  public:
78  typedef size_t value_type;
79 
80  VariableAccessor(const FactorGraph<S,I>* factorGraph = NULL, const size_t factor = 0)
81  : factorGraph_(factorGraph), factor_(factor)
82  {}
83  VariableAccessor(const FactorGraph<S,I>& factorGraph, const size_t factor = 0)
84  : factorGraph_(&factorGraph), factor_(factor)
85  {}
86  size_t size() const
87  { OPENGM_ASSERT(factorGraph_ != NULL);
88  return factorGraph_->numberOfVariables(factor_); }
89  const size_t operator[](const size_t number) const
90  { OPENGM_ASSERT(factorGraph_ != NULL);
91  return factorGraph_->variableOfFactor(factor_, number); }
92  bool operator==(const VariableAccessor& a) const
93  { OPENGM_ASSERT(factorGraph_ != NULL);
94  return factor_ == a.factor_ && factorGraph_ == a.factorGraph_; }
95 
96  private:
97  const FactorGraph<S,I>* factorGraph_;
98  size_t factor_;
99  };
100 
101  class FactorAccessor {
102  public:
103  typedef I value_type;
104 
105  FactorAccessor(const FactorGraph<S,I>* factorGraph = NULL, const size_t variable = 0)
106  : factorGraph_(factorGraph), variable_(variable)
107  {}
108  FactorAccessor(const FactorGraph<S,I>& factorGraph, const size_t variable = 0)
109  : factorGraph_(&factorGraph), variable_(variable)
110  {}
111  size_t size() const
112  { OPENGM_ASSERT(factorGraph_ != NULL);
113  return factorGraph_->numberOfFactors(variable_); }
114  const size_t operator[](const size_t number) const
115  { OPENGM_ASSERT(factorGraph_ != NULL);
116  return factorGraph_->factorOfVariable(variable_, number); }
117  bool operator==(const FactorAccessor& a) const
118  { OPENGM_ASSERT(factorGraph_ != NULL);
119  return variable_ == a.variable_ && factorGraph_ == a.factorGraph_; }
120 
121  private:
122  const FactorGraph<S,I>* factorGraph_;
123  size_t variable_;
124  };
125 
126  template<class LIST>
127  void templatedVariableAdjacencyList(LIST&) const;
128  template<class LIST>
129  void templatedFactorAdjacencyList(LIST&) const;
130 };
131 
134 template<class S,class I>
135 inline size_t
137 {
138  return static_cast<const SpecialType&>(*this).numberOfVariables();
139 }
140 
144 template<class S,class I>
145 inline size_t
147 (
148  const size_t factor
149 ) const
150 {
151  return static_cast<const SpecialType&>(*this).numberOfVariables(factor);
152 }
153 
156 template<class S,class I>
157 inline size_t
159 {
160  return static_cast<const SpecialType&>(*this).numberOfFactors();
161 }
162 
166 template<class S,class I>
167 inline size_t
169 (
170  const size_t variable
171 ) const
172 {
173  return static_cast<const SpecialType&>(*this).numberOfFactors(variable);
174 }
175 
180 template<class S,class I>
181 inline size_t
183 (
184  const size_t factor,
185  const size_t j
186 ) const
187 {
188  return static_cast<const SpecialType&>(*this).variableOfFactor(factor, j);
189 }
190 
195 template<class S,class I>
196 inline size_t
198 (
199  const size_t variable,
200  const size_t j
201 ) const
202 {
203  return static_cast<const SpecialType&>(*this).factorOfVariable(variable, j);
204 }
205 
209 template<class S,class I>
212 (
213  const size_t factor
214 ) const
215 {
216  VariableAccessor accessor(this, factor);
217  return ConstVariableIterator(accessor);
218 }
219 
223 template<class S,class I>
226 (
227  const size_t factor
228 ) const
229 {
230  VariableAccessor accessor(this, factor);
231  return ConstVariableIterator(accessor, numberOfVariables(factor));
232 }
233 
237 template<class S,class I>
240 (
241  const size_t variable
242 ) const
243 {
244  FactorAccessor accessor(this, variable);
245  return ConstFactorIterator(accessor);
246 }
247 
251 template<class S,class I>
254 (
255  const size_t variable
256 ) const
257 {
258  FactorAccessor accessor(this, variable);
259  return ConstFactorIterator(accessor, numberOfFactors(variable));
260 }
261 
266 template<class S,class I>
267 inline bool
269 (
270  const size_t variable,
271  const size_t factor
272 ) const
273 {
274  OPENGM_ASSERT(factor < numberOfFactors());
275  OPENGM_ASSERT(variable < numberOfVariables());
276  if(!NO_DEBUG) {
277  for(size_t j=1; j<numberOfVariables(factor); ++j) {
278  OPENGM_ASSERT(variableOfFactor(factor, j-1) < variableOfFactor(factor, j));
279  }
280  }
281  return std::binary_search(variablesOfFactorBegin(factor),
282  variablesOfFactorEnd(factor), variable);
283  return false;
284 }
285 
290 template<class S,class I>
291 inline bool
293 (
294  const size_t factor,
295  const size_t variable
296 ) const
297 {
298  OPENGM_ASSERT(factor < numberOfFactors());
299  OPENGM_ASSERT(variable < numberOfVariables());
300  return variableFactorConnection(variable, factor);
301 }
302 
307 template<class S,class I>
308 inline bool
310 (
311  const size_t variable1,
312  const size_t variable2
313 ) const
314 {
315  OPENGM_ASSERT(variable1 < numberOfVariables());
316  OPENGM_ASSERT(variable2 < numberOfVariables());
317  if(variable1 != variable2) {
318  ConstFactorIterator it1 = factorsOfVariableBegin(variable1);
319  ConstFactorIterator it2 = factorsOfVariableBegin(variable2);
320  while(it1 != factorsOfVariableEnd(variable1) && it2 != factorsOfVariableEnd(variable2)) {
321  if(*it1 < *it2) {
322  ++it1;
323  }
324  else if(*it1 == *it2) {
325  return true;
326  }
327  else {
328  ++it2;
329  }
330  }
331  }
332  return false;
333 }
334 
337 template<class S,class I>
338 bool
340 {
341  const size_t NO_FACTOR = numberOfFactors();
342  const size_t NO_VARIABLE = numberOfVariables();
343  const size_t ROOT_FACTOR = numberOfVariables() + 1;
344  std::vector<size_t> factorFathers(numberOfFactors(), NO_VARIABLE);
345  std::vector<size_t> variableFathers(numberOfVariables(), NO_FACTOR);
346  std::queue<size_t> factorQueue;
347  std::queue<size_t> variableQueue;
348  for(size_t F = 0; F < numberOfFactors(); ++F) {
349  if(factorFathers[F] == NO_VARIABLE) {
350  factorFathers[F] = ROOT_FACTOR;
351  factorQueue.push(F);
352  while(!factorQueue.empty()) {
353  while(!factorQueue.empty()) {
354  const size_t f = factorQueue.front();
355  factorQueue.pop();
356  for(size_t j = 0; j < numberOfVariables(f); ++j) {
357  const size_t v = variableOfFactor(f, j);
358  if(variableFathers[v] == NO_FACTOR) {
359  variableFathers[v] = f;
360  variableQueue.push(v);
361  }
362  else if(factorFathers[f] != v) {
363  return false;
364  }
365  }
366  }
367  while(!variableQueue.empty()) {
368  const size_t v = variableQueue.front();
369  variableQueue.pop();
370  for(size_t j = 0; j < numberOfFactors(v); ++j) {
371  const size_t f = factorOfVariable(v, j);
372  if(factorFathers[f] == NO_VARIABLE) {
373  factorFathers[f] = v;
374  factorQueue.push(f);
375  }
376  else if(variableFathers[v] != f) {
377  return false;
378  }
379  }
380  }
381  }
382  }
383  }
384  return true;
385 }
386 
390 template<class S,class I>
391 bool
393 {
394  // check if factor graph has zero variables
395  if(numberOfVariables() == 0) {
396  return false;
397  }
398 
399  // create a partition of all connected components
400  Partition<size_t> connectedComponents(numberOfVariables());
401  // iterate over all factors
402  for(size_t i = 0; i < numberOfFactors(); i++) {
403  // iterate over all connected variables of factor and merge them to one partition
404  const ConstVariableIterator variablesBegin = variablesOfFactorBegin(i);
405  const ConstVariableIterator variablesEnd = variablesOfFactorEnd(i);
406  OPENGM_ASSERT(variablesBegin != variablesEnd);
407 
408  for(ConstVariableIterator iter = variablesBegin + 1; iter != variablesEnd; iter++) {
409  connectedComponents.merge(*(iter - 1), *iter);
410  }
411  }
412 
413  // check number of connected components
414  OPENGM_ASSERT(connectedComponents.numberOfSets() > 0);
415 
416  representatives = marray::Vector<size_t>(connectedComponents.numberOfSets());
417  connectedComponents.representatives(representatives.begin());
418 
419  if(connectedComponents.numberOfSets() == 1) {
420  return true;
421  } else {
422  return false;
423  }
424 }
425 
429 template<class S,class I>
430 inline bool
432  const size_t numVariables = numberOfVariables();
433 
434  // check if factor graph has zero variables
435  if(numVariables == 0) {
436  return false;
437  }
438 
439  // check Factor Order
440  if(!maxFactorOrder(2)) {
441  return false;
442  }
443 
444  // special case: graph contains only one variable
445  if(numVariables == 1) {
446  chainIDs = marray::Vector<size_t>(numVariables);
447  chainIDs[0] = 0;
448  return true;
449  }
450 
451  // find ends
452  marray::Vector<size_t> ends(2);
453  size_t detectedEnds = 0;
454  for(size_t i = 0; i < numVariables; i++) {
455  size_t countSecondOrderFactors = numberOfNthOrderFactorsOfVariable(i, 2);
456  if(countSecondOrderFactors == 1) {
457  if(detectedEnds > 1) {
458  return false;
459  }
460  ends[detectedEnds] = i;
461  detectedEnds++;
462  }
463  }
464 
465  // two ends found?
466  if(detectedEnds != 2) {
467  return false;
468  }
469 
470  chainIDs = marray::Vector<size_t>(numVariables);
471  // set ends
472  chainIDs[0] = ends[0];
473  chainIDs[numVariables - 1] = ends[1];
474 
475  // try to traverse from first end to second end
476  // set predecessor and successor of ends[0]
477  size_t predecessor = ends[0];
478  OPENGM_ASSERT(numberOfVariables() < std::numeric_limits<size_t>::max());
479  size_t successor = std::numeric_limits<size_t>::max();
480  for(ConstFactorIterator iter = factorsOfVariableBegin(ends[0]); iter != factorsOfVariableEnd(ends[0]); iter++) {
481  if(numberOfVariables(*iter) == 2) {
482  successor = secondVariableOfSecondOrderFactor(ends[0], *iter);
483  }
484  }
485 
486  OPENGM_ASSERT(successor != std::numeric_limits<size_t>::max());
487 
488  // traverse chain while successor != ends[1]
489  size_t countTraversedVariables = 1;
490  while(successor != ends[1]) {
491  marray::Vector<size_t> secondOrderFactorIds;
492  size_t countSecondOrderFactors = numberOfNthOrderFactorsOfVariable(successor, 2, secondOrderFactorIds);
493  if(countSecondOrderFactors > 2) {
494  return false;
495  }
496  // add successor to chainIDs
497  chainIDs[countTraversedVariables] = successor;
498  countTraversedVariables++;
499 
500  // update predecessor and successor
501  OPENGM_ASSERT(secondOrderFactorIds.size() == 2);
502  for(size_t j = 0; j < 2; j++) {
503  size_t possibleSuccesor = secondVariableOfSecondOrderFactor(successor, secondOrderFactorIds[j]);
504  if(possibleSuccesor != predecessor) {
505  predecessor = successor;
506  successor = possibleSuccesor;
507  break;
508  }
509  }
510  }
511 
512  if(countTraversedVariables != numVariables - 1) {
513  // end of chain reached too soon
514  return false;
515  }
516  OPENGM_ASSERT(countTraversedVariables == numVariables - 1);
517 
518  // check if last variable is really the expected second end
519  OPENGM_ASSERT(chainIDs[numVariables - 1] == ends[1]);
520 
521  return true;
522 }
523 
527 template<class S,class I>
528 inline bool
530 
531  // check if factor graph has zero variables
532  if(numberOfVariables() == 0) {
533  return false;
534  }
535 
536  // check Factor Order
537  if(!maxFactorOrder(2)) {
538  return false;
539  }
540 
541  // special case: graph contains only one variable
542  if(numberOfVariables() == 1) {
543  gridIDs = marray::Matrix<size_t>(1,1);
544  gridIDs(0, 0) = 0;
545  return true;
546  }
547 
548  // check one dimensional case (e.g. graph is a chain)
549  marray::Vector<size_t> chainIDs;
550  bool graphIsChain = isChain(chainIDs);
551  if(graphIsChain) {
552  gridIDs = marray::Matrix<size_t>(1, chainIDs.size());
553  for(size_t i = 0; i < chainIDs.size(); i++) {
554  gridIDs(0, i) = chainIDs[i];
555  }
556  return true;
557  }
558 
559  // find corner variables (variables connected to two second order factors)
560  // and outer hull variables
561  marray::Vector<size_t> cornerIDs(4);
562  size_t numCornersFound = 0;
563  std::list<size_t> outerHullVariableIDs;
564 
565  for(size_t i = 0; i < numberOfVariables(); i++) {
566  size_t countSecondOrderFactors = numberOfNthOrderFactorsOfVariable(i, 2);
567  if(countSecondOrderFactors == 2) {
568  // corner found
569  if(numCornersFound > 3) {
570  return false;
571  }
572  cornerIDs(numCornersFound) = i;
573  numCornersFound++;
574  // corner is also an outer hull variable
575  outerHullVariableIDs.push_back(i);
576  } else if(countSecondOrderFactors == 3) {
577  outerHullVariableIDs.push_back(i);
578  } else if(countSecondOrderFactors > 4) {
579  // variable is connected to too many other variables
580  return false;
581  }
582  }
583 
584  if(numCornersFound < 4) {
585  return false;
586  }
587 
588  OPENGM_ASSERT(numCornersFound == 4);
589 
590  // find shortest path from one corner to all other corners
591  std::vector<std::list<size_t> > shortestPaths(3);
592  if(!shortestPath(cornerIDs(0), cornerIDs(1), shortestPaths[0], outerHullVariableIDs)) {
593  return false;
594  }
595 
596  if(!shortestPath(cornerIDs(0), cornerIDs(2), shortestPaths[1], outerHullVariableIDs)) {
597  return false;
598  }
599 
600  if(!shortestPath(cornerIDs(0), cornerIDs(3), shortestPaths[2], outerHullVariableIDs)) {
601  return false;
602  }
603 
604  // find diagonal corner
605  size_t diagonalCorner = 1;
606  for(size_t i = 1; i < 4; i++) {
607  if(shortestPaths[i - 1].size() > shortestPaths[diagonalCorner].size()) {
608  diagonalCorner = i;
609  }
610  }
611 
612  // compute shortest paths from adjacent corners to diagonal corner
613  std::vector<std::list<size_t> > shortestAdjacentCornerPaths(2);
614  size_t shortestAdjacentCornerPathsComputed = 0;
615  for(size_t i = 1; i < 4; i++) {
616  if(i != diagonalCorner) {
617  if(!shortestPath(cornerIDs(i), cornerIDs(diagonalCorner), shortestAdjacentCornerPaths[shortestAdjacentCornerPathsComputed], outerHullVariableIDs)) {
618  return false;
619  }
620  shortestAdjacentCornerPathsComputed++;
621  }
622  }
623  OPENGM_ASSERT(shortestAdjacentCornerPathsComputed == 2);
624 
625  // compute grid dimension
626  std::vector<size_t> dimension(2);
627  size_t dimensionIndex = 0;
628  for(size_t i = 1; i < 4; i++) {
629  if(i != diagonalCorner) {
630  dimension[dimensionIndex] = shortestPaths[i - 1].size();
631  dimensionIndex++;
632  }
633  }
634  OPENGM_ASSERT(dimensionIndex == 2);
635 
636  //check dimensions
637  if(dimension[0] != shortestAdjacentCornerPaths[1].size()) {
638  return false;
639  }
640  if(dimension[1] != shortestAdjacentCornerPaths[0].size()) {
641  return false;
642  }
643 
644  // create storage
645  gridIDs = marray::Matrix<size_t>(dimension[0], dimension[1]);
646 
647  // fill outer values
648  // from first corner to adjacent corners
649  bool transpose = false;
650  for(size_t i = 1; i < 4; i++) {
651  if(i != diagonalCorner) {
652  size_t indexHelper = 0;
653  if(transpose == false) {
654  for(typename std::list<size_t>::iterator iter = shortestPaths[i - 1].begin(); iter != shortestPaths[i - 1].end(); iter++) {
655  gridIDs(indexHelper, 0) = *iter;
656  indexHelper++;
657  }
658  transpose = true;
659  } else {
660  for(typename std::list<size_t>::iterator iter = shortestPaths[i - 1].begin(); iter != shortestPaths[i - 1].end(); iter++) {
661  gridIDs(0, indexHelper) = *iter;
662  indexHelper++;
663  }
664  }
665 
666  }
667  }
668 
669  // from diagonal corner to adjacent corners
670  transpose = false;
671  for(size_t i = 0; i <= 1; i++) {
672  size_t indexHelper = 0;
673  if(transpose == false) {
674  for(typename std::list<size_t>::iterator iter = shortestAdjacentCornerPaths[i].begin(); iter != shortestAdjacentCornerPaths[i].end(); iter++) {
675  gridIDs(dimension[0] - 1, indexHelper) = *iter;
676  indexHelper++;
677  }
678  transpose = true;
679  } else {
680  for(typename std::list<size_t>::iterator iter = shortestAdjacentCornerPaths[i].begin(); iter != shortestAdjacentCornerPaths[i].end(); iter++) {
681  gridIDs(indexHelper, dimension[1] - 1) = *iter;
682  indexHelper++;
683  }
684  }
685  }
686 
687  // fill inner values
688  for(size_t i = 1; i < dimension[0] - 1; i++) {
689  for(size_t j = 1; j < dimension[1] - 1; j++) {
690  std::vector<size_t> oneHopVariables;
691  if(twoHopConnected(gridIDs(i - 1, j), gridIDs(i, j - 1), oneHopVariables)) {
692  if(oneHopVariables.size() < 2) {
693  return false;
694  }
695  OPENGM_ASSERT(oneHopVariables.size() == 2);
696  if(oneHopVariables[0] != gridIDs(i - 1, j - 1)) {
697  gridIDs(i, j) = oneHopVariables[0];
698  } else {
699  gridIDs(i, j) = oneHopVariables[1];
700  }
701  } else {
702  return false;
703  }
704  }
705  }
706 
707  return true;
708 }
709 
712 template<class S,class I>
713 inline size_t
715  size_t maxFactorOrder = 0;
716  for(size_t i = 0; i < numberOfFactors(); i++) {
717  if(numberOfVariables(i) > maxFactorOrder) {
718  maxFactorOrder = numberOfVariables(i);
719  }
720  }
721  return maxFactorOrder;
722 }
723 
727 template<class S,class I>
728 inline bool
729 FactorGraph<S,I>::maxFactorOrder(const size_t maxOrder) const {
730  for(size_t i = 0; i < numberOfFactors(); i++) {
731  if(numberOfVariables(i) > maxOrder) {
732  return false;
733  }
734  }
735  return true;
736 }
737 
742 template<class S,class I>
743 inline size_t
744 FactorGraph<S,I>::numberOfNthOrderFactorsOfVariable(const size_t variable, const size_t n) const {
745  OPENGM_ASSERT(variable < numberOfVariables());
746  size_t countNthOrderFactors = 0;
747  for(ConstFactorIterator iter = factorsOfVariableBegin(variable); iter != factorsOfVariableEnd(variable); iter++) {
748  if(numberOfVariables(*iter) == n) {
749  countNthOrderFactors++;
750  }
751  }
752  return countNthOrderFactors;
753 }
754 
760 template<class S,class I>
761 inline size_t
762 FactorGraph<S,I>::numberOfNthOrderFactorsOfVariable(const size_t variable, const size_t n, marray::Vector<size_t>& factorIDs) const {
763  OPENGM_ASSERT(variable < numberOfVariables());
764  // FIXME this might be done more efficiently without numberOfNthOrderFactorsOfVariable(variable, n) if marray::Vector<size_t> would support something like push_back()
765  size_t countNthOrderFactors = numberOfNthOrderFactorsOfVariable(variable, n);
766  factorIDs = marray::Vector<size_t>(countNthOrderFactors);
767  for(ConstFactorIterator iter = factorsOfVariableBegin(variable); iter != factorsOfVariableEnd(variable); iter++) {
768  if(numberOfVariables(*iter) == n) {
769  countNthOrderFactors--;
770  factorIDs[countNthOrderFactors] = *iter;
771  }
772  }
773  OPENGM_ASSERT(countNthOrderFactors == 0);
774  return factorIDs.size();
775 }
776 
781 template<class S,class I>
782 inline size_t
783 FactorGraph<S,I>::secondVariableOfSecondOrderFactor(const size_t variable, const size_t factor) const {
784  OPENGM_ASSERT(variable < numberOfVariables());
785  OPENGM_ASSERT(factor < numberOfFactors());
786  OPENGM_ASSERT(numberOfVariables(factor) == 2);
787  OPENGM_ASSERT(variableFactorConnection(variable, factor));
788  for(ConstVariableIterator iter = variablesOfFactorBegin(factor); iter != variablesOfFactorEnd(factor); iter++) {
789  if(*iter != variable) {
790  return *iter;
791  }
792  }
793  return variable;
794 }
795 
800 template<class S,class I>
801 inline bool
803 (
804  const size_t factor1,
805  const size_t factor2
806 ) const
807 {
808  OPENGM_ASSERT(factor1 < numberOfFactors());
809  OPENGM_ASSERT(factor2 < numberOfFactors());
810  if(factor1 != factor2) {
811  ConstVariableIterator it1 = variablesOfFactorBegin(factor1);
812  ConstVariableIterator it2 = variablesOfFactorBegin(factor2);
813  while(it1 != variablesOfFactorEnd(factor1) && it2 != variablesOfFactorEnd(factor2)) {
814  if(*it1 < *it2) {
815  ++it1;
816  }
817  else if(*it1 == *it2) {
818  return true;
819  }
820  else {
821  ++it2;
822  }
823  }
824  }
825  return false;
826 }
827 
830 template<class S,class I>
831 inline void
833 (
835 ) const
836 {
837  out = marray::Matrix<bool>(numberOfVariables(), numberOfVariables(), false);
838  for(size_t factor=0; factor<numberOfFactors(); ++factor) {
839  for(size_t j=0; j<numberOfVariables(factor); ++j) {
840  for(size_t k=j+1; k<numberOfVariables(factor); ++k) {
841  const size_t variable1 = variableOfFactor(factor, j);
842  const size_t variable2 = variableOfFactor(factor, k);
843  out(variable1, variable2) = true;
844  out(variable2, variable1) = true;
845  }
846  }
847  }
848 }
849 
852 template<class S,class I>
853 inline void
855 (
856  std::vector<RandomAccessSet<IndexType> >& out
857 ) const
858 {
859  templatedVariableAdjacencyList(out);
860 }
861 
864 template<class S,class I>
865 inline void
867 (
868  std::vector<std::set<IndexType> >& out
869 ) const
870 {
871  templatedVariableAdjacencyList(out);
872 }
873 
876 template<class S,class I>
877 template<class LIST>
878 inline void
880 (
881  LIST& out
882 ) const
883 {
884  out.clear();
885  out.resize(numberOfVariables());
886  for(size_t factor=0; factor<numberOfFactors(); ++factor) {
887  for(size_t j=0; j<numberOfVariables(factor); ++j) {
888  for(size_t k=j+1; k<numberOfVariables(factor); ++k) {
889  const size_t variable1 = variableOfFactor(factor, j);
890  const size_t variable2 = variableOfFactor(factor, k);
891  out[variable1].insert(variable2);
892  out[variable2].insert(variable1);
893  }
894  }
895  }
896 }
897 
898 template<class S,class I>
899 inline void
901 (
902  std::vector<std::set<IndexType> >& out
903 ) const
904 {
905  templatedFactorAdjacencyList(out);
906 }
907 
908 template<class S,class I>
909 inline void
911 (
912  std::vector< RandomAccessSet<IndexType> >& out
913 ) const
914 {
915  templatedFactorAdjacencyList(out);
916 }
917 
918 template<class S,class I>
919 template<class LIST>
920 inline void
922 (
923  LIST& out
924 ) const
925 {
926  out.clear();
927  out.resize(numberOfFactors());
928  for(size_t f=0; f<numberOfFactors(); ++f) {
929  for(size_t v=0 ;v<numberOfVariables(f); ++v) {
930  for(size_t ff=0;ff<numberOfFactors(v);++ff) {
931  const size_t fOfVar=factorOfVariable(v,ff);
932  if(f!=fOfVar) {
933  out[f].insert(fOfVar);
934  }
935  }
936  }
937  }
938 }
939 
945 template<class S,class I>
946 template <class LIST>
947 inline bool
948 FactorGraph<S,I>::shortestPath(const size_t s, const size_t t, LIST& path, const LIST& allowedVariables) const {
949  OPENGM_ASSERT(s < numberOfVariables());
950  OPENGM_ASSERT(t < numberOfVariables());
951  OPENGM_ASSERT(allowedVariables.size() <= numberOfVariables());
952  OPENGM_ASSERT(numberOfVariables() != std::numeric_limits<size_t>::max());
953  const size_t infinity = std::numeric_limits<size_t>::max();
954 
955  bool useAllVariables = (allowedVariables.size() == 0) || (allowedVariables.size() == numberOfVariables());
956 
957  if(useAllVariables) {
958  std::vector<size_t> distances(numberOfVariables(), infinity);
959  std::vector<size_t> previous(numberOfVariables(), infinity);
960  distances[s] = 0;
961  LIST Q;
962  for(size_t i = 0; i < numberOfVariables(); i++) {
963  Q.push_back(i);
964  }
965  while(Q.size() !=0) {
966  typename LIST::iterator currentIter = Q.begin();
967  for(typename LIST::iterator iter = Q.begin(); iter != Q.end(); iter++) {
968  if(distances[*iter] < distances[*currentIter]) {
969  currentIter = iter;
970  }
971  }
972  if(distances[*currentIter] == infinity) {
973  // all remaining variables are inaccessible from s
974  return false;
975  }
976  if(*currentIter == t) {
977  // target found
978  break;
979  }
980  size_t currentID = *currentIter;
981  Q.erase(currentIter);
982  // iterate over all neighbor variables of *current which are still in Q
983  for(ConstFactorIterator factorIter = factorsOfVariableBegin(currentID); factorIter != factorsOfVariableEnd(currentID); factorIter++) {
984  for(ConstVariableIterator variableIter = variablesOfFactorBegin(*factorIter); variableIter != variablesOfFactorEnd(*factorIter); variableIter++) {
985  if(std::find(Q.begin(), Q.end(), *variableIter) != Q.end()) {
986  size_t newDistance = distances[currentID] + 1;
987  if(newDistance < distances[*variableIter]) {
988  distances[*variableIter] = newDistance;
989  previous[*variableIter] = currentID;
990  }
991  }
992  }
993  }
994  }
995  OPENGM_ASSERT(previous[t] != infinity);
996  // create path
997  size_t u = t;
998  while(previous[u] != infinity) {
999  path.push_front(u);
1000  u = previous[u];
1001  }
1002  path.push_front(s);
1003  return true;
1004  } else {
1005  OPENGM_ASSERT(std::find(allowedVariables.begin(), allowedVariables.end(), s) != allowedVariables.end());
1006  OPENGM_ASSERT(std::find(allowedVariables.begin(), allowedVariables.end(), t) != allowedVariables.end());
1007  std::vector<size_t> distances(allowedVariables.size(), infinity);
1008  std::vector<size_t> previous(allowedVariables.size(), infinity);
1009  std::map<size_t, size_t> local2actualIDs;
1010  std::map<size_t, size_t> actual2localIDs;
1011  LIST Q;
1012  size_t counter = 0;
1013  for(typename LIST::const_iterator iter = allowedVariables.begin(); iter != allowedVariables.end(); iter++) {
1014  Q.push_back(counter);
1015  local2actualIDs.insert(std::pair<size_t, size_t>(counter, *iter));
1016  actual2localIDs.insert(std::pair<size_t, size_t>(*iter, counter));
1017  counter++;
1018  }
1019  distances[actual2localIDs.find(s)->second] = 0;
1020  while(Q.size() !=0) {
1021  typename LIST::iterator currentIter = Q.begin();
1022  for(typename LIST::iterator iter = Q.begin(); iter != Q.end(); iter++) {
1023  if(distances[*iter] < distances[*currentIter]) {
1024  currentIter = iter;
1025  }
1026  }
1027  if(distances[*currentIter] == infinity) {
1028  // all remaining variables are inaccessible from s
1029  return false;
1030  }
1031  // get actual ID
1032  size_t actualID = local2actualIDs.find(*currentIter)->second;
1033  if(actualID == t) {
1034  // target found
1035  break;
1036  }
1037  size_t currentLocalID = *currentIter;
1038  Q.erase(currentIter);
1039  // iterate over all neighbor variables of *current which are in allowedVariables and are still in Q
1040  for(ConstFactorIterator factorIter = factorsOfVariableBegin(actualID); factorIter != factorsOfVariableEnd(actualID); factorIter++) {
1041  for(ConstVariableIterator variableIter = variablesOfFactorBegin(*factorIter); variableIter != variablesOfFactorEnd(*factorIter); variableIter++) {
1042  const std::map<size_t, size_t>::const_iterator actual2localIDsCurrentPosition = actual2localIDs.find(*variableIter);
1043  if(actual2localIDsCurrentPosition != actual2localIDs.end()) {
1044  size_t localID = actual2localIDsCurrentPosition->second;
1045  if(std::find(Q.begin(), Q.end(), localID) != Q.end()) {
1046  size_t newDistance = distances[currentLocalID] + 1;
1047  if(newDistance < distances[localID]) {
1048  distances[localID] = newDistance;
1049  previous[localID] = currentLocalID;
1050  }
1051  }
1052  }
1053  }
1054  }
1055  }
1056  OPENGM_ASSERT(actual2localIDs.find(t)->second != infinity);
1057  // create path
1058  size_t u = actual2localIDs.find(t)->second;
1059  while(previous[u] != infinity) {
1060 
1061  path.push_front(local2actualIDs.find(u)->second);
1062  u = previous[u];
1063  }
1064  path.push_front(s);
1065  return true;
1066  }
1067  return false;
1068 }
1069 
1074 template<class S,class I>
1075 template <class LIST>
1076 inline bool
1077 FactorGraph<S,I>::twoHopConnected(const size_t variable1, const size_t variable2, LIST& oneHopVariables) const {
1078  OPENGM_ASSERT(variable1 < numberOfVariables());
1079  OPENGM_ASSERT(variable2 < numberOfVariables());
1080  oneHopVariables.clear();
1081  if(variable1 != variable2) {
1082  for(ConstFactorIterator factorIter = factorsOfVariableBegin(variable1); factorIter != factorsOfVariableEnd(variable1); factorIter++) {
1083  for(ConstVariableIterator variableIter = variablesOfFactorBegin(*factorIter); variableIter != variablesOfFactorEnd(*factorIter); variableIter++) {
1084  if((*variableIter != variable1) || (*variableIter != variable2)) {
1085  if(variableVariableConnection(*variableIter, variable2)) {
1086  oneHopVariables.push_back(*variableIter);
1087  }
1088  }
1089  }
1090  }
1091  }
1092  if(oneHopVariables.size() == 0) {
1093  return false;
1094  } else {
1095  return true;
1096  }
1097 }
1098 
1099 } // namespace opengm
1100 
1101 #endif // #ifndef OPENGM_FACTORGRAPH_HXX
AccessorIterator< FactorAccessor, true > ConstFactorIterator
Definition: factorgraph.hxx:26
size_t variableOfFactor(const size_t, const size_t) const
j-th variable node connected to a factor node
bool isGrid(marray::Matrix< size_t > &) const
return true if the factor graph (!) is a grid
The OpenGM namespace.
Definition: config.hxx:43
size_t secondVariableOfSecondOrderFactor(const size_t, const size_t) const
return returns the id of the second variable which is connected to a given variable via a second orde...
void merge(value_type, value_type)
Merge two sets.
Definition: partition.hxx:147
Interface that makes an object of type S (the template parameter) look like a (non-editable) factor g...
Definition: factorgraph.hxx:18
bool isAcyclic() const
return true if the factor graph (!) is acyclic
size_t numberOfVariables() const
total number of variable nodes in the factor graph
void factorAdjacencyList(std::vector< std::set< IndexType > > &) const
bool operator==(const IndicatorVariable< INDEX1_TYPE, LABEL1_TYPE > &indicatorVar1, const IndicatorVariable< INDEX2_TYPE, LABEL2_TYPE > &indicatorVar2)
ConstFactorIterator factorsOfVariableEnd(const size_t) const
constant iterator to the end of the squence of factors connected to a variable
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
value_type numberOfSets() const
Definition: partition.hxx:258
bool shortestPath(const size_t, const size_t, LIST &, const LIST &=LIST()) const
computes the shortest path from s to t using Dijkstra's algorithm with uniform distances ...
One-dimensional Marray.
Definition: marray.hxx:50
size_t factorOfVariable(const size_t, const size_t) const
j-th factor node connected to a variable node
ConstVariableIterator variablesOfFactorEnd(const size_t) const
constant iterator to the end of the squence of variables connected to a factor
bool variableVariableConnection(const size_t, const size_t) const
return true if a variable is connected to a variable
bool isConnected(marray::Vector< size_t > &representatives) const
return true if the factor graph (!) is connected
AccessorIterator< VariableAccessor, true > ConstVariableIterator
Definition: factorgraph.hxx:25
const size_t size() const
void transpose(const MatrixWrapper< T > &input, MatrixWrapper< T > &result)
void variableAdjacencyMatrix(marray::Matrix< bool > &) const
outputs the factor graph as a variable adjacency matrix
size_t numberOfFactors() const
total number of factor nodes in the factor graph
bool twoHopConnected(const size_t, const size_t, LIST &) const
checks if variabel1 is connected to variable2 via two hops
void representatives(Iterator) const
Output all elements which are set representatives.
Definition: partition.hxx:198
bool variableFactorConnection(const size_t, const size_t) const
return true if a factor is connected to a variable
const bool NO_DEBUG
Definition: config.hxx:64
Disjoint set data structure with path compression.
Definition: partition.hxx:13
size_t numberOfNthOrderFactorsOfVariable(const size_t, const size_t) const
return number of factors with order n which are connected to variable
size_t maxFactorOrder() const
return maximum factor order
bool isChain(marray::Vector< size_t > &) const
return true if the factor graph (!) is a chain
bool factorFactorConnection(const size_t, const size_t) const
return true if a factor is connected to a factor
void variableAdjacencyList(std::vector< std::set< IndexType > > &) const
outputs the factor graph as variable adjacency lists
bool factorVariableConnection(const size_t, const size_t) const
return true if a variable is connected to a factor
ConstFactorIterator factorsOfVariableBegin(const size_t) const
constant iterator to the beginning of the squence of factors connected to a variable ...
ConstVariableIterator variablesOfFactorBegin(const size_t) const
constant iterator to the beginning of the squence of variables connected to a factor ...