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;
 | 
						|
}
 | 
						|
 |