These pages are meant as a help for developers programming against the
Hugin C++ API 6.1. Short descriptions can be found for all classes and
their members. However, additional information might be relevant for
different tasks. In such cases, the Hugin API 6.0 reference manual
will be a good place to look. It contains detailed documentation of
the Hugin C API 6.1 which is currently the basis of the C++ API
6.1. The Hugin API 6.1 reference manual can be downloaded from Hugin Expert A/S - Documentation.
ClassCollection Classes |
| ClassCollection |
Several types of errors can occur when using a class or member method from the Hugin C++ API. These errors can be the result of error in the application program, of running out of memory, of corrupted data files, etc.
As a general principle, the Hugin C++ API will try to recover from any error as well as possible. The API will then inform the application program of the problem and take no further action. It is then up to the application program to take the appropriate action.
When a member method fails, the data structures will always be left in a consistent state. Moreover, unless otherwise stated explicitly for a particular method, this state can be assumed identical to the state before the failed API call.
To communicate errors to the user of the Hugin C++ API, the API defines a set of exception classes. All exception classes are subclasses of ExceptionHugin.
The following examples describe how the Hugin C++ API can be used to manipulate Bayesian networks and influence diagrams, and to perform the two different kind of learning in the networks.
This first example is concerned with loading a Bayesian network or an influence diagram. Once the Bayesian network or influence diagram has been loaded the corresponding domain is triangulated using the minimum fill-in-weight heuristic and the compilation process is completed. Next, the members of each clique of the junction tree(s) are printed on standard output. Finally, a propagation of evidence is performed and the resulting posterior marginals are printed on standard output.
#include < vector >
#include < iostream >
#include < cstdio >
#include "hugin"
using namespace HAPI;
using namespace std;
class LAP {
public:
LAP(const string& fileName);
void printJunctionTrees(JunctionTreeList& list);
void printNodeMarginals(Domain *domain);
void printNodes(NodeList& list);
};
LAP::LAP(const string& fileName)
{
try
{
string netFileName = fileName + ".net";
Domain *domain = new Domain(netFileName, NULL);
string logFileName = fileName + ".log";
FILE *logFile = fopen(logFileName.c_str(), "w");
domain->setLogFile(logFile);
domain->triangulate(H_TM_FILL_IN_WEIGHT);
domain->compile();
printJunctionTrees(domain->getJunctionTrees());
domain->propagate(H_EQUILIBRIUM_SUM,
H_EVIDENCE_MODE_NORMAL);
printNodeMarginals(domain);
fclose(logFile);
string hkbFileName = fileName + ".hkb";
domain->save(hkbFileName, H_ENDIAN_BIG);
}
catch (ExceptionHugin *e) {
cerr << e->what() << endl;
}
}
/**
* Print the cliques of the junction tree(s).
*/
void LAP::printJunctionTrees(JunctionTreeList& list)
{
try
{
JunctionTreeList::iterator jtit = list.begin();
CliqueList clist;
CliqueList::iterator cliqueit = NULL;
cerr << "Cliques : ";
while (list.end() != jtit)
{
clist = (*jtit)->getCliques();
cliqueit = clist.begin();
while (clist.end() != cliqueit)
{
printNodes((*cliqueit)->getMembers());
cliqueit++;
}
jtit++;
}
cout << endl;
}
catch (ExceptionHugin *e) {
cerr << e->what() << endl;
}
}
/**
* Print the marginal distribution of each variable in the domain.
*/
void LAP::printNodeMarginals(Domain *domain)
{
try
{
Node *node;
NodeList nlist = domain->getNodes();
NodeList::iterator nit = nlist.begin();
while(nlist.end() != nit)
{
node = *nit;
cout << node->getLabel() << "("
<< node->getName() << ")" << endl;
if (node->getCategory()==H_CATEGORY_CHANCE)
{
if (node->getKind()==H_KIND_CONTINUOUS)
{
cout << "-Mean : "
<< ((ContinuousChanceNode*)node)->getMean() << endl;
cout << "-Variance : "
<< ((ContinuousChanceNode*)node)->getVariance()
<< endl;
}
else
if (node->getKind()==H_KIND_DISCRETE)
{
for (int i=0;i<((DiscreteChanceNode*)node)->getNumberOfStates();i++)
{
cout << "-"
<< ((DiscreteChanceNode*)node)->getStateLabel(i)
<< " "
<< ((DiscreteChanceNode*)node)->getBelief(i) << endl;
}
}
}
else
if (node->getCategory()==H_CATEGORY_DECISION)
{
for (int i=0;i<((DiscreteDecisionNode*)node)->getNumberOfStates();i++)
{
cout << "-"
<< ((DiscreteDecisionNode*)node)->getStateLabel(i)
<< " "
<< ((DiscreteDecisionNode*)node)->getExpectedUtility(i) << endl;
}
}
nit++;
}
}
catch (ExceptionHugin *e) {
cout << e->what() << endl;
}
}
/**
* Print the name of each node in the list.
*/
void LAP::printNodes(NodeList& list)
{
try
{
NodeList::iterator nit = list.begin();
while (list.end() != nit)
{
cout << (*nit)->getName() + " ";
nit++;
}
cout << endl;
}
catch (ExceptionHugin *e)
{
cout << e->what() << endl;
}
}
/**
* Load a Hugin net file and perform a single propagation of
* evidence. Print the results.
*/
int main (int argc, char *argv[])
{
new LAP(string(argv[1]));
return 0;
}
The second example describes how a Bayesian network can be constructed using the Hugin C++ API. The Bayesian network constructed consists of three numbered nodes. Two of the nodes take on values 0, 1, and 2. The third node is the sum of the two other nodes. Once the Bayesian network is constructed the network is saved to a net specification file and an initial propagation is performed. Finally, the marginals of the nodes are printed on standard output.
#include < vector >
#include < iostream >
#include "hugin"
using namespace HAPI;
using namespace std;
class BAP {
public:
BAP::BAP();
protected:
void propagateEvidenceInNetwork();
void printNodeMarginals(Domain *d);
NumberedDCNode* constructNDC(char *label, char *name, int n);
void buildStructure(NumberedDCNode *A, NumberedDCNode *B,
NumberedDCNode *C);
void buildExpressionForC(NumberedDCNode *A,
NumberedDCNode *B,
NumberedDCNode *C);
void specifyDistributions(NumberedDCNode *A,
NumberedDCNode *B);
void buildNetwork();
Domain *domain;
};
/**
* Build a Bayesian network and propagate evidence.
*/
BAP::BAP()
{
try
{
domain = new Domain();
buildNetwork();
domain->writeNet("builddomain.net");
domain->compile();
propagateEvidenceInNetwork();
} catch(ExceptionHugin *e) {
cout << e->what() << endl;
}
}
/**
* Propagate evidence in domain.
*/
void BAP::propagateEvidenceInNetwork()
{
try
{
domain->propagate(H_EQUILIBRIUM_SUM,
H_EVIDENCE_MODE_NORMAL);
printNodeMarginals(domain);
} catch (ExceptionHugin *e) {
cout << e->what() << endl;
}
}
/**
* print node marginals.
*/
void BAP::printNodeMarginals(Domain *d)
{
try
{
NodeList nlist = domain->getNodes();
NodeList::iterator nit = nlist.begin();
DiscreteChanceNode *node;
while(nlist.end() != nit)
{
node = (DiscreteChanceNode*) *nit;
cout << node->getLabel() << endl;
for (int i=0;i<((DiscreteChanceNode*)node)->getNumberOfStates(); i++)
cout << "-" << node->getStateLabel(i)
<< " " << node->getBelief(i) << endl;
nit++;
}
} catch (ExceptionHugin *e) {
cout << e->what() << endl;
}
}
/**
* Construct numbered discrete chance node.
*/
NumberedDCNode* BAP::constructNDC(char *label,
char *name,
int n)
{
try
{
NumberedDCNode *node = new NumberedDCNode(domain);
node->setNumberOfStates(n);
for (int i=0;isetStateValue(i, i);
char s[10];
for (i=0;isetStateLabel(i, s);
}
node->setLabel(label);
node->setName(name);
return node;
}
catch (ExceptionHugin *e) {
cout << e->what() << endl;
}
return NULL;
}
/**
* Build the structure.
*/
void BAP::buildStructure(NumberedDCNode *A,
NumberedDCNode *B,
NumberedDCNode *C)
{
try
{
C->addParent(A);
C->addParent(B);
A->setPosition(100, 200);
B->setPosition(200, 200);
C->setPosition(150, 50);
}
catch (ExceptionHugin *e) {
cout << e->what() << endl;
}
}
/**
* Expression for C
*/
void BAP::buildExpressionForC(NumberedDCNode *A,
NumberedDCNode *B,
NumberedDCNode *C)
{
try
{
NodeList modelNodes;
Model *model = new Model(C, modelNodes);
NodeExpression *exprA = new NodeExpression(A);
NodeExpression *exprB = new NodeExpression(B);
AddExpression *exprC = new AddExpression(exprA, exprB);
model->setExpression(0, exprC);
}
catch (ExceptionHugin *e) {
cout << e->what() << endl;
}
}
/**
* Specify the prior distribution of A and B.
*/
void BAP::specifyDistributions(NumberedDCNode *A,
NumberedDCNode *B)
{
try
{
Table *table;
table = A->getTable();
std::vector *data = new std::vector(3);
(*data)[0] = 0.1;
(*data)[1] = 0.2;
(*data)[2] = 0.7;
for (int i=0; i<3; i++)
table->getData()[i] = (*data)[i];
table = B->getTable();
table->getData()[0] = 0.2;
table->getData()[1] = 0.2;
table->getData()[2] = 0.6;
}
catch (ExceptionHugin *e) {
cout << e->what() << endl;
}
}
/**
* Build the Bayesian network.
*/
void BAP::buildNetwork()
{
try
{
domain->setNodeSize(50,30);
NumberedDCNode *A = constructNDC("A", "A", 3);
NumberedDCNode *B = constructNDC("B", "B", 3);
NumberedDCNode *C = constructNDC("C", "C", 5);
buildStructure(A,B,C);
buildExpressionForC(A,B,C);
specifyDistributions(A, B);
}
catch (ExceptionHugin *e) {
cout << e->what() << endl;
}
}
/**
* Build a Bayesian network and perform a propagation of
* evidence. Print the results.
*/
int main(int argc, char *argv[])
{
new BAP();
return 0;
}
Example three presents a skeleton for sequential learning. Sequential learning, or adaptation, is an update process applied to the conditional probability tables. After a network has been built, sequential learning can be applied during operation in order to maintain the correspondence between the model (conditional probability tables) and the real-world domain.
After the network is loaded in Hugin, the learning parameters are specified. Then follows the build-up and entering of cases, and finally, the tables are updated and node marginals are printed.
#include < vector >
#include < string >
#include < cstdio >
#include < iostream >
#include < exception >
#include "hugin"
using namespace HAPI;
using namespace std;
class Adapt {
public:
Adapt(const string &fileName);
private:
void specifyLearningParameters(Domain *d);
void printLearningParameters(Domain *d);
void enterCase(Domain *d);
void printCase(Domain *d);
void printNodeMarginals(Domain *d);
};
int main (int argc, char *argv[]) {
try {
new Adapt(string(argv[1]));
}
catch (exception e) {
cerr << e.what() << endl;
return -1;
}
catch (...) {
cerr << "caught something..." << endl;
return -2;
}
return 0;
}
Adapt::Adapt(const string &fileName) {
Domain *d;
try {
string netFileName = fileName + ".net";
d = new Domain(netFileName, NULL);
string logFileName = fileName + ".log";
FILE *logFile = fopen(logFileName.c_str(), "w");
d->setLogFile(logFile);
d->compile();
specifyLearningParameters(d);
printLearningParameters(d);
enterCase(d);
printCase(d);
d->adapt();
d->initialize();
d->propagate();
printNodeMarginals(d);
d->writeNet("q.net");
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin in Adapt::Adapt()." << endl;
cerr << eh.what() << endl;
return;
}
catch (exception e) {
cerr << "Caught general exception in Adapt::Adapt()." << endl;
cerr << e.what() << endl;
return;
}
}
void Adapt::specifyLearningParameters(Domain *d) {
NodeList nl;
NodeList::iterator nlIter, nlEnd;
DiscreteChanceNode *node;
Table *table;
vector data;
try {
nl = d->getNodes();
nlIter = nl.begin();
nlEnd = nl.end();
while (nlIter != nlEnd) {
node = dynamic_cast (*nlIter);
table = node->getExperienceTable();
data.clear();
data.insert(data.end(), table->getSize(), 1);
table->setData(data);
nlIter++;
}
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin" << endl;
cerr << "Filling experience tables in Adapt::specifyLearningParameters()"
<< endl;
cerr << eh.what() << endl;
throw eh;
}
catch (exception e) {
cerr << "Caught general exception" << endl;
cerr << "Filling experience tables in Adapt::specifyLearningParameters()"
<< endl;
cerr << e.what() << endl;
throw e;
}
try {
nlIter = nl.begin();
nlEnd = nl.end();
while (nlIter != nlEnd) {
node = dynamic_cast (*nlIter);
table = node->getFadingTable();
data.clear();
data.insert(data.end(), table->getSize(), 1);
table->setData(data);
nlIter++;
}
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin in Adapt::specifyLearningParameters()"
<< endl;
cerr << "Filling fading tables in Adapt::specifyLearningParameters()"
<< endl;
cerr << eh.what() << endl;
throw eh;
}
catch (exception e) {
cerr << "General exception in Adapt::specifyLearningParameters()"
<< endl;
cerr << "Filling fading tables in Adapt::specifyLearningParameters()"
<< endl;
cerr << e.what() << endl;
throw e;
}
}
void Adapt::printLearningParameters(Domain *d) {
NodeList nl;
NodeList::iterator nlIter, nlEnd;
DiscreteChanceNode *dcNode;
Table *table;
try {
nl = d->getNodes();
nlIter = nl.begin();
nlEnd = nl.end();
while (nlIter != nlEnd) {
dcNode = dynamic_cast (*nlIter);
cout << dcNode->getLabel() << " (" << dcNode->getName() << "): " << endl;
cout << " ";
if (dcNode->hasExperienceTable()) {
table = dcNode->getExperienceTable();
int i, tblSize;
tblSize = table->getSize();
for (i = 0; i < tblSize; i++) {
cout << table->getData()[i] << " ";
}
cout << endl;
}
else {
cout << "No experience table" << endl;
}
cout << " ";
if (dcNode->hasFadingTable()) {
table = dcNode->getFadingTable();
int i, tblSize;
tblSize = table->getSize();
for (i = 0; i < tblSize; i++) {
cout << table->getData()[i] << " ";
}
cout << endl;
}
else {
cout << "No fading table" << endl;
}
nlIter++;
}
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin in Adapt::printLearningParameters()." << endl;
cerr << eh.what() << endl;
}
catch (exception e) {
cerr << "Caught general exception in Adapt::printLearningParameters()."
<< endl;
cerr << e.what() << endl;
}
}
void Adapt::enterCase(Domain *d) {
DiscreteChanceNode *dcNode;
NodeList::iterator nlIter;
NodeList::iterator nlEnd;
NodeList nl;
try {
nl = d->getNodes();
nlIter = nl.begin();
nlEnd = nl.end();
while (nlIter != nlEnd) {
dcNode = dynamic_cast (*nlIter);
dcNode->selectState(0);
nlIter++;
}
dcNode = dynamic_cast (nl[1]));
dcNode->retractFindings();
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin in Adapt::enterCase()" << endl;
cerr << eh.what() << endl;
throw eh;
}
catch (exception e) {
cerr << "Caught general exception in Adapt::enterCase()" << endl;
cerr << e.what() << endl;
throw e;
}
}
void Adapt::printCase(Domain *d) {
DiscreteChanceNode *dcNode;
NodeList::iterator nlIter;
NodeList::iterator nlEnd;
NodeList nl;
try {
nl = d->getNodes();
nlIter = nl.begin();
nlEnd = nl.end();
while (nlIter != nlEnd) {
dcNode = dynamic_cast (*nlIter);
cout << "(" + dcNode->getName() + ",";
if (dcNode->isEvidenceEntered())
cout << " evidence entered) ";
else
cout << " evidence not entered) ";
nlIter++;
}
cout << endl;
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin in Adapt::printCase()" << endl;
cerr << eh.what() << endl;
throw eh;
}
catch (exception e) {
cerr << "Caught general exception in Adapt::printCase()" << endl;
cerr << e.what() << endl;
throw e;
}
}
void Adapt::printNodeMarginals(Domain *d) {
DiscreteChanceNode *dcNode;
NodeList::iterator nlIter;
NodeList::iterator nlEnd;
NodeList nl;
int i, nStates;
try {
nl = d->getNodes();
nlIter = nl.begin();
nlEnd = nl.end();
while (nlIter != nlEnd) {
dcNode = dynamic_cast (*nlIter);
nStates = dcNode->getNumberOfStates();
cout << dcNode->getLabel() + " (" + dcNode->getName() + ")" << endl;
string res;
for (i = 0; i < nStates; i++) {
cout << " - " << dcNode->getStateLabel(i)
<< ": " << dcNode->getBelief(i) << endl;
}
nlIter++;
}
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin in Adapt::printNodeMarginals()" << endl;
cerr << eh.what() << endl;
throw eh;
}
catch (exception e) {
cerr << "Caught general exception in Adapt::printNodeMarginals()" << endl;
cerr << e.what() << endl;
throw e;
}
}
The fourth example shows how the Hugin C++ API can be used for parametric learning in a Bayesian network. The network is loaded from disk, and the parameters controlling the learning process are loaded. Then, the conditional probability tables are computed from data using the EM algorithm. Finally, the node marginals are printed.
#include < vector >
#include < string >
#include < cstdio >
#include < iostream >
#include < exception >
#include "hugin"
using namespace HAPI;
using namespace std;
class EM {
public:
EM(const string &fileName);
private:
void specifyLearningParameters(Domain *d);
void printLearningParameters(Domain *d);
void loadCases(Domain *d);
void printCases(Domain *d);
void printNodeMarginals(Domain *d);
};
int main (int argc, char *argv[]) {
try {
new EM(string(argv[1]));
}
catch (exception e) {
cerr << e.what() << endl;
return -1;
}
catch (...) {
cerr << "caught something..." << endl;
return -2;
}
return 0;
}
EM::EM(const string &fileName) {
Domain *d;
try {
string netFileName = fileName + ".net";
d = new Domain(netFileName, NULL);
string logFileName = fileName + ".log";
FILE *logFile = fopen(logFileName.c_str(), "w");
d->setLogFile(logFile);
d->compile();
specifyLearningParameters(d);
printLearningParameters(d);
loadCases(d);
printCases(d);
d->learnTables();
d->setNumberOfCases(0); // ??
cout << "Log likelihood: " << d->getLogLikelihood() << endl;
d->initialize();
d->propagate();
printNodeMarginals(d);
d->writeNet("q.net");
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin in EM::EM()." << endl;
cerr << eh.what() << endl;
return;
}
catch (exception e) {
cerr << "Caught general exception in EM::EM()." << endl;
cerr << e.what() << endl;
return;
}
}
void EM::specifyLearningParameters(Domain *d) {
NodeList nl;
NodeList::iterator nlIter, nlEnd;
DiscreteChanceNode *node;
Table *table;
vector data;
try {
nl = d->getNodes();
nlIter = nl.begin();
nlEnd = nl.end();
while (nlIter != nlEnd) {
node = dynamic_cast (*nlIter);
table = node->getExperienceTable();
data.clear();
data.insert(data.end(), table->getSize(), 1);
table->setData(data);
nlIter++;
}
d->setLogLikelihoodTolerance(0.000001);
d->setMaxNumberOfEMIterations(1000);
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin" << endl;
cerr << "Filling experience tables in EM::specifyLearningParameters(Domain *d)"
<< endl;
cerr << eh.what() << endl;
throw eh;
}
catch (exception e) {
cerr << "Caught general exception" << endl;
cerr << "Filling experience tables in EM::specifyLearningParameters(Domain *d)"
<< endl;
cerr << e.what() << endl;
throw e;
}
}
void EM::printLearningParameters(Domain *d) {
NodeList nl;
NodeList::iterator nlIter, nlEnd;
DiscreteChanceNode *dcNode;
Table *table;
try {
nl = d->getNodes();
nlIter = nl.begin();
nlEnd = nl.end();
while (nlIter != nlEnd) {
dcNode = dynamic_cast (*nlIter);
cout << dcNode->getLabel() << " (" << dcNode->getName() << "): " << endl;
cout << " ";
if (dcNode->hasExperienceTable()) {
table = dcNode->getExperienceTable();
int i, tblSize;
tblSize = table->getSize();
for (i = 0; i < tblSize; i++) {
cout << table->getData()[i] << " ";
}
cout << endl;
}
else {
cout << "No experience table" << endl;
}
cout << " ";
if (dcNode->hasFadingTable()) {
table = dcNode->getFadingTable();
int i, tblSize;
tblSize = table->getSize();
for (i = 0; i < tblSize; i++) {
cout << table->getData()[i] << " ";
}
cout << endl;
}
else {
cout << "No fading table" << endl;
}
nlIter++;
}
cout << "Log likelihood tolerance: " << d->getLogLikelihoodTolerance() << endl;
cout << "Max EM iterations: " << d->getMaxNumberOfEMIterations() << endl;
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin." << endl;
cerr << eh.what() << endl;
}
catch (exception e) {
cerr << "Caught general exception." << endl;
cerr << e.what() << endl;
}
}
void EM::loadCases(Domain *d) {
DiscreteChanceNode *dcNode;
int iCase;
NodeList::iterator nlIter;
NodeList::iterator nlEnd;
NodeList nl;
try {
nl = d->getNodes();
nlIter = nl.begin();
nlEnd = nl.end();
d->setNumberOfCases(0);
iCase = d->newCase();
cout << "Case index: " << iCase << endl;
d->setCaseCount(iCase, 2.5);
while (nlIter != nlEnd) {
dcNode = dynamic_cast (*nlIter);
dcNode->setCaseState(iCase, 0);
nlIter++;
}
dcNode = dynamic_cast (nl[1]);
dcNode->unsetCase(iCase);
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin in EM::enterCase(Domain *d)" << endl;
cerr << eh.what() << endl;
throw eh;
}
catch (exception e) {
cerr << "Caught general exception in EM::enterCase(Domain *d)" << endl;
cerr << e.what() << endl;
throw e;
}
}
void EM::printCases(Domain *d) {
DiscreteChanceNode *dcNode;
NodeList::iterator nlIter;
NodeList::iterator nlEnd;
NodeList nl;
try {
nl = d->getNodes();
nlIter = nl.begin();
nlEnd = nl.end();
int nCases = d->getNumberOfCases();
int i;
cout << "Number of cases: " << nCases << endl;
for (i = 0; i < nCases; i++) {
cout << "case " << i << " " << d->getCaseCount(i) << " " << endl;
while (nlIter != nlEnd) {
dcNode = dynamic_cast (*nlIter);
cout << "(" + dcNode->getName() + ",";
if (dcNode->caseIsSet(i))
cout << dcNode->getCaseState(i) << ") ";
else
cout << "N/A) ";
nlIter++;
}
}
cout << endl;
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin in EM::printCase(Domain *d)" << endl;
cerr << eh.what() << endl;
throw eh;
}
catch (exception e) {
cerr << "Caught general exception in EM::printCase(Domain *d)" << endl;
cerr << e.what() << endl;
throw e;
}
}
void EM::printNodeMarginals(Domain *d) {
DiscreteChanceNode *dcNode;
NodeList::iterator nlIter;
NodeList::iterator nlEnd;
NodeList nl;
int i, nStates;
try {
nl = d->getNodes();
nlIter = nl.begin();
nlEnd = nl.end();
while (nlIter != nlEnd) {
dcNode = dynamic_cast (*nlIter);
nStates = dcNode->getNumberOfStates();
cout << dcNode->getLabel() + " (" + dcNode->getName() + ")" << endl;
string res;
for (i = 0; i < nStates; i++) {
cout << " - " << dcNode->getStateLabel(i)
<< ": " << dcNode->getBelief(i) << endl;
}
nlIter++;
}
}
catch (ExceptionHugin eh) {
cerr << "Caught ExceptionHugin in EM::printNodeMarginals(Domain *d)" << endl;
cerr << eh.what() << endl;
throw eh;
}
catch (exception e) {
cerr << "Caught general exception in EM::printNodeMarginals(Domain *d)"
<< endl;
cerr << e.what() << endl;
throw e;
}
}
The last example demonstrates the Object Oriented network facilities
of the Hugin C++ API. It starts out be creating two very simple
networks. Creates an instance of one network in the other. Then it
uses the input and output nodes in the instance to connect the two
networks, and creates a runtime domain from the class. It ends by
printing the origin of all the nodes in the domain.
#include < stdio.h >
#include "hugin"
using namespace HAPI;
class ClassBuildInstance{
public:
int test();
};
/* Build the first network. This will contain an
instance of the second network
*/
void buildFirst(Class* cls){
LabelledDCNode *node1, *node2, *node3;
node1=new LabelledDCNode(cls);
node1->setName("c1_n1");
node1->setNumberOfStates(3);
node2=new LabelledDCNode(cls);
node2->setName("c1_n2");
node2->setNumberOfStates(2);
node3=new LabelledDCNode(cls);
node3->setName("c1_n3");
node3->setNumberOfStates(3);
node2->addParent(node1);
node3->addParent(node2);
}
/* Build the second network to be instantiated in
the first network
*/
void buildSecond(Class* cls){
LabelledDCNode *node1, *node2, *node3;
node1=new LabelledDCNode(cls);
node1->setName("c2_n1");
node1->setNumberOfStates(3);
node2=new LabelledDCNode(cls);
node2->setName("c2_n2");
node2->setNumberOfStates(2);
node3=new LabelledDCNode(cls);
node3->setName("c2_n3");
node3->setNumberOfStates(3);
node3->addParent(node1);
node3->addParent(node2);
// make node3 output node
node3->addToOutputs();
// make node2 input node
// note that only nodes with no parents can be input node
node2->addToInputs();
}
int ClassBuildInstance::test(){
try{
ClassCollection* coll;
Class* cls1, *cls2;
ClassList *clsList;
LabelledDCNode *node, *node2;
InstanceNode *instance;
// create the class collection to contain the classes
coll=new ClassCollection();
// create the first class in the collection
cls1=new Class(coll);
cls1->setName("c1");
buildFirst(cls1);
// create the second class in the collection
cls2=new Class(coll);
cls2->setName("c2");
buildSecond(cls2);
cerr<<"----------------------------------------\n";
cerr<<"Testing instances\n";
cerr<<"----------------------------------------\n";
// create an instance of cls2 in cls1
instance=new InstanceNode(cls1, cls2);
cerr<<"Instance derived from "<getClass()->getName()<getNodeByName("c2_n3");
// we will add the clone of the output as parent to c1_n2
node2=(LabelledDCNode*)cls1->getNodeByName("c1_n2");
// instance->getOutput retrieves the output clone for the given node
node2->addParent((DiscreteChanceNode*)instance->getOutput(node));
cerr<<"Removing output \n";
// removing the c2_n3 from the output list. This will
// delete the output clone, so that c1_n2 no longer has that as parent
node->removeFromOutputs();
cerr<<"Done \n";
cerr<<"\n----------------------------------------\n";
cerr<<"Testing inputs and bindings\n";
cerr<<"----------------------------------------\n";
// get the first (and only) input node from cls2
node=((LabelledDCNode*)cls2->getInputs().front());
node2=(LabelledDCNode*)cls1->getNodeByName("c1_n2");
// bind c1_n2 to the input node. This effectively replaces
// the table of the input node with that of the bound node
instance->setInput(node, node2);
cerr<<"Bound "<getName()<<" to "<getInput(node)->getName()<createDomain();
// print out the origin of all nodes in the domain
NodeList nodes=dom->getNodes();
NodeList list;
for(int j=0; jgetSource();
cerr<getName()<<" comes from ";
for(int i=0; igetName()<<(i+1==list.size() ? "\n":".");
}
}
dom->writeNet("cbap.net");
coll->saveAsNet("cbColl.net");
}
catch(ExceptionHugin e){
cerr<<"Caught exception\n";
cerr<test();
}