// m_ij(x_j) = sum_xi {phi(i)*phi(i,j)*prod_{u \in N(i)\j} {m_uj(xi)}} // m_ij(x_j) = max_xi {phi(i)*phi(i,j)*prod_{u \in N(i)\j} {m_uj(xi)}} void InferenceEngineBP::sendMessage(BPNode* xi, BPNode* xj, dVector* phi_i, dMatrix** phi_ij, dVector** msg) { // potential(i) -> Vi dVector Vi(phi_i[xi->id]); // potential(i,j) -> Mij dMatrix Mij; if( xi->id < xj->id ) Mij.set( phi_ij[xi->id][xj->id] ); else { Mij.set( phi_ij[xj->id][xi->id] ); Mij.transpose(); } // prod_{u \in N(i)\j} {m_ui(xi)} -> Vi std::list<BPNode*>::iterator it; for(it=xi->neighbors.begin(); it!=xi->neighbors.end(); it++) { if( xj->equal(*it) ) continue; Vi.add( msg[(*it)->id][xi->id] ); } if( isSumProduct ) logMultiply( Vi, Mij, msg[xi->id][xj->id] ); else logMultiplyMaxProd( Vi, Mij, msg[xi->id][xj->id] ); }
// m_ij(x_j) = sum_xi {potential(i)*potential(i,j)*prod_{u \in N(i)\j} {m_ui(xi)}} void InferenceEngineLoopyBP::sendMessage(int xi, int xj, int nbNodes, const Beliefs potentials, std::vector<dVector>& messages, iMatrix adjMat, int adjMatMax, bool bMaxProd) { int max_hi=-1; // for Viterbi decoding // potential(i) dVector Vi(potentials.belStates[xi]); // potential(i,j) dMatrix Mij(potentials.belEdges[adjMat(xi,xj)-1]); if( xi>xj ) Mij.transpose(); // prod_{u \in N(i)\j} {m_ui(xi)}} int msg_idx; for( int xu=0; xu<nbNodes; xu++ ) { if( !adjMat(xu,xi) || xu==xj ) continue; msg_idx = (xu>xi) ? adjMatMax+adjMat(xu,xi)-1 : adjMat(xu,xi)-1; Vi.add(messages[msg_idx]); } // m_ij(xj) = Vi \dot Mij msg_idx = (xi>xj) ? adjMatMax+adjMat(xi,xj)-1 : adjMat(xi,xj)-1; if( bMaxProd ) max_hi = logMultiplyMaxProd(Vi, Mij, messages[msg_idx]); else logMultiply(Vi, Mij, messages[msg_idx]); // Normalize messages to avoid numerical over/under-flow // Make \sum_{xj} m_ij(xj)=1. Other methods could also be used. double min = messages[msg_idx].min(); if( min < 0 ) messages[msg_idx].add(-min); messages[msg_idx].multiply(1/messages[msg_idx].sum()); }