dualdecomposition_bundle.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef OPENGM_DUALDDECOMPOSITION_BUNDLE_HXX
00003 #define OPENGM_DUALDDECOMPOSITION_BUNDLE_HXX
00004 
00005 #include <vector>
00006 #include <list>
00007 #include <typeinfo>
00008 #include "opengm/inference/inference.hxx"
00009 #include "opengm/inference/visitors/visitor.hxx"
00010 #include "opengm/inference/dualdecomposition/dualdecomposition_base.hxx"
00011 
00012 #ifdef WITH_OPENMP
00013 #include <omp.h>
00014 #endif
00015 #ifdef WITH_CONICBUNDLE
00016 #include <CBSolver.hxx>
00017 
00018 namespace opengm {
00019 
00021    template<class GM, class INF, class DUALBLOCK >
00022    class DualDecompositionBundle 
00023       : public Inference<GM,typename INF::AccumulationType>,  
00024         public DualDecompositionBase<GM, DUALBLOCK>,
00025         public ConicBundle::FunctionOracle
00026    {
00027    public:
00028       typedef GM                                                 GmType; 
00029       typedef GM                                                 GraphicalModelType;
00030       typedef typename INF::AccumulationType                     AccumulationType;
00031       OPENGM_GM_TYPE_TYPEDEFS;
00032       typedef VerboseVisitor<DualDecompositionBundle<GM, INF,DUALBLOCK> > VerboseVisitorType;
00033       typedef TimingVisitor<DualDecompositionBundle<GM, INF,DUALBLOCK> >  TimingVisitorType;
00034       typedef EmptyVisitor<DualDecompositionBundle<GM, INF,DUALBLOCK> >   EmptyVisitorType;
00035       typedef INF                                                InfType;
00036       typedef DUALBLOCK                                          DualBlockType;
00037       typedef typename DualBlockType::DualVariableType           DualVariableType;
00038       typedef DualDecompositionBase<GmType, DualBlockType>       DDBaseType;    
00039      
00040       typedef typename DDBaseType::SubGmType                     SubGmType;
00041       typedef typename DualBlockType::SubFactorType              SubFactorType;
00042       typedef typename DualBlockType::SubFactorListType          SubFactorListType; 
00043       typedef typename DDBaseType::SubVariableType               SubVariableType;
00044       typedef typename DDBaseType::SubVariableListType           SubVariableListType; 
00045 
00046       class Parameter : public DualDecompositionBaseParameter{
00047       public: 
00049          double minimalRelAccuracy_;
00051          typename InfType::Parameter subPara_;
00053          double relativeDualBoundPrecision_;
00055          size_t maxBundlesize_;
00057          bool activeBoundFixing_;
00059          double minDualWeight_;
00061          double maxDualWeight_;
00063          bool noBundle_;
00065          bool useHeuristicStepsize_;
00066        
00067          Parameter() 
00068             : relativeDualBoundPrecision_(0.0),
00069               maxBundlesize_(100),
00070               activeBoundFixing_(false),
00071               minDualWeight_(-1),
00072               maxDualWeight_(-1),
00073               noBundle_(false),
00074               useHeuristicStepsize_(true)
00075             {};
00076       };
00077 
00078       using  DualDecompositionBase<GmType, DualBlockType >::gm_;
00079       using  DualDecompositionBase<GmType, DualBlockType >::subGm_;
00080       using  DualDecompositionBase<GmType, DualBlockType >::dualBlocks_;
00081       using  DualDecompositionBase<GmType, DualBlockType >::numDualsOvercomplete_;
00082       using  DualDecompositionBase<GmType, DualBlockType >::numDualsMinimal_;
00083       
00084       ~DualDecompositionBundle();
00085       DualDecompositionBundle(const GmType&);
00086       DualDecompositionBundle(const GmType&, const Parameter&);
00087       virtual std::string name() const {return "DualDecompositionSubGradient";};
00088       virtual const GmType& graphicalModel() const {return gm_;};
00089       virtual InferenceTermination infer();
00090       template<class VisitorType>
00091       InferenceTermination infer(VisitorType&);
00092       virtual ValueType bound() const;
00093       virtual ValueType value() const;
00094       virtual InferenceTermination arg(std::vector<LabelType>&, const size_t = 1)const;
00095       virtual int evaluate(const ConicBundle::DVector&, double, double&, ConicBundle::DVector&, std::vector<ConicBundle::DVector>&,
00096                            std::vector<ConicBundle::PrimalData*>&, ConicBundle::PrimalExtender*&);
00097     
00098    private: 
00099       virtual void allocate();
00100       virtual DualDecompositionBaseParameter& parameter();
00101       int dualStep(const size_t iteration);
00102      template <class T_IndexType, class T_LabelType>
00103       void getPartialSubGradient(const size_t, const std::vector<T_IndexType>&, std::vector<T_LabelType>&)const;
00104       double euclideanSubGradientNorm();
00105 
00106       // Members
00107       std::vector<std::vector<LabelType> >  subStates_;
00108       ConicBundle::CBSolver* solver;
00109       size_t nullStepCounter_;
00110 
00111       Accumulation<ValueType,LabelType,AccumulationType> acUpperBound_;
00112       Accumulation<ValueType,LabelType,AccumulationType> acNegLowerBound_;
00113       ValueType upperBound_;
00114       ValueType lowerBound_;
00115 
00116       Parameter              para_;
00117       std::vector<ValueType> mem_; 
00118       std::vector<ValueType> mem2_;
00119 
00120       opengm::Timer primalTimer_;
00121       opengm::Timer dualTimer_;
00122       double primalTime_;
00123       double dualTime_;
00124 
00125    };  
00126       
00127 //**********************************************************************************
00128    template<class GM, class INF, class DUALBLOCK>
00129    DualDecompositionBundle<GM,INF,DUALBLOCK>::~DualDecompositionBundle()
00130    {
00131       delete solver;
00132    }
00133 
00134    template<class GM, class INF, class DUALBLOCK>
00135    DualDecompositionBundle<GM,INF,DUALBLOCK>::DualDecompositionBundle(const GmType& gm)
00136       : DualDecompositionBase<GmType, DualBlockType >(gm)
00137    {
00138       this->init(para_);
00139       subStates_.resize(subGm_.size());
00140       for(size_t i=0; i<subGm_.size(); ++i)
00141          subStates_[i].resize(subGm_[i].numberOfVariables());
00142   
00143       solver = new ConicBundle::CBSolver(para_.noBundle_);
00144       // Setup bundle-solver
00145       solver->init_problem(numDualsMinimal_);
00146       solver->add_function(*this); 
00147       solver->set_out(&std::cout,0);//1=output
00148      
00149       solver->set_max_bundlesize(*this,para_.maxBundlesize_);
00150       //solver->set_eval_limit(1000); 
00151       //solver->set_inner_update_limit(1);
00152       solver->set_active_bounds_fixing(para_.activeBoundFixing_);
00153       solver->set_term_relprec(para_.relativeDualBoundPrecision_); 
00154       solver->set_min_weight(para_.minDualWeight_);
00155       solver->set_max_weight(para_.maxDualWeight_);
00156       nullStepCounter_ =0;
00157    }
00158    
00159    template<class GM, class INF, class DUALBLOCK>
00160    DualDecompositionBundle<GM,INF,DUALBLOCK>::DualDecompositionBundle(const GmType& gm, const Parameter& para)
00161       :  DualDecompositionBase<GmType, DualBlockType >(gm)
00162    {
00163       para_ = para;
00164       this->init(para_); 
00165  
00166       subStates_.resize(subGm_.size());
00167       for(size_t i=0; i<subGm_.size(); ++i)
00168          subStates_[i].resize(subGm_[i].numberOfVariables()); 
00169  
00170       solver = new ConicBundle::CBSolver(para_.noBundle_);
00171       // Setup bundle-solver
00172       solver->init_problem(numDualsMinimal_);
00173       solver->add_function(*this); 
00174       solver->set_out(&std::cout,0);//1=output
00175       solver->set_max_bundlesize(*this,para_.maxBundlesize_);
00176       //solver->set_eval_limit(1000);
00177       //solver->set_inner_update_limit(1);
00178       solver->set_active_bounds_fixing(para.activeBoundFixing_);
00179       solver->set_term_relprec(para_.relativeDualBoundPrecision_); 
00180       solver->set_min_weight(para_.minDualWeight_);
00181       solver->set_max_weight(para_.maxDualWeight_);
00182       nullStepCounter_ =0;
00183  }
00184 
00185 
00187 
00188    template <class GM, class INF, class DUALBLOCK> 
00189    void DualDecompositionBundle<GM,INF,DUALBLOCK>::allocate()  
00190    { 
00191       mem_.resize(numDualsOvercomplete_,0);
00192       mem2_.resize(numDualsOvercomplete_,0);
00193       ValueType *data1Front = &mem_[0];
00194       ValueType *data1Back  = &mem_[numDualsOvercomplete_];
00195       ValueType *data2Front = &mem2_[0];
00196       ValueType *data2Back  = &mem2_[numDualsOvercomplete_];
00197       for(typename std::vector<DualBlockType>::iterator it=dualBlocks_.begin(); it!=dualBlocks_.end(); ++it){
00198          for(size_t i=0; i<(*it).duals_.size(); ++i){
00199             DualVariableType& dv1 = (*it).duals_[i];
00200             DualVariableType& dv2 = (*it).duals2_[i];
00201             if(i+1==(*it).duals_.size()){
00202                data1Back -= dv1.size(); 
00203                data2Back -= dv2.size(); 
00204                dv1.assign( dv1.shapeBegin(),dv1.shapeEnd(),data1Back); 
00205                dv2.assign( dv2.shapeBegin(),dv2.shapeEnd(),data2Back); 
00206             }
00207             else{
00208                dv1.assign( dv1.shapeBegin(),dv1.shapeEnd(),data1Front); 
00209                dv2.assign( dv2.shapeBegin(),dv2.shapeEnd(),data2Front); 
00210                data1Front += dv1.size(); 
00211                data2Front += dv2.size();
00212             } 
00213          }
00214       }
00215       OPENGM_ASSERT(data1Front ==  data1Back );
00216       OPENGM_ASSERT(data2Front ==  data2Back ); 
00217       OPENGM_ASSERT(data1Front ==  &mem_[0]+numDualsMinimal_);
00218       OPENGM_ASSERT(data2Front ==  &mem2_[0]+numDualsMinimal_ );
00219    }   
00220 
00221    template <class GM, class INF, class DUALBLOCK> 
00222    DualDecompositionBaseParameter& DualDecompositionBundle<GM,INF,DUALBLOCK>::parameter()
00223    {
00224       return para_;
00225    }
00226 
00228   
00229    template<class GM, class INF, class DUALBLOCK>
00230    InferenceTermination DualDecompositionBundle<GM,INF,DUALBLOCK>::
00231    infer() 
00232    {
00233       EmptyVisitorType visitor;
00234       return infer(visitor);
00235    }
00236 
00237    template<class GM, class INF, class DUALBLOCK>
00238    template<class VisitorType>
00239    InferenceTermination DualDecompositionBundle<GM,INF,DUALBLOCK>::
00240    infer(VisitorType& visitor) 
00241    {
00242       std::cout.precision(15);
00243       visitor.begin(*this,this->value(),this->bound());    
00244       for(size_t iteration=0; iteration<para_.maximalNumberOfIterations_; ++iteration){  
00245          // Dual Step 
00246          dualTimer_.tic();
00247          int ret;
00248          if(dualBlocks_.size() == 0){
00249             // Solve subproblems
00250             for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){ 
00251                InfType inf(subGm_[subModelId],para_.subPara_);
00252                inf.infer(); 
00253                inf.arg(subStates_[subModelId]); 
00254             } 
00255 
00256             // Calculate lower-bound
00257             std::vector<LabelType> temp;  
00258             std::vector<LabelType> temp2; 
00259             const std::vector<SubVariableListType>& subVariableLists = para_.decomposition_.getVariableLists();
00260             (*this).template getBounds<AccumulationType>(subStates_, subVariableLists, lowerBound_, upperBound_, temp);
00261             acNegLowerBound_(-lowerBound_,temp2);
00262             acUpperBound_(upperBound_, temp);
00263             ret=128;
00264          }
00265          else{
00266             ret = dualStep(iteration);
00267          }
00268          dualTimer_.toc();
00269          dualTime_ = dualTimer_.elapsedTime() - primalTime_;
00270          std::cout.precision(15);
00271          visitor((*this), upperBound_, lowerBound_); 
00272          //visitor((*this),lowerBound_,-acNegLowerBound_.value(), upperBound_, acUpperBound_.value(), primalTime_, dualTime_);
00273 
00274          dualTime_  = 0;
00275          primalTime_ = 0;
00276 
00277 
00278          // Test for Convergence
00279          ValueType o;
00280          AccumulationType::iop(0.0001,-0.0001,o);
00281          OPENGM_ASSERT(AccumulationType::bop(lowerBound_, upperBound_+o));
00282          OPENGM_ASSERT(AccumulationType::bop(-acNegLowerBound_.value(), acUpperBound_.value()+o));
00283          
00284          if(   fabs(acUpperBound_.value() + acNegLowerBound_.value())                       <= para_.minimalAbsAccuracy_
00285             || fabs((acUpperBound_.value()+ acNegLowerBound_.value())/acUpperBound_.value()) <= para_.minimalRelAccuracy_
00286             || ret ==1){
00287             visitor.end((*this), acUpperBound_.value(), -acNegLowerBound_.value()); 
00288             return NORMAL;
00289          } 
00290          if(ret>0){
00291             break;
00292          }
00293       } 
00294       visitor.end((*this), acUpperBound_.value(), -acNegLowerBound_.value()); 
00295       return NORMAL;
00296    }
00297 
00298    template<class GM, class INF, class DUALBLOCK>
00299    InferenceTermination DualDecompositionBundle<GM,INF,DUALBLOCK>::
00300    arg(std::vector<LabelType>& conf, const size_t n)const 
00301    {
00302       if(n!=1){
00303          return UNKNOWN;
00304       }
00305       else{ 
00306          acUpperBound_.state(conf);
00307          return NORMAL;
00308       }
00309    }
00310 
00311    template<class GM, class INF, class DUALBLOCK>
00312    typename GM::ValueType DualDecompositionBundle<GM,INF,DUALBLOCK>::value() const 
00313    {
00314       return acUpperBound_.value();
00315    }
00316 
00317    template<class GM, class INF, class DUALBLOCK>
00318    typename GM::ValueType DualDecompositionBundle<GM,INF,DUALBLOCK>::bound() const 
00319    {
00320       return -acNegLowerBound_.value();
00321    }
00322 
00323 
00325  
00326    template <class GM, class INF, class DUALBLOCK> 
00327    int DualDecompositionBundle<GM,INF,DUALBLOCK>::dualStep(const size_t iteration)
00328    { 
00329       int retval; 
00330       if(para_.useHeuristicStepsize_){ 
00331          solver->set_min_weight(para_.minDualWeight_);
00332          solver->set_max_weight(para_.maxDualWeight_);
00333       }
00334       else if(iteration == 0){
00335          solver->set_min_weight(100);
00336          solver->set_max_weight(100);
00337       }
00338       else{
00339          if(solver->get_objval() == solver->get_candidate_value() || iteration==1){
00340             //Serious Step
00341             double primalDualGap   = fabs(acUpperBound_.value() + acNegLowerBound_.value());
00342            
00343             double subgradientNorm =  (*this).euclideanSubGradientNorm();
00344             double stepsize = (primalDualGap)/subgradientNorm * para_.stepsizeStride_;
00345            
00346             if(para_.minDualWeight_>=0)     
00347                stepsize = std::min(1/para_.minDualWeight_, stepsize);
00348             if(para_.maxDualWeight_>=0)
00349                stepsize = std::max(1/para_.maxDualWeight_, stepsize);
00350                  
00351             double t   = 1/stepsize;
00352             solver->set_next_weight(t);
00353             solver->set_min_weight(t);
00354             solver->set_max_weight(t);
00355             nullStepCounter_ =0;
00356          }
00357          else{
00358             // Null Step  
00359             ++nullStepCounter_;
00360          }
00361       }
00362 
00363       retval=solver->do_descent_step(1);
00364 
00365       if (retval){
00366          std::cout<<"descent_step returned "<<retval<<std::endl;
00367       }
00368       //std::cout << solver->get_last_weight() << std::endl;
00369       return solver->termination_code();
00370    } 
00371 
00372    template <class GM, class INF, class DUALBLOCK> 
00373    int DualDecompositionBundle<GM,INF,DUALBLOCK>::evaluate
00374    (  
00375       const ConicBundle::DVector&            dual, // Argument/Lagrange multipliers 
00376       double                                 relprec,
00377       double&                                objective_value,
00378       ConicBundle::DVector&                  cut_vals,
00379       std::vector<ConicBundle::DVector>&     subgradients,
00380       std::vector<ConicBundle::PrimalData*>& primal_solutions,
00381       ConicBundle::PrimalExtender*&          primal_extender
00382       )
00383    { 
00384       typename std::vector<DualBlockType>::iterator it;
00385       typename SubFactorListType::const_iterator lit;
00386    
00387       for(size_t i=0; i<numDualsMinimal_; ++i){
00388          mem_[i] = dual[i];
00389       }
00390       for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
00391          const size_t numDuals = (*it).duals_.size();
00392          (*it).duals_[numDuals-1] = -(*it).duals_[0];
00393          for(size_t i=1; i<numDuals-1;++i){
00394             (*it).duals_[numDuals-1] -= (*it).duals_[i];
00395          }
00396       } 
00397       // Solve Subproblems 
00398       objective_value=0;
00399       primalTimer_.tic();
00400    
00401 //#ifdef WITH_OPENMP 
00402 //      omp_set_num_threads(para_.numberOfThreads_);
00403 //#pragma omp parallel for
00404 //#endif
00405       for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){ 
00406          InfType inf(subGm_[subModelId],para_.subPara_);
00407          inf.infer(); 
00408          inf.arg(subStates_[subModelId]); 
00409       } 
00410       primalTimer_.toc();
00411       primalTime_ +=  primalTimer_.elapsedTime();
00412 
00413       // Calculate lower-bound
00414       std::vector<LabelType> temp;  
00415       std::vector<LabelType> temp2; 
00416       const std::vector<SubVariableListType>& subVariableLists = para_.decomposition_.getVariableLists();
00417       (*this).template getBounds<AccumulationType>(subStates_, subVariableLists, lowerBound_, upperBound_, temp);
00418       acNegLowerBound_(-lowerBound_,temp2);
00419       acUpperBound_(upperBound_, temp);
00420       objective_value = -lowerBound_;
00421 
00422       // Store subgradient
00423       std::vector<size_t> s;
00424       mem2_.assign(mem2_.size(),0);
00425       for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
00426          const size_t numDuals = (*it).duals_.size();
00427          lit = (*((*it).subFactorList_)).begin();
00428          s.resize((*lit).subIndices_.size());
00429          for(size_t i=0; i<numDuals; ++i){
00430             getPartialSubGradient((*lit).subModelId_, (*lit).subIndices_, s); 
00431             ++lit;              
00432             (*it).duals2_[i](s.begin()) += -1.0;
00433          }
00434          for(size_t i=0; i<numDuals-1; ++i){ 
00435             (*it).duals2_[i] -=  (*it).duals2_[numDuals-1] ;
00436          }   
00437       }  
00438 
00439       //construct first subgradient and objective value
00440       ConicBundle::PrimalDVector h(numDualsMinimal_,0);
00441       cut_vals.push_back(objective_value);
00442       for(size_t i=0; i<numDualsMinimal_; ++i){
00443          h[i] = mem2_[i];
00444       }
00445       subgradients.push_back(h);
00446       //  primal_solutions.push_back(h.clone_primal_data());
00447       return 0;
00448    }
00449 
00450 
00451 
00452    template <class GM, class INF, class DUALBLOCK> 
00453    template <class T_IndexType, class T_LabelType>
00454    inline void DualDecompositionBundle<GM,INF,DUALBLOCK>::getPartialSubGradient 
00455    ( 
00456       const size_t                             subModelId,
00457       const std::vector<T_IndexType>&    subIndices, 
00458       std::vector<T_LabelType> &                 s
00459    )const 
00460    {
00461       OPENGM_ASSERT(subIndices.size() == s.size());
00462       for(size_t n=0; n<s.size(); ++n){
00463          s[n] = subStates_[subModelId][subIndices[n]];
00464       }
00465    } 
00466 
00467    template <class GM, class INF, class DUALBLOCK> 
00468    double DualDecompositionBundle<GM,INF,DUALBLOCK>::euclideanSubGradientNorm()
00469    { 
00470       double norm = 0;
00471       std::vector<size_t> s,s2;
00472       typename std::vector<DUALBLOCK>::const_iterator it;
00473       typename SubFactorListType::const_iterator                  lit;
00474       for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
00475          const size_t numDuals = (*it).duals_.size(); 
00476          const SubFactorType& sf = (*((*it).subFactorList_)).back();
00477          lit = (*((*it).subFactorList_)).begin();
00478          s.resize((*lit).subIndices_.size());
00479          s2.resize((*lit).subIndices_.size());
00480          getPartialSubGradient(sf.subModelId_, sf.subIndices_, s2);   
00481          for(size_t i=0; i<numDuals-1; ++i){
00482             getPartialSubGradient((*lit).subModelId_, (*lit).subIndices_, s); 
00483             ++lit; 
00484             if(s!=s2)
00485                norm += 2;
00486          }
00487       }
00488       return sqrt(norm);
00489    } 
00490 
00491 
00492 
00493 }
00494 #endif // WITH_CONICBUNDLE   
00495 #endif
00496 
 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