2 #ifndef OPENGM_FUNCTION_PROPERTIES_BASE_HXX
3 #define OPENGM_FUNCTION_PROPERTIES_BASE_HXX
23 #define OPENGM_FLOAT_TOL 0.000001
29 if(meta::IsFloatingPoint<T>::value) {
43 template<
class FUNCTION,
class VALUE,
class INDEX =
size_t,
class LABEL =
size_t>
46 typedef VALUE ReturnType;
47 typedef const VALUE& ReturnReferenceType;
61 MinMaxFunctor<VALUE>
minMax()
const;
63 ReturnType
min()
const;
64 ReturnType
max()
const;
65 ReturnType
sum()
const;
92 template<
class FUNCTOR>
95 template<
class FUNCTOR>
101 template<
class FUNCTOR>
107 template<
class FUNCTOR>
111 template<
class COORDINATE_FUNCTOR>
113 template<
class COORDINATE_FUNCTOR>
115 template<
class COORDINATE_FUNCTOR>
121 typedef FUNCTION FunctionType;
122 typedef FunctionShapeAccessor<FunctionType> FunctionShapeAccessorType;
134 throw RuntimeError(
"Function base has no parameters,this needs to be implemented in any function type");
141 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
143 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::operator==
147 const FunctionType& fa=*
static_cast<FunctionType
const *
>(
this);
148 const size_t dimA=fa.dimension();
150 if(dimA==fb.dimension()) {
152 for(
size_t i=0;i<dimA;++i) {
153 if(fa.shape(i)!=fb.shape(i)) {
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) {
171 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
172 template<
class COORDINATE_FUNCTOR>
176 COORDINATE_FUNCTOR& functor
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());
185 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
186 template<
class COORDINATE_FUNCTOR>
190 COORDINATE_FUNCTOR& functor
192 this->forAllValuesInOrderWithCoordinate(functor);
195 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
196 template<
class COORDINATE_FUNCTOR>
200 COORDINATE_FUNCTOR& functor
202 this->forAllValuesInAnyOrderWithCoordinate(functor);
206 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
207 template<
class FUNCTOR>
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()));
220 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
221 template<
class FUNCTOR>
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()));
234 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
235 template<
class FUNCTOR>
241 static_cast<FunctionType
const *
>(
this)->forAllValuesInOrder(functor);
244 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
245 template<
class FUNCTOR>
251 static_cast<FunctionType
const *
>(
this)->forAllValuesInAnyOrder(functor);
254 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
257 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
261 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
264 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
268 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
271 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
272 if(f.dimension()==2) {
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]);
290 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
293 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
294 if(f.dimension()==2) {
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]);
306 const VALUE fval=f(c);
307 const VALUE compare=d*weight;
318 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
321 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
322 if(f.dimension()==2) {
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]);
339 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
342 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
343 if(f.dimension()==2) {
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;
366 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
369 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
370 if (f.size()<=2)
return true;
371 ShapeWalker<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
372 VALUE vEqual=f(shapeWalker.coordinateTuple().begin());
374 VALUE vNotEqual=f(shapeWalker.coordinateTuple().begin());
376 for(INDEX i=2;i<f.size();++i, ++shapeWalker) {
378 if(isEqualValueVector(shapeWalker.coordinateTuple()) ) {
379 if(vEqual!=f(shapeWalker.coordinateTuple().begin()))
384 if(vNotEqual!=f(shapeWalker.coordinateTuple().begin()))
391 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
394 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
395 if(f.dimension()==2) {
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;
407 else if(f.dimension()==3) {
408 LABEL l[] = {0, 1, 2};
410 l[2]=0; l[1]=1; l[0]=1;
412 l[2]=1; l[1]=0; l[0]=1;
414 l[2]=1; l[1]=1; l[0]=0;
416 l[2]=0; l[1]=0; l[0]=0;
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;
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;
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;
447 VALUE v011001 = f(l);
448 l[3]=0; l[2]=0; l[1]=0; l[0]=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;
461 VALUE v101010 = f(l);
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;}
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;}
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;}
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;}
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;}
498 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
501 const FunctionType& f = *
static_cast<FunctionType
const *
>(
this);
502 if(f.dimension()==1){
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");
508 LABEL l00[] = {0, 0};
509 LABEL l01[] = {0, 1};
510 LABEL l10[] = {1, 0};
511 LABEL l11[] = {1, 1};
513 return f(l00)+f(l11)<= f(l10)+f(l01);
516 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
523 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
524 inline MinMaxFunctor<VALUE>
526 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
528 const VALUE tmp=f(c.begin());
529 MinMaxFunctor<VALUE> minMax(tmp, tmp);
530 static_cast<FunctionType
const *
>(
this)->forAtLeastAllUniqueValues(minMax);
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);
539 AccumulationFunctor<Minimizer, VALUE> accumulator(f(c.begin()));
540 static_cast<FunctionType
const *
>(
this)->forAtLeastAllUniqueValues(accumulator);
541 return accumulator.value();
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);
549 AccumulationFunctor<Maximizer, VALUE> accumulator(f(c.begin()));
550 static_cast<FunctionType
const *
>(
this)->forAtLeastAllUniqueValues(accumulator);
551 return accumulator.value();
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();
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();
570 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
572 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
574 if(meta::Compare<ACC, Minimizer>::value ) {
575 return static_cast<FunctionType
const *
>(
this)->min();
577 else if( meta::Compare<ACC, Maximizer>::value ) {
578 return static_cast<FunctionType
const *
>(
this)->max();
580 else if( meta::Compare<ACC, Adder>::value ) {
581 return static_cast<FunctionType
const *
>(
this)->sum();
583 else if( meta::Compare<ACC, Integrator>::value ) {
584 return static_cast<FunctionType
const *
>(
this)->sum();
586 else if( meta::Compare<ACC, Multiplier>::value ) {
587 return static_cast<FunctionType
const *
>(
this)->product();
590 AccumulationFunctor<ACC, VALUE> accumulator;
591 static_cast<FunctionType
const *
>(
this)->forAllValuesInOrder(accumulator);
592 return accumulator.value();
598 #endif // OPENGM_FUNCTION_PROPERTIES_BASE_HXX
void forAtLeastAllUniqueValuesWithCoordinate(COORDINATE_FUNCTOR &functor) const
bool operator==(const FUNCTION &) const
bool isTruncatedAbsoluteDifference() const
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)
bool isTruncatedSquaredDifference() const
bool isSquaredDifference() const
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
size_t numberOfParameters() const
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)
ReturnType product() const
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
bool isAbsoluteDifference() const
bool isGeneralizedPotts() const
bool isSubmodular() const
FunctionShapeIteratorType functionShapeEnd() const
bool isLinearConstraint() 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