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