OpenGM  2.3.x
Discrete Graphical Model Library
qpbo.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_QPBO_HXX
3 #define OPENGM_QPBO_HXX
4 
11 
12 namespace opengm {
13 
18 template<class GM, class MIN_ST_CUT>
19 class QPBO : public Inference<GM, opengm::Minimizer>
20 {
21 public:
22  typedef GM GraphicalModelType;
28 
29  template<class _GM>
30  struct RebindGm{
32  };
33 
34  template<class _GM,class _ACC>
37  };
38 
39 
40  struct Parameter{
41  Parameter ( ) {};
42  template<class P>
43  Parameter (const P & p) {};
44  };
45 
46  QPBO(const GraphicalModelType&, Parameter = Parameter());
47  std::string name() const;
48  const GraphicalModelType& graphicalModel() const;
50  template<class VISITOR>
51  InferenceTermination infer(VISITOR &);
52  InferenceTermination arg(std::vector<LabelType>&, const size_t& = 1) const;
53  double partialOptimality(std::vector<bool>&) const;
54 
55 private:
56  void addUnaryFactorType(const FactorType& factor);
57  void addUnaryFactorType(size_t var, ValueType value0, ValueType value1);
58  void addEdgeCapacity(size_t v,size_t w, ValueType val);
59  void addPairwiseFactorType(const FactorType& factor);
60  void addPairwiseFactorType(size_t var0,size_t var1,ValueType A,ValueType B,ValueType C,ValueType D);
61 
62  // get the index of the opposite literal in the graph_
63  size_t neg(size_t var) const { return (var+numVars_)%(2*numVars_); }
64 
65  const GraphicalModelType& gm_;
66  //std::vector<LabelType> state_;
67  std::vector<bool> stateBool_;
68  size_t numVars_;
69  ValueType constTerm_;
70  MIN_ST_CUT minStCut_;
71  ValueType tolerance_;
72  size_t source_;
73  size_t sink_;
74 };
75 
76 template<class GM,class MIN_ST_CUT>
78 (
79  const GM & gm,
81 )
82 : gm_(gm),
83  numVars_(gm_.numberOfVariables()),
84  minStCut_(2*gm_.numberOfVariables()+2, 6*gm_.numberOfVariables())
85 {
86  constTerm_ = 0;
87  source_ = 2*numVars_;
88  sink_ = 2*numVars_ + 1;
89 
90  // add pairwise factors
91  for(size_t j=0; j<gm_.numberOfFactors(); ++j) {
92  switch (gm_[j].numberOfVariables()) {
93  case 0:
94  {
95  size_t c[]={0};
96  constTerm_ += gm_[j](c);
97  }
98  break;
99  case 1:
100  addUnaryFactorType(gm_[j]);
101  break;
102  case 2:
103  addPairwiseFactorType(gm_[j]);
104  break;
105  default: throw std::runtime_error("This implementation of the QPBO optimizer does not support factors of order >2.");
106  }
107  }
108 }
109 
110 template<class GM,class MIN_ST_CUT>
111 inline std::string
113 {
114  return "QPBO";
115 }
116 
117 template<class GM,class MIN_ST_CUT>
118 inline const typename QPBO<GM,MIN_ST_CUT>::GraphicalModelType&
120 {
121  return gm_;
122 }
123 
124 template<class GM,class MIN_ST_CUT>
128  return infer(v);
129 }
130 
131 template<class GM,class MIN_ST_CUT>
132 template<class VISITOR>
134 QPBO<GM,MIN_ST_CUT>::infer(VISITOR & visitor)
135 {
136  visitor.begin(*this);
137  minStCut_.calculateCut(stateBool_);
138  visitor.end(*this);
139  return NORMAL;
140 }
141 
142 template<class GM,class MIN_ST_CUT>
145 (
146  std::vector<LabelType>& arg,
147  const size_t& n
148  ) const
149 {
150  if(n > 1) {
151  return UNKNOWN;
152  }
153  else {
154  arg.resize(numVars_);
155  for(size_t j=0; j<arg.size(); ++j) {
156  if (stateBool_[j+2] == true && stateBool_[neg(j)+2] == false)
157  arg[j] = 1;
158  else if (stateBool_[j+2] == false && stateBool_[neg(j)+2] == true)
159  arg[j] = 0;
160  else
161  arg[j] = 0; // select 0 or 1
162  }
163  return NORMAL;
164  }
165 }
166 
167 template<class GM,class MIN_ST_CUT>
168 double
170 (
171  std::vector<bool>& optVec
172  ) const
173 {
174  double opt = 0;
175  optVec.resize(numVars_);
176  for(size_t j=0; j<optVec.size(); ++j)
177  if (stateBool_[j+2] != stateBool_[neg(j)+2]) {
178  optVec[j] = true;
179  opt++;
180  } else
181  optVec[j] = false;
182 
183  return opt/gm_.numerOfVariables();
184 }
185 
186 template<class GM,class MIN_ST_CUT>
187 void inline
188 QPBO<GM,MIN_ST_CUT>::addEdgeCapacity(size_t v, size_t w, ValueType val)
189 {
190  minStCut_.addEdge((v+2)%(2*numVars_+2),(w+2)%(2*numVars_+2),val);
191 }
192 
193 template<class GM,class MIN_ST_CUT>
194 void
196 {
197  // indices of literal nodes in graph_
198  size_t x_i = factor.variableIndex(0);
199  size_t nx_i = neg(x_i);
200 
201  // conversion to normal form on-the-fly: c_[n]x_i are the new
202  // values of the unary factor.
203  size_t c[]={0};
204  ValueType c_nx_i = factor(c);
205  c[0]=1;
206  ValueType c_x_i = factor(c);
207 
208  // has to be zero
209  ValueType delta = std::min(c_nx_i, c_x_i);
210  c_nx_i -= delta;
211  c_x_i -= delta;
212  constTerm_ += delta;
213 
214  addEdgeCapacity(x_i, sink_, 0.5*c_nx_i);
215  addEdgeCapacity(source_, nx_i, 0.5*c_nx_i);
216 
217  addEdgeCapacity(nx_i, sink_, 0.5*c_x_i);
218  addEdgeCapacity(source_, x_i, 0.5*c_x_i);
219 }
220 
221 template<class GM,class MIN_ST_CUT>
222 void
224 (
225  const FactorType& factor
226 ) {
227  // indices of literal nodes in graph_
228  size_t x_i = factor.variableIndex(0);
229  size_t x_j = factor.variableIndex(1);
230  size_t nx_i = neg(x_i);
231  size_t nx_j = neg(x_j);
232 
233  // conversion to normal form on-the-fly: c_[n]x_i_[n]x_j are the new
234  // values of the pairwise factors. delta_c_[n]x_{i,j} are changes that have
235  // to be made to the unary factors.
236 
237  size_t c[]={0,0};
238  ValueType c_nx_i_nx_j = factor(c);
239  c[1]=1;
240  ValueType c_nx_i_x_j = factor(c);
241  c[0]=1;
242  c[1]=0;
243  ValueType c_x_i_nx_j = factor(c);
244  c[1]=1;
245  ValueType c_x_i_x_j = factor(c);
246 
247  ValueType delta_c_nx_j = 0;
248  ValueType delta_c_x_j = 0;
249  ValueType delta_c_nx_i = 0;
250  ValueType delta_c_x_i = 0;
251 
252  // hast to be zero
253  ValueType delta = std::min(c_nx_i_nx_j, c_x_i_nx_j);
254  if (delta != 0) {
255 
256  c_nx_i_nx_j -= delta;
257  c_x_i_nx_j -= delta;
258  delta_c_nx_j += delta;
259  }
260 
261  // has to be zero
262  delta = std::min(c_nx_i_x_j, c_x_i_x_j);
263  if (delta != 0) {
264 
265  c_nx_i_x_j -= delta;
266  c_x_i_x_j -= delta;
267  delta_c_x_j += delta;
268  }
269 
270  // has to be zero
271  delta = std::min(c_nx_i_nx_j, c_nx_i_x_j);
272  if (delta != 0) {
273 
274  c_nx_i_nx_j -= delta;
275  c_nx_i_x_j -= delta;
276  delta_c_nx_i += delta;
277  }
278 
279  // has to be zero
280  delta = std::min(c_x_i_nx_j, c_x_i_x_j);
281  if (delta != 0) {
282 
283  c_x_i_nx_j -= delta;
284  c_x_i_x_j -= delta;
285  delta_c_x_i += delta;
286  }
287 
288  // for every non-zero c_[n]x_i_[n]x_j add two edges to the flow network
289 
290  if (c_nx_i_nx_j != 0) {
291  addEdgeCapacity(x_i, nx_j, 0.5*c_nx_i_nx_j);
292  addEdgeCapacity(x_j, nx_i, 0.5*c_nx_i_nx_j);
293  }
294  if (c_nx_i_x_j != 0) {
295  addEdgeCapacity(x_i, x_j, 0.5*c_nx_i_x_j);
296  addEdgeCapacity(nx_j, nx_i, 0.5*c_nx_i_x_j);
297  }
298  if (c_x_i_nx_j != 0) {
299  addEdgeCapacity(nx_i, nx_j, 0.5*c_x_i_nx_j);
300  addEdgeCapacity(x_j, x_i, 0.5*c_x_i_nx_j);
301  }
302  if (c_x_i_x_j != 0) {
303  addEdgeCapacity(nx_i, x_j, 0.5*c_x_i_x_j);
304  addEdgeCapacity(nx_j, x_i, 0.5*c_x_i_x_j);
305  }
306 
307  // for every non-zero c_[n]x_{i,j} add two edges to the flow network
308 
309  if (delta_c_nx_j != 0) {
310  addEdgeCapacity(x_j, sink_, 0.5*delta_c_nx_j);
311  addEdgeCapacity(source_, nx_j, 0.5*delta_c_nx_j);
312  }
313  if (delta_c_x_j != 0) {
314  addEdgeCapacity(nx_j, sink_, 0.5*delta_c_x_j);
315  addEdgeCapacity(source_, x_j, 0.5*delta_c_x_j);
316  }
317  if (delta_c_nx_i != 0) {
318  addEdgeCapacity(x_i, sink_, 0.5*delta_c_nx_i);
319  addEdgeCapacity(source_, nx_i, 0.5*delta_c_nx_i);
320  }
321  if (delta_c_x_i != 0) {
322  addEdgeCapacity(nx_i, sink_, 0.5*delta_c_x_i);
323  addEdgeCapacity(source_, x_i, 0.5*delta_c_x_i);
324  }
325 }
326 
327 } // namespace opengm
328 
329 #endif // #ifndef OPENGM_EXTERNAL_QPBO_HXX
OPENGM_GM_TYPE_TYPEDEFS
Definition: qpbo.hxx:24
The OpenGM namespace.
Definition: config.hxx:43
QPBO< _GM, MIN_ST_CUT > type
Definition: qpbo.hxx:31
visitors::TimingVisitor< QPBO< GM, MIN_ST_CUT > > TimingVisitorType
Definition: qpbo.hxx:26
QPBO(const GraphicalModelType &, Parameter=Parameter())
Parameter(const P &p)
Definition: qpbo.hxx:43
const GraphicalModelType & graphicalModel() const
Definition: qpbo.hxx:119
GraphicalModelType::FactorType FactorType
Definition: inference.hxx:52
double partialOptimality(std::vector< bool > &) const
Definition: qpbo.hxx:170
visitors::EmptyVisitor< QPBO< GM, MIN_ST_CUT > > EmptyVisitorType
Definition: qpbo.hxx:27
GraphicalModelType::ValueType ValueType
Definition: inference.hxx:50
GM GraphicalModelType
Definition: qpbo.hxx:22
QPBO Algorithm C. Rother, V. Kolmogorov, V. Lempitsky, and M. Szummer, "Optimizing binary MRFs via e...
Definition: qpbo.hxx:19
Inference algorithm interface.
Definition: inference.hxx:43
opengm::Minimizer AccumulationType
Definition: qpbo.hxx:23
InferenceTermination infer()
Definition: qpbo.hxx:126
visitors::VerboseVisitor< QPBO< GM, MIN_ST_CUT > > VerboseVisitorType
Definition: qpbo.hxx:25
QPBO< _GM,MIN_ST_CUT > type
Definition: qpbo.hxx:36
Minimization as a unary accumulation.
Definition: minimizer.hxx:12
std::string name() const
Definition: qpbo.hxx:112
InferenceTermination arg(std::vector< LabelType > &, const size_t &=1) const
Definition: qpbo.hxx:145
InferenceTermination
Definition: inference.hxx:24