OpenGM  2.3.x
Discrete Graphical Model Library
dualdecomposition_base.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_DUALDECOMPOSITION_BASE_HXX
3 #define OPENGM_DUALDECOMPOSITION_BASE_HXX
4 
5 #include <vector>
6 #include <set>
7 #include <string>
8 #include <iostream>
9 #include <cmath>
10 #include <limits>
11 
12 #include "opengm/opengm.hxx"
20 
21 namespace opengm {
22 
24  public:
27 
31  GraphicalModelDecomposition decomposition_;
33  std::vector<std::vector<size_t> > subFactors_;
35  std::vector<std::set<size_t> > subVariables_;
51  size_t k_;
52 
53  // Update parameters
54  double stepsizeStride_; //updateStride_;
55  double stepsizeScale_; //updateScale_;
56  double stepsizeExponent_; //updateExponent_;
57  double stepsizeMin_; //updateMin_;
58  double stepsizeMax_; //updateMax_;
61  // DualUpdateId dualUpdateId_ = ADAPTIVE;
62 
64  decompositionId_(SPANNINGTREES),
65  maximalDualOrder_(std::numeric_limits<size_t>::max()),
66  numberOfBlocks_(2),
67  maximalNumberOfIterations_(100),
68  minimalAbsAccuracy_(0.0),
69  minimalRelAccuracy_(0.0),
70  numberOfThreads_(1),
71  fillSubLabelings_(false),
72  stepsizeStride_(1),
73  stepsizeScale_(1),
74  stepsizeExponent_(0.5),
75  stepsizeMin_(0),
76  stepsizeMax_(std::numeric_limits<double>::infinity()),
77  stepsizePrimalDualGapStride_(false),
78  stepsizeNormalizedSubgradient_(false),
79  k_(4)
80  {};
81 
82  double getStepsize(size_t iteration, double primalDualGap, double subgradientNorm){
83  OPENGM_ASSERT(iteration>=0);
84  double stepsize = stepsizeStride_;
85  if(stepsizePrimalDualGapStride_){
86  stepsize *= fabs(primalDualGap) / subgradientNorm / subgradientNorm;
87  }
88  else{
89  stepsize /= (1+std::pow( stepsizeScale_*(double)(iteration),stepsizeExponent_));
90  if(stepsizeNormalizedSubgradient_)
91  stepsize /= subgradientNorm;
92  }
93  //stepsize /= (1+std::pow( stepsizeScale_*(double)(iteration),stepsizeExponent_));
94  //stepsize = std::max(std::min(stepsizeMax_,stepsize),stepsizeMin_);
95  //if(stepsizeNormalizedSubgradient_)
96  // stepsize /= subgradientNorm;
97  return stepsize;
98  }
99  };
100 
102  template<class DD>
104  public:
105  typedef DD DDType;
106  typedef typename DDType::ValueType ValueType;
107 
109  const DDType& dd,
110  const ValueType bound, const ValueType bestBound,
111  const ValueType value, const ValueType bestValue,
112  double primalTime, double dualTime
113  )
114  {;}
115  void startInference(){;}
116  };
117 
119  template<class DD>
121  public:
122  typedef DD DDType;
123  typedef typename DDType::ValueType ValueType;
124 
126  const DDType& dd,
127  const ValueType bound, const ValueType bestBound,
128  const ValueType value, const ValueType bestValue,
129  const double primalTime, const double dualTime
130  )
131  {
132  totalTimer_.toc();
133  if(times_.size()==0)
134  times_.push_back(totalTimer_.elapsedTime());
135  else
136  times_.push_back(times_.back() + totalTimer_.elapsedTime());
137  values_.push_back(value);
138  bounds_.push_back(bound);
139  primalTimes_.push_back(primalTime);
140  dualTimes_.push_back(dualTime);
141 /*
142  std::cout << "(" << values_.size() << " / "<< times_.back() <<" ) "
143  << bound << " <= " << bestBound
144  << " <= " << "E"
145  << " <= " << bestValue << " <= "
146  << value << std::endl;
147 */
148  totalTimer_.tic();
149  }
150  void startInference(){totalTimer_.tic();}
151  const std::vector<ValueType>& values(){return values_;}
152  const std::vector<ValueType>& bounds(){return bounds_;}
153  const std::vector<double>& times(){return times_;}
154  const std::vector<double>& primalTimes(){return primalTimes_;}
155  const std::vector<double>& dualTimes(){return dualTimes_;}
156 
157  private:
158  std::vector<ValueType> values_;
159  std::vector<ValueType> bounds_;
160  std::vector<double> times_;
161  std::vector<double> primalTimes_;
162  std::vector<double> dualTimes_;
163  opengm::Timer totalTimer_;
164  };
165 
167  template<class GM, class DUALBLOCK>
169  {
170  public:
171  typedef GM GmType;
172  typedef GM GraphicalModelType;
173  typedef DUALBLOCK DualBlockType;
174  typedef typename DualBlockType::DualVariableType DualVariableType;
178 
179 
180  typedef GraphicalModelDecomposition DecompositionType;
181  typedef typename DecompositionType::SubVariable SubVariableType;
182  typedef typename DecompositionType::SubVariableListType SubVariableListType;
183  typedef typename DecompositionType::SubFactor SubFactorType;
184  typedef typename DecompositionType::SubFactorListType SubFactorListType;
185 
186 
187  DualDecompositionBase(const GmType&);
189  const SubGmType& subModel(size_t subModelId) const {return subGm_[subModelId];};
190 
191  protected:
192  template<class ITERATOR> void addDualBlock(const SubFactorListType&,ITERATOR,ITERATOR);
193  std::vector<DualVariableType*> getDualPointers(size_t);
194  template<class ACC> void getBounds(const std::vector<std::vector<LabelType> >&, const std::vector<SubVariableListType>&, ValueType&, ValueType&, std::vector<LabelType>&);
195  double subGradientNorm(double L=1) const;
197  virtual void allocate() = 0;
198 
199  const GmType& gm_;
200  std::vector<SubGmType> subGm_;
201  std::vector<DualBlockType> dualBlocks_;
204  std::vector<Tribool> modelWithSameVariables_;
205  };
206 
208  template<class DUALVAR> struct DDIsView {static bool isView(){return false;}};
209  template<> struct DDIsView<marray::View<double,false> > {static bool isView(){return true;}};
210  template<> struct DDIsView<marray::View<double,true> > {static bool isView(){return true;}};
211  template<> struct DDIsView<marray::View<float,false> > {static bool isView(){return true;}};
212  template<> struct DDIsView<marray::View<float,true> > {static bool isView(){return true;}};
214 
216 
217  template<class DUALVAR, class T>
218  void DualVarAssign(DUALVAR& dv,T* t)
219  {
220  }
221 
222  template <class T>
224  {
225  dv.assign( dv.shapeBegin(),dv.shapeEnd(),t);
226  }
227 
228  template<class GM, class DUALBLOCK>
230  {}
231 
232  template<class GM, class DUALBLOCK>
234  {
236  opengm::GraphicalModelDecomposer<GmType> decomposer;
237  para.decomposition_ = decomposer.decomposeIntoTree(gm_);
238  para.decomposition_.reorder();
239  para.decomposition_.complete();
240  para.maximalDualOrder_ = 1;
241  }
243  opengm::GraphicalModelDecomposer<GmType> decomposer;
244  para.decomposition_ = decomposer.decomposeIntoSpanningTrees(gm_);
245  para.decomposition_.reorder();
246  para.decomposition_.complete();
247  para.maximalDualOrder_ = 1;
248  }
250  opengm::GraphicalModelDecomposer<GmType> decomposer;
251  para.decomposition_ = decomposer.decomposeIntoClosedBlocks(gm_,para.numberOfBlocks_);
252  para.decomposition_.reorder();
253  para.decomposition_.complete();
254  para.maximalDualOrder_ = 1;
255  }
257  opengm::GraphicalModelDecomposer<GmType> decomposer;
258  para.decomposition_ = decomposer.decomposeIntoKFans(gm_,para.k_);
259  para.decomposition_.reorder();
260  para.decomposition_.complete();
261  para.maximalDualOrder_ = 1;
262  }
264  opengm::GraphicalModelDecomposer<GmType> decomposer;
265  para.decomposition_ = decomposer.decomposeManual(gm_,para.subFactors_);
266  para.decomposition_.reorder();
267  para.decomposition_.complete();
268  para.maximalDualOrder_ = 1;
269  }
271  opengm::GraphicalModelDecomposer<GmType> decomposer;
272  para.decomposition_ = decomposer.decomposeIntoClosedBlocks(gm_,para.subVariables_);
273  para.decomposition_.reorder();
274  para.decomposition_.complete();
275  para.maximalDualOrder_ = 1;
276  }
278  opengm::GraphicalModelDecomposer<GmType> decomposer;
279  para.decomposition_ = decomposer.decomposeIntoOpenBlocks(gm_,para.subVariables_);
280  para.decomposition_.reorder();
281  para.decomposition_.complete();
282  para.maximalDualOrder_ = 1;
283  }
284 
285  OPENGM_ASSERT(para.decomposition_.isValid(gm_));
286 
287  //Build SubModels
288  const std::vector<SubVariableListType>& subVariableLists = para.decomposition_.getVariableLists();
289  const std::vector<SubFactorListType>& subFactorLists = para.decomposition_.getFactorLists();
290  const std::map<std::vector<size_t>,SubFactorListType>& emptySubFactorLists = para.decomposition_.getEmptyFactorLists();
291  const size_t numberOfSubModels = para.decomposition_.numberOfSubModels();
292 
293  modelWithSameVariables_.resize(numberOfSubModels,Tribool::Maybe);
294 
295  typename SubVariableListType::const_iterator it;
296  typename SubFactorListType::const_iterator it2;
297  typename SubFactorListType::const_iterator it3;
298  typename std::map<std::vector<size_t>,SubFactorListType>::const_iterator it4;
299 
300 
301  std::vector<std::vector<size_t> > numStates(numberOfSubModels);
302  for(size_t subModelId=0; subModelId<numberOfSubModels; ++subModelId){
303  numStates[subModelId].resize(para.decomposition_.numberOfSubVariables(subModelId),0);
304  }
305 
306  for(size_t varId=0; varId<gm_.numberOfVariables(); ++varId){
307  for(it = subVariableLists[varId].begin(); it!=subVariableLists[varId].end();++it){
308  numStates[(*it).subModelId_][(*it).subVariableId_] = gm_.numberOfLabels(varId);
309  }
310  }
311 
312  subGm_.resize(numberOfSubModels);
313  for(size_t subModelId=0; subModelId<numberOfSubModels; ++subModelId){
314  subGm_[subModelId] = SubGmType(opengm::DiscreteSpace<IndexType,LabelType>(numStates[subModelId].begin(),numStates[subModelId].end()));
315  }
316 
317  // Add Duals
318  numDualsOvercomplete_ = 0;
319  numDualsMinimal_ = 0;
320 
321  for(size_t factorId=0; factorId<gm_.numberOfFactors(); ++factorId){
322  if(subFactorLists[factorId].size()>1 && (gm_[factorId].numberOfVariables() <= para.maximalDualOrder_)){
323  addDualBlock(subFactorLists[factorId], gm_[factorId].shapeBegin(), gm_[factorId].shapeEnd());
324  numDualsOvercomplete_ += subFactorLists[factorId].size() * gm_[factorId].size();
325  numDualsMinimal_ += (subFactorLists[factorId].size()-1) * gm_[factorId].size();
326  }
327  }
328 
329  for(it4=emptySubFactorLists.begin() ; it4 != emptySubFactorLists.end(); it4++ ){
330  if((*it4).second.size()>1 && ((*it4).first.size() <= para.maximalDualOrder_)){
331  std::vector<size_t> shape((*it4).first.size());
332  size_t temp = 1;
333  for(size_t i=0; i<(*it4).first.size(); ++i){
334  shape[i] = gm_.numberOfLabels((*it4).first[i]);
335  temp *= gm_.numberOfLabels((*it4).first[i]);
336  }
337  numDualsOvercomplete_ += (*it4).second.size() * temp;
338  numDualsMinimal_ += ((*it4).second.size()-1) * temp;
339  addDualBlock((*it4).second,shape.begin(),shape.end());
340  }
341  }
342 
343  // Allocate memmory if this has not been done yet
344  this->allocate();
345 
346  // Add Factors
347  size_t dualCounter = 0;
348  for(size_t factorId=0; factorId<gm_.numberOfFactors(); ++factorId){
349  if(subFactorLists[factorId].size()>1 && (gm_[factorId].numberOfVariables() <= para.maximalDualOrder_)){
350  std::vector<DualVariableType*> offsets = getDualPointers(dualCounter++);
351  size_t i=0;
352  for(it2 = subFactorLists[factorId].begin(); it2!=subFactorLists[factorId].end();++it2){
353  OPENGM_ASSERT(offsets[i]->dimension() == gm_[factorId].numberOfVariables());
354  for(size_t j=0; j<offsets[i]->dimension();++j)
355  OPENGM_ASSERT(offsets[i]->shape(j) == gm_[factorId].shape(j));
356 
357  const size_t subModelId = (*it2).subModelId_;
358  const ViewFunctionType function(gm_,factorId, 1.0/subFactorLists[factorId].size(),offsets[i++]);
359  const typename SubGmType::FunctionIdentifier funcId = subGm_[subModelId].addFunction(function);
360  subGm_[subModelId].addFactor(funcId,(*it2).subIndices_.begin(),(*it2).subIndices_.end());
361  }
362  }
363  else{
364  for(it2 = subFactorLists[factorId].begin(); it2!=subFactorLists[factorId].end();++it2){
365  const size_t subModelId = (*it2).subModelId_;
366  const ViewFunctionType function(gm_,factorId, 1.0/subFactorLists[factorId].size());
367  const typename SubGmType::FunctionIdentifier funcId = subGm_[subModelId].addFunction(function);
368  subGm_[subModelId].addFactor(funcId,(*it2).subIndices_.begin(),(*it2).subIndices_.end());
369  }
370  }
371  }
372  //Add EmptyFactors
373  for(it4=emptySubFactorLists.begin() ; it4 != emptySubFactorLists.end(); it4++ ){
374  if((*it4).second.size()>1 && ((*it4).first.size() <= para.maximalDualOrder_)){
375  size_t i=0;
376  std::vector<DualVariableType*> offsets = getDualPointers(dualCounter++);
377  for(it3 = (*it4).second.begin(); it3!=(*it4).second.end();++it3){
378  const size_t subModelId = (*it3).subModelId_;
379  const ViewFunctionType function(offsets[i++]);
380  const typename SubGmType::FunctionIdentifier funcId = subGm_[subModelId].addFunction(function);
381  subGm_[subModelId].addFactor(funcId,(*it3).subIndices_.begin(),(*it3).subIndices_.end());
382  }
383  }
384  }
385  }
386 
387 
388 
389  template<class GM, class DUALBLOCK>
390  template <class ITERATOR>
391  inline void DualDecompositionBase<GM,DUALBLOCK>::addDualBlock(const SubFactorListType& c,ITERATOR shapeBegin, ITERATOR shapeEnd)
392  {
393  dualBlocks_.push_back(DualBlockType(c,shapeBegin,shapeEnd));
394  return;
395  }
396 
397 
398 
399  template<class GM, class DUALBLOCK>
400  inline std::vector<typename DUALBLOCK::DualVariableType*> DualDecompositionBase<GM,DUALBLOCK>::getDualPointers(size_t dualBlockId)
401  {
402  return dualBlocks_[dualBlockId].getPointers();
403  }
404 
405  template<class GM, class DUALBLOCK>
406  template <class ACC>
408  (
409  const std::vector<std::vector<LabelType> >& subStates,
410  const std::vector<SubVariableListType>& subVariableLists,
411  ValueType& lowerBound,
412  ValueType& upperBound,
413  std::vector<LabelType> & upperState
414  )
415  {
416  bool useFilling = parameter().fillSubLabelings_;
417 
418  // Calculate lower-bound
419  lowerBound=0;
420  for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){
421  lowerBound += subGm_[subModelId].evaluate(subStates[subModelId]);
422  }
423 
424  // Calculate upper-bound
425  Accumulation<ValueType,LabelType,ACC> ac;
426 
427  // Set modelWithSameVariables_
428  if(modelWithSameVariables_[0] == Tribool::Maybe){
429  for(size_t varId=0; varId<gm_.numberOfVariables(); ++varId){
430  for(typename SubVariableListType::const_iterator its = subVariableLists[varId].begin();
431  its!=subVariableLists[varId].end();++its){
432  const size_t& subModelId = (*its).subModelId_;
433  const size_t& subVariableId = (*its).subVariableId_;
434  if(subVariableId != varId){
435  modelWithSameVariables_[subModelId] = Tribool::False;
436  }
437  }
438  }
439  for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){
440  if(gm_.numberOfVariables() != subGm_[subModelId].numberOfVariables()){
441  modelWithSameVariables_[subModelId] = Tribool::False;
442  }
443  if(modelWithSameVariables_[subModelId] == Tribool::Maybe){
444  modelWithSameVariables_[subModelId] = Tribool::True;
445  }
446  }
447  }
448 
449  // Build Primal-Candidates
450 
451  // -- Build/Evaluate default canidate
452  std::vector<std::vector<IndexType> > subVariable2TrueVariable(subGm_.size());
453  if(useFilling){
454  for(size_t s=0; s<subGm_.size();++s){
455  subVariable2TrueVariable[s].resize(subGm_[s].numberOfVariables());
456  }
457  }
458  std::vector<LabelType> defaultLabel(gm_.numberOfVariables());
459  for(size_t varId=0; varId<gm_.numberOfVariables(); ++varId){
460  std::map<LabelType,size_t> labelCount;
461  for(typename SubVariableListType::const_iterator its = subVariableLists[varId].begin(); its!=subVariableLists[varId].end();++its){
462  const size_t& subModelId = (*its).subModelId_;
463  const size_t& subVariableId = (*its).subVariableId_;
464  if(useFilling){
465  subVariable2TrueVariable[subModelId][subVariableId] = varId;
466  }
467  ++labelCount[subStates[subModelId][subVariableId]];
468  }
469  size_t c=0;
470  for(typename std::map<LabelType,size_t>::iterator it=labelCount.begin(); it!=labelCount.end(); ++it){
471  if( it->second > c ){
472  c = it->second;
473  defaultLabel[varId] = it->first;
474  }
475  }
476  }
477  ac(gm_.evaluate(defaultLabel),defaultLabel);
478 
479 
480  // -- Build/Evaluate subproblem canidates
481  size_t a;
482  for(size_t subModelId=0; subModelId<subGm_.size(); ++subModelId){
483  if(modelWithSameVariables_[subModelId] == Tribool::False){
484  if(useFilling){
485  std::vector<LabelType> label(defaultLabel);
486  for(size_t i=0; i<subStates[subModelId].size(); ++i){
487  label[subVariable2TrueVariable[subModelId][i]]=subStates[subModelId][i];
488  }
489  ac(gm_.evaluate(label),label);
490  }
491  }
492  else{
493  ac(gm_.evaluate(subStates[subModelId]),subStates[subModelId]);
494  }
495  }
496  upperBound = ac.value();
497  ac.state(upperState);
498  }
499 
500  template <class GM, class DUALBLOCK>
502  {
503  double norm = 0;
504  typename std::vector<DualBlockType>::const_iterator it;
505  for(it = dualBlocks_.begin(); it != dualBlocks_.end(); ++it){
506  norm += (*it).duals_.size();
507  }
508  norm = pow(norm,1.0/L);
509  return norm;
510  }
511 
512 } // namespace opengm
513 
514 #endif
double minimalRelAccuracy_
the relative accuracy that has to be guaranteed to stop with an approximate solution (set 0 for optim...
void getBounds(const std::vector< std::vector< LabelType > > &, const std::vector< SubVariableListType > &, ValueType &, ValueType &, std::vector< LabelType > &)
The OpenGM namespace.
Definition: config.hxx:43
std::vector< DualBlockType > dualBlocks_
Discrete space in which variables can have differently many labels.
Runtime-flexible multi-dimensional views and arrays.
Definition: marray.hxx:20
DecompositionType::SubFactor SubFactorType
DecompositionType::SubVariable SubVariableType
void operator()(const DDType &dd, const ValueType bound, const ValueType bestBound, const ValueType value, const ValueType bestValue, double primalTime, double dualTime)
std::vector< DualVariableType * > getDualPointers(size_t)
void operator()(const DDType &dd, const ValueType bound, const ValueType bestBound, const ValueType value, const ValueType bestValue, const double primalTime, const double dualTime)
const SubGmType & subModel(size_t subModelId) const
virtual DualDecompositionBaseParameter & parameter()=0
void toc()
Definition: timer.hxx:109
DecompositionType::SubVariableListType SubVariableListType
STL namespace.
size_t numberOfBlocks_
number of blocks for block decomposition
Array-Interface to an interval of memory.
Definition: marray.hxx:44
Platform-independent runtime measurements.
Definition: timer.hxx:29
size_t k_
size of inner clique of kfan
double minimalAbsAccuracy_
the absolut accuracy that has to be guaranteed to stop with an approximate solution (set 0 for optima...
const std::vector< double > & primalTimes()
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
const std::vector< double > & dualTimes()
double subGradientNorm(double L=1) const
GraphicalModelDecomposition decomposition_
decomposition of the model (needs to fit to the model structure)
const std::vector< ValueType > & values()
void init(DualDecompositionBaseParameter &)
bool fillSubLabelings_
use filling to generate full labelings from non-spanning subproblems. If one labeling is generated fo...
double elapsedTime() const
Definition: timer.hxx:130
DecompositionId decompositionId_
type of decomposition that should be used (independent of model structure)
void tic()
Definition: timer.hxx:96
void DualVarAssign(DUALVAR &dv, T *t)
const std::vector< double > & times()
Function that refers to a factor of another GraphicalModel.
std::vector< std::set< size_t > > subVariables_
vectors of variables of the subproblems - used form manual variable decomposition only...
GraphicalModelDecomposition DecompositionType
size_t numberOfThreads_
number of threads for primal problems
void addDualBlock(const SubFactorListType &, ITERATOR, ITERATOR)
size_t maximalDualOrder_
maximum order of dual variables (order of the corresponding factor)
double getStepsize(size_t iteration, double primalDualGap, double subgradientNorm)
std::vector< std::vector< size_t > > subFactors_
vectors of factors of the subproblems - used form manual decomposition only.
ModelViewFunction< GmType, DualVariableType > ViewFunctionType
GraphicalModel< ValueType, OperatorType, typename meta::TypeListGenerator< ViewFunctionType >::type, opengm::DiscreteSpace< IndexType, LabelType > > SubGmType
const std::vector< ValueType > & bounds()
DualBlockType::DualVariableType DualVariableType
DecompositionType::SubFactorListType SubFactorListType
size_t maximalNumberOfIterations_
maximum number of dual iterations
const size_t * shapeEnd() const
Get a constant iterator to the end of the shape vector.
Definition: marray.hxx:1756
const size_t * shapeBegin() const
Get a constant iterator to the beginning of the shape vector.
Definition: marray.hxx:1742
A framework for inference algorithms based on Lagrangian decomposition.
std::vector< Tribool > modelWithSameVariables_
void assign(const allocator_type &=allocator_type())
Clear View.
Definition: marray.hxx:1105