dualdecomposition_subgradient.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef OPENGM_DUALDDECOMPOSITION_SUBGRADIENT_HXX
00003 #define OPENGM_DUALDDECOMPOSITION_SUBGRADIENT_HXX
00004 
00005 #include <vector>
00006 #include <list>
00007 #include <typeinfo>
00008 
00009 #include "opengm/inference/inference.hxx"
00010 #include "opengm/inference/visitors/visitor.hxx"
00011 #include "opengm/inference/dualdecomposition/dualdecomposition_base.hxx"
00012 
00013 namespace opengm {
00014 
00016    template<class GM, class INF, class DUALBLOCK >
00017    class DualDecompositionSubGradient 
00018       : public Inference<GM,typename INF::AccumulationType>,  public DualDecompositionBase<GM, DUALBLOCK > 
00019    {
00020    public:
00021       typedef GM                                                 GmType;
00022       typedef GM                                                 GraphicalModelType;
00023       typedef typename INF::AccumulationType                     AccumulationType;
00024       OPENGM_GM_TYPE_TYPEDEFS;
00025       typedef VerboseVisitor<DualDecompositionSubGradient<GM, INF,DUALBLOCK> > VerboseVisitorType;
00026       typedef TimingVisitor<DualDecompositionSubGradient<GM, INF,DUALBLOCK> >  TimingVisitorType;
00027       typedef EmptyVisitor<DualDecompositionSubGradient<GM, INF,DUALBLOCK> >   EmptyVisitorType;
00028 
00029       typedef INF                                                InfType;
00030       typedef DUALBLOCK                                          DualBlockType;
00031       typedef DualDecompositionBase<GmType, DualBlockType>       DDBaseType;
00032      
00033       typedef typename DualBlockType::DualVariableType           DualVariableType;
00034       typedef typename DDBaseType::SubGmType                     SubGmType;
00035       typedef typename DualBlockType::SubFactorType              SubFactorType;
00036       typedef typename DualBlockType::SubFactorListType          SubFactorListType; 
00037       typedef typename DDBaseType::SubVariableType               SubVariableType;
00038       typedef typename DDBaseType::SubVariableListType           SubVariableListType; 
00039 
00040       class Parameter : public DualDecompositionBaseParameter{
00041       public:
00043          typename InfType::Parameter subPara_;
00044          bool useAdaptiveStepsize_;
00045          bool useProjectedAdaptiveStepsize_;
00046          Parameter() : useAdaptiveStepsize_(false), useProjectedAdaptiveStepsize_(false){};
00047       };
00048 
00049       using  DualDecompositionBase<GmType, DualBlockType >::gm_;
00050       using  DualDecompositionBase<GmType, DualBlockType >::subGm_;
00051       using  DualDecompositionBase<GmType, DualBlockType >::dualBlocks_;
00052       using  DualDecompositionBase<GmType, DualBlockType >::numDualsOvercomplete_;
00053       using  DualDecompositionBase<GmType, DualBlockType >::numDualsMinimal_;
00054 
00055       DualDecompositionSubGradient(const GmType&);
00056       DualDecompositionSubGradient(const GmType&, const Parameter&);
00057       virtual std::string name() const {return "DualDecompositionSubGradient";};
00058       virtual const GmType& graphicalModel() const {return gm_;};
00059       virtual InferenceTermination infer();
00060       template <class VISITOR> InferenceTermination infer(VISITOR&);
00061       virtual ValueType bound() const;
00062       virtual ValueType value() const;
00063       virtual InferenceTermination arg(std::vector<LabelType>&, const size_t = 1)const;
00064      
00065    private: 
00066       virtual void allocate();
00067       virtual DualDecompositionBaseParameter& parameter();
00068       void dualStep(const size_t);
00069       template <class T_IndexType, class T_LabelType>
00070       void getPartialSubGradient(const size_t, const std::vector<T_IndexType>&, std::vector<T_LabelType>&)const;
00071       double euclideanProjectedSubGradientNorm();
00072 
00073       // Members
00074       std::vector<std::vector<LabelType> >  subStates_;
00075    
00076       Accumulation<ValueType,LabelType,AccumulationType> acUpperBound_;
00077       Accumulation<ValueType,LabelType,AccumulationType> acNegLowerBound_;
00078       ValueType upperBound_;
00079       ValueType lowerBound_;
00080       std::vector<ValueType> values_;
00081 
00082       Parameter              para_;
00083       std::vector<ValueType> mem_;
00084   
00085       opengm::Timer primalTimer_;
00086       opengm::Timer dualTimer_;
00087       double primalTime_;
00088       double dualTime_;
00089 
00090    };  
00091       
00092 //**********************************************************************************
00093    template<class GM, class INF, class DUALBLOCK>
00094    DualDecompositionSubGradient<GM,INF,DUALBLOCK>::DualDecompositionSubGradient(const GmType& gm)
00095       : DualDecompositionBase<GmType, DualBlockType >(gm)
00096    {
00097       this->init(para_);
00098       subStates_.resize(subGm_.size());
00099       for(size_t i=0; i<subGm_.size(); ++i)
00100          subStates_[i].resize(subGm_[i].numberOfVariables()); 
00101    }
00102    
00103    template<class GM, class INF, class DUALBLOCK>
00104    DualDecompositionSubGradient<GM,INF,DUALBLOCK>::DualDecompositionSubGradient(const GmType& gm, const Parameter& para)
00105       :   DualDecompositionBase<GmType, DualBlockType >(gm),para_(para)
00106    {  
00107       this->init(para_);  
00108       subStates_.resize(subGm_.size());
00109       for(size_t i=0; i<subGm_.size(); ++i)
00110          subStates_[i].resize(subGm_[i].numberOfVariables());
00111    }
00112 
00113 
00115 
00116    template <class GM, class INF, class DUALBLOCK> 
00117    void DualDecompositionSubGradient<GM,INF,DUALBLOCK>::allocate()  
00118    { 
00119       if(DDIsView<DualVariableType>::isView()){
00120          mem_.resize(numDualsOvercomplete_,0.0);
00121       }
00122       else 
00123          mem_.resize(1,0.0);
00124       //std::cout << mem_.size() <<std::flush;
00125       ValueType *data = &mem_[0];
00126       for(typename std::vector<DualBlockType>::iterator it=dualBlocks_.begin(); it!=dualBlocks_.end(); ++it){
00127          for(size_t i=0; i<(*it).duals_.size(); ++i){
00128             DualVariableType& dv = (*it).duals_[i];
00129             DualVarAssign(dv, data);
00130             if(DDIsView<DualVariableType>::isView()) 
00131                data += dv.size(); 
00132          }
00133       }
00134    }   
00135    template <class GM, class INF, class DUALBLOCK> 
00136    DualDecompositionBaseParameter& DualDecompositionSubGradient<GM,INF,DUALBLOCK>::parameter()
00137    {
00138       return para_;
00139    }
00140 
00142    template<class GM, class INF, class DUALBLOCK>
00143    InferenceTermination DualDecompositionSubGradient<GM,INF,DUALBLOCK>::
00144    infer() 
00145    {
00146       EmptyVisitorType visitor;
00147       return infer(visitor);
00148    }
00149    template<class GM, class INF, class DUALBLOCK> 
00150    template<class VISITOR>
00151    InferenceTermination DualDecompositionSubGradient<GM,INF,DUALBLOCK>::
00152    infer(VISITOR& visitor) 
00153    {
00154       std::cout.precision(15);
00155       //visitor.startInference();
00156       visitor.begin(*this,this->value(),this->bound());
00157           
00158       for(size_t iteration=0; iteration<para_.maximalNumberOfIterations_; ++iteration){  
00159        
00160          // Solve Subproblems
00161          primalTime_=0;
00162          primalTimer_.tic();
00163          //omp_set_num_threads(para_.numberOfThreads_);
00164  
00165 //#pragma omp parallel for
00166          for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){ 
00167             InfType inf(subGm_[subModelId],para_.subPara_);
00168             inf.infer(); 
00169             inf.arg(subStates_[subModelId]); 
00170          } 
00171          primalTimer_.toc(); 
00172 
00173          dualTimer_.tic();
00174          // Calculate lower-bound 
00175          std::vector<LabelType> temp;  
00176          std::vector<LabelType> temp2; 
00177          const std::vector<SubVariableListType>& subVariableLists = para_.decomposition_.getVariableLists();
00178          (*this).template getBounds<AccumulationType>(subStates_, subVariableLists, lowerBound_, upperBound_, temp);
00179          acNegLowerBound_(-lowerBound_,temp2);
00180          acUpperBound_(upperBound_, temp);
00181          
00182           //dualStep
00183          double stepsize;
00184          if(para_.useAdaptiveStepsize_){
00185             stepsize = para_.stepsizeStride_ * fabs(acUpperBound_.value() - lowerBound_) 
00186                        /(*this).subGradientNorm(1);
00187          }
00188          else if(para_.useProjectedAdaptiveStepsize_){
00189             double subgradientNorm = euclideanProjectedSubGradientNorm();
00190             stepsize = para_.stepsizeStride_ * fabs(acUpperBound_.value() - lowerBound_) 
00191                        /subgradientNorm/subgradientNorm;
00192          }
00193          else{
00194             double primalDualGap = fabs(acUpperBound_.value() + acNegLowerBound_.value());
00195             double subgradientNorm = euclideanProjectedSubGradientNorm();//(*this).subGradientNorm(1); 
00196             stepsize = para_.getStepsize(iteration,primalDualGap,subgradientNorm); 
00197 //            std::cout << stepsize << std::endl;
00198          }
00199      
00200          if(typeid(AccumulationType) == typeid(opengm::Minimizer))
00201             stepsize *=1;
00202          else 
00203             stepsize *= -1;
00204                   
00205          std::vector<size_t> s;
00206          for(typename std::vector<DualBlockType>::const_iterator it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
00207             const size_t numDuals = (*it).duals_.size();
00208             typename SubFactorListType::const_iterator lit = (*((*it).subFactorList_)).begin();
00209             s.resize((*lit).subIndices_.size());
00210             for(size_t i=0; i<numDuals; ++i){
00211          getPartialSubGradient<size_t>((*lit).subModelId_, (*lit).subIndices_, s); 
00212                ++lit;     
00213                (*it).duals_[i](s.begin()) += stepsize;
00214                for(size_t j=0; j<numDuals; ++j){ 
00215                   (*it).duals_[j](s.begin()) -= stepsize/numDuals;
00216                }
00217             }
00218             (*it).test();
00219          }          
00220          dualTimer_.toc();
00221 
00222          primalTime_ = primalTimer_.elapsedTime();
00223          dualTime_   = dualTimer_.elapsedTime();  
00224          visitor((*this), upperBound_, lowerBound_); 
00225          //visitor((*this), lowerBound_, -acNegLowerBound_.value(), upperBound_, acUpperBound_.value(), primalTime_, dualTime_); 
00226 
00227      
00228          // Test for Convergence
00229          ValueType o;
00230          AccumulationType::iop(0.0001,-0.0001,o);
00231          OPENGM_ASSERT(AccumulationType::bop(lowerBound_, upperBound_+o));
00232          OPENGM_ASSERT(AccumulationType::bop(-acNegLowerBound_.value(), acUpperBound_.value()+o));
00233          
00234          if(   fabs(acUpperBound_.value() + acNegLowerBound_.value())                       <= para_.minimalAbsAccuracy_
00235             || fabs((acUpperBound_.value()+ acNegLowerBound_.value())/acUpperBound_.value()) <= para_.minimalRelAccuracy_){
00236             //std::cout << "bound reached ..." <<std::endl;
00237             visitor.end((*this), acUpperBound_.value(), -acNegLowerBound_.value()); 
00238             return NORMAL;
00239          } 
00240       } 
00241       //std::cout << "maximal number of dual steps ..." <<std::endl;
00242       visitor.end((*this), acUpperBound_.value(), -acNegLowerBound_.value()); 
00243            
00244       return NORMAL;
00245    }
00246    
00247 
00248    template<class GM, class INF, class DUALBLOCK>
00249    InferenceTermination DualDecompositionSubGradient<GM,INF,DUALBLOCK>::
00250    arg(std::vector<LabelType>& conf, const size_t n)const 
00251    {
00252       if(n!=1){
00253          return UNKNOWN;
00254       }
00255       else{ 
00256          acUpperBound_.state(conf);
00257          return NORMAL;
00258       }
00259    }
00260 
00261    template<class GM, class INF, class DUALBLOCK>
00262    typename GM::ValueType DualDecompositionSubGradient<GM,INF,DUALBLOCK>::value() const 
00263    {
00264       return acUpperBound_.value();
00265    }
00266 
00267    template<class GM, class INF, class DUALBLOCK>
00268    typename GM::ValueType DualDecompositionSubGradient<GM,INF,DUALBLOCK>::bound() const 
00269    {
00270       return -acNegLowerBound_.value();
00271    }
00272 
00273 
00275  
00276    template <class GM, class INF, class DUALBLOCK> 
00277    void DualDecompositionSubGradient<GM,INF,DUALBLOCK>::dualStep(const size_t iteration)
00278    { 
00279     
00280    } 
00281 
00282    template <class GM, class INF, class DUALBLOCK> 
00283    template <class T_IndexType, class T_LabelType>
00284    inline void DualDecompositionSubGradient<GM,INF,DUALBLOCK>::getPartialSubGradient 
00285    ( 
00286       const size_t                             subModelId,
00287       const std::vector<T_IndexType>&    subIndices, 
00288       std::vector<T_LabelType> &                 s
00289    )const 
00290    {
00291       OPENGM_ASSERT(subIndices.size() == s.size());
00292       for(size_t n=0; n<s.size(); ++n){
00293          s[n] = subStates_[subModelId][subIndices[n]];
00294       }
00295    } 
00296 
00297    template <class GM, class INF, class DUALBLOCK> 
00298    double DualDecompositionSubGradient<GM,INF,DUALBLOCK>::euclideanProjectedSubGradientNorm()
00299    { 
00300       double norm = 0;
00301       std::vector<LabelType> s;
00302       marray::Marray<double> M;
00303       typename std::vector<DUALBLOCK>::const_iterator it;
00304       typename SubFactorListType::const_iterator                  lit;
00305       for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
00306          const size_t numDuals = (*it).duals_.size(); 
00307          marray::Marray<double> M( (*it).duals_[0].shapeBegin(), (*it).duals_[0].shapeEnd() ,0.0);
00308          lit = (*((*it).subFactorList_)).begin();
00309          s.resize((*lit).subIndices_.size());
00310          for(size_t i=0; i<numDuals; ++i){
00311             getPartialSubGradient((*lit).subModelId_, (*lit).subIndices_, s); 
00312             ++lit; 
00313             M(s.begin()) += 1;
00314          }
00315          for(size_t i=0; i<M.size(); ++i){
00316             norm  += M(i)            * pow(1.0 - M(i)/numDuals,2);
00317             norm  += (numDuals-M(i)) * pow(      M(i)/numDuals,2);
00318          }
00319       }
00320       return sqrt(norm);
00321    } 
00322 
00323 
00324 }
00325    
00326 #endif
00327 
 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