OpenGM  2.3.x
Discrete Graphical Model Library
reducedinference.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_REDUCEDINFERENCE_HXX
3 #define OPENGM_REDUCEDINFERENCE_HXX
4 
5 #include <vector>
6 #include <set>
7 #include <map>
8 #include <string>
9 #include <iostream>
10 
11 #include "opengm/opengm.hxx"
16 
19 #include "opengm/inference/fix-fusion/fusion-move.hpp"
21 
25 
30 
31 namespace opengm {
32  template<class GM>
34  {
35  public:
36  typedef typename GM::ValueType ValueType;
37  typedef typename GM::LabelType LabelType;
38  typedef typename GM::IndexType IndexType;
39  typedef typename GM::OperatorType OperatorType;
41 
42  typedef typename meta::TypeListGenerator< ViewFixVariablesFunction<GM>,
48  };
49 
73  template<class GM, class ACC, class INF>
74  class ReducedInference : public Inference<GM, ACC>
75  {
76  public:
77  typedef ACC AccumulationType;
78  typedef GM GmType;
79  typedef GM GraphicalModelType;
80  typedef INF InfType;
85 
86 
87  class Parameter
88  {
89  public:
90  typename INF::Parameter subParameter_;
92  bool Tentacle_;
95  const bool Persistency=false,
96  const bool Tentacle=false,
97  const bool ConnectedComponents=false,
98  typename INF::Parameter subParameter = typename INF::Parameter()
99  )
100  :
101  Persistency_(Persistency),
102  Tentacle_(Tentacle),
103  ConnectedComponents_(ConnectedComponents),
104  subParameter_(subParameter)
105  {
106 
107  };
108  };
109 
110  ReducedInference(const GmType&, const Parameter & = Parameter() );
111  std::string name() const;
112  const GmType& graphicalModel() const;
114  typename GM::ValueType bound() const;
115  template<class VisitorType>
116  InferenceTermination infer(VisitorType&);
117  virtual InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const ;
118  typename GM::ValueType value() const;
119 
120  private:
121  //typedef typename ReducedInferenceHelper<GM>::InfGmType GM2;
122  //typedef external::QPBO<GM> QPBO;
123 
125  //typedef disjoint_set<IndexType> Set;
126  //typedef opengm::DynamicProgramming<GM2,AccumulationType> dynP;
127  //typedef modelTrees<GM2> MT;
128 
129 
130  const GmType& gm_;
131 
132  Parameter param_;
133  ValueType bound_;
134  ValueType value_;
135 
136  std::vector<LabelType> state_;
137 
138  void getPartialOptimalityByQPBO(std::vector<LabelType>&, std::vector<bool>&);
139  void getPartialOptimalityByFixsHOQPBO(std::vector<LabelType>&, std::vector<bool>&);
140  void getPartialOptimalityByKovtunsMethod(std::vector<LabelType>&, std::vector<bool>&);
141  void getPartialOptimalityByMQPBO(std::vector<LabelType>&, std::vector<bool>&);
142  void getPartialOptimalityByAutoSelection(std::vector<LabelType>&, std::vector<bool>&);
143  void setPartialOptimality(std::vector<LabelType>&, std::vector<bool>&);
144 
145  void subinf(const typename ReducedInferenceHelper<GM>::InfGmType&,const bool,std::vector<LabelType>&, typename GM::ValueType&, typename GM::ValueType&);
146 
147  //std::vector<bool> variableOpt_;
148  //std::vector<bool> factorOpt_;
149  //ValueType const_;
150  //std::vector<IndexType> model2gm_;
151 
152  //void updateFactorOpt(std::vector<ExplicitFunction<ValueType,IndexType,LabelType> >&);
153  //void getConnectComp(std::vector< std::vector<IndexType> >&, std::vector<GM2>&, std::vector<ExplicitFunction<ValueType,IndexType,LabelType> >&, bool );
154  //void getTentacle(std::vector< std::vector<IndexType> >&, std::vector<IndexType>&, std::vector< std::vector<ValueType> >&, std::vector< std::vector<std::vector<LabelType> > >&, std::vector< std::vector<IndexType> >&, std::vector<ExplicitFunction<ValueType,IndexType,LabelType> >& );
155  //void getRoots(std::vector< std::vector<IndexType> >&, std::vector<IndexType>& );
156  //void getTentacleCC(std::vector< std::vector<IndexType> >&, std::vector<IndexType>&, std::vector< std::vector<ValueType> >&, std::vector< std::vector<std::vector<LabelType> > >&, std::vector< std::vector<IndexType> >&, std::vector<GM2>&, GM2&);
157 
158  };
160 
161 
162  template<class GM, class ACC, class INF>
164  (
165  const GmType& gm,
166  const Parameter& parameter
167  )
168  : gm_( gm ),
169  param_(parameter)
170  {
171 
172  ACC::ineutral(bound_);
173  OperatorType::neutral(value_);
174  state_.resize(gm.numberOfVariables(),0);
175 
176  //variableOpt_.resize(gm_.numberOfVariables(),false);
177  //factorOpt_.resize(gm.numberOfFactors(),false);
178  //const_ = 0;
179  }
180 
181  template<class GM, class ACC, class INF>
182  void ReducedInference<GM,ACC,INF>::getPartialOptimalityByAutoSelection(std::vector<LabelType>& arg, std::vector<bool>& opt)
183  {
184  bool binary = true;
185  bool potts = true;
186  IndexType order = 0;
187 
188  for(IndexType j = 0; j < gm_.numberOfVariables(); ++j) {
189  if(gm_.numberOfLabels(j) != 2) {
190  binary = false;
191  }
192  }
193 
194  for(IndexType j = 0; j < gm_.numberOfFactors(); ++j) {
195  if(potts && gm_[j].numberOfVariables() >1 && (gm_[j].numberOfVariables() > 3 || !gm_[j].isPotts() ) )
196  potts=false;
197  if(gm_[j].numberOfVariables() > order) {
198  order = gm_[j].numberOfVariables();
199  }
200  }
201 
202  if(binary){
203  if(order<=2)
204  getPartialOptimalityByQPBO(arg,opt);
205  else
206  getPartialOptimalityByFixsHOQPBO(arg,opt);
207  }
208  else{
209  if(potts)
210  getPartialOptimalityByKovtunsMethod(arg,opt);
211  else if(order<=2)
212  getPartialOptimalityByMQPBO(arg,opt);
213  else
214  throw RuntimeError("This implementation of Reduced Inference supports no higher order multi-label problems.");
215  }
216  }
217 
218  template<class GM, class ACC, class INF>
219  void ReducedInference<GM,ACC,INF>::getPartialOptimalityByQPBO(std::vector<LabelType>& arg, std::vector<bool>& opt)
220  {
221  typedef external::QPBO<GM> QPBO;
222  typename QPBO::Parameter paraQPBO;
223  paraQPBO.strongPersistency_=false;
224  QPBO qpbo(gm_,paraQPBO);
225  qpbo.infer();
226  qpbo.arg(arg);
227  qpbo.partialOptimality(opt);
228  bound_=qpbo.bound();
229  }
230  template<class GM, class ACC, class INF>
231  void ReducedInference<GM,ACC,INF>::getPartialOptimalityByFixsHOQPBO(std::vector<LabelType>& arg, std::vector<bool>& opt)
232  {
233  const size_t maxOrder = 10;
234  ValueType constV = 0;
235  HigherOrderEnergy<ValueType, maxOrder> hoe;
236  hoe.AddVars(gm_.numberOfVariables());
237  for(IndexType f=0; f<gm_.numberOfFactors(); ++f){
238  IndexType size = gm_[f].numberOfVariables();
239  const LabelType l0 = 0;
240  const LabelType l1 = 1;
241  if (size == 0) {
242  constV += gm_[f](&l0);
243  continue;
244  } else if (size == 1) {
245  IndexType var = gm_[f].variableIndex(0);
246  const ValueType e0 = gm_[f](&l0);
247  const ValueType e1 = gm_[f](&l1);
248  hoe.AddUnaryTerm(var, e1 - e0);
249  } else {
250  unsigned int numAssignments = 1 << size;
251  ValueType coeffs[numAssignments];
252  for (unsigned int subset = 1; subset < numAssignments; ++subset) {
253  coeffs[subset] = 0;
254  }
255  // For each boolean assignment, get the clique energy at the
256  // corresponding labeling
257  LabelType cliqueLabels[size];
258  for(unsigned int assignment = 0; assignment < numAssignments; ++assignment){
259  for (unsigned int i = 0; i < size; ++i) {
260  if (assignment & (1 << i)) {
261  cliqueLabels[i] = l1;
262  } else {
263  cliqueLabels[i] = l0;
264  }
265  }
266  ValueType energy = gm_[f](cliqueLabels);
267  for (unsigned int subset = 1; subset < numAssignments; ++subset){
268  if (assignment & ~subset) {
269  continue;
270  } else {
271  int parity = 0;
272  for (unsigned int b = 0; b < size; ++b) {
273  parity ^= (((assignment ^ subset) & (1 << b)) != 0);
274  }
275  coeffs[subset] += parity ? -energy : energy;
276  }
277  }
278  }
279  typename HigherOrderEnergy<ValueType, maxOrder> ::VarId vars[maxOrder];
280  for (unsigned int subset = 1; subset < numAssignments; ++subset) {
281  int degree = 0;
282  for (unsigned int b = 0; b < size; ++b) {
283  if (subset & (1 << b)) {
284  vars[degree++] = gm_[f].variableIndex(b);
285  }
286  }
287  std::sort(vars, vars+degree);
288  hoe.AddTerm(coeffs[subset], degree, vars);
289  }
290  }
291  }
292  kolmogorov::qpbo::QPBO<ValueType> qr(gm_.numberOfVariables(), 0);
293  hoe.ToQuadratic(qr);
294  qr.Solve();
295 
296  for (IndexType i = 0; i < gm_.numberOfVariables(); ++i) {
297  int label = qr.GetLabel(i);
298  if(label == 0 ){
299  arg[i] = 0;
300  opt[i] = true;
301  }
302  else if(label == 1){
303  arg[i] = 1;
304  opt[i] = true;
305  }
306  else{
307  arg[i] = 0;
308  opt[i] = false;
309  }
310  }
311  bound_ = constV + 0.5 * qr.ComputeTwiceLowerBound();
312  }
313 
314  template<class GM, class ACC, class INF>
315  void ReducedInference<GM,ACC,INF>::getPartialOptimalityByMQPBO(std::vector<LabelType>& arg, std::vector<bool>& opt)
316  {
317  typedef opengm::MQPBO<GM,ACC> MQPBOType;
318  typename MQPBOType::Parameter mqpboPara;
319  mqpboPara.useKovtunsMethod_ = false;
320  mqpboPara.strongPersistency_ = true;
321  mqpboPara.rounds_ = 10;
322  mqpboPara.permutationType_ = MQPBOType::RANDOM;
323  MQPBOType mqpbo(gm_,mqpboPara);
324  mqpbo.infer();
325  arg.resize(gm_.numberOfVariables(),0);
326  opt.resize(gm_.numberOfVariables(),false);
327  for(IndexType var=0; var<gm_.numberOfVariables(); ++var){
328  opt[var] = mqpbo.partialOptimality(var,arg[var]);
329  }
330  }
331 
332  template<class GM, class ACC, class INF>
333  void ReducedInference<GM,ACC,INF>::getPartialOptimalityByKovtunsMethod(std::vector<LabelType>& arg, std::vector<bool>& opt)
334  {
335  typedef opengm::MQPBO<GM,ACC> MQPBOType;
336  typename MQPBOType::Parameter mqpboPara;
337  mqpboPara.strongPersistency_ = true;
338  MQPBOType mqpbo(gm_,mqpboPara);
339  mqpbo.infer();
340  arg.resize(gm_.numberOfVariables(),0);
341  opt.resize(gm_.numberOfVariables(),false);
342  for(IndexType var=0; var<gm_.numberOfVariables(); ++var){
343  opt[var] = mqpbo.partialOptimality(var,arg[var]);
344  }
345  }
346 
347 
348  template<class GM, class ACC, class INF>
349  inline std::string
351  {
352  return "ReducedInference";
353  }
354 
355  template<class GM, class ACC, class INF>
356  inline const typename ReducedInference<GM,ACC,INF>::GmType&
358  {
359  return gm_;
360  }
361 
362  template<class GM, class ACC, class INF>
363  inline InferenceTermination
365  {
366  EmptyVisitorType v;
367  return infer(v);
368  }
369 
370 
371  template<class GM, class ACC, class INF>
372  template<class VisitorType>
374  (
375  VisitorType& visitor
376  )
377  {
378  visitor.begin(*this);
379 
381 
382  // Find persistency
383  size_t numFixedVars = 0;
384  if(param_.Persistency_ == true){
385  std::vector<bool> opt(gm_.numberOfVariables(),false);
386  std::vector<LabelType> arg(gm_.numberOfVariables(),0);
387  getPartialOptimalityByAutoSelection(arg,opt);
388  for(IndexType i=0; i<gm_.numberOfVariables(); ++i){
389  if(opt[i]){
390  ++numFixedVars;
391  gmm.fixVariable(i, arg[i]);
392  }
393  }
394  }
395 
396  //std::cout << numFixedVars <<" of " <<gm_.numberOfVariables() << " are fixed."<<std::endl;
397 
398  if(numFixedVars == gm_.numberOfVariables()){
399  gmm.lock();
400  std::vector<LabelType> arg(0);
401  gmm.modifiedState2OriginalState(arg, state_);
402  bound_ = value();
403  //visitor(*this);
404  visitor.end(*this);
405  return NORMAL;
406  }
407 
408  if(param_.Tentacle_ == true){
409  //std::cout << " Search for tentacles." <<std::endl;
410  gmm.template lockAndTentacelElimination<ACC>();
411  }
412  else{
413  gmm.lock();
414  }
415 
416  if( visitor(*this) != visitors::VisitorReturnFlag::ContinueInf ) {
417  visitor.end(*this);
418  return NORMAL;
419  }
420 
421 
422  //ValueType sv, v;
423  ValueType sb, b, v;
424  OperatorType::neutral(sb);
425  //OperatorType::neutral(sv);
426 
427  // CONNTECTED COMPONENTS INFERENCE
428  if(param_.ConnectedComponents_ == true){
430  std::vector<std::vector<LabelType> > args(gmm.numberOfSubmodels(),std::vector<LabelType>() );
431  for(size_t i=0; i<gmm.numberOfSubmodels(); ++i){
432  args[i].resize(gmm.getModifiedSubModel(i).numberOfVariables());
433  }
434  for(size_t i=0; i<gmm.numberOfSubmodels(); ++i){
436  subinf(agm, param_.Tentacle_, args[i],v,b);
437  //OperatorType::op(v,sv);
438  OperatorType::op(b,sb);
439  //gmm.modifiedSubStates2OriginalState(args, state_);
440  //visitor(*this,value(),bound(),"numberOfComp",i);
441  if( visitor(*this) != visitors::VisitorReturnFlag::ContinueInf ) {
442  visitor.end(*this);
443  return NORMAL;
444  }
445  }
446  bound_= sb;
447  gmm.modifiedSubStates2OriginalState(args, state_);
448  if( visitor(*this) != visitors::VisitorReturnFlag::ContinueInf ) {
449  visitor.end(*this);
450  return NORMAL;
451  }
452  //gmm.modifiedSubStates2OriginalState(args, state_);
453 
454  }
455  else{
456  //size_t i=0;
457  std::vector<LabelType> arg;
458  gmm.buildModifiedModel();
460  subinf(agm, param_.Tentacle_, arg,v,b);
461  gmm.modifiedState2OriginalState(arg, state_);
462  //visitor(*this,value(),bound(),"numberOfComp",i);
463  //gmm.modifiedState2OriginalState(arg, state_);
464  bound_=b;
465  }
466  //value_=gm_.evaluate(state_);
467  visitor.end(*this);
468  return NORMAL;
469  }
470 
471 
472  template<class GM, class ACC, class INF>
474  (
475  const typename ReducedInferenceHelper<GM>::InfGmType& agm,
476  const bool tentacleElimination,
477  std::vector<LabelType>& arg,
478  typename GM::ValueType& value,
479  typename GM::ValueType& bound
480  )
481  {
482  //std::cout << "solve model with "<<agm.numberOfVariables()<<" and "<<agm.numberOfFactors()<<" factors."<<std::endl;
483  InfType inf(agm, param_.subParameter_);
484  inf.infer();
485  arg.resize(agm.numberOfVariables());
486  inf.arg(arg);
487  value = inf.value();
488  bound = inf.bound();
489  }
490 
491 
492  template<class GM, class ACC, class INF>
493  typename GM::ValueType ReducedInference<GM,ACC,INF>::bound() const {
494  return bound_;
495  }
496 
497  template<class GM, class ACC, class INF>
498  typename GM::ValueType ReducedInference<GM,ACC,INF>::value() const {
499  return gm_.evaluate(state_);
500  }
501 
502  template<class GM, class ACC, class INF>
503  inline InferenceTermination
505  (
506  std::vector<LabelType>& x,
507  const size_t N
508  ) const
509  {
510  if(N==1){
511  x.resize(gm_.numberOfVariables());
512  for(size_t i=0; i<x.size(); ++i){
513  x[i] = state_[i];
514  }
515  return NORMAL;
516  }
517  else {
518  return UNKNOWN;
519  }
520  }
521 } // namespace opengm
522 
523 #endif // #ifndef OPENGM_ReducedInference_HXX
524 
Constant function.
Definition: constant.hxx:19
void modifiedState2OriginalState(const std::vector< LabelType > &, std::vector< LabelType > &) const
transforming label of the modified to the labeling of the original problem
The OpenGM namespace.
Definition: config.hxx:43
Discrete space in which variables can have differently many labels.
Parameter(const bool Persistency=false, const bool Tentacle=false, const bool ConnectedComponents=false, typename INF::Parameter subParameter=typename INF::Parameter())
void buildModifiedModel()
build modified model
void modifiedSubStates2OriginalState(const std::vector< std::vector< LabelType > > &, std::vector< LabelType > &) const
transforming label of the modified subproblems to the labeling of the original problem ...
ReducedInference(const GmType &, const Parameter &=Parameter())
[class reducedinference]
InferenceTermination infer()
virtual InferenceTermination arg(std::vector< LabelType > &, const size_t=1) const
output a solution
visitors::VerboseVisitor< ReducedInference< GM, ACC, INF > > VerboseVisitorType
void fixVariable(const typename GM::IndexType, const typename GM::LabelType)
fix label for variable
const GmType & graphicalModel() const
[class mqpbo] Multilabel QPBO (MQPBO) Implements the algorithms described in i) Ivan Kovtun: Partial ...
Definition: mqpbo.hxx:37
GraphicalModel< ValueType, OperatorType, FunctionTypeList, SpaceType > InfGmType
void buildModifiedSubModels()
build modified sub-models
GraphicalModelType::IndexType IndexType
Definition: inference.hxx:40
reference to a Factor of a GraphicalModel
Definition: view.hxx:13
visitors::EmptyVisitor< ReducedInference< GM, ACC, INF > > EmptyVisitorType
std::string name() const
const MGM & getModifiedModel() const
return the modified graphical model
GM::ValueType bound() const
return a bound on the solution
GraphicalModelType::ValueType ValueType
Definition: inference.hxx:41
const MGM & getModifiedSubModel(size_t) const
return the i-th modified sub graphical model
Inference algorithm interface.
Definition: inference.hxx:34
visitors::TimingVisitor< ReducedInference< GM, ACC, INF > > TimingVisitorType
DiscreteSpace< IndexType, LabelType > SpaceType
size_t numberOfSubmodels() const
return the number of submodels
meta::TypeListGenerator< ViewFixVariablesFunction< GM >, ViewFunction< GM >, ConstantFunction< ValueType, IndexType, LabelType >, ExplicitFunction< ValueType, IndexType, LabelType > >::type FunctionTypeList
IndexType numberOfVariables() const
GM::ValueType value() const
return the solution (value)
[class reducedinference] Reduced Inference Implementation of the reduction techniques proposed in J...
InferenceTermination
Definition: inference.hxx:24