OpenGM  2.3.x
Discrete Graphical Model Library
function_properties_base.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_FUNCTION_PROPERTIES_BASE_HXX
3 #define OPENGM_FUNCTION_PROPERTIES_BASE_HXX
4 
5 #include <cmath>
6 
7 #include "opengm/opengm.hxx"
15 #include "opengm/operations/or.hxx"
22 
23 #define OPENGM_FLOAT_TOL 0.000001
24 
25 namespace opengm {
26 
27 template<class T>
28 inline bool isNumericEqual(const T a, const T b) {
29  if(meta::IsFloatingPoint<T>::value) {
30  if(a < b) {
31  return b-a<OPENGM_FLOAT_TOL ? true : false;
32  }
33  else {
34  return a - b < OPENGM_FLOAT_TOL ? true : false;
35  }
36  }
37  else {
38  return a == b;
39  }
40 }
41 
43 template<class FUNCTION, class VALUE, class INDEX = size_t, class LABEL = size_t>
44 class FunctionBase {
45 private:
46  typedef VALUE ReturnType;
47  typedef const VALUE& ReturnReferenceType;
48 
49 public:
50  bool isPotts() const;
51  bool isGeneralizedPotts() const;
52  bool isSubmodular() const;
53  bool isSquaredDifference() const;
54  bool isTruncatedSquaredDifference() const;
55  bool isAbsoluteDifference() const;
56  bool isTruncatedAbsoluteDifference() const;
57  bool isLinearConstraint() const;
58 
61  MinMaxFunctor<VALUE> minMax() const;
62 
63  ReturnType min() const;
64  ReturnType max() const;
65  ReturnType sum() const;
66  ReturnType product() const;
67 
71  template<class ACC>
72  ReturnType accumulate() const;
73 
92  template<class FUNCTOR>
93  void forAllValuesInOrder(FUNCTOR& functor) const;
94 
95  template<class FUNCTOR>
96  void forAllValuesInSwitchedOrder(FUNCTOR& functor) const;
97 
101  template<class FUNCTOR>
102  void forAllValuesInAnyOrder(FUNCTOR& functor) const;
103 
107  template<class FUNCTOR>
108  void forAtLeastAllUniqueValues(FUNCTOR& functor) const ;
109 
110 
111  template<class COORDINATE_FUNCTOR>
112  void forAllValuesInOrderWithCoordinate(COORDINATE_FUNCTOR& functor) const;
113  template<class COORDINATE_FUNCTOR>
114  void forAllValuesInAnyOrderWithCoordinate(COORDINATE_FUNCTOR& functor) const;
115  template<class COORDINATE_FUNCTOR>
116  void forAtLeastAllUniqueValuesWithCoordinate(COORDINATE_FUNCTOR& functor) const ;
117 
118  bool operator==(const FUNCTION&) const;
119 
120 private:
121  typedef FUNCTION FunctionType;
122  typedef FunctionShapeAccessor<FunctionType> FunctionShapeAccessorType;
123 
124 public:
125  typedef AccessorIterator<FunctionShapeAccessorType, true> FunctionShapeIteratorType;
126 
127  FunctionShapeIteratorType functionShapeBegin() const;
128  FunctionShapeIteratorType functionShapeEnd() const;
129 
130  size_t numberOfParameters()const{
131  return 0;
132  }
133  INDEX parameterIndex(const size_t paramNumber)const{
134  throw RuntimeError("Function base has no parameters,this needs to be implemented in any function type");
135  }
136 };
137 
138 
139 
140 
141 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
142 inline bool
143 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::operator==
144 (
145  const FUNCTION& fb
146 ) const{
147  const FunctionType& fa=*static_cast<FunctionType const *>(this);
148  const size_t dimA=fa.dimension();
149  // compare dimension
150  if(dimA==fb.dimension()) {
151  // compare shape
152  for(size_t i=0;i<dimA;++i) {
153  if(fa.shape(i)!=fb.shape(i)) {
154  return false;
155  }
156  }
157  // compare all values
158  ShapeWalker<FunctionShapeIteratorType> shapeWalker(fa.functionShapeBegin(), dimA);
159  for(INDEX i=0;i<fa.size();++i, ++shapeWalker) {
160  if(isNumericEqual(fa(shapeWalker.coordinateTuple().begin()), fb(shapeWalker.coordinateTuple().begin()))==false) {
161  return false;
162  }
163  }
164  }
165  else{
166  return false;
167  }
168  return true;
169 }
170 
171 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
172 template<class COORDINATE_FUNCTOR>
173 inline void
175 (
176  COORDINATE_FUNCTOR& functor
177 ) const {
178  const FunctionType& f=*static_cast<FunctionType const *>(this);
179  ShapeWalker<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
180  for(INDEX i=0;i<f.size();++i, ++shapeWalker) {
181  functor(f(shapeWalker.coordinateTuple().begin()),shapeWalker.coordinateTuple().begin());
182  }
183 }
184 
185 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
186 template<class COORDINATE_FUNCTOR>
187 inline void
189 (
190  COORDINATE_FUNCTOR& functor
191 ) const{
192  this->forAllValuesInOrderWithCoordinate(functor);
193 }
194 
195 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
196 template<class COORDINATE_FUNCTOR>
197 inline void
199 (
200  COORDINATE_FUNCTOR& functor
201 ) const {
202  this->forAllValuesInAnyOrderWithCoordinate(functor);
203 }
204 
205 
206 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
207 template<class FUNCTOR>
208 inline void
210 (
211  FUNCTOR& functor
212 ) const {
213  const FunctionType& f=*static_cast<FunctionType const *>(this);
214  ShapeWalker<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
215  for(INDEX i=0;i<f.size();++i, ++shapeWalker) {
216  functor(f(shapeWalker.coordinateTuple().begin()));
217  }
218 }
219 
220 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
221 template<class FUNCTOR>
222 inline void
224 (
225  FUNCTOR& functor
226 ) const {
227  const FunctionType& f=*static_cast<FunctionType const *>(this);
228  ShapeWalkerSwitchedOrder<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
229  for(INDEX i=0;i<f.size();++i, ++shapeWalker) {
230  functor(f(shapeWalker.coordinateTuple().begin()));
231  }
232 }
233 
234 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
235 template<class FUNCTOR>
236 inline void
238 (
239  FUNCTOR& functor
240 ) const {
241  static_cast<FunctionType const *>(this)->forAllValuesInOrder(functor);
242 }
243 
244 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
245 template<class FUNCTOR>
246 inline void
248 (
249  FUNCTOR& functor
250 ) const {
251  static_cast<FunctionType const *>(this)->forAllValuesInAnyOrder(functor);
252 }
253 
254 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
257  const FunctionType& f=*static_cast<FunctionType const *>(this);
258  return FunctionShapeIteratorType(FunctionShapeAccessorType(f), 0);
259 }
260 
261 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
264  const FunctionType& f=*static_cast<FunctionType const *>(this);
265  return FunctionShapeIteratorType(FunctionShapeAccessorType(f), f.dimension());
266 }
267 
268 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
269 inline bool
271  const FunctionType& f=*static_cast<FunctionType const *>(this);
272  if(f.dimension()==2) {
273  OPENGM_ASSERT(f.shape(0)>static_cast<LABEL>(1));
274  LABEL c[2]={1, 0};
275  //get possible weight
276  VALUE weight=f(c);
277  for( c[1]=0;c[1]<f.shape(1);++c[1]) {
278  for( c[0]=0;c[0]<f.shape(0);++c[0]) {
279  VALUE d= static_cast<VALUE> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
280  d*=d;
281  if( isNumericEqual(f(c), d*weight )==false)
282  return false;
283  }
284  }
285  return true;
286  }
287  return false;
288 }
289 
290 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
291 inline bool
293  const FunctionType& f=*static_cast<FunctionType const *>(this);
294  if(f.dimension()==2) {
295  OPENGM_ASSERT(f.shape(0)>static_cast<LABEL>(1));
296  LABEL c[2]={1, 0};
297  //get possible weight
298  VALUE weight=f(c);
299  //get possible truncation (compute the biggest possible distance => value is the truncation value)
300  c[0]=f.shape(0)-static_cast<LABEL>(1);
301  VALUE truncated=f(c);
302  for( c[1]=0;c[1]<f.shape(1);++c[1]) {
303  for( c[0]=0;c[0]<f.shape(0);++c[0]) {
304  VALUE d= static_cast<VALUE> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
305  d*=d;
306  const VALUE fval=f(c);
307  const VALUE compare=d*weight;
308  if( isNumericEqual(fval, compare )==false && ((isNumericEqual(fval, truncated) && truncated<compare)==false)) {
309  return false;
310  }
311  }
312  }
313  return true;
314  }
315  return false;
316 }
317 
318 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
319 inline bool
321  const FunctionType& f=*static_cast<FunctionType const *>(this);
322  if(f.dimension()==2) {
323  OPENGM_ASSERT(f.shape(0)>static_cast<LABEL>(1));
324  LABEL c[2]={1, 0};
325  //get possible weight
326  VALUE weight=f(c);
327  for( c[1]=0;c[1]<f.shape(1);++c[1]) {
328  for( c[0]=0;c[0]<f.shape(0);++c[0]) {
329  VALUE d= static_cast<VALUE> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
330  if( isNumericEqual(f(c), d*weight )==false)
331  return false;
332  }
333  }
334  return true;
335  }
336  return false;
337 }
338 
339 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
340 inline bool
342  const FunctionType& f=*static_cast<FunctionType const *>(this);
343  if(f.dimension()==2) {
344  OPENGM_ASSERT(f.shape(0)>static_cast<LABEL>(1));
345  LABEL c[2]={1, 0};
346  //get possible weight
347  VALUE weight=f(c);
348  //get possible truncation (compute the biggest possible distance => value is the truncation value)
349  c[0]=f.shape(0)-static_cast<LABEL>(1);
350  VALUE truncated=f(c);
351  for( c[1]=0;c[1]<f.shape(1);++c[1]) {
352  for( c[0]=0;c[0]<f.shape(0);++c[0]) {
353  VALUE d= static_cast<VALUE> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
354  const VALUE fval=f(c);
355  const VALUE compare=d*weight;
356  if( isNumericEqual(fval, compare )==false && ((isNumericEqual(fval, truncated) && truncated<compare)==false)) {
357  return false;
358  }
359  }
360  }
361  return true;
362  }
363  return false;
364 }
365 
366 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
367 inline bool
369  const FunctionType& f=*static_cast<FunctionType const *>(this);
370  if (f.size()<=2) return true;//BSD: Bug fixed?
371  ShapeWalker<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
372  VALUE vEqual=f(shapeWalker.coordinateTuple().begin());
373  ++shapeWalker;
374  VALUE vNotEqual=f(shapeWalker.coordinateTuple().begin());
375  ++shapeWalker;
376  for(INDEX i=2;i<f.size();++i, ++shapeWalker) {
377  // all labels are equal
378  if(isEqualValueVector(shapeWalker.coordinateTuple()) ) {
379  if(vEqual!=f(shapeWalker.coordinateTuple().begin()))
380  return false;
381  }
382  // all labels are not equal
383  else{
384  if(vNotEqual!=f(shapeWalker.coordinateTuple().begin()))
385  return false;
386  }
387  }
388  return true;
389 }
390 
391 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
392 inline bool
394  const FunctionType& f=*static_cast<FunctionType const *>(this);
395  if(f.dimension()==2) {
396  LABEL l[] = {0, 1};
397  VALUE v0 = f(l);
398  l[1]=0;
399  VALUE v1 = f(l);
400  for(l[0]=0;l[0]<f.shape(0);++l[0]) {
401  for(l[1]=0;l[1]<f.shape(1);++l[1]) {
402  if((l[0]==l[1] && f(l)!=v1) || ((l[0]!=l[1] && f(l)!=v0)) ) return false;
403  }
404  }
405  return true;
406  }
407  else if(f.dimension()==3) {
408  LABEL l[] = {0, 1, 2};
409  VALUE v000 = f(l);
410  l[2]=0; l[1]=1; l[0]=1;
411  VALUE v001 = f(l);
412  l[2]=1; l[1]=0; l[0]=1;
413  VALUE v010 = f(l);
414  l[2]=1; l[1]=1; l[0]=0;
415  VALUE v100 = f(l);
416  l[2]=0; l[1]=0; l[0]=0;
417  VALUE v111 = f(l);
418  for(l[0]=0;l[0]<f.shape(0);++l[0]) {
419  for(l[1]=0;l[1]<f.shape(1);++l[1]) {
420  for(l[2]=0;l[2]<f.shape(2);++l[2]) {
421  if((l[1]!=l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v000) ) return false;
422  if((l[1]!=l[2] && l[0]!=l[2] && l[0]==l[1] && f(l)!=v001) ) return false;
423  if((l[1]!=l[2] && l[0]==l[2] && l[0]!=l[1] && f(l)!=v010) ) return false;
424  if((l[1]==l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v100) ) return false;
425  if((l[1]==l[2] && l[0]==l[2] && l[0]==l[1] && f(l)!=v111) ) return false;
426  }
427  }
428  }
429  return true;
430  }
431  else if(f.dimension()==4) {
432  LABEL l[] = {0, 1, 2, 3};
433  VALUE v000000 = f(l);
434  l[3]=2; l[2]=1; l[1]=0;l[0]=0;
435  VALUE v000001 = f(l);
436  l[3]=2; l[2]=0; l[1]=1;l[0]=0;
437  VALUE v000010 = f(l);
438  l[3]=2; l[2]=0; l[1]=0;l[0]=1;
439  VALUE v000100 = f(l);
440  l[3]=1; l[2]=0; l[1]=0;l[0]=0; //3-1
441  VALUE v000111 = f(l);
442  l[3]=0; l[2]=1; l[1]=2; l[0]=0;
443  VALUE v001000 = f(l);
444  l[3]=0; l[2]=1; l[1]=1; l[0]=0;
445  VALUE v001100 = f(l);
446  l[3]=0; l[2]=1; l[1]=0; l[0]=0; //3-1
447  VALUE v011001 = f(l);
448  l[3]=0; l[2]=0; l[1]=0; l[0]=1; //3-1
449  VALUE v110100 = f(l);
450  l[3]=0; l[2]=0; l[1]=0; l[0]=0;
451  VALUE v111111 = f(l);
452  l[3]=1; l[2]=1; l[1]=0; l[0]=0;
453  VALUE v100001 = f(l);
454  l[3]=1; l[2]=0; l[1]=1; l[0]=0;
455  VALUE v010010 = f(l);
456  l[3]=0; l[2]=0; l[1]=1; l[0]=2;
457  VALUE v100000 = f(l);
458  l[3]=0; l[2]=1; l[1]=0; l[0]=2;
459  VALUE v010000 = f(l);
460  l[3]=0; l[2]=0; l[1]=1; l[0]=0; //3-1
461  VALUE v101010 = f(l);
462 
463 
464  for(l[0]=0;l[0]<f.shape(0);++l[0]) {
465  for(l[1]=0;l[1]<f.shape(1);++l[1]) {
466  for(l[2]=0;l[2]<f.shape(2);++l[2]) {
467  for(l[3]=0;l[3]<f.shape(3);++l[3]) {
468  if((l[2]!=l[3] && l[1]!=l[3] && l[0]!=l[3] && l[1]!=l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v000000) ) {std::cout<<"1"; return false;}
469  if((l[2]!=l[3] && l[1]!=l[3] && l[0]!=l[3] && l[1]!=l[2] && l[0]!=l[2] && l[0]==l[1] && f(l)!=v000001) ) {std::cout<<"1"; return false;}
470  if((l[2]!=l[3] && l[1]!=l[3] && l[0]!=l[3] && l[1]!=l[2] && l[0]==l[2] && l[0]!=l[1] && f(l)!=v000010) ) {std::cout<<"1"; return false;}
471  if((l[2]!=l[3] && l[1]!=l[3] && l[0]!=l[3] && l[1]==l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v000100) ) {std::cout<<"1"; return false;}
472  if((l[2]!=l[3] && l[1]!=l[3] && l[0]!=l[3] && l[1]==l[2] && l[0]==l[2] && l[0]==l[1] && f(l)!=v000111) ) {std::cout<<"1"; return false;}
473 
474  if((l[2]!=l[3] && l[1]!=l[3] && l[0]==l[3] && l[1]!=l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v001000) ) {std::cout<<"1"; return false;}
475  if((l[2]!=l[3] && l[1]!=l[3] && l[0]==l[3] && l[1]==l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v001100) ) {std::cout<<"1"; return false;}
476 
477  if((l[2]!=l[3] && l[1]==l[3] && l[0]!=l[3] && l[1]!=l[2] && l[0]==l[2] && l[0]!=l[1] && f(l)!=v010010) ) {std::cout<<"1"; return false;}
478  if((l[2]!=l[3] && l[1]==l[3] && l[0]!=l[3] && l[1]!=l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v010000) ) {std::cout<<"1"; return false;}
479  if((l[2]!=l[3] && l[1]==l[3] && l[0]==l[3] && l[1]!=l[2] && l[0]!=l[2] && l[0]==l[1] && f(l)!=v011001) ) {std::cout<<"1"; return false;}
480 
481  if((l[2]==l[3] && l[1]==l[3] && l[0]!=l[3] && l[1]==l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v110100) ) {std::cout<<"1"; return false;}
482  if((l[2]==l[3] && l[1]==l[3] && l[0]==l[3] && l[1]==l[2] && l[0]==l[2] && l[0]==l[1] && f(l)!=v111111) ) {std::cout<<"1"; return false;}
483 
484  if((l[2]==l[3] && l[1]!=l[3] && l[0]!=l[3] && l[1]!=l[2] && l[0]!=l[2] && l[0]==l[1] && f(l)!=v100001) ) {std::cout<<"1"; return false;}
485  if((l[2]==l[3] && l[1]!=l[3] && l[0]!=l[3] && l[1]!=l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v100000) ) {std::cout<<"1"; return false;}
486  if((l[2]==l[3] && l[1]!=l[3] && l[0]==l[3] && l[1]!=l[2] && l[0]==l[2] && l[0]!=l[1] && f(l)!=v101010) ) {std::cout<<"1"; return false;}
487  }
488  }
489  }
490  }
491  return true;
492  }
493  else{
494  return false;
495  }
496 }
497 
498 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
499 inline bool
501  const FunctionType& f = *static_cast<FunctionType const *>(this);
502  if(f.dimension()==1){
503  return true;
504  }
505  if(f.dimension()!=2 ||f.shape(0)!=2 || f.shape(1)!=2) {
506  throw RuntimeError("Fallback FunctionBase::isSubmodular only defined for binary functions with order less than 3");
507  }
508  LABEL l00[] = {0, 0};
509  LABEL l01[] = {0, 1};
510  LABEL l10[] = {1, 0};
511  LABEL l11[] = {1, 1};
512 
513  return f(l00)+f(l11)<= f(l10)+f(l01);
514 }
515 
516 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
517 inline bool
519  // by default all Functions are not of type linear constraint.
520  return false;
521 }
522 
523 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
524 inline MinMaxFunctor<VALUE>
526  const FunctionType& f=*static_cast<FunctionType const *>(this);
527  opengm::FastSequence<INDEX> c(f.dimension(), 0);
528  const VALUE tmp=f(c.begin());
529  MinMaxFunctor<VALUE> minMax(tmp, tmp);
530  static_cast<FunctionType const *>(this)->forAtLeastAllUniqueValues(minMax);
531  return minMax;
532 }
533 
534 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
535 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
537  const FunctionType& f=*static_cast<FunctionType const *>(this);
538  opengm::FastSequence<INDEX> c(f.dimension(), 0);
539  AccumulationFunctor<Minimizer, VALUE> accumulator(f(c.begin()));
540  static_cast<FunctionType const *>(this)->forAtLeastAllUniqueValues(accumulator);
541  return accumulator.value();
542 }
543 
544 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
545 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
547  const FunctionType& f=*static_cast<FunctionType const *>(this);
548  opengm::FastSequence<INDEX> c(f.dimension(), 0);
549  AccumulationFunctor<Maximizer, VALUE> accumulator(f(c.begin()));
550  static_cast<FunctionType const *>(this)->forAtLeastAllUniqueValues(accumulator);
551  return accumulator.value();
552 }
553 
554 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
555 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
557  AccumulationFunctor<Integrator, VALUE> accumulator(static_cast<VALUE>(0));
558  static_cast<FunctionType const *>(this)->forAllValuesInAnyOrder(accumulator);
559  return accumulator.value();
560 }
561 
562 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
563 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
565  AccumulationFunctor<Multiplier, VALUE> accumulator(static_cast<VALUE>(1));;
566  static_cast<FunctionType const *>(this)->forAllValuesInAnyOrder(accumulator);
567  return accumulator.value();
568 }
569 
570 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
571 template<class ACC>
572 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
574  if(meta::Compare<ACC, Minimizer>::value ) {
575  return static_cast<FunctionType const *>(this)->min();
576  }
577  else if( meta::Compare<ACC, Maximizer>::value ) {
578  return static_cast<FunctionType const *>(this)->max();
579  }
580  else if( meta::Compare<ACC, Adder>::value ) {
581  return static_cast<FunctionType const *>(this)->sum();
582  }
583  else if( meta::Compare<ACC, Integrator>::value ) {
584  return static_cast<FunctionType const *>(this)->sum();
585  }
586  else if( meta::Compare<ACC, Multiplier>::value ) {
587  return static_cast<FunctionType const *>(this)->product();
588  }
589  else{
590  AccumulationFunctor<ACC, VALUE> accumulator;
591  static_cast<FunctionType const *>(this)->forAllValuesInOrder(accumulator);
592  return accumulator.value();
593  }
594 }
595 
596 } // namespace opengm
597 
598 #endif // OPENGM_FUNCTION_PROPERTIES_BASE_HXX
#define OPENGM_FLOAT_TOL
void forAtLeastAllUniqueValuesWithCoordinate(COORDINATE_FUNCTOR &functor) const
bool operator==(const FUNCTION &) const
The OpenGM namespace.
Definition: config.hxx:43
Fallback implementation of member functions of OpenGM functions.
void forAllValuesInOrderWithCoordinate(COORDINATE_FUNCTOR &functor) const
void forAllValuesInSwitchedOrder(FUNCTOR &functor) const
INDEX parameterIndex(const size_t paramNumber) const
bool isNumericEqual(const T a, const T b)
MinMaxFunctor< VALUE > minMax() const
find minimum and maximum of the function in a single sweep
void forAtLeastAllUniqueValues(FUNCTOR &functor) const
call a functor for at least all unique values of the function
AccessorIterator< FunctionShapeAccessorType, true > FunctionShapeIteratorType
FunctionShapeIteratorType functionShapeBegin() const
Vector that stores values on the stack if size is smaller than MAX_STACK.
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
void forAllValuesInOrder(FUNCTOR &functor) const
call a functor for each value of the function (in lexicographical order of the variable indices) ...
ReturnType accumulate() const
accumulate all values of the function
FunctionShapeIteratorType functionShapeEnd() const
void forAllValuesInAnyOrder(FUNCTOR &functor) const
call a functor for each value of the function (in un-specified order)
void forAllValuesInAnyOrderWithCoordinate(COORDINATE_FUNCTOR &functor) const
OpenGM runtime error.
Definition: opengm.hxx:100