OpenGM  2.3.x
Discrete Graphical Model Library
dualdecomposition_subgradient.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_DUALDDECOMPOSITION_SUBGRADIENT_HXX
3 #define OPENGM_DUALDDECOMPOSITION_SUBGRADIENT_HXX
4 
5 #include <vector>
6 #include <list>
7 #include <typeinfo>
8 
12 
13 namespace opengm {
14 
22  template<class GM, class INF, class DUALBLOCK >
24  : public Inference<GM,typename INF::AccumulationType>, public DualDecompositionBase<GM, DUALBLOCK >
25  {
26  public:
27  typedef GM GmType;
28  typedef GM GraphicalModelType;
29  typedef typename INF::AccumulationType AccumulationType;
34 
35  typedef INF InfType;
36  typedef DUALBLOCK DualBlockType;
38 
39  typedef typename DualBlockType::DualVariableType DualVariableType;
40  typedef typename DDBaseType::SubGmType SubGmType;
41  typedef typename DualBlockType::SubFactorType SubFactorType;
42  typedef typename DualBlockType::SubFactorListType SubFactorListType;
45 
47  public:
49  typename InfType::Parameter subPara_;
52  Parameter() : useAdaptiveStepsize_(false), useProjectedAdaptiveStepsize_(false){};
53  };
54 
60 
61  DualDecompositionSubGradient(const GmType&);
62  DualDecompositionSubGradient(const GmType&, const Parameter&);
63  virtual std::string name() const {return "DualDecompositionSubGradient";};
64  virtual const GmType& graphicalModel() const {return gm_;};
65  virtual InferenceTermination infer();
66  template <class VISITOR> InferenceTermination infer(VISITOR&);
67  virtual ValueType bound() const;
68  virtual ValueType value() const;
69  virtual InferenceTermination arg(std::vector<LabelType>&, const size_t = 1)const;
70 
71  private:
72  virtual void allocate();
73  virtual DualDecompositionBaseParameter& parameter();
74  void dualStep(const size_t);
75  template <class T_IndexType, class T_LabelType>
76  void getPartialSubGradient(const size_t, const std::vector<T_IndexType>&, std::vector<T_LabelType>&)const;
77  double euclideanProjectedSubGradientNorm();
78 
79  // Members
80  std::vector<std::vector<LabelType> > subStates_;
81 
82  Accumulation<ValueType,LabelType,AccumulationType> acUpperBound_;
83  Accumulation<ValueType,LabelType,AccumulationType> acNegLowerBound_;
84  ValueType upperBound_;
85  ValueType lowerBound_;
86  std::vector<ValueType> values_;
87 
88  Parameter para_;
89  std::vector<ValueType> mem_;
90 
91  opengm::Timer primalTimer_;
92  opengm::Timer dualTimer_;
93  double primalTime_;
94  double dualTime_;
95 
96  };
97 
98 //**********************************************************************************
99  template<class GM, class INF, class DUALBLOCK>
102  {
103  this->init(para_);
104  subStates_.resize(subGm_.size());
105  for(size_t i=0; i<subGm_.size(); ++i)
106  subStates_[i].resize(subGm_[i].numberOfVariables());
107  }
108 
109  template<class GM, class INF, class DUALBLOCK>
111  : DualDecompositionBase<GmType, DualBlockType >(gm),para_(para)
112  {
113  this->init(para_);
114  subStates_.resize(subGm_.size());
115  for(size_t i=0; i<subGm_.size(); ++i)
116  subStates_[i].resize(subGm_[i].numberOfVariables());
117  }
118 
119 
121 
122  template <class GM, class INF, class DUALBLOCK>
124  {
125  if(DDIsView<DualVariableType>::isView()){
126  mem_.resize(numDualsOvercomplete_,0.0);
127  }
128  else
129  mem_.resize(1,0.0);
130  //std::cout << mem_.size() <<std::flush;
131  ValueType *data = &mem_[0];
132  for(typename std::vector<DualBlockType>::iterator it=dualBlocks_.begin(); it!=dualBlocks_.end(); ++it){
133  for(size_t i=0; i<(*it).duals_.size(); ++i){
134  DualVariableType& dv = (*it).duals_[i];
135  DualVarAssign(dv, data);
136  if(DDIsView<DualVariableType>::isView())
137  data += dv.size();
138  }
139  }
140  }
141  template <class GM, class INF, class DUALBLOCK>
142  DualDecompositionBaseParameter& DualDecompositionSubGradient<GM,INF,DUALBLOCK>::parameter()
143  {
144  return para_;
145  }
146 
148  template<class GM, class INF, class DUALBLOCK>
151  {
152  EmptyVisitorType visitor;
153  return infer(visitor);
154  }
155  template<class GM, class INF, class DUALBLOCK>
156  template<class VISITOR>
158  infer(VISITOR& visitor)
159  {
160  std::cout.precision(15);
161  //visitor.startInference();
162  visitor.begin(*this);
163 
164  for(size_t iteration=0; iteration<para_.maximalNumberOfIterations_; ++iteration){
165 
166  // Solve Subproblems
169  //omp_set_num_threads(para_.numberOfThreads_);
170 
171  //#pragma omp parallel for
172  for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){
173  InfType inf(subGm_[subModelId],para_.subPara_);
174  inf.infer();
175  inf.arg(subStates_[subModelId]);
176  }
178 
180  // Calculate lower-bound
181  std::vector<LabelType> temp;
182  std::vector<LabelType> temp2;
183  const std::vector<SubVariableListType>& subVariableLists = para_.decomposition_.getVariableLists();
184  (*this).template getBounds<AccumulationType>(subStates_, subVariableLists, lowerBound_, upperBound_, temp);
185  acNegLowerBound_(-lowerBound_,temp2);
186  acUpperBound_(upperBound_, temp);
187 
188  //dualStep
189  double stepsize;
190  if(para_.useAdaptiveStepsize_){
191  stepsize = para_.stepsizeStride_ * fabs(acUpperBound_.value() - lowerBound_)
192  /(*this).subGradientNorm(1);
193  }
194  else if(para_.useProjectedAdaptiveStepsize_){
195  double subgradientNorm = euclideanProjectedSubGradientNorm();
196  stepsize = para_.stepsizeStride_ * fabs(acUpperBound_.value() - lowerBound_)
197  /subgradientNorm/subgradientNorm;
198  }
199  else{
200  double primalDualGap = fabs(acUpperBound_.value() + acNegLowerBound_.value());
201  double subgradientNorm = euclideanProjectedSubGradientNorm();//(*this).subGradientNorm(1);
202  stepsize = para_.getStepsize(iteration,primalDualGap,subgradientNorm);
203 // std::cout << stepsize << std::endl;
204  }
205 
206  if(typeid(AccumulationType) == typeid(opengm::Minimizer))
207  stepsize *=1;
208  else
209  stepsize *= -1;
210 
211  std::vector<size_t> s;
212  for(typename std::vector<DualBlockType>::const_iterator it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
213  const size_t numDuals = (*it).duals_.size();
214  typename SubFactorListType::const_iterator lit = (*((*it).subFactorList_)).begin();
215  s.resize((*lit).subIndices_.size());
216  for(size_t i=0; i<numDuals; ++i){
217  getPartialSubGradient<size_t>((*lit).subModelId_, (*lit).subIndices_, s);
218  ++lit;
219  (*it).duals_[i](s.begin()) += stepsize;
220  for(size_t j=0; j<numDuals; ++j){
221  (*it).duals_[j](s.begin()) -= stepsize/numDuals;
222  }
223  }
224  //(*it).test();
225  }
227 
230  if(visitor(*this)!= 0){
231  break;
232  };
233  //visitor((*this), lowerBound_, -acNegLowerBound_.value(), upperBound_, acUpperBound_.value(), primalTime_, dualTime_);
234 
235 
236  // Test for Convergence
237  ValueType o;
238  AccumulationType::iop(0.0001,-0.0001,o);
239  OPENGM_ASSERT(AccumulationType::bop(lowerBound_, upperBound_+o));
240  OPENGM_ASSERT(AccumulationType::bop(-acNegLowerBound_.value(), acUpperBound_.value()+o));
241 
242  if( fabs(acUpperBound_.value() + acNegLowerBound_.value()) <= para_.minimalAbsAccuracy_
243  || fabs((acUpperBound_.value()+ acNegLowerBound_.value())/acUpperBound_.value()) <= para_.minimalRelAccuracy_){
244  //std::cout << "bound reached ..." <<std::endl;
245  visitor.end(*this);
246  //visitor.end((*this), acUpperBound_.value(), -acNegLowerBound_.value());
247  return NORMAL;
248  }
249  }
250  //std::cout << "maximal number of dual steps ..." <<std::endl;
251  visitor.end(*this);
252 
253  return NORMAL;
254  }
255 
256 
257  template<class GM, class INF, class DUALBLOCK>
259  arg(std::vector<LabelType>& conf, const size_t n)const
260  {
261  if(n!=1){
262  return UNKNOWN;
263  }
264  else{
265  acUpperBound_.state(conf);
266  return NORMAL;
267  }
268  }
269 
270  template<class GM, class INF, class DUALBLOCK>
272  {
273  return acUpperBound_.value();
274  }
275 
276  template<class GM, class INF, class DUALBLOCK>
278  {
279  return -acNegLowerBound_.value();
280  }
281 
282 
284 
285  template <class GM, class INF, class DUALBLOCK>
287  {
288 
289  }
290 
291  template <class GM, class INF, class DUALBLOCK>
292  template <class T_IndexType, class T_LabelType>
293  inline void DualDecompositionSubGradient<GM,INF,DUALBLOCK>::getPartialSubGradient
294  (
295  const size_t subModelId,
296  const std::vector<T_IndexType>& subIndices,
297  std::vector<T_LabelType> & s
298  )const
299  {
300  OPENGM_ASSERT(subIndices.size() == s.size());
301  for(size_t n=0; n<s.size(); ++n){
302  s[n] = subStates_[subModelId][subIndices[n]];
303  }
304  }
305 
306  template <class GM, class INF, class DUALBLOCK>
307  double DualDecompositionSubGradient<GM,INF,DUALBLOCK>::euclideanProjectedSubGradientNorm()
308  {
309  double norm = 0;
310  std::vector<LabelType> s;
312  typename std::vector<DUALBLOCK>::const_iterator it;
313  typename SubFactorListType::const_iterator lit;
314  for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
315  const size_t numDuals = (*it).duals_.size();
316  marray::Marray<double> M( (*it).duals_[0].shapeBegin(), (*it).duals_[0].shapeEnd() ,0.0);
317  lit = (*((*it).subFactorList_)).begin();
318  s.resize((*lit).subIndices_.size());
319  for(size_t i=0; i<numDuals; ++i){
320  getPartialSubGradient((*lit).subModelId_, (*lit).subIndices_, s);
321  ++lit;
322  M(s.begin()) += 1;
323  }
324  for(size_t i=0; i<M.size(); ++i){
325  norm += M(i) * pow(1.0 - M(i)/numDuals,2);
326  norm += (numDuals-M(i)) * pow( M(i)/numDuals,2);
327  }
328  }
329  return sqrt(norm);
330  }
331 
332 
333 }
334 
335 #endif
336 
InfType::Parameter subPara_
Parameter for Subproblems.
The OpenGM namespace.
Definition: config.hxx:43
DecompositionType::SubVariable SubVariableType
virtual InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
output a solution
DecompositionType::SubVariableListType SubVariableListType
DualDecompositionBase< GmType, DualBlockType > DDBaseType
Platform-independent runtime measurements.
Definition: timer.hxx:29
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
visitors::TimingVisitor< DualDecompositionSubGradient< GM, INF, DUALBLOCK > > TimingVisitorType
void init(DualDecompositionBaseParameter &)
DDBaseType::SubVariableListType SubVariableListType
Dual-Decomposition-Subgradient Inference based on dual decomposition using sub-gradient descent Refe...
void DualVarAssign(DUALVAR &dv, T *t)
const size_t size() const
Get the number of data items.
Definition: marray.hxx:1698
GraphicalModelType::ValueType ValueType
Definition: inference.hxx:41
Inference algorithm interface.
Definition: inference.hxx:34
DualBlockType::SubFactorListType SubFactorListType
virtual ValueType value() const
return the solution (value)
Runtime-flexible multi-dimensional array.
Definition: marray.hxx:52
DualBlockType::DualVariableType DualVariableType
Minimization as a unary accumulation.
Definition: minimizer.hxx:12
visitors::EmptyVisitor< DualDecompositionSubGradient< GM, INF, DUALBLOCK > > EmptyVisitorType
virtual ValueType bound() const
return a bound on the solution
visitors::VerboseVisitor< DualDecompositionSubGradient< GM, INF, DUALBLOCK > > VerboseVisitorType
A framework for inference algorithms based on Lagrangian decomposition.
InferenceTermination
Definition: inference.hxx:24