2011-07-22 21:33:30 +01:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <cassert>
|
|
|
|
|
2011-05-17 12:00:33 +01:00
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
#include "xmlParser/xmlParser.h"
|
|
|
|
|
|
|
|
#include "BayesNet.h"
|
2012-03-22 11:33:24 +00:00
|
|
|
#include "Util.h"
|
2011-05-17 12:00:33 +01:00
|
|
|
|
|
|
|
|
2012-04-05 18:38:56 +01:00
|
|
|
void
|
|
|
|
DAGraph::addNode (DAGraphNode* n)
|
|
|
|
{
|
|
|
|
nodes_.push_back (n);
|
|
|
|
assert (Util::contains (varMap_, n->varId()) == false);
|
|
|
|
varMap_[n->varId()] = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
DAGraph::addEdge (VarId vid1, VarId vid2)
|
|
|
|
{
|
|
|
|
unordered_map<VarId, DAGraphNode*>::iterator it1;
|
|
|
|
unordered_map<VarId, DAGraphNode*>::iterator it2;
|
|
|
|
it1 = varMap_.find (vid1);
|
|
|
|
it2 = varMap_.find (vid2);
|
|
|
|
assert (it1 != varMap_.end());
|
|
|
|
assert (it2 != varMap_.end());
|
|
|
|
it1->second->addChild (it2->second);
|
|
|
|
it2->second->addParent (it1->second);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const DAGraphNode*
|
|
|
|
DAGraph::getNode (VarId vid) const
|
|
|
|
{
|
|
|
|
unordered_map<VarId, DAGraphNode*>::const_iterator it;
|
|
|
|
it = varMap_.find (vid);
|
|
|
|
return it != varMap_.end() ? it->second : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DAGraphNode*
|
|
|
|
DAGraph::getNode (VarId vid)
|
|
|
|
{
|
|
|
|
unordered_map<VarId, DAGraphNode*>::const_iterator it;
|
|
|
|
it = varMap_.find (vid);
|
|
|
|
return it != varMap_.end() ? it->second : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
DAGraph::setIndexes (void)
|
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
nodes_[i]->setIndex (i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
DAGraph::clear (void)
|
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
nodes_[i]->clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
DAGraph::exportToGraphViz (const char* fileName)
|
|
|
|
{
|
|
|
|
ofstream out (fileName);
|
|
|
|
if (!out.is_open()) {
|
|
|
|
cerr << "error: cannot open file to write at " ;
|
|
|
|
cerr << "DAGraph::exportToDotFile()" << endl;
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
out << "digraph {" << endl;
|
|
|
|
out << "ranksep=1" << endl;
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
out << nodes_[i]->varId() ;
|
|
|
|
out << " [" ;
|
|
|
|
out << "label=\"" << nodes_[i]->label() << "\"" ;
|
|
|
|
if (nodes_[i]->hasEvidence()) {
|
|
|
|
out << ",style=filled, fillcolor=yellow" ;
|
|
|
|
}
|
|
|
|
out << "]" << endl;
|
|
|
|
}
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
const vector<DAGraphNode*>& childs = nodes_[i]->childs();
|
|
|
|
for (unsigned j = 0; j < childs.size(); j++) {
|
|
|
|
out << nodes_[i]->varId() << " -> " << childs[j]->varId();
|
|
|
|
out << " [style=bold]" << endl ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out << "}" << endl;
|
|
|
|
out.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-12-12 15:29:51 +00:00
|
|
|
|
|
|
|
BayesNet::~BayesNet (void)
|
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
delete nodes_[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
BayesNet::readFromBifFormat (const char* fileName)
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
|
|
|
XMLNode xMainNode = XMLNode::openFileHelper (fileName, "BIF");
|
|
|
|
// only the first network is parsed, others are ignored
|
2011-12-12 15:29:51 +00:00
|
|
|
XMLNode xNode = xMainNode.getChildNode ("NETWORK");
|
2011-07-22 21:33:30 +01:00
|
|
|
unsigned nVars = xNode.nChildNode ("VARIABLE");
|
|
|
|
for (unsigned i = 0; i < nVars; i++) {
|
2011-05-17 12:00:33 +01:00
|
|
|
XMLNode var = xNode.getChildNode ("VARIABLE", i);
|
2011-12-12 15:29:51 +00:00
|
|
|
if (string (var.getAttribute ("TYPE")) != "nature") {
|
2011-05-17 12:00:33 +01:00
|
|
|
cerr << "error: only \"nature\" variables are supported" << endl;
|
|
|
|
abort();
|
|
|
|
}
|
2011-12-12 15:29:51 +00:00
|
|
|
States states;
|
|
|
|
string label = var.getChildNode("NAME").getText();
|
2012-04-05 18:38:56 +01:00
|
|
|
unsigned range = var.nChildNode ("OUTCOME");
|
|
|
|
for (unsigned j = 0; j < range; j++) {
|
2011-05-17 12:00:33 +01:00
|
|
|
if (var.getChildNode("OUTCOME", j).getText() == 0) {
|
|
|
|
stringstream ss;
|
|
|
|
ss << j + 1;
|
2011-12-12 15:29:51 +00:00
|
|
|
states.push_back (ss.str());
|
2011-05-17 12:00:33 +01:00
|
|
|
} else {
|
2011-12-12 15:29:51 +00:00
|
|
|
states.push_back (var.getChildNode("OUTCOME", j).getText());
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
|
|
|
}
|
2011-12-12 15:29:51 +00:00
|
|
|
addNode (label, states);
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
|
|
|
|
2011-07-22 21:33:30 +01:00
|
|
|
unsigned nDefs = xNode.nChildNode ("DEFINITION");
|
2011-05-17 12:00:33 +01:00
|
|
|
if (nVars != nDefs) {
|
2011-07-22 21:33:30 +01:00
|
|
|
cerr << "error: different number of variables and definitions" << endl;
|
|
|
|
abort();
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
2011-07-22 21:33:30 +01:00
|
|
|
for (unsigned i = 0; i < nDefs; i++) {
|
2011-12-12 15:29:51 +00:00
|
|
|
XMLNode def = xNode.getChildNode ("DEFINITION", i);
|
|
|
|
string label = def.getChildNode("FOR").getText();
|
|
|
|
BayesNode* node = getBayesNode (label);
|
|
|
|
if (!node) {
|
|
|
|
cerr << "error: unknow variable `" << label << "'" << endl;
|
2011-05-17 12:00:33 +01:00
|
|
|
abort();
|
|
|
|
}
|
2011-07-22 21:33:30 +01:00
|
|
|
BnNodeSet parents;
|
2012-04-05 18:38:56 +01:00
|
|
|
unsigned nParams = node->range();
|
2011-05-17 12:00:33 +01:00
|
|
|
for (int j = 0; j < def.nChildNode ("GIVEN"); j++) {
|
|
|
|
string parentLabel = def.getChildNode("GIVEN", j).getText();
|
2011-07-22 21:33:30 +01:00
|
|
|
BayesNode* parentNode = getBayesNode (parentLabel);
|
2011-12-12 15:29:51 +00:00
|
|
|
if (!parentNode) {
|
|
|
|
cerr << "error: unknow variable `" << parentLabel << "'" << endl;
|
|
|
|
abort();
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
2012-04-05 18:38:56 +01:00
|
|
|
nParams *= parentNode->range();
|
2011-12-12 15:29:51 +00:00
|
|
|
parents.push_back (parentNode);
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
2011-12-12 15:29:51 +00:00
|
|
|
node->setParents (parents);
|
|
|
|
unsigned count = 0;
|
2012-03-22 11:33:24 +00:00
|
|
|
Params params (nParams);
|
2011-12-12 15:29:51 +00:00
|
|
|
stringstream s (def.getChildNode("TABLE").getText());
|
|
|
|
while (!s.eof() && count < nParams) {
|
|
|
|
s >> params[count];
|
|
|
|
count ++;
|
|
|
|
}
|
|
|
|
if (count != nParams) {
|
|
|
|
cerr << "error: invalid number of parameters " ;
|
|
|
|
cerr << "for variable `" << label << "'" << endl;
|
|
|
|
abort();
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
2012-04-05 18:38:56 +01:00
|
|
|
params = reorderParameters (params, node->range());
|
2012-03-31 23:27:37 +01:00
|
|
|
if (Globals::logDomain) {
|
|
|
|
Util::toLog (params);
|
|
|
|
}
|
|
|
|
node->setParams (params);
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
|
|
|
setIndexes();
|
2012-03-31 23:27:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BayesNode*
|
|
|
|
BayesNet::addNode (BayesNode* n)
|
|
|
|
{
|
|
|
|
varMap_.insert (make_pair (n->varId(), nodes_.size()));
|
|
|
|
nodes_.push_back (n);
|
|
|
|
return nodes_.back();
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BayesNode*
|
2011-12-12 15:29:51 +00:00
|
|
|
BayesNet::addNode (string label, const States& states)
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
2011-12-12 15:29:51 +00:00
|
|
|
VarId vid = nodes_.size();
|
2012-03-22 11:33:24 +00:00
|
|
|
varMap_.insert (make_pair (vid, nodes_.size()));
|
2011-12-12 15:29:51 +00:00
|
|
|
GraphicalModel::addVariableInformation (vid, label, states);
|
|
|
|
BayesNode* node = new BayesNode (VarNode (vid, states.size()));
|
|
|
|
nodes_.push_back (node);
|
|
|
|
return node;
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BayesNode*
|
2011-12-12 15:29:51 +00:00
|
|
|
BayesNet::getBayesNode (VarId vid) const
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
2012-03-22 11:33:24 +00:00
|
|
|
IndexMap::const_iterator it = varMap_.find (vid);
|
|
|
|
if (it == varMap_.end()) {
|
2011-05-17 12:00:33 +01:00
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return nodes_[it->second];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BayesNode*
|
2011-07-22 21:33:30 +01:00
|
|
|
BayesNet::getBayesNode (string label) const
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
|
|
|
BayesNode* node = 0;
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
2011-12-12 15:29:51 +00:00
|
|
|
if (nodes_[i]->label() == label) {
|
2011-05-17 12:00:33 +01:00
|
|
|
node = nodes_[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-07-22 21:33:30 +01:00
|
|
|
|
2011-12-12 15:29:51 +00:00
|
|
|
VarNode*
|
|
|
|
BayesNet::getVariableNode (VarId vid) const
|
2011-07-22 21:33:30 +01:00
|
|
|
{
|
2011-12-12 15:29:51 +00:00
|
|
|
BayesNode* node = getBayesNode (vid);
|
|
|
|
assert (node);
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VarNodes
|
|
|
|
BayesNet::getVariableNodes (void) const
|
|
|
|
{
|
|
|
|
VarNodes vars;
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
vars.push_back (nodes_[i]);
|
|
|
|
}
|
|
|
|
return vars;
|
2011-07-22 21:33:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const BnNodeSet&
|
|
|
|
BayesNet::getBayesNodes (void) const
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
|
|
|
return nodes_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-07-22 21:33:30 +01:00
|
|
|
unsigned
|
2011-12-12 15:29:51 +00:00
|
|
|
BayesNet::nrNodes (void) const
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
|
|
|
return nodes_.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-07-22 21:33:30 +01:00
|
|
|
BnNodeSet
|
2011-05-17 12:00:33 +01:00
|
|
|
BayesNet::getRootNodes (void) const
|
|
|
|
{
|
2011-07-22 21:33:30 +01:00
|
|
|
BnNodeSet roots;
|
2011-05-17 12:00:33 +01:00
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
if (nodes_[i]->isRoot()) {
|
|
|
|
roots.push_back (nodes_[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return roots;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-07-22 21:33:30 +01:00
|
|
|
BnNodeSet
|
2011-05-17 12:00:33 +01:00
|
|
|
BayesNet::getLeafNodes (void) const
|
|
|
|
{
|
2011-07-22 21:33:30 +01:00
|
|
|
BnNodeSet leafs;
|
2011-05-17 12:00:33 +01:00
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
if (nodes_[i]->isLeaf()) {
|
|
|
|
leafs.push_back (nodes_[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return leafs;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2011-12-12 15:29:51 +00:00
|
|
|
BayesNet::isPolyTree (void) const
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
|
|
|
return !containsUndirectedCycle();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
BayesNet::setIndexes (void)
|
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
nodes_[i]->setIndex (i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2011-07-22 21:33:30 +01:00
|
|
|
BayesNet::printGraphicalModel (void) const
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
cout << *nodes_[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2011-12-12 15:29:51 +00:00
|
|
|
BayesNet::exportToGraphViz (const char* fileName,
|
|
|
|
bool showNeighborless,
|
2012-03-22 11:33:24 +00:00
|
|
|
const VarIds& highlightVarIds) const
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
2011-07-22 21:33:30 +01:00
|
|
|
ofstream out (fileName);
|
2011-05-17 12:00:33 +01:00
|
|
|
if (!out.is_open()) {
|
|
|
|
cerr << "error: cannot open file to write at " ;
|
|
|
|
cerr << "BayesNet::exportToDotFile()" << endl;
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2011-12-12 15:29:51 +00:00
|
|
|
out << "digraph {" << endl;
|
|
|
|
out << "ranksep=1" << endl;
|
2011-05-17 12:00:33 +01:00
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
if (showNeighborless || nodes_[i]->hasNeighbors()) {
|
2011-12-12 15:29:51 +00:00
|
|
|
out << nodes_[i]->varId() ;
|
2011-05-17 12:00:33 +01:00
|
|
|
if (nodes_[i]->hasEvidence()) {
|
2011-12-12 15:29:51 +00:00
|
|
|
out << " [" ;
|
|
|
|
out << "label=\"" << nodes_[i]->label() << "\"," ;
|
|
|
|
out << "style=filled, fillcolor=yellow" ;
|
|
|
|
out << "]" ;
|
2011-05-17 12:00:33 +01:00
|
|
|
} else {
|
2011-12-12 15:29:51 +00:00
|
|
|
out << " [" ;
|
|
|
|
out << "label=\"" << nodes_[i]->label() << "\"" ;
|
|
|
|
out << "]" ;
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
2011-12-12 15:29:51 +00:00
|
|
|
out << endl;
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-12 15:29:51 +00:00
|
|
|
for (unsigned i = 0; i < highlightVarIds.size(); i++) {
|
|
|
|
BayesNode* node = getBayesNode (highlightVarIds[i]);
|
2011-07-22 21:33:30 +01:00
|
|
|
if (node) {
|
2011-12-12 15:29:51 +00:00
|
|
|
out << node->varId() ;
|
2011-07-22 21:33:30 +01:00
|
|
|
out << " [shape=box3d]" << endl;
|
|
|
|
} else {
|
2011-12-12 15:29:51 +00:00
|
|
|
cout << "error: invalid variable id: " << highlightVarIds[i] << endl;
|
2011-07-22 21:33:30 +01:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
const BnNodeSet& childs = nodes_[i]->getChilds();
|
|
|
|
for (unsigned j = 0; j < childs.size(); j++) {
|
2011-12-12 15:29:51 +00:00
|
|
|
out << nodes_[i]->varId() << " -> " << childs[j]->varId() << " [style=bold]" << endl ;
|
2011-07-22 21:33:30 +01:00
|
|
|
}
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
out << "}" << endl;
|
|
|
|
out.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2011-07-22 21:33:30 +01:00
|
|
|
BayesNet::exportToBifFormat (const char* fileName) const
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
2011-07-22 21:33:30 +01:00
|
|
|
ofstream out (fileName);
|
2011-05-17 12:00:33 +01:00
|
|
|
if(!out.is_open()) {
|
|
|
|
cerr << "error: cannot open file to write at " ;
|
|
|
|
cerr << "BayesNet::exportToBifFile()" << endl;
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
out << "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>" << endl;
|
|
|
|
out << "<BIF VERSION=\"0.3\">" << endl;
|
|
|
|
out << "<NETWORK>" << endl;
|
|
|
|
out << "<NAME>" << fileName << "</NAME>" << endl << endl;
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
out << "<VARIABLE TYPE=\"nature\">" << endl;
|
2011-12-12 15:29:51 +00:00
|
|
|
out << "\t<NAME>" << nodes_[i]->label() << "</NAME>" << endl;
|
|
|
|
const States& states = nodes_[i]->states();
|
|
|
|
for (unsigned j = 0; j < states.size(); j++) {
|
|
|
|
out << "\t<OUTCOME>" << states[j] << "</OUTCOME>" << endl;
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
|
|
|
out << "</VARIABLE>" << endl << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
out << "<DEFINITION>" << endl;
|
2011-12-12 15:29:51 +00:00
|
|
|
out << "\t<FOR>" << nodes_[i]->label() << "</FOR>" << endl;
|
2011-07-22 21:33:30 +01:00
|
|
|
const BnNodeSet& parents = nodes_[i]->getParents();
|
2011-05-17 12:00:33 +01:00
|
|
|
for (unsigned j = 0; j < parents.size(); j++) {
|
2011-12-12 15:29:51 +00:00
|
|
|
out << "\t<GIVEN>" << parents[j]->label();
|
2011-05-17 12:00:33 +01:00
|
|
|
out << "</GIVEN>" << endl;
|
|
|
|
}
|
2012-03-31 23:27:37 +01:00
|
|
|
Params params = revertParameterReorder (
|
2012-04-05 18:38:56 +01:00
|
|
|
nodes_[i]->params(), nodes_[i]->range());
|
2011-05-17 12:00:33 +01:00
|
|
|
out << "\t<TABLE>" ;
|
|
|
|
for (unsigned j = 0; j < params.size(); j++) {
|
|
|
|
out << " " << params[j];
|
|
|
|
}
|
|
|
|
out << " </TABLE>" << endl;
|
|
|
|
out << "</DEFINITION>" << endl << endl;
|
|
|
|
}
|
|
|
|
out << "</NETWORK>" << endl;
|
|
|
|
out << "</BIF>" << endl << endl;
|
2011-07-22 21:33:30 +01:00
|
|
|
out.close();
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
BayesNet::containsUndirectedCycle (void) const
|
|
|
|
{
|
|
|
|
vector<bool> visited (nodes_.size(), false);
|
|
|
|
for (unsigned i = 0; i < nodes_.size(); i++) {
|
|
|
|
int v = nodes_[i]->getIndex();
|
|
|
|
if (!visited[v]) {
|
|
|
|
if (containsUndirectedCycle (v, -1, visited)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2011-12-12 15:29:51 +00:00
|
|
|
BayesNet::containsUndirectedCycle (int v, int p, vector<bool>& visited) const
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
|
|
|
visited[v] = true;
|
|
|
|
vector<int> adjacencies = getAdjacentNodes (v);
|
|
|
|
for (unsigned i = 0; i < adjacencies.size(); i++) {
|
|
|
|
int w = adjacencies[i];
|
|
|
|
if (!visited[w]) {
|
|
|
|
if (containsUndirectedCycle (w, v, visited)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (visited[w] && w != p) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false; // no cycle detected in this component
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vector<int>
|
|
|
|
BayesNet::getAdjacentNodes (int v) const
|
|
|
|
{
|
|
|
|
vector<int> adjacencies;
|
2011-07-22 21:33:30 +01:00
|
|
|
const BnNodeSet& parents = nodes_[v]->getParents();
|
|
|
|
const BnNodeSet& childs = nodes_[v]->getChilds();
|
2011-05-17 12:00:33 +01:00
|
|
|
for (unsigned i = 0; i < parents.size(); i++) {
|
|
|
|
adjacencies.push_back (parents[i]->getIndex());
|
|
|
|
}
|
|
|
|
for (unsigned i = 0; i < childs.size(); i++) {
|
|
|
|
adjacencies.push_back (childs[i]->getIndex());
|
|
|
|
}
|
|
|
|
return adjacencies;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-03-22 11:33:24 +00:00
|
|
|
Params
|
|
|
|
BayesNet::reorderParameters (const Params& params, unsigned dsize) const
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
|
|
|
// the interchange format for bayesian networks keeps the probabilities
|
|
|
|
// in the following order:
|
|
|
|
// p(a1|b1,c1) p(a2|b1,c1) p(a1|b1,c2) p(a2|b1,c2) p(a1|b2,c1) p(a2|b2,c1)
|
|
|
|
// p(a1|b2,c2) p(a2|b2,c2).
|
|
|
|
//
|
|
|
|
// however, in clpbn we keep the probabilities in this order:
|
|
|
|
// p(a1|b1,c1) p(a1|b1,c2) p(a1|b2,c1) p(a1|b2,c2) p(a2|b1,c1) p(a2|b1,c2)
|
|
|
|
// p(a2|b2,c1) p(a2|b2,c2).
|
|
|
|
unsigned count = 0;
|
2011-12-12 15:29:51 +00:00
|
|
|
unsigned rowSize = params.size() / dsize;
|
2012-03-22 11:33:24 +00:00
|
|
|
Params reordered;
|
2011-05-17 12:00:33 +01:00
|
|
|
while (reordered.size() < params.size()) {
|
|
|
|
unsigned idx = count;
|
|
|
|
for (unsigned i = 0; i < rowSize; i++) {
|
|
|
|
reordered.push_back (params[idx]);
|
2011-12-12 15:29:51 +00:00
|
|
|
idx += dsize ;
|
2011-05-17 12:00:33 +01:00
|
|
|
}
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
return reordered;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-03-22 11:33:24 +00:00
|
|
|
Params
|
|
|
|
BayesNet::revertParameterReorder (const Params& params, unsigned dsize) const
|
2011-05-17 12:00:33 +01:00
|
|
|
{
|
|
|
|
unsigned count = 0;
|
2011-12-12 15:29:51 +00:00
|
|
|
unsigned rowSize = params.size() / dsize;
|
2012-03-22 11:33:24 +00:00
|
|
|
Params reordered;
|
2011-05-17 12:00:33 +01:00
|
|
|
while (reordered.size() < params.size()) {
|
|
|
|
unsigned idx = count;
|
2011-12-12 15:29:51 +00:00
|
|
|
for (unsigned i = 0; i < dsize; i++) {
|
2011-05-17 12:00:33 +01:00
|
|
|
reordered.push_back (params[idx]);
|
|
|
|
idx += rowSize;
|
|
|
|
}
|
|
|
|
count ++;
|
|
|
|
}
|
|
|
|
return reordered;
|
|
|
|
}
|
|
|
|
|