dualdecomposition_base.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef OPENGM_DUALDECOMPOSITION_BASE_HXX
00003 #define OPENGM_DUALDECOMPOSITION_BASE_HXX
00004 
00005 #include <vector>
00006 #include <string>
00007 #include <iostream>
00008 #include <cmath>
00009 #include <limits>
00010 
00011 #include "opengm/opengm.hxx"
00012 #include "opengm/graphicalmodel/decomposition/graphicalmodeldecomposition.hxx"
00013 #include "opengm/graphicalmodel/decomposition/graphicalmodeldecomposer.hxx"
00014 #include "opengm/functions/modelviewfunction.hxx"
00015 #include "opengm/datastructures/marray/marray.hxx"
00016 #include "opengm/utilities/tribool.hxx"
00017 #include "opengm/inference/dualdecomposition/dddualvariableblock.hxx"
00018 #include <opengm/utilities/timer.hxx>
00019 
00020 namespace opengm { 
00021 
00022    class DualDecompositionBaseParameter{
00023    public:
00024       enum DecompositionId {MANUAL, TREE, SPANNINGTREES, BLOCKS};
00025       enum DualUpdateId {ADAPTIVE, STEPSIZE, STEPLENGTH, KIEWIL};
00026       
00028       DecompositionId decompositionId_;
00030       GraphicalModelDecomposition decomposition_;
00032       size_t maximalDualOrder_;
00034       size_t numberOfBlocks_;
00036       size_t maximalNumberOfIterations_;
00038       double minimalAbsAccuracy_; 
00040       double minimalRelAccuracy_;
00042       size_t numberOfThreads_;
00043 
00044       // Update parameters
00045       double stepsizeStride_;    //updateStride_;
00046       double stepsizeScale_;     //updateScale_;
00047       double stepsizeExponent_;  //updateExponent_;
00048       double stepsizeMin_;       //updateMin_;
00049       double stepsizeMax_;       //updateMax_;
00050       bool   stepsizePrimalDualGapStride_; //obsolete
00051       bool   stepsizeNormalizedSubgradient_; //obsolete
00052       // DualUpdateId dualUpdateId_ = ADAPTIVE;
00053     
00054       DualDecompositionBaseParameter() : 
00055          decompositionId_(SPANNINGTREES),  
00056          maximalDualOrder_(std::numeric_limits<size_t>::max()),
00057          numberOfBlocks_(2),
00058          maximalNumberOfIterations_(100),
00059          minimalAbsAccuracy_(0.0), 
00060          minimalRelAccuracy_(0.0),
00061          numberOfThreads_(1),
00062          stepsizeStride_(1),
00063          stepsizeScale_(1),
00064          stepsizeExponent_(0.5),
00065          stepsizeMin_(0),
00066          stepsizeMax_(std::numeric_limits<double>::infinity()),
00067          stepsizePrimalDualGapStride_(false),
00068          stepsizeNormalizedSubgradient_(false)
00069          
00070          {};
00071 
00072       double getStepsize(size_t iteration, double primalDualGap, double subgradientNorm){
00073          OPENGM_ASSERT(iteration>=0);
00074          double stepsize = stepsizeStride_;
00075          if(stepsizePrimalDualGapStride_){ 
00076             stepsize *= fabs(primalDualGap) / subgradientNorm / subgradientNorm;
00077          }
00078          else{
00079             stepsize /= (1+std::pow( stepsizeScale_*(double)(iteration),stepsizeExponent_));
00080             if(stepsizeNormalizedSubgradient_) 
00081                stepsize /= subgradientNorm; 
00082          }
00083          //stepsize /= (1+std::pow( stepsizeScale_*(double)(iteration),stepsizeExponent_));
00084          //stepsize = std::max(std::min(stepsizeMax_,stepsize),stepsizeMin_); 
00085          //if(stepsizeNormalizedSubgradient_) 
00086          //   stepsize /= subgradientNorm; 
00087          return stepsize;
00088       }
00089    };  
00090 
00092    template<class DD>
00093    class DualDecompositionEmptyVisitor {
00094    public:
00095       typedef DD DDType;
00096       typedef typename DDType::ValueType ValueType;
00097 
00098       void operator()(
00099          const DDType& dd, 
00100          const ValueType bound, const ValueType bestBound, 
00101          const ValueType value, const ValueType bestValue,
00102          double primalTime, double dualTime
00103          )
00104          {;}
00105       void startInference(){;}
00106     };
00107 
00109    template<class DD>
00110    class DualDecompositionVisitor {
00111    public:
00112       typedef DD DDType;
00113       typedef typename DDType::ValueType ValueType;
00114 
00115       void operator()(
00116          const DDType& dd, 
00117          const ValueType bound, const ValueType bestBound, 
00118          const ValueType value, const ValueType bestValue,
00119          const double primalTime, const double dualTime
00120          )
00121          {
00122             totalTimer_.toc(); 
00123             if(times_.size()==0)
00124                times_.push_back(totalTimer_.elapsedTime());
00125             else
00126                times_.push_back(times_.back() + totalTimer_.elapsedTime()); 
00127             values_.push_back(value);
00128             bounds_.push_back(bound);
00129             primalTimes_.push_back(primalTime);
00130             dualTimes_.push_back(dualTime);
00131 /*
00132             std::cout << "(" << values_.size() << " / "<< times_.back() <<"  )  " 
00133                       << bound << " <= " << bestBound 
00134                       << " <= " << "E" 
00135                       << " <= " << bestValue << " <= " 
00136                       << value << std::endl;
00137 */
00138             totalTimer_.tic();
00139          }
00140       void startInference(){totalTimer_.tic();}     
00141       const std::vector<ValueType>& values(){return values_;}
00142       const std::vector<ValueType>& bounds(){return bounds_;}
00143       const std::vector<double>& times(){return times_;}
00144       const std::vector<double>& primalTimes(){return primalTimes_;}
00145       const std::vector<double>& dualTimes(){return dualTimes_;}
00146 
00147    private:
00148       std::vector<ValueType> values_;
00149       std::vector<ValueType> bounds_;
00150       std::vector<double>    times_;    
00151       std::vector<double>    primalTimes_;
00152       std::vector<double>    dualTimes_;
00153       opengm::Timer totalTimer_;
00154     };
00155 
00157    template<class GM, class DUALBLOCK>
00158    class DualDecompositionBase
00159    {
00160    public:
00161       typedef GM                                                        GmType;
00162       typedef GM                                                        GraphicalModelType;
00163       typedef DUALBLOCK                                                 DualBlockType; 
00164       typedef typename DualBlockType::DualVariableType                  DualVariableType;
00165       OPENGM_GM_TYPE_TYPEDEFS;
00166       typedef ModelViewFunction<GmType, DualVariableType>               ViewFunctionType;
00167       typedef GraphicalModel<ValueType, OperatorType,  typename meta::TypeListGenerator<ViewFunctionType>::type, opengm::DiscreteSpace<IndexType,LabelType> > SubGmType;
00168      
00169 
00170       typedef GraphicalModelDecomposition                               DecompositionType;
00171       typedef typename DecompositionType::SubVariable                   SubVariableType;
00172       typedef typename DecompositionType::SubVariableListType           SubVariableListType;
00173       typedef typename DecompositionType::SubFactor                     SubFactorType;
00174       typedef typename DecompositionType::SubFactorListType             SubFactorListType; 
00175 
00176      
00177       DualDecompositionBase(const GmType&);
00178       void init(DualDecompositionBaseParameter&);
00179       const SubGmType& subModel(size_t subModelId) const {return subGm_[subModelId];};
00180   
00181    protected:
00182       template<class ITERATOR> void addDualBlock(const SubFactorListType&,ITERATOR,ITERATOR);
00183       std::vector<DualVariableType*> getDualPointers(size_t);
00184       template<class ACC> void getBounds(const std::vector<std::vector<LabelType> >&, const std::vector<SubVariableListType>&, ValueType&, ValueType&, std::vector<LabelType>&);
00185       double subGradientNorm(double L=1) const;
00186       virtual DualDecompositionBaseParameter& parameter() = 0;
00187       virtual void allocate() = 0;
00188      
00189       const GmType&              gm_;
00190       std::vector<SubGmType>     subGm_;
00191       std::vector<DualBlockType> dualBlocks_;
00192       size_t                     numDualsOvercomplete_;
00193       size_t                     numDualsMinimal_;
00194       std::vector<Tribool>       modelWithSameVariables_;
00195    };
00196  
00198    template<class DUALVAR> struct DDIsView                              {static bool isView(){return false;}};
00199    template<>              struct DDIsView<marray::View<double,false> > {static bool isView(){return true;}}; 
00200    template<>              struct DDIsView<marray::View<double,true> >  {static bool isView(){return true;}};  
00201    template<>              struct DDIsView<marray::View<float,false> >  {static bool isView(){return true;}};   
00202    template<>              struct DDIsView<marray::View<float,true> >   {static bool isView(){return true;}};     
00204 
00206     
00207    template<class DUALVAR, class T>
00208    void DualVarAssign(DUALVAR& dv,T* t)
00209    {  
00210    }
00211    
00212    template <class T>
00213    void DualVarAssign(marray::View<T,false>& dv, T* t)
00214    { 
00215       dv.assign( dv.shapeBegin(),dv.shapeEnd(),t);
00216    }
00217  
00218    template<class GM, class DUALBLOCK>
00219    DualDecompositionBase<GM, DUALBLOCK>::DualDecompositionBase(const GmType& gm):gm_(gm)
00220    {}
00221   
00222    template<class GM, class DUALBLOCK>
00223    void DualDecompositionBase<GM, DUALBLOCK>::init(DualDecompositionBaseParameter& para) 
00224    {
00225       if(para.decompositionId_ == DualDecompositionBaseParameter::TREE){
00226          opengm::GraphicalModelDecomposer<GmType> decomposer;
00227          para.decomposition_ = decomposer.decomposeIntoTree(gm_);
00228          para.decomposition_.reorder();
00229          para.decomposition_.complete();
00230          para.maximalDualOrder_ = 1;
00231       }
00232       if(para.decompositionId_ == DualDecompositionBaseParameter::SPANNINGTREES){
00233          opengm::GraphicalModelDecomposer<GmType> decomposer;
00234          para.decomposition_ = decomposer.decomposeIntoSpanningTrees(gm_);
00235          para.decomposition_.reorder();
00236          para.decomposition_.complete();
00237          para.maximalDualOrder_ = 1;
00238       } 
00239       if(para.decompositionId_ == DualDecompositionBaseParameter::BLOCKS){
00240          opengm::GraphicalModelDecomposer<GmType> decomposer;
00241          para.decomposition_ = decomposer.decomposeIntoClosedBlocks(gm_,para.numberOfBlocks_);
00242          para.decomposition_.reorder();
00243          para.decomposition_.complete();
00244          para.maximalDualOrder_ = 1;
00245       }
00246 
00247       OPENGM_ASSERT(para.decomposition_.isValid(gm_));
00248     
00249       //Build SubModels
00250       const std::vector<SubVariableListType>&                subVariableLists    =  para.decomposition_.getVariableLists();
00251       const std::vector<SubFactorListType>&                  subFactorLists      =  para.decomposition_.getFactorLists();
00252       const std::map<std::vector<size_t>,SubFactorListType>& emptySubFactorLists =  para.decomposition_.getEmptyFactorLists();
00253       const size_t                                           numberOfSubModels   =  para.decomposition_.numberOfSubModels();
00254       
00255       modelWithSameVariables_.resize(numberOfSubModels,Tribool::Maybe);
00256 
00257       typename SubVariableListType::const_iterator it;
00258       typename SubFactorListType::const_iterator it2; 
00259       typename SubFactorListType::const_iterator it3;
00260       typename std::map<std::vector<size_t>,SubFactorListType>::const_iterator it4;
00261 
00262  
00263       std::vector<std::vector<size_t> > numStates(numberOfSubModels);
00264       for(size_t subModelId=0; subModelId<numberOfSubModels; ++subModelId){
00265          numStates[subModelId].resize(para.decomposition_.numberOfSubVariables(subModelId),0);
00266       }
00267  
00268       for(size_t varId=0; varId<gm_.numberOfVariables(); ++varId){
00269          for(it = subVariableLists[varId].begin(); it!=subVariableLists[varId].end();++it){
00270             numStates[(*it).subModelId_][(*it).subVariableId_] = gm_.numberOfLabels(varId);        
00271          }
00272       }
00273 
00274       subGm_.resize(numberOfSubModels);
00275       for(size_t subModelId=0; subModelId<numberOfSubModels; ++subModelId){
00276          subGm_[subModelId] = SubGmType(opengm::DiscreteSpace<IndexType,LabelType>(numStates[subModelId].begin(),numStates[subModelId].end()));
00277       }
00278    
00279       // Add Duals 
00280       numDualsOvercomplete_ = 0;
00281       numDualsMinimal_ = 0;
00282      
00283       for(size_t factorId=0; factorId<gm_.numberOfFactors(); ++factorId){
00284          if(subFactorLists[factorId].size()>1 && (gm_[factorId].numberOfVariables() <= para.maximalDualOrder_)){
00285             addDualBlock(subFactorLists[factorId], gm_[factorId].shapeBegin(), gm_[factorId].shapeEnd());
00286             numDualsOvercomplete_ += subFactorLists[factorId].size()     *  gm_[factorId].size();
00287             numDualsMinimal_      += (subFactorLists[factorId].size()-1) *  gm_[factorId].size();
00288           }
00289       } 
00290   
00291       for(it4=emptySubFactorLists.begin() ; it4 != emptySubFactorLists.end(); it4++ ){
00292          if((*it4).second.size()>1 && ((*it4).first.size() <= para.maximalDualOrder_)){
00293             std::vector<size_t> shape((*it4).first.size());
00294             size_t temp = 1;
00295             for(size_t i=0; i<(*it4).first.size(); ++i){
00296                shape[i] = gm_.numberOfLabels((*it4).first[i]);
00297                temp *= gm_.numberOfLabels((*it4).first[i]);
00298             }  
00299             numDualsOvercomplete_ += (*it4).second.size()    * temp;
00300             numDualsMinimal_      += ((*it4).second.size()-1) * temp;
00301             addDualBlock((*it4).second,shape.begin(),shape.end());
00302          }
00303       }
00304 
00305       // Allocate memmory if this has not been done yet 
00306       this->allocate();
00307 
00308       // Add Factors
00309       size_t dualCounter = 0;
00310       for(size_t factorId=0; factorId<gm_.numberOfFactors(); ++factorId){
00311          if(subFactorLists[factorId].size()>1 && (gm_[factorId].numberOfVariables() <= para.maximalDualOrder_)){
00312             std::vector<DualVariableType*> offsets = getDualPointers(dualCounter++);
00313             size_t i=0;
00314             for(it2 = subFactorLists[factorId].begin(); it2!=subFactorLists[factorId].end();++it2){
00315                OPENGM_ASSERT(offsets[i]->dimension() == gm_[factorId].numberOfVariables());
00316                for(size_t j=0; j<offsets[i]->dimension();++j)
00317                   OPENGM_ASSERT(offsets[i]->shape(j) == gm_[factorId].shape(j));
00318 
00319                const size_t subModelId = (*it2).subModelId_;
00320                const ViewFunctionType function(gm_,factorId, 1.0/subFactorLists[factorId].size(),offsets[i++]); 
00321                const typename SubGmType::FunctionIdentifier funcId = subGm_[subModelId].addFunction(function); 
00322                subGm_[subModelId].addFactor(funcId,(*it2).subIndices_.begin(),(*it2).subIndices_.end());
00323             }
00324          }
00325          else{
00326             for(it2 = subFactorLists[factorId].begin(); it2!=subFactorLists[factorId].end();++it2){
00327                const size_t subModelId = (*it2).subModelId_;
00328                const ViewFunctionType function(gm_,factorId, 1.0/subFactorLists[factorId].size()); 
00329                const typename SubGmType::FunctionIdentifier funcId = subGm_[subModelId].addFunction(function); 
00330                subGm_[subModelId].addFactor(funcId,(*it2).subIndices_.begin(),(*it2).subIndices_.end());
00331             }
00332          }
00333       } 
00334       //Add EmptyFactors 
00335       for(it4=emptySubFactorLists.begin() ; it4 != emptySubFactorLists.end(); it4++ ){ 
00336          if((*it4).second.size()>1 && ((*it4).first.size() <= para.maximalDualOrder_)){
00337             size_t i=0;
00338             std::vector<DualVariableType*> offsets = getDualPointers(dualCounter++);
00339             for(it3 = (*it4).second.begin(); it3!=(*it4).second.end();++it3){
00340                const size_t subModelId = (*it3).subModelId_;
00341                const ViewFunctionType function(offsets[i++]); 
00342                const typename SubGmType::FunctionIdentifier funcId = subGm_[subModelId].addFunction(function); 
00343                subGm_[subModelId].addFactor(funcId,(*it3).subIndices_.begin(),(*it3).subIndices_.end());
00344             }
00345          }
00346       } 
00347    }
00348 
00349 
00350 
00351    template<class GM, class DUALBLOCK>
00352    template <class ITERATOR> 
00353    inline void DualDecompositionBase<GM,DUALBLOCK>::addDualBlock(const SubFactorListType& c,ITERATOR shapeBegin, ITERATOR shapeEnd)
00354    {  
00355       dualBlocks_.push_back(DualBlockType(c,shapeBegin,shapeEnd));
00356       return;
00357    } 
00358 
00359 
00360 
00361    template<class GM, class DUALBLOCK>
00362    inline std::vector<typename DUALBLOCK::DualVariableType*> DualDecompositionBase<GM,DUALBLOCK>::getDualPointers(size_t dualBlockId)
00363    {  
00364       return dualBlocks_[dualBlockId].getPointers();
00365    }
00366 
00367    template<class GM, class DUALBLOCK>
00368    template <class ACC>
00369    void DualDecompositionBase<GM,DUALBLOCK>::getBounds
00370    (
00371       const std::vector<std::vector<LabelType> >& subStates,
00372       const std::vector<SubVariableListType>& subVariableLists,
00373       ValueType& lowerBound, 
00374       ValueType& upperBound,
00375       std::vector<LabelType> & upperState
00376       )
00377    {
00378       // Calculate lower-bound 
00379       lowerBound=0;
00380       for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){ 
00381          lowerBound += subGm_[subModelId].evaluate(subStates[subModelId]); 
00382       }
00383       
00384       // Calculate upper-bound 
00385       Accumulation<ValueType,LabelType,ACC> ac;
00386      
00387       // Set modelWithSameVariables_
00388       if(modelWithSameVariables_[0] == Tribool::Maybe){
00389          for(size_t varId=0; varId<gm_.numberOfVariables(); ++varId){
00390             for(typename SubVariableListType::const_iterator its = subVariableLists[varId].begin();
00391                 its!=subVariableLists[varId].end();++its){
00392                const size_t& subModelId    = (*its).subModelId_;
00393                const size_t& subVariableId = (*its).subVariableId_;
00394                if(subVariableId != varId){
00395                   modelWithSameVariables_[subModelId] = Tribool::False;
00396                }
00397             }
00398          } 
00399          for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){ 
00400             if(gm_.numberOfVariables() != subGm_[subModelId].numberOfVariables()){
00401                modelWithSameVariables_[subModelId] = Tribool::False;
00402             }
00403             if(modelWithSameVariables_[subModelId] == Tribool::Maybe){
00404                modelWithSameVariables_[subModelId] = Tribool::True;
00405             }
00406          }
00407       }
00408 
00409       // Build Primal-Candidates
00410       std::vector<std::vector<LabelType> > args(subGm_.size());
00411       bool somethingToFill = false;
00412       for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){ 
00413          if(modelWithSameVariables_[subModelId] == Tribool::False){
00414             args[subModelId].assign(gm_.numberOfVariables(),std::numeric_limits<LabelType>::max());
00415             somethingToFill = true;
00416          }
00417          else{
00418             ac(gm_.evaluate(subStates[subModelId]),subStates[subModelId]);
00419          }
00420       } 
00421 
00422       if(somethingToFill){
00423          for(size_t varId=0; varId<gm_.numberOfVariables(); ++varId){
00424             for(typename SubVariableListType::const_iterator its = subVariableLists[varId].begin();
00425                 its!=subVariableLists[varId].end();++its){
00426                const size_t& subModelId    = (*its).subModelId_;
00427                const size_t& subVariableId = (*its).subVariableId_;
00428                if(modelWithSameVariables_[subModelId] == Tribool::False){
00429                   args[subModelId][varId] = subStates[subModelId][subVariableId]; 
00430                }      
00431             }
00432             for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){
00433                if(modelWithSameVariables_[subModelId] == Tribool::False && 
00434                   args[subModelId][varId] == std::numeric_limits<LabelType>::max())
00435                {
00436                   const size_t& aSubModelId    = subVariableLists[varId].front().subModelId_; 
00437                   const size_t& aSubVariableId = subVariableLists[varId].front().subVariableId_;
00438                   args[subModelId][varId] = subStates[aSubModelId][aSubVariableId];   
00439                }
00440             }
00441          }
00442          for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){
00443             if(modelWithSameVariables_[subModelId] == Tribool::False){
00444                ac(gm_.evaluate(args[subModelId]),args[subModelId]);
00445             }
00446          }
00447       }
00448       
00449       upperBound = ac.value();
00450       ac.state(upperState);
00451    }
00452 
00453    template <class GM, class DUALBLOCK> 
00454    double DualDecompositionBase<GM,DUALBLOCK>::subGradientNorm(double L) const
00455    { 
00456       double norm = 0;
00457       typename std::vector<DualBlockType>::const_iterator it;
00458       for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
00459          norm  += (*it).duals_.size();
00460       }
00461       norm = pow(norm,1.0/L);
00462       return norm;
00463    } 
00464 
00465 } // namespace opengm
00466 
00467 #endif
 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