00001 #pragma once
00002 #ifndef OPENGM_BELIEFPROPAGATION_HXX
00003 #define OPENGM_BELIEFPROPAGATION_HXX
00004
00005 #include <vector>
00006 #include <map>
00007 #include <list>
00008 #include <set>
00009
00010 #include "opengm/opengm.hxx"
00011 #include "opengm/utilities/tribool.hxx"
00012 #include "opengm/operations/weightedoperations.hxx"
00013 #include "opengm/operations/normalize.hxx"
00014 #include "opengm/utilities/metaprogramming.hxx"
00015 #include "opengm/inference/messagepassing/messagepassing_operations.hxx"
00016 #include "opengm/inference/messagepassing/messagepassing_buffer.hxx"
00017
00018 namespace opengm {
00019
00021
00022 template<class GM, class BUFFER, class OP, class ACC>
00023 class VariableHullBP {
00024 public:
00025 typedef GM GraphicalModelType;
00026 typedef BUFFER BufferType;
00027 typedef typename BUFFER::ArrayType BufferArrayType;
00028 typedef typename GM::FactorType FactorType;
00029 typedef typename GM::IndependentFactorType IndependentFactorType;
00030 typedef typename GM::ValueType ValueType;
00031
00032 VariableHullBP();
00033 void assign(const GM&, const size_t, const meta::EmptyType*);
00034 BUFFER& connectFactorHullBP(const size_t, BUFFER&);
00035 size_t numberOfBuffers() const;
00036 void propagateAll(const GM&, const ValueType& = 0, const bool = false);
00037 void propagate(const GM&, const size_t, const ValueType& = 0, const bool = false);
00038 void marginal(const GM&, const size_t, IndependentFactorType&, const bool = true) const;
00039
00040 template<class DIST> ValueType distance(const size_t) const;
00041 const typename BUFFER::ArrayType& outBuffer(const size_t) const;
00042
00043 private:
00044 std::vector<BUFFER* > outBuffer_;
00045 std::vector<BUFFER > inBuffer_;
00046 };
00047
00048 template<class GM, class BUFFER, class OP, class ACC>
00049 class FactorHullBP {
00050 public:
00051 typedef GM GraphicalModelType;
00052 typedef BUFFER BufferType;
00053 typedef typename BUFFER::ArrayType BufferArrayType;
00054 typedef typename GM::FactorType FactorType;
00055 typedef typename GM::IndependentFactorType IndependentFactorType;
00056 typedef typename GM::ValueType ValueType;
00057
00058 size_t numberOfBuffers() const { return inBuffer_.size(); }
00059 void assign(const GM&, const size_t, std::vector<VariableHullBP<GM,BUFFER,OP,ACC> >&, const meta::EmptyType*);
00060 void propagateAll(const ValueType& = 0, const bool = true);
00061 void propagate(const size_t, const ValueType& = 0, const bool = true);
00062 void marginal(IndependentFactorType&, const bool = true) const;
00063
00064 template<class DIST> ValueType distance(const size_t) const;
00065
00066 private:
00067 FactorType const* myFactor_;
00068 std::vector<BUFFER* > outBuffer_;
00069 std::vector<BUFFER > inBuffer_;
00070 };
00071
00073
00075 template<class GM, class ACC, class BUFFER = MessageBuffer<marray::Marray<double> > >
00076 class BeliefPropagationUpdateRules {
00077 public:
00078 typedef GM GraphicalModelType;
00079 typedef BUFFER BufferType;
00080 typedef typename BUFFER::ArrayType BufferArrayType;
00081 typedef typename GM::ValueType ValueType;
00082 typedef typename GM::IndependentFactorType IndependentFactorType;
00083 typedef typename GM::FactorType FactorType;
00084 typedef typename GM::OperatorType OperatorType;
00086 typedef FactorHullBP<GM, BufferType, OperatorType, ACC> FactorHullType;
00087 typedef VariableHullBP<GM, BufferType, OperatorType, ACC> VariableHullType;
00088 typedef meta::EmptyType SpecialParameterType;
00089
00090 template<class MP_PARAM>
00091 static void initializeSpecialParameter(const GM& gm, MP_PARAM& mpParameter)
00092 {}
00094 };
00095
00096 template<class GM, class BUFFER, class OP, class ACC>
00097 inline VariableHullBP<GM, BUFFER, OP, ACC>::VariableHullBP()
00098 {}
00099
00100 template<class GM, class BUFFER, class OP, class ACC>
00101 inline void VariableHullBP<GM, BUFFER, OP, ACC>::assign
00102 (
00103 const GM& gm,
00104 const size_t variableIndex,
00105 const meta::EmptyType* et
00106 ) {
00107 size_t numberOfFactors = gm.numberOfFactors(variableIndex);
00108 inBuffer_.resize(numberOfFactors);
00109 outBuffer_.resize(numberOfFactors);
00110 for(size_t j = 0; j < numberOfFactors; ++j) {
00111 inBuffer_[j].assign(gm.numberOfLabels(variableIndex), OP::template neutral<ValueType>());
00112 }
00113 }
00114
00115 template<class GM, class BUFFER, class OP, class ACC>
00116 inline size_t VariableHullBP<GM, BUFFER, OP, ACC>::numberOfBuffers() const {
00117 return outBuffer_.size();
00118 }
00119
00120 template<class GM, class BUFFER, class OP, class ACC>
00121 inline BUFFER& VariableHullBP<GM, BUFFER, OP, ACC>::connectFactorHullBP
00122 (
00123 const size_t bufferNumber,
00124 BUFFER& variableOutBuffer
00125 ) {
00126 OPENGM_ASSERT(bufferNumber < numberOfBuffers());
00127 outBuffer_[bufferNumber] = &variableOutBuffer;
00128 return inBuffer_[bufferNumber];
00129 }
00130
00131 template<class GM, class BUFFER, class OP, class ACC >
00132 inline void VariableHullBP<GM, BUFFER, OP, ACC>::propagate
00133 (
00134 const GM& gm,
00135 const size_t bufferNumber,
00136 const ValueType& damping,
00137 const bool useNormalization
00138 ) {
00139 OPENGM_ASSERT(bufferNumber < numberOfBuffers());
00140 outBuffer_[bufferNumber]->toggle();
00141 if(inBuffer_.size() < 2) {
00142 return;
00143 }
00144
00145 BufferArrayType& newMessage = outBuffer_[bufferNumber]->current();
00146 opengm::messagepassingOperations::operate<OP>(inBuffer_, bufferNumber, newMessage);
00147
00148
00149 if(damping != 0) {
00150 BufferArrayType& oldMessage = outBuffer_[bufferNumber]->old();
00151 opengm::messagepassingOperations::weightedMean<OP>(newMessage, oldMessage, damping, newMessage);
00152 }
00153
00154 if(useNormalization) {
00155 opengm::messagepassingOperations::normalize<OP,ACC>(newMessage);
00156 }
00157 }
00158
00159
00160 template<class GM, class BUFFER, class OP, class ACC>
00161 inline void VariableHullBP<GM, BUFFER, OP, ACC>::propagateAll
00162 (
00163 const GM& gm,
00164 const ValueType& damping,
00165 const bool useNormalization
00166 ) {
00167 for(size_t bufferNumber = 0; bufferNumber < numberOfBuffers(); ++bufferNumber) {
00168 propagate(gm, bufferNumber, damping, useNormalization);
00169 }
00170 }
00171
00172 template<class GM, class BUFFER, class OP, class ACC >
00173 inline void VariableHullBP<GM, BUFFER, OP, ACC>::marginal
00174 (
00175 const GM& gm,
00176 const size_t variableIndex,
00177 IndependentFactorType& out,
00178 const bool useNormalization
00179 ) const {
00180
00181
00182 out.assign(gm, &variableIndex, &variableIndex+1, OP::template neutral<ValueType>());
00183 opengm::messagepassingOperations::operate<OP>(inBuffer_, out);
00184
00185
00186 if(useNormalization) {
00187 opengm::messagepassingOperations::normalize<OP,ACC>(out);
00188 }
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 template<class GM, class BUFFER, class OP, class ACC >
00218 template<class DIST>
00219 inline typename GM::ValueType VariableHullBP<GM, BUFFER, OP, ACC>::distance
00220 (
00221 const size_t bufferNumber
00222 ) const {
00223 return inBuffer_[bufferNumber].template dist<DIST > ();
00224 }
00225
00226 template<class GM, class BUFFER, class OP, class ACC >
00227 inline const typename BUFFER::ArrayType& VariableHullBP<GM, BUFFER, OP, ACC>::outBuffer
00228 (
00229 const size_t bufferIndex
00230 ) const {
00231 OPENGM_ASSERT(bufferIndex < outBuffer_.size());
00232 return outBuffer_[bufferIndex]->current();
00233 }
00234
00235 template<class GM, class BUFFER, class OP, class ACC>
00236 inline void FactorHullBP<GM, BUFFER, OP, ACC>::assign
00237 (
00238 const GM& gm,
00239 const size_t factorIndex,
00240 std::vector<VariableHullBP<GM, BUFFER, OP, ACC> >& variableHulls,
00241 const meta::EmptyType* et
00242 ) {
00243 myFactor_ = (FactorType *const)(&gm[factorIndex]);
00244 inBuffer_.resize(gm[factorIndex].numberOfVariables());
00245 outBuffer_.resize(gm[factorIndex].numberOfVariables());
00246 for(size_t n=0; n<gm.numberOfVariables(factorIndex); ++n) {
00247 size_t variableIndex = gm.variableOfFactor(factorIndex,n);
00248 inBuffer_[n].assign(gm.numberOfLabels(variableIndex), OP::template neutral<ValueType > ());
00249 size_t bufferNumber = 1000000;
00250 for(size_t i=0; i<gm.numberOfFactors(variableIndex); ++i) {
00251 if(gm.factorOfVariable(variableIndex,i) == factorIndex) {
00252 bufferNumber=i;
00253 break;
00254 }
00255 }
00256 outBuffer_[n] =&(variableHulls[variableIndex].connectFactorHullBP(bufferNumber, inBuffer_[n]));
00257 }
00258 }
00259
00260 template<class GM, class BUFFER, class OP, class ACC >
00261 inline void FactorHullBP<GM, BUFFER, OP, ACC>::propagate
00262 (
00263 const size_t id,
00264 const ValueType& damping,
00265 const bool useNormalization
00266 ) {
00267 OPENGM_ASSERT(id < outBuffer_.size());
00268 outBuffer_[id]->toggle();
00269 BufferArrayType& newMessage = outBuffer_[id]->current();
00270 opengm::messagepassingOperations::operateF<GM,ACC>(*myFactor_, inBuffer_, id, newMessage);
00271
00272
00273 if(damping != 0) {
00274 BufferArrayType& oldMessage = outBuffer_[id]->old();
00275 opengm::messagepassingOperations::weightedMean<OP>(newMessage, oldMessage, damping, newMessage);
00276 }
00277
00278 if(useNormalization) {
00279 opengm::messagepassingOperations::normalize<OP,ACC>(newMessage);
00280 }
00281 }
00282
00283 template<class GM, class BUFFER, class OP, class ACC >
00284 inline void FactorHullBP<GM, BUFFER, OP, ACC>::propagateAll
00285 (
00286 const ValueType& damping,
00287 const bool useNormalization
00288 ) {
00289 for(size_t j = 0; j < inBuffer_.size(); ++j) {
00290 propagate(j, damping, useNormalization);
00291 }
00292 }
00293
00294 template<class GM, class BUFFER, class OP, class ACC>
00295 inline void FactorHullBP<GM, BUFFER, OP, ACC>::marginal
00296 (
00297 IndependentFactorType& out,
00298 const bool useNormalization
00299 ) const
00300 {
00301 opengm::messagepassingOperations::operateF<GM>(*myFactor_, inBuffer_,out);
00302
00303 if(useNormalization) {
00304 opengm::messagepassingOperations::normalize<OP,ACC>(out);
00305 }
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 template<class GM, class BUFFER, class OP, class ACC >
00331 template<class DIST>
00332 inline typename GM::ValueType FactorHullBP<GM, BUFFER, OP, ACC>::distance
00333 (
00334 const size_t j
00335 ) const {
00336 return inBuffer_[j].template dist<DIST > ();
00337 }
00338
00339 }
00340
00341 #endif // #ifndef OPENGM_BELIEFPROPAGATION_HXX
00342