OpenGM  2.3.x
Discrete Graphical Model Library
messagepassing_bp.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_BELIEFPROPAGATION_HXX
3 #define OPENGM_BELIEFPROPAGATION_HXX
4 
5 #include <vector>
6 #include <map>
7 #include <list>
8 #include <set>
9 
10 #include "opengm/opengm.hxx"
17 
18 namespace opengm {
19 
21 
22  template<class GM, class BUFFER, class OP, class ACC>
23  class VariableHullBP {
24  public:
25  typedef GM GraphicalModelType;
26  typedef BUFFER BufferType;
27  typedef typename BUFFER::ArrayType BufferArrayType;
28  typedef typename GM::FactorType FactorType;
29  typedef typename GM::IndependentFactorType IndependentFactorType;
30  typedef typename GM::ValueType ValueType;
31 
32  VariableHullBP();
33  void assign(const GM&, const size_t, const meta::EmptyType*);
34  BUFFER& connectFactorHullBP(const size_t, BUFFER&);
35  size_t numberOfBuffers() const;
36  void propagateAll(const GM&, const ValueType& = 0, const bool = false);
37  void propagate(const GM&, const size_t, const ValueType& = 0, const bool = false);
38  void marginal(const GM&, const size_t, IndependentFactorType&, const bool = true) const;
39  //typename GM::ValueType bound() const;
40  template<class DIST> ValueType distance(const size_t) const;
41  const typename BUFFER::ArrayType& outBuffer(const size_t) const;
42 
43  private:
44  std::vector<BUFFER* > outBuffer_;
45  std::vector<BUFFER > inBuffer_;
46  };
47 
48  template<class GM, class BUFFER, class OP, class ACC>
49  class FactorHullBP {
50  public:
51  typedef GM GraphicalModelType;
52  typedef BUFFER BufferType;
53  typedef typename BUFFER::ArrayType BufferArrayType;
54  typedef typename GM::FactorType FactorType;
55  typedef typename GM::IndependentFactorType IndependentFactorType;
56  typedef typename GM::ValueType ValueType;
57 
58  size_t numberOfBuffers() const { return inBuffer_.size(); }
59  void assign(const GM&, const size_t, std::vector<VariableHullBP<GM,BUFFER,OP,ACC> >&, const meta::EmptyType*);
60  void propagateAll(const ValueType& = 0, const bool = true);
61  void propagate(const size_t, const ValueType& = 0, const bool = true);
62  void marginal(IndependentFactorType&, const bool = true) const;
63  //typename GM::ValueType bound() const;
64  template<class DIST> ValueType distance(const size_t) const;
65 
66  private:
67  FactorType const* myFactor_;
68  std::vector<BUFFER* > outBuffer_;
69  std::vector<BUFFER > inBuffer_;
70  };
71 
73 
75  template<class GM, class ACC, class BUFFER = MessageBuffer<marray::Marray<double> > >
77  public:
78  typedef GM GraphicalModelType;
79  typedef BUFFER BufferType;
80  typedef typename BUFFER::ArrayType BufferArrayType;
81  typedef typename GM::ValueType ValueType;
82  typedef typename GM::IndependentFactorType IndependentFactorType;
83  typedef typename GM::FactorType FactorType;
84  typedef typename GM::OperatorType OperatorType;
86  typedef FactorHullBP<GM, BufferType, OperatorType, ACC> FactorHullType;
87  typedef VariableHullBP<GM, BufferType, OperatorType, ACC> VariableHullType;
88  typedef meta::EmptyType SpecialParameterType;
89 
90  template<class _GM>
91  struct RebindGm{
93  };
94 
95  template<class _GM,class _ACC>
96  struct RebindGmAndAcc{
98  };
99 
100 
101  template<class MP_PARAM>
102  static void initializeSpecialParameter(const GM& gm, MP_PARAM& mpParameter)
103  {}
105  };
106 
107  template<class GM, class BUFFER, class OP, class ACC>
108  inline VariableHullBP<GM, BUFFER, OP, ACC>::VariableHullBP()
109  {}
110 
111  template<class GM, class BUFFER, class OP, class ACC>
112  inline void VariableHullBP<GM, BUFFER, OP, ACC>::assign
113  (
114  const GM& gm,
115  const size_t variableIndex,
116  const meta::EmptyType* et
117  ) {
118  size_t numberOfFactors = gm.numberOfFactors(variableIndex);
119  inBuffer_.resize(numberOfFactors);
120  outBuffer_.resize(numberOfFactors);
121  for(size_t j = 0; j < numberOfFactors; ++j) {
122  inBuffer_[j].assign(gm.numberOfLabels(variableIndex), OP::template neutral<ValueType>());
123  }
124  }
125 
126  template<class GM, class BUFFER, class OP, class ACC>
127  inline size_t VariableHullBP<GM, BUFFER, OP, ACC>::numberOfBuffers() const {
128  return outBuffer_.size();
129  }
130 
131  template<class GM, class BUFFER, class OP, class ACC>
132  inline BUFFER& VariableHullBP<GM, BUFFER, OP, ACC>::connectFactorHullBP
133  (
134  const size_t bufferNumber,
135  BUFFER& variableOutBuffer
136  ) {
137  OPENGM_ASSERT(bufferNumber < numberOfBuffers());
138  outBuffer_[bufferNumber] = &variableOutBuffer;
139  return inBuffer_[bufferNumber];
140  }
141 
142  template<class GM, class BUFFER, class OP, class ACC >
143  inline void VariableHullBP<GM, BUFFER, OP, ACC>::propagate
144  (
145  const GM& gm,
146  const size_t bufferNumber,
147  const ValueType& damping,
148  const bool useNormalization
149  ) {
150  OPENGM_ASSERT(bufferNumber < numberOfBuffers());
151  outBuffer_[bufferNumber]->toggle();
152  if(inBuffer_.size() < 2) {
153  return; // nothing to send
154  }
155  // initialize neutral message
156  BufferArrayType& newMessage = outBuffer_[bufferNumber]->current();
157  opengm::messagepassingOperations::operate<OP>(inBuffer_, bufferNumber, newMessage);
158 
159  // damp message
160  if(damping != 0) {
161  BufferArrayType& oldMessage = outBuffer_[bufferNumber]->old();
162  opengm::messagepassingOperations::weightedMean<OP>(newMessage, oldMessage, damping, newMessage);
163  }
164  // normalize message
165  if(useNormalization) {
166  opengm::messagepassingOperations::normalize<OP,ACC>(newMessage);
167  }
168  }
169 
170 
171  template<class GM, class BUFFER, class OP, class ACC>
172  inline void VariableHullBP<GM, BUFFER, OP, ACC>::propagateAll
173  (
174  const GM& gm,
175  const ValueType& damping,
176  const bool useNormalization
177  ) {
178  for(size_t bufferNumber = 0; bufferNumber < numberOfBuffers(); ++bufferNumber) {
179  propagate(gm, bufferNumber, damping, useNormalization);
180  }
181  }
182 
183  template<class GM, class BUFFER, class OP, class ACC >
184  inline void VariableHullBP<GM, BUFFER, OP, ACC>::marginal
185  (
186  const GM& gm,
187  const size_t variableIndex,
189  const bool useNormalization
190  ) const {
191 
192  // set out to neutral
193  out.assign(gm, &variableIndex, &variableIndex+1, OP::template neutral<ValueType>());
194  opengm::messagepassingOperations::operate<OP>(inBuffer_, out);
195 
196  // normalize output
197  if(useNormalization) {
198  opengm::messagepassingOperations::normalize<OP,ACC>(out);
199  }
200  }
201 /*
202  template<class GM, class BUFFER, class OP, class ACC>
203  inline typename GM::ValueType VariableHullBP<GM, BUFFER, OP, ACC>::bound() const
204  {
205  ValueType v;
206  //OP::neutral(v);
207 
208  BufferArrayType a(inBuffer_[0].current().shapeBegin(),inBuffer_[0].current().shapeEnd());
209  opengm::messagepassingOperations::operate<OP>(inBuffer_, a);
210 
211  if(typeid(ACC)==typeid(opengm::Minimizer) || typeid(ACC)==typeid(opengm::Maximizer)) {
212  v = a(0);
213  for(size_t n=1; n<a.size(); ++n) {
214  ACC::op(a(n),v);
215  }
216  }
217  else{
218  ACC::ineutral(v);
219  }
220  //ACC::ineutral(v);
221 
222  //v = opengm::messagepassingOperations::template boundOperation<ValueType,OP,ACC>(a,a);
223 // ACC::ineutral(v);
224  return v;
225  }
226 */
227 
228  template<class GM, class BUFFER, class OP, class ACC >
229  template<class DIST>
230  inline typename GM::ValueType VariableHullBP<GM, BUFFER, OP, ACC>::distance
231  (
232  const size_t bufferNumber
233  ) const {
234  return inBuffer_[bufferNumber].template dist<DIST > ();
235  }
236 
237  template<class GM, class BUFFER, class OP, class ACC >
238  inline const typename BUFFER::ArrayType& VariableHullBP<GM, BUFFER, OP, ACC>::outBuffer
239  (
240  const size_t bufferIndex
241  ) const {
242  OPENGM_ASSERT(bufferIndex < outBuffer_.size());
243  return outBuffer_[bufferIndex]->current();
244  }
245 
246  template<class GM, class BUFFER, class OP, class ACC>
247  inline void FactorHullBP<GM, BUFFER, OP, ACC>::assign
248  (
249  const GM& gm,
250  const size_t factorIndex,
251  std::vector<VariableHullBP<GM, BUFFER, OP, ACC> >& variableHulls,
252  const meta::EmptyType* et
253  ) {
254  myFactor_ = (FactorType *const)(&gm[factorIndex]);
255  inBuffer_.resize(gm[factorIndex].numberOfVariables());
256  outBuffer_.resize(gm[factorIndex].numberOfVariables());
257  for(size_t n=0; n<gm.numberOfVariables(factorIndex); ++n) {
258  size_t variableIndex = gm.variableOfFactor(factorIndex,n);
259  inBuffer_[n].assign(gm.numberOfLabels(variableIndex), OP::template neutral<ValueType > ());
260  size_t bufferNumber = 1000000;
261  for(size_t i=0; i<gm.numberOfFactors(variableIndex); ++i) {
262  if(gm.factorOfVariable(variableIndex,i) == factorIndex) {
263  bufferNumber=i;
264  break;
265  }
266  }
267  outBuffer_[n] =&(variableHulls[variableIndex].connectFactorHullBP(bufferNumber, inBuffer_[n]));
268  }
269  }
270 
271  template<class GM, class BUFFER, class OP, class ACC >
272  inline void FactorHullBP<GM, BUFFER, OP, ACC>::propagate
273  (
274  const size_t id,
275  const ValueType& damping,
276  const bool useNormalization
277  ) {
278  OPENGM_ASSERT(id < outBuffer_.size());
279  outBuffer_[id]->toggle();
280  BufferArrayType& newMessage = outBuffer_[id]->current();
281  opengm::messagepassingOperations::operateF<GM,ACC>(*myFactor_, inBuffer_, id, newMessage);
282 
283  // damp message
284  if(damping != 0) {
285  BufferArrayType& oldMessage = outBuffer_[id]->old();
286  opengm::messagepassingOperations::weightedMean<OP>(newMessage, oldMessage, damping, newMessage);
287  }
288  // normalize message
289  if(useNormalization) {
290  opengm::messagepassingOperations::normalize<OP,ACC>(newMessage);
291  }
292  }
293 
294  template<class GM, class BUFFER, class OP, class ACC >
295  inline void FactorHullBP<GM, BUFFER, OP, ACC>::propagateAll
296  (
297  const ValueType& damping,
298  const bool useNormalization
299  ) {
300  for(size_t j = 0; j < inBuffer_.size(); ++j) {
301  propagate(j, damping, useNormalization);
302  }
303  }
304 
305  template<class GM, class BUFFER, class OP, class ACC>
306  inline void FactorHullBP<GM, BUFFER, OP, ACC>::marginal
307  (
309  const bool useNormalization
310  ) const
311  {
312  opengm::messagepassingOperations::operateF<GM>(*myFactor_, inBuffer_,out);
313 
314  if(useNormalization) {
315  opengm::messagepassingOperations::normalize<OP,ACC>(out);
316  }
317  }
318 /*
319  template<class GM, class BUFFER, class OP, class ACC>
320  inline typename GM::ValueType FactorHullBP<GM, BUFFER, OP, ACC>::bound
321  () const
322  {
323  //typename GM::IndependentFactorType a = myFactor_;
324  typename GM::IndependentFactorType a = *myFactor_;
325  //opengm::messagepassingOperations::operateF<GM>(*myFactor_, inBuffer_,a);
326  opengm::messagepassingOperations::operateFi<GM>(*myFactor_, outBuffer_, a);
327  //return opengm::messagepassingOperations::boundOperation<ValueType,OP,ACC>(a,b);
328  ValueType v;
329  if(typeid(ACC)==typeid(opengm::Minimizer) || typeid(ACC)==typeid(opengm::Maximizer)) {
330  v = a(0);
331  for(size_t n=1; n<a.size(); ++n) {
332  ACC::op(a(n),v);
333  }
334  }
335  else{
336  ACC::ineutral(v);
337  }
338  return v;
339  }
340 */
341  template<class GM, class BUFFER, class OP, class ACC >
342  template<class DIST>
343  inline typename GM::ValueType FactorHullBP<GM, BUFFER, OP, ACC>::distance
344  (
345  const size_t j
346  ) const {
347  return inBuffer_[j].template dist<DIST > ();
348  }
349 
350 } // namespace opengm
351 
352 #endif // #ifndef OPENGM_BELIEFPROPAGATION_HXX
353 
Update rules for the MessagePassing framework.
The OpenGM namespace.
Definition: config.hxx:43
GM::IndependentFactorType IndependentFactorType
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77