00001 #pragma once
00002 #ifndef OPENGM_FUNCTION_PROPERTIES_BASE_HXX
00003 #define OPENGM_FUNCTION_PROPERTIES_BASE_HXX
00004
00005 #include <cmath>
00006
00007 #include "opengm/opengm.hxx"
00008 #include "opengm/utilities/shape_accessor.hxx"
00009 #include "opengm/utilities/accessor_iterator.hxx"
00010 #include "opengm/utilities/accumulation.hxx"
00011 #include "opengm/utilities/indexing.hxx"
00012 #include "opengm/utilities/functors.hxx"
00013 #include "opengm/operations/adder.hxx"
00014 #include "opengm/operations/and.hxx"
00015 #include "opengm/operations/or.hxx"
00016 #include "opengm/operations/minimizer.hxx"
00017 #include "opengm/operations/maximizer.hxx"
00018 #include "opengm/operations/adder.hxx"
00019 #include "opengm/operations/integrator.hxx"
00020 #include "opengm/operations/multiplier.hxx"
00021
00022 #define OPENGM_FLOAT_TOL 0.000001
00023
00024 namespace opengm {
00025
00026 template<class T>
00027 inline bool isNumericEqual(const T a, const T b) {
00028 if(meta::IsFloatingPoint<T>::value) {
00029 if(a < b) {
00030 return b-a<OPENGM_FLOAT_TOL ? true : false;
00031 }
00032 else {
00033 return a - b < OPENGM_FLOAT_TOL ? true : false;
00034 }
00035 }
00036 else {
00037 return a == b;
00038 }
00039 }
00040
00042 template<class FUNCTION, class VALUE, class INDEX = size_t, class LABEL = size_t>
00043 class FunctionBase {
00044 private:
00045 typedef VALUE ReturnType;
00046 typedef const VALUE& ReturnReferenceType;
00047
00048 public:
00049 bool isPotts() const;
00050 bool isGeneralizedPotts() const;
00051 bool isSubmodular() const;
00052 bool isSquaredDifference() const;
00053 bool isTruncatedSquaredDifference() const;
00054 bool isAbsoluteDifference() const;
00055 bool isTruncatedAbsoluteDifference() const;
00056
00059 MinMaxFunctor<VALUE> minMax() const;
00060
00061 ReturnType min() const;
00062 ReturnType max() const;
00063 ReturnType sum() const;
00064 ReturnType product() const;
00065
00069 template<class ACC>
00070 ReturnType accumulate() const;
00071
00090 template<class FUNCTOR>
00091 void forAllValuesInOrder(FUNCTOR& functor) const;
00092
00093 template<class FUNCTOR>
00094 void forAllValuesInSwitchedOrder(FUNCTOR& functor) const;
00095
00099 template<class FUNCTOR>
00100 void forAllValuesInAnyOrder(FUNCTOR& functor) const;
00101
00105 template<class FUNCTOR>
00106 void forAtLeastAllUniqueValues(FUNCTOR& functor) const ;
00107
00108
00109 template<class COORDINATE_FUNCTOR>
00110 void forAllValuesInOrderWithCoordinate(COORDINATE_FUNCTOR& functor) const;
00111 template<class COORDINATE_FUNCTOR>
00112 void forAllValuesInAnyOrderWithCoordinate(COORDINATE_FUNCTOR& functor) const;
00113 template<class COORDINATE_FUNCTOR>
00114 void forAtLeastAllUniqueValuesWithCoordinate(COORDINATE_FUNCTOR& functor) const ;
00115
00116 bool operator==(const FUNCTION&) const;
00117
00118 private:
00119 typedef FUNCTION FunctionType;
00120 typedef FunctionShapeAccessor<FunctionType> FunctionShapeAccessorType;
00121
00122 public:
00123 typedef AccessorIterator<FunctionShapeAccessorType, true> FunctionShapeIteratorType;
00124
00125 FunctionShapeIteratorType functionShapeBegin() const;
00126 FunctionShapeIteratorType functionShapeEnd() const;
00127 };
00128
00129
00130
00131
00132 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00133 inline bool
00134 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::operator==
00135 (
00136 const FUNCTION& fb
00137 ) const{
00138 const FunctionType& fa=*static_cast<FunctionType const *>(this);
00139 const size_t dimA=fa.dimension();
00140
00141 if(dimA==fb.dimension()) {
00142
00143 for(size_t i=0;i<dimA;++i) {
00144 if(fa.shape(i)!=fb.shape(i)) {
00145 return false;
00146 }
00147 }
00148
00149 ShapeWalker<FunctionShapeIteratorType> shapeWalker(fa.functionShapeBegin(), dimA);
00150 for(INDEX i=0;i<fa.size();++i, ++shapeWalker) {
00151 if(isNumericEqual(fa(shapeWalker.coordinateTuple().begin()), fb(shapeWalker.coordinateTuple().begin()))==false) {
00152 return false;
00153 }
00154 }
00155 }
00156 else{
00157 return false;
00158 }
00159 return true;
00160 }
00161
00162 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00163 template<class COORDINATE_FUNCTOR>
00164 inline void
00165 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::forAllValuesInOrderWithCoordinate
00166 (
00167 COORDINATE_FUNCTOR& functor
00168 ) const {
00169 const FunctionType& f=*static_cast<FunctionType const *>(this);
00170 ShapeWalker<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
00171 for(INDEX i=0;i<f.size();++i, ++shapeWalker) {
00172 functor(f(shapeWalker.coordinateTuple().begin()),shapeWalker.coordinateTuple().begin());
00173 }
00174 }
00175
00176 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00177 template<class COORDINATE_FUNCTOR>
00178 inline void
00179 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::forAllValuesInAnyOrderWithCoordinate
00180 (
00181 COORDINATE_FUNCTOR& functor
00182 ) const{
00183 this->forAllValuesInOrderWithCoordinate(functor);
00184 }
00185
00186 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00187 template<class COORDINATE_FUNCTOR>
00188 inline void
00189 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::forAtLeastAllUniqueValuesWithCoordinate
00190 (
00191 COORDINATE_FUNCTOR& functor
00192 ) const {
00193 this->forAllValuesInAnyOrderWithCoordinate(functor);
00194 }
00195
00196
00197 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00198 template<class FUNCTOR>
00199 inline void
00200 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::forAllValuesInOrder
00201 (
00202 FUNCTOR& functor
00203 ) const {
00204 const FunctionType& f=*static_cast<FunctionType const *>(this);
00205 ShapeWalker<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
00206 for(INDEX i=0;i<f.size();++i, ++shapeWalker) {
00207 functor(f(shapeWalker.coordinateTuple().begin()));
00208 }
00209 }
00210
00211 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00212 template<class FUNCTOR>
00213 inline void
00214 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::forAllValuesInSwitchedOrder
00215 (
00216 FUNCTOR& functor
00217 ) const {
00218 const FunctionType& f=*static_cast<FunctionType const *>(this);
00219 ShapeWalkerSwitchedOrder<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
00220 for(INDEX i=0;i<f.size();++i, ++shapeWalker) {
00221 functor(f(shapeWalker.coordinateTuple().begin()));
00222 }
00223 }
00224
00225 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00226 template<class FUNCTOR>
00227 inline void
00228 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::forAllValuesInAnyOrder
00229 (
00230 FUNCTOR& functor
00231 ) const {
00232 static_cast<FunctionType const *>(this)->forAllValuesInOrder(functor);
00233 }
00234
00235 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00236 template<class FUNCTOR>
00237 inline void
00238 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::forAtLeastAllUniqueValues
00239 (
00240 FUNCTOR& functor
00241 ) const {
00242 static_cast<FunctionType const *>(this)->forAllValuesInAnyOrder(functor);
00243 }
00244
00245 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00246 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::FunctionShapeIteratorType
00247 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::functionShapeBegin() const {
00248 const FunctionType& f=*static_cast<FunctionType const *>(this);
00249 return FunctionShapeIteratorType(FunctionShapeAccessorType(f), 0);
00250 }
00251
00252 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00253 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::FunctionShapeIteratorType
00254 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::functionShapeEnd() const {
00255 const FunctionType& f=*static_cast<FunctionType const *>(this);
00256 return FunctionShapeIteratorType(FunctionShapeAccessorType(f), f.dimension());
00257 }
00258
00259 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00260 inline bool
00261 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::isSquaredDifference() const{
00262 const FunctionType& f=*static_cast<FunctionType const *>(this);
00263 if(f.dimension()==2) {
00264 OPENGM_ASSERT(f.shape(0)>static_cast<LABEL>(1));
00265 LABEL c[2]={1, 0};
00266
00267 VALUE weight=f(c);
00268 for( c[1]=0;c[1]<f.shape(1);++c[1]) {
00269 for( c[0]=0;c[0]<f.shape(0);++c[0]) {
00270 VALUE d= static_cast<VALUE> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
00271 d*=d;
00272 if( isNumericEqual(f(c), d*weight )==false)
00273 return false;
00274 }
00275 }
00276 return true;
00277 }
00278 return false;
00279 }
00280
00281 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00282 inline bool
00283 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::isTruncatedSquaredDifference() const{
00284 const FunctionType& f=*static_cast<FunctionType const *>(this);
00285 if(f.dimension()==2) {
00286 OPENGM_ASSERT(f.shape(0)>static_cast<LABEL>(1));
00287 LABEL c[2]={1, 0};
00288
00289 VALUE weight=f(c);
00290
00291 c[0]=f.shape(0)-static_cast<LABEL>(1);
00292 VALUE truncated=f(c);
00293 for( c[1]=0;c[1]<f.shape(1);++c[1]) {
00294 for( c[0]=0;c[0]<f.shape(0);++c[0]) {
00295 VALUE d= static_cast<VALUE> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
00296 d*=d;
00297 const VALUE fval=f(c);
00298 const VALUE compare=d*weight;
00299 if( isNumericEqual(fval, compare )==false && ((isNumericEqual(fval, truncated) && truncated<compare)==false)) {
00300 return false;
00301 }
00302 }
00303 }
00304 return true;
00305 }
00306 return false;
00307 }
00308
00309 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00310 inline bool
00311 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::isAbsoluteDifference() const{
00312 const FunctionType& f=*static_cast<FunctionType const *>(this);
00313 if(f.dimension()==2) {
00314 OPENGM_ASSERT(f.shape(0)>static_cast<LABEL>(1));
00315 LABEL c[2]={1, 0};
00316
00317 VALUE weight=f(c);
00318 for( c[1]=0;c[1]<f.shape(1);++c[1]) {
00319 for( c[0]=0;c[0]<f.shape(0);++c[0]) {
00320 VALUE d= static_cast<VALUE> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
00321 if( isNumericEqual(f(c), d*weight )==false)
00322 return false;
00323 }
00324 }
00325 return true;
00326 }
00327 return false;
00328 }
00329
00330 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00331 inline bool
00332 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::isTruncatedAbsoluteDifference() const{
00333 const FunctionType& f=*static_cast<FunctionType const *>(this);
00334 if(f.dimension()==2) {
00335 OPENGM_ASSERT(f.shape(0)>static_cast<LABEL>(1));
00336 LABEL c[2]={1, 0};
00337
00338 VALUE weight=f(c);
00339
00340 c[0]=f.shape(0)-static_cast<LABEL>(1);
00341 VALUE truncated=f(c);
00342 for( c[1]=0;c[1]<f.shape(1);++c[1]) {
00343 for( c[0]=0;c[0]<f.shape(0);++c[0]) {
00344 VALUE d= static_cast<VALUE> (c[0]<c[1] ? c[1]-c[0]:c[0]-c[1]);
00345 const VALUE fval=f(c);
00346 const VALUE compare=d*weight;
00347 if( isNumericEqual(fval, compare )==false && ((isNumericEqual(fval, truncated) && truncated<compare)==false)) {
00348 return false;
00349 }
00350 }
00351 }
00352 return true;
00353 }
00354 return false;
00355 }
00356
00357 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00358 inline bool
00359 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::isPotts() const {
00360 const FunctionType& f=*static_cast<FunctionType const *>(this);
00361 ShapeWalker<FunctionShapeIteratorType> shapeWalker(f.functionShapeBegin(), f.dimension());
00362 VALUE vEqual=f(shapeWalker.coordinateTuple().begin());
00363 ++shapeWalker;
00364 VALUE vNotEqual=f(shapeWalker.coordinateTuple().begin());
00365 ++shapeWalker;
00366 for(INDEX i=2;i<f.size();++i, ++shapeWalker) {
00367
00368 if(isEqualValueVector(shapeWalker.coordinateTuple()) ) {
00369 if(vEqual!=f(shapeWalker.coordinateTuple().begin()))
00370 return false;
00371 }
00372
00373 else{
00374 if(vNotEqual!=f(shapeWalker.coordinateTuple().begin()))
00375 return false;
00376 }
00377 }
00378 return true;
00379 }
00380
00381 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00382 inline bool
00383 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::isGeneralizedPotts() const {
00384 const FunctionType& f=*static_cast<FunctionType const *>(this);
00385 if(f.dimension()==2) {
00386 LABEL l[] = {0, 1};
00387 VALUE v0 = f(l);
00388 l[1]=0;
00389 VALUE v1 = f(l);
00390 for(l[0]=0;l[0]<f.shape(0);++l[0]) {
00391 for(l[1]=0;l[1]<f.shape(1);++l[1]) {
00392 if((l[0]==l[1] && f(l)!=v1) || ((l[0]!=l[1] && f(l)!=v0)) ) return false;
00393 }
00394 }
00395 return true;
00396 }
00397 else if(f.dimension()==3) {
00398 LABEL l[] = {0, 1, 2};
00399 VALUE v000 = f(l);
00400 l[2]=0; l[1]=1; l[0]=1;
00401 VALUE v001 = f(l);
00402 l[2]=1; l[1]=0; l[0]=1;
00403 VALUE v010 = f(l);
00404 l[2]=1; l[1]=1; l[0]=0;
00405 VALUE v100 = f(l);
00406 l[2]=0; l[1]=0; l[0]=0;
00407 VALUE v111 = f(l);
00408 for(l[0]=0;l[0]<f.shape(0);++l[0]) {
00409 for(l[1]=0;l[1]<f.shape(1);++l[1]) {
00410 for(l[2]=0;l[2]<f.shape(2);++l[2]) {
00411 if((l[1]!=l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v000) ) return false;
00412 if((l[1]!=l[2] && l[0]!=l[2] && l[0]==l[1] && f(l)!=v001) ) return false;
00413 if((l[1]!=l[2] && l[0]==l[2] && l[0]!=l[1] && f(l)!=v010) ) return false;
00414 if((l[1]==l[2] && l[0]!=l[2] && l[0]!=l[1] && f(l)!=v100) ) return false;
00415 if((l[1]==l[2] && l[0]==l[2] && l[0]==l[1] && f(l)!=v111) ) return false;
00416 }
00417 }
00418 }
00419 return true;
00420 }
00421 else if(f.dimension()==4) {
00422 LABEL l[] = {0, 1, 2, 3};
00423 VALUE v000000 = f(l);
00424 l[3]=2; l[2]=1; l[1]=0;l[0]=0;
00425 VALUE v000001 = f(l);
00426 l[3]=2; l[2]=0; l[1]=1;l[0]=0;
00427 VALUE v000010 = f(l);
00428 l[3]=2; l[2]=0; l[1]=0;l[0]=1;
00429 VALUE v000100 = f(l);
00430 l[3]=1; l[2]=0; l[1]=0;l[0]=0;
00431 VALUE v000111 = f(l);
00432 l[3]=0; l[2]=1; l[1]=2; l[0]=0;
00433 VALUE v001000 = f(l);
00434 l[3]=0; l[2]=1; l[1]=1; l[0]=0;
00435 VALUE v001100 = f(l);
00436 l[3]=0; l[2]=1; l[1]=0; l[0]=0;
00437 VALUE v011001 = f(l);
00438 l[3]=0; l[2]=0; l[1]=0; l[0]=1;
00439 VALUE v110100 = f(l);
00440 l[3]=0; l[2]=0; l[1]=0; l[0]=0;
00441 VALUE v111111 = f(l);
00442 l[3]=1; l[2]=1; l[1]=0; l[0]=0;
00443 VALUE v100001 = f(l);
00444 l[3]=1; l[2]=0; l[1]=1; l[0]=0;
00445 VALUE v010010 = f(l);
00446 l[3]=0; l[2]=0; l[1]=1; l[0]=2;
00447 VALUE v100000 = f(l);
00448 l[3]=0; l[2]=1; l[1]=0; l[0]=2;
00449 VALUE v010000 = f(l);
00450 l[3]=0; l[2]=0; l[1]=1; l[0]=0;
00451 VALUE v101010 = f(l);
00452
00453
00454 for(l[0]=0;l[0]<f.shape(0);++l[0]) {
00455 for(l[1]=0;l[1]<f.shape(1);++l[1]) {
00456 for(l[2]=0;l[2]<f.shape(2);++l[2]) {
00457 for(l[3]=0;l[3]<f.shape(3);++l[3]) {
00458 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;}
00459 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;}
00460 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;}
00461 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;}
00462 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;}
00463
00464 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;}
00465 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;}
00466
00467 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;}
00468 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;}
00469 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;}
00470
00471 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;}
00472 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;}
00473
00474 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;}
00475 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;}
00476 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;}
00477 }
00478 }
00479 }
00480 }
00481 return true;
00482 }
00483 else{
00484 return false;
00485 }
00486 }
00487
00488 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00489 inline bool
00490 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::isSubmodular() const {
00491 const FunctionType& f = *static_cast<FunctionType const *>(this);
00492 if(f.dimension()==1){
00493 return true;
00494 }
00495 if(f.dimension()!=2 ||f.shape(0)!=2 || f.shape(1)!=2) {
00496 throw RuntimeError("Fallback FunctionBase::isSubmodular only defined for binary functions with order less than 3");
00497 }
00498 LABEL l00[] = {0, 0};
00499 LABEL l01[] = {0, 1};
00500 LABEL l10[] = {1, 0};
00501 LABEL l11[] = {1, 1};
00502
00503 return f(l00)+f(l11)<= f(l10)+f(l01);
00504 }
00505
00506 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00507 inline MinMaxFunctor<VALUE>
00508 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::minMax() const {
00509 const FunctionType& f=*static_cast<FunctionType const *>(this);
00510 opengm::FastSequence<INDEX> c(f.dimension(), 0);
00511 const VALUE tmp=f(c.begin());
00512 MinMaxFunctor<VALUE> minMax(tmp, tmp);
00513 static_cast<FunctionType const *>(this)->forAtLeastAllUniqueValues(minMax);
00514 return minMax;
00515 }
00516
00517 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00518 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
00519 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::min() const {
00520 const FunctionType& f=*static_cast<FunctionType const *>(this);
00521 opengm::FastSequence<INDEX> c(f.dimension(), 0);
00522 AccumulationFunctor<Minimizer, VALUE> accumulator(f(c.begin()));
00523 static_cast<FunctionType const *>(this)->forAtLeastAllUniqueValues(accumulator);
00524 return accumulator.value();
00525 }
00526
00527 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00528 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
00529 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::max() const {
00530 const FunctionType& f=*static_cast<FunctionType const *>(this);
00531 opengm::FastSequence<INDEX> c(f.dimension(), 0);
00532 AccumulationFunctor<Maximizer, VALUE> accumulator(f(c.begin()));
00533 static_cast<FunctionType const *>(this)->forAtLeastAllUniqueValues(accumulator);
00534 return accumulator.value();
00535 }
00536
00537 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00538 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
00539 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::sum() const {
00540 AccumulationFunctor<Integrator, VALUE> accumulator(static_cast<VALUE>(0));
00541 static_cast<FunctionType const *>(this)->forAllValuesInAnyOrder(accumulator);
00542 return accumulator.value();
00543 }
00544
00545 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00546 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
00547 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::product() const {
00548 AccumulationFunctor<Multiplier, VALUE> accumulator(static_cast<VALUE>(1));;
00549 static_cast<FunctionType const *>(this)->forAllValuesInAnyOrder(accumulator);
00550 return accumulator.value();
00551 }
00552
00553 template<class FUNCTION, class VALUE, class INDEX, class LABEL>
00554 template<class ACC>
00555 inline typename FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::ReturnType
00556 FunctionBase<FUNCTION, VALUE, INDEX, LABEL>::accumulate() const {
00557 if(meta::Compare<ACC, Minimizer>::value ) {
00558 return static_cast<FunctionType const *>(this)->min();
00559 }
00560 else if( meta::Compare<ACC, Maximizer>::value ) {
00561 return static_cast<FunctionType const *>(this)->max();
00562 }
00563 else if( meta::Compare<ACC, Adder>::value ) {
00564 return static_cast<FunctionType const *>(this)->sum();
00565 }
00566 else if( meta::Compare<ACC, Integrator>::value ) {
00567 return static_cast<FunctionType const *>(this)->sum();
00568 }
00569 else if( meta::Compare<ACC, Multiplier>::value ) {
00570 return static_cast<FunctionType const *>(this)->product();
00571 }
00572 else{
00573 AccumulationFunctor<ACC, VALUE> accumulator;
00574 static_cast<FunctionType const *>(this)->forAllValuesInOrder(accumulator);
00575 return accumulator.value();
00576 }
00577 }
00578
00579 }
00580
00581 #endif // OPENGM_FUNCTION_PROPERTIES_BASE_HXX