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