function_properties_base.hxx

Go to the documentation of this file.
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    // compare dimension
00141    if(dimA==fb.dimension()) {
00142       // compare shape
00143       for(size_t i=0;i<dimA;++i) {
00144          if(fa.shape(i)!=fb.shape(i)) {
00145             return false;
00146          }
00147       }
00148       // compare all values
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       //get possible weight
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       //get possible weight
00289       VALUE weight=f(c);
00290       //get possible truncation (compute the biggest possible distance => value is the truncation value)
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       //get possible weight
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       //get possible weight
00338       VALUE weight=f(c);
00339       //get possible truncation (compute the biggest possible distance => value is the truncation value)
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       // all labels are equal
00368       if(isEqualValueVector(shapeWalker.coordinateTuple()) ) {
00369          if(vEqual!=f(shapeWalker.coordinateTuple().begin()))
00370             return false;
00371       }
00372       // all labels are not equal
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; //3-1
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; //3-1
00437       VALUE v011001 = f(l);
00438       l[3]=0; l[2]=0; l[1]=0; l[0]=1; //3-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; //3-1
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 } // namespace opengm
00580 
00581 #endif // OPENGM_FUNCTION_PROPERTIES_BASE_HXX
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:02 2013 for OpenGM by  doxygen 1.6.3