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/FactorGraph.cpp

530 lines
12 KiB
C++
Raw Normal View History

#include <set>
2011-12-12 15:29:51 +00:00
#include <vector>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include "FactorGraph.h"
#include "Factor.h"
#include "BayesNet.h"
2012-04-05 18:38:56 +01:00
#include "BayesBall.h"
2012-03-22 11:33:24 +00:00
#include "Util.h"
bool FactorGraph::orderFactorVariables = false;
FactorGraph::FactorGraph (const FactorGraph& fg)
{
2012-04-05 23:00:48 +01:00
const VarNodes& vars = fg.varNodes();
2012-03-22 11:33:24 +00:00
for (unsigned i = 0; i < vars.size(); i++) {
2012-04-05 23:00:48 +01:00
VarNode* varNode = new VarNode (vars[i]);
2012-03-22 11:33:24 +00:00
addVariable (varNode);
}
2012-04-05 23:00:48 +01:00
const FactorNodes& facs = fg.factorNodes();
2012-03-22 11:33:24 +00:00
for (unsigned i = 0; i < facs.size(); i++) {
2012-04-05 23:00:48 +01:00
FactorNode* facNode = new FactorNode (facs[i]);
2012-03-22 11:33:24 +00:00
addFactor (facNode);
2012-04-05 23:00:48 +01:00
const VarNodes& neighs = facs[i]->neighbors();
2012-03-22 11:33:24 +00:00
for (unsigned j = 0; j < neighs.size(); j++) {
addEdge (facNode, varNodes_[neighs[j]->getIndex()]);
}
}
}
2011-12-12 15:29:51 +00:00
void
FactorGraph::readFromUaiFormat (const char* fileName)
{
ifstream is (fileName);
if (!is.is_open()) {
cerr << "error: cannot read from file " + std::string (fileName) << endl;
abort();
}
string line;
while (is.peek() == '#' || is.peek() == '\n') getline (is, line);
getline (is, line);
if (line != "MARKOV") {
cerr << "error: the network must be a MARKOV network " << endl;
abort();
}
while (is.peek() == '#' || is.peek() == '\n') getline (is, line);
2011-12-12 15:29:51 +00:00
unsigned nVars;
is >> nVars;
while (is.peek() == '#' || is.peek() == '\n') getline (is, line);
vector<int> domainSizes (nVars);
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < nVars; i++) {
unsigned ds;
is >> ds;
domainSizes[i] = ds;
}
while (is.peek() == '#' || is.peek() == '\n') getline (is, line);
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < nVars; i++) {
2012-04-05 23:00:48 +01:00
addVariable (new VarNode (i, domainSizes[i]));
}
2011-12-12 15:29:51 +00:00
unsigned nFactors;
is >> nFactors;
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < nFactors; i++) {
while (is.peek() == '#' || is.peek() == '\n') getline (is, line);
2011-12-12 15:29:51 +00:00
unsigned nFactorVars;
is >> nFactorVars;
2012-04-05 23:00:48 +01:00
Vars neighs;
2011-12-12 15:29:51 +00:00
for (unsigned j = 0; j < nFactorVars; j++) {
unsigned vid;
is >> vid;
2012-04-05 23:00:48 +01:00
VarNode* neigh = getVarNode (vid);
2011-12-12 15:29:51 +00:00
if (!neigh) {
cerr << "error: invalid variable identifier (" << vid << ")" << endl;
abort();
}
2011-12-12 15:29:51 +00:00
neighs.push_back (neigh);
}
2012-04-05 23:00:48 +01:00
FactorNode* fn = new FactorNode (new Factor (neighs));
2011-12-12 15:29:51 +00:00
addFactor (fn);
for (unsigned j = 0; j < neighs.size(); j++) {
2012-04-05 23:00:48 +01:00
addEdge (fn, static_cast<VarNode*> (neighs[j]));
}
}
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < nFactors; i++) {
while (is.peek() == '#' || is.peek() == '\n') getline (is, line);
2011-12-12 15:29:51 +00:00
unsigned nParams;
is >> nParams;
2012-03-31 23:27:37 +01:00
if (facNodes_[i]->params().size() != nParams) {
2011-12-12 15:29:51 +00:00
cerr << "error: invalid number of parameters for factor " ;
cerr << facNodes_[i]->getLabel() ;
2012-03-31 23:27:37 +01:00
cerr << ", expected: " << facNodes_[i]->params().size();
2011-12-12 15:29:51 +00:00
cerr << ", given: " << nParams << endl;
abort();
}
2012-03-22 11:33:24 +00:00
Params params (nParams);
2011-12-12 15:29:51 +00:00
for (unsigned j = 0; j < nParams; j++) {
double param;
is >> param;
params[j] = param;
}
2012-03-22 11:33:24 +00:00
if (Globals::logDomain) {
2011-12-12 15:29:51 +00:00
Util::toLog (params);
}
2012-03-31 23:27:37 +01:00
facNodes_[i]->factor()->setParams (params);
}
is.close();
2011-12-12 15:29:51 +00:00
setIndexes();
}
2011-12-12 15:29:51 +00:00
void
FactorGraph::readFromLibDaiFormat (const char* fileName)
{
2011-12-12 15:29:51 +00:00
ifstream is (fileName);
if (!is.is_open()) {
cerr << "error: cannot read from file " + std::string (fileName) << endl;
abort();
}
2011-12-12 15:29:51 +00:00
string line;
unsigned nFactors;
while ((is.peek()) == '#') getline (is, line);
is >> nFactors;
if (is.fail()) {
cerr << "error: cannot read the number of factors" << endl;
abort();
}
getline (is, line);
if (is.fail() || line.size() > 0) {
cerr << "error: cannot read the number of factors" << endl;
abort();
}
for (unsigned i = 0; i < nFactors; i++) {
unsigned nVars;
while ((is.peek()) == '#') getline (is, line);
is >> nVars;
2012-03-22 11:33:24 +00:00
VarIds vids;
2011-12-12 15:29:51 +00:00
for (unsigned j = 0; j < nVars; j++) {
VarId vid;
while ((is.peek()) == '#') getline (is, line);
is >> vid;
vids.push_back (vid);
}
2012-04-05 23:00:48 +01:00
Vars neighs;
2011-12-12 15:29:51 +00:00
unsigned nParams = 1;
for (unsigned j = 0; j < nVars; j++) {
unsigned dsize;
while ((is.peek()) == '#') getline (is, line);
is >> dsize;
2012-04-05 23:00:48 +01:00
VarNode* var = getVarNode (vids[j]);
2011-12-12 15:29:51 +00:00
if (var == 0) {
2012-04-05 23:00:48 +01:00
var = new VarNode (vids[j], dsize);
2011-12-12 15:29:51 +00:00
addVariable (var);
} else {
2012-04-05 18:38:56 +01:00
if (var->range() != dsize) {
2011-12-12 15:29:51 +00:00
cerr << "error: variable `" << vids[j] << "' appears in two or " ;
cerr << "more factors with different domain sizes" << endl;
}
}
2011-12-12 15:29:51 +00:00
neighs.push_back (var);
2012-04-05 18:38:56 +01:00
nParams *= var->range();
2011-12-12 15:29:51 +00:00
}
2012-03-22 11:33:24 +00:00
Params params (nParams, 0);
2011-12-12 15:29:51 +00:00
unsigned nNonzeros;
2012-03-22 11:33:24 +00:00
while ((is.peek()) == '#') getline (is, line);
2011-12-12 15:29:51 +00:00
is >> nNonzeros;
for (unsigned j = 0; j < nNonzeros; j++) {
unsigned index;
2012-03-22 11:33:24 +00:00
double val;
2011-12-12 15:29:51 +00:00
while ((is.peek()) == '#') getline (is, line);
is >> index;
while ((is.peek()) == '#') getline (is, line);
is >> val;
params[index] = val;
}
reverse (neighs.begin(), neighs.end());
2012-03-22 11:33:24 +00:00
if (Globals::logDomain) {
2011-12-12 15:29:51 +00:00
Util::toLog (params);
}
2012-04-05 23:00:48 +01:00
FactorNode* fn = new FactorNode (new Factor (neighs, params));
2011-12-12 15:29:51 +00:00
addFactor (fn);
for (unsigned j = 0; j < neighs.size(); j++) {
2012-04-05 23:00:48 +01:00
addEdge (fn, static_cast<VarNode*> (neighs[j]));
}
}
2011-12-12 15:29:51 +00:00
is.close();
setIndexes();
}
FactorGraph::~FactorGraph (void)
{
for (unsigned i = 0; i < varNodes_.size(); i++) {
delete varNodes_[i];
}
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < facNodes_.size(); i++) {
delete facNodes_[i];
}
}
void
2012-04-05 23:00:48 +01:00
FactorGraph::addVariable (VarNode* vn)
{
2011-12-12 15:29:51 +00:00
varNodes_.push_back (vn);
vn->setIndex (varNodes_.size() - 1);
2012-03-22 11:33:24 +00:00
varMap_.insert (make_pair (vn->varId(), varNodes_.size() - 1));
}
void
2012-04-05 23:00:48 +01:00
FactorGraph::addFactor (FactorNode* fn)
{
2011-12-12 15:29:51 +00:00
facNodes_.push_back (fn);
fn->setIndex (facNodes_.size() - 1);
}
2012-03-22 11:33:24 +00:00
2012-04-05 18:38:56 +01:00
void
FactorGraph::addFactor (const Factor& factor)
{
2012-04-05 23:00:48 +01:00
FactorNode* fn = new FactorNode (factor);
2012-04-05 18:38:56 +01:00
addFactor (fn);
const VarIds& vids = factor.arguments();
for (unsigned i = 0; i < vids.size(); i++) {
bool found = false;
for (unsigned j = 0; j < varNodes_.size(); j++) {
if (varNodes_[j]->varId() == vids[i]) {
addEdge (varNodes_[j], fn);
found = true;
}
}
if (found == false) {
2012-04-05 23:00:48 +01:00
VarNode* vn = new VarNode (vids[i], factor.range (i));
2012-04-05 18:38:56 +01:00
addVariable (vn);
addEdge (vn, fn);
}
}
}
void
2012-04-05 23:00:48 +01:00
FactorGraph::addEdge (VarNode* vn, FactorNode* fn)
{
2011-12-12 15:29:51 +00:00
vn->addNeighbor (fn);
fn->addNeighbor (vn);
}
void
2012-04-05 23:00:48 +01:00
FactorGraph::addEdge (FactorNode* fn, VarNode* vn)
{
2011-12-12 15:29:51 +00:00
fn->addNeighbor (vn);
vn->addNeighbor (fn);
}
bool
FactorGraph::isTree (void) const
{
2011-12-12 15:29:51 +00:00
return !containsCycle();
}
2012-04-05 18:38:56 +01:00
DAGraph&
FactorGraph::getStructure (void)
{
assert (fromBayesNet_);
if (structure_.empty()) {
for (unsigned i = 0; i < varNodes_.size(); i++) {
structure_.addNode (new DAGraphNode (varNodes_[i]));
}
for (unsigned i = 0; i < facNodes_.size(); i++) {
const VarIds& vids = facNodes_[i]->factor()->arguments();
for (unsigned j = 1; j < vids.size(); j++) {
structure_.addEdge (vids[j], vids[0]);
}
}
}
return structure_;
}
void
FactorGraph::setIndexes (void)
{
for (unsigned i = 0; i < varNodes_.size(); i++) {
varNodes_[i]->setIndex (i);
}
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < facNodes_.size(); i++) {
facNodes_[i]->setIndex (i);
}
}
void
2012-04-05 23:00:48 +01:00
FactorGraph::print (void) const
{
for (unsigned i = 0; i < varNodes_.size(); i++) {
2012-04-05 18:38:56 +01:00
cout << "var id = " << varNodes_[i]->varId() << endl;
cout << "label = " << varNodes_[i]->label() << endl;
cout << "range = " << varNodes_[i]->range() << endl;
cout << "evidence = " << varNodes_[i]->getEvidence() << endl;
cout << "factors = " ;
2011-12-12 15:29:51 +00:00
for (unsigned j = 0; j < varNodes_[i]->neighbors().size(); j++) {
cout << varNodes_[i]->neighbors()[j]->getLabel() << " " ;
}
cout << endl << endl;
}
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < facNodes_.size(); i++) {
2012-03-22 11:33:24 +00:00
facNodes_[i]->factor()->print();
}
}
void
2011-12-12 15:29:51 +00:00
FactorGraph::exportToGraphViz (const char* fileName) const
{
ofstream out (fileName);
if (!out.is_open()) {
cerr << "error: cannot open file to write at " ;
cerr << "FactorGraph::exportToDotFile()" << endl;
abort();
}
out << "graph \"" << fileName << "\" {" << endl;
for (unsigned i = 0; i < varNodes_.size(); i++) {
if (varNodes_[i]->hasEvidence()) {
2011-12-12 15:29:51 +00:00
out << '"' << varNodes_[i]->label() << '"' ;
out << " [style=filled, fillcolor=yellow]" << endl;
}
}
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < facNodes_.size(); i++) {
out << '"' << facNodes_[i]->getLabel() << '"' ;
out << " [label=\"" << facNodes_[i]->getLabel();
out << "\"" << ", shape=box]" << endl;
}
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < facNodes_.size(); i++) {
2012-04-05 23:00:48 +01:00
const VarNodes& myVars = facNodes_[i]->neighbors();
for (unsigned j = 0; j < myVars.size(); j++) {
2011-12-12 15:29:51 +00:00
out << '"' << facNodes_[i]->getLabel() << '"' ;
out << " -- " ;
2011-12-12 15:29:51 +00:00
out << '"' << myVars[j]->label() << '"' << endl;
}
}
out << "}" << endl;
out.close();
}
void
FactorGraph::exportToUaiFormat (const char* fileName) const
{
ofstream out (fileName);
if (!out.is_open()) {
cerr << "error: cannot open file to write at " ;
cerr << "FactorGraph::exportToUaiFormat()" << endl;
abort();
}
out << "MARKOV" << endl;
out << varNodes_.size() << endl;
for (unsigned i = 0; i < varNodes_.size(); i++) {
2012-04-05 18:38:56 +01:00
out << varNodes_[i]->range() << " " ;
}
out << endl;
2011-12-12 15:29:51 +00:00
out << facNodes_.size() << endl;
for (unsigned i = 0; i < facNodes_.size(); i++) {
2012-04-05 23:00:48 +01:00
const VarNodes& factorVars = facNodes_[i]->neighbors();
out << factorVars.size();
for (unsigned j = 0; j < factorVars.size(); j++) {
out << " " << factorVars[j]->getIndex();
}
out << endl;
}
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < facNodes_.size(); i++) {
2012-03-31 23:27:37 +01:00
Params params = facNodes_[i]->params();
2012-03-22 11:33:24 +00:00
if (Globals::logDomain) {
Util::fromLog (params);
}
out << endl << params.size() << endl << " " ;
for (unsigned j = 0; j < params.size(); j++) {
out << params[j] << " " ;
}
out << endl;
}
out.close();
}
2011-12-12 15:29:51 +00:00
void
FactorGraph::exportToLibDaiFormat (const char* fileName) const
{
ofstream out (fileName);
if (!out.is_open()) {
cerr << "error: cannot open file to write at " ;
cerr << "FactorGraph::exportToLibDaiFormat()" << endl;
abort();
}
out << facNodes_.size() << endl << endl;
for (unsigned i = 0; i < facNodes_.size(); i++) {
2012-04-05 23:00:48 +01:00
const VarNodes& factorVars = facNodes_[i]->neighbors();
2011-12-12 15:29:51 +00:00
out << factorVars.size() << endl;
for (int j = factorVars.size() - 1; j >= 0; j--) {
out << factorVars[j]->varId() << " " ;
}
out << endl;
for (unsigned j = 0; j < factorVars.size(); j++) {
2012-04-05 18:38:56 +01:00
out << factorVars[j]->range() << " " ;
2011-12-12 15:29:51 +00:00
}
out << endl;
2012-03-31 23:27:37 +01:00
Params params = facNodes_[i]->factor()->params();
2012-03-22 11:33:24 +00:00
if (Globals::logDomain) {
Util::fromLog (params);
}
2011-12-12 15:29:51 +00:00
out << params.size() << endl;
for (unsigned j = 0; j < params.size(); j++) {
out << j << " " << params[j] << endl;
}
out << endl;
}
out.close();
}
bool
FactorGraph::containsCycle (void) const
{
vector<bool> visitedVars (varNodes_.size(), false);
vector<bool> visitedFactors (facNodes_.size(), false);
for (unsigned i = 0; i < varNodes_.size(); i++) {
int v = varNodes_[i]->getIndex();
if (!visitedVars[v]) {
if (containsCycle (varNodes_[i], 0, visitedVars, visitedFactors)) {
return true;
}
}
}
return false;
}
bool
2012-04-05 18:38:56 +01:00
FactorGraph::containsCycle (
2012-04-05 23:00:48 +01:00
const VarNode* v,
const FactorNode* p,
2012-04-05 18:38:56 +01:00
vector<bool>& visitedVars,
vector<bool>& visitedFactors) const
2011-12-12 15:29:51 +00:00
{
visitedVars[v->getIndex()] = true;
2012-04-05 23:00:48 +01:00
const FactorNodes& adjacencies = v->neighbors();
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < adjacencies.size(); i++) {
int w = adjacencies[i]->getIndex();
if (!visitedFactors[w]) {
if (containsCycle (adjacencies[i], v, visitedVars, visitedFactors)) {
return true;
}
}
else if (visitedFactors[w] && adjacencies[i] != p) {
return true;
}
}
return false; // no cycle detected in this component
}
bool
2012-04-05 18:38:56 +01:00
FactorGraph::containsCycle (
2012-04-05 23:00:48 +01:00
const FactorNode* v,
const VarNode* p,
2012-04-05 18:38:56 +01:00
vector<bool>& visitedVars,
vector<bool>& visitedFactors) const
2011-12-12 15:29:51 +00:00
{
visitedFactors[v->getIndex()] = true;
2012-04-05 23:00:48 +01:00
const VarNodes& adjacencies = v->neighbors();
2011-12-12 15:29:51 +00:00
for (unsigned i = 0; i < adjacencies.size(); i++) {
int w = adjacencies[i]->getIndex();
if (!visitedVars[w]) {
if (containsCycle (adjacencies[i], v, visitedVars, visitedFactors)) {
return true;
}
}
else if (visitedVars[w] && adjacencies[i] != p) {
return true;
}
}
return false; // no cycle detected in this component
}