This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/packages/CLPBN/clpbn/bp/BayesianNode.cpp
2011-02-23 15:31:56 +00:00

383 lines
7.2 KiB
C++

#include <iostream>
#include <iomanip>
#include <cassert>
#include "BayesianNode.h"
#include "CptEntry.h"
BayesianNode::BayesianNode (string varName,
vector<BayesianNode*> parents,
Distribution* dist,
int evidence)
{
varName_ = varName;
parents_ = parents;
dist_ = dist;
evidence_ = evidence;
for (unsigned int i = 0; i < parents.size(); i++) {
parents[i]->addChild (this);
}
}
BayesianNode::~BayesianNode (void)
{
}
string
BayesianNode::getVariableName (void) const
{
return varName_;
}
vector<BayesianNode*>
BayesianNode::getParents (void) const
{
return parents_;
}
vector<BayesianNode*>
BayesianNode::getChilds (void) const
{
return childs_;
}
void
BayesianNode::addChild (BayesianNode* node)
{
childs_.push_back (node);
}
double*
BayesianNode::getParameters (void)
{
return dist_->params;
}
double*
BayesianNode::getRow (int rowIndex) const
{
int offset = getRowSize() * rowIndex;
return &dist_->params[offset];
}
double
BayesianNode::getProbability (CptEntry& entry)
{
int index = entry.getCptIndex();
return dist_->params[index];
}
void
BayesianNode::setProbability (CptEntry& entry, double prob)
{
int index = entry.getCptIndex();
dist_->params[index] = prob;
}
bool
BayesianNode::isRoot (void)
{
return parents_.empty();
}
bool
BayesianNode::isLeaf (void)
{
return childs_.empty();
}
int
BayesianNode::getRowSize (void) const
{
return dist_->nParams / dist_->domain.size();
}
int
BayesianNode::getCptSize (void)
{
return dist_->nParams;
}
vector<string>
BayesianNode::getDomain (void) const
{
return dist_->domain;
}
int
BayesianNode::getDomainSize (void) const
{
return dist_->domain.size();
}
vector<CptEntry>
BayesianNode::getCptEntries (const vector<pair<int,int> >& constraints)
{
vector<CptEntry> matchedEntries;
if (constraints.size() > 0 && constraints[0].first == 0) {
vector<CptEntry> entries = getCptEntriesOfRow (constraints[0].second);
for (unsigned int i = 0; i < entries.size(); i++) {
if (entries[i].matchConstraints (constraints)) {
matchedEntries.push_back (entries[i]);
}
}
}
else {
for (unsigned int i = 0; i < dist_->domain.size(); i++) {
vector<CptEntry> entries = getCptEntriesOfRow (i);
for (unsigned int j = 0; j < entries.size(); j++) {
if (entries[j].matchConstraints (constraints)) {
matchedEntries.push_back (entries[j]);
}
}
}
}
return matchedEntries;
}
vector<CptEntry>
BayesianNode::getCptEntriesOfRow (int rowIndex)
{
int rowSize = getRowSize();
int nParents = parents_.size();
vector<vector<int> > insts (rowSize);
for (int i = 0; i < rowSize; i++) {
insts[i].resize (nParents + 1);
insts[i][0] = rowIndex;
}
int reps = 1;
for (int i = nParents - 1; i >= 0; i--) {
int index = 0;
while (index < rowSize) {
for (int j = 0; j < parents_[i]->getDomainSize(); j++) {
for (int k = 0; k < reps; k++) {
insts[index][i + 1] = j;
index++;
}
}
}
reps *= parents_[i]->getDomainSize();
}
vector<CptEntry> entries;
for (int i = 0; i < rowSize; i++ ) {
entries.push_back (CptEntry ((rowIndex * rowSize) + i, insts[i]));
}
return entries;
}
int
BayesianNode::getIndexOfParent (const BayesianNode* myParent) const
{
for (unsigned int i = 0; i < parents_.size(); i++) {
if (myParent == parents_[i]) {
return i;
}
}
return -1;
}
bool
BayesianNode::hasEvidence (void)
{
return evidence_ != -1;
}
int
BayesianNode::getEvidence (void)
{
return evidence_;
}
void
BayesianNode::setEvidence (int evidence)
{
evidence_ = evidence;
}
string
BayesianNode::entryToString (const CptEntry& entry) const
{
string s = "p(" ;
vector<int> insts = entry.getDomainInstantiations();
s += getDomain()[insts[0]];
if (parents_.size() > 0) {
s += "|" ;
for (unsigned int i = 1; i < insts.size() - 1; i++) {
s += parents_[i - 1]->getDomain()[insts[i]] + ",";
}
BayesianNode* lastParent = parents_[parents_.size() - 1];
int lastIndex = insts[insts.size() - 1];
s += lastParent->getDomain()[lastIndex];
}
s += ")" ;
return s;
}
vector<string>
BayesianNode::getDomainHeaders (void) const
{
int rowSize = getRowSize();
int nParents = parents_.size();
int reps = 1;
vector<string> headers (rowSize);
for (int i = nParents - 1; i >= 0; i--) {
vector<string> domain = parents_[i]->getDomain();
int index = 0;
while (index < rowSize) {
for (int j = 0; j < parents_[i]->getDomainSize(); j++) {
for (int k = 0; k < reps; k++) {
if (headers[index] != "") {
headers[index] = domain[j] + "," + headers[index];
} else {
headers[index] = domain[j];
}
index++;
}
}
}
reps *= parents_[i]->getDomainSize();
}
return headers;
}
ostream&
operator << (ostream& o, const BayesianNode& node)
{
o << "Variable: " << node.getVariableName() << endl;
o << "Domain: " ;
vector<string> domain = node.dist_->domain;
for (unsigned int i = 0; i < domain.size() - 1; i++) {
o << domain[i] << ", " ;
}
if (domain.size() != 0) {
o << domain[domain.size() - 1];
}
o << endl;
o << "Parents: " ;
vector<BayesianNode*> parents = node.getParents();
if (parents.size() != 0) {
for (unsigned int i = 0; i < parents.size() - 1; i++) {
o << parents[i]->getVariableName() << ", " ;
}
o << parents[parents.size() - 1]->getVariableName();
}
o << endl;
o << "Childs: " ;
vector<BayesianNode*> childs = node.getChilds();
if (childs.size() != 0) {
for (unsigned int i = 0; i < childs.size() - 1; i++) {
o << childs[i]->getVariableName() << ", " ;
}
o << childs[childs.size() - 1]->getVariableName();
}
o << endl;
const unsigned int MIN_DOMAIN_WIDTH = 4; // min width of first column
const unsigned int MIN_COMBO_WIDTH = 12; // min width of following columns
unsigned int domainWidth = domain[0].length();
for (unsigned int i = 1; i < domain.size(); i++) {
if (domain[i].length() > domainWidth) {
domainWidth = domain[i].length();
}
}
domainWidth = (domainWidth < MIN_DOMAIN_WIDTH)
? MIN_DOMAIN_WIDTH
: domainWidth;
o << left << setw (domainWidth) << "cpt" << right;
vector<int> widths;
int lineWidth = domainWidth;
vector<string> headers = node.getDomainHeaders();
if (!headers.empty()) {
for (unsigned int i = 0; i < headers.size(); i++) {
unsigned int len = headers[i].length();
int w = (len < MIN_COMBO_WIDTH) ? MIN_COMBO_WIDTH : len;
widths.push_back (w);
o << setw (w) << headers[i];
lineWidth += w;
}
o << endl;
} else {
cout << endl;
widths.push_back (domainWidth);
lineWidth += MIN_COMBO_WIDTH;
}
for (int i = 0; i < lineWidth; i++) {
o << "-" ;
}
o << endl;
for (unsigned int i = 0; i < domain.size(); i++) {
double* row = node.getRow (i);
o << left << setw (domainWidth) << domain[i] << right;
for (int j = 0; j < node.getRowSize(); j++) {
o << setw (widths[j]) << row[j];
}
o << endl;
}
o << endl;
return o;
}