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 
46  template<class _GM>
47  struct RebindGm{
48  typedef typename INF:: template RebindGm<_GM>::type RebindedInf;
50  };
51 
52  template<class _GM,class _ACC>
54  typedef typename INF:: template RebindGm<_GM,_ACC>::type RebindedInf;
56  };
57 
58 
60  public:
62  typename InfType::Parameter subPara_;
65  Parameter() : useAdaptiveStepsize_(false), useProjectedAdaptiveStepsize_(false){};
66 
67  template<class P>
68  Parameter(const P & p)
69  : subPara_(p.subPara_),
70  useAdaptiveStepsize_(p.useAdaptiveStepsize_),
71  useProjectedAdaptiveStepsize_(p.useProjectedAdaptiveStepsize_){
72 
73  }
74  };
75 
81 
82  DualDecompositionSubGradient(const GmType&);
83  DualDecompositionSubGradient(const GmType&, const Parameter&);
84  virtual std::string name() const {return "DualDecompositionSubGradient";};
85  virtual const GmType& graphicalModel() const {return gm_;};
86  virtual InferenceTermination infer();
87  template <class VISITOR> InferenceTermination infer(VISITOR&);
88  virtual ValueType bound() const;
89  virtual ValueType value() const;
90  virtual InferenceTermination arg(std::vector<LabelType>&, const size_t = 1)const;
91 
92  private:
93  virtual void allocate();
94  virtual DualDecompositionBaseParameter& parameter();
95  void dualStep(const size_t);
96  template <class T_IndexType, class T_LabelType>
97  void getPartialSubGradient(const size_t, const std::vector<T_IndexType>&, std::vector<T_LabelType>&)const;
98  double euclideanProjectedSubGradientNorm();
99 
100  // Members
101  std::vector<std::vector<LabelType> > subStates_;
102 
103  Accumulation<ValueType,LabelType,AccumulationType> acUpperBound_;
104  Accumulation<ValueType,LabelType,AccumulationType> acNegLowerBound_;
105  ValueType upperBound_;
106  ValueType lowerBound_;
107  std::vector<ValueType> values_;
108 
109  Parameter para_;
110  std::vector<ValueType> mem_;
111 
112  opengm::Timer primalTimer_;
113  opengm::Timer dualTimer_;
114  double primalTime_;
115  double dualTime_;
116 
117  };
118 
119 //**********************************************************************************
120  template<class GM, class INF, class DUALBLOCK>
123  {
124  this->init(para_);
125  subStates_.resize(subGm_.size());
126  for(size_t i=0; i<subGm_.size(); ++i)
127  subStates_[i].resize(subGm_[i].numberOfVariables());
128  }
129 
130  template<class GM, class INF, class DUALBLOCK>
132  : DualDecompositionBase<GmType, DualBlockType >(gm),para_(para)
133  {
134  this->init(para_);
135  subStates_.resize(subGm_.size());
136  for(size_t i=0; i<subGm_.size(); ++i)
137  subStates_[i].resize(subGm_[i].numberOfVariables());
138  }
139 
140 
142 
143  template <class GM, class INF, class DUALBLOCK>
145  {
146  if(DDIsView<DualVariableType>::isView()){
147  mem_.resize(numDualsOvercomplete_,0.0);
148  }
149  else
150  mem_.resize(1,0.0);
151  //std::cout << mem_.size() <<std::flush;
152  ValueType *data = &mem_[0];
153  for(typename std::vector<DualBlockType>::iterator it=dualBlocks_.begin(); it!=dualBlocks_.end(); ++it){
154  for(size_t i=0; i<(*it).duals_.size(); ++i){
155  DualVariableType& dv = (*it).duals_[i];
156  DualVarAssign(dv, data);
157  if(DDIsView<DualVariableType>::isView())
158  data += dv.size();
159  }
160  }
161  }
162  template <class GM, class INF, class DUALBLOCK>
164  {
165  return para_;
166  }
167 
169  template<class GM, class INF, class DUALBLOCK>
172  {
173  EmptyVisitorType visitor;
174  return infer(visitor);
175  }
176  template<class GM, class INF, class DUALBLOCK>
177  template<class VISITOR>
179  infer(VISITOR& visitor)
180  {
181  std::cout.precision(15);
182  //visitor.startInference();
183  visitor.begin(*this);
184 
185  for(size_t iteration=0; iteration<para_.maximalNumberOfIterations_; ++iteration){
186 
187  // Solve Subproblems
190  //omp_set_num_threads(para_.numberOfThreads_);
191 
192  //#pragma omp parallel for
193  for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){
194  InfType inf(subGm_[subModelId],para_.subPara_);
195  inf.infer();
196  inf.arg(subStates_[subModelId]);
197  }
199 
201  // Calculate lower-bound
202  std::vector<LabelType> temp;
203  std::vector<LabelType> temp2;
204  const std::vector<SubVariableListType>& subVariableLists = para_.decomposition_.getVariableLists();
205  (*this).template getBounds<AccumulationType>(subStates_, subVariableLists, lowerBound_, upperBound_, temp);
206  acNegLowerBound_(-lowerBound_,temp2);
207  acUpperBound_(upperBound_, temp);
208 
209  //dualStep
210  double stepsize;
211  if(para_.useAdaptiveStepsize_){
212  stepsize = para_.stepsizeStride_ * fabs(acUpperBound_.value() - lowerBound_)
213  /(*this).subGradientNorm(1);
214  }
215  else if(para_.useProjectedAdaptiveStepsize_){
216  double subgradientNorm = euclideanProjectedSubGradientNorm();
217  stepsize = para_.stepsizeStride_ * fabs(acUpperBound_.value() - lowerBound_)
218  /subgradientNorm/subgradientNorm;
219  }
220  else{
221  double primalDualGap = fabs(acUpperBound_.value() + acNegLowerBound_.value());
222  double subgradientNorm = euclideanProjectedSubGradientNorm();//(*this).subGradientNorm(1);
223  stepsize = para_.getStepsize(iteration,primalDualGap,subgradientNorm);
224 // std::cout << stepsize << std::endl;
225  }
226 
227  if(typeid(AccumulationType) == typeid(opengm::Minimizer))
228  stepsize *=1;
229  else
230  stepsize *= -1;
231 
232  std::vector<size_t> s;
233  for(typename std::vector<DualBlockType>::const_iterator it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
234  const size_t numDuals = (*it).duals_.size();
235  typename SubFactorListType::const_iterator lit = (*((*it).subFactorList_)).begin();
236  s.resize((*lit).subIndices_.size());
237  for(size_t i=0; i<numDuals; ++i){
238  getPartialSubGradient<size_t>((*lit).subModelId_, (*lit).subIndices_, s);
239  ++lit;
240  (*it).duals_[i](s.begin()) += stepsize;
241  for(size_t j=0; j<numDuals; ++j){
242  (*it).duals_[j](s.begin()) -= stepsize/numDuals;
243  }
244  }
245  //(*it).test();
246  }
248 
251  if(visitor(*this)!= 0){
252  break;
253  };
254  //visitor((*this), lowerBound_, -acNegLowerBound_.value(), upperBound_, acUpperBound_.value(), primalTime_, dualTime_);
255 
256 
257  // Test for Convergence
258  ValueType o;
259  AccumulationType::iop(0.0001,-0.0001,o);
260  OPENGM_ASSERT(AccumulationType::bop(lowerBound_, upperBound_+o));
261  OPENGM_ASSERT(AccumulationType::bop(-acNegLowerBound_.value(), acUpperBound_.value()+o));
262 
263  if( fabs(acUpperBound_.value() + acNegLowerBound_.value()) <= para_.minimalAbsAccuracy_
264  || fabs((acUpperBound_.value()+ acNegLowerBound_.value())/acUpperBound_.value()) <= para_.minimalRelAccuracy_){
265  //std::cout << "bound reached ..." <<std::endl;
266  visitor.end(*this);
267  //visitor.end((*this), acUpperBound_.value(), -acNegLowerBound_.value());
268  return NORMAL;
269  }
270  }
271  //std::cout << "maximal number of dual steps ..." <<std::endl;
272  visitor.end(*this);
273 
274  return NORMAL;
275  }
276 
277 
278  template<class GM, class INF, class DUALBLOCK>
280  arg(std::vector<LabelType>& conf, const size_t n)const
281  {
282  if(n!=1){
283  return UNKNOWN;
284  }
285  else{
286  acUpperBound_.state(conf);
287  return NORMAL;
288  }
289  }
290 
291  template<class GM, class INF, class DUALBLOCK>
293  {
294  return acUpperBound_.value();
295  }
296 
297  template<class GM, class INF, class DUALBLOCK>
299  {
300  return -acNegLowerBound_.value();
301  }
302 
303 
305 
306  template <class GM, class INF, class DUALBLOCK>
308  {
309 
310  }
311 
312  template <class GM, class INF, class DUALBLOCK>
313  template <class T_IndexType, class T_LabelType>
315  (
316  const size_t subModelId,
317  const std::vector<T_IndexType>& subIndices,
318  std::vector<T_LabelType> & s
319  )const
320  {
321  OPENGM_ASSERT(subIndices.size() == s.size());
322  for(size_t n=0; n<s.size(); ++n){
323  s[n] = subStates_[subModelId][subIndices[n]];
324  }
325  }
326 
327  template <class GM, class INF, class DUALBLOCK>
329  {
330  double norm = 0;
331  std::vector<LabelType> s;
333  typename std::vector<DUALBLOCK>::const_iterator it;
334  typename SubFactorListType::const_iterator lit;
335  for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
336  const size_t numDuals = (*it).duals_.size();
337  marray::Marray<double> M( (*it).duals_[0].shapeBegin(), (*it).duals_[0].shapeEnd() ,0.0);
338  lit = (*((*it).subFactorList_)).begin();
339  s.resize((*lit).subIndices_.size());
340  for(size_t i=0; i<numDuals; ++i){
341  getPartialSubGradient((*lit).subModelId_, (*lit).subIndices_, s);
342  ++lit;
343  M(s.begin()) += 1;
344  }
345  for(size_t i=0; i<M.size(); ++i){
346  norm += M(i) * pow(1.0 - M(i)/numDuals,2);
347  norm += (numDuals-M(i)) * pow( M(i)/numDuals,2);
348  }
349  }
350  return sqrt(norm);
351  }
352 
353 
354 }
355 
356 #endif
357 
double minimalRelAccuracy_
the relative accuracy that has to be guaranteed to stop with an approximate solution (set 0 for optim...
virtual ValueType value() const
return the solution (value)
virtual ValueType bound() const
return a bound on the solution
virtual InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
InfType::Parameter subPara_
Parameter for Subproblems.
The OpenGM namespace.
Definition: config.hxx:43
std::vector< DualBlockType > dualBlocks_
DecompositionType::SubVariable SubVariableType
DecompositionType::SubVariableListType SubVariableListType
DualDecompositionBase< GmType, DualBlockType > DDBaseType
Platform-independent runtime measurements.
Definition: timer.hxx:29
double minimalAbsAccuracy_
the absolut accuracy that has to be guaranteed to stop with an approximate solution (set 0 for optima...
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
visitors::TimingVisitor< DualDecompositionSubGradient< GM, INF, DUALBLOCK > > TimingVisitorType
GraphicalModelDecomposition decomposition_
decomposition of the model (needs to fit to the model structure)
void init(DualDecompositionBaseParameter &)
DualDecompositionSubGradient< _GM, RebindedInf, DUALBLOCK > type
DDBaseType::SubVariableListType SubVariableListType
Dual-Decomposition-Subgradient Inference based on dual decomposition using sub-gradient descent Refe...
void DualVarAssign(DUALVAR &dv, T *t)
GraphicalModelType::ValueType ValueType
Definition: inference.hxx:50
Inference algorithm interface.
Definition: inference.hxx:43
DualBlockType::SubFactorListType SubFactorListType
double getStepsize(size_t iteration, double primalDualGap, double subgradientNorm)
DualDecompositionSubGradient< _GM, RebindedInf, DUALBLOCK > type
Runtime-flexible multi-dimensional array.
Definition: marray.hxx:52
DualBlockType::DualVariableType DualVariableType
DualBlockType::DualVariableType DualVariableType
Minimization as a unary accumulation.
Definition: minimizer.hxx:12
size_t maximalNumberOfIterations_
maximum number of dual iterations
visitors::EmptyVisitor< DualDecompositionSubGradient< GM, INF, DUALBLOCK > > EmptyVisitorType
visitors::VerboseVisitor< DualDecompositionSubGradient< GM, INF, DUALBLOCK > > VerboseVisitorType
A framework for inference algorithms based on Lagrangian decomposition.
const size_t size() const
Get the number of data items.
Definition: marray.hxx:1698
InferenceTermination
Definition: inference.hxx:24