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>
152 const FunctionType& fa=*
static_cast<FunctionType
const *
>(
this);
153 const size_t dimA=fa.dimension();
155 if(dimA==fb.dimension()) {
157 for(
size_t i=0;i<dimA;++i) {
158 if(fa.shape(i)!=fb.shape(i)) {
163 ShapeWalker<FunctionShapeIteratorType> shapeWalker(fa.functionShapeBegin(), dimA);
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
183 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
184 ShapeWalker<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
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>
218 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
219 ShapeWalker<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
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>
232 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
233 ShapeWalkerSwitchedOrder<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
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>
262 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
266 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
269 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
273 template<
class FUNCTION,
class VALUE,
class INDEX,
class LABEL>
276 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
277 if(f.dimension()==2) {
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>
298 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
299 if(f.dimension()==2) {
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>
326 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
327 if(f.dimension()==2) {
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>
347 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
348 if(f.dimension()==2) {
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>
374 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
375 if (f.size()<=2)
return true;
376 ShapeWalker<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
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>
399 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
400 if(f.dimension()==2) {
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;
412 else if(f.dimension()==3) {
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;
436 else if(f.dimension()==4) {
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>
506 const FunctionType& f = *
static_cast<FunctionType
const *
>(
this);
507 if(f.dimension()==1){
510 if(f.dimension()!=2 ||f.shape(0)!=2 || f.shape(1)!=2) {
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>
531 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
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
542 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
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
552 const FunctionType& f=*
static_cast<FunctionType
const *
>(
this);
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 ) {
580 return static_cast<FunctionType
const *
>(
this)->
min();
582 else if( meta::Compare<ACC, Maximizer>::value ) {
583 return static_cast<FunctionType
const *
>(
this)->
max();
585 else if( meta::Compare<ACC, Adder>::value ) {
586 return static_cast<FunctionType
const *
>(
this)->
sum();
588 else if( meta::Compare<ACC, Integrator>::value ) {
589 return static_cast<FunctionType
const *
>(
this)->
sum();
591 else if( meta::Compare<ACC, Multiplier>::value ) {
592 return static_cast<FunctionType
const *
>(
this)->
product();
595 AccumulationFunctor<ACC, VALUE> accumulator;
597 return accumulator.value();
603 #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
bool isNumericEqual(const T a, const T b)
bool isTruncatedSquaredDifference() const
INDEX weightIndex(const size_t weightNumber) const
bool isSquaredDifference() const
void setWeights(const opengm::learning::Weights< VALUE > &) 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
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
size_t numberOfWeights() 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)
VALUE weightGradient(size_t, ITERATOR) const
void forAllValuesInAnyOrderWithCoordinate(COORDINATE_FUNCTOR &functor) const