OpenGM  2.3.x
Discrete Graphical Model Library
external/qpbo.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_EXTERNAL_QPBO_HXX
3 #define OPENGM_EXTERNAL_QPBO_HXX
4 
8 //#include "opengm/inference/alphabetaswap.hxx"
9 //#include "opengm/inference/alphaexpansion.hxx"
10 
11 #include "QPBO.h"
12 
13 namespace opengm {
14  namespace external {
15 
22  template<class GM>
23  class QPBO : public Inference<GM, opengm::Minimizer> {
24 
25  public:
26  typedef GM GraphicalModelType;
32 
34  enum TriBool {
36  };
37 
39  struct Parameter {
47  std::vector<size_t> label_;
49 
51  strongPersistency_ = true;
52  useImproveing_ = false;
53  useProbeing_ = false;
54  }
55  };
56  // construction
57  QPBO(const GraphicalModelType& gm, const Parameter para = Parameter());
58  ~QPBO();
59  // query
60  std::string name() const;
61  const GraphicalModelType& graphicalModel() const;
62  // inference
64  template<class VisitorType>
65  InferenceTermination infer(VisitorType&);
66  InferenceTermination arg(std::vector<LabelType>&, const size_t& = 1) const;
67  InferenceTermination arg(std::vector<TriBool>&, const size_t& = 1) const;
68  virtual typename GM::ValueType bound() const;
69  virtual typename GM::ValueType value() const;
70  double partialOptimality(std::vector<bool>&) const;
71 
72  private:
73  const GraphicalModelType& gm_;
74  Parameter parameter_;
75  kolmogorov::qpbo::QPBO<ValueType>* qpbo_;
76  ValueType constTerm_;
77  ValueType bound_;
78 
79  int* label_;
80  int* defaultLabel_;
81 
82  };
83  // public interface
87 
88  template<class GM>
89  QPBO<GM>
90  ::QPBO(
91  const typename QPBO::GraphicalModelType& gm,
92  const Parameter para
93  )
94  : gm_(gm), bound_(-std::numeric_limits<ValueType>::infinity()) {
95  parameter_ = para;
96  label_ = new int[gm_.numberOfVariables()];
97  defaultLabel_ = new int[gm_.numberOfVariables()];
98  for(size_t i = 0; i < gm_.numberOfVariables(); ++i) {
99  label_[i] = -1;
100  defaultLabel_[i] = 0;
101  }
102  if(parameter_.label_.size() > 0) {
103  for(size_t i = 0; i < parameter_.label_.size(); ++i) {
104  defaultLabel_[i] = parameter_.label_[i];
105  }
106  }
107  size_t numVariables = gm_.numberOfVariables();
108  size_t numPairwiseFactors = 0;
109  constTerm_ = 0;
110  size_t vec0[] = {0};
111  size_t vec1[] = {1};
112  size_t vec00[] = {0, 0};
113  size_t vec01[] = {0, 1};
114  size_t vec10[] = {1, 0};
115  size_t vec11[] = {1, 1};
116  for(size_t j = 0; j < gm_.numberOfVariables(); ++j) {
117  if(gm_.numberOfLabels(j) != 2) {
118  throw RuntimeError("This implementation of QPBO supports only binary variables.");
119  }
120  }
121  for(size_t j = 0; j < gm_.numberOfFactors(); ++j) {
122  if(gm_[j].numberOfVariables() == 2) {
123  ++numPairwiseFactors;
124  }
125  else if(gm_[j].numberOfVariables() > 2) {
126  throw RuntimeError("This implementation of QPBO supports only factors of order <= 2.");
127  }
128  }
129  qpbo_ = new kolmogorov::qpbo::QPBO<ValueType > (numVariables, numPairwiseFactors); // max number of nodes & edges
130  qpbo_->AddNode(numVariables); // add two nodes
131  for(size_t j = 0; j < gm_.numberOfFactors(); ++j) {
132  if(gm_[j].numberOfVariables() == 0) {
133  ; //constTerm_+= gm_[j](0);
134  }
135  else if(gm_[j].numberOfVariables() == 1) {
136  qpbo_->AddUnaryTerm((int) (gm_[j].variableIndex(0)), gm_[j](vec0), gm_[j](vec1));
137  }
138  else if(gm_[j].numberOfVariables() == 2) {
139  qpbo_->AddPairwiseTerm((int) (gm_[j].variableIndex(0)), (int) (gm_[j].variableIndex(1)),
140  gm_[j](vec00), gm_[j](vec01), gm_[j](vec10), gm_[j](vec11));
141  }
142  }
143  qpbo_->MergeParallelEdges();
144  }
145 
146  template<class GM>
147  QPBO<GM>
149  delete label_;
150  delete defaultLabel_;
151  delete qpbo_;
152  }
153 
154  template<class GM>
155  inline std::string
156  QPBO<GM>
157  ::name() const {
158  return "QPBO";
159  }
160 
161  template<class GM>
162  inline const typename QPBO<GM>::GraphicalModelType&
163  QPBO<GM>
165  return gm_;
166  }
167 
168  template<class GM>
169  inline InferenceTermination
170  QPBO<GM>
172  EmptyVisitorType v;
173  return infer(v);
174  }
175 
176  template<class GM>
177  template<class VisitorType>
179  QPBO<GM>::infer(VisitorType& visitor)
180  {
181  visitor.begin(*this);
182  qpbo_->Solve();
183  if(!parameter_.strongPersistency_) {
184  qpbo_->ComputeWeakPersistencies();
185  }
186 
187  bound_ = constTerm_ + 0.5 * qpbo_->ComputeTwiceLowerBound();
188 
189  int countUnlabel = 0;
190  int *listUnlabel = new int[gm_.numberOfVariables()];
191  for(size_t i = 0; i < gm_.numberOfVariables(); ++i) {
192  label_[i] = qpbo_->GetLabel(i);
193  if(label_[i] < 0) {
194  listUnlabel[countUnlabel++] = i;
195  }
196  }
197 
198  // Initialize mapping for probe
199  int *mapping = new int[gm_.numberOfVariables()];
200  for(int i = 0; i < static_cast<int>(gm_.numberOfVariables()); i++) {
201  mapping[i] = i * 2;
202  }
203 
204  /*PROBEING*/
205  if(parameter_.useProbeing_ && countUnlabel > 0) {
206  typename kolmogorov::qpbo::QPBO<ValueType>::ProbeOptions options;
207  //options.C = 1000000000;
208  //options.dilation = 1;
209  options.weak_persistencies = 1;
210  //options.iters = (int)(10);//parameter_.numberOfProbeingIterations_);
211 
212  int *new_mapping = new int[gm_.numberOfVariables()];
213  qpbo_->Probe(new_mapping, options);
214  qpbo_->MergeMappings(gm_.numberOfVariables(), mapping, new_mapping);
215  qpbo_->ComputeWeakPersistencies();
216  delete new_mapping;
217 
218  // Read out entire labelling again (as weak persistencies may have changed)
219  countUnlabel = 0;
220  for(IndexType i = 0; i < gm_.numberOfVariables(); ++i) {
221  label_[i] = qpbo_->GetLabel(mapping[i] / 2);
222  if(label_[i] < 0)
223  listUnlabel[countUnlabel++] = i;
224  else
225  label_[i] = (label_[i] + mapping[i]) % 2;
226  }
227  }
228  if(parameter_.useImproveing_ && countUnlabel > 0) {
229  int *improve_order = new int[countUnlabel];
230 
231  // Set the labels to the user-defined value
232  for(size_t i = 0; static_cast<int>(i) < countUnlabel; i++) {
233  improve_order[i] = mapping[listUnlabel[i]] / 2;
234  qpbo_->SetLabel(improve_order[i], defaultLabel_[improve_order[i]]);
235  }
236 
237  // Randomize order
238  for(int i = 0; i < countUnlabel - 1; ++i) {
239  int j = i + (int) (((double) rand() / ((double) RAND_MAX + 1)) * (countUnlabel - i));
240  OPENGM_ASSERT(j < countUnlabel);
241  int k = improve_order[j];
242  improve_order[j] = improve_order[i];
243  improve_order[i] = k;
244  }
245 
246  // Run QPBO-I
247  qpbo_->Improve(countUnlabel, improve_order);
248  delete improve_order;
249 
250  // Read out the labels
251  for(int i = 0; i < countUnlabel; ++i) {
252  label_[listUnlabel[i]] = (qpbo_->GetLabel(mapping[listUnlabel[i]] / 2) + mapping[listUnlabel[i]]) % 2;
253  }
254  }
255 
256  visitor.end(*this);
257  delete mapping;
258  delete listUnlabel;
259  return NORMAL;
260  }
261 
262  template<class GM>
263  inline InferenceTermination
264  QPBO<GM>
265  ::arg(std::vector<LabelType>& arg, const size_t& n) const {
266  if(n > 1) {
267  return UNKNOWN;
268  }
269  else {
270  arg.resize(gm_.numberOfVariables());
271  for(size_t i = 0; i < gm_.numberOfVariables(); ++i) {
272  if(label_[i] < 0) arg[i] = defaultLabel_[i];
273  else arg[i] = label_[i];
274  }
275  return NORMAL;
276  }
277  }
278 
279  template<class GM>
280  inline InferenceTermination
281  QPBO<GM>
282  ::arg(std::vector<TriBool>& arg, const size_t& n) const {
283  if(n > 1) {
284  return UNKNOWN;
285  }
286  else {
287  arg.resize(gm_.numberOfVariables(), TBX);
288  for(int i = 0; i < gm_.numberOfVariables(); ++i) {
289  if(label_[i] < 0) arg[i] = TBX;
290  if(label_[i] == 0) arg[i] = TB0;
291  else arg[i] = TB1;
292  }
293  return NORMAL;
294  }
295  }
296 
297  template<class GM>
298  double QPBO<GM>::partialOptimality(std::vector<bool>& opt) const
299  {
300  double p=0;
301  opt.resize(gm_.numberOfVariables());
302  for(IndexType i = 0; i < gm_.numberOfVariables(); ++i) {
303  if(label_[i] < 0) {opt[i] = 0;}
304  else {opt[i] = 1; ++p;}
305  }
306  return p/gm_.numberOfVariables();
307  }
308 
309 
310  template<class GM>
311  inline typename GM::ValueType
312  QPBO<GM>
313  ::bound() const {
314  return bound_;//constTerm_ + 0.5 * qpbo_->ComputeTwiceLowerBound();
315  }
316 
317  template<class GM>
318  inline typename GM::ValueType
319  QPBO<GM>
320  ::value() const {
321  std::vector<LabelType> c;
322  arg(c);
323  return gm_.evaluate(c);
324  //return constTerm_ + 0.5 * qpbo_->ComputeTwiceEnergy();
325  }
326 
327  } // namespace external
328 } // namespace opengm
329 
330 #endif // #ifndef OPENGM_EXTERNAL_QPBO_HXX
331 
The OpenGM namespace.
Definition: config.hxx:43
bool useProbeing_
using probeing technique
visitors::VerboseVisitor< QPBO< GM > > VerboseVisitorType
std::vector< size_t > label_
initial configuration for improving
STL namespace.
double partialOptimality(std::vector< bool > &) const
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77
Parameter for opengm::external::QPBO.
opengm::Minimizer AccumulationType
bool strongPersistency_
forcing strong persistency
GraphicalModelType::IndexType IndexType
Definition: inference.hxx:40
GraphicalModelType::ValueType ValueType
Definition: inference.hxx:41
GM GraphicalModelType
Definition: qpbo.hxx:22
QPBO Algorithm.
visitors::TimingVisitor< QPBO< GM > > TimingVisitorType
Inference algorithm interface.
Definition: inference.hxx:34
InferenceTermination arg(std::vector< LabelType > &, const size_t &=1) const
virtual GM::ValueType bound() const
return a bound on the solution
std::string name() const
InferenceTermination infer()
virtual GM::ValueType value() const
return the solution (value)
visitors::EmptyVisitor< QPBO< GM > > EmptyVisitorType
Minimization as a unary accumulation.
Definition: minimizer.hxx:12
bool useImproveing_
using improving technique
QPBO(const GraphicalModelType &gm, const Parameter para=Parameter())
const GraphicalModelType & graphicalModel() const
InferenceTermination
Definition: inference.hxx:24