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;
62 MinMaxFunctor<VALUE>
minMax()
const;
64 ReturnType
min()
const;
65 ReturnType
max()
const;
66 ReturnType
sum()
const;
93 template<
class FUNCTOR>
96 template<
class FUNCTOR>
102 template<
class FUNCTOR>
108 template<
class FUNCTOR>
112 template<
class COORDINATE_FUNCTOR>
114 template<
class COORDINATE_FUNCTOR>
116 template<
class COORDINATE_FUNCTOR>
122 typedef FUNCTION FunctionType;
123 typedef FunctionShapeAccessor<FunctionType> FunctionShapeAccessorType;
135 throw RuntimeError(
"Function base has no parameters,this needs to be implemented in any function type");
138 template<
class ITERATOR>
146 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
155 if(dimA==fb.dimension()) {
157 for(
size_t i=0;i<dimA;++i) {
158 if(fa.
shape(i)!=fb.shape(i)) {
164 for(INDEX i=0;i<fa.
size();++i, ++shapeWalker) {
165 if(
isNumericEqual(fa(shapeWalker.coordinateTuple().begin()), fb(shapeWalker.coordinateTuple().begin()))==
false) {
176 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
177 template<
class COORDINATE_FUNCTOR>
181 COORDINATE_FUNCTOR& functor
185 for(INDEX i=0;i<f.
size();++i, ++shapeWalker) {
186 functor(f(shapeWalker.coordinateTuple().begin()),shapeWalker.coordinateTuple().begin());
190 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
191 template<
class COORDINATE_FUNCTOR>
195 COORDINATE_FUNCTOR& functor
200 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
201 template<
class COORDINATE_FUNCTOR>
205 COORDINATE_FUNCTOR& functor
211 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
212 template<
class FUNCTOR>
220 for(INDEX i=0;i<f.
size();++i, ++shapeWalker) {
221 functor(f(shapeWalker.coordinateTuple().begin()));
225 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
226 template<
class FUNCTOR>
234 for(INDEX i=0;i<f.
size();++i, ++shapeWalker) {
235 functor(f(shapeWalker.coordinateTuple().begin()));
239 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
240 template<
class FUNCTOR>
249 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
250 template<
class FUNCTOR>
259 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
266 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
273 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
282 for( c[1]=0;c[1]<f.
shape(1);++c[1]) {
283 for( c[0]=0;c[0]<f.
shape(0);++c[0]) {
284 VALUE d=
static_cast<VALUE
> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
295 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
305 c[0]=f.
shape(0)-
static_cast<LABEL
>(1);
306 VALUE truncated=f(c);
307 for( c[1]=0;c[1]<f.
shape(1);++c[1]) {
308 for( c[0]=0;c[0]<f.
shape(0);++c[0]) {
309 VALUE d=
static_cast<VALUE
> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
311 const VALUE fval=f(c);
312 const VALUE compare=d*weight;
323 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
332 for( c[1]=0;c[1]<f.
shape(1);++c[1]) {
333 for( c[0]=0;c[0]<f.
shape(0);++c[0]) {
334 VALUE d=
static_cast<VALUE
> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
344 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
354 c[0]=f.
shape(0)-
static_cast<LABEL
>(1);
355 VALUE truncated=f(c);
356 for( c[1]=0;c[1]<f.
shape(1);++c[1]) {
357 for( c[0]=0;c[0]<f.
shape(0);++c[0]) {
358 VALUE d=
static_cast<VALUE
> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
359 const VALUE fval=f(c);
360 const VALUE compare=d*weight;
371 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
375 if (f.
size()<=2)
return true;
377 VALUE vEqual=f(shapeWalker.coordinateTuple().begin());
379 VALUE vNotEqual=f(shapeWalker.coordinateTuple().begin());
381 for(INDEX i=2;i<f.
size();++i, ++shapeWalker) {
383 if(isEqualValueVector(shapeWalker.coordinateTuple()) ) {
384 if(vEqual!=f(shapeWalker.coordinateTuple().begin()))
389 if(vNotEqual!=f(shapeWalker.coordinateTuple().begin()))
396 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
405 for(l[0]=0;l[0]<f.
shape(0);++l[0]) {
406 for(l[1]=0;l[1]<f.
shape(1);++l[1]) {
407 if((l[0]==l[1] && f(l)!=v1) || ((l[0]!=l[1] && f(l)!=v0)) )
return false;
413 LABEL l[] = {0, 1, 2};
415 l[2]=0; l[1]=1; l[0]=1;
417 l[2]=1; l[1]=0; l[0]=1;
419 l[2]=1; l[1]=1; l[0]=0;
421 l[2]=0; l[1]=0; l[0]=0;
423 for(l[0]=0;l[0]<f.
shape(0);++l[0]) {
424 for(l[1]=0;l[1]<f.
shape(1);++l[1]) {
425 for(l[2]=0;l[2]<f.
shape(2);++l[2]) {
426 if((l[1]!=l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v000) )
return false;
427 if((l[1]!=l[2] && l[0]!=l[2] && l[0]==l[1] && f(l)!=v001) )
return false;
428 if((l[1]!=l[2] && l[0]==l[2] && l[0]!=l[1] && f(l)!=v010) )
return false;
429 if((l[1]==l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v100) )
return false;
430 if((l[1]==l[2] && l[0]==l[2] && l[0]==l[1] && f(l)!=v111) )
return false;
437 LABEL l[] = {0, 1, 2, 3};
438 VALUE v000000 = f(l);
439 l[3]=2; l[2]=1; l[1]=0;l[0]=0;
440 VALUE v000001 = f(l);
441 l[3]=2; l[2]=0; l[1]=1;l[0]=0;
442 VALUE v000010 = f(l);
443 l[3]=2; l[2]=0; l[1]=0;l[0]=1;
444 VALUE v000100 = f(l);
445 l[3]=1; l[2]=0; l[1]=0;l[0]=0;
446 VALUE v000111 = f(l);
447 l[3]=0; l[2]=1; l[1]=2; l[0]=0;
448 VALUE v001000 = f(l);
449 l[3]=0; l[2]=1; l[1]=1; l[0]=0;
450 VALUE v001100 = f(l);
451 l[3]=0; l[2]=1; l[1]=0; l[0]=0;
452 VALUE v011001 = f(l);
453 l[3]=0; l[2]=0; l[1]=0; l[0]=1;
454 VALUE v110100 = f(l);
455 l[3]=0; l[2]=0; l[1]=0; l[0]=0;
456 VALUE v111111 = f(l);
457 l[3]=1; l[2]=1; l[1]=0; l[0]=0;
458 VALUE v100001 = f(l);
459 l[3]=1; l[2]=0; l[1]=1; l[0]=0;
460 VALUE v010010 = f(l);
461 l[3]=0; l[2]=0; l[1]=1; l[0]=2;
462 VALUE v100000 = f(l);
463 l[3]=0; l[2]=1; l[1]=0; l[0]=2;
464 VALUE v010000 = f(l);
465 l[3]=0; l[2]=0; l[1]=1; l[0]=0;
466 VALUE v101010 = f(l);
469 for(l[0]=0;l[0]<f.
shape(0);++l[0]) {
470 for(l[1]=0;l[1]<f.
shape(1);++l[1]) {
471 for(l[2]=0;l[2]<f.
shape(2);++l[2]) {
472 for(l[3]=0;l[3]<f.
shape(3);++l[3]) {
473 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;}
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)!=v000001) ) {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)!=v000010) ) {std::cout<<
"1";
return false;}
476 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;}
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)!=v000111) ) {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)!=v001000) ) {std::cout<<
"1";
return false;}
480 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;}
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)!=v010010) ) {std::cout<<
"1";
return false;}
483 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;}
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)!=v011001) ) {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)!=v110100) ) {std::cout<<
"1";
return false;}
487 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;}
489 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;}
490 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;}
491 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;}
503 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
511 throw RuntimeError(
"Fallback FunctionBase::isSubmodular only defined for binary functions with order less than 3");
513 LABEL l00[] = {0, 0};
514 LABEL l01[] = {0, 1};
515 LABEL l10[] = {1, 0};
516 LABEL l11[] = {1, 1};
518 return f(l00)+f(l11)<= f(l10)+f(l01);
521 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
528 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
529 inline MinMaxFunctor<VALUE>
533 const VALUE tmp=f(c.begin());
534 MinMaxFunctor<VALUE>
minMax(tmp, tmp);
539 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
540 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
544 AccumulationFunctor<Minimizer, VALUE> accumulator(f(c.begin()));
546 return accumulator.value();
549 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
550 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
554 AccumulationFunctor<Maximizer, VALUE> accumulator(f(c.begin()));
556 return accumulator.value();
559 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
560 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
562 AccumulationFunctor<Integrator, VALUE> accumulator(static_cast<VALUE>(0));
564 return accumulator.value();
567 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
568 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
570 AccumulationFunctor<Multiplier, VALUE> accumulator(static_cast<VALUE>(1));;
572 return accumulator.value();
575 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
577 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
579 if(meta::Compare<ACC, Minimizer>::value ) {
582 else if( meta::Compare<ACC, Maximizer>::value ) {
585 else if( meta::Compare<ACC, Adder>::value ) {
588 else if( meta::Compare<ACC, Integrator>::value ) {
591 else if( meta::Compare<ACC, Multiplier>::value ) {
595 AccumulationFunctor<ACC, VALUE> accumulator;
597 return accumulator.value();
603 #endif // OPENGM_FUNCTION_PROPERTIES_BASE_HXX
void forAtLeastAllUniqueValuesWithCoordinate(COORDINATE_FUNCTOR &functor) const
void forAllValuesInAnyOrder(FUNCTOR &functor) const
call a functor for each value of the function (in un-specified order)
void setWeights(const opengm::learning::Weights< VALUE > &) const
FunctionShapeIteratorType functionShapeEnd() const
ReturnType product() const
Fallback implementation of member functions of OpenGM functions.
bool isNumericEqual(const T a, const T b)
bool isSquaredDifference() const
ReturnType accumulate() const
accumulate all values of the function
VALUE weightGradient(size_t, ITERATOR) const
AccessorIterator< FunctionShapeAccessorType, true > FunctionShapeIteratorType
bool isGeneralizedPotts() const
bool operator==(const FUNCTION &) const
void forAllValuesInOrderWithCoordinate(COORDINATE_FUNCTOR &functor) const
Vector that stores values on the stack if size is smaller than MAX_STACK.
#define OPENGM_ASSERT(expression)
bool isAbsoluteDifference() const
bool isLinearConstraint() const
bool isTruncatedSquaredDifference() const
void forAllValuesInSwitchedOrder(FUNCTOR &functor) const
void forAllValuesInAnyOrderWithCoordinate(COORDINATE_FUNCTOR &functor) const
INDEX weightIndex(const size_t weightNumber) const
bool isTruncatedAbsoluteDifference() const
bool isSubmodular() const
size_t size() const
number of entries a value table encoding this function would have (used for I/O)
size_t numberOfWeights() const
MinMaxFunctor< VALUE > minMax() const
find minimum and maximum of the function in a single sweep
truncated squared difference of the labels of two variables
void forAtLeastAllUniqueValues(FUNCTOR &functor) const
call a functor for at least all unique values of the function
FunctionShapeIteratorType functionShapeBegin() const
void forAllValuesInOrder(FUNCTOR &functor) const
call a functor for each value of the function (in lexicographical order of the variable indices) ...
size_t shape(const IndexType) const
extension a value table encoding this function would have