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