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
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
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
00156 visitor.begin(*this,this->value(),this->bound());
00157
00158 for(size_t iteration=0; iteration<para_.maximalNumberOfIterations_; ++iteration){
00159
00160
00161 primalTime_=0;
00162 primalTimer_.tic();
00163
00164
00165
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
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
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();
00196 stepsize = para_.getStepsize(iteration,primalDualGap,subgradientNorm);
00197
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
00226
00227
00228
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
00237 visitor.end((*this), acUpperBound_.value(), -acNegLowerBound_.value());
00238 return NORMAL;
00239 }
00240 }
00241
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