812 lines
21 KiB
C++
812 lines
21 KiB
C++
#include <iostream>
|
|
#include <iomanip>
|
|
#include <cstdlib>
|
|
#include <sstream>
|
|
|
|
#include "BpNetwork.h"
|
|
#include "BpNode.h"
|
|
#include "CptEntry.h"
|
|
|
|
BpNetwork::BpNetwork (void)
|
|
{
|
|
schedule_ = SEQUENTIAL_SCHEDULE;
|
|
maxIter_ = 150;
|
|
stableThreashold_ = 0.00000000000000000001;
|
|
}
|
|
|
|
|
|
|
|
BpNetwork::~BpNetwork (void)
|
|
{
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
delete nodes_[i];
|
|
}
|
|
nodes_.clear();
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::setSolverParameters (Schedule schedule,
|
|
int maxIter,
|
|
double stableThreashold)
|
|
{
|
|
if (maxIter <= 0) {
|
|
cerr << "error: maxIter must be greater or equal to 1" << endl;
|
|
abort();
|
|
}
|
|
if (stableThreashold <= 0.0 || stableThreashold >= 1.0) {
|
|
cerr << "error: stableThreashold must be greater than 0.0 " ;
|
|
cerr << "and lesser than 1.0" << endl;
|
|
abort();
|
|
}
|
|
schedule_ = schedule;
|
|
maxIter_ = maxIter;
|
|
stableThreashold_ = stableThreashold;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::runSolver (BayesianNode* queryVar)
|
|
{
|
|
vector<BayesianNode*> queryVars;
|
|
queryVars.push_back (queryVar);
|
|
runSolver (queryVars);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::runSolver (vector<BayesianNode*> queryVars)
|
|
{
|
|
if (queryVars.size() > 1) {
|
|
addJunctionNode (queryVars);
|
|
}
|
|
else {
|
|
string varName = queryVars[0]->getVariableName();
|
|
queryNode_ = static_cast<BpNode*> (getNode (varName));
|
|
}
|
|
|
|
if (!isPolyTree()) {
|
|
if (DL_ >= 1) {
|
|
cout << "The graph is not single connected. " ;
|
|
cout << "Iterative belief propagation will be used." ;
|
|
cout << endl << endl;
|
|
}
|
|
schedule_ = PARALLEL_SCHEDULE;
|
|
}
|
|
|
|
if (schedule_ == SEQUENTIAL_SCHEDULE) {
|
|
initializeSolver (queryVars);
|
|
runNeapolitanSolver();
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
if (nodes_[i]->hasEvidence()) {
|
|
BpNode* v = static_cast<BpNode*> (nodes_[i]);
|
|
addEvidence (v);
|
|
vector<BpNode*> parents = cast (v->getParents());
|
|
for (unsigned int i = 0; i < parents.size(); i++) {
|
|
if (!parents[i]->hasEvidence()) {
|
|
sendLambdaMessage (v, parents[i]);
|
|
}
|
|
}
|
|
vector<BpNode*> childs = cast (v->getChilds());
|
|
for (unsigned int i = 0; i < childs.size(); i++) {
|
|
sendPiMessage (v, childs[i]);
|
|
}
|
|
}
|
|
}
|
|
} else if (schedule_ == PARALLEL_SCHEDULE) {
|
|
BpNode::enableParallelSchedule();
|
|
initializeSolver (queryVars);
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
if (nodes_[i]->hasEvidence()) {
|
|
addEvidence (static_cast<BpNode*> (nodes_[i]));
|
|
}
|
|
}
|
|
runIterativeBpSolver();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::printCurrentStatus (void)
|
|
{
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
printCurrentStatusOf (static_cast<BpNode*> (nodes_[i]));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::printCurrentStatusOf (BpNode* x)
|
|
{
|
|
vector<BpNode*> childs = cast (x->getChilds());
|
|
vector<string> domain = x->getDomain();
|
|
|
|
cout << left;
|
|
cout << setw (10) << "domain" ;
|
|
cout << setw (20) << "π(" + x->getVariableName() + ")" ;
|
|
cout << setw (20) << "λ(" + x->getVariableName() + ")" ;
|
|
cout << setw (16) << "belief" ;
|
|
cout << endl;
|
|
|
|
cout << "--------------------------------" ;
|
|
cout << "--------------------------------" ;
|
|
cout << endl;
|
|
|
|
double* piValues = x->getPiValues();
|
|
double* lambdaValues = x->getLambdaValues();
|
|
double* beliefs = x->getBeliefs();
|
|
for (int xi = 0; xi < x->getDomainSize(); xi++) {
|
|
cout << setw (10) << domain[xi];
|
|
cout << setw (19) << piValues[xi];
|
|
cout << setw (19) << lambdaValues[xi];
|
|
cout.precision (PRECISION_);
|
|
cout << setw (16) << beliefs[xi];
|
|
cout << endl;
|
|
}
|
|
cout << endl;
|
|
if (childs.size() > 0) {
|
|
string s = "(" + x->getVariableName() + ")" ;
|
|
for (unsigned int j = 0; j < childs.size(); j++) {
|
|
cout << setw (10) << "domain" ;
|
|
cout << setw (28) << "π" + childs[j]->getVariableName() + s;
|
|
cout << setw (28) << "λ" + childs[j]->getVariableName() + s;
|
|
cout << endl;
|
|
cout << "--------------------------------" ;
|
|
cout << "--------------------------------" ;
|
|
cout << endl;
|
|
for (int xi = 0; xi < x->getDomainSize(); xi++) {
|
|
cout << setw (10) << domain[xi];
|
|
cout.precision (PRECISION_);
|
|
cout << setw (27) << x->getPiMessage(childs[j], xi);
|
|
cout.precision (PRECISION_);
|
|
cout << setw (27) << x->getLambdaMessage(childs[j], xi);
|
|
cout << endl;
|
|
}
|
|
cout << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::printBeliefs (void)
|
|
{
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
BpNode* x = static_cast<BpNode*> (nodes_[i]);
|
|
vector<string> domain = x->getDomain();
|
|
cout << setw (20) << left << x->getVariableName() ;
|
|
cout << setw (26) << "belief" ;
|
|
cout << endl;
|
|
cout << "--------------------------------------" ;
|
|
cout << endl;
|
|
double* beliefs = x->getBeliefs();
|
|
for (int xi = 0; xi < x->getDomainSize(); xi++) {
|
|
cout << setw (20) << domain[xi];
|
|
cout.precision (PRECISION_);
|
|
cout << setw (26) << beliefs[xi];
|
|
cout << endl;
|
|
}
|
|
cout << endl;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
vector<double>
|
|
BpNetwork::getBeliefs (void)
|
|
{
|
|
return getBeliefs (queryNode_);
|
|
}
|
|
|
|
|
|
|
|
vector<double>
|
|
BpNetwork::getBeliefs (BpNode* x)
|
|
{
|
|
double* beliefs = x->getBeliefs();
|
|
vector<double> beliefsVec;
|
|
for (int xi = 0; xi < x->getDomainSize(); xi++) {
|
|
beliefsVec.push_back (beliefs[xi]);
|
|
}
|
|
return beliefsVec;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::initializeSolver (vector<BayesianNode*> queryVars)
|
|
{
|
|
if (DL_ >= 1) {
|
|
cout << "Initializing solver" << endl;
|
|
if (schedule_ == SEQUENTIAL_SCHEDULE) {
|
|
cout << "-> schedule = sequential" << endl;
|
|
} else {
|
|
cout << "-> schedule = parallel" << endl;
|
|
}
|
|
cout << "-> max iters = " << maxIter_ << endl;
|
|
cout << "-> stable threashold = " << stableThreashold_ << endl;
|
|
cout << "-> query vars = " ;
|
|
for (unsigned int i = 0; i < queryVars.size(); i++) {
|
|
cout << queryVars[i]->getVariableName() << " " ;
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
nIter_ = 0;
|
|
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
BpNode* node = static_cast<BpNode*> (nodes_[i]);
|
|
node->allocateMemory();
|
|
}
|
|
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
BpNode* x = static_cast<BpNode*> (nodes_[i]);
|
|
|
|
double* piValues = x->getPiValues();
|
|
double* lambdaValues = x->getLambdaValues();
|
|
for (int xi = 0; xi < x->getDomainSize(); xi++) {
|
|
piValues[xi] = 1.0;
|
|
lambdaValues[xi] = 1.0;
|
|
}
|
|
|
|
vector<BpNode*> xChilds = cast (x->getChilds());
|
|
for (unsigned int j = 0; j < xChilds.size(); j++) {
|
|
double* piMessages = x->getPiMessages (xChilds[j]);
|
|
for (int xi = 0; xi < x->getDomainSize(); xi++) {
|
|
piMessages[xi] = 1.0;
|
|
//x->setPiMessage (xChilds[j], xi, 1.0);
|
|
}
|
|
}
|
|
|
|
vector<BpNode*> xParents = cast (x->getParents());
|
|
for (unsigned int j = 0; j < xParents.size(); j++) {
|
|
double* lambdaMessages = xParents[j]->getLambdaMessages (x);
|
|
for (int xi = 0; xi < xParents[j]->getDomainSize(); xi++) {
|
|
lambdaMessages[xi] = 1.0;
|
|
//xParents[j]->setLambdaMessage (x, xi, 1.0);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
BpNode* x = static_cast<BpNode*> (nodes_[i]);
|
|
x->normalizeMessages();
|
|
}
|
|
printCurrentStatus();
|
|
|
|
|
|
vector<BpNode*> roots = cast (getRootNodes());
|
|
for (unsigned int i = 0; i < roots.size(); i++) {
|
|
double* params = roots[i]->getParameters();
|
|
double* piValues = roots[i]->getPiValues();
|
|
for (int ri = 0; ri < roots[i]->getDomainSize(); ri++) {
|
|
piValues[ri] = params[ri];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::addJunctionNode (vector<BayesianNode*> queryVars)
|
|
{
|
|
const string VAR_NAME = "_Jn";
|
|
int nStates = 1;
|
|
vector<BayesianNode*> parents;
|
|
vector<string> domain;
|
|
for (unsigned int i = 0; i < queryVars.size(); i++) {
|
|
parents.push_back (queryVars[i]);
|
|
nStates *= queryVars[i]->getDomainSize();
|
|
}
|
|
|
|
for (int i = 0; i < nStates; i++) {
|
|
stringstream ss;
|
|
ss << "_jn" << i;
|
|
domain.push_back (ss.str()); // FIXME make domain optional
|
|
}
|
|
|
|
int nParams = nStates * nStates;
|
|
double* params = new double [nParams];
|
|
for (int i = 0; i < nParams; i++) {
|
|
int row = i / nStates;
|
|
int col = i % nStates;
|
|
if (row == col) {
|
|
params[i] = 1;
|
|
} else {
|
|
params[i] = 0;
|
|
}
|
|
}
|
|
addNode (VAR_NAME, parents, params, nParams, domain);
|
|
queryNode_ = static_cast<BpNode*> (getNode (VAR_NAME));
|
|
printNetwork();
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::addEvidence (BpNode* v)
|
|
{
|
|
if (DL_ >= 1) {
|
|
cout << "Adding evidence: node " ;
|
|
cout << "`" << v->getVariableName() << "' was instantiated as " ;
|
|
cout << "`" << v->getDomain()[v->getEvidence()] << "'" ;
|
|
cout << endl;
|
|
}
|
|
double* piValues = v->getPiValues();
|
|
double* lambdaValues = v->getLambdaValues();
|
|
for (int vi = 0; vi < v->getDomainSize(); vi++) {
|
|
if (vi == v->getEvidence()) {
|
|
piValues[vi] = 1.0;
|
|
lambdaValues[vi] = 1.0;
|
|
} else {
|
|
piValues[vi] = 0.0;
|
|
lambdaValues[vi] = 0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::runNeapolitanSolver (void)
|
|
{
|
|
vector<BpNode*> roots = cast (getRootNodes());
|
|
for (unsigned int i = 0; i < roots.size(); i++) {
|
|
vector<BpNode*> childs = cast (roots[i]->getChilds());
|
|
for (unsigned int j = 0; j < childs.size(); j++) {
|
|
sendPiMessage (roots[i], static_cast<BpNode*> (childs[j]));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::sendPiMessage (BpNode* z, BpNode* x)
|
|
{
|
|
nIter_ ++;
|
|
if (!(maxIter_ == -1 || nIter_ < maxIter_)) {
|
|
cout << "the maximum number of iterations was achieved, terminating..." ;
|
|
cout << endl;
|
|
return;
|
|
}
|
|
|
|
if (DL_ >= 1) {
|
|
cout << "π message " << z->getVariableName();
|
|
cout << " --> " << x->getVariableName() << endl;
|
|
}
|
|
|
|
updatePiMessages(z, x);
|
|
|
|
if (!x->hasEvidence()) {
|
|
updatePiValues (x);
|
|
vector<BpNode*> xChilds = cast (x->getChilds());
|
|
for (unsigned int i = 0; i < xChilds.size(); i++) {
|
|
sendPiMessage (x, xChilds[i]);
|
|
}
|
|
}
|
|
|
|
bool isAllOnes = true;
|
|
double* lambdaValues = x->getLambdaValues();
|
|
for (int xi = 0; xi < x->getDomainSize(); xi++) {
|
|
if (lambdaValues[xi] != 1.0) {
|
|
isAllOnes = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!isAllOnes) {
|
|
vector<BpNode*> xParents = cast (x->getParents());
|
|
for (unsigned int i = 0; i < xParents.size(); i++) {
|
|
if (xParents[i] != z && !xParents[i]->hasEvidence()) {
|
|
sendLambdaMessage (x, xParents[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::sendLambdaMessage (BpNode* y, BpNode* x)
|
|
{
|
|
nIter_ ++;
|
|
if (!(maxIter_ == -1 || nIter_ < maxIter_)) {
|
|
cout << "the maximum number of iterations was achieved, terminating..." ;
|
|
cout << endl;
|
|
return;
|
|
}
|
|
|
|
if (DL_ >= 1) {
|
|
cout << "λ message " << y->getVariableName();
|
|
cout << " --> " << x->getVariableName() << endl;
|
|
}
|
|
|
|
updateLambdaMessages (x, y);
|
|
updateLambdaValues (x);
|
|
|
|
vector<BpNode*> xParents = cast (x->getParents());
|
|
for (unsigned int i = 0; i < xParents.size(); i++) {
|
|
if (!xParents[i]->hasEvidence()) {
|
|
sendLambdaMessage (x, xParents[i]);
|
|
}
|
|
}
|
|
|
|
vector<BpNode*> xChilds = cast (x->getChilds());
|
|
for (unsigned int i = 0; i < xChilds.size(); i++) {
|
|
if (xChilds[i] != y) {
|
|
sendPiMessage (x, xChilds[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::updatePiValues (BpNode* x)
|
|
{
|
|
// π(Xi)
|
|
vector<BpNode*> parents = cast (x->getParents());
|
|
for (int xi = 0; xi < x->getDomainSize(); xi++) {
|
|
stringstream calcs1;
|
|
stringstream calcs2;
|
|
if (DL_ >= 2) {
|
|
calcs1 << "π("<< x->getDomain()[xi] << ")" << endl << "= " ;
|
|
}
|
|
double sum = 0.0;
|
|
vector<pair<int, int> > constraints;
|
|
vector<CptEntry> entries = x->getCptEntriesOfRow (xi);
|
|
for (unsigned int k = 0; k < entries.size(); k++) {
|
|
double prod = x->getProbability (entries[k]);
|
|
if (DL_ >= 2) {
|
|
if (k != 0) calcs1 << endl << "+ " ;
|
|
calcs1 << x->entryToString (entries[k]);
|
|
if (DL_ >= 3) {
|
|
(k == 0) ? calcs2 << "(" << prod : calcs2 << endl << "+ (" << prod;
|
|
}
|
|
}
|
|
vector<int> insts = entries[k].getDomainInstantiations();
|
|
for (unsigned int i = 0; i < parents.size(); i++) {
|
|
double value = parents[i]->getPiMessage (x, insts[i + 1]);
|
|
prod *= value;
|
|
if (DL_ >= 2) {
|
|
calcs1 << ".π" << x->getVariableName();
|
|
calcs1 << "(" << parents[i]->getDomain()[insts[i + 1]] << ")";
|
|
if (DL_ >= 3) calcs2 << "x" << value;
|
|
}
|
|
}
|
|
sum += prod;
|
|
if (DL_ >= 3) calcs2 << ")";
|
|
}
|
|
x->setPiValue (xi, sum);
|
|
if (DL_ >= 2) {
|
|
cout << calcs1.str();
|
|
if (DL_ >= 3) cout << endl << "= " << calcs2.str();
|
|
cout << " = " << sum << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::updatePiMessages (BpNode* z, BpNode* x)
|
|
{
|
|
// πX(Zi)
|
|
vector<BpNode*> zChilds = cast (z->getChilds());
|
|
for (int zi = 0; zi < z->getDomainSize(); zi++) {
|
|
stringstream calcs1;
|
|
stringstream calcs2;
|
|
if (DL_ >= 2) {
|
|
calcs1 << "π" << x->getVariableName();
|
|
calcs1 << "(" << z->getDomain()[zi] << ") = " ;
|
|
}
|
|
double prod = z->getPiValue (zi);
|
|
if (DL_ >= 2) {
|
|
calcs1 << "π(" << z->getDomain()[zi] << ")" ;
|
|
if (DL_ >= 3) calcs2 << prod;
|
|
}
|
|
for (unsigned int i = 0; i < zChilds.size(); i++) {
|
|
if (zChilds[i] != x) {
|
|
double value = z->getLambdaMessage (zChilds[i], zi);
|
|
prod *= value;
|
|
if (DL_ >= 2) {
|
|
calcs1 << ".λ" << zChilds[i]->getVariableName();
|
|
calcs1 << "(" << z->getDomain()[zi] + ")" ;
|
|
if (DL_ >= 3) calcs2 << " x " << value;
|
|
}
|
|
}
|
|
}
|
|
z->setPiMessage (x, zi, prod);
|
|
if (DL_ >= 2) {
|
|
cout << calcs1.str();
|
|
if (DL_ >= 3) cout << " = " << calcs2.str();
|
|
cout << " = " << prod << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::updateLambdaValues (BpNode* x)
|
|
{
|
|
// λ(Xi)
|
|
vector<BpNode*> childs = cast (x->getChilds());
|
|
for (int xi = 0; xi < x->getDomainSize(); xi++) {
|
|
stringstream calcs1;
|
|
stringstream calcs2;
|
|
if (DL_ >= 2) {
|
|
calcs1 << "λ" << "(" << x->getDomain()[xi] << ") = " ;
|
|
}
|
|
double prod = 1.0;
|
|
for (unsigned int i = 0; i < childs.size(); i++) {
|
|
double val = x->getLambdaMessage (childs[i], xi);
|
|
prod *= val;
|
|
if (DL_ >= 2) {
|
|
if (i != 0) calcs1 << "." ;
|
|
calcs1 << "λ" << childs[i]->getVariableName();
|
|
calcs1 << "(" << x->getDomain()[xi] + ")" ;
|
|
if (DL_ >= 3) (i == 0) ? calcs2 << val : calcs2 << " x " << val;
|
|
}
|
|
}
|
|
x->setLambdaValue (xi, prod);
|
|
if (DL_ >= 2) {
|
|
cout << calcs1.str();
|
|
if (childs.size() == 0) {
|
|
cout << 1 << endl;
|
|
} else {
|
|
if (DL_ >= 3) cout << " = " << calcs2.str();
|
|
cout << " = " << prod << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::updateLambdaMessages (BpNode* x, BpNode* y)
|
|
{
|
|
// λY(Xi)
|
|
int parentIndex = y->getIndexOfParent (x) + 1;
|
|
vector<BpNode*> yParents = cast (y->getParents());
|
|
for (int xi = 0; xi < x->getDomainSize(); xi++) {
|
|
stringstream calcs1;
|
|
stringstream calcs2;
|
|
if (DL_ >= 2) {
|
|
calcs1 << "λ" << y->getVariableName() ;
|
|
calcs1 << "(" << x->getDomain()[xi] << ")" << endl << "= " ;
|
|
}
|
|
double outer_sum = 0.0;
|
|
for (int yi = 0; yi < y->getDomainSize(); yi++) {
|
|
if (DL_ >= 2) {
|
|
(yi == 0) ? calcs1 << "[" : calcs1 << endl << "+ [" ;
|
|
if (DL_ >= 3) {
|
|
(yi == 0) ? calcs2 << "[" : calcs2 << endl << "+ [" ;
|
|
}
|
|
}
|
|
double inner_sum = 0.0;
|
|
vector<pair<int, int> > constraints;
|
|
constraints.push_back (make_pair (0, yi));
|
|
constraints.push_back (make_pair (parentIndex, xi));
|
|
vector<CptEntry> entries = y->getCptEntries (constraints);
|
|
for (unsigned int k = 0; k < entries.size(); k++) {
|
|
double prod = y->getProbability (entries[k]);
|
|
if (DL_ >= 2) {
|
|
if (k != 0) calcs1 << " + " ;
|
|
calcs1 << y->entryToString (entries[k]);
|
|
if (DL_ >= 3) {
|
|
(k == 0) ? calcs2 << "(" << prod : calcs2 << " + (" << prod;
|
|
}
|
|
}
|
|
vector<int> insts = entries[k].getDomainInstantiations();
|
|
for (unsigned int i = 0; i < yParents.size(); i++) {
|
|
if (yParents[i] != x) {
|
|
double val = yParents[i]->getPiMessage (y, insts[i + 1]);
|
|
prod *= val;
|
|
if (DL_ >= 2) {
|
|
calcs1 << ".π" << y->getVariableName();
|
|
calcs1 << "(" << yParents[i]->getDomain()[insts[i + 1]] << ")" ;
|
|
if (DL_ >= 3) calcs2 << "x" << val;
|
|
}
|
|
|
|
}
|
|
}
|
|
inner_sum += prod;
|
|
if (DL_ >= 3) {
|
|
calcs2 << ")" ;
|
|
}
|
|
}
|
|
outer_sum += inner_sum * y->getLambdaValue (yi);
|
|
if (DL_ >= 2) {
|
|
calcs1 << "].λ(" << y->getDomain()[yi] << ")";
|
|
if (DL_ >= 3) calcs2 << "]x" << y->getLambdaValue (yi);
|
|
}
|
|
}
|
|
x->setLambdaMessage (y, xi, outer_sum);
|
|
if (DL_ >= 2) {
|
|
cout << calcs1.str();
|
|
if (DL_ >= 3) cout << endl << "= " << calcs2.str();
|
|
cout << " = " << outer_sum << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::runIterativeBpSolver()
|
|
{
|
|
int nIter = 0;
|
|
maxIter_ = 100;
|
|
bool converged = false;
|
|
while (nIter < maxIter_ && !converged) {
|
|
if (DL_ >= 1) {
|
|
cout << endl << endl;
|
|
cout << "****************************************" ;
|
|
cout << "****************************************" ;
|
|
cout << endl;
|
|
cout << " Iteration " << nIter + 1 << endl;
|
|
cout << "****************************************" ;
|
|
cout << "****************************************" ;
|
|
}
|
|
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
BpNode* x = static_cast<BpNode*>(nodes_[i]);
|
|
vector<BpNode*> xParents = cast (x->getParents());
|
|
for (unsigned int j = 0; j < xParents.size(); j++) {
|
|
//if (!xParents[j]->hasEvidence()) {
|
|
if (DL_ >= 1) {
|
|
cout << endl << "λ message " << x->getVariableName();
|
|
cout << " --> " << xParents[j]->getVariableName() << endl;
|
|
}
|
|
updateLambdaMessages (xParents[j], x);
|
|
//}
|
|
}
|
|
}
|
|
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
BpNode* x = static_cast<BpNode*>(nodes_[i]);
|
|
vector<BpNode*> xChilds = cast (x->getChilds());
|
|
for (unsigned int j = 0; j < xChilds.size(); j++) {
|
|
if (DL_ >= 1) {
|
|
cout << endl << "π message " << x->getVariableName();
|
|
cout << " --> " << xChilds[j]->getVariableName() << endl;
|
|
}
|
|
updatePiMessages (x, xChilds[j]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
BpNode* x = static_cast<BpNode*>(nodes_[i]);
|
|
vector<BpNode*> xChilds = cast (x->getChilds());
|
|
for (unsigned int j = 0; j < xChilds.size(); j++) {
|
|
if (DL_ >= 1) {
|
|
cout << "π message " << x->getVariableName();
|
|
cout << " --> " << xChilds[j]->getVariableName() << endl;
|
|
}
|
|
updatePiMessages (x, xChilds[j]);
|
|
}
|
|
vector<BpNode*> xParents = cast (x->getParents());
|
|
for (unsigned int j = 0; j < xParents.size(); j++) {
|
|
//if (!xParents[j]->hasEvidence()) {
|
|
if (DL_ >= 1) {
|
|
cout << "λ message " << x->getVariableName();
|
|
cout << " --> " << xParents[j]->getVariableName() << endl;
|
|
}
|
|
updateLambdaMessages (xParents[j], x);
|
|
//}
|
|
}
|
|
}
|
|
*/
|
|
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
BpNode* x = static_cast<BpNode*> (nodes_[i]);
|
|
//cout << endl << "SWAPING MESSAGES FOR " << x->getVariableName() << ":" ;
|
|
//cout << endl << endl;
|
|
//printCurrentStatusOf (x);
|
|
x->swapMessages();
|
|
x->normalizeMessages();
|
|
//cout << endl << "messages swaped " << endl;
|
|
//printCurrentStatusOf (x);
|
|
}
|
|
|
|
converged = true;
|
|
for (unsigned int i = 0; i < nodes_.size(); i++) {
|
|
BpNode* x = static_cast<BpNode*>(nodes_[i]);
|
|
if (DL_ >= 1) {
|
|
cout << endl << "var " << x->getVariableName() << ":" << endl;
|
|
}
|
|
//if (!x->hasEvidence()) {
|
|
updatePiValues (x);
|
|
updateLambdaValues (x);
|
|
double change = x->getBeliefChange();
|
|
if (DL_ >= 1) {
|
|
cout << "belief change = " << change << endl;
|
|
}
|
|
if (change > stableThreashold_) {
|
|
converged = false;
|
|
}
|
|
//}
|
|
}
|
|
|
|
if (converged) {
|
|
// converged = false;
|
|
}
|
|
if (DL_ >= 2) {
|
|
cout << endl;
|
|
printCurrentStatus();
|
|
}
|
|
nIter++;
|
|
}
|
|
|
|
if (DL_ >= 1) {
|
|
cout << endl;
|
|
if (converged) {
|
|
cout << "Iterative belief propagation converged in " ;
|
|
cout << nIter << " iterations" << endl;
|
|
} else {
|
|
cout << "Iterative belief propagation converged didn't converge" ;
|
|
cout << endl;
|
|
}
|
|
if (DL_ == 1) {
|
|
cout << endl;
|
|
printBeliefs();
|
|
}
|
|
cout << endl;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::addNode (string varName,
|
|
vector<BayesianNode*> parents,
|
|
int evidence,
|
|
int distId)
|
|
{
|
|
for (unsigned int i = 0; i < dists_.size(); i++) {
|
|
if (dists_[i]->id == distId) {
|
|
BpNode* node = new BpNode (varName, parents, dists_[i], evidence);
|
|
nodes_.push_back (node);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BpNetwork::addNode (string varName,
|
|
vector<BayesianNode*> parents,
|
|
double* params,
|
|
int nParams,
|
|
vector<string> domain)
|
|
{
|
|
Distribution* dist = new Distribution (params, nParams, domain);
|
|
BpNode* node = new BpNode (varName, parents, dist);
|
|
dists_.push_back (dist);
|
|
nodes_.push_back (node);
|
|
}
|
|
|
|
|
|
|
|
vector<BpNode*>
|
|
BpNetwork::cast (vector<BayesianNode*> nodes)
|
|
{
|
|
vector<BpNode*> castedNodes (nodes.size());
|
|
for (unsigned int i = 0; i < nodes.size(); i++) {
|
|
castedNodes[i] = static_cast<BpNode*> (nodes[i]);
|
|
}
|
|
return castedNodes;
|
|
}
|
|
|