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