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 MP_PARAM>
91  static void initializeSpecialParameter(const GM& gm, MP_PARAM& mpParameter)
92  {}
94  };
95 
96  template<class GM, class BUFFER, class OP, class ACC>
97  inline VariableHullBP<GM, BUFFER, OP, ACC>::VariableHullBP()
98  {}
99 
100  template<class GM, class BUFFER, class OP, class ACC>
101  inline void VariableHullBP<GM, BUFFER, OP, ACC>::assign
102  (
103  const GM& gm,
104  const size_t variableIndex,
105  const meta::EmptyType* et
106  ) {
107  size_t numberOfFactors = gm.numberOfFactors(variableIndex);
108  inBuffer_.resize(numberOfFactors);
109  outBuffer_.resize(numberOfFactors);
110  for(size_t j = 0; j < numberOfFactors; ++j) {
111  inBuffer_[j].assign(gm.numberOfLabels(variableIndex), OP::template neutral<ValueType>());
112  }
113  }
114 
115  template<class GM, class BUFFER, class OP, class ACC>
116  inline size_t VariableHullBP<GM, BUFFER, OP, ACC>::numberOfBuffers() const {
117  return outBuffer_.size();
118  }
119 
120  template<class GM, class BUFFER, class OP, class ACC>
121  inline BUFFER& VariableHullBP<GM, BUFFER, OP, ACC>::connectFactorHullBP
122  (
123  const size_t bufferNumber,
124  BUFFER& variableOutBuffer
125  ) {
126  OPENGM_ASSERT(bufferNumber < numberOfBuffers());
127  outBuffer_[bufferNumber] = &variableOutBuffer;
128  return inBuffer_[bufferNumber];
129  }
130 
131  template<class GM, class BUFFER, class OP, class ACC >
132  inline void VariableHullBP<GM, BUFFER, OP, ACC>::propagate
133  (
134  const GM& gm,
135  const size_t bufferNumber,
136  const ValueType& damping,
137  const bool useNormalization
138  ) {
139  OPENGM_ASSERT(bufferNumber < numberOfBuffers());
140  outBuffer_[bufferNumber]->toggle();
141  if(inBuffer_.size() < 2) {
142  return; // nothing to send
143  }
144  // initialize neutral message
145  BufferArrayType& newMessage = outBuffer_[bufferNumber]->current();
146  opengm::messagepassingOperations::operate<OP>(inBuffer_, bufferNumber, newMessage);
147 
148  // damp message
149  if(damping != 0) {
150  BufferArrayType& oldMessage = outBuffer_[bufferNumber]->old();
151  opengm::messagepassingOperations::weightedMean<OP>(newMessage, oldMessage, damping, newMessage);
152  }
153  // normalize message
154  if(useNormalization) {
155  opengm::messagepassingOperations::normalize<OP,ACC>(newMessage);
156  }
157  }
158 
159 
160  template<class GM, class BUFFER, class OP, class ACC>
161  inline void VariableHullBP<GM, BUFFER, OP, ACC>::propagateAll
162  (
163  const GM& gm,
164  const ValueType& damping,
165  const bool useNormalization
166  ) {
167  for(size_t bufferNumber = 0; bufferNumber < numberOfBuffers(); ++bufferNumber) {
168  propagate(gm, bufferNumber, damping, useNormalization);
169  }
170  }
171 
172  template<class GM, class BUFFER, class OP, class ACC >
173  inline void VariableHullBP<GM, BUFFER, OP, ACC>::marginal
174  (
175  const GM& gm,
176  const size_t variableIndex,
177  IndependentFactorType& out,
178  const bool useNormalization
179  ) const {
180 
181  // set out to neutral
182  out.assign(gm, &variableIndex, &variableIndex+1, OP::template neutral<ValueType>());
183  opengm::messagepassingOperations::operate<OP>(inBuffer_, out);
184 
185  // normalize output
186  if(useNormalization) {
187  opengm::messagepassingOperations::normalize<OP,ACC>(out);
188  }
189  }
190 /*
191  template<class GM, class BUFFER, class OP, class ACC>
192  inline typename GM::ValueType VariableHullBP<GM, BUFFER, OP, ACC>::bound() const
193  {
194  ValueType v;
195  //OP::neutral(v);
196 
197  BufferArrayType a(inBuffer_[0].current().shapeBegin(),inBuffer_[0].current().shapeEnd());
198  opengm::messagepassingOperations::operate<OP>(inBuffer_, a);
199 
200  if(typeid(ACC)==typeid(opengm::Minimizer) || typeid(ACC)==typeid(opengm::Maximizer)) {
201  v = a(0);
202  for(size_t n=1; n<a.size(); ++n) {
203  ACC::op(a(n),v);
204  }
205  }
206  else{
207  ACC::ineutral(v);
208  }
209  //ACC::ineutral(v);
210 
211  //v = opengm::messagepassingOperations::template boundOperation<ValueType,OP,ACC>(a,a);
212 // ACC::ineutral(v);
213  return v;
214  }
215 */
216 
217  template<class GM, class BUFFER, class OP, class ACC >
218  template<class DIST>
219  inline typename GM::ValueType VariableHullBP<GM, BUFFER, OP, ACC>::distance
220  (
221  const size_t bufferNumber
222  ) const {
223  return inBuffer_[bufferNumber].template dist<DIST > ();
224  }
225 
226  template<class GM, class BUFFER, class OP, class ACC >
227  inline const typename BUFFER::ArrayType& VariableHullBP<GM, BUFFER, OP, ACC>::outBuffer
228  (
229  const size_t bufferIndex
230  ) const {
231  OPENGM_ASSERT(bufferIndex < outBuffer_.size());
232  return outBuffer_[bufferIndex]->current();
233  }
234 
235  template<class GM, class BUFFER, class OP, class ACC>
236  inline void FactorHullBP<GM, BUFFER, OP, ACC>::assign
237  (
238  const GM& gm,
239  const size_t factorIndex,
240  std::vector<VariableHullBP<GM, BUFFER, OP, ACC> >& variableHulls,
241  const meta::EmptyType* et
242  ) {
243  myFactor_ = (FactorType *const)(&gm[factorIndex]);
244  inBuffer_.resize(gm[factorIndex].numberOfVariables());
245  outBuffer_.resize(gm[factorIndex].numberOfVariables());
246  for(size_t n=0; n<gm.numberOfVariables(factorIndex); ++n) {
247  size_t variableIndex = gm.variableOfFactor(factorIndex,n);
248  inBuffer_[n].assign(gm.numberOfLabels(variableIndex), OP::template neutral<ValueType > ());
249  size_t bufferNumber = 1000000;
250  for(size_t i=0; i<gm.numberOfFactors(variableIndex); ++i) {
251  if(gm.factorOfVariable(variableIndex,i) == factorIndex) {
252  bufferNumber=i;
253  break;
254  }
255  }
256  outBuffer_[n] =&(variableHulls[variableIndex].connectFactorHullBP(bufferNumber, inBuffer_[n]));
257  }
258  }
259 
260  template<class GM, class BUFFER, class OP, class ACC >
261  inline void FactorHullBP<GM, BUFFER, OP, ACC>::propagate
262  (
263  const size_t id,
264  const ValueType& damping,
265  const bool useNormalization
266  ) {
267  OPENGM_ASSERT(id < outBuffer_.size());
268  outBuffer_[id]->toggle();
269  BufferArrayType& newMessage = outBuffer_[id]->current();
270  opengm::messagepassingOperations::operateF<GM,ACC>(*myFactor_, inBuffer_, id, newMessage);
271 
272  // damp message
273  if(damping != 0) {
274  BufferArrayType& oldMessage = outBuffer_[id]->old();
275  opengm::messagepassingOperations::weightedMean<OP>(newMessage, oldMessage, damping, newMessage);
276  }
277  // normalize message
278  if(useNormalization) {
279  opengm::messagepassingOperations::normalize<OP,ACC>(newMessage);
280  }
281  }
282 
283  template<class GM, class BUFFER, class OP, class ACC >
284  inline void FactorHullBP<GM, BUFFER, OP, ACC>::propagateAll
285  (
286  const ValueType& damping,
287  const bool useNormalization
288  ) {
289  for(size_t j = 0; j < inBuffer_.size(); ++j) {
290  propagate(j, damping, useNormalization);
291  }
292  }
293 
294  template<class GM, class BUFFER, class OP, class ACC>
295  inline void FactorHullBP<GM, BUFFER, OP, ACC>::marginal
296  (
297  IndependentFactorType& out,
298  const bool useNormalization
299  ) const
300  {
301  opengm::messagepassingOperations::operateF<GM>(*myFactor_, inBuffer_,out);
302 
303  if(useNormalization) {
304  opengm::messagepassingOperations::normalize<OP,ACC>(out);
305  }
306  }
307 /*
308  template<class GM, class BUFFER, class OP, class ACC>
309  inline typename GM::ValueType FactorHullBP<GM, BUFFER, OP, ACC>::bound
310  () const
311  {
312  //typename GM::IndependentFactorType a = myFactor_;
313  typename GM::IndependentFactorType a = *myFactor_;
314  //opengm::messagepassingOperations::operateF<GM>(*myFactor_, inBuffer_,a);
315  opengm::messagepassingOperations::operateFi<GM>(*myFactor_, outBuffer_, a);
316  //return opengm::messagepassingOperations::boundOperation<ValueType,OP,ACC>(a,b);
317  ValueType v;
318  if(typeid(ACC)==typeid(opengm::Minimizer) || typeid(ACC)==typeid(opengm::Maximizer)) {
319  v = a(0);
320  for(size_t n=1; n<a.size(); ++n) {
321  ACC::op(a(n),v);
322  }
323  }
324  else{
325  ACC::ineutral(v);
326  }
327  return v;
328  }
329 */
330  template<class GM, class BUFFER, class OP, class ACC >
331  template<class DIST>
332  inline typename GM::ValueType FactorHullBP<GM, BUFFER, OP, ACC>::distance
333  (
334  const size_t j
335  ) const {
336  return inBuffer_[j].template dist<DIST > ();
337  }
338 
339 } // namespace opengm
340 
341 #endif // #ifndef OPENGM_BELIEFPROPAGATION_HXX
342 
Update rules for the MessagePassing framework.
The OpenGM namespace.
Definition: config.hxx:43
GM::IndependentFactorType IndependentFactorType
#define OPENGM_ASSERT(expression)
Definition: opengm.hxx:77