383 lines
7.2 KiB
C++
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;
|
|
}
|
|
|