OpenGM  2.3.x
Discrete Graphical Model Library
alphaexpansionfusion.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_ALPHAEXPANSIONFUSION_HXX
3 #define OPENGM_ALPHAEXPANSIONSUSION_HXX
4 
7 #include "opengm/inference/fix-fusion/fusion-move.hpp"
8 #include "QPBO.h"
9 
10 namespace opengm {
11 
19 template<class GM, class ACC>
20 class AlphaExpansionFusion : public Inference<GM, ACC>
21 {
22 public:
23  typedef GM GraphicalModelType;
24  typedef ACC AccumulationType;
29 
30  template<class _GM>
31  struct RebindGm{
33  };
34 
35  template<class _GM,class _ACC>
38  };
39 
40  struct Parameter {
41  enum LabelingIntitialType {DEFAULT_LABEL, RANDOM_LABEL,
42  LOCALOPT_LABEL, EXPLICIT_LABEL};
43  enum OrderType {DEFAULT_ORDER, RANDOM_ORDER,
44  EXPLICIT_ORDER};
45 
46 
47  Parameter
48  (
49  const size_t maxNumberOfSteps = 1000
50  )
51  : maxNumberOfSteps_(maxNumberOfSteps),
52  labelInitialType_(DEFAULT_LABEL),
53  orderType_(DEFAULT_ORDER),
54  randSeedOrder_(0),
55  randSeedLabel_(0),
56  labelOrder_(),
57  label_()
58  {}
59 
60  template<class P>
61  Parameter
62  (
63  const P & p
64  )
65  : maxNumberOfSteps_(p.maxNumberOfSteps_),
66  labelInitialType_(p.labelInitialType_),
67  orderType_(p.orderType_),
68  randSeedOrder_(p.randSeedOrder_),
69  randSeedLabel_(p.randSeedLabel_),
70  labelOrder_(p.labelOrder_),
71  label_(p.labelOrder_)
72  {}
73 
77  unsigned int randSeedOrder_;
78  unsigned int randSeedLabel_;
79  std::vector<LabelType> labelOrder_;
80  std::vector<LabelType> label_;
81  };
82 
83  AlphaExpansionFusion(const GraphicalModelType&, Parameter para = Parameter());
84 
85  std::string name() const;
86  const GraphicalModelType& graphicalModel() const;
87  template<class StateIterator>
88  void setState(StateIterator, StateIterator);
90  void reset();
91  template<class Visitor>
92  InferenceTermination infer(Visitor& visitor);
93  void setStartingPoint(typename std::vector<LabelType>::const_iterator);
94  InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const;
95 
96 private:
97  const GraphicalModelType& gm_;
98  Parameter parameter_;
99  static const size_t maxOrder_ =10;
100  std::vector<LabelType> label_;
101  std::vector<LabelType> labelList_;
102  size_t maxState_;
103  size_t alpha_;
104  size_t counter_;
105  void incrementAlpha();
106  void setLabelOrder(std::vector<LabelType>& l);
107  void setLabelOrderRandom(unsigned int);
108  void setInitialLabel(std::vector<LabelType>& l);
109  void setInitialLabelLocalOptimal();
110  void setInitialLabelRandom(unsigned int);
111  template<class INF>
112  void addUnary(INF&, const size_t var, const ValueType v0, const ValueType v1);
113  template<class INF>
114  void addPairwise(INF&, const size_t var1, const size_t var2, const ValueType v0, const ValueType v1, const ValueType v2, const ValueType v3);
115 };
116 
117 template<class GM, class ACC>
118 inline std::string
120 {
121  return "Alpha-Expansion-Fusion";
122 }
123 
124 template<class GM, class ACC>
127 {
128  return gm_;
129 }
130 
131 template<class GM, class ACC>
132 template<class StateIterator>
133 inline void
135 (
136  StateIterator begin,
137  StateIterator end
138 )
139 {
140  label_.assign(begin, end);
141 }
142 
143 template<class GM, class ACC>
144 inline void
146 (
147  typename std::vector<typename AlphaExpansionFusion<GM,ACC>::LabelType>::const_iterator begin
148 ) {
149  try{
150  label_.assign(begin, begin+gm_.numberOfVariables());
151  }
152  catch(...) {
153  throw RuntimeError("unsuitable starting point");
154  }
155 }
156 
157 template<class GM, class ACC>
158 inline
160 (
161  const GraphicalModelType& gm,
162  Parameter para
163 )
164 : gm_(gm),
165  parameter_(para),
166  maxState_(0)
167 {
168  for(size_t j=0; j<gm_.numberOfFactors(); ++j) {
169  if(gm_[j].numberOfVariables() > maxOrder_) {
170  throw RuntimeError("This implementation of Alpha-Expansion-Fusion supports only factors of this order! Increase the constant maxOrder_!");
171  }
172  }
173  for(size_t i=0; i<gm_.numberOfVariables(); ++i) {
174  size_t numSt = gm_.numberOfLabels(i);
175  if(numSt > maxState_) {
176  maxState_ = numSt;
177  }
178  }
179 
180  if(parameter_.labelInitialType_ == Parameter::RANDOM_LABEL) {
181  setInitialLabelRandom(parameter_.randSeedLabel_);
182  }
183  else if(parameter_.labelInitialType_ == Parameter::LOCALOPT_LABEL) {
184  setInitialLabelLocalOptimal();
185  }
186  else if(parameter_.labelInitialType_ == Parameter::EXPLICIT_LABEL) {
187  setInitialLabel(parameter_.label_);
188  }
189  else{
190  label_.resize(gm_.numberOfVariables(), 0);
191  }
192 
193 
194  if(parameter_.orderType_ == Parameter::RANDOM_ORDER) {
195  setLabelOrderRandom(parameter_.randSeedOrder_);
196  }
197  else if(parameter_.orderType_ == Parameter::EXPLICIT_ORDER) {
198  setLabelOrder(parameter_.labelOrder_);
199  }
200  else{
201  labelList_.resize(maxState_);
202  for(size_t i=0; i<maxState_; ++i)
203  labelList_[i] = i;
204  }
205 
206  counter_ = 0;
207  alpha_ = labelList_[counter_];
208 }
209 
210 // reset assumes that the structure of
211 // the graphical model has not changed
212 template<class GM, class ACC>
213 inline void
215  if(parameter_.labelInitialType_ == Parameter::RANDOM_LABEL) {
216  setInitialLabelRandom(parameter_.randSeedLabel_);
217  }
218  else if(parameter_.labelInitialType_ == Parameter::LOCALOPT_LABEL) {
219  setInitialLabelLocalOptimal();
220  }
221  else if(parameter_.labelInitialType_ == Parameter::EXPLICIT_LABEL) {
222  setInitialLabel(parameter_.label_);
223  }
224  else{
225  std::fill(label_.begin(),label_.end(),0);
226  }
227 
228 
229  if(parameter_.orderType_ == Parameter::RANDOM_ORDER) {
230  setLabelOrderRandom(parameter_.randSeedOrder_);
231  }
232  else if(parameter_.orderType_ == Parameter::EXPLICIT_ORDER) {
233  setLabelOrder(parameter_.labelOrder_);
234  }
235  else{
236  for(size_t i=0; i<maxState_; ++i)
237  labelList_[i] = i;
238  }
239  counter_ = 0;
240  alpha_ = labelList_[counter_];
241 }
242 
243 template<class GM, class ACC>
244 template<class INF>
245 inline void
247 (
248  INF& inf,
249  const size_t var1,
250  const ValueType v0,
251  const ValueType v1
252 ) {
253  inf.AddUnaryTerm((int) (var1), v0, v1);
254 }
255 
256 template<class GM, class ACC>
257 template<class INF>
258 inline void
260 (
261  INF& inf,
262  const size_t var1,
263  const size_t var2,
264  const ValueType v0,
265  const ValueType v1,
266  const ValueType v2,
267  const ValueType v3
268 ) {
269  inf.AddPairwiseTerm((int) (var1), (int)(var2),v0,v1,v2,v3);
270 }
271 
272 template<class GM, class ACC>
275 {
276  EmptyVisitorType visitor;
277  return infer(visitor);
278 }
279 
280 template<class GM, class ACC>
281 template<class Visitor>
284 (
285  Visitor& visitor
286 )
287 {
288  bool exitInf = false;
289  size_t it = 0;
290  size_t countUnchanged = 0;
291 // size_t numberOfVariables = gm_.numberOfVariables();
292 // std::vector<size_t> variable2Node(numberOfVariables);
293  //ValueType energy = gm_.evaluate(label_);
294  //visitor.begin(*this,energy,this->bound(),0);
295  visitor.begin(*this);
296 /*
297  LabelType vecA[1];
298  LabelType vecX[1];
299  LabelType vecAA[2];
300  LabelType vecAX[2];
301  LabelType vecXA[2];
302  LabelType vecXX[2];
303 */
304  while(it++ < parameter_.maxNumberOfSteps_ && countUnchanged < maxState_ && exitInf == false) {
305  // DO MOVE
306  unsigned int maxNumAssignments = 1 << maxOrder_;
307  std::vector<ValueType> coeffs(maxNumAssignments);
308  std::vector<LabelType> cliqueLabels(maxOrder_);
309 
310  HigherOrderEnergy<ValueType, maxOrder_> hoe;
311  hoe.AddVars(gm_.numberOfVariables());
312  for(IndexType f=0; f<gm_.numberOfFactors(); ++f){
313  IndexType size = gm_[f].numberOfVariables();
314  if (size == 0) {
315  continue;
316  } else if (size == 1) {
317  IndexType var = gm_[f].variableIndex(0);
318  ValueType e0 = gm_[f](&label_[var]);
319  ValueType e1 = gm_[f](&alpha_);
320  hoe.AddUnaryTerm(var, e1 - e0);
321  } else {
322 
323  // unsigned int numAssignments = std::pow(2,size);
324  unsigned int numAssignments = 1 << size;
325  // -- // ValueType coeffs[numAssignments];
326  for (unsigned int subset = 1; subset < numAssignments; ++subset) {
327  coeffs[subset] = 0;
328  }
329  // For each boolean assignment, get the clique energy at the
330  // corresponding labeling
331  // -- // LabelType cliqueLabels[size];
332  for(unsigned int assignment = 0; assignment < numAssignments; ++assignment){
333  for (unsigned int i = 0; i < size; ++i) {
334  // only true for each second assigment?!?
335  //if ( assignment%2 == (std::pow(2,i))%2 )
336  if (assignment & (1 << i)) {
337  cliqueLabels[i] = alpha_;
338  } else {
339  cliqueLabels[i] = label_[gm_[f].variableIndex(i)];
340  }
341  }
342  ValueType energy = gm_[f](cliqueLabels.begin());
343  for (unsigned int subset = 1; subset < numAssignments; ++subset){
344  // if (assigment%2 != subset%2)
345  if (assignment & ~subset) {
346  continue;
347  }
348  //(assigment%2 == subset%2)
349  else {
350  int parity = 0;
351  for (unsigned int b = 0; b < size; ++b) {
352  parity ^= (((assignment ^ subset) & (1 << b)) != 0);
353  }
354  coeffs[subset] += parity ? -energy : energy;
355  }
356  }
357  }
358  typename HigherOrderEnergy<ValueType, maxOrder_> ::VarId vars[maxOrder_];
359  for (unsigned int subset = 1; subset < numAssignments; ++subset) {
360  int degree = 0;
361  for (unsigned int b = 0; b < size; ++b) {
362  if (subset & (1 << b)) {
363  vars[degree++] = gm_[f].variableIndex(b);
364  }
365  }
366  std::sort(vars, vars+degree);
367  hoe.AddTerm(coeffs[subset], degree, vars);
368  }
369  }
370  }
371  kolmogorov::qpbo::QPBO<ValueType> qr(gm_.numberOfVariables(), 0);
372  hoe.ToQuadratic(qr);
373  qr.Solve();
374  IndexType numberOfChangedVariables = 0;
375  for (IndexType i = 0; i < gm_.numberOfVariables(); ++i) {
376  int label = qr.GetLabel(i);
377  if (label == 1) {
378  label_[i] = alpha_;
379  ++numberOfChangedVariables;
380  }
381  }
382 
383  OPENGM_ASSERT(gm_.numberOfVariables() == label_.size());
384  //ValueType energy2 = gm_.evaluate(label_);
385  if(numberOfChangedVariables>0){
386  //energy=energy2;
387  countUnchanged = 0;
388  }else{
389  ++countUnchanged;
390  }
391  //visitor(*this,energy2,this->bound(),"alpha",alpha_);
392  if( visitor(*this) != visitors::VisitorReturnFlag::ContinueInf ){
393  exitInf = true;
394  }
395  // OPENGM_ASSERT(!AccumulationType::ibop(energy2, energy));
396  incrementAlpha();
397  OPENGM_ASSERT(alpha_ < maxState_);
398  }
399  //visitor.end(*this,energy,this->bound(),0);
400  visitor.end(*this);
401  return NORMAL;
402  /*
403  while(it++ < parameter_.maxNumberOfSteps_ && countUnchanged < maxState_) {
404  size_t numberOfAuxiliaryNodes = 0;
405  for(size_t k=0 ; k<gm_.numberOfFactors(); ++k) {
406  const FactorType& factor = gm_[k];
407  if(factor.numberOfVariables() == 2) {
408  size_t var1 = factor.variableIndex(0);
409  size_t var2 = factor.variableIndex(1);
410  if(label_[var1] != label_[var2] && label_[var1] != alpha_ && label_[var2] != alpha_ ) {
411  ++numberOfAuxiliaryNodes;
412  }
413  }
414  }
415  std::vector<size_t> numFacDim(4, 0);
416 
417  kolmogorov::qpbo::QPBO<ValueType > inf(numberOfVariables + numberOfAuxiliaryNodes, gm_.numberOfFactors());
418  inf.AddNode(numberOfVariables + numberOfAuxiliaryNodes);
419  size_t varX = numberOfVariables;
420  size_t countAlphas = 0;
421  for (size_t k=0 ; k<gm_.numberOfVariables(); ++k) {
422  if (label_[k] == alpha_ ) {
423  addUnary(inf, k, 0, std::numeric_limits<ValueType>::infinity());
424  ++countAlphas;
425  }
426  }
427  if(countAlphas < gm_.numberOfVariables()) {
428  for (size_t k=0 ; k<gm_.numberOfFactors(); ++k) {
429  const FactorType& factor = gm_[k];
430  if(factor.numberOfVariables() == 1) {
431  size_t var = factor.variableIndex(0);
432  vecA[0] = alpha_;
433  vecX[0] = label_[var];
434  if (label_[var] != alpha_ ) {
435  addUnary(inf, var, factor(vecX), factor(vecA));
436  }
437  }
438  else if (factor.numberOfVariables() == 2) {
439  size_t var1 = factor.variableIndex(0);
440  size_t var2 = factor.variableIndex(1);
441  std::vector<IndexType> vars(2); vars[0]=var1;vars[1]=var2;
442  vecAA[0] = vecAA[1] = alpha_;
443  vecAX[0] = alpha_; vecAX[1] = label_[var2];
444  vecXA[0] = label_[var1]; vecXA[1] = alpha_;
445  vecXX[0] = label_[var1]; vecXX[1] = label_[var2];
446  if(label_[var1]==alpha_ && label_[var2]==alpha_) {
447  continue;
448  }
449  else if(label_[var1]==alpha_) {
450  addUnary(inf, var2, factor(vecAX), factor(vecAA));
451  }
452  else if(label_[var2]==alpha_) {
453  addUnary(inf, var1, factor(vecXA), factor(vecAA));
454  }
455  else if(label_[var1]==label_[var2]) {
456  addPairwise(inf, var1, var2, factor(vecXX), factor(vecXA), factor(vecAX), factor(vecAA));
457  }
458  else{
459  OPENGM_ASSERT(varX < numberOfVariables + numberOfAuxiliaryNodes);
460  addPairwise(inf, var1, varX, 0, factor(vecXA), 0, 0);
461  addPairwise(inf, var2, varX, 0, factor(vecAX), 0, 0);
462  addUnary(inf, varX, factor(vecXX), factor(vecAA));
463  ++varX;
464  }
465  }
466  }
467  inf.MergeParallelEdges();
468  inf.Solve();
469 
470  for(size_t var=0; var<numberOfVariables ; ++var) {
471  int b = inf.GetLabel(var);
472  if (label_[var] != alpha_ && b==1) {
473  label_[var] = alpha_;
474  }
475  OPENGM_ASSERT(label_[var] < gm_.numberOfLabels(var));
476  }
477  }
478  OPENGM_ASSERT(gm_.numberOfVariables() == label_.size());
479  ValueType energy2 = gm_.evaluate(label_);
480  visitor(*this,energy,this->bound(),alpha_);
481  // OPENGM_ASSERT(!AccumulationType::ibop(energy2, energy));
482  if(AccumulationType::bop(energy2, energy)) {
483  energy=energy2;
484  countUnchanged = 0;
485  }
486  else{
487  ++countUnchanged;
488  }
489  incrementAlpha();
490  OPENGM_ASSERT(alpha_ < maxState_);
491  }
492  }
493  visitor.end(*this,energy,this->bound(),0);
494  return NORMAL;
495 */
496 }
497 
498 template<class GM, class ACC>
501 (
502  std::vector<LabelType>& arg,
503  const size_t n
504 ) const
505 {
506  if(n > 1) {
507  return UNKNOWN;
508  }
509  else {
510  OPENGM_ASSERT(label_.size() == gm_.numberOfVariables());
511  arg.resize(label_.size());
512  for(size_t i=0; i<label_.size(); ++i) {
513  arg[i] = label_[i];
514  }
515  return NORMAL;
516  }
517 }
518 
519 template<class GM, class ACC>
520 inline void
522 (
523  std::vector<LabelType>& l
524 ) {
525  if(l.size() == maxState_) {
526  labelList_=l;
527  }
528 }
529 
530 template<class GM, class ACC>
531 inline void
533 (
534  unsigned int seed
535 ) {
536  srand(seed);
537  labelList_.resize(maxState_);
538  for (size_t i=0; i<maxState_;++i) {
539  labelList_[i]=i;
540  }
541  random_shuffle(labelList_.begin(), labelList_.end());
542 }
543 
544 template<class GM, class ACC>
545 inline void
547 (
548  std::vector<LabelType>& l
549 ) {
550  label_.resize(gm_.numberOfVariables());
551  if(l.size() == label_.size()) {
552  for(size_t i=0; i<l.size();++i) {
553  if(l[i]>=gm_.numberOfLabels(i)) return;
554  }
555  for(size_t i=0; i<l.size();++i) {
556  label_[i] = l[i];
557  }
558  }
559 }
560 
561 template<class GM, class ACC>
562 inline void
564  label_.resize(gm_.numberOfVariables(), 0);
565  std::vector<size_t> accVec;
566  for(size_t i=0; i<gm_.numberOfFactors();++i) {
567  if(gm_[i].numberOfVariables()==1) {
568  std::vector<size_t> state(1, 0);
569  ValueType value = gm_[i](state.begin());
570  for(state[0]=1; state[0]<gm_.numberOfLabels(i); ++state[0]) {
571  if(AccumulationType::bop(gm_[i](state.begin()), value)) {
572  value = gm_[i](state.begin());
573  label_[i] = state[0];
574  }
575  }
576  }
577  }
578 }
579 
580 template<class GM, class ACC>
581 inline void
583 (
584  unsigned int seed
585 ) {
586  srand(seed);
587  label_.resize(gm_.numberOfVariables());
588  for(size_t i=0; i<gm_.numberOfVariables();++i) {
589  label_[i] = rand() % gm_.numberOfLabels(i);
590  }
591 }
592 
593 template<class GM, class ACC>
594 inline void
596  counter_ = (counter_+1) % maxState_;
597  alpha_ = labelList_[counter_];
598 }
599 
600 } // namespace opengm
601 
602 #endif // #ifndef OPENGM_ALPHAEXPANSIONFUSION_HXX
The OpenGM namespace.
Definition: config.hxx:43
virtual ValueType value() const
return the solution (value)
Definition: inference.hxx:401
AlphaExpansionFusion(const GraphicalModelType &, Parameter para=Parameter())
Alpha-Expansion-Fusion Algorithm uses the code of Alexander Fix to reduce the higer order moves to bi...
visitors::TimingVisitor< AlphaExpansionFusion< GM, ACC > > TimingVisitorType
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
GraphicalModelType::IndexType IndexType
Definition: inference.hxx:49
InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
output a solution
visitors::VerboseVisitor< AlphaExpansionFusion< GM, ACC > > VerboseVisitorType
AlphaExpansionFusion< _GM, ACC > type
GraphicalModelType::ValueType ValueType
Definition: inference.hxx:50
Inference algorithm interface.
Definition: inference.hxx:43
visitors::EmptyVisitor< AlphaExpansionFusion< GM, ACC > > EmptyVisitorType
GraphicalModelType::LabelType LabelType
Definition: inference.hxx:48
const GraphicalModelType & graphicalModel() const
void setStartingPoint(typename std::vector< LabelType >::const_iterator)
set initial labeling
void setState(StateIterator, StateIterator)
OpenGM runtime error.
Definition: opengm.hxx:100
InferenceTermination
Definition: inference.hxx:24