new version of bp

This commit is contained in:
Vitor Santos Costa 2012-03-22 11:33:24 +00:00
parent 6e36498cac
commit 21d317b223
91 changed files with 1255511 additions and 3840 deletions

View File

@ -8,6 +8,7 @@
#include "xmlParser/xmlParser.h" #include "xmlParser/xmlParser.h"
#include "BayesNet.h" #include "BayesNet.h"
#include "Util.h"
@ -75,7 +76,7 @@ BayesNet::readFromBifFormat (const char* fileName)
} }
node->setParents (parents); node->setParents (parents);
unsigned count = 0; unsigned count = 0;
ParamSet params (nParams); Params params (nParams);
stringstream s (def.getChildNode("TABLE").getText()); stringstream s (def.getChildNode("TABLE").getText());
while (!s.eof() && count < nParams) { while (!s.eof() && count < nParams) {
s >> params[count]; s >> params[count];
@ -93,27 +94,18 @@ BayesNet::readFromBifFormat (const char* fileName)
} }
setIndexes(); setIndexes();
if (NSPACE == NumberSpace::LOGARITHM) { if (Globals::logDomain) {
distributionsToLogs(); distributionsToLogs();
} }
} }
void
BayesNet::addNode (BayesNode* n)
{
indexMap_.insert (make_pair (n->varId(), nodes_.size()));
nodes_.push_back (n);
}
BayesNode* BayesNode*
BayesNet::addNode (string label, const States& states) BayesNet::addNode (string label, const States& states)
{ {
VarId vid = nodes_.size(); VarId vid = nodes_.size();
indexMap_.insert (make_pair (vid, nodes_.size())); varMap_.insert (make_pair (vid, nodes_.size()));
GraphicalModel::addVariableInformation (vid, label, states); GraphicalModel::addVariableInformation (vid, label, states);
BayesNode* node = new BayesNode (VarNode (vid, states.size())); BayesNode* node = new BayesNode (VarNode (vid, states.size()));
nodes_.push_back (node); nodes_.push_back (node);
@ -123,56 +115,20 @@ BayesNet::addNode (string label, const States& states)
BayesNode* BayesNode*
BayesNet::addNode (VarId vid, BayesNet::addNode (VarId vid, unsigned dsize, int evidence, Distribution* dist)
unsigned dsize,
int evidence,
BnNodeSet& parents,
Distribution* dist)
{ {
indexMap_.insert (make_pair (vid, nodes_.size())); varMap_.insert (make_pair (vid, nodes_.size()));
nodes_.push_back (new BayesNode (vid, dsize, evidence, parents, dist));
return nodes_.back();
}
BayesNode*
BayesNet::addNode (VarId vid,
unsigned dsize,
int evidence,
Distribution* dist)
{
indexMap_.insert (make_pair (vid, nodes_.size()));
nodes_.push_back (new BayesNode (vid, dsize, evidence, dist)); nodes_.push_back (new BayesNode (vid, dsize, evidence, dist));
return nodes_.back(); return nodes_.back();
} }
BayesNode*
BayesNet::addNode (string label,
States states,
BnNodeSet& parents,
ParamSet& params)
{
VarId vid = nodes_.size();
indexMap_.insert (make_pair (vid, nodes_.size()));
GraphicalModel::addVariableInformation (vid, label, states);
Distribution* dist = new Distribution (params);
BayesNode* node = new BayesNode (
vid, states.size(), NO_EVIDENCE, parents, dist);
dists_.push_back (dist);
nodes_.push_back (node);
return node;
}
BayesNode* BayesNode*
BayesNet::getBayesNode (VarId vid) const BayesNet::getBayesNode (VarId vid) const
{ {
IndexMap::const_iterator it = indexMap_.find (vid); IndexMap::const_iterator it = varMap_.find (vid);
if (it == indexMap_.end()) { if (it == varMap_.end()) {
return 0; return 0;
} else { } else {
return nodes_[it->second]; return nodes_[it->second];
@ -233,7 +189,7 @@ BayesNet::getDistribution (unsigned distId) const
{ {
Distribution* dist = 0; Distribution* dist = 0;
for (unsigned i = 0; i < dists_.size(); i++) { for (unsigned i = 0; i < dists_.size(); i++) {
if (dists_[i]->id == distId) { if (dists_[i]->id == (int) distId) {
dist = dists_[i]; dist = dists_[i];
break; break;
} }
@ -290,33 +246,25 @@ BayesNet::getLeafNodes (void) const
BayesNet* BayesNet*
BayesNet::getMinimalRequesiteNetwork (VarId vid) const BayesNet::getMinimalRequesiteNetwork (VarId vid) const
{ {
return getMinimalRequesiteNetwork (VarIdSet() = {vid}); return getMinimalRequesiteNetwork (VarIds() = {vid});
} }
BayesNet* BayesNet*
BayesNet::getMinimalRequesiteNetwork (const VarIdSet& queryVarIds) const BayesNet::getMinimalRequesiteNetwork (const VarIds& queryVarIds) const
{ {
BnNodeSet queryVars; BnNodeSet queryVars;
Scheduling scheduling;
for (unsigned i = 0; i < queryVarIds.size(); i++) { for (unsigned i = 0; i < queryVarIds.size(); i++) {
assert (getBayesNode (queryVarIds[i])); BayesNode* n = getBayesNode (queryVarIds[i]);
queryVars.push_back (getBayesNode (queryVarIds[i])); assert (n);
queryVars.push_back (n);
scheduling.push (ScheduleInfo (n, false, true));
} }
// cout << "query vars: " ;
// for (unsigned i = 0; i < queryVars.size(); i++) {
// cout << queryVars[i]->label() << " " ;
// }
// cout << endl;
vector<StateInfo*> states (nodes_.size(), 0); vector<StateInfo*> states (nodes_.size(), 0);
Scheduling scheduling;
for (BnNodeSet::const_iterator it = queryVars.begin();
it != queryVars.end(); it++) {
scheduling.push (ScheduleInfo (*it, false, true));
}
while (!scheduling.empty()) { while (!scheduling.empty()) {
ScheduleInfo& sch = scheduling.front(); ScheduleInfo& sch = scheduling.front();
StateInfo* state = states[sch.node->getIndex()]; StateInfo* state = states[sch.node->getIndex()];
@ -385,7 +333,7 @@ BayesNet::constructGraph (BayesNet* bn,
const vector<StateInfo*>& states) const const vector<StateInfo*>& states) const
{ {
BnNodeSet mrnNodes; BnNodeSet mrnNodes;
vector<VarIdSet> parents; vector<VarIds> parents;
for (unsigned i = 0; i < nodes_.size(); i++) { for (unsigned i = 0; i < nodes_.size(); i++) {
bool isRequired = false; bool isRequired = false;
if (states[i]) { if (states[i]) {
@ -394,7 +342,7 @@ BayesNet::constructGraph (BayesNet* bn,
states[i]->markedOnTop; states[i]->markedOnTop;
} }
if (isRequired) { if (isRequired) {
parents.push_back (VarIdSet()); parents.push_back (VarIds());
if (states[i]->markedOnTop) { if (states[i]->markedOnTop) {
const BnNodeSet& ps = nodes_[i]->getParents(); const BnNodeSet& ps = nodes_[i]->getParents();
for (unsigned j = 0; j < ps.size(); j++) { for (unsigned j = 0; j < ps.size(); j++) {
@ -473,7 +421,7 @@ BayesNet::printGraphicalModel (void) const
void void
BayesNet::exportToGraphViz (const char* fileName, BayesNet::exportToGraphViz (const char* fileName,
bool showNeighborless, bool showNeighborless,
const VarIdSet& highlightVarIds) const const VarIds& highlightVarIds) const
{ {
ofstream out (fileName); ofstream out (fileName);
if (!out.is_open()) { if (!out.is_open()) {
@ -556,7 +504,7 @@ BayesNet::exportToBifFormat (const char* fileName) const
out << "\t<GIVEN>" << parents[j]->label(); out << "\t<GIVEN>" << parents[j]->label();
out << "</GIVEN>" << endl; out << "</GIVEN>" << endl;
} }
ParamSet params = revertParameterReorder (nodes_[i]->getParameters(), Params params = revertParameterReorder (nodes_[i]->getParameters(),
nodes_[i]->nrStates()); nodes_[i]->nrStates());
out << "\t<TABLE>" ; out << "\t<TABLE>" ;
for (unsigned j = 0; j < params.size(); j++) { for (unsigned j = 0; j < params.size(); j++) {
@ -627,8 +575,8 @@ BayesNet::getAdjacentNodes (int v) const
ParamSet Params
BayesNet::reorderParameters (const ParamSet& params, unsigned dsize) const BayesNet::reorderParameters (const Params& params, unsigned dsize) const
{ {
// the interchange format for bayesian networks keeps the probabilities // the interchange format for bayesian networks keeps the probabilities
// in the following order: // in the following order:
@ -640,7 +588,7 @@ BayesNet::reorderParameters (const ParamSet& params, unsigned dsize) const
// p(a2|b2,c1) p(a2|b2,c2). // p(a2|b2,c1) p(a2|b2,c2).
unsigned count = 0; unsigned count = 0;
unsigned rowSize = params.size() / dsize; unsigned rowSize = params.size() / dsize;
ParamSet reordered; Params reordered;
while (reordered.size() < params.size()) { while (reordered.size() < params.size()) {
unsigned idx = count; unsigned idx = count;
for (unsigned i = 0; i < rowSize; i++) { for (unsigned i = 0; i < rowSize; i++) {
@ -654,12 +602,12 @@ BayesNet::reorderParameters (const ParamSet& params, unsigned dsize) const
ParamSet Params
BayesNet::revertParameterReorder (const ParamSet& params, unsigned dsize) const BayesNet::revertParameterReorder (const Params& params, unsigned dsize) const
{ {
unsigned count = 0; unsigned count = 0;
unsigned rowSize = params.size() / dsize; unsigned rowSize = params.size() / dsize;
ParamSet reordered; Params reordered;
while (reordered.size() < params.size()) { while (reordered.size() < params.size()) {
unsigned idx = count; unsigned idx = count;
for (unsigned i = 0; i < dsize; i++) { for (unsigned i = 0; i < dsize; i++) {

View File

@ -8,7 +8,7 @@
#include "GraphicalModel.h" #include "GraphicalModel.h"
#include "BayesNode.h" #include "BayesNode.h"
#include "Shared.h" #include "Horus.h"
using namespace std; using namespace std;
@ -53,11 +53,9 @@ class BayesNet : public GraphicalModel
~BayesNet (void); ~BayesNet (void);
void readFromBifFormat (const char*); void readFromBifFormat (const char*);
void addNode (BayesNode*);
BayesNode* addNode (string, const States&); BayesNode* addNode (string, const States&);
BayesNode* addNode (VarId, unsigned, int, BnNodeSet&, Distribution*); // BayesNode* addNode (VarId, unsigned, int, BnNodeSet&, Distribution*);
BayesNode* addNode (VarId, unsigned, int, Distribution*); BayesNode* addNode (VarId, unsigned, int, Distribution*);
BayesNode* addNode (string, States, BnNodeSet&, ParamSet&);
BayesNode* getBayesNode (VarId) const; BayesNode* getBayesNode (VarId) const;
BayesNode* getBayesNode (string) const; BayesNode* getBayesNode (string) const;
VarNode* getVariableNode (VarId) const; VarNode* getVariableNode (VarId) const;
@ -69,7 +67,7 @@ class BayesNet : public GraphicalModel
BnNodeSet getRootNodes (void) const; BnNodeSet getRootNodes (void) const;
BnNodeSet getLeafNodes (void) const; BnNodeSet getLeafNodes (void) const;
BayesNet* getMinimalRequesiteNetwork (VarId) const; BayesNet* getMinimalRequesiteNetwork (VarId) const;
BayesNet* getMinimalRequesiteNetwork (const VarIdSet&) const; BayesNet* getMinimalRequesiteNetwork (const VarIds&) const;
void constructGraph ( void constructGraph (
BayesNet*, const vector<StateInfo*>&) const; BayesNet*, const vector<StateInfo*>&) const;
bool isPolyTree (void) const; bool isPolyTree (void) const;
@ -78,7 +76,7 @@ class BayesNet : public GraphicalModel
void freeDistributions (void); void freeDistributions (void);
void printGraphicalModel (void) const; void printGraphicalModel (void) const;
void exportToGraphViz (const char*, bool = true, void exportToGraphViz (const char*, bool = true,
const VarIdSet& = VarIdSet()) const; const VarIds& = VarIds()) const;
void exportToBifFormat (const char*) const; void exportToBifFormat (const char*) const;
private: private:
@ -87,8 +85,8 @@ class BayesNet : public GraphicalModel
bool containsUndirectedCycle (void) const; bool containsUndirectedCycle (void) const;
bool containsUndirectedCycle (int, int, vector<bool>&)const; bool containsUndirectedCycle (int, int, vector<bool>&)const;
vector<int> getAdjacentNodes (int) const; vector<int> getAdjacentNodes (int) const;
ParamSet reorderParameters (const ParamSet&, unsigned) const; Params reorderParameters (const Params&, unsigned) const;
ParamSet revertParameterReorder (const ParamSet&, unsigned) const; Params revertParameterReorder (const Params&, unsigned) const;
void scheduleParents (const BayesNode*, Scheduling&) const; void scheduleParents (const BayesNode*, Scheduling&) const;
void scheduleChilds (const BayesNode*, Scheduling&) const; void scheduleChilds (const BayesNode*, Scheduling&) const;
@ -96,7 +94,7 @@ class BayesNet : public GraphicalModel
DistSet dists_; DistSet dists_;
typedef unordered_map<unsigned, unsigned> IndexMap; typedef unordered_map<unsigned, unsigned> IndexMap;
IndexMap indexMap_; IndexMap varMap_;
}; };

View File

@ -71,7 +71,7 @@ BayesNode::getDistribution (void)
const ParamSet& const Params&
BayesNode::getParameters (void) BayesNode::getParameters (void)
{ {
return dist_->params; return dist_->params;
@ -79,12 +79,12 @@ BayesNode::getParameters (void)
ParamSet Params
BayesNode::getRow (int rowIndex) const BayesNode::getRow (int rowIndex) const
{ {
int rowSize = getRowSize(); int rowSize = getRowSize();
int offset = rowSize * rowIndex; int offset = rowSize * rowIndex;
ParamSet row (rowSize); Params row (rowSize);
for (int i = 0; i < rowSize; i++) { for (int i = 0; i < rowSize; i++) {
row[i] = dist_->params[offset + i] ; row[i] = dist_->params[offset + i] ;
} }
@ -124,41 +124,6 @@ BayesNode::getCptSize (void)
const vector<CptEntry>&
BayesNode::getCptEntries (void)
{
if (dist_->entries.size() == 0) {
unsigned rowSize = getRowSize();
vector<DConf> confs (rowSize);
for (unsigned i = 0; i < rowSize; i++) {
confs[i].resize (parents_.size());
}
unsigned nReps = 1;
for (int i = parents_.size() - 1; i >= 0; i--) {
unsigned index = 0;
while (index < rowSize) {
for (unsigned j = 0; j < parents_[i]->nrStates(); j++) {
for (unsigned r = 0; r < nReps; r++) {
confs[index][i] = j;
index++;
}
}
}
nReps *= parents_[i]->nrStates();
}
dist_->entries.reserve (rowSize);
for (unsigned i = 0; i < rowSize; i++) {
dist_->entries.push_back (CptEntry (i, confs[i]));
}
}
return dist_->entries;
}
int int
BayesNode::getIndexOfParent (const BayesNode* parent) const BayesNode::getIndexOfParent (const BayesNode* parent) const
{ {
@ -173,42 +138,20 @@ BayesNode::getIndexOfParent (const BayesNode* parent) const
string string
BayesNode::cptEntryToString (const CptEntry& entry) const BayesNode::cptEntryToString (
int row,
const vector<unsigned>& stateConf) const
{ {
stringstream ss; stringstream ss;
ss << "p(" ; ss << "p(" ;
const DConf& conf = entry.getDomainConfiguration();
int row = entry.getParameterIndex() / getRowSize();
ss << states()[row]; ss << states()[row];
if (parents_.size() > 0) { if (parents_.size() > 0) {
ss << "|" ; ss << "|" ;
for (unsigned int i = 0; i < conf.size(); i++) { for (unsigned int i = 0; i < stateConf.size(); i++) {
if (i != 0) { if (i != 0) {
ss << ","; ss << ",";
} }
ss << parents_[i]->states()[conf[i]]; ss << parents_[i]->states()[stateConf[i]];
}
}
ss << ")" ;
return ss.str();
}
string
BayesNode::cptEntryToString (int row, const CptEntry& entry) const
{
stringstream ss;
ss << "p(" ;
const DConf& conf = entry.getDomainConfiguration();
ss << states()[row];
if (parents_.size() > 0) {
ss << "|" ;
for (unsigned int i = 0; i < conf.size(); i++) {
if (i != 0) {
ss << ",";
}
ss << parents_[i]->states()[conf[i]];
} }
} }
ss << ")" ; ss << ")" ;
@ -334,7 +277,7 @@ operator << (ostream& o, const BayesNode& node)
o << endl; o << endl;
for (unsigned int i = 0; i < states.size(); i++) { for (unsigned int i = 0; i < states.size(); i++) {
ParamSet row = node.getRow (i); Params row = node.getRow (i);
o << left << setw (domainWidth) << states[i] << right; o << left << setw (domainWidth) << states[i] << right;
for (unsigned j = 0; j < node.getRowSize(); j++) { for (unsigned j = 0; j < node.getRowSize(); j++) {
o << setw (widths[j]) << row[j]; o << setw (widths[j]) << row[j];

View File

@ -4,9 +4,8 @@
#include <vector> #include <vector>
#include "VarNode.h" #include "VarNode.h"
#include "CptEntry.h"
#include "Distribution.h" #include "Distribution.h"
#include "Shared.h" #include "Horus.h"
using namespace std; using namespace std;
@ -22,17 +21,14 @@ class BayesNode : public VarNode
void addChild (BayesNode*); void addChild (BayesNode*);
void setDistribution (Distribution*); void setDistribution (Distribution*);
Distribution* getDistribution (void); Distribution* getDistribution (void);
const ParamSet& getParameters (void); const Params& getParameters (void);
ParamSet getRow (int) const; Params getRow (int) const;
void setProbability (int, const CptEntry&, double);
bool isRoot (void); bool isRoot (void);
bool isLeaf (void); bool isLeaf (void);
bool hasNeighbors (void) const; bool hasNeighbors (void) const;
int getCptSize (void); int getCptSize (void);
const vector<CptEntry>& getCptEntries (void);
int getIndexOfParent (const BayesNode*) const; int getIndexOfParent (const BayesNode*) const;
string cptEntryToString (const CptEntry&) const; string cptEntryToString (int, const vector<unsigned>&) const;
string cptEntryToString (int, const CptEntry&) const;
const BnNodeSet& getParents (void) const { return parents_; } const BnNodeSet& getParents (void) const { return parents_; }
const BnNodeSet& getChilds (void) const { return childs_; } const BnNodeSet& getChilds (void) const { return childs_; }
@ -42,9 +38,8 @@ class BayesNode : public VarNode
return dist_->params.size() / nrStates(); return dist_->params.size() / nrStates();
} }
double getProbability (int row, const CptEntry& entry) double getProbability (int row, unsigned col)
{ {
int col = entry.getParameterIndex();
int idx = (row * getRowSize()) + col; int idx = (row * getRowSize()) + col;
return dist_->params[idx]; return dist_->params[idx];
} }

View File

@ -9,12 +9,11 @@
#include <iomanip> #include <iomanip>
#include "BnBpSolver.h" #include "BnBpSolver.h"
#include "Indexer.h"
BnBpSolver::BnBpSolver (const BayesNet& bn) : Solver (&bn) BnBpSolver::BnBpSolver (const BayesNet& bn) : Solver (&bn)
{ {
bayesNet_ = &bn; bayesNet_ = &bn;
jointCalcType_ = CHAIN_RULE;
//jointCalcType_ = JUNCTION_NODE;
} }
@ -39,21 +38,18 @@ BnBpSolver::runSolver (void)
start = clock(); start = clock();
} }
initializeSolver(); initializeSolver();
if (!BpOptions::useAlwaysLoopySolver && bayesNet_->isPolyTree()) { runLoopySolver();
runPolyTreeSolver(); if (DL >= 2) {
} else { cout << endl;
runLoopySolver(); if (nIters_ < BpOptions::maxIter) {
if (DL >= 2) { cout << "Belief propagation converged in " ;
cout << nIters_ << " iterations" << endl;
} else {
cout << "The maximum number of iterations was hit, terminating..." ;
cout << endl; cout << endl;
if (nIters_ < BpOptions::maxIter) {
cout << "Belief propagation converged in " ;
cout << nIters_ << " iterations" << endl;
} else {
cout << "The maximum number of iterations was hit, terminating..." ;
cout << endl;
}
} }
} }
unsigned size = bayesNet_->nrNodes(); unsigned size = bayesNet_->nrNodes();
if (COLLECT_STATISTICS) { if (COLLECT_STATISTICS) {
unsigned nIters = 0; unsigned nIters = 0;
@ -71,7 +67,7 @@ BnBpSolver::runSolver (void)
ParamSet Params
BnBpSolver::getPosterioriOf (VarId vid) BnBpSolver::getPosterioriOf (VarId vid)
{ {
BayesNode* node = bayesNet_->getBayesNode (vid); BayesNode* node = bayesNet_->getBayesNode (vid);
@ -81,8 +77,8 @@ BnBpSolver::getPosterioriOf (VarId vid)
ParamSet Params
BnBpSolver::getJointDistributionOf (const VarIdSet& jointVarIds) BnBpSolver::getJointDistributionOf (const VarIds& jointVarIds)
{ {
if (DL >= 2) { if (DL >= 2) {
cout << "calculating joint distribution on: " ; cout << "calculating joint distribution on: " ;
@ -92,12 +88,7 @@ BnBpSolver::getJointDistributionOf (const VarIdSet& jointVarIds)
} }
cout << endl; cout << endl;
} }
return getJointByConditioning (jointVarIds);
if (jointCalcType_ == JUNCTION_NODE) {
return getJointByJunctionNode (jointVarIds);
} else {
return getJointByChainRule (jointVarIds);
}
} }
@ -121,8 +112,8 @@ BnBpSolver::initializeSolver (void)
BnNodeSet roots = bayesNet_->getRootNodes(); BnNodeSet roots = bayesNet_->getRootNodes();
for (unsigned i = 0; i < roots.size(); i++) { for (unsigned i = 0; i < roots.size(); i++) {
const ParamSet& params = roots[i]->getParameters(); const Params& params = roots[i]->getParameters();
ParamSet& piVals = ninf(roots[i])->getPiValues(); Params& piVals = ninf(roots[i])->getPiValues();
for (unsigned ri = 0; ri < roots[i]->nrStates(); ri++) { for (unsigned ri = 0; ri < roots[i]->nrStates(); ri++) {
piVals[ri] = params[ri]; piVals[ri] = params[ri];
} }
@ -149,8 +140,8 @@ BnBpSolver::initializeSolver (void)
for (unsigned i = 0; i < nodes.size(); i++) { for (unsigned i = 0; i < nodes.size(); i++) {
if (nodes[i]->hasEvidence()) { if (nodes[i]->hasEvidence()) {
ParamSet& piVals = ninf(nodes[i])->getPiValues(); Params& piVals = ninf(nodes[i])->getPiValues();
ParamSet& ldVals = ninf(nodes[i])->getLambdaValues(); Params& ldVals = ninf(nodes[i])->getLambdaValues();
for (unsigned xi = 0; xi < nodes[i]->nrStates(); xi++) { for (unsigned xi = 0; xi < nodes[i]->nrStates(); xi++) {
piVals[xi] = Util::noEvidence(); piVals[xi] = Util::noEvidence();
ldVals[xi] = Util::noEvidence(); ldVals[xi] = Util::noEvidence();
@ -163,76 +154,6 @@ BnBpSolver::initializeSolver (void)
void
BnBpSolver::runPolyTreeSolver (void)
{
const BnNodeSet& nodes = bayesNet_->getBayesNodes();
for (unsigned i = 0; i < nodes.size(); i++) {
if (nodes[i]->isRoot()) {
ninf(nodes[i])->markPiValuesAsCalculated();
}
if (nodes[i]->isLeaf()) {
ninf(nodes[i])->markLambdaValuesAsCalculated();
}
}
bool finish = false;
while (!finish) {
finish = true;
for (unsigned i = 0; i < nodes.size(); i++) {
if (ninf(nodes[i])->piValuesCalculated() == false
&& ninf(nodes[i])->receivedAllPiMessages()) {
if (!nodes[i]->hasEvidence()) {
updatePiValues (nodes[i]);
}
ninf(nodes[i])->markPiValuesAsCalculated();
finish = false;
}
if (ninf(nodes[i])->lambdaValuesCalculated() == false
&& ninf(nodes[i])->receivedAllLambdaMessages()) {
if (!nodes[i]->hasEvidence()) {
updateLambdaValues (nodes[i]);
}
ninf(nodes[i])->markLambdaValuesAsCalculated();
finish = false;
}
if (ninf(nodes[i])->piValuesCalculated()) {
const BpLinkSet& outChildLinks
= ninf(nodes[i])->getOutcomingChildLinks();
for (unsigned j = 0; j < outChildLinks.size(); j++) {
BayesNode* child = outChildLinks[j]->getDestination();
if (!outChildLinks[j]->messageWasSended()) {
if (ninf(nodes[i])->readyToSendPiMsgTo (child)) {
calculateAndUpdateMessage (outChildLinks[j], false);
ninf(child)->incNumPiMsgsReceived();
}
finish = false;
}
}
}
if (ninf(nodes[i])->lambdaValuesCalculated()) {
const BpLinkSet& outParentLinks =
ninf(nodes[i])->getOutcomingParentLinks();
for (unsigned j = 0; j < outParentLinks.size(); j++) {
BayesNode* parent = outParentLinks[j]->getDestination();
if (!outParentLinks[j]->messageWasSended()) {
if (ninf(nodes[i])->readyToSendLambdaMsgTo (parent)) {
calculateAndUpdateMessage (outParentLinks[j], false);
ninf(parent)->incNumLambdaMsgsReceived();
}
finish = false;
}
}
}
}
}
}
void void
BnBpSolver::runLoopySolver() BnBpSolver::runLoopySolver()
{ {
@ -298,7 +219,7 @@ BnBpSolver::converged (void) const
} }
bool converged = true; bool converged = true;
if (BpOptions::schedule == BpOptions::Schedule::MAX_RESIDUAL) { if (BpOptions::schedule == BpOptions::Schedule::MAX_RESIDUAL) {
Param maxResidual = (*(sortedOrder_.begin()))->getResidual(); double maxResidual = (*(sortedOrder_.begin()))->getResidual();
if (maxResidual < BpOptions::accuracy) { if (maxResidual < BpOptions::accuracy) {
converged = true; converged = true;
} else { } else {
@ -306,7 +227,7 @@ BnBpSolver::converged (void) const
} }
} else { } else {
for (unsigned i = 0; i < links_.size(); i++) { for (unsigned i = 0; i < links_.size(); i++) {
Param residual = links_[i]->getResidual(); double residual = links_[i]->getResidual();
if (DL >= 2) { if (DL >= 2) {
cout << links_[i]->toString() + " residual change = " ; cout << links_[i]->toString() + " residual change = " ;
cout << residual << endl; cout << residual << endl;
@ -395,36 +316,38 @@ BnBpSolver::updatePiValues (BayesNode* x)
if (DL >= 3) { if (DL >= 3) {
cout << "updating " << PI_SYMBOL << " values for " << x->label() << endl; cout << "updating " << PI_SYMBOL << " values for " << x->label() << endl;
} }
ParamSet& piValues = ninf(x)->getPiValues(); Params& piValues = ninf(x)->getPiValues();
const BpLinkSet& parentLinks = ninf(x)->getIncomingParentLinks(); const BpLinkSet& parentLinks = ninf(x)->getIncomingParentLinks();
const vector<CptEntry>& entries = x->getCptEntries(); const BnNodeSet& ps = x->getParents();
Ranges ranges;
for (unsigned i = 0; i < ps.size(); i++) {
ranges.push_back (ps[i]->nrStates());
}
StatesIndexer indexer (ranges, false);
stringstream* calcs1 = 0; stringstream* calcs1 = 0;
stringstream* calcs2 = 0; stringstream* calcs2 = 0;
ParamSet messageProducts (entries.size()); Params messageProducts (indexer.size());
for (unsigned k = 0; k < entries.size(); k++) { for (unsigned k = 0; k < indexer.size(); k++) {
if (DL >= 5) { if (DL >= 5) {
calcs1 = new stringstream; calcs1 = new stringstream;
calcs2 = new stringstream; calcs2 = new stringstream;
} }
double messageProduct = Util::multIdenty(); double messageProduct = Util::multIdenty();
const DConf& conf = entries[k].getDomainConfiguration(); if (Globals::logDomain) {
switch (NSPACE) { for (unsigned i = 0; i < parentLinks.size(); i++) {
case NumberSpace::NORMAL: messageProduct += parentLinks[i]->getMessage()[indexer[i]];
for (unsigned i = 0; i < parentLinks.size(); i++) { }
messageProduct *= parentLinks[i]->getMessage()[conf[i]]; } else {
if (DL >= 5) { for (unsigned i = 0; i < parentLinks.size(); i++) {
if (i != 0) *calcs1 << " + " ; messageProduct *= parentLinks[i]->getMessage()[indexer[i]];
if (i != 0) *calcs2 << " + " ; if (DL >= 5) {
*calcs1 << parentLinks[i]->toString (conf[i]); if (i != 0) *calcs1 << " + " ;
*calcs2 << parentLinks[i]->getMessage()[conf[i]]; if (i != 0) *calcs2 << " + " ;
} *calcs1 << parentLinks[i]->toString (indexer[i]);
} *calcs2 << parentLinks[i]->getMessage()[indexer[i]];
break;
case NumberSpace::LOGARITHM:
for (unsigned i = 0; i < parentLinks.size(); i++) {
messageProduct += parentLinks[i]->getMessage()[conf[i]];
} }
}
} }
messageProducts[k] = messageProduct; messageProducts[k] = messageProduct;
if (DL >= 5) { if (DL >= 5) {
@ -439,6 +362,7 @@ BnBpSolver::updatePiValues (BayesNode* x)
delete calcs1; delete calcs1;
delete calcs2; delete calcs2;
} }
++ indexer;
} }
for (unsigned xi = 0; xi < x->nrStates(); xi++) { for (unsigned xi = 0; xi < x->nrStates(); xi++) {
@ -447,26 +371,28 @@ BnBpSolver::updatePiValues (BayesNode* x)
calcs1 = new stringstream; calcs1 = new stringstream;
calcs2 = new stringstream; calcs2 = new stringstream;
} }
switch (NSPACE) { indexer.reset();
case NumberSpace::NORMAL: if (Globals::logDomain) {
for (unsigned k = 0; k < entries.size(); k++) { for (unsigned k = 0; k < indexer.size(); k++) {
sum += x->getProbability (xi, entries[k]) * messageProducts[k]; Util::logSum (sum,
if (DL >= 5) { x->getProbability(xi, indexer.linearIndex()) + messageProducts[k]);
if (k != 0) *calcs1 << " + " ; ++ indexer;
if (k != 0) *calcs2 << " + " ; }
*calcs1 << x->cptEntryToString (xi, entries[k]); } else {
*calcs1 << ".mp" << k; for (unsigned k = 0; k < indexer.size(); k++) {
*calcs2 << Util::fl (x->getProbability (xi, entries[k])); sum += x->getProbability (xi, indexer.linearIndex()) * messageProducts[k];
*calcs2 << "*" << messageProducts[k]; if (DL >= 5) {
} if (k != 0) *calcs1 << " + " ;
} if (k != 0) *calcs2 << " + " ;
break; *calcs1 << x->cptEntryToString (xi, indexer.indices());
case NumberSpace::LOGARITHM: *calcs1 << ".mp" << k;
for (unsigned k = 0; k < entries.size(); k++) { *calcs2 << Util::fl (x->getProbability (xi, indexer.linearIndex()));
Util::logSum (sum, *calcs2 << "*" << messageProducts[k];
x->getProbability(xi,entries[k]) + messageProducts[k]);
} }
++ indexer;
}
} }
piValues[xi] = sum; piValues[xi] = sum;
if (DL >= 5) { if (DL >= 5) {
cout << " " << PI_SYMBOL << "(" << x->label() << ")" ; cout << " " << PI_SYMBOL << "(" << x->label() << ")" ;
@ -489,7 +415,7 @@ BnBpSolver::updateLambdaValues (BayesNode* x)
if (DL >= 3) { if (DL >= 3) {
cout << "updating " << LD_SYMBOL << " values for " << x->label() << endl; cout << "updating " << LD_SYMBOL << " values for " << x->label() << endl;
} }
ParamSet& lambdaValues = ninf(x)->getLambdaValues(); Params& lambdaValues = ninf(x)->getLambdaValues();
const BpLinkSet& childLinks = ninf(x)->getIncomingChildLinks(); const BpLinkSet& childLinks = ninf(x)->getIncomingChildLinks();
stringstream* calcs1 = 0; stringstream* calcs1 = 0;
stringstream* calcs2 = 0; stringstream* calcs2 = 0;
@ -500,22 +426,20 @@ BnBpSolver::updateLambdaValues (BayesNode* x)
calcs2 = new stringstream; calcs2 = new stringstream;
} }
double product = Util::multIdenty(); double product = Util::multIdenty();
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: for (unsigned i = 0; i < childLinks.size(); i++) {
for (unsigned i = 0; i < childLinks.size(); i++) { product += childLinks[i]->getMessage()[xi];
product *= childLinks[i]->getMessage()[xi]; }
if (DL >= 5) { } else {
if (i != 0) *calcs1 << "." ; for (unsigned i = 0; i < childLinks.size(); i++) {
if (i != 0) *calcs2 << "*" ; product *= childLinks[i]->getMessage()[xi];
*calcs1 << childLinks[i]->toString (xi); if (DL >= 5) {
*calcs2 << childLinks[i]->getMessage()[xi]; if (i != 0) *calcs1 << "." ;
} if (i != 0) *calcs2 << "*" ;
} *calcs1 << childLinks[i]->toString (xi);
break; *calcs2 << childLinks[i]->getMessage()[xi];
case NumberSpace::LOGARITHM:
for (unsigned i = 0; i < childLinks.size(); i++) {
product += childLinks[i]->getMessage()[xi];
} }
}
} }
lambdaValues[xi] = product; lambdaValues[xi] = product;
if (DL >= 5) { if (DL >= 5) {
@ -542,12 +466,12 @@ BnBpSolver::calculatePiMessage (BpLink* link)
// πX(Zi) // πX(Zi)
BayesNode* z = link->getSource(); BayesNode* z = link->getSource();
BayesNode* x = link->getDestination(); BayesNode* x = link->getDestination();
ParamSet& zxPiNextMessage = link->getNextMessage(); Params& zxPiNextMessage = link->getNextMessage();
const BpLinkSet& zChildLinks = ninf(z)->getIncomingChildLinks(); const BpLinkSet& zChildLinks = ninf(z)->getIncomingChildLinks();
stringstream* calcs1 = 0; stringstream* calcs1 = 0;
stringstream* calcs2 = 0; stringstream* calcs2 = 0;
const ParamSet& zPiValues = ninf(z)->getPiValues(); const Params& zPiValues = ninf(z)->getPiValues();
for (unsigned zi = 0; zi < z->nrStates(); zi++) { for (unsigned zi = 0; zi < z->nrStates(); zi++) {
double product = zPiValues[zi]; double product = zPiValues[zi];
if (DL >= 5) { if (DL >= 5) {
@ -557,24 +481,22 @@ BnBpSolver::calculatePiMessage (BpLink* link)
*calcs1 << "[" << z->states()[zi] << "]" ; *calcs1 << "[" << z->states()[zi] << "]" ;
*calcs2 << product; *calcs2 << product;
} }
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: for (unsigned i = 0; i < zChildLinks.size(); i++) {
for (unsigned i = 0; i < zChildLinks.size(); i++) { if (zChildLinks[i]->getSource() != x) {
if (zChildLinks[i]->getSource() != x) { product += zChildLinks[i]->getMessage()[zi];
product *= zChildLinks[i]->getMessage()[zi]; }
if (DL >= 5) { }
*calcs1 << "." << zChildLinks[i]->toString (zi); } else {
*calcs2 << " * " << zChildLinks[i]->getMessage()[zi]; for (unsigned i = 0; i < zChildLinks.size(); i++) {
} if (zChildLinks[i]->getSource() != x) {
} product *= zChildLinks[i]->getMessage()[zi];
} if (DL >= 5) {
break; *calcs1 << "." << zChildLinks[i]->toString (zi);
case NumberSpace::LOGARITHM: *calcs2 << " * " << zChildLinks[i]->getMessage()[zi];
for (unsigned i = 0; i < zChildLinks.size(); i++) {
if (zChildLinks[i]->getSource() != x) {
product += zChildLinks[i]->getMessage()[zi];
} }
} }
}
} }
zxPiNextMessage[zi] = product; zxPiNextMessage[zi] = product;
if (DL >= 5) { if (DL >= 5) {
@ -605,52 +527,53 @@ BnBpSolver::calculateLambdaMessage (BpLink* link)
if (x->hasEvidence()) { if (x->hasEvidence()) {
return; return;
} }
ParamSet& yxLambdaNextMessage = link->getNextMessage(); Params& yxLambdaNextMessage = link->getNextMessage();
const BpLinkSet& yParentLinks = ninf(y)->getIncomingParentLinks(); const BpLinkSet& yParentLinks = ninf(y)->getIncomingParentLinks();
const ParamSet& yLambdaValues = ninf(y)->getLambdaValues(); const Params& yLambdaValues = ninf(y)->getLambdaValues();
const vector<CptEntry>& allEntries = y->getCptEntries();
int parentIndex = y->getIndexOfParent (x); int parentIndex = y->getIndexOfParent (x);
stringstream* calcs1 = 0; stringstream* calcs1 = 0;
stringstream* calcs2 = 0; stringstream* calcs2 = 0;
vector<CptEntry> entries;
DConstraint constr = make_pair (parentIndex, 0);
for (unsigned i = 0; i < allEntries.size(); i++) {
if (allEntries[i].matchConstraints(constr)) {
entries.push_back (allEntries[i]);
}
}
ParamSet messageProducts (entries.size()); const BnNodeSet& ps = y->getParents();
for (unsigned k = 0; k < entries.size(); k++) { Ranges ranges;
for (unsigned i = 0; i < ps.size(); i++) {
ranges.push_back (ps[i]->nrStates());
}
StatesIndexer indexer (ranges, false);
unsigned N = indexer.size() / x->nrStates();
Params messageProducts (N);
for (unsigned k = 0; k < N; k++) {
while (indexer[parentIndex] != 0) {
++ indexer;
}
if (DL >= 5) { if (DL >= 5) {
calcs1 = new stringstream; calcs1 = new stringstream;
calcs2 = new stringstream; calcs2 = new stringstream;
} }
double messageProduct = Util::multIdenty(); double messageProduct = Util::multIdenty();
const DConf& conf = entries[k].getDomainConfiguration(); if (Globals::logDomain) {
switch (NSPACE) { for (unsigned i = 0; i < yParentLinks.size(); i++) {
case NumberSpace::NORMAL: if (yParentLinks[i]->getSource() != x) {
for (unsigned i = 0; i < yParentLinks.size(); i++) { messageProduct += yParentLinks[i]->getMessage()[indexer[i]];
if (yParentLinks[i]->getSource() != x) {
if (DL >= 5) {
if (messageProduct != Util::multIdenty()) *calcs1 << "*" ;
if (messageProduct != Util::multIdenty()) *calcs2 << "*" ;
*calcs1 << yParentLinks[i]->toString (conf[i]);
*calcs2 << yParentLinks[i]->getMessage()[conf[i]];
}
messageProduct *= yParentLinks[i]->getMessage()[conf[i]];
}
} }
break; }
case NumberSpace::LOGARITHM: } else {
for (unsigned i = 0; i < yParentLinks.size(); i++) { for (unsigned i = 0; i < yParentLinks.size(); i++) {
if (yParentLinks[i]->getSource() != x) { if (yParentLinks[i]->getSource() != x) {
messageProduct += yParentLinks[i]->getMessage()[conf[i]]; if (DL >= 5) {
} if (messageProduct != Util::multIdenty()) *calcs1 << "*" ;
} if (messageProduct != Util::multIdenty()) *calcs2 << "*" ;
*calcs1 << yParentLinks[i]->toString (indexer[i]);
*calcs2 << yParentLinks[i]->getMessage()[indexer[i]];
}
messageProduct *= yParentLinks[i]->getMessage()[indexer[i]];
}
}
} }
messageProducts[k] = messageProduct; messageProducts[k] = messageProduct;
++ indexer;
if (DL >= 5) { if (DL >= 5) {
cout << " mp" << k; cout << " mp" << k;
cout << " = " << (*calcs1).str(); cout << " = " << (*calcs1).str();
@ -672,13 +595,6 @@ BnBpSolver::calculateLambdaMessage (BpLink* link)
calcs1 = new stringstream; calcs1 = new stringstream;
calcs2 = new stringstream; calcs2 = new stringstream;
} }
vector<CptEntry> entries;
DConstraint constr = make_pair (parentIndex, xi);
for (unsigned i = 0; i < allEntries.size(); i++) {
if (allEntries[i].matchConstraints(constr)) {
entries.push_back (allEntries[i]);
}
}
double outerSum = Util::addIdenty(); double outerSum = Util::addIdenty();
for (unsigned yi = 0; yi < y->nrStates(); yi++) { for (unsigned yi = 0; yi < y->nrStates(); yi++) {
if (DL >= 5) { if (DL >= 5) {
@ -686,27 +602,35 @@ BnBpSolver::calculateLambdaMessage (BpLink* link)
(yi != 0) ? *calcs2 << " + {" : *calcs2 << "{" ; (yi != 0) ? *calcs2 << " + {" : *calcs2 << "{" ;
} }
double innerSum = Util::addIdenty(); double innerSum = Util::addIdenty();
switch (NSPACE) { indexer.reset();
case NumberSpace::NORMAL: if (Globals::logDomain) {
for (unsigned k = 0; k < entries.size(); k++) { for (unsigned k = 0; k < N; k++) {
if (DL >= 5) { while (indexer[parentIndex] != xi) {
if (k != 0) *calcs1 << " + " ; ++ indexer;
if (k != 0) *calcs2 << " + " ;
*calcs1 << y->cptEntryToString (yi, entries[k]);
*calcs1 << ".mp" << k;
*calcs2 << y->getProbability (yi, entries[k]);
*calcs2 << "*" << messageProducts[k];
}
innerSum += y->getProbability (yi, entries[k]) * messageProducts[k];
} }
outerSum += innerSum * yLambdaValues[yi]; Util::logSum (innerSum, y->getProbability (
break; yi, indexer.linearIndex()) + messageProducts[k]);
case NumberSpace::LOGARITHM: ++ indexer;
for (unsigned k = 0; k < entries.size(); k++) { }
Util::logSum (innerSum, Util::logSum (outerSum, innerSum + yLambdaValues[yi]);
y->getProbability(yi, entries[k]) + messageProducts[k]); } else {
} for (unsigned k = 0; k < N; k++) {
Util::logSum (outerSum, innerSum + yLambdaValues[yi]); while (indexer[parentIndex] != xi) {
++ indexer;
}
if (DL >= 5) {
if (k != 0) *calcs1 << " + " ;
if (k != 0) *calcs2 << " + " ;
*calcs1 << y->cptEntryToString (yi, indexer.indices());
*calcs1 << ".mp" << k;
*calcs2 << y->getProbability (yi, indexer.linearIndex());
*calcs2 << "*" << messageProducts[k];
}
innerSum += y->getProbability (
yi, indexer.linearIndex()) * messageProducts[k];
++ indexer;
}
outerSum += innerSum * yLambdaValues[yi];
} }
if (DL >= 5) { if (DL >= 5) {
*calcs1 << "}." << LD_SYMBOL << "(" << y->label() << ")" ; *calcs1 << "}." << LD_SYMBOL << "(" << y->label() << ")" ;
@ -730,62 +654,45 @@ BnBpSolver::calculateLambdaMessage (BpLink* link)
ParamSet Params
BnBpSolver::getJointByJunctionNode (const VarIdSet& jointVarIds) BnBpSolver::getJointByConditioning (const VarIds& jointVarIds) const
{
unsigned msgSize = 1;
vector<unsigned> dsizes (jointVarIds.size());
for (unsigned i = 0; i < jointVarIds.size(); i++) {
dsizes[i] = bayesNet_->getBayesNode (jointVarIds[i])->nrStates();
msgSize *= dsizes[i];
}
unsigned reps = 1;
ParamSet jointDist (msgSize, Util::multIdenty());
for (int i = jointVarIds.size() - 1 ; i >= 0; i--) {
Util::multiply (jointDist, getPosterioriOf (jointVarIds[i]), reps);
reps *= dsizes[i] ;
}
return jointDist;
}
ParamSet
BnBpSolver::getJointByChainRule (const VarIdSet& jointVarIds) const
{ {
BnNodeSet jointVars; BnNodeSet jointVars;
for (unsigned i = 0; i < jointVarIds.size(); i++) { for (unsigned i = 0; i < jointVarIds.size(); i++) {
assert (bayesNet_->getBayesNode (jointVarIds[i]));
jointVars.push_back (bayesNet_->getBayesNode (jointVarIds[i])); jointVars.push_back (bayesNet_->getBayesNode (jointVarIds[i]));
} }
BayesNet* mrn = bayesNet_->getMinimalRequesiteNetwork (jointVarIds[0]); BayesNet* mrn = bayesNet_->getMinimalRequesiteNetwork (jointVarIds[0]);
BnBpSolver solver (*mrn); BnBpSolver solver (*mrn);
solver.runSolver(); solver.runSolver();
ParamSet prevBeliefs = solver.getPosterioriOf (jointVarIds[0]); Params prevBeliefs = solver.getPosterioriOf (jointVarIds[0]);
delete mrn; delete mrn;
VarNodes observedVars = {jointVars[0]}; VarIds observedVids = {jointVars[0]->varId()};
for (unsigned i = 1; i < jointVarIds.size(); i++) { for (unsigned i = 1; i < jointVarIds.size(); i++) {
mrn = bayesNet_->getMinimalRequesiteNetwork (jointVarIds[i]); assert (jointVars[i]->hasEvidence() == false);
ParamSet newBeliefs; VarIds reqVars = {jointVarIds[i]};
vector<DConf> confs = reqVars.insert (reqVars.end(), observedVids.begin(), observedVids.end());
Util::getDomainConfigurations (observedVars); mrn = bayesNet_->getMinimalRequesiteNetwork (reqVars);
for (unsigned j = 0; j < confs.size(); j++) { Params newBeliefs;
for (unsigned k = 0; k < observedVars.size(); k++) { VarNodes observedVars;
if (!observedVars[k]->hasEvidence()) { for (unsigned j = 0; j < observedVids.size(); j++) {
BayesNode* node = mrn->getBayesNode (observedVars[k]->varId()); observedVars.push_back (mrn->getBayesNode (observedVids[j]));
if (node) { }
node->setEvidence (confs[j][k]); StatesIndexer idx (observedVars, false);
} while (idx.valid()) {
} for (unsigned j = 0; j < observedVars.size(); j++) {
observedVars[j]->setEvidence (idx[j]);
} }
BnBpSolver solver (*mrn); BnBpSolver solver (*mrn);
solver.runSolver(); solver.runSolver();
ParamSet beliefs = solver.getPosterioriOf (jointVarIds[i]); Params beliefs = solver.getPosterioriOf (jointVarIds[i]);
for (unsigned k = 0; k < beliefs.size(); k++) { for (unsigned k = 0; k < beliefs.size(); k++) {
newBeliefs.push_back (beliefs[k]); newBeliefs.push_back (beliefs[k]);
} }
++ idx;
} }
int count = -1; int count = -1;
@ -796,7 +703,7 @@ BnBpSolver::getJointByChainRule (const VarIdSet& jointVarIds) const
newBeliefs[j] *= prevBeliefs[count]; newBeliefs[j] *= prevBeliefs[count];
} }
prevBeliefs = newBeliefs; prevBeliefs = newBeliefs;
observedVars.push_back (jointVars[i]); observedVids.push_back (jointVars[i]->varId());
delete mrn; delete mrn;
} }
return prevBeliefs; return prevBeliefs;
@ -817,9 +724,9 @@ BnBpSolver::printPiLambdaValues (const BayesNode* var) const
cout << "--------------------------------" ; cout << "--------------------------------" ;
cout << endl; cout << endl;
const States& states = var->states(); const States& states = var->states();
const ParamSet& piVals = ninf(var)->getPiValues(); const Params& piVals = ninf(var)->getPiValues();
const ParamSet& ldVals = ninf(var)->getLambdaValues(); const Params& ldVals = ninf(var)->getLambdaValues();
const ParamSet& beliefs = ninf(var)->getBeliefs(); const Params& beliefs = ninf(var)->getBeliefs();
for (unsigned xi = 0; xi < var->nrStates(); xi++) { for (unsigned xi = 0; xi < var->nrStates(); xi++) {
cout << setw (10) << states[xi]; cout << setw (10) << states[xi];
cout << setw (19) << piVals[xi]; cout << setw (19) << piVals[xi];
@ -847,33 +754,27 @@ BnBpSolver::printAllMessageStatus (void) const
BpNodeInfo::BpNodeInfo (BayesNode* node) BpNodeInfo::BpNodeInfo (BayesNode* node)
{ {
node_ = node; node_ = node;
piValsCalc_ = false;
ldValsCalc_ = false;
nPiMsgsRcv_ = 0;
nLdMsgsRcv_ = 0;
piVals_.resize (node->nrStates(), Util::one()); piVals_.resize (node->nrStates(), Util::one());
ldVals_.resize (node->nrStates(), Util::one()); ldVals_.resize (node->nrStates(), Util::one());
} }
ParamSet Params
BpNodeInfo::getBeliefs (void) const BpNodeInfo::getBeliefs (void) const
{ {
double sum = 0.0; double sum = 0.0;
ParamSet beliefs (node_->nrStates()); Params beliefs (node_->nrStates());
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: for (unsigned xi = 0; xi < node_->nrStates(); xi++) {
for (unsigned xi = 0; xi < node_->nrStates(); xi++) { beliefs[xi] = exp (piVals_[xi] + ldVals_[xi]);
beliefs[xi] = piVals_[xi] * ldVals_[xi]; sum += beliefs[xi];
sum += beliefs[xi]; }
} } else {
break; for (unsigned xi = 0; xi < node_->nrStates(); xi++) {
case NumberSpace::LOGARITHM: beliefs[xi] = piVals_[xi] * ldVals_[xi];
for (unsigned xi = 0; xi < node_->nrStates(); xi++) { sum += beliefs[xi];
beliefs[xi] = exp (piVals_[xi] + ldVals_[xi]); }
sum += beliefs[xi];
}
} }
assert (sum); assert (sum);
for (unsigned xi = 0; xi < node_->nrStates(); xi++) { for (unsigned xi = 0; xi < node_->nrStates(); xi++) {
@ -884,66 +785,6 @@ BpNodeInfo::getBeliefs (void) const
void
BpNodeInfo::markPiValuesAsCalculated (void)
{
piValsCalc_ = true;
}
void
BpNodeInfo::markLambdaValuesAsCalculated (void)
{
ldValsCalc_ = true;
}
bool
BpNodeInfo::receivedAllPiMessages (void)
{
return node_->getParents().size() == nPiMsgsRcv_;
}
bool
BpNodeInfo::receivedAllLambdaMessages (void)
{
return node_->getChilds().size() == nLdMsgsRcv_;
}
bool
BpNodeInfo::readyToSendPiMsgTo (const BayesNode* child) const
{
for (unsigned i = 0; i < inChildLinks_.size(); i++) {
if (inChildLinks_[i]->getSource() != child
&& inChildLinks_[i]->messageWasSended() == false) {
return false;
}
}
return true;
}
bool
BpNodeInfo::readyToSendLambdaMsgTo (const BayesNode* parent) const
{
for (unsigned i = 0; i < inParentLinks_.size(); i++) {
if (inParentLinks_[i]->getSource() != parent
&& inParentLinks_[i]->messageWasSended() == false) {
return false;
}
}
return true;
}
bool bool
BpNodeInfo::receivedBottomInfluence (void) const BpNodeInfo::receivedBottomInfluence (void) const
{ {

View File

@ -6,7 +6,8 @@
#include "Solver.h" #include "Solver.h"
#include "BayesNet.h" #include "BayesNet.h"
#include "Shared.h" #include "Horus.h"
#include "Util.h"
using namespace std; using namespace std;
@ -16,7 +17,6 @@ static const string PI_SYMBOL = "pi" ;
static const string LD_SYMBOL = "ld" ; static const string LD_SYMBOL = "ld" ;
enum LinkOrientation {UP, DOWN}; enum LinkOrientation {UP, DOWN};
enum JointCalcType {CHAIN_RULE, JUNCTION_NODE};
class BpLink class BpLink
{ {
@ -27,11 +27,11 @@ class BpLink
destin_ = d; destin_ = d;
orientation_ = o; orientation_ = o;
if (orientation_ == LinkOrientation::DOWN) { if (orientation_ == LinkOrientation::DOWN) {
v1_.resize (s->nrStates(), Util::tl (1.0/s->nrStates())); v1_.resize (s->nrStates(), Util::tl (1.0 / s->nrStates()));
v2_.resize (s->nrStates(), Util::tl (1.0/s->nrStates())); v2_.resize (s->nrStates(), Util::tl (1.0 / s->nrStates()));
} else { } else {
v1_.resize (d->nrStates(), Util::tl (1.0/d->nrStates())); v1_.resize (d->nrStates(), Util::tl (1.0 / d->nrStates()));
v2_.resize (d->nrStates(), Util::tl (1.0/d->nrStates())); v2_.resize (d->nrStates(), Util::tl (1.0 / d->nrStates()));
} }
currMsg_ = &v1_; currMsg_ = &v1_;
nextMsg_ = &v2_; nextMsg_ = &v2_;
@ -78,8 +78,8 @@ class BpLink
BayesNode* getSource (void) const { return source_; } BayesNode* getSource (void) const { return source_; }
BayesNode* getDestination (void) const { return destin_; } BayesNode* getDestination (void) const { return destin_; }
LinkOrientation getOrientation (void) const { return orientation_; } LinkOrientation getOrientation (void) const { return orientation_; }
const ParamSet& getMessage (void) const { return *currMsg_; } const Params& getMessage (void) const { return *currMsg_; }
ParamSet& getNextMessage (void) { return *nextMsg_; } Params& getNextMessage (void) { return *nextMsg_; }
bool messageWasSended (void) const { return msgSended_; } bool messageWasSended (void) const { return msgSended_; }
double getResidual (void) const { return residual_; } double getResidual (void) const { return residual_; }
void clearResidual (void) { residual_ = 0;} void clearResidual (void) { residual_ = 0;}
@ -88,10 +88,10 @@ class BpLink
BayesNode* source_; BayesNode* source_;
BayesNode* destin_; BayesNode* destin_;
LinkOrientation orientation_; LinkOrientation orientation_;
ParamSet v1_; Params v1_;
ParamSet v2_; Params v2_;
ParamSet* currMsg_; Params* currMsg_;
ParamSet* nextMsg_; Params* nextMsg_;
bool msgSended_; bool msgSended_;
double residual_; double residual_;
}; };
@ -105,22 +105,11 @@ class BpNodeInfo
public: public:
BpNodeInfo (BayesNode*); BpNodeInfo (BayesNode*);
ParamSet getBeliefs (void) const; Params getBeliefs (void) const;
bool receivedBottomInfluence (void) const; bool receivedBottomInfluence (void) const;
ParamSet& getPiValues (void) { return piVals_; } Params& getPiValues (void) { return piVals_; }
ParamSet& getLambdaValues (void) { return ldVals_; } Params& getLambdaValues (void) { return ldVals_; }
void incNumPiMsgsReceived (void) { nPiMsgsRcv_ ++; }
void incNumLambdaMsgsReceived (void) { nLdMsgsRcv_ ++; }
bool piValuesCalculated (void) { return piValsCalc_; }
bool lambdaValuesCalculated (void) { return ldValsCalc_; }
void markPiValuesAsCalculated (void);
void markLambdaValuesAsCalculated (void);
bool receivedAllPiMessages (void);
bool receivedAllLambdaMessages (void);
bool readyToSendPiMsgTo (const BayesNode*) const ;
bool readyToSendLambdaMsgTo (const BayesNode*) const;
const BpLinkSet& getIncomingParentLinks (void) { return inParentLinks_; } const BpLinkSet& getIncomingParentLinks (void) { return inParentLinks_; }
const BpLinkSet& getIncomingChildLinks (void) { return inChildLinks_; } const BpLinkSet& getIncomingChildLinks (void) { return inChildLinks_; }
@ -135,17 +124,13 @@ class BpNodeInfo
private: private:
DISALLOW_COPY_AND_ASSIGN (BpNodeInfo); DISALLOW_COPY_AND_ASSIGN (BpNodeInfo);
ParamSet piVals_; // pi values const BayesNode* node_;
ParamSet ldVals_; // lambda values Params piVals_; // pi values
unsigned nPiMsgsRcv_; Params ldVals_; // lambda values
unsigned nLdMsgsRcv_;
bool piValsCalc_;
bool ldValsCalc_;
BpLinkSet inParentLinks_; BpLinkSet inParentLinks_;
BpLinkSet inChildLinks_; BpLinkSet inChildLinks_;
BpLinkSet outParentLinks_; BpLinkSet outParentLinks_;
BpLinkSet outChildLinks_; BpLinkSet outChildLinks_;
const BayesNode* node_;
}; };
@ -157,15 +142,14 @@ class BnBpSolver : public Solver
~BnBpSolver (void); ~BnBpSolver (void);
void runSolver (void); void runSolver (void);
ParamSet getPosterioriOf (VarId); Params getPosterioriOf (VarId);
ParamSet getJointDistributionOf (const VarIdSet&); Params getJointDistributionOf (const VarIds&);
private: private:
DISALLOW_COPY_AND_ASSIGN (BnBpSolver); DISALLOW_COPY_AND_ASSIGN (BnBpSolver);
void initializeSolver (void); void initializeSolver (void);
void runPolyTreeSolver (void);
void runLoopySolver (void); void runLoopySolver (void);
void maxResidualSchedule (void); void maxResidualSchedule (void);
bool converged (void) const; bool converged (void) const;
@ -173,8 +157,8 @@ class BnBpSolver : public Solver
void updateLambdaValues (BayesNode*); void updateLambdaValues (BayesNode*);
void calculateLambdaMessage (BpLink*); void calculateLambdaMessage (BpLink*);
void calculatePiMessage (BpLink*); void calculatePiMessage (BpLink*);
ParamSet getJointByJunctionNode (const VarIdSet&); Params getJointByJunctionNode (const VarIds&);
ParamSet getJointByChainRule (const VarIdSet&) const; Params getJointByConditioning (const VarIds&) const;
void printPiLambdaValues (const BayesNode*) const; void printPiLambdaValues (const BayesNode*) const;
void printAllMessageStatus (void) const; void printAllMessageStatus (void) const;
@ -240,7 +224,6 @@ class BnBpSolver : public Solver
vector<BpLink*> links_; vector<BpLink*> links_;
vector<BpNodeInfo*> nodesI_; vector<BpNodeInfo*> nodesI_;
unsigned nIters_; unsigned nIters_;
JointCalcType jointCalcType_;
struct compare struct compare
{ {

View File

@ -4,7 +4,7 @@
#include "Distribution.h" #include "Distribution.h"
bool CFactorGraph::checkForIdenticalFactors_ = true; bool CFactorGraph::checkForIdenticalFactors = true;
CFactorGraph::CFactorGraph (const FactorGraph& fg) CFactorGraph::CFactorGraph (const FactorGraph& fg)
{ {
@ -38,8 +38,8 @@ CFactorGraph::~CFactorGraph (void)
for (unsigned i = 0; i < varClusters_.size(); i++) { for (unsigned i = 0; i < varClusters_.size(); i++) {
delete varClusters_[i]; delete varClusters_[i];
} }
for (unsigned i = 0; i < factorClusters_.size(); i++) { for (unsigned i = 0; i < facClusters_.size(); i++) {
delete factorClusters_[i]; delete facClusters_[i];
} }
} }
@ -72,33 +72,17 @@ CFactorGraph::setInitialColors (void)
} }
const FgFacSet& facNodes = groundFg_->getFactorNodes(); const FgFacSet& facNodes = groundFg_->getFactorNodes();
if (checkForIdenticalFactors_) { if (checkForIdenticalFactors) {
for (unsigned i = 0; i < facNodes.size() - 1; i++) {
// facNodes[i]->factor()->orderFactorVariables();
// FIXME
}
for (unsigned i = 0, s = facNodes.size(); i < s; i++) { for (unsigned i = 0, s = facNodes.size(); i < s; i++) {
Distribution* dist1 = facNodes[i]->getDistribution(); Distribution* dist1 = facNodes[i]->getDistribution();
for (unsigned j = 0; j < i; j++) { for (unsigned j = 0; j < i; j++) {
Distribution* dist2 = facNodes[j]->getDistribution(); Distribution* dist2 = facNodes[j]->getDistribution();
if (dist1 != dist2 && dist1->params == dist2->params) { if (dist1 != dist2 && dist1->params == dist2->params) {
facNodes[i]->factor()->setDistribution (dist2); if (facNodes[i]->factor()->getRanges() ==
// delete dist2; facNodes[j]->factor()->getRanges()) {
break; facNodes[i]->factor()->setDistribution (dist2);
}
/*
if (ok) {
const FgVarSet& fiVars = factors[i]->getFgVarNodes();
const FgVarSet& fjVars = factors[j]->getFgVarNodes();
if (fiVars.size() != fjVars.size()) continue;
for (unsigned k = 0; k < fiVars.size(); k++) {
if (fiVars[k]->nrStates() != fjVars[k]->nrStates()) {
ok = false;
break;
}
} }
} }
*/
} }
} }
} }
@ -194,7 +178,7 @@ CFactorGraph::createClusters (const VarSignMap& varGroups,
varClusters_.push_back (vc); varClusters_.push_back (vc);
} }
factorClusters_.reserve (factorGroups.size()); facClusters_.reserve (factorGroups.size());
for (FacSignMap::const_iterator it = factorGroups.begin(); for (FacSignMap::const_iterator it = factorGroups.begin();
it != factorGroups.end(); it++) { it != factorGroups.end(); it++) {
FgFacNode* groupFactor = it->second[0]; FgFacNode* groupFactor = it->second[0];
@ -205,7 +189,7 @@ CFactorGraph::createClusters (const VarSignMap& varGroups,
VarId vid = neighs[i]->varId(); VarId vid = neighs[i]->varId();
varClusters.push_back (vid2VarCluster_.find (vid)->second); varClusters.push_back (vid2VarCluster_.find (vid)->second);
} }
factorClusters_.push_back (new FacCluster (it->second, varClusters)); facClusters_.push_back (new FacCluster (it->second, varClusters));
} }
} }
@ -220,7 +204,7 @@ CFactorGraph::getSignature (const FgVarNode* varNode)
for (unsigned i = 0; i < neighs.size(); i++) { for (unsigned i = 0; i < neighs.size(); i++) {
*it = getColor (neighs[i]); *it = getColor (neighs[i]);
it ++; it ++;
*it = neighs[i]->factor()->getPositionOf (varNode->varId()); *it = neighs[i]->factor()->indexOf (varNode->varId());
it ++; it ++;
} }
*it = getColor (varNode); *it = getColor (varNode);
@ -256,8 +240,8 @@ CFactorGraph::getCompressedFactorGraph (void)
fg->addVariable (newVar); fg->addVariable (newVar);
} }
for (unsigned i = 0; i < factorClusters_.size(); i++) { for (unsigned i = 0; i < facClusters_.size(); i++) {
const VarClusterSet& myVarClusters = factorClusters_[i]->getVarClusters(); const VarClusterSet& myVarClusters = facClusters_[i]->getVarClusters();
VarNodes myGroundVars; VarNodes myGroundVars;
myGroundVars.reserve (myVarClusters.size()); myGroundVars.reserve (myVarClusters.size());
for (unsigned j = 0; j < myVarClusters.size(); j++) { for (unsigned j = 0; j < myVarClusters.size(); j++) {
@ -265,9 +249,9 @@ CFactorGraph::getCompressedFactorGraph (void)
myGroundVars.push_back (v); myGroundVars.push_back (v);
} }
Factor* newFactor = new Factor (myGroundVars, Factor* newFactor = new Factor (myGroundVars,
factorClusters_[i]->getGroundFactors()[0]->getDistribution()); facClusters_[i]->getGroundFactors()[0]->getDistribution());
FgFacNode* fn = new FgFacNode (newFactor); FgFacNode* fn = new FgFacNode (newFactor);
factorClusters_[i]->setRepresentativeFactor (fn); facClusters_[i]->setRepresentativeFactor (fn);
fg->addFactor (fn); fg->addFactor (fn);
for (unsigned j = 0; j < myGroundVars.size(); j++) { for (unsigned j = 0; j < myGroundVars.size(); j++) {
fg->addEdge (fn, static_cast<FgVarNode*> (myGroundVars[j])); fg->addEdge (fn, static_cast<FgVarNode*> (myGroundVars[j]));
@ -280,14 +264,15 @@ CFactorGraph::getCompressedFactorGraph (void)
unsigned unsigned
CFactorGraph::getGroundEdgeCount (const FacCluster* fc, CFactorGraph::getGroundEdgeCount (
const VarCluster* vc) const const FacCluster* fc,
const VarCluster* vc) const
{ {
const FgFacSet& clusterGroundFactors = fc->getGroundFactors(); const FgFacSet& clusterGroundFactors = fc->getGroundFactors();
FgVarNode* varNode = vc->getGroundFgVarNodes()[0]; FgVarNode* varNode = vc->getGroundFgVarNodes()[0];
unsigned count = 0; unsigned count = 0;
for (unsigned i = 0; i < clusterGroundFactors.size(); i++) { for (unsigned i = 0; i < clusterGroundFactors.size(); i++) {
if (clusterGroundFactors[i]->factor()->getPositionOf (varNode->varId()) != -1) { if (clusterGroundFactors[i]->factor()->indexOf (varNode->varId()) != -1) {
count ++; count ++;
} }
} }
@ -296,7 +281,7 @@ CFactorGraph::getGroundEdgeCount (const FacCluster* fc,
// FgVarNode* var = vc->getGroundFgVarNodes()[i]; // FgVarNode* var = vc->getGroundFgVarNodes()[i];
// unsigned count2 = 0; // unsigned count2 = 0;
// for (unsigned i = 0; i < clusterGroundFactors.size(); i++) { // for (unsigned i = 0; i < clusterGroundFactors.size(); i++) {
// if (clusterGroundFactors[i]->getPositionOf (var) != -1) { // if (clusterGroundFactors[i]->getPosition (var) != -1) {
// count2 ++; // count2 ++;
// } // }
// } // }

View File

@ -5,7 +5,7 @@
#include "FactorGraph.h" #include "FactorGraph.h"
#include "Factor.h" #include "Factor.h"
#include "Shared.h" #include "Horus.h"
class VarCluster; class VarCluster;
class FacCluster; class FacCluster;
@ -18,15 +18,16 @@ class SignatureHash;
typedef long Color; typedef long Color;
typedef unordered_map<unsigned, vector<Color> > VarColorMap; typedef unordered_map<unsigned, vector<Color> > VarColorMap;
typedef unordered_map<const Distribution*, Color> DistColorMap; typedef unordered_map<const Distribution*, Color> DistColorMap;
typedef unordered_map<VarId, VarCluster*> VarId2VarCluster; typedef unordered_map<VarId, VarCluster*> VarId2VarCluster;
typedef vector<VarCluster*> VarClusterSet; typedef vector<VarCluster*> VarClusterSet;
typedef vector<FacCluster*> FacClusterSet; typedef vector<FacCluster*> FacClusterSet;
typedef unordered_map<Signature, FgVarSet, SignatureHash> VarSignMap; typedef unordered_map<Signature, FgVarSet, SignatureHash> VarSignMap;
typedef unordered_map<Signature, FgFacSet, SignatureHash> FacSignMap; typedef unordered_map<Signature, FgFacSet, SignatureHash> FacSignMap;
struct Signature { struct Signature
{
Signature (unsigned size) Signature (unsigned size)
{ {
colors.resize (size); colors.resize (size);
@ -90,12 +91,12 @@ class VarCluster
void addFacCluster (FacCluster* fc) void addFacCluster (FacCluster* fc)
{ {
factorClusters_.push_back (fc); facClusters_.push_back (fc);
} }
const FacClusterSet& getFacClusters (void) const const FacClusterSet& getFacClusters (void) const
{ {
return factorClusters_; return facClusters_;
} }
FgVarNode* getRepresentativeVariable (void) const { return representVar_; } FgVarNode* getRepresentativeVariable (void) const { return representVar_; }
@ -103,9 +104,9 @@ class VarCluster
const FgVarSet& getGroundFgVarNodes (void) const { return groundVars_; } const FgVarSet& getGroundFgVarNodes (void) const { return groundVars_; }
private: private:
FgVarSet groundVars_; FgVarSet groundVars_;
FacClusterSet factorClusters_; FacClusterSet facClusters_;
FgVarNode* representVar_; FgVarNode* representVar_;
}; };
@ -151,9 +152,9 @@ class FacCluster
private: private:
FgFacSet groundFactors_; FgFacSet groundFactors_;
VarClusterSet varClusters_; VarClusterSet varClusters_;
FgFacNode* representFactor_; FgFacNode* representFactor_;
}; };
@ -172,18 +173,10 @@ class CFactorGraph
return vc->getRepresentativeVariable(); return vc->getRepresentativeVariable();
} }
const VarClusterSet& getVariableClusters (void) { return varClusters_; } const VarClusterSet& getVarClusters (void) { return varClusters_; }
const FacClusterSet& getFacClusters (void) { return factorClusters_; } const FacClusterSet& getFacClusters (void) { return facClusters_; }
static void enableCheckForIdenticalFactors (void) static bool checkForIdenticalFactors;
{
checkForIdenticalFactors_ = true;
}
static void disableCheckForIdenticalFactors (void)
{
checkForIdenticalFactors_ = false;
}
private: private:
void setInitialColors (void); void setInitialColors (void);
@ -227,10 +220,9 @@ class CFactorGraph
vector<Signature> varSignatures_; vector<Signature> varSignatures_;
vector<Signature> factorSignatures_; vector<Signature> factorSignatures_;
VarClusterSet varClusters_; VarClusterSet varClusters_;
FacClusterSet factorClusters_; FacClusterSet facClusters_;
VarId2VarCluster vid2VarCluster_; VarId2VarCluster vid2VarCluster_;
const FactorGraph* groundFg_; const FactorGraph* groundFg_;
bool static checkForIdenticalFactors_;
}; };
#endif // HORUS_CFACTORGRAPH_H #endif // HORUS_CFACTORGRAPH_H

View File

@ -13,32 +13,31 @@ CbpSolver::~CbpSolver (void)
ParamSet Params
CbpSolver::getPosterioriOf (VarId vid) CbpSolver::getPosterioriOf (VarId vid)
{ {
assert (lfg_->getEquivalentVariable (vid));
FgVarNode* var = lfg_->getEquivalentVariable (vid); FgVarNode* var = lfg_->getEquivalentVariable (vid);
ParamSet probs; Params probs;
if (var->hasEvidence()) { if (var->hasEvidence()) {
probs.resize (var->nrStates(), Util::noEvidence()); probs.resize (var->nrStates(), Util::noEvidence());
probs[var->getEvidence()] = Util::withEvidence(); probs[var->getEvidence()] = Util::withEvidence();
} else { } else {
probs.resize (var->nrStates(), Util::multIdenty()); probs.resize (var->nrStates(), Util::multIdenty());
const SpLinkSet& links = ninf(var)->getLinks(); const SpLinkSet& links = ninf(var)->getLinks();
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL:
for (unsigned i = 0; i < links.size(); i++) {
CbpSolverLink* l = static_cast<CbpSolverLink*> (links[i]);
Util::multiply (probs, l->getPoweredMessage());
}
Util::normalize (probs);
break;
case NumberSpace::LOGARITHM:
for (unsigned i = 0; i < links.size(); i++) { for (unsigned i = 0; i < links.size(); i++) {
CbpSolverLink* l = static_cast<CbpSolverLink*> (links[i]); CbpSolverLink* l = static_cast<CbpSolverLink*> (links[i]);
Util::add (probs, l->getPoweredMessage()); Util::add (probs, l->getPoweredMessage());
} }
Util::normalize (probs); Util::normalize (probs);
Util::fromLog (probs); Util::fromLog (probs);
} else {
for (unsigned i = 0; i < links.size(); i++) {
CbpSolverLink* l = static_cast<CbpSolverLink*> (links[i]);
Util::multiply (probs, l->getPoweredMessage());
}
Util::normalize (probs);
} }
} }
return probs; return probs;
@ -46,26 +45,19 @@ CbpSolver::getPosterioriOf (VarId vid)
ParamSet Params
CbpSolver::getJointDistributionOf (const VarIdSet& jointVarIds) CbpSolver::getJointDistributionOf (const VarIds& jointVarIds)
{ {
unsigned msgSize = 1; VarIds eqVarIds;
vector<unsigned> dsizes (jointVarIds.size());
for (unsigned i = 0; i < jointVarIds.size(); i++) { for (unsigned i = 0; i < jointVarIds.size(); i++) {
dsizes[i] = lfg_->getEquivalentVariable (jointVarIds[i])->nrStates(); eqVarIds.push_back (lfg_->getEquivalentVariable (jointVarIds[i])->varId());
msgSize *= dsizes[i];
} }
unsigned reps = 1; return FgBpSolver::getJointDistributionOf (eqVarIds);
ParamSet jointDist (msgSize, Util::multIdenty());
for (int i = jointVarIds.size() - 1 ; i >= 0; i--) {
Util::multiply (jointDist, getPosterioriOf (jointVarIds[i]), reps);
reps *= dsizes[i];
}
return jointDist;
} }
void void
CbpSolver::initializeSolver (void) CbpSolver::initializeSolver (void)
{ {
@ -119,7 +111,6 @@ CbpSolver::createLinks (void)
vcs[j]->getRepresentativeVariable(), c)); vcs[j]->getRepresentativeVariable(), c));
} }
} }
return;
} }
@ -197,10 +188,10 @@ CbpSolver::maxResidualSchedule (void)
ParamSet Params
CbpSolver::getVar2FactorMsg (const SpLink* link) const CbpSolver::getVar2FactorMsg (const SpLink* link) const
{ {
ParamSet msg; Params msg;
const FgVarNode* src = link->getVariable(); const FgVarNode* src = link->getVariable();
const FgFacNode* dst = link->getFactor(); const FgFacNode* dst = link->getFactor();
const CbpSolverLink* l = static_cast<const CbpSolverLink*> (link); const CbpSolverLink* l = static_cast<const CbpSolverLink*> (link);
@ -216,27 +207,26 @@ CbpSolver::getVar2FactorMsg (const SpLink* link) const
cout << " " << "init: " << Util::parametersToString (msg) << endl; cout << " " << "init: " << Util::parametersToString (msg) << endl;
} }
const SpLinkSet& links = ninf(src)->getLinks(); const SpLinkSet& links = ninf(src)->getLinks();
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: for (unsigned i = 0; i < links.size(); i++) {
for (unsigned i = 0; i < links.size(); i++) { if (links[i]->getFactor() != dst) {
if (links[i]->getFactor() != dst) { CbpSolverLink* l = static_cast<CbpSolverLink*> (links[i]);
CbpSolverLink* l = static_cast<CbpSolverLink*> (links[i]); Util::add (msg, l->getPoweredMessage());
Util::multiply (msg, l->getPoweredMessage()); }
if (DL >= 5) { }
cout << " msg from " << l->getFactor()->getLabel() << ": " ; } else {
cout << Util::parametersToString (l->getPoweredMessage()) << endl; for (unsigned i = 0; i < links.size(); i++) {
} if (links[i]->getFactor() != dst) {
} CbpSolverLink* l = static_cast<CbpSolverLink*> (links[i]);
} Util::multiply (msg, l->getPoweredMessage());
break; if (DL >= 5) {
case NumberSpace::LOGARITHM: cout << " msg from " << l->getFactor()->getLabel() << ": " ;
for (unsigned i = 0; i < links.size(); i++) { cout << Util::parametersToString (l->getPoweredMessage()) << endl;
if (links[i]->getFactor() != dst) {
CbpSolverLink* l = static_cast<CbpSolverLink*> (links[i]);
Util::add (msg, l->getPoweredMessage());
} }
} }
}
} }
if (DL >= 5) { if (DL >= 5) {
cout << " result = " << Util::parametersToString (msg) << endl; cout << " result = " << Util::parametersToString (msg) << endl;
} }

View File

@ -23,11 +23,11 @@ class CbpSolverLink : public SpLink
Util::pow (poweredMsg_, edgeCount_); Util::pow (poweredMsg_, edgeCount_);
} }
unsigned getNumberOfEdges (void) const { return edgeCount_; } unsigned getNumberOfEdges (void) const { return edgeCount_; }
const ParamSet& getPoweredMessage (void) const { return poweredMsg_; } const Params& getPoweredMessage (void) const { return poweredMsg_; }
private: private:
ParamSet poweredMsg_; Params poweredMsg_;
unsigned edgeCount_; unsigned edgeCount_;
}; };
@ -39,15 +39,15 @@ class CbpSolver : public FgBpSolver
CbpSolver (FactorGraph& fg) : FgBpSolver (fg) { } CbpSolver (FactorGraph& fg) : FgBpSolver (fg) { }
~CbpSolver (void); ~CbpSolver (void);
ParamSet getPosterioriOf (VarId); Params getPosterioriOf (VarId);
ParamSet getJointDistributionOf (const VarIdSet&); Params getJointDistributionOf (const VarIds&);
private: private:
void initializeSolver (void); void initializeSolver (void);
void createLinks (void); void createLinks (void);
void maxResidualSchedule (void); void maxResidualSchedule (void);
ParamSet getVar2FactorMsg (const SpLink*) const; Params getVar2FactorMsg (const SpLink*) const;
void printLinkInformation (void) const; void printLinkInformation (void) const;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,189 @@
#ifndef HORUS_CONSTRAINTTREE_H
#define HORUS_CONSTRAINTTREE_H
#include <cassert>
#include <algorithm>
#include <iostream>
#include <sstream>
#include "TinySet.h"
#include "LiftedUtils.h"
using namespace std;
class CTNode;
typedef vector<CTNode*> CTNodes;
class ConstraintTree;
typedef vector<ConstraintTree*> ConstraintTrees;
class CTNode
{
public:
CTNode (const CTNode& n) : symbol_(n.symbol()), level_(n.level()) { }
CTNode (Symbol s, unsigned l) : symbol_(s) , level_(l) { }
unsigned level (void) const { return level_; }
void setLevel (unsigned level) { level_ = level; }
Symbol symbol (void) const { return symbol_; }
void setSymbol (const Symbol s) { symbol_ = s; }
CTNodes& childs (void) { return childs_; }
const CTNodes& childs (void) const { return childs_; }
unsigned nrChilds (void) const { return childs_.size(); }
bool isRoot (void) const { return level_ == 0; }
bool isLeaf (void) const { return childs_.empty(); }
void addChild (CTNode*, bool = true);
void removeChild (CTNode*);
SymbolSet childSymbols (void) const;
private:
void updateChildLevels (CTNode*, unsigned);
Symbol symbol_;
CTNodes childs_;
unsigned level_;
};
ostream& operator<< (ostream &out, const CTNode&);
class ConstraintTree
{
public:
ConstraintTree (const LogVars&);
ConstraintTree (const LogVars&, const Tuples&);
ConstraintTree (const ConstraintTree&);
~ConstraintTree (void);
CTNode* root (void) const { return root_; }
bool empty (void) const { return root_->childs().empty(); }
const LogVars& logVars (void) const
{
assert (LogVarSet (logVars_) == logVarSet_);
return logVars_;
}
const LogVarSet& logVarSet (void) const
{
assert (LogVarSet (logVars_) == logVarSet_);
return logVarSet_;
}
unsigned nrLogVars (void) const
{
return logVars_.size();
assert (LogVarSet (logVars_) == logVarSet_);
}
void addTuple (const Tuple&);
bool containsTuple (const Tuple&);
void moveToTop (const LogVars&);
void moveToBottom (const LogVars&);
void join (ConstraintTree*, bool = false);
unsigned getLevel (LogVar) const;
void rename (LogVar, LogVar);
void applySubstitution (const Substitution&);
void project (const LogVarSet&);
void remove (const LogVarSet&);
bool isSingleton (LogVar);
LogVarSet singletons (void);
TupleSet tupleSet (unsigned = 0) const;
TupleSet tupleSet (const LogVars&);
unsigned size (void) const;
unsigned nrSymbols (LogVar);
void exportToGraphViz (const char*, bool = false) const;
bool isCountNormalized (const LogVarSet&);
unsigned getConditionalCount (const LogVarSet&);
TinySet<unsigned> getConditionalCounts (const LogVarSet&);
bool isCarteesianProduct (const LogVarSet&) const;
std::pair<ConstraintTree*, ConstraintTree*> split (
const Tuple&,
unsigned);
std::pair<ConstraintTree*, ConstraintTree*> split (
const ConstraintTree*,
unsigned) const;
ConstraintTrees countNormalize (const LogVarSet&);
ConstraintTrees jointCountNormalize (
ConstraintTree*,
ConstraintTree*,
LogVar,
LogVar,
LogVar);
static bool identical (
const ConstraintTree*,
const ConstraintTree*,
unsigned);
static bool overlap (
const ConstraintTree*,
const ConstraintTree*,
unsigned);
LogVars expand (LogVar);
ConstraintTrees ground (LogVar);
private:
unsigned countTuples (const CTNode*) const;
CTNodes getNodesBelow (CTNode*) const;
CTNodes getNodesAtLevel (unsigned) const;
void swapLogVar (LogVar);
bool join (CTNode*, const Tuple&, unsigned, CTNode*);
bool indenticalSubtrees (
const CTNode*,
const CTNode*,
bool) const;
void getTuples (
CTNode*,
Tuples,
unsigned,
Tuples&,
CTNodes&) const;
vector<std::pair<CTNode*, unsigned>> countNormalize (
const CTNode*,
unsigned);
static void split (
CTNode*,
CTNode*,
CTNodes&,
unsigned);
static bool overlap (const CTNode*, const CTNode*, unsigned);
static CTNode* copySubtree (const CTNode*);
static void deleteSubtree (CTNode*);
CTNode* root_;
LogVars logVars_;
LogVarSet logVarSet_;
};
#endif // HORUS_CONSTRAINTTREE_H

View File

@ -1,38 +0,0 @@
#include "CptEntry.h"
CptEntry::CptEntry (int cptIndex, vector<int> instantiations)
{
cptIndex_ = cptIndex;
instantiations_ = instantiations;
}
int
CptEntry::getCptIndex (void) const
{
return cptIndex_;
}
vector<int>
CptEntry::getDomainInstantiations (void) const
{
return instantiations_;
}
bool
CptEntry::matchConstraints (const vector<pair<int,int> >& constraints) const
{
for (unsigned int j = 0; j < constraints.size(); j++) {
int index = constraints[j].first;
if (instantiations_[index] != constraints[j].second) {
return false;
}
}
return true;
}

View File

@ -1,43 +0,0 @@
#ifndef HORUS_CPTENTRY_H
#define HORUS_CPTENTRY_H
#include <vector>
#include "Shared.h"
using namespace std;
class CptEntry
{
public:
CptEntry (unsigned index, const DConf& conf)
{
index_ = index;
conf_ = conf;
}
unsigned getParameterIndex (void) const { return index_; }
const DConf& getDomainConfiguration (void) const { return conf_; }
bool matchConstraints (const DConstraint& constr) const
{
return conf_[constr.first] == constr.second;
}
bool matchConstraints (const vector<DConstraint>& constrs) const
{
for (unsigned j = 0; j < constrs.size(); j++) {
if (conf_[constrs[j].first] != constrs[j].second) {
return false;
}
}
return true;
}
private:
unsigned index_;
DConf conf_;
};
#endif // HORUS_CPTENTRY_H

View File

@ -3,34 +3,39 @@
#include <vector> #include <vector>
#include "CptEntry.h" #include "Horus.h"
#include "Shared.h"
//TODO die die die die die
using namespace std; using namespace std;
struct Distribution struct Distribution
{ {
public: public:
Distribution (unsigned id) Distribution (int id)
{
this->id = id;
}
Distribution (const Params& params, int id = -1)
{ {
this->id = id; this->id = id;
this->params = params; this->params = params;
} }
Distribution (const ParamSet& params, unsigned id = -1) void updateParameters (const Params& params)
{
this->id = id;
this->params = params;
}
void updateParameters (const ParamSet& params)
{ {
this->params = params; this->params = params;
} }
unsigned id; bool shared (void)
ParamSet params; {
vector<CptEntry> entries; return id != -1;
}
int id;
Params params;
private: private:
DISALLOW_COPY_AND_ASSIGN (Distribution); DISALLOW_COPY_AND_ASSIGN (Distribution);

View File

@ -65,7 +65,7 @@ void
ElimGraph::addNode (EgNode* n) ElimGraph::addNode (EgNode* n)
{ {
nodes_.push_back (n); nodes_.push_back (n);
vid2nodes_.insert (make_pair (n->varId(), n)); varMap_.insert (make_pair (n->varId(), n));
} }
@ -73,8 +73,8 @@ ElimGraph::addNode (EgNode* n)
EgNode* EgNode*
ElimGraph::getEgNode (VarId vid) const ElimGraph::getEgNode (VarId vid) const
{ {
unordered_map<VarId,EgNode*>::const_iterator it = vid2nodes_.find (vid); unordered_map<VarId,EgNode*>::const_iterator it =varMap_.find (vid);
if (it == vid2nodes_.end()) { if (it ==varMap_.end()) {
return 0; return 0;
} else { } else {
return it->second; return it->second;
@ -83,10 +83,10 @@ ElimGraph::getEgNode (VarId vid) const
VarIdSet VarIds
ElimGraph::getEliminatingOrder (const VarIdSet& exclude) ElimGraph::getEliminatingOrder (const VarIds& exclude)
{ {
VarIdSet elimOrder; VarIds elimOrder;
marked_.resize (nodes_.size(), false); marked_.resize (nodes_.size(), false);
for (unsigned i = 0; i < exclude.size(); i++) { for (unsigned i = 0; i < exclude.size(); i++) {
@ -275,7 +275,7 @@ ElimGraph::printGraphicalModel (void) const
void void
ElimGraph::exportToGraphViz (const char* fileName, ElimGraph::exportToGraphViz (const char* fileName,
bool showNeighborless, bool showNeighborless,
const VarIdSet& highlightVarIds) const const VarIds& highlightVarIds) const
{ {
ofstream out (fileName); ofstream out (fileName);
if (!out.is_open()) { if (!out.is_open()) {

View File

@ -4,7 +4,7 @@
#include "unordered_map" #include "unordered_map"
#include "FactorGraph.h" #include "FactorGraph.h"
#include "Shared.h" #include "Horus.h"
using namespace std; using namespace std;
@ -45,10 +45,10 @@ class ElimGraph
} }
void addNode (EgNode*); void addNode (EgNode*);
EgNode* getEgNode (VarId) const; EgNode* getEgNode (VarId) const;
VarIdSet getEliminatingOrder (const VarIdSet&); VarIds getEliminatingOrder (const VarIds&);
void printGraphicalModel (void) const; void printGraphicalModel (void) const;
void exportToGraphViz (const char*, bool = true, void exportToGraphViz (const char*, bool = true,
const VarIdSet& = VarIdSet()) const; const VarIds& = VarIds()) const;
void setIndexes(); void setIndexes();
static void setEliminationHeuristic (ElimHeuristic h) static void setEliminationHeuristic (ElimHeuristic h)
@ -68,7 +68,7 @@ class ElimGraph
vector<EgNode*> nodes_; vector<EgNode*> nodes_;
vector<bool> marked_; vector<bool> marked_;
unordered_map<VarId,EgNode*> vid2nodes_; unordered_map<VarId,EgNode*> varMap_;
static ElimHeuristic elimHeuristic_; static ElimHeuristic elimHeuristic_;
}; };

View File

@ -7,7 +7,8 @@
#include <sstream> #include <sstream>
#include "Factor.h" #include "Factor.h"
#include "StatesIndexer.h" #include "Indexer.h"
#include "Util.h"
Factor::Factor (const Factor& g) Factor::Factor (const Factor& g)
@ -21,7 +22,7 @@ Factor::Factor (VarId vid, unsigned nStates)
{ {
varids_.push_back (vid); varids_.push_back (vid);
ranges_.push_back (nStates); ranges_.push_back (nStates);
dist_ = new Distribution (ParamSet (nStates, 1.0)); dist_ = new Distribution (Params (nStates, 1.0));
} }
@ -36,12 +37,12 @@ Factor::Factor (const VarNodes& vars)
} }
// create a uniform distribution // create a uniform distribution
double val = 1.0 / nParams; double val = 1.0 / nParams;
dist_ = new Distribution (ParamSet (nParams, val)); dist_ = new Distribution (Params (nParams, val));
} }
Factor::Factor (VarId vid, unsigned nStates, const ParamSet& params) Factor::Factor (VarId vid, unsigned nStates, const Params& params)
{ {
varids_.push_back (vid); varids_.push_back (vid);
ranges_.push_back (nStates); ranges_.push_back (nStates);
@ -61,7 +62,7 @@ Factor::Factor (VarNodes& vars, Distribution* dist)
Factor::Factor (const VarNodes& vars, const ParamSet& params) Factor::Factor (const VarNodes& vars, const Params& params)
{ {
for (unsigned i = 0; i < vars.size(); i++) { for (unsigned i = 0; i < vars.size(); i++) {
varids_.push_back (vars[i]->varId()); varids_.push_back (vars[i]->varId());
@ -72,9 +73,9 @@ Factor::Factor (const VarNodes& vars, const ParamSet& params)
Factor::Factor (const VarIdSet& vids, Factor::Factor (const VarIds& vids,
const Ranges& ranges, const Ranges& ranges,
const ParamSet& params) const Params& params)
{ {
varids_ = vids; varids_ = vids;
ranges_ = ranges; ranges_ = ranges;
@ -83,11 +84,20 @@ Factor::Factor (const VarIdSet& vids,
Factor::~Factor (void)
{
if (dist_->shared() == false) {
delete dist_;
}
}
void void
Factor::setParameters (const ParamSet& params) Factor::setParameters (const Params& params)
{ {
assert (dist_->params.size() == params.size()); assert (dist_->params.size() == params.size());
dist_->updateParameters (params); dist_->params = params;
} }
@ -97,140 +107,159 @@ Factor::copyFromFactor (const Factor& g)
{ {
varids_ = g.getVarIds(); varids_ = g.getVarIds();
ranges_ = g.getRanges(); ranges_ = g.getRanges();
dist_ = new Distribution (g.getDistribution()->params); dist_ = new Distribution (g.getParameters());
} }
void void
Factor::multiplyByFactor (const Factor& g, const vector<CptEntry>* entries) Factor::multiply (const Factor& g)
{ {
if (varids_.size() == 0) { if (varids_.size() == 0) {
copyFromFactor (g); copyFromFactor (g);
return; return;
} }
const VarIdSet& gvarids = g.getVarIds(); const VarIds& g_varids = g.getVarIds();
const Ranges& granges = g.getRanges(); const Ranges& g_ranges = g.getRanges();
const ParamSet& gparams = g.getParameters(); const Params& g_params = g.getParameters();
if (varids_ == gvarids) { if (varids_ == g_varids) {
// optimization: if the factors contain the same set of variables, // optimization: if the factors contain the same set of variables,
// we can do a 1 to 1 operation on the parameters // we can do a 1 to 1 operation on the parameters
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: Util::add (dist_->params, g_params);
Util::multiply (dist_->params, gparams); } else {
break; Util::multiply (dist_->params, g_params);
case NumberSpace::LOGARITHM:
Util::add (dist_->params, gparams);
} }
} else { } else {
bool hasCommonVars = false; bool sharedVars = false;
vector<unsigned> gvarpos; vector<unsigned> gvarpos;
for (unsigned i = 0; i < gvarids.size(); i++) { for (unsigned i = 0; i < g_varids.size(); i++) {
int pos = getPositionOf (gvarids[i]); int idx = indexOf (g_varids[i]);
if (pos == -1) { if (idx == -1) {
insertVariable (gvarids[i], granges[i]); insertVariable (g_varids[i], g_ranges[i]);
gvarpos.push_back (varids_.size() - 1); gvarpos.push_back (varids_.size() - 1);
} else { } else {
hasCommonVars = true; sharedVars = true;
gvarpos.push_back (pos); gvarpos.push_back (idx);
} }
} }
if (hasCommonVars) { if (sharedVars == false) {
vector<unsigned> gvaroffsets (gvarids.size());
gvaroffsets[gvarids.size() - 1] = 1;
for (int i = gvarids.size() - 2; i >= 0; i--) {
gvaroffsets[i] = gvaroffsets[i + 1] * granges[i + 1];
}
if (entries == 0) {
entries = &getCptEntries();
}
for (unsigned i = 0; i < entries->size(); i++) {
unsigned idx = 0;
const DConf& conf = (*entries)[i].getDomainConfiguration();
for (unsigned j = 0; j < gvarpos.size(); j++) {
idx += gvaroffsets[j] * conf[ gvarpos[j] ];
}
switch (NSPACE) {
case NumberSpace::NORMAL:
dist_->params[i] *= gparams[idx];
break;
case NumberSpace::LOGARITHM:
dist_->params[i] += gparams[idx];
}
}
} else {
// optimization: if the original factors doesn't have common variables, // optimization: if the original factors doesn't have common variables,
// we don't need to marry the states of the common variables // we don't need to marry the states of the common variables
unsigned count = 0; unsigned count = 0;
for (unsigned i = 0; i < dist_->params.size(); i++) { for (unsigned i = 0; i < dist_->params.size(); i++) {
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: dist_->params[i] += g_params[count];
dist_->params[i] *= gparams[count]; } else {
break; dist_->params[i] *= g_params[count];
case NumberSpace::LOGARITHM:
dist_->params[i] += gparams[count];
} }
count ++; count ++;
if (count >= gparams.size()) { if (count >= g_params.size()) {
count = 0; count = 0;
} }
} }
} else {
StatesIndexer indexer (ranges_, false);
while (indexer.valid()) {
unsigned g_li = 0;
unsigned prod = 1;
for (int j = gvarpos.size() - 1; j >= 0; j--) {
g_li += indexer[gvarpos[j]] * prod;
prod *= g_ranges[j];
}
if (Globals::logDomain) {
dist_->params[indexer] += g_params[g_li];
} else {
dist_->params[indexer] *= g_params[g_li];
}
++ indexer;
}
} }
} }
dist_->entries.clear();
} }
void void
Factor::insertVariable (VarId vid, unsigned nStates) Factor::insertVariable (VarId varId, unsigned nrStates)
{ {
assert (getPositionOf (vid) == -1); assert (indexOf (varId) == -1);
ParamSet newPs; Params oldParams = dist_->params;
newPs.reserve (dist_->params.size() * nStates); dist_->params.clear();
for (unsigned i = 0; i < dist_->params.size(); i++) { dist_->params.reserve (oldParams.size() * nrStates);
for (unsigned j = 0; j < nStates; j++) { for (unsigned i = 0; i < oldParams.size(); i++) {
newPs.push_back (dist_->params[i]); for (unsigned reps = 0; reps < nrStates; reps++) {
dist_->params.push_back (oldParams[i]);
} }
} }
varids_.push_back (vid); varids_.push_back (varId);
ranges_.push_back (nStates); ranges_.push_back (nrStates);
dist_->updateParameters (newPs);
dist_->entries.clear();
} }
void void
Factor::removeAllVariablesExcept (VarId vid) Factor::insertVariables (const VarIds& varIds, const Ranges& ranges)
{ {
assert (getPositionOf (vid) != -1); Params oldParams = dist_->params;
unsigned nrStates = 1;
for (unsigned i = 0; i < varIds.size(); i++) {
assert (indexOf (varIds[i]) == -1);
varids_.push_back (varIds[i]);
ranges_.push_back (ranges[i]);
nrStates *= ranges[i];
}
dist_->params.clear();
dist_->params.reserve (oldParams.size() * nrStates);
for (unsigned i = 0; i < oldParams.size(); i++) {
for (unsigned reps = 0; reps < nrStates; reps++) {
dist_->params.push_back (oldParams[i]);
}
}
}
void
Factor::sumOutAllExcept (VarId vid)
{
assert (indexOf (vid) != -1);
while (varids_.back() != vid) { while (varids_.back() != vid) {
removeLastVariable(); sumOutLastVariable();
} }
while (varids_.front() != vid) { while (varids_.front() != vid) {
removeFirstVariable(); sumOutFirstVariable();
} }
} }
void void
Factor::removeVariable (VarId vid) Factor::sumOutAllExcept (const VarIds& vids)
{ {
int pos = getPositionOf (vid); for (unsigned i = 0; i < varids_.size(); i++) {
assert (pos != -1); if (std::find (vids.begin(), vids.end(), varids_[i]) == vids.end()) {
sumOut (varids_[i]);
}
}
}
void
Factor::sumOut (VarId vid)
{
int idx = indexOf (vid);
assert (idx != -1);
if (vid == varids_.back()) { if (vid == varids_.back()) {
removeLastVariable(); // optimization sumOutLastVariable(); // optimization
return; return;
} }
if (vid == varids_.front()) { if (vid == varids_.front()) {
removeFirstVariable(); // optimization sumOutFirstVariable(); // optimization
return; return;
} }
@ -242,36 +271,35 @@ Factor::removeVariable (VarId vid)
// on the left of `var', with the states of the remaining vars fixed // on the left of `var', with the states of the remaining vars fixed
unsigned leftVarOffset = 1; unsigned leftVarOffset = 1;
for (int i = varids_.size() - 1; i > pos; i--) { for (int i = varids_.size() - 1; i > idx; i--) {
varOffset *= ranges_[i]; varOffset *= ranges_[i];
leftVarOffset *= ranges_[i]; leftVarOffset *= ranges_[i];
} }
leftVarOffset *= ranges_[pos]; leftVarOffset *= ranges_[idx];
unsigned offset = 0; unsigned offset = 0;
unsigned count1 = 0; unsigned count1 = 0;
unsigned count2 = 0; unsigned count2 = 0;
unsigned newPsSize = dist_->params.size() / ranges_[pos]; unsigned newpsSize = dist_->params.size() / ranges_[idx];
ParamSet newPs; Params newps;
newPs.reserve (newPsSize); newps.reserve (newpsSize);
Params& params = dist_->params;
while (newPs.size() < newPsSize) { while (newps.size() < newpsSize) {
double sum = Util::addIdenty(); double sum = Util::addIdenty();
for (unsigned i = 0; i < ranges_[pos]; i++) { for (unsigned i = 0; i < ranges_[idx]; i++) {
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: Util::logSum (sum, params[offset]);
sum += dist_->params[offset]; } else {
break; sum += params[offset];
case NumberSpace::LOGARITHM:
Util::logSum (sum, dist_->params[offset]);
} }
offset += varOffset; offset += varOffset;
} }
newPs.push_back (sum); newps.push_back (sum);
count1 ++; count1 ++;
if (pos == (int)varids_.size() - 1) { if (idx == (int)varids_.size() - 1) {
offset = count1 * ranges_[pos]; offset = count1 * ranges_[idx];
} else { } else {
if (((offset - varOffset + 1) % leftVarOffset) == 0) { if (((offset - varOffset + 1) % leftVarOffset) == 0) {
count1 = 0; count1 = 0;
@ -280,73 +308,66 @@ Factor::removeVariable (VarId vid)
offset = (leftVarOffset * count2) + count1; offset = (leftVarOffset * count2) + count1;
} }
} }
varids_.erase (varids_.begin() + pos); varids_.erase (varids_.begin() + idx);
ranges_.erase (ranges_.begin() + pos); ranges_.erase (ranges_.begin() + idx);
dist_->updateParameters (newPs); dist_->params = newps;
dist_->entries.clear();
} }
void void
Factor::removeFirstVariable (void) Factor::sumOutFirstVariable (void)
{ {
ParamSet& params = dist_->params; Params& params = dist_->params;
unsigned nStates = ranges_.front(); unsigned nStates = ranges_.front();
unsigned sep = params.size() / nStates; unsigned sep = params.size() / nStates;
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: for (unsigned i = sep; i < params.size(); i++) {
for (unsigned i = sep; i < params.size(); i++) { Util::logSum (params[i % sep], params[i]);
params[i % sep] += params[i]; }
} } else {
break; for (unsigned i = sep; i < params.size(); i++) {
case NumberSpace::LOGARITHM: params[i % sep] += params[i];
for (unsigned i = sep; i < params.size(); i++) { }
Util::logSum (params[i % sep], params[i]);
}
} }
params.resize (sep); params.resize (sep);
varids_.erase (varids_.begin()); varids_.erase (varids_.begin());
ranges_.erase (ranges_.begin()); ranges_.erase (ranges_.begin());
dist_->entries.clear();
} }
void void
Factor::removeLastVariable (void) Factor::sumOutLastVariable (void)
{ {
ParamSet& params = dist_->params; Params& params = dist_->params;
unsigned nStates = ranges_.back(); unsigned nStates = ranges_.back();
unsigned idx1 = 0; unsigned idx1 = 0;
unsigned idx2 = 0; unsigned idx2 = 0;
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: while (idx1 < params.size()) {
while (idx1 < params.size()) { params[idx2] = params[idx1];
params[idx2] = params[idx1]; idx1 ++;
for (unsigned j = 1; j < nStates; j++) {
Util::logSum (params[idx2], params[idx1]);
idx1 ++; idx1 ++;
for (unsigned j = 1; j < nStates; j++) {
params[idx2] += params[idx1];
idx1 ++;
}
idx2 ++;
} }
break; idx2 ++;
case NumberSpace::LOGARITHM: }
while (idx1 < params.size()) { } else {
params[idx2] = params[idx1]; while (idx1 < params.size()) {
params[idx2] = params[idx1];
idx1 ++;
for (unsigned j = 1; j < nStates; j++) {
params[idx2] += params[idx1];
idx1 ++; idx1 ++;
for (unsigned j = 1; j < nStates; j++) {
Util::logSum (params[idx2], params[idx1]);
idx1 ++;
}
idx2 ++;
} }
idx2 ++;
}
} }
params.resize (idx2); params.resize (idx2);
varids_.pop_back(); varids_.pop_back();
ranges_.pop_back(); ranges_.pop_back();
dist_->entries.clear();
} }
@ -354,34 +375,31 @@ Factor::removeLastVariable (void)
void void
Factor::orderVariables (void) Factor::orderVariables (void)
{ {
VarIdSet sortedVarIds = varids_; VarIds sortedVarIds = varids_;
sort (sortedVarIds.begin(), sortedVarIds.end()); sort (sortedVarIds.begin(), sortedVarIds.end());
orderVariables (sortedVarIds); reorderVariables (sortedVarIds);
} }
void void
Factor::orderVariables (const VarIdSet& newVarIdOrder) Factor::reorderVariables (const VarIds& newVarIds)
{ {
assert (newVarIdOrder.size() == varids_.size()); assert (newVarIds.size() == varids_.size());
if (newVarIdOrder == varids_) { if (newVarIds == varids_) {
return; return;
} }
Ranges newRangeOrder; Ranges newRanges;
for (unsigned i = 0; i < newVarIdOrder.size(); i++) { vector<unsigned> positions;
unsigned pos = getPositionOf (newVarIdOrder[i]); for (unsigned i = 0; i < newVarIds.size(); i++) {
newRangeOrder.push_back (ranges_[pos]); unsigned idx = indexOf (newVarIds[i]);
newRanges.push_back (ranges_[idx]);
positions.push_back (idx);
} }
vector<unsigned> positions;
for (unsigned i = 0; i < newVarIdOrder.size(); i++) {
positions.push_back (getPositionOf (newVarIdOrder[i]));
}
unsigned N = ranges_.size(); unsigned N = ranges_.size();
ParamSet newPs (dist_->params.size()); Params newParams (dist_->params.size());
for (unsigned i = 0; i < dist_->params.size(); i++) { for (unsigned i = 0; i < dist_->params.size(); i++) {
unsigned li = i; unsigned li = i;
// calculate vector index corresponding to linear index // calculate vector index corresponding to linear index
@ -397,35 +415,68 @@ Factor::orderVariables (const VarIdSet& newVarIdOrder)
new_li += vi[positions[k]] * prod; new_li += vi[positions[k]] * prod;
prod *= ranges_[positions[k]]; prod *= ranges_[positions[k]];
} }
newPs[new_li] = dist_->params[i]; newParams[new_li] = dist_->params[i];
} }
varids_ = newVarIdOrder; varids_ = newVarIds;
ranges_ = newRangeOrder; ranges_ = newRanges;
dist_->params = newPs; dist_->params = newParams;
dist_->entries.clear();
} }
void void
Factor::removeInconsistentEntries (VarId vid, unsigned evidence) Factor::absorveEvidence (VarId vid, unsigned evidence)
{ {
int pos = getPositionOf (vid); int idx = indexOf (vid);
assert (pos != -1); assert (idx != -1);
ParamSet newPs;
newPs.reserve (dist_->params.size() / ranges_[pos]); Params oldParams = dist_->params;
StatesIndexer idx (ranges_); dist_->params.clear();
dist_->params.reserve (oldParams.size() / ranges_[idx]);
StatesIndexer indexer (ranges_);
for (unsigned i = 0; i < evidence; i++) { for (unsigned i = 0; i < evidence; i++) {
idx.incrementState (pos); indexer.increment (idx);
} }
while (idx.valid()) { while (indexer.valid()) {
newPs.push_back (dist_->params[idx.getLinearIndex()]); dist_->params.push_back (oldParams[indexer]);
idx.nextSameState (pos); indexer.incrementExcluding (idx);
} }
varids_.erase (varids_.begin() + pos); varids_.erase (varids_.begin() + idx);
ranges_.erase (ranges_.begin() + pos); ranges_.erase (ranges_.begin() + idx);
dist_->updateParameters (newPs); }
dist_->entries.clear();
void
Factor::normalize (void)
{
Util::normalize (dist_->params);
}
bool
Factor::contains (const VarIds& vars) const
{
for (unsigned i = 0; i < vars.size(); i++) {
if (indexOf (vars[i]) == -1) {
return false;
}
}
return true;
}
int
Factor::indexOf (VarId vid) const
{
for (unsigned i = 0; i < varids_.size(); i++) {
if (varids_[i] == vid) {
return i;
}
}
return -1;
} }
@ -446,7 +497,7 @@ Factor::getLabel (void) const
void void
Factor::printFactor (void) const Factor::print (void) const
{ {
VarNodes vars; VarNodes vars;
for (unsigned i = 0; i < varids_.size(); i++) { for (unsigned i = 0; i < varids_.size(); i++) {
@ -457,53 +508,10 @@ Factor::printFactor (void) const
cout << "f(" << jointStrings[i] << ")" ; cout << "f(" << jointStrings[i] << ")" ;
cout << " = " << dist_->params[i] << endl; cout << " = " << dist_->params[i] << endl;
} }
cout << endl;
for (unsigned i = 0; i < vars.size(); i++) { for (unsigned i = 0; i < vars.size(); i++) {
delete vars[i]; delete vars[i];
} }
} }
int
Factor::getPositionOf (VarId vid) const
{
for (unsigned i = 0; i < varids_.size(); i++) {
if (varids_[i] == vid) {
return i;
}
}
return -1;
}
const vector<CptEntry>&
Factor::getCptEntries (void) const
{
if (dist_->entries.size() == 0) {
vector<DConf> confs (dist_->params.size());
for (unsigned i = 0; i < dist_->params.size(); i++) {
confs[i].resize (varids_.size());
}
unsigned nReps = 1;
for (int i = varids_.size() - 1; i >= 0; i--) {
unsigned index = 0;
while (index < dist_->params.size()) {
for (unsigned j = 0; j < ranges_[i]; j++) {
for (unsigned r = 0; r < nReps; r++) {
confs[index][i] = j;
index++;
}
}
}
nReps *= ranges_[i];
}
dist_->entries.clear();
dist_->entries.reserve (dist_->params.size());
for (unsigned i = 0; i < dist_->params.size(); i++) {
dist_->entries.push_back (CptEntry (i, confs[i]));
}
}
return dist_->entries;
}

View File

@ -4,7 +4,6 @@
#include <vector> #include <vector>
#include "Distribution.h" #include "Distribution.h"
#include "CptEntry.h"
#include "VarNode.h" #include "VarNode.h"
@ -20,47 +19,46 @@ class Factor
Factor (const Factor&); Factor (const Factor&);
Factor (VarId, unsigned); Factor (VarId, unsigned);
Factor (const VarNodes&); Factor (const VarNodes&);
Factor (VarId, unsigned, const ParamSet&); Factor (VarId, unsigned, const Params&);
Factor (VarNodes&, Distribution*); Factor (VarNodes&, Distribution*);
Factor (const VarNodes&, const ParamSet&); Factor (const VarNodes&, const Params&);
Factor (const VarIdSet&, const Ranges&, const ParamSet&); Factor (const VarIds&, const Ranges&, const Params&);
~Factor (void);
void setParameters (const ParamSet&); void setParameters (const Params&);
void copyFromFactor (const Factor& f); void copyFromFactor (const Factor& f);
void multiplyByFactor (const Factor&, const vector<CptEntry>* = 0); void multiply (const Factor&);
void insertVariable (VarId, unsigned); void insertVariable (VarId, unsigned);
void removeAllVariablesExcept (VarId); void insertVariables (const VarIds&, const Ranges&);
void removeVariable (VarId); void sumOutAllExcept (VarId);
void removeFirstVariable (void); void sumOutAllExcept (const VarIds&);
void removeLastVariable (void); void sumOut (VarId);
void sumOutFirstVariable (void);
void sumOutLastVariable (void);
void orderVariables (void); void orderVariables (void);
void orderVariables (const VarIdSet&); void reorderVariables (const VarIds&);
void removeInconsistentEntries (VarId, unsigned); void absorveEvidence (VarId, unsigned);
void normalize (void);
bool contains (const VarIds&) const;
int indexOf (VarId) const;
string getLabel (void) const; string getLabel (void) const;
void printFactor (void) const; void print (void) const;
int getPositionOf (VarId) const;
const vector<CptEntry>& getCptEntries (void) const;
const VarIdSet& getVarIds (void) const { return varids_; } const VarIds& getVarIds (void) const { return varids_; }
const Ranges& getRanges (void) const { return ranges_; } const Ranges& getRanges (void) const { return ranges_; }
const ParamSet& getParameters (void) const { return dist_->params; } const Params& getParameters (void) const { return dist_->params; }
Distribution* getDistribution (void) const { return dist_; } Distribution* getDistribution (void) const { return dist_; }
unsigned nrVariables (void) const { return varids_.size(); } unsigned nrVariables (void) const { return varids_.size(); }
unsigned nrParameters() const { return dist_->params.size(); } unsigned nrParameters() const { return dist_->params.size(); }
void setDistribution (Distribution* dist) void setDistribution (Distribution* dist)
{ {
dist_ = dist; dist_ = dist;
} }
void freeDistribution (void)
{
delete dist_;
dist_ = 0;
}
private: private:
VarIdSet varids_; VarIds varids_;
Ranges ranges_; Ranges ranges_;
Distribution* dist_; Distribution* dist_;
}; };

View File

@ -9,6 +9,30 @@
#include "FactorGraph.h" #include "FactorGraph.h"
#include "Factor.h" #include "Factor.h"
#include "BayesNet.h" #include "BayesNet.h"
#include "Util.h"
bool FactorGraph::orderFactorVariables = false;
FactorGraph::FactorGraph (const FactorGraph& fg)
{
const FgVarSet& vars = fg.getVarNodes();
for (unsigned i = 0; i < vars.size(); i++) {
FgVarNode* varNode = new FgVarNode (vars[i]);
addVariable (varNode);
}
const FgFacSet& facs = fg.getFactorNodes();
for (unsigned i = 0; i < facs.size(); i++) {
FgFacNode* facNode = new FgFacNode (facs[i]);
addFactor (facNode);
const FgVarSet& neighs = facs[i]->neighbors();
for (unsigned j = 0; j < neighs.size(); j++) {
addEdge (facNode, varNodes_[neighs[j]->getIndex()]);
}
}
}
@ -30,6 +54,10 @@ FactorGraph::FactorGraph (const BayesNet& bn)
} }
FgFacNode* fn = new FgFacNode ( FgFacNode* fn = new FgFacNode (
new Factor (neighs, nodes[i]->getDistribution())); new Factor (neighs, nodes[i]->getDistribution()));
if (orderFactorVariables) {
sort (neighs.begin(), neighs.end(), CompVarId());
fn->factor()->orderVariables();
}
addFactor (fn); addFactor (fn);
for (unsigned j = 0; j < neighs.size(); j++) { for (unsigned j = 0; j < neighs.size(); j++) {
addEdge (fn, static_cast<FgVarNode*> (neighs[j])); addEdge (fn, static_cast<FgVarNode*> (neighs[j]));
@ -110,13 +138,13 @@ FactorGraph::readFromUaiFormat (const char* fileName)
cerr << ", given: " << nParams << endl; cerr << ", given: " << nParams << endl;
abort(); abort();
} }
ParamSet params (nParams); Params params (nParams);
for (unsigned j = 0; j < nParams; j++) { for (unsigned j = 0; j < nParams; j++) {
double param; double param;
is >> param; is >> param;
params[j] = param; params[j] = param;
} }
if (NSPACE == NumberSpace::LOGARITHM) { if (Globals::logDomain) {
Util::toLog (params); Util::toLog (params);
} }
facNodes_[i]->factor()->setParameters (params); facNodes_[i]->factor()->setParameters (params);
@ -158,7 +186,7 @@ FactorGraph::readFromLibDaiFormat (const char* fileName)
while ((is.peek()) == '#') getline (is, line); while ((is.peek()) == '#') getline (is, line);
is >> nVars; is >> nVars;
VarIdSet vids; VarIds vids;
for (unsigned j = 0; j < nVars; j++) { for (unsigned j = 0; j < nVars; j++) {
VarId vid; VarId vid;
while ((is.peek()) == '#') getline (is, line); while ((is.peek()) == '#') getline (is, line);
@ -185,15 +213,14 @@ FactorGraph::readFromLibDaiFormat (const char* fileName)
neighs.push_back (var); neighs.push_back (var);
nParams *= var->nrStates(); nParams *= var->nrStates();
} }
ParamSet params (nParams, 0); Params params (nParams, 0);
unsigned nNonzeros; unsigned nNonzeros;
while ((is.peek()) == '#') while ((is.peek()) == '#') getline (is, line);
getline (is, line);
is >> nNonzeros; is >> nNonzeros;
for (unsigned j = 0; j < nNonzeros; j++) { for (unsigned j = 0; j < nNonzeros; j++) {
unsigned index; unsigned index;
Param val; double val;
while ((is.peek()) == '#') getline (is, line); while ((is.peek()) == '#') getline (is, line);
is >> index; is >> index;
while ((is.peek()) == '#') getline (is, line); while ((is.peek()) == '#') getline (is, line);
@ -201,7 +228,7 @@ FactorGraph::readFromLibDaiFormat (const char* fileName)
params[index] = val; params[index] = val;
} }
reverse (neighs.begin(), neighs.end()); reverse (neighs.begin(), neighs.end());
if (NSPACE == NumberSpace::LOGARITHM) { if (Globals::logDomain) {
Util::toLog (params); Util::toLog (params);
} }
FgFacNode* fn = new FgFacNode (new Factor (neighs, params)); FgFacNode* fn = new FgFacNode (new Factor (neighs, params));
@ -233,7 +260,7 @@ FactorGraph::addVariable (FgVarNode* vn)
{ {
varNodes_.push_back (vn); varNodes_.push_back (vn);
vn->setIndex (varNodes_.size() - 1); vn->setIndex (varNodes_.size() - 1);
indexMap_.insert (make_pair (vn->varId(), varNodes_.size() - 1)); varMap_.insert (make_pair (vn->varId(), varNodes_.size() - 1));
} }
@ -246,6 +273,7 @@ FactorGraph::addFactor (FgFacNode* fn)
} }
void void
FactorGraph::addEdge (FgVarNode* vn, FgFacNode* fn) FactorGraph::addEdge (FgVarNode* vn, FgFacNode* fn)
{ {
@ -326,10 +354,10 @@ void
FactorGraph::printGraphicalModel (void) const FactorGraph::printGraphicalModel (void) const
{ {
for (unsigned i = 0; i < varNodes_.size(); i++) { for (unsigned i = 0; i < varNodes_.size(); i++) {
cout << "VarId = " << varNodes_[i]->varId() << endl; cout << "VarId = " << varNodes_[i]->varId() << endl;
cout << "Label = " << varNodes_[i]->label() << endl; cout << "Label = " << varNodes_[i]->label() << endl;
cout << "Nr States = " << varNodes_[i]->nrStates() << endl; cout << "Nr States = " << varNodes_[i]->nrStates() << endl;
cout << "Evidence = " << varNodes_[i]->getEvidence() << endl; cout << "Evidence = " << varNodes_[i]->getEvidence() << endl;
cout << "Factors = " ; cout << "Factors = " ;
for (unsigned j = 0; j < varNodes_[i]->neighbors().size(); j++) { for (unsigned j = 0; j < varNodes_[i]->neighbors().size(); j++) {
cout << varNodes_[i]->neighbors()[j]->getLabel() << " " ; cout << varNodes_[i]->neighbors()[j]->getLabel() << " " ;
@ -337,7 +365,7 @@ FactorGraph::printGraphicalModel (void) const
cout << endl << endl; cout << endl << endl;
} }
for (unsigned i = 0; i < facNodes_.size(); i++) { for (unsigned i = 0; i < facNodes_.size(); i++) {
facNodes_[i]->factor()->printFactor(); facNodes_[i]->factor()->print();
cout << endl; cout << endl;
} }
} }
@ -412,7 +440,10 @@ FactorGraph::exportToUaiFormat (const char* fileName) const
} }
for (unsigned i = 0; i < facNodes_.size(); i++) { for (unsigned i = 0; i < facNodes_.size(); i++) {
const ParamSet& params = facNodes_[i]->getParameters(); Params params = facNodes_[i]->getParameters();
if (Globals::logDomain) {
Util::fromLog (params);
}
out << endl << params.size() << endl << " " ; out << endl << params.size() << endl << " " ;
for (unsigned j = 0; j < params.size(); j++) { for (unsigned j = 0; j < params.size(); j++) {
out << params[j] << " " ; out << params[j] << " " ;
@ -446,7 +477,10 @@ FactorGraph::exportToLibDaiFormat (const char* fileName) const
out << factorVars[j]->nrStates() << " " ; out << factorVars[j]->nrStates() << " " ;
} }
out << endl; out << endl;
const ParamSet& params = facNodes_[i]->factor()->getParameters(); Params params = facNodes_[i]->factor()->getParameters();
if (Globals::logDomain) {
Util::fromLog (params);
}
out << params.size() << endl; out << params.size() << endl;
for (unsigned j = 0; j < params.size(); j++) { for (unsigned j = 0; j < params.size(); j++) {
out << j << " " << params[j] << endl; out << j << " " << params[j] << endl;

View File

@ -4,13 +4,13 @@
#include <vector> #include <vector>
#include "GraphicalModel.h" #include "GraphicalModel.h"
#include "Shared.h"
#include "Distribution.h" #include "Distribution.h"
#include "Factor.h" #include "Factor.h"
#include "Horus.h"
using namespace std; using namespace std;
class BayesNet;
class FgFacNode; class FgFacNode;
class FgVarNode : public VarNode class FgVarNode : public VarNode
@ -18,42 +18,29 @@ class FgVarNode : public VarNode
public: public:
FgVarNode (VarId varId, unsigned nrStates) : VarNode (varId, nrStates) { } FgVarNode (VarId varId, unsigned nrStates) : VarNode (varId, nrStates) { }
FgVarNode (const VarNode* v) : VarNode (v) { } FgVarNode (const VarNode* v) : VarNode (v) { }
void addNeighbor (FgFacNode* fn)
{ void addNeighbor (FgFacNode* fn) { neighs_.push_back (fn); }
neighs_.push_back (fn); const FgFacSet& neighbors (void) const { return neighs_; }
}
const vector<FgFacNode*>& neighbors (void) const
{
return neighs_;
}
private: private:
DISALLOW_COPY_AND_ASSIGN (FgVarNode); DISALLOW_COPY_AND_ASSIGN (FgVarNode);
// members // members
vector<FgFacNode*> neighs_; FgFacSet neighs_;
}; };
class FgFacNode class FgFacNode
{ {
public: public:
FgFacNode (Factor* factor) FgFacNode (const FgFacNode* fn) {
{ factor_ = new Factor (*fn->factor());
factor_ = factor;
index_ = -1; index_ = -1;
} }
Factor* factor() const FgFacNode (Factor* f) : factor_(new Factor(*f)), index_(-1) { }
{ Factor* factor() const { return factor_; }
return factor_; void addNeighbor (FgVarNode* vn) { neighs_.push_back (vn); }
} const FgVarSet& neighbors (void) const { return neighs_; }
void addNeighbor (FgVarNode* vn)
{
neighs_.push_back (vn);
}
const vector<FgVarNode*>& neighbors (void) const
{
return neighs_;
}
int getIndex (void) const int getIndex (void) const
{ {
assert (index_ != -1); assert (index_ != -1);
@ -67,7 +54,7 @@ class FgFacNode
{ {
return factor_->getDistribution(); return factor_->getDistribution();
} }
const ParamSet& getParameters (void) const const Params& getParameters (void) const
{ {
return factor_->getParameters(); return factor_->getParameters();
} }
@ -80,7 +67,16 @@ class FgFacNode
Factor* factor_; Factor* factor_;
int index_; int index_;
vector<FgVarNode*> neighs_; FgVarSet neighs_;
};
struct CompVarId
{
bool operator() (const VarNode* vn1, const VarNode* vn2) const
{
return vn1->varId() < vn2->varId();
}
}; };
@ -88,6 +84,7 @@ class FactorGraph : public GraphicalModel
{ {
public: public:
FactorGraph (void) {}; FactorGraph (void) {};
FactorGraph (const FactorGraph&);
FactorGraph (const BayesNet&); FactorGraph (const BayesNet&);
~FactorGraph (void); ~FactorGraph (void);
@ -112,28 +109,29 @@ class FactorGraph : public GraphicalModel
FgVarNode* getFgVarNode (VarId vid) const FgVarNode* getFgVarNode (VarId vid) const
{ {
IndexMap::const_iterator it = indexMap_.find (vid); IndexMap::const_iterator it = varMap_.find (vid);
if (it == indexMap_.end()) { if (it == varMap_.end()) {
return 0; return 0;
} else { } else {
return varNodes_[it->second]; return varNodes_[it->second];
} }
} }
static bool orderFactorVariables;
private: private:
//DISALLOW_COPY_AND_ASSIGN (FactorGraph);
bool containsCycle (void) const; bool containsCycle (void) const;
bool containsCycle (const FgVarNode*, const FgFacNode*, bool containsCycle (const FgVarNode*, const FgFacNode*,
vector<bool>&, vector<bool>&) const; vector<bool>&, vector<bool>&) const;
bool containsCycle (const FgFacNode*, const FgVarNode*, bool containsCycle (const FgFacNode*, const FgVarNode*,
vector<bool>&, vector<bool>&) const; vector<bool>&, vector<bool>&) const;
DISALLOW_COPY_AND_ASSIGN (FactorGraph);
FgVarSet varNodes_; FgVarSet varNodes_;
FgFacSet facNodes_; FgFacSet facNodes_;
typedef unordered_map<unsigned, unsigned> IndexMap; typedef unordered_map<unsigned, unsigned> IndexMap;
IndexMap indexMap_; IndexMap varMap_;
}; };
#endif // HORUS_FACTORGRAPH_H #endif // HORUS_FACTORGRAPH_H

View File

@ -8,7 +8,8 @@
#include "FgBpSolver.h" #include "FgBpSolver.h"
#include "FactorGraph.h" #include "FactorGraph.h"
#include "Factor.h" #include "Factor.h"
#include "Shared.h" #include "Indexer.h"
#include "Horus.h"
FgBpSolver::FgBpSolver (const FactorGraph& fg) : Solver (&fg) FgBpSolver::FgBpSolver (const FactorGraph& fg) : Solver (&fg)
@ -40,20 +41,15 @@ FgBpSolver::runSolver (void)
if (COLLECT_STATISTICS) { if (COLLECT_STATISTICS) {
start = clock(); start = clock();
} }
if (false) { runLoopySolver();
//if (!BpOptions::useAlwaysLoopySolver && factorGraph_->isTree()) { if (DL >= 2) {
runTreeSolver(); cout << endl;
} else { if (nIters_ < BpOptions::maxIter) {
runLoopySolver(); cout << "Sum-Product converged in " ;
if (DL >= 2) { cout << nIters_ << " iterations" << endl;
} else {
cout << "The maximum number of iterations was hit, terminating..." ;
cout << endl; cout << endl;
if (nIters_ < BpOptions::maxIter) {
cout << "Sum-Product converged in " ;
cout << nIters_ << " iterations" << endl;
} else {
cout << "The maximum number of iterations was hit, terminating..." ;
cout << endl;
}
} }
} }
unsigned size = factorGraph_->getVarNodes().size(); unsigned size = factorGraph_->getVarNodes().size();
@ -73,32 +69,29 @@ FgBpSolver::runSolver (void)
ParamSet Params
FgBpSolver::getPosterioriOf (VarId vid) FgBpSolver::getPosterioriOf (VarId vid)
{ {
assert (factorGraph_->getFgVarNode (vid)); assert (factorGraph_->getFgVarNode (vid));
FgVarNode* var = factorGraph_->getFgVarNode (vid); FgVarNode* var = factorGraph_->getFgVarNode (vid);
ParamSet probs; Params probs;
if (var->hasEvidence()) { if (var->hasEvidence()) {
probs.resize (var->nrStates(), Util::noEvidence()); probs.resize (var->nrStates(), Util::noEvidence());
probs[var->getEvidence()] = Util::withEvidence(); probs[var->getEvidence()] = Util::withEvidence();
} else { } else {
probs.resize (var->nrStates(), Util::multIdenty()); probs.resize (var->nrStates(), Util::multIdenty());
const SpLinkSet& links = ninf(var)->getLinks(); const SpLinkSet& links = ninf(var)->getLinks();
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: for (unsigned i = 0; i < links.size(); i++) {
for (unsigned i = 0; i < links.size(); i++) { Util::add (probs, links[i]->getMessage());
Util::multiply (probs, links[i]->getMessage()); }
} Util::normalize (probs);
Util::normalize (probs); Util::fromLog (probs);
break; } else {
case NumberSpace::LOGARITHM: for (unsigned i = 0; i < links.size(); i++) {
for (unsigned i = 0; i < links.size(); i++) { Util::multiply (probs, links[i]->getMessage());
Util::add (probs, links[i]->getMessage()); }
} Util::normalize (probs);
Util::normalize (probs);
Util::fromLog (probs);
} }
} }
return probs; return probs;
@ -106,66 +99,38 @@ FgBpSolver::getPosterioriOf (VarId vid)
ParamSet Params
FgBpSolver::getJointDistributionOf (const VarIdSet& jointVarIds) FgBpSolver::getJointDistributionOf (const VarIds& jointVarIds)
{ {
unsigned msgSize = 1; FgVarNode* vn = factorGraph_->getFgVarNode (jointVarIds[0]);
vector<unsigned> dsizes (jointVarIds.size()); const FgFacSet& factorNodes = vn->neighbors();
for (unsigned i = 0; i < jointVarIds.size(); i++) { int idx = -1;
dsizes[i] = factorGraph_->getFgVarNode (jointVarIds[i])->nrStates(); for (unsigned i = 0; i < factorNodes.size(); i++) {
msgSize *= dsizes[i]; if (factorNodes[i]->factor()->contains (jointVarIds)) {
} idx = i;
unsigned reps = 1; break;
ParamSet jointDist (msgSize, Util::multIdenty());
for (int i = jointVarIds.size() - 1 ; i >= 0; i--) {
Util::multiply (jointDist, getPosterioriOf (jointVarIds[i]), reps);
reps *= dsizes[i];
}
return jointDist;
}
void
FgBpSolver::runTreeSolver (void)
{
initializeSolver();
const FgFacSet& facNodes = factorGraph_->getFactorNodes();
bool finish = false;
while (!finish) {
finish = true;
for (unsigned i = 0; i < facNodes.size(); i++) {
const SpLinkSet& links = ninf (facNodes[i])->getLinks();
for (unsigned j = 0; j < links.size(); j++) {
if (!links[j]->messageWasSended()) {
if (readyToSendMessage (links[j])) {
calculateAndUpdateMessage (links[j], false);
}
finish = false;
}
}
} }
} }
} if (idx == -1) {
return getJointByConditioning (jointVarIds);
} else {
Factor r (*factorNodes[idx]->factor());
bool const SpLinkSet& links = ninf(factorNodes[idx])->getLinks();
FgBpSolver::readyToSendMessage (const SpLink* link) const for (unsigned i = 0; i < links.size(); i++) {
{ Factor msg (links[i]->getVariable()->varId(),
const FgVarSet& neighbors = link->getFactor()->neighbors(); links[i]->getVariable()->nrStates(),
for (unsigned i = 0; i < neighbors.size(); i++) { getVar2FactorMsg (links[i]));
if (neighbors[i] != link->getVariable()) { r.multiply (msg);
const SpLinkSet& links = ninf (neighbors[i])->getLinks();
for (unsigned j = 0; j < links.size(); j++) {
if (links[j]->getFactor() != link->getFactor() &&
!links[j]->messageWasSended()) {
return false;
}
}
} }
r.sumOutAllExcept (jointVarIds);
r.reorderVariables (jointVarIds);
r.normalize();
Params jointDist = r.getParameters();
if (Globals::logDomain) {
Util::fromLog (jointDist);
}
return jointDist;
} }
return true;
} }
@ -282,7 +247,7 @@ FgBpSolver::converged (void)
} }
bool converged = true; bool converged = true;
if (BpOptions::schedule == BpOptions::Schedule::MAX_RESIDUAL) { if (BpOptions::schedule == BpOptions::Schedule::MAX_RESIDUAL) {
Param maxResidual = (*(sortedOrder_.begin()))->getResidual(); double maxResidual = (*(sortedOrder_.begin()))->getResidual();
if (maxResidual > BpOptions::accuracy) { if (maxResidual > BpOptions::accuracy) {
converged = false; converged = false;
} else { } else {
@ -374,40 +339,39 @@ FgBpSolver::calculateFactor2VariableMsg (SpLink* link) const
msgSize *= links[i]->getVariable()->nrStates(); msgSize *= links[i]->getVariable()->nrStates();
} }
unsigned repetitions = 1; unsigned repetitions = 1;
ParamSet msgProduct (msgSize, Util::multIdenty()); Params msgProduct (msgSize, Util::multIdenty());
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: for (int i = links.size() - 1; i >= 0; i--) {
for (int i = links.size() - 1; i >= 0; i--) { if (links[i]->getVariable() != dst) {
if (links[i]->getVariable() != dst) { Util::add (msgProduct, getVar2FactorMsg (links[i]), repetitions);
if (DL >= 5) { repetitions *= links[i]->getVariable()->nrStates();
cout << " message from " << links[i]->getVariable()->label(); } else {
cout << ": " << endl; unsigned ds = links[i]->getVariable()->nrStates();
} Util::add (msgProduct, Params (ds, 1.0), repetitions);
Util::multiply (msgProduct, getVar2FactorMsg (links[i]), repetitions); repetitions *= ds;
repetitions *= links[i]->getVariable()->nrStates();
} else {
unsigned ds = links[i]->getVariable()->nrStates();
Util::multiply (msgProduct, ParamSet (ds, 1.0), repetitions);
repetitions *= ds;
}
} }
break; }
case NumberSpace::LOGARITHM: } else {
for (int i = links.size() - 1; i >= 0; i--) { for (int i = links.size() - 1; i >= 0; i--) {
if (links[i]->getVariable() != dst) { if (links[i]->getVariable() != dst) {
Util::add (msgProduct, getVar2FactorMsg (links[i]), repetitions); if (DL >= 5) {
repetitions *= links[i]->getVariable()->nrStates(); cout << " message from " << links[i]->getVariable()->label();
} else { cout << ": " << endl;
unsigned ds = links[i]->getVariable()->nrStates();
Util::add (msgProduct, ParamSet (ds, 1.0), repetitions);
repetitions *= ds;
} }
Util::multiply (msgProduct, getVar2FactorMsg (links[i]), repetitions);
repetitions *= links[i]->getVariable()->nrStates();
} else {
unsigned ds = links[i]->getVariable()->nrStates();
Util::multiply (msgProduct, Params (ds, 1.0), repetitions);
repetitions *= ds;
} }
}
} }
Factor result (src->factor()->getVarIds(), Factor result (src->factor()->getVarIds(),
src->factor()->getRanges(), src->factor()->getRanges(),
msgProduct); msgProduct);
result.multiplyByFactor (*(src->factor())); result.multiply (*(src->factor()));
if (DL >= 5) { if (DL >= 5) {
cout << " message product: " ; cout << " message product: " ;
cout << Util::parametersToString (msgProduct) << endl; cout << Util::parametersToString (msgProduct) << endl;
@ -416,13 +380,13 @@ FgBpSolver::calculateFactor2VariableMsg (SpLink* link) const
cout << " factor product: " ; cout << " factor product: " ;
cout << Util::parametersToString (result.getParameters()) << endl; cout << Util::parametersToString (result.getParameters()) << endl;
} }
result.removeAllVariablesExcept (dst->varId()); result.sumOutAllExcept (dst->varId());
if (DL >= 5) { if (DL >= 5) {
cout << " marginalized: " ; cout << " marginalized: " ;
cout << Util::parametersToString (result.getParameters()) << endl; cout << Util::parametersToString (result.getParameters()) << endl;
} }
const ParamSet& resultParams = result.getParameters(); const Params& resultParams = result.getParameters();
ParamSet& message = link->getNextMessage(); Params& message = link->getNextMessage();
for (unsigned i = 0; i < resultParams.size(); i++) { for (unsigned i = 0; i < resultParams.size(); i++) {
message[i] = resultParams[i]; message[i] = resultParams[i];
} }
@ -433,17 +397,16 @@ FgBpSolver::calculateFactor2VariableMsg (SpLink* link) const
cout << " next msg: " ; cout << " next msg: " ;
cout << Util::parametersToString (message) << endl; cout << Util::parametersToString (message) << endl;
} }
result.freeDistribution();
} }
ParamSet Params
FgBpSolver::getVar2FactorMsg (const SpLink* link) const FgBpSolver::getVar2FactorMsg (const SpLink* link) const
{ {
const FgVarNode* src = link->getVariable(); const FgVarNode* src = link->getVariable();
const FgFacNode* dst = link->getFactor(); const FgFacNode* dst = link->getFactor();
ParamSet msg; Params msg;
if (src->hasEvidence()) { if (src->hasEvidence()) {
msg.resize (src->nrStates(), Util::noEvidence()); msg.resize (src->nrStates(), Util::noEvidence());
msg[src->getEvidence()] = Util::withEvidence(); msg[src->getEvidence()] = Util::withEvidence();
@ -457,23 +420,21 @@ FgBpSolver::getVar2FactorMsg (const SpLink* link) const
cout << Util::parametersToString (msg); cout << Util::parametersToString (msg);
} }
const SpLinkSet& links = ninf (src)->getLinks(); const SpLinkSet& links = ninf (src)->getLinks();
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: for (unsigned i = 0; i < links.size(); i++) {
for (unsigned i = 0; i < links.size(); i++) { if (links[i]->getFactor() != dst) {
if (links[i]->getFactor() != dst) { Util::add (msg, links[i]->getMessage());
Util::multiply (msg, links[i]->getMessage()); }
if (DL >= 5) { }
cout << " x " << Util::parametersToString (links[i]->getMessage()); } else {
} for (unsigned i = 0; i < links.size(); i++) {
} if (links[i]->getFactor() != dst) {
} Util::multiply (msg, links[i]->getMessage());
break; if (DL >= 5) {
case NumberSpace::LOGARITHM: cout << " x " << Util::parametersToString (links[i]->getMessage());
for (unsigned i = 0; i < links.size(); i++) {
if (links[i]->getFactor() != dst) {
Util::add (msg, links[i]->getMessage());
} }
} }
}
} }
if (DL >= 5) { if (DL >= 5) {
cout << " = " << Util::parametersToString (msg); cout << " = " << Util::parametersToString (msg);
@ -483,6 +444,58 @@ FgBpSolver::getVar2FactorMsg (const SpLink* link) const
Params
FgBpSolver::getJointByConditioning (const VarIds& jointVarIds) const
{
FgVarSet jointVars;
for (unsigned i = 0; i < jointVarIds.size(); i++) {
assert (factorGraph_->getFgVarNode (jointVarIds[i]));
jointVars.push_back (factorGraph_->getFgVarNode (jointVarIds[i]));
}
FactorGraph* fg = new FactorGraph (*factorGraph_);
FgBpSolver solver (*fg);
solver.runSolver();
Params prevBeliefs = solver.getPosterioriOf (jointVarIds[0]);
VarIds observedVids = {jointVars[0]->varId()};
for (unsigned i = 1; i < jointVarIds.size(); i++) {
assert (jointVars[i]->hasEvidence() == false);
Params newBeliefs;
VarNodes observedVars;
for (unsigned j = 0; j < observedVids.size(); j++) {
observedVars.push_back (fg->getFgVarNode (observedVids[j]));
}
StatesIndexer idx (observedVars, false);
while (idx.valid()) {
for (unsigned j = 0; j < observedVars.size(); j++) {
observedVars[j]->setEvidence (idx[j]);
}
++ idx;
FgBpSolver solver (*fg);
solver.runSolver();
Params beliefs = solver.getPosterioriOf (jointVarIds[i]);
for (unsigned k = 0; k < beliefs.size(); k++) {
newBeliefs.push_back (beliefs[k]);
}
}
int count = -1;
for (unsigned j = 0; j < newBeliefs.size(); j++) {
if (j % jointVars[i]->nrStates() == 0) {
count ++;
}
newBeliefs[j] *= prevBeliefs[count];
}
prevBeliefs = newBeliefs;
observedVids.push_back (jointVars[i]->varId());
}
return prevBeliefs;
}
void void
FgBpSolver::printLinkInformation (void) const FgBpSolver::printLinkInformation (void) const
{ {

View File

@ -8,6 +8,7 @@
#include "Solver.h" #include "Solver.h"
#include "Factor.h" #include "Factor.h"
#include "FactorGraph.h" #include "FactorGraph.h"
#include "Util.h"
using namespace std; using namespace std;
@ -52,8 +53,8 @@ class SpLink
FgFacNode* getFactor (void) const { return fac_; } FgFacNode* getFactor (void) const { return fac_; }
FgVarNode* getVariable (void) const { return var_; } FgVarNode* getVariable (void) const { return var_; }
const ParamSet& getMessage (void) const { return *currMsg_; } const Params& getMessage (void) const { return *currMsg_; }
ParamSet& getNextMessage (void) { return *nextMsg_; } Params& getNextMessage (void) { return *nextMsg_; }
bool messageWasSended (void) const { return msgSended_; } bool messageWasSended (void) const { return msgSended_; }
double getResidual (void) const { return residual_; } double getResidual (void) const { return residual_; }
void clearResidual (void) { residual_ = 0.0; } void clearResidual (void) { residual_ = 0.0; }
@ -61,10 +62,10 @@ class SpLink
protected: protected:
FgFacNode* fac_; FgFacNode* fac_;
FgVarNode* var_; FgVarNode* var_;
ParamSet v1_; Params v1_;
ParamSet v2_; Params v2_;
ParamSet* currMsg_; Params* currMsg_;
ParamSet* nextMsg_; Params* nextMsg_;
bool msgSended_; bool msgSended_;
double residual_; double residual_;
}; };
@ -91,15 +92,16 @@ class FgBpSolver : public Solver
virtual ~FgBpSolver (void); virtual ~FgBpSolver (void);
void runSolver (void); void runSolver (void);
virtual ParamSet getPosterioriOf (VarId); virtual Params getPosterioriOf (VarId);
virtual ParamSet getJointDistributionOf (const VarIdSet&); virtual Params getJointDistributionOf (const VarIds&);
protected: protected:
virtual void initializeSolver (void); virtual void initializeSolver (void);
virtual void createLinks (void); virtual void createLinks (void);
virtual void maxResidualSchedule (void); virtual void maxResidualSchedule (void);
virtual void calculateFactor2VariableMsg (SpLink*) const; virtual void calculateFactor2VariableMsg (SpLink*) const;
virtual ParamSet getVar2FactorMsg (const SpLink*) const; virtual Params getVar2FactorMsg (const SpLink*) const;
virtual Params getJointByConditioning (const VarIds&) const;
virtual void printLinkInformation (void) const; virtual void printLinkInformation (void) const;
void calculateAndUpdateMessage (SpLink* link, bool calcResidual = true) void calculateAndUpdateMessage (SpLink* link, bool calcResidual = true)
@ -163,8 +165,6 @@ class FgBpSolver : public Solver
SpLinkMap linkMap_; SpLinkMap linkMap_;
private: private:
void runTreeSolver (void);
bool readyToSendMessage (const SpLink*) const;
void runLoopySolver (void); void runLoopySolver (void);
bool converged (void); bool converged (void);

View File

@ -0,0 +1,703 @@
#include <algorithm>
#include <set>
#include "FoveSolver.h"
#include "Histogram.h"
#include "Util.h"
vector<LiftedOperator*>
LiftedOperator::getValidOps (ParfactorList& pfList, const Grounds& query)
{
vector<LiftedOperator*> validOps;
vector<SumOutOperator*> sumOutOps;
vector<CountingOperator*> countOps;
vector<GroundOperator*> groundOps;
sumOutOps = SumOutOperator::getValidOps (pfList, query);
countOps = CountingOperator::getValidOps (pfList);
groundOps = GroundOperator::getValidOps (pfList);
validOps.insert (validOps.end(), sumOutOps.begin(), sumOutOps.end());
validOps.insert (validOps.end(), countOps.begin(), countOps.end());
validOps.insert (validOps.end(), groundOps.begin(), groundOps.end());
return validOps;
}
void
LiftedOperator::printValidOps (ParfactorList& pfList, const Grounds& query)
{
vector<LiftedOperator*> validOps;
validOps = LiftedOperator::getValidOps (pfList, query);
for (unsigned i = 0; i < validOps.size(); i++) {
cout << "-> " << validOps[i]->toString() << endl;
}
}
unsigned
SumOutOperator::getCost (void)
{
TinySet<unsigned> groupSet;
ParfactorList::const_iterator pfIter = pfList_.begin();
while (pfIter != pfList_.end()) {
if ((*pfIter)->containsGroup (group_)) {
vector<unsigned> groups = (*pfIter)->getAllGroups();
groupSet |= TinySet<unsigned> (groups);
}
++ pfIter;
}
unsigned cost = 1;
for (unsigned i = 0; i < groupSet.size(); i++) {
pfIter = pfList_.begin();
while (pfIter != pfList_.end()) {
if ((*pfIter)->containsGroup (groupSet[i])) {
int idx = (*pfIter)->indexOfFormulaWithGroup (groupSet[i]);
cost *= (*pfIter)->range (idx);
break;
}
++ pfIter;
}
}
return cost;
}
void
SumOutOperator::apply (void)
{
vector<ParfactorList::iterator> iters
= parfactorsWithGroup (pfList_, group_);
Parfactor* product = *(iters[0]);
pfList_.remove (iters[0]);
for (unsigned i = 1; i < iters.size(); i++) {
product->multiply (**(iters[i]));
delete *(iters[i]);
pfList_.remove (iters[i]);
}
if (product->nrFormulas() == 1) {
delete product;
return;
}
int fIdx = product->indexOfFormulaWithGroup (group_);
LogVarSet excl = product->exclusiveLogVars (fIdx);
if (product->constr()->isCountNormalized (excl)) {
product->sumOut (fIdx);
pfList_.addShattered (product);
} else {
Parfactors pfs = FoveSolver::countNormalize (product, excl);
for (unsigned i = 0; i < pfs.size(); i++) {
pfs[i]->sumOut (fIdx);
pfList_.add (pfs[i]);
}
delete product;
pfList_.shatter();
}
}
vector<SumOutOperator*>
SumOutOperator::getValidOps (ParfactorList& pfList, const Grounds& query)
{
vector<SumOutOperator*> validOps;
set<unsigned> allGroups;
ParfactorList::const_iterator it = pfList.begin();
while (it != pfList.end()) {
assert (*it);
const ProbFormulas& formulas = (*it)->formulas();
for (unsigned i = 0; i < formulas.size(); i++) {
allGroups.insert (formulas[i].group());
}
++ it;
}
set<unsigned>::const_iterator groupIt = allGroups.begin();
while (groupIt != allGroups.end()) {
if (validOp (*groupIt, pfList, query)) {
validOps.push_back (new SumOutOperator (*groupIt, pfList));
}
++ groupIt;
}
return validOps;
}
string
SumOutOperator::toString (void)
{
stringstream ss;
vector<ParfactorList::iterator> pfIters;
pfIters = parfactorsWithGroup (pfList_, group_);
int idx = (*pfIters[0])->indexOfFormulaWithGroup (group_);
ProbFormula f = (*pfIters[0])->formula (idx);
TupleSet tupleSet = (*pfIters[0])->constr()->tupleSet (f.logVars());
ss << "sum out " << f.functor() << "/" << f.arity();
ss << "|" << tupleSet << " (group " << group_ << ")";
ss << " [cost=" << getCost() << "]" << endl;
return ss.str();
}
bool
SumOutOperator::validOp (
unsigned group,
ParfactorList& pfList,
const Grounds& query)
{
vector<ParfactorList::iterator> pfIters;
pfIters = parfactorsWithGroup (pfList, group);
if (isToEliminate (*pfIters[0], group, query) == false) {
return false;
}
unordered_map<unsigned, unsigned> groupToRange;
for (unsigned i = 0; i < pfIters.size(); i++) {
int fIdx = (*pfIters[i])->indexOfFormulaWithGroup (group);
if ((*pfIters[i])->formulas()[fIdx].contains (
(*pfIters[i])->elimLogVars()) == false) {
return false;
}
vector<unsigned> ranges = (*pfIters[i])->ranges();
vector<unsigned> groups = (*pfIters[i])->getAllGroups();
for (unsigned i = 0; i < groups.size(); i++) {
unordered_map<unsigned, unsigned>::iterator it;
it = groupToRange.find (groups[i]);
if (it == groupToRange.end()) {
groupToRange.insert (make_pair (groups[i], ranges[i]));
} else {
if (it->second != ranges[i]) {
return false;
}
}
}
}
return true;
}
vector<ParfactorList::iterator>
SumOutOperator::parfactorsWithGroup (
ParfactorList& pfList,
unsigned group)
{
vector<ParfactorList::iterator> iters;
ParfactorList::iterator pflIt = pfList.begin();
while (pflIt != pfList.end()) {
if ((*pflIt)->containsGroup (group)) {
iters.push_back (pflIt);
}
++ pflIt;
}
return iters;
}
bool
SumOutOperator::isToEliminate (
Parfactor* g,
unsigned group,
const Grounds& query)
{
int fIdx = g->indexOfFormulaWithGroup (group);
const ProbFormula& formula = g->formula (fIdx);
bool toElim = true;
for (unsigned i = 0; i < query.size(); i++) {
if (formula.functor() == query[i].functor() &&
formula.arity() == query[i].arity()) {
g->constr()->moveToTop (formula.logVars());
if (g->constr()->containsTuple (query[i].args())) {
toElim = false;
break;
}
}
}
return toElim;
}
unsigned
CountingOperator::getCost (void)
{
unsigned cost = 0;
int fIdx = (*pfIter_)->indexOfFormulaWithLogVar (X_);
unsigned range = (*pfIter_)->range (fIdx);
unsigned size = (*pfIter_)->size() / range;
TinySet<unsigned> counts;
counts = (*pfIter_)->constr()->getConditionalCounts (X_);
for (unsigned i = 0; i < counts.size(); i++) {
cost += size * HistogramSet::nrHistograms (counts[i], range);
}
return cost;
}
void
CountingOperator::apply (void)
{
if ((*pfIter_)->constr()->isCountNormalized (X_)) {
(*pfIter_)->countConvert (X_);
} else {
Parfactors pfs = FoveSolver::countNormalize (*pfIter_, X_);
for (unsigned i = 0; i < pfs.size(); i++) {
unsigned condCount = pfs[i]->constr()->getConditionalCount (X_);
bool cartProduct = pfs[i]->constr()->isCarteesianProduct (
(*pfIter_)->countedLogVars() | X_);
if (condCount > 1 && cartProduct) {
pfs[i]->countConvert (X_);
}
pfList_.add (pfs[i]);
}
pfList_.deleteAndRemove (pfIter_);
pfList_.shatter();
}
}
vector<CountingOperator*>
CountingOperator::getValidOps (ParfactorList& pfList)
{
vector<CountingOperator*> validOps;
ParfactorList::iterator it = pfList.begin();
while (it != pfList.end()) {
LogVarSet candidates = (*it)->uncountedLogVars();
for (unsigned i = 0; i < candidates.size(); i++) {
if (validOp (*it, candidates[i])) {
validOps.push_back (new CountingOperator (
it, candidates[i], pfList));
}
}
++ it;
}
return validOps;
}
string
CountingOperator::toString (void)
{
stringstream ss;
ss << "count convert " << X_ << " in " ;
ss << (*pfIter_)->getHeaderString();
ss << " [cost=" << getCost() << "]" << endl;
Parfactors pfs = FoveSolver::countNormalize (*pfIter_, X_);
if ((*pfIter_)->constr()->isCountNormalized (X_) == false) {
for (unsigned i = 0; i < pfs.size(); i++) {
ss << " º " << pfs[i]->getHeaderString() << endl;
}
}
return ss.str();
}
bool
CountingOperator::validOp (Parfactor* g, LogVar X)
{
if (g->nrFormulas (X) != 1) {
return false;
}
int fIdx = g->indexOfFormulaWithLogVar (X);
if (g->formulas()[fIdx].isCounting()) {
return false;
}
bool countNormalized = g->constr()->isCountNormalized (X);
if (countNormalized) {
unsigned condCount = g->constr()->getConditionalCount (X);
bool cartProduct = g->constr()->isCarteesianProduct (
g->countedLogVars() | X);
if (condCount == 1 || cartProduct == false) {
return false;
}
}
return true;
}
unsigned
GroundOperator::getCost (void)
{
unsigned cost = 0;
bool isCountingLv = (*pfIter_)->countedLogVars().contains (X_);
if (isCountingLv) {
int fIdx = (*pfIter_)->indexOfFormulaWithLogVar (X_);
unsigned currSize = (*pfIter_)->size();
unsigned nrHists = (*pfIter_)->range (fIdx);
unsigned range = (*pfIter_)->formula(fIdx).range();
unsigned nrSymbols = (*pfIter_)->constr()->getConditionalCount (X_);
cost = (currSize / nrHists) * (std::pow (range, nrSymbols));
} else {
cost = (*pfIter_)->constr()->nrSymbols (X_) * (*pfIter_)->size();
}
return cost;
}
void
GroundOperator::apply (void)
{
bool countedLv = (*pfIter_)->countedLogVars().contains (X_);
if (countedLv) {
(*pfIter_)->fullExpand (X_);
(*pfIter_)->setNewGroups();
pfList_.shatter();
} else {
ConstraintTrees cts = (*pfIter_)->constr()->ground (X_);
for (unsigned i = 0; i < cts.size(); i++) {
Parfactor* newPf = new Parfactor (*pfIter_, cts[i]);
pfList_.add (newPf);
}
pfList_.deleteAndRemove (pfIter_);
pfList_.shatter();
}
}
vector<GroundOperator*>
GroundOperator::getValidOps (ParfactorList& pfList)
{
vector<GroundOperator*> validOps;
ParfactorList::iterator pfIter = pfList.begin();
while (pfIter != pfList.end()) {
LogVarSet set = (*pfIter)->logVarSet();
for (unsigned i = 0; i < set.size(); i++) {
if ((*pfIter)->constr()->isSingleton (set[i]) == false) {
validOps.push_back (new GroundOperator (pfIter, set[i], pfList));
}
}
++ pfIter;
}
return validOps;
}
string
GroundOperator::toString (void)
{
stringstream ss;
((*pfIter_)->countedLogVars().contains (X_))
? ss << "full expanding "
: ss << "grounding " ;
ss << X_ << " in " << (*pfIter_)->getHeaderString();
ss << " [cost=" << getCost() << "]" << endl;
return ss.str();
}
FoveSolver::FoveSolver (const ParfactorList* pfList)
{
for (ParfactorList::const_iterator it = pfList->begin();
it != pfList->end();
it ++) {
pfList_.addShattered (new Parfactor (**it));
}
}
Params
FoveSolver::getPosterioriOf (const Ground& query)
{
return getJointDistributionOf ({query});
}
Params
FoveSolver::getJointDistributionOf (const Grounds& query)
{
shatterAgainstQuery (query);
runSolver (query);
(*pfList_.begin())->normalize();
Params params = (*pfList_.begin())->params();
if (Globals::logDomain) {
Util::fromLog (params);
}
delete *pfList_.begin();
return params;
}
void
FoveSolver::absorveEvidence (
ParfactorList& pfList,
const ObservedFormulas& obsFormulas)
{
ParfactorList::iterator it = pfList.begin();
while (it != pfList.end()) {
bool increment = true;
for (unsigned i = 0; i < obsFormulas.size(); i++) {
if (absorved (pfList, it, obsFormulas[i])) {
it = pfList.deleteAndRemove (it);
increment = false;
break;
}
}
if (increment) {
++ it;
}
}
pfList.shatter();
if (obsFormulas.empty() == false) {
cout << "*******************************************************" << endl;
cout << "AFTER EVIDENCE ABSORVED" << endl;
for (unsigned i = 0; i < obsFormulas.size(); i++) {
cout << " -> " << *obsFormulas[i] << endl;
}
cout << "*******************************************************" << endl;
}
pfList.print();
}
Parfactors
FoveSolver::countNormalize (
Parfactor* g,
const LogVarSet& set)
{
if (set.empty()) {
assert (false); // TODO
return {};
}
Parfactors normPfs;
ConstraintTrees normCts = g->constr()->countNormalize (set);
for (unsigned i = 0; i < normCts.size(); i++) {
normPfs.push_back (new Parfactor (g, normCts[i]));
}
return normPfs;
}
void
FoveSolver::runSolver (const Grounds& query)
{
while (true) {
cout << "---------------------------------------------------" << endl;
pfList_.print();
LiftedOperator::printValidOps (pfList_, query);
LiftedOperator* op = getBestOperation (query);
if (op == 0) {
break;
}
cout << "best operation: " << op->toString() << endl;
op->apply();
}
if (pfList_.size() > 1) {
ParfactorList::iterator pfIter = pfList_.begin();
pfIter ++;
while (pfIter != pfList_.end()) {
(*pfList_.begin())->multiply (**pfIter);
++ pfIter;
}
}
(*pfList_.begin())->reorderAccordingGrounds (query);
}
bool
FoveSolver::allEliminated (const Grounds&)
{
ParfactorList::iterator pfIter = pfList_.begin();
while (pfIter != pfList_.end()) {
const ProbFormulas formulas = (*pfIter)->formulas();
for (unsigned i = 0; i < formulas.size(); i++) {
//bool toElim = false;
//for (unsigned j = 0; j < queries.size(); j++) {
// if ((*pfIter)->containsGround (queries[i]) == false) {
// return
// }
}
++ pfIter;
}
return false;
}
LiftedOperator*
FoveSolver::getBestOperation (const Grounds& query)
{
unsigned bestCost;
LiftedOperator* bestOp = 0;
vector<LiftedOperator*> validOps;
validOps = LiftedOperator::getValidOps (pfList_, query);
for (unsigned i = 0; i < validOps.size(); i++) {
unsigned cost = validOps[i]->getCost();
if ((bestOp == 0) || (cost < bestCost)) {
bestOp = validOps[i];
bestCost = cost;
}
}
return bestOp;
}
void
FoveSolver::shatterAgainstQuery (const Grounds& query)
{
// return;
for (unsigned i = 0; i < query.size(); i++) {
if (query[i].isAtom()) {
continue;
}
ParfactorList pfListCopy = pfList_;
pfList_.clear();
for (ParfactorList::iterator it = pfListCopy.begin();
it != pfListCopy.end(); ++ it) {
Parfactor* pf = *it;
if (pf->containsGround (query[i])) {
std::pair<ConstraintTree*, ConstraintTree*> split =
pf->constr()->split (query[i].args(), query[i].arity());
ConstraintTree* commCt = split.first;
ConstraintTree* exclCt = split.second;
pfList_.add (new Parfactor (pf, commCt));
if (exclCt->empty() == false) {
pfList_.add (new Parfactor (pf, exclCt));
} else {
delete exclCt;
}
delete pf;
} else {
pfList_.add (pf);
}
}
pfList_.shatter();
}
cout << endl;
cout << "*******************************************************" << endl;
cout << "SHATTERED AGAINST THE QUERY" << endl;
for (unsigned i = 0; i < query.size(); i++) {
cout << " -> " << query[i] << endl;
}
cout << "*******************************************************" << endl;
pfList_.print();
}
bool
FoveSolver::absorved (
ParfactorList& pfList,
ParfactorList::iterator pfIter,
const ObservedFormula* obsFormula)
{
Parfactors absorvedPfs;
Parfactor* g = *pfIter;
const ProbFormulas& formulas = g->formulas();
for (unsigned i = 0; i < formulas.size(); i++) {
if (obsFormula->functor() == formulas[i].functor() &&
obsFormula->arity() == formulas[i].arity()) {
if (obsFormula->isAtom()) {
if (formulas.size() > 1) {
g->absorveEvidence (i, obsFormula->evidence());
} else {
return true;
}
}
g->constr()->moveToTop (formulas[i].logVars());
std::pair<ConstraintTree*, ConstraintTree*> res
= g->constr()->split (obsFormula->constr(), formulas[i].arity());
ConstraintTree* commCt = res.first;
ConstraintTree* exclCt = res.second;
if (commCt->empty()) {
delete commCt;
delete exclCt;
continue;
}
if (exclCt->empty() == false) {
pfList.add (new Parfactor (g, exclCt));
} else {
delete exclCt;
}
if (formulas.size() > 1) {
LogVarSet excl = g->exclusiveLogVars (i);
Parfactors countNormPfs = countNormalize (g, excl);
for (unsigned j = 0; j < countNormPfs.size(); j++) {
countNormPfs[j]->absorveEvidence (i, obsFormula->evidence());
absorvedPfs.push_back (countNormPfs[j]);
}
} else {
delete commCt;
}
return true;
}
}
return false;
}
bool
FoveSolver::proper (
const ProbFormula& f1,
ConstraintTree* c1,
const ProbFormula& f2,
ConstraintTree* c2)
{
return disjoint (f1, c1, f2, c2)
|| identical (f1, c1, f2, c2);
}
bool
FoveSolver::identical (
const ProbFormula& f1,
ConstraintTree* c1,
const ProbFormula& f2,
ConstraintTree* c2)
{
if (f1.sameSkeletonAs (f2) == false) {
return false;
}
c1->moveToTop (f1.logVars());
c2->moveToTop (f2.logVars());
return ConstraintTree::identical (
c1, c2, f1.logVars().size());
}
bool
FoveSolver::disjoint (
const ProbFormula& f1,
ConstraintTree* c1,
const ProbFormula& f2,
ConstraintTree* c2)
{
if (f1.sameSkeletonAs (f2) == false) {
return true;
}
c1->moveToTop (f1.logVars());
c2->moveToTop (f2.logVars());
return ConstraintTree::overlap (
c1, c2, f1.arity()) == false;
}

View File

@ -0,0 +1,132 @@
#ifndef HORUS_FOVESOLVER_H
#define HORUS_FOVESOLVER_H
#include "ParfactorList.h"
class LiftedOperator
{
public:
virtual unsigned getCost (void) = 0;
virtual void apply (void) = 0;
virtual string toString (void) = 0;
static vector<LiftedOperator*> getValidOps (
ParfactorList&, const Grounds&);
static void printValidOps (ParfactorList&, const Grounds&);
};
class SumOutOperator : public LiftedOperator
{
public:
SumOutOperator (unsigned group, ParfactorList& pfList)
: group_(group), pfList_(pfList) { }
unsigned getCost (void);
void apply (void);
static vector<SumOutOperator*> getValidOps (
ParfactorList&, const Grounds&);
string toString (void);
private:
static bool validOp (unsigned, ParfactorList&, const Grounds&);
static vector<ParfactorList::iterator> parfactorsWithGroup (
ParfactorList& pfList, unsigned group);
static bool isToEliminate (Parfactor*, unsigned, const Grounds&);
unsigned group_;
ParfactorList& pfList_;
};
class CountingOperator : public LiftedOperator
{
public:
CountingOperator (
ParfactorList::iterator pfIter,
LogVar X,
ParfactorList& pfList)
: pfIter_(pfIter), X_(X), pfList_(pfList) { }
unsigned getCost (void);
void apply (void);
static vector<CountingOperator*> getValidOps (ParfactorList&);
string toString (void);
private:
static bool validOp (Parfactor*, LogVar);
ParfactorList::iterator pfIter_;
LogVar X_;
ParfactorList& pfList_;
};
class GroundOperator : public LiftedOperator
{
public:
GroundOperator (
ParfactorList::iterator pfIter,
LogVar X,
ParfactorList& pfList)
: pfIter_(pfIter), X_(X), pfList_(pfList) { }
unsigned getCost (void);
void apply (void);
static vector<GroundOperator*> getValidOps (ParfactorList&);
string toString (void);
private:
ParfactorList::iterator pfIter_;
LogVar X_;
ParfactorList& pfList_;
};
class FoveSolver
{
public:
FoveSolver (const ParfactorList*);
Params getPosterioriOf (const Ground&);
Params getJointDistributionOf (const Grounds&);
static void absorveEvidence (
ParfactorList& pfList,
const ObservedFormulas& obsFormulas);
static Parfactors countNormalize (Parfactor*, const LogVarSet&);
private:
void runSolver (const Grounds&);
bool allEliminated (const Grounds&);
LiftedOperator* getBestOperation (const Grounds&);
void shatterAgainstQuery (const Grounds&);
static bool absorved (
ParfactorList& pfList,
ParfactorList::iterator pfIter,
const ObservedFormula*);
public:
static bool proper (
const ProbFormula&,
ConstraintTree*,
const ProbFormula&,
ConstraintTree*);
static bool identical (
const ProbFormula&,
ConstraintTree*,
const ProbFormula&,
ConstraintTree*);
static bool disjoint (
const ProbFormula&,
ConstraintTree*,
const ProbFormula&,
ConstraintTree*);
ParfactorList pfList_;
};
#endif // HORUS_FOVESOLVER_H

View File

@ -1,11 +1,15 @@
#ifndef HORUS_GRAPHICALMODEL_H #ifndef HORUS_GRAPHICALMODEL_H
#define HORUS_GRAPHICALMODEL_H #define HORUS_GRAPHICALMODEL_H
#include <sstream>
#include "VarNode.h" #include "VarNode.h"
#include "Shared.h" #include "Distribution.h"
#include "Horus.h"
using namespace std; using namespace std;
struct VariableInfo struct VariableInfo
{ {
VariableInfo (string l, const States& sts) VariableInfo (string l, const States& sts)
@ -45,9 +49,18 @@ class GraphicalModel
{ {
varsInfo_.clear(); varsInfo_.clear();
} }
static void addDistribution (unsigned id, Distribution* dist)
{
distsInfo_[id] = dist;
}
static void updateDistribution (unsigned id, const Params& params)
{
distsInfo_[id]->updateParameters (params);
}
private: private:
static unordered_map<VarId,VariableInfo> varsInfo_; static unordered_map<VarId,VariableInfo> varsInfo_;
static unordered_map<unsigned,Distribution*> distsInfo_;
}; };
#endif // HORUS_GRAPHICALMODEL_H #endif // HORUS_GRAPHICALMODEL_H

View File

@ -0,0 +1,126 @@
#include <cassert>
#include <algorithm>
#include <numeric>
#include "Histogram.h"
#include "Util.h"
HistogramSet::HistogramSet (unsigned size, unsigned range)
{
size_ = size;
hist_.resize (range, 0);
hist_[0] = size;
}
void
HistogramSet::nextHistogram (void)
{
for (int i = hist_.size() - 2; i >= 0; i--) {
if (hist_[i] > 0) {
hist_[i] --;
hist_[i + 1] = maxCount (i + 1);
clearAfter (i + 1);
break;
}
}
assert (std::accumulate (hist_.begin(), hist_.end(), 0) == (int)size_);
}
unsigned
HistogramSet::operator[] (unsigned idx) const
{
assert (idx < hist_.size());
return hist_[idx];
}
unsigned
HistogramSet::nrHistograms (void) const
{
return Util::nrCombinations (size_ + hist_.size() - 1, hist_.size() - 1);
}
void
HistogramSet::reset (void)
{
std::fill (hist_.begin() + 1, hist_.end(), 0);
hist_[0] = size_;
}
vector<Histogram>
HistogramSet::getHistograms (unsigned N, unsigned R)
{
HistogramSet hs (N, R);
unsigned H = hs.nrHistograms();
vector<Histogram> histograms;
histograms.reserve (H);
for (unsigned i = 0; i < H; i++) {
histograms.push_back (hs.hist_);
hs.nextHistogram();
}
return histograms;
}
unsigned
HistogramSet::nrHistograms (unsigned N, unsigned R)
{
return Util::nrCombinations (N + R - 1, R - 1);
}
unsigned
HistogramSet::findIndex (
const Histogram& hist,
const vector<Histogram>& histograms)
{
vector<Histogram>::const_iterator it = std::lower_bound (
histograms.begin(),
histograms.end(),
hist,
std::greater<Histogram>());
assert (it != histograms.end() && *it == hist);
return std::distance (histograms.begin(), it);
}
ostream& operator<< (ostream &os, const HistogramSet& hs)
{
os << "#" << hs.hist_;
return os;
}
unsigned
HistogramSet::maxCount (unsigned idx) const
{
unsigned sum = 0;
for (unsigned i = 0; i < idx; i++) {
sum += hist_[i];
}
return size_ - sum;
}
void
HistogramSet::clearAfter (unsigned idx)
{
std::fill (hist_.begin() + idx + 1, hist_.end(), 0);
}

View File

@ -0,0 +1,44 @@
#ifndef HORUS_HISTOGRAM_H
#define HORUS_HISTOGRAM_H
#include <vector>
#include <ostream>
using namespace std;
typedef vector<unsigned> Histogram;
class HistogramSet
{
public:
HistogramSet (unsigned, unsigned);
void nextHistogram (void);
unsigned operator[] (unsigned idx) const;
unsigned nrHistograms (void) const;
void reset (void);
static vector<Histogram> getHistograms (unsigned ,unsigned);
static unsigned nrHistograms (unsigned, unsigned);
static unsigned findIndex (
const Histogram&,
const vector<Histogram>&);
friend std::ostream& operator<< (ostream &os, const HistogramSet& hs);
private:
unsigned maxCount (unsigned) const;
void clearAfter (unsigned);
unsigned size_;
Histogram hist_;
};
#endif // HORUS_HISTOGRAM_H

View File

@ -0,0 +1,88 @@
#ifndef HORUS_HORUS_H
#define HORUS_HORUS_H
#include <cmath>
#include <cassert>
#include <limits>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <iostream>
#include <fstream>
#include <sstream>
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
using namespace std;
class VarNode;
class BayesNode;
class FgVarNode;
class FgFacNode;
class Factor;
typedef vector<double> Params;
typedef unsigned VarId;
typedef vector<VarId> VarIds;
typedef vector<VarNode*> VarNodes;
typedef vector<BayesNode*> BnNodeSet;
typedef vector<FgVarNode*> FgVarSet;
typedef vector<FgFacNode*> FgFacSet;
typedef vector<Factor*> FactorSet;
typedef vector<string> States;
typedef vector<unsigned> Ranges;
namespace Globals {
extern bool logDomain;
};
// level of debug information
static const unsigned DL = 1;
static const int NO_EVIDENCE = -1;
// number of digits to show when printing a parameter
static const unsigned PRECISION = 5;
static const bool COLLECT_STATISTICS = false;
static const bool EXPORT_TO_GRAPHVIZ = false;
static const unsigned EXPORT_MINIMAL_SIZE = 100;
static const double INF = -numeric_limits<double>::infinity();
namespace InfAlgorithms {
enum InfAlgs
{
VE, // variable elimination
BN_BP, // bayesian network belief propagation
FG_BP, // factor graph belief propagation
CBP // counting bp solver
};
extern InfAlgs infAlgorithm;
};
namespace BpOptions
{
enum Schedule {
SEQ_FIXED,
SEQ_RANDOM,
PARALLEL,
MAX_RESIDUAL
};
extern Schedule schedule;
extern double accuracy;
extern unsigned maxIter;
}
#endif // HORUS_HORUS_H

View File

@ -10,7 +10,9 @@
#include "FgBpSolver.h" #include "FgBpSolver.h"
#include "CbpSolver.h" #include "CbpSolver.h"
#include "StatesIndexer.h" //#include "TinySet.h"
#include "LiftedUtils.h"
using namespace std; using namespace std;
@ -22,9 +24,38 @@ const string USAGE = "usage: \
./hcli FILE [VARIABLE | OBSERVED_VARIABLE=EVIDENCE]..." ; ./hcli FILE [VARIABLE | OBSERVED_VARIABLE=EVIDENCE]..." ;
class Cenas
{
public:
Cenas (int cc)
{
c = cc;
}
//operator int (void) const
//{
// cout << "return int" << endl;
// return c;
//}
operator double (void) const
{
cout << "return double" << endl;
return 0.0;
}
private:
int c;
};
int int
main (int argc, const char* argv[]) main (int argc, const char* argv[])
{ {
LogVar X = 3;
LogVarSet Xs = X;
cout << "set: " << X << endl;
Cenas c1 (1);
Cenas c2 (3);
cout << (c1 < c2) << endl;
return 0;
if (!argv[1]) { if (!argv[1]) {
cerr << "error: no graphical model specified" << endl; cerr << "error: no graphical model specified" << endl;
cerr << USAGE << endl; cerr << USAGE << endl;
@ -121,7 +152,6 @@ processArguments (BayesNet& bn, int argc, const char* argv[])
break; break;
case InfAlgorithms::FG_BP: case InfAlgorithms::FG_BP:
fg = new FactorGraph (bn); fg = new FactorGraph (bn);
fg->printGraphicalModel();
solver = new FgBpSolver (*fg); solver = new FgBpSolver (*fg);
break; break;
case InfAlgorithms::CBP: case InfAlgorithms::CBP:
@ -230,6 +260,9 @@ processArguments (FactorGraph& fg, int argc, const char* argv[])
break; break;
case InfAlgorithms::BN_BP: case InfAlgorithms::BN_BP:
case InfAlgorithms::FG_BP: case InfAlgorithms::FG_BP:
//cout << "here!" << endl;
//fg.printGraphicalModel();
//fg.exportToLibDaiFormat ("net.fg");
solver = new FgBpSolver (fg); solver = new FgBpSolver (fg);
break; break;
case InfAlgorithms::CBP: case InfAlgorithms::CBP:
@ -247,7 +280,7 @@ processArguments (FactorGraph& fg, int argc, const char* argv[])
void void
runSolver (Solver* solver, const VarNodes& queryVars) runSolver (Solver* solver, const VarNodes& queryVars)
{ {
VarIdSet vids; VarIds vids;
for (unsigned i = 0; i < queryVars.size(); i++) { for (unsigned i = 0; i < queryVars.size(); i++) {
vids.push_back (queryVars[i]->varId()); vids.push_back (queryVars[i]->varId());
} }

View File

@ -1,4 +1,5 @@
#include <cstdlib> #include <cstdlib>
#include <vector> #include <vector>
#include <iostream> #include <iostream>
@ -13,12 +14,169 @@
#include "FgBpSolver.h" #include "FgBpSolver.h"
#include "CbpSolver.h" #include "CbpSolver.h"
#include "ElimGraph.h" #include "ElimGraph.h"
#include "FoveSolver.h"
#include "ParfactorList.h"
using namespace std; using namespace std;
Params readParams (YAP_Term);
int createLiftedNetwork (void)
{
Parfactors parfactors;
YAP_Term parfactorList = YAP_ARG1;
while (parfactorList != YAP_TermNil()) {
YAP_Term parfactor = YAP_HeadOfTerm (parfactorList);
// read dist id
unsigned distId = YAP_IntOfTerm (YAP_ArgOfTerm (1, parfactor));
// read the ranges
Ranges ranges;
YAP_Term rangeList = YAP_ArgOfTerm (3, parfactor);
while (rangeList != YAP_TermNil()) {
unsigned range = (unsigned) YAP_IntOfTerm (YAP_HeadOfTerm (rangeList));
ranges.push_back (range);
rangeList = YAP_TailOfTerm (rangeList);
}
// read parametric random vars
ProbFormulas formulas;
unsigned count = 0;
unordered_map<YAP_Term, LogVar> lvMap;
YAP_Term pvList = YAP_ArgOfTerm (2, parfactor);
while (pvList != YAP_TermNil()) {
YAP_Term formulaTerm = YAP_HeadOfTerm (pvList);
if (YAP_IsAtomTerm (formulaTerm)) {
string name ((char*) YAP_AtomName (YAP_AtomOfTerm (formulaTerm)));
Symbol functor = LiftedUtils::getSymbol (name);
formulas.push_back (ProbFormula (functor, ranges[count]));
} else {
LogVars logVars;
YAP_Functor yapFunctor = YAP_FunctorOfTerm (formulaTerm);
string name ((char*) YAP_AtomName (YAP_NameOfFunctor (yapFunctor)));
Symbol functor = LiftedUtils::getSymbol (name);
unsigned arity = (unsigned) YAP_ArityOfFunctor (yapFunctor);
for (unsigned i = 1; i <= arity; i++) {
YAP_Term ti = YAP_ArgOfTerm (i, formulaTerm);
unordered_map<YAP_Term, LogVar>::iterator it = lvMap.find (ti);
if (it != lvMap.end()) {
logVars.push_back (it->second);
} else {
unsigned newLv = lvMap.size();
lvMap[ti] = newLv;
logVars.push_back (newLv);
}
}
formulas.push_back (ProbFormula (functor, logVars, ranges[count]));
}
count ++;
pvList = YAP_TailOfTerm (pvList);
}
// read the parameters
const Params& params = readParams (YAP_ArgOfTerm (4, parfactor));
// read the constraint
Tuples tuples;
if (lvMap.size() >= 1) {
YAP_Term tupleList = YAP_ArgOfTerm (5, parfactor);
while (tupleList != YAP_TermNil()) {
YAP_Term term = YAP_HeadOfTerm (tupleList);
assert (YAP_IsApplTerm (term));
YAP_Functor yapFunctor = YAP_FunctorOfTerm (term);
unsigned arity = (unsigned) YAP_ArityOfFunctor (yapFunctor);
assert (lvMap.size() == arity);
Tuple tuple (arity);
for (unsigned i = 1; i <= arity; i++) {
YAP_Term ti = YAP_ArgOfTerm (i, term);
if (YAP_IsAtomTerm (ti) == false) {
cerr << "error: bad formed constraint" << endl;
abort();
}
string name ((char*) YAP_AtomName (YAP_AtomOfTerm (ti)));
tuple[i - 1] = LiftedUtils::getSymbol (name);
}
tuples.push_back (tuple);
tupleList = YAP_TailOfTerm (tupleList);
}
}
parfactors.push_back (new Parfactor (formulas, params, tuples, distId));
parfactorList = YAP_TailOfTerm (parfactorList);
}
// LiftedUtils::printSymbolDictionary();
cout << "*******************************************************" << endl;
cout << "INITIAL PARFACTORS" << endl;
cout << "*******************************************************" << endl;
for (unsigned i = 0; i < parfactors.size(); i++) {
parfactors[i]->print();
cout << endl;
}
ParfactorList* pfList = new ParfactorList();
for (unsigned i = 0; i < parfactors.size(); i++) {
pfList->add (parfactors[i]);
}
cout << endl;
cout << "*******************************************************" << endl;
cout << "SHATTERED PARFACTORS" << endl;
cout << "*******************************************************" << endl;
pfList->shatter();
pfList->print();
// insert the evidence
ObservedFormulas obsFormulas;
YAP_Term observedList = YAP_ARG2;
while (observedList != YAP_TermNil()) {
YAP_Term pair = YAP_HeadOfTerm (observedList);
YAP_Term ground = YAP_ArgOfTerm (1, pair);
Symbol functor;
Symbols args;
if (YAP_IsAtomTerm (ground)) {
string name ((char*) YAP_AtomName (YAP_AtomOfTerm (ground)));
functor = LiftedUtils::getSymbol (name);
} else {
assert (YAP_IsApplTerm (ground));
YAP_Functor yapFunctor = YAP_FunctorOfTerm (ground);
string name ((char*) (YAP_AtomName (YAP_NameOfFunctor (yapFunctor))));
functor = LiftedUtils::getSymbol (name);
unsigned arity = (unsigned) YAP_ArityOfFunctor (yapFunctor);
for (unsigned i = 1; i <= arity; i++) {
YAP_Term ti = YAP_ArgOfTerm (i, ground);
assert (YAP_IsAtomTerm (ti));
string arg ((char *) YAP_AtomName (YAP_AtomOfTerm (ti)));
args.push_back (LiftedUtils::getSymbol (arg));
}
}
unsigned evidence = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (2, pair));
bool found = false;
for (unsigned i = 0; i < obsFormulas.size(); i++) {
if (obsFormulas[i]->functor() == functor &&
obsFormulas[i]->arity() == args.size() &&
obsFormulas[i]->evidence() == evidence) {
obsFormulas[i]->addTuple (args);
found = true;
}
}
if (found == false) {
obsFormulas.push_back (new ObservedFormula (functor, evidence, args));
}
observedList = YAP_TailOfTerm (observedList);
}
FoveSolver::absorveEvidence (*pfList, obsFormulas);
YAP_Int p = (YAP_Int) (pfList);
return YAP_Unify (YAP_MkIntTerm (p), YAP_ARG3);
}
int int
createNetwork (void) createGroundNetwork (void)
{ {
Statistics::incrementPrimaryNetworksCounting(); Statistics::incrementPrimaryNetworksCounting();
// cout << "creating network number " ; // cout << "creating network number " ;
@ -29,15 +187,15 @@ createNetwork (void)
BayesNet* bn = new BayesNet(); BayesNet* bn = new BayesNet();
YAP_Term varList = YAP_ARG1; YAP_Term varList = YAP_ARG1;
BnNodeSet nodes; BnNodeSet nodes;
vector<VarIdSet> parents; vector<VarIds> parents;
while (varList != YAP_TermNil()) { while (varList != YAP_TermNil()) {
YAP_Term var = YAP_HeadOfTerm (varList); YAP_Term var = YAP_HeadOfTerm (varList);
VarId vid = (VarId) YAP_IntOfTerm (YAP_ArgOfTerm (1, var)); VarId vid = (VarId) YAP_IntOfTerm (YAP_ArgOfTerm (1, var));
unsigned dsize = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (2, var)); unsigned dsize = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (2, var));
int evidence = (int) YAP_IntOfTerm (YAP_ArgOfTerm (3, var)); int evidence = (int) YAP_IntOfTerm (YAP_ArgOfTerm (3, var));
YAP_Term parentL = YAP_ArgOfTerm (4, var); YAP_Term parentL = YAP_ArgOfTerm (4, var);
unsigned distId = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (5, var)); unsigned distId = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (5, var));
parents.push_back (VarIdSet()); parents.push_back (VarIds());
while (parentL != YAP_TermNil()) { while (parentL != YAP_TermNil()) {
unsigned parentId = (unsigned) YAP_IntOfTerm (YAP_HeadOfTerm (parentL)); unsigned parentId = (unsigned) YAP_IntOfTerm (YAP_HeadOfTerm (parentL));
parents.back().push_back (parentId); parents.back().push_back (parentId);
@ -67,6 +225,211 @@ createNetwork (void)
int
setBayesNetParams (void)
{
BayesNet* bn = (BayesNet*) YAP_IntOfTerm (YAP_ARG1);
YAP_Term distList = YAP_ARG2;
while (distList != YAP_TermNil()) {
YAP_Term dist = YAP_HeadOfTerm (distList);
unsigned distId = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (1, dist));
const Params params = readParams (YAP_ArgOfTerm (2, dist));
bn->getDistribution(distId)->updateParameters (params);
distList = YAP_TailOfTerm (distList);
}
return TRUE;
}
int
setParfactorGraphParams (void)
{
// FIXME
// ParfactorGraph* pfg = (ParfactorGraph*) YAP_IntOfTerm (YAP_ARG1);
YAP_Term distList = YAP_ARG2;
while (distList != YAP_TermNil()) {
// YAP_Term dist = YAP_HeadOfTerm (distList);
// unsigned distId = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (1, dist));
// const Params params = readParams (YAP_ArgOfTerm (2, dist));
// pfg->getDistribution(distId)->setData (params);
distList = YAP_TailOfTerm (distList);
}
return TRUE;
}
Params
readParams (YAP_Term paramL)
{
Params params;
while (paramL!= YAP_TermNil()) {
params.push_back ((double) YAP_FloatOfTerm (YAP_HeadOfTerm (paramL)));
paramL = YAP_TailOfTerm (paramL);
}
if (Globals::logDomain) {
Util::toLog (params);
}
return params;
}
int
runLiftedSolver (void)
{
ParfactorList* pfList = (ParfactorList*) YAP_IntOfTerm (YAP_ARG1);
YAP_Term taskList = YAP_ARG2;
vector<Params> results;
while (taskList != YAP_TermNil()) {
YAP_Term jointList = YAP_HeadOfTerm (taskList);
Grounds queryVars;
assert (YAP_IsPairTerm (taskList));
assert (YAP_IsPairTerm (jointList));
while (jointList != YAP_TermNil()) {
YAP_Term ground = YAP_HeadOfTerm (jointList);
if (YAP_IsAtomTerm (ground)) {
string name ((char*) YAP_AtomName (YAP_AtomOfTerm (ground)));
queryVars.push_back (Ground (LiftedUtils::getSymbol (name)));
} else {
assert (YAP_IsApplTerm (ground));
YAP_Functor yapFunctor = YAP_FunctorOfTerm (ground);
string name ((char*) (YAP_AtomName (YAP_NameOfFunctor (yapFunctor))));
unsigned arity = (unsigned) YAP_ArityOfFunctor (yapFunctor);
Symbol functor = LiftedUtils::getSymbol (name);
Symbols args;
for (unsigned i = 1; i <= arity; i++) {
YAP_Term ti = YAP_ArgOfTerm (i, ground);
assert (YAP_IsAtomTerm (ti));
string arg ((char *) YAP_AtomName (YAP_AtomOfTerm (ti)));
args.push_back (LiftedUtils::getSymbol (arg));
}
queryVars.push_back (Ground (functor, args));
}
jointList = YAP_TailOfTerm (jointList);
}
FoveSolver solver (pfList);
if (queryVars.size() == 1) {
results.push_back (solver.getPosterioriOf (queryVars[0]));
} else {
assert (false); // TODO joint dist
}
taskList = YAP_TailOfTerm (taskList);
}
YAP_Term list = YAP_TermNil();
for (int i = results.size() - 1; i >= 0; i--) {
const Params& beliefs = results[i];
YAP_Term queryBeliefsL = YAP_TermNil();
for (int j = beliefs.size() - 1; j >= 0; j--) {
YAP_Int sl1 = YAP_InitSlot (list);
YAP_Term belief = YAP_MkFloatTerm (beliefs[j]);
queryBeliefsL = YAP_MkPairTerm (belief, queryBeliefsL);
list = YAP_GetFromSlot (sl1);
YAP_RecoverSlots (1);
}
list = YAP_MkPairTerm (queryBeliefsL, list);
}
return YAP_Unify (list, YAP_ARG3);
}
int
runOtherSolvers (void)
{
BayesNet* bn = (BayesNet*) YAP_IntOfTerm (YAP_ARG1);
YAP_Term taskList = YAP_ARG2;
vector<VarIds> tasks;
std::set<VarId> vids;
while (taskList != YAP_TermNil()) {
if (YAP_IsPairTerm (YAP_HeadOfTerm (taskList))) {
tasks.push_back (VarIds());
YAP_Term jointList = YAP_HeadOfTerm (taskList);
while (jointList != YAP_TermNil()) {
VarId vid = (unsigned) YAP_IntOfTerm (YAP_HeadOfTerm (jointList));
assert (bn->getBayesNode (vid));
tasks.back().push_back (vid);
vids.insert (vid);
jointList = YAP_TailOfTerm (jointList);
}
} else {
VarId vid = (unsigned) YAP_IntOfTerm (YAP_HeadOfTerm (taskList));
assert (bn->getBayesNode (vid));
tasks.push_back (VarIds() = {vid});
vids.insert (vid);
}
taskList = YAP_TailOfTerm (taskList);
}
Solver* bpSolver = 0;
GraphicalModel* graphicalModel = 0;
CFactorGraph::checkForIdenticalFactors = false;
if (InfAlgorithms::infAlgorithm != InfAlgorithms::VE) {
BayesNet* mrn = bn->getMinimalRequesiteNetwork (
VarIds (vids.begin(), vids.end()));
if (InfAlgorithms::infAlgorithm == InfAlgorithms::BN_BP) {
graphicalModel = mrn;
bpSolver = new BnBpSolver (*static_cast<BayesNet*> (graphicalModel));
} else if (InfAlgorithms::infAlgorithm == InfAlgorithms::FG_BP) {
graphicalModel = new FactorGraph (*mrn);
bpSolver = new FgBpSolver (*static_cast<FactorGraph*> (graphicalModel));
delete mrn;
} else if (InfAlgorithms::infAlgorithm == InfAlgorithms::CBP) {
graphicalModel = new FactorGraph (*mrn);
bpSolver = new CbpSolver (*static_cast<FactorGraph*> (graphicalModel));
delete mrn;
}
bpSolver->runSolver();
}
vector<Params> results;
results.reserve (tasks.size());
for (unsigned i = 0; i < tasks.size(); i++) {
//if (i == 1) exit (0);
if (InfAlgorithms::infAlgorithm == InfAlgorithms::VE) {
BayesNet* mrn = bn->getMinimalRequesiteNetwork (tasks[i]);
VarElimSolver* veSolver = new VarElimSolver (*mrn);
if (tasks[i].size() == 1) {
results.push_back (veSolver->getPosterioriOf (tasks[i][0]));
} else {
results.push_back (veSolver->getJointDistributionOf (tasks[i]));
}
delete mrn;
delete veSolver;
} else {
if (tasks[i].size() == 1) {
results.push_back (bpSolver->getPosterioriOf (tasks[i][0]));
} else {
results.push_back (bpSolver->getJointDistributionOf (tasks[i]));
}
}
}
delete bpSolver;
delete graphicalModel;
YAP_Term list = YAP_TermNil();
for (int i = results.size() - 1; i >= 0; i--) {
const Params& beliefs = results[i];
YAP_Term queryBeliefsL = YAP_TermNil();
for (int j = beliefs.size() - 1; j >= 0; j--) {
YAP_Int sl1 = YAP_InitSlot (list);
YAP_Term belief = YAP_MkFloatTerm (beliefs[j]);
queryBeliefsL = YAP_MkPairTerm (belief, queryBeliefsL);
list = YAP_GetFromSlot (sl1);
YAP_RecoverSlots (1);
}
list = YAP_MkPairTerm (queryBeliefsL, list);
}
return YAP_Unify (list, YAP_ARG3);
}
int int
setExtraVarsInfo (void) setExtraVarsInfo (void)
{ {
@ -94,124 +457,7 @@ setExtraVarsInfo (void)
int int
setParameters (void) setHorusFlag (void)
{
BayesNet* bn = (BayesNet*) YAP_IntOfTerm (YAP_ARG1);
YAP_Term distList = YAP_ARG2;
while (distList != YAP_TermNil()) {
YAP_Term dist = YAP_HeadOfTerm (distList);
unsigned distId = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (1, dist));
YAP_Term paramL = YAP_ArgOfTerm (2, dist);
ParamSet params;
while (paramL!= YAP_TermNil()) {
params.push_back ((double) YAP_FloatOfTerm (YAP_HeadOfTerm (paramL)));
paramL = YAP_TailOfTerm (paramL);
}
if (NSPACE == NumberSpace::LOGARITHM) {
Util::toLog (params);
}
bn->getDistribution(distId)->updateParameters (params);
distList = YAP_TailOfTerm (distList);
}
return TRUE;
}
int
runSolver (void)
{
BayesNet* bn = (BayesNet*) YAP_IntOfTerm (YAP_ARG1);
YAP_Term taskList = YAP_ARG2;
vector<VarIdSet> tasks;
std::set<VarId> vids;
while (taskList != YAP_TermNil()) {
if (YAP_IsPairTerm (YAP_HeadOfTerm (taskList))) {
tasks.push_back (VarIdSet());
YAP_Term jointList = YAP_HeadOfTerm (taskList);
while (jointList != YAP_TermNil()) {
VarId vid = (unsigned) YAP_IntOfTerm (YAP_HeadOfTerm (jointList));
assert (bn->getBayesNode (vid));
tasks.back().push_back (vid);
vids.insert (vid);
jointList = YAP_TailOfTerm (jointList);
}
} else {
VarId vid = (unsigned) YAP_IntOfTerm (YAP_HeadOfTerm (taskList));
assert (bn->getBayesNode (vid));
tasks.push_back (VarIdSet() = {vid});
vids.insert (vid);
}
taskList = YAP_TailOfTerm (taskList);
}
Solver* bpSolver = 0;
GraphicalModel* graphicalModel = 0;
CFactorGraph::disableCheckForIdenticalFactors();
if (InfAlgorithms::infAlgorithm != InfAlgorithms::VE) {
BayesNet* mrn = bn->getMinimalRequesiteNetwork (
VarIdSet (vids.begin(), vids.end()));
if (InfAlgorithms::infAlgorithm == InfAlgorithms::BN_BP) {
graphicalModel = mrn;
bpSolver = new BnBpSolver (*static_cast<BayesNet*> (graphicalModel));
} else if (InfAlgorithms::infAlgorithm == InfAlgorithms::FG_BP) {
graphicalModel = new FactorGraph (*mrn);
bpSolver = new FgBpSolver (*static_cast<FactorGraph*> (graphicalModel));
delete mrn;
} else if (InfAlgorithms::infAlgorithm == InfAlgorithms::CBP) {
graphicalModel = new FactorGraph (*mrn);
bpSolver = new CbpSolver (*static_cast<FactorGraph*> (graphicalModel));
delete mrn;
}
bpSolver->runSolver();
}
vector<ParamSet> results;
results.reserve (tasks.size());
for (unsigned i = 0; i < tasks.size(); i++) {
//if (i == 1) exit (0);
if (InfAlgorithms::infAlgorithm == InfAlgorithms::VE) {
BayesNet* mrn = bn->getMinimalRequesiteNetwork (tasks[i]);
VarElimSolver* veSolver = new VarElimSolver (*mrn);
if (tasks[i].size() == 1) {
results.push_back (veSolver->getPosterioriOf (tasks[i][0]));
} else {
results.push_back (veSolver->getJointDistributionOf (tasks[i]));
}
delete mrn;
delete veSolver;
} else {
if (tasks[i].size() == 1) {
results.push_back (bpSolver->getPosterioriOf (tasks[i][0]));
} else {
results.push_back (bpSolver->getJointDistributionOf (tasks[i]));
}
}
}
delete bpSolver;
delete graphicalModel;
YAP_Term list = YAP_TermNil();
for (int i = results.size() - 1; i >= 0; i--) {
const ParamSet& beliefs = results[i];
YAP_Term queryBeliefsL = YAP_TermNil();
for (int j = beliefs.size() - 1; j >= 0; j--) {
YAP_Int sl1 = YAP_InitSlot (list);
YAP_Term belief = YAP_MkFloatTerm (beliefs[j]);
queryBeliefsL = YAP_MkPairTerm (belief, queryBeliefsL);
list = YAP_GetFromSlot (sl1);
YAP_RecoverSlots (1);
}
list = YAP_MkPairTerm (queryBeliefsL, list);
}
return YAP_Unify (list, YAP_ARG3);
}
int
setSolverParameter (void)
{ {
string key ((char*) YAP_AtomName (YAP_AtomOfTerm (YAP_ARG1))); string key ((char*) YAP_AtomName (YAP_AtomOfTerm (YAP_ARG1)));
if (key == "inf_alg") { if (key == "inf_alg") {
@ -263,12 +509,23 @@ setSolverParameter (void)
BpOptions::accuracy = (double) YAP_FloatOfTerm (YAP_ARG2); BpOptions::accuracy = (double) YAP_FloatOfTerm (YAP_ARG2);
} else if (key == "max_iter") { } else if (key == "max_iter") {
BpOptions::maxIter = (int) YAP_IntOfTerm (YAP_ARG2); BpOptions::maxIter = (int) YAP_IntOfTerm (YAP_ARG2);
} else if (key == "always_loopy_solver") { } else if (key == "use_logarithms") {
string value ((char*) YAP_AtomName (YAP_AtomOfTerm (YAP_ARG2))); string value ((char*) YAP_AtomName (YAP_AtomOfTerm (YAP_ARG2)));
if (value == "true") { if ( value == "true") {
BpOptions::useAlwaysLoopySolver = true; Globals::logDomain = true;
} else if (value == "false") { } else if (value == "false") {
BpOptions::useAlwaysLoopySolver = false; Globals::logDomain = false;
} else {
cerr << "warning: invalid value `" << value << "' " ;
cerr << "for `" << key << "'" << endl;
return FALSE;
}
} else if (key == "order_factor_variables") {
string value ((char*) YAP_AtomName (YAP_AtomOfTerm (YAP_ARG2)));
if ( value == "true") {
FactorGraph::orderFactorVariables = true;
} else if (value == "false") {
FactorGraph::orderFactorVariables = false;
} else { } else {
cerr << "warning: invalid value `" << value << "' " ; cerr << "warning: invalid value `" << value << "' " ;
cerr << "for `" << key << "'" << endl; cerr << "for `" << key << "'" << endl;
@ -283,14 +540,6 @@ setSolverParameter (void)
int useLogSpace (void)
{
NSPACE = NumberSpace::LOGARITHM;
return TRUE;
}
int int
freeBayesNetwork (void) freeBayesNetwork (void)
{ {
@ -303,15 +552,27 @@ freeBayesNetwork (void)
int
freeParfactorGraph (void)
{
delete (ParfactorList*) YAP_IntOfTerm (YAP_ARG1);
return TRUE;
}
extern "C" void extern "C" void
init_predicates (void) init_predicates (void)
{ {
YAP_UserCPredicate ("create_network", createNetwork, 2); YAP_UserCPredicate ("create_lifted_network", createLiftedNetwork, 3);
YAP_UserCPredicate ("set_extra_vars_info", setExtraVarsInfo, 2); YAP_UserCPredicate ("create_ground_network", createGroundNetwork, 2);
YAP_UserCPredicate ("set_parameters", setParameters, 2); YAP_UserCPredicate ("set_parfactor_graph_params", setParfactorGraphParams, 2);
YAP_UserCPredicate ("run_solver", runSolver, 3); YAP_UserCPredicate ("set_bayes_net_params", setBayesNetParams, 2);
YAP_UserCPredicate ("set_solver_parameter", setSolverParameter, 2); YAP_UserCPredicate ("run_lifted_solver", runLiftedSolver, 3);
YAP_UserCPredicate ("use_log_space", useLogSpace, 0); YAP_UserCPredicate ("run_other_solvers", runOtherSolvers, 3);
YAP_UserCPredicate ("free_bayesian_network", freeBayesNetwork, 1); YAP_UserCPredicate ("set_extra_vars_info", setExtraVarsInfo, 2);
YAP_UserCPredicate ("set_horus_flag", setHorusFlag, 2);
YAP_UserCPredicate ("free_bayesian_network", freeBayesNetwork, 1);
YAP_UserCPredicate ("free_parfactor_graph", freeParfactorGraph, 1);
} }

View File

@ -0,0 +1,301 @@
#ifndef HORUS_STATESINDEXER_H
#define HORUS_STATESINDEXER_H
#include <algorithm>
#include <numeric>
#include <functional>
#include <sstream>
#include <iomanip>
#include "VarNode.h"
#include "Util.h"
class StatesIndexer {
public:
StatesIndexer (const Ranges& ranges, bool calcOffsets = true)
{
size_ = 1;
indices_.resize (ranges.size(), 0);
ranges_ = ranges;
for (unsigned i = 0; i < ranges.size(); i++) {
size_ *= ranges[i];
}
li_ = 0;
if (calcOffsets) {
calculateOffsets();
}
}
StatesIndexer (const VarNodes& vars, bool calcOffsets = true)
{
size_ = 1;
indices_.resize (vars.size(), 0);
ranges_.reserve (vars.size());
for (unsigned i = 0; i < vars.size(); i++) {
ranges_.push_back (vars[i]->nrStates());
size_ *= vars[i]->nrStates();
}
li_ = 0;
if (calcOffsets) {
calculateOffsets();
}
}
void increment (void)
{
for (int i = ranges_.size() - 1; i >= 0; i--) {
indices_[i] ++;
if (indices_[i] != ranges_[i]) {
break;
} else {
indices_[i] = 0;
}
}
li_ ++;
}
void increment (unsigned dim)
{
assert (dim < ranges_.size());
assert (ranges_.size() == offsets_.size());
assert (indices_[dim] < ranges_[dim]);
indices_[dim] ++;
li_ += offsets_[dim];
}
void incrementExcluding (unsigned skipDim)
{
assert (ranges_.size() == offsets_.size());
for (int i = ranges_.size() - 1; i >= 0; i--) {
if (i != (int)skipDim) {
indices_[i] ++;
li_ += offsets_[i];
if (indices_[i] != ranges_[i]) {
return;
} else {
indices_[i] = 0;
li_ -= offsets_[i] * ranges_[i];
}
}
}
li_ = size_;
}
unsigned linearIndex (void) const
{
return li_;
}
const vector<unsigned>& indices (void) const
{
return indices_;
}
StatesIndexer& operator ++ (void)
{
increment();
return *this;
}
operator unsigned (void) const
{
return li_;
}
unsigned operator[] (unsigned dim) const
{
assert (valid());
assert (dim < ranges_.size());
return indices_[dim];
}
bool valid (void) const
{
return li_ < size_;
}
void reset (void)
{
std::fill (indices_.begin(), indices_.end(), 0);
li_ = 0;
}
void reset (unsigned dim)
{
indices_[dim] = 0;
li_ -= offsets_[dim] * ranges_[dim];
}
unsigned size (void) const
{
return size_ ;
}
friend ostream& operator<< (ostream &out, const StatesIndexer& idx)
{
out << "(" << std::setw (2) << std::setfill('0') << idx.li_ << ") " ;
out << idx.indices_;
return out;
}
private:
void calculateOffsets (void)
{
unsigned prod = 1;
offsets_.resize (ranges_.size());
for (int i = ranges_.size() - 1; i >= 0; i--) {
offsets_[i] = prod;
prod *= ranges_[i];
}
}
unsigned li_;
unsigned size_;
vector<unsigned> indices_;
vector<unsigned> ranges_;
vector<unsigned> offsets_;
};
class MapIndexer
{
public:
MapIndexer (const Ranges& ranges, const vector<bool>& mapDims)
{
assert (ranges.size() == mapDims.size());
unsigned prod = 1;
offsets_.resize (ranges.size());
for (int i = ranges.size() - 1; i >= 0; i--) {
if (mapDims[i]) {
offsets_[i] = prod;
prod *= ranges[i];
}
}
indices_.resize (ranges.size(), 0);
ranges_ = ranges;
index_ = 0;
valid_ = true;
}
MapIndexer (const Ranges& ranges, unsigned ignoreDim)
{
unsigned prod = 1;
offsets_.resize (ranges.size());
for (int i = ranges.size() - 1; i >= 0; i--) {
if (i != (int)ignoreDim) {
offsets_[i] = prod;
prod *= ranges[i];
}
}
indices_.resize (ranges.size(), 0);
ranges_ = ranges;
index_ = 0;
valid_ = true;
}
/*
MapIndexer (
const VarIds& loopVids,
const Ranges& loopRanges,
const VarIds& mapVids,
const Ranges& mapRanges)
{
unsigned prod = 1;
vector<unsigned> offsets (mapRanges.size());
for (int i = mapRanges.size() - 1; i >= 0; i--) {
offsets[i] = prod;
prod *= mapRanges[i];
}
offsets_.reserve (loopVids.size());
for (unsigned i = 0; i < loopVids.size(); i++) {
VarIds::const_iterator it =
std::find (mapVids.begin(), mapVids.end(), loopVids[i]);
if (it != mapVids.end()) {
offsets_.push_back (offsets[it - mapVids.begin()]);
} else {
offsets_.push_back (0);
}
}
indices_.resize (loopVids.size(), 0);
ranges_ = loopRanges;
index_ = 0;
size_ = prod;
}
*/
MapIndexer& operator ++ (void)
{
assert (valid_);
for (int i = ranges_.size() - 1; i >= 0; i--) {
indices_[i] ++;
index_ += offsets_[i];
if (indices_[i] != ranges_[i]) {
return *this;
} else {
indices_[i] = 0;
index_ -= offsets_[i] * ranges_[i];
}
}
valid_ = false;
return *this;
}
unsigned mappedIndex (void) const
{
return index_;
}
operator unsigned (void) const
{
return index_;
}
unsigned operator[] (unsigned dim) const
{
assert (valid());
assert (dim < ranges_.size());
return indices_[dim];
}
bool valid (void) const
{
return valid_;
}
void reset (void)
{
std::fill (indices_.begin(), indices_.end(), 0);
index_ = 0;
}
friend ostream& operator<< (ostream &out, const MapIndexer& idx)
{
out << "(" << std::setw (2) << std::setfill('0') << idx.index_ << ") " ;
out << idx.indices_;
return out;
}
private:
MapIndexer (const Ranges& ranges) :
ranges_(ranges),
indices_(ranges.size(), 0),
offsets_(ranges.size())
{
index_ = 0;
}
unsigned index_;
bool valid_;
vector<unsigned> ranges_;
vector<unsigned> indices_;
vector<unsigned> offsets_;
};
#endif // HORUS_STATESINDEXER_H

View File

@ -0,0 +1,120 @@
#include <cassert>
#include <algorithm>
#include <iostream>
#include <sstream>
#include "LiftedUtils.h"
#include "ConstraintTree.h"
namespace LiftedUtils {
unordered_map<string, unsigned> symbolDict;
Symbol
getSymbol (const string& symbolName)
{
unordered_map<string, unsigned>::iterator it
= symbolDict.find (symbolName);
if (it != symbolDict.end()) {
return it->second;
} else {
symbolDict[symbolName] = symbolDict.size() - 1;
return symbolDict.size() - 1;
}
}
void
printSymbolDictionary (void)
{
unordered_map<string, unsigned>::const_iterator it
= symbolDict.begin();
while (it != symbolDict.end()) {
cout << it->first << " -> " << it->second << endl;
it ++;
}
}
}
ostream& operator<< (ostream &os, const Symbol& s)
{
unordered_map<string, unsigned>::const_iterator it
= LiftedUtils::symbolDict.begin();
while (it != LiftedUtils::symbolDict.end() && it->second != s) {
it ++;
}
assert (it != LiftedUtils::symbolDict.end());
os << it->first;
return os;
}
ostream& operator<< (ostream &os, const LogVar& X)
{
const string labels[] = {
"A", "B", "C", "D", "E", "F",
"G", "H", "I", "J", "K", "M" };
(X >= 12) ? os << "X_" << X.id_ : os << labels[X];
return os;
}
ostream& operator<< (ostream &os, const Tuple& t)
{
os << "(" ;
for (unsigned i = 0; i < t.size(); i++) {
os << ((i != 0) ? "," : "") << t[i];
}
os << ")" ;
return os;
}
ostream& operator<< (ostream &os, const Ground& gr)
{
os << gr.functor();
os << "(" ;
for (unsigned i = 0; i < gr.args().size(); i++) {
if (i != 0) os << ", " ;
os << gr.args()[i];
}
os << ")" ;
return os;
}
void
ObservedFormula::addTuple (const Tuple& t)
{
if (constr_ == 0) {
LogVars lvs (arity_);
for (unsigned i = 0; i < arity_; i++) {
lvs[i] = i;
}
constr_ = new ConstraintTree (lvs);
}
constr_->addTuple (t);
}
ostream& operator<< (ostream &os, const ObservedFormula of)
{
os << of.functor_ << "/" << of.arity_;
os << "|" << of.constr_->tupleSet();
os << " [evidence=" << of.evidence_ << "]";
return os;
}

View File

@ -0,0 +1,161 @@
#ifndef HORUS_LIFTEDUTILS_H
#define HORUS_LIFTEDUTILS_H
#include <limits>
#include <string>
#include <vector>
#include <unordered_map>
#include "TinySet.h"
#include "Util.h"
using namespace std;
class Symbol
{
public:
Symbol (void) : id_(numeric_limits<unsigned>::max()) { }
Symbol (unsigned id) : id_(id) { }
operator unsigned (void) const { return id_; }
bool valid (void) const { return id_ != numeric_limits<unsigned>::max(); }
static Symbol invalid (void) { return Symbol(); }
friend ostream& operator<< (ostream &os, const Symbol& s);
private:
unsigned id_;
};
class LogVar
{
public:
LogVar (void) : id_(numeric_limits<unsigned>::max()) { }
LogVar (unsigned id) : id_(id) { }
operator unsigned (void) const { return id_; }
LogVar& operator++ (void)
{
assert (valid());
id_ ++;
return *this;
}
bool valid (void) const
{
return id_ != numeric_limits<unsigned>::max();
}
friend ostream& operator<< (ostream &os, const LogVar& X);
private:
unsigned id_;
};
namespace std {
template <> struct hash<Symbol> {
size_t operator() (const Symbol& s) const {
return std::hash<unsigned>() (s);
}};
template <> struct hash<LogVar> {
size_t operator() (const LogVar& X) const {
return std::hash<unsigned>() (X);
}};
};
typedef vector<Symbol> Symbols;
typedef vector<Symbol> Tuple;
typedef vector<Tuple> Tuples;
typedef vector<LogVar> LogVars;
typedef TinySet<Symbol> SymbolSet;
typedef TinySet<LogVar> LogVarSet;
typedef TinySet<Tuple> TupleSet;
ostream& operator<< (ostream &os, const Tuple& t);
namespace LiftedUtils {
Symbol getSymbol (const string&);
void printSymbolDictionary (void);
}
class Ground
{
public:
Ground (Symbol f) : functor_(f) { }
Ground (Symbol f, const Symbols& args) : functor_(f), args_(args) { }
Symbol functor (void) const { return functor_; }
Symbols args (void) const { return args_; }
unsigned arity (void) const { return args_.size(); }
bool isAtom (void) const { return args_.size() == 0; }
friend ostream& operator<< (ostream &os, const Ground& gr);
private:
Symbol functor_;
Symbols args_;
};
typedef vector<Ground> Grounds;
class ConstraintTree;
class ObservedFormula
{
public:
ObservedFormula (Symbol f, unsigned a, unsigned ev)
: functor_(f), arity_(a), evidence_(ev), constr_(0) { }
ObservedFormula (Symbol f, unsigned ev, const Tuple& tuple)
: functor_(f), arity_(tuple.size()), evidence_(ev), constr_(0)
{
addTuple (tuple);
}
Symbol functor (void) const { return functor_; }
unsigned arity (void) const { return arity_; }
unsigned evidence (void) const { return evidence_; }
ConstraintTree* constr (void) const { return constr_; }
bool isAtom (void) const { return arity_ == 0; }
void addTuple (const Tuple& t);
friend ostream& operator<< (ostream &os, const ObservedFormula opv);
private:
Symbol functor_;
unsigned arity_;
unsigned evidence_;
ConstraintTree* constr_;
};
typedef vector<ObservedFormula*> ObservedFormulas;
class Substitution
{
public:
void add (LogVar X_old, LogVar X_new)
{
subs_.insert (make_pair (X_old, X_new));
}
void rename (LogVar X_old, LogVar X_new)
{
assert (subs_.find (X_old) != subs_.end());
subs_.find (X_old)->second = X_new;
}
LogVar newNameFor (LogVar X) const
{
assert (subs_.find (X) != subs_.end());
return subs_.find (X)->second;
}
private:
unordered_map<LogVar, LogVar> subs_;
};
#endif // HORUS_LIFTEDUTILS_H

View File

@ -23,10 +23,10 @@ CC=@CC@
CXX=@CXX@ CXX=@CXX@
# normal # normal
CXXFLAGS= -std=c++0x @SHLIB_CXXFLAGS@ $(YAP_EXTRAS) $(DEFS) -D_YAP_NOT_INSTALLED_=1 -I$(srcdir) -I../../../.. -I$(srcdir)/../../../../include @CPPFLAGS@ -DNDEBUG #CXXFLAGS= -std=c++0x @SHLIB_CXXFLAGS@ $(YAP_EXTRAS) $(DEFS) -D_YAP_NOT_INSTALLED_=1 -I$(srcdir) -I../../../.. -I$(srcdir)/../../../../include @CPPFLAGS@ -DNDEBUG
# debug # debug
#CXXFLAGS= -std=c++0x @SHLIB_CXXFLAGS@ $(YAP_EXTRAS) $(DEFS) -D_YAP_NOT_INSTALLED_=1 -I$(srcdir) -I../../../.. -I$(srcdir)/../../../../include @CPPFLAGS@ -g -O0 -Wextra CXXFLAGS= -std=c++0x @SHLIB_CXXFLAGS@ $(YAP_EXTRAS) $(DEFS) -D_YAP_NOT_INSTALLED_=1 -I$(srcdir) -I../../../.. -I$(srcdir)/../../../../include @CPPFLAGS@ -g -O0 -Wextra
# #
@ -46,24 +46,32 @@ CWD=$(PWD)
HEADERS = \ HEADERS = \
$(srcdir)/GraphicalModel.h \ $(srcdir)/GraphicalModel.h \
$(srcdir)/VarNode.h \
$(srcdir)/Distribution.h \
$(srcdir)/BayesNet.h \ $(srcdir)/BayesNet.h \
$(srcdir)/BayesNode.h \ $(srcdir)/BayesNode.h \
$(srcdir)/ElimGraph.h \ $(srcdir)/ElimGraph.h \
$(srcdir)/CFactorGraph.h \
$(srcdir)/CptEntry.h \
$(srcdir)/FactorGraph.h \ $(srcdir)/FactorGraph.h \
$(srcdir)/Factor.h \ $(srcdir)/Factor.h \
$(srcdir)/CFactorGraph.h \
$(srcdir)/ConstraintTree.h \
$(srcdir)/Solver.h \ $(srcdir)/Solver.h \
$(srcdir)/VarElimSolver.h \ $(srcdir)/VarElimSolver.h \
$(srcdir)/BnBpSolver.h \ $(srcdir)/BnBpSolver.h \
$(srcdir)/FgBpSolver.h \ $(srcdir)/FgBpSolver.h \
$(srcdir)/CbpSolver.h \ $(srcdir)/CbpSolver.h \
$(srcdir)/Shared.h \ $(srcdir)/FoveSolver.h \
$(srcdir)/StatesIndexer.h \ $(srcdir)/VarNode.h \
$(srcdir)/Distribution.h \
$(srcdir)/Indexer.h \
$(srcdir)/Parfactor.h \
$(srcdir)/ProbFormula.h \
$(srcdir)/Histogram.h \
$(srcdir)/ParfactorList.h \
$(srcdir)/LiftedUtils.h \
$(srcdir)/TinySet.h \
$(srcdir)/Util.h \
$(srcdir)/Horus.h \
$(srcdir)/xmlParser/xmlParser.h $(srcdir)/xmlParser/xmlParser.h
CPP_SOURCES = \ CPP_SOURCES = \
$(srcdir)/BayesNet.cpp \ $(srcdir)/BayesNet.cpp \
$(srcdir)/BayesNode.cpp \ $(srcdir)/BayesNode.cpp \
@ -71,12 +79,19 @@ CPP_SOURCES = \
$(srcdir)/FactorGraph.cpp \ $(srcdir)/FactorGraph.cpp \
$(srcdir)/Factor.cpp \ $(srcdir)/Factor.cpp \
$(srcdir)/CFactorGraph.cpp \ $(srcdir)/CFactorGraph.cpp \
$(srcdir)/ConstraintTree.cpp \
$(srcdir)/VarNode.cpp \ $(srcdir)/VarNode.cpp \
$(srcdir)/Solver.cpp \ $(srcdir)/Solver.cpp \
$(srcdir)/VarElimSolver.cpp \ $(srcdir)/VarElimSolver.cpp \
$(srcdir)/BnBpSolver.cpp \ $(srcdir)/BnBpSolver.cpp \
$(srcdir)/FgBpSolver.cpp \ $(srcdir)/FgBpSolver.cpp \
$(srcdir)/CbpSolver.cpp \ $(srcdir)/CbpSolver.cpp \
$(srcdir)/FoveSolver.cpp \
$(srcdir)/Parfactor.cpp \
$(srcdir)/ProbFormula.cpp \
$(srcdir)/Histogram.cpp \
$(srcdir)/ParfactorList.cpp \
$(srcdir)/LiftedUtils.cpp \
$(srcdir)/Util.cpp \ $(srcdir)/Util.cpp \
$(srcdir)/HorusYap.cpp \ $(srcdir)/HorusYap.cpp \
$(srcdir)/HorusCli.cpp \ $(srcdir)/HorusCli.cpp \
@ -89,12 +104,19 @@ OBJS = \
FactorGraph.o \ FactorGraph.o \
Factor.o \ Factor.o \
CFactorGraph.o \ CFactorGraph.o \
ConstraintTree.o \
VarNode.o \ VarNode.o \
Solver.o \ Solver.o \
VarElimSolver.o \ VarElimSolver.o \
BnBpSolver.o \ BnBpSolver.o \
FgBpSolver.o \ FgBpSolver.o \
CbpSolver.o \ CbpSolver.o \
FoveSolver.o \
Parfactor.o \
ProbFormula.o \
Histogram.o \
ParfactorList.o \
LiftedUtils.o \
Util.o \ Util.o \
HorusYap.o HorusYap.o
@ -105,12 +127,19 @@ HCLI_OBJS = \
FactorGraph.o \ FactorGraph.o \
Factor.o \ Factor.o \
CFactorGraph.o \ CFactorGraph.o \
ConstraintTree.o \
VarNode.o \ VarNode.o \
Solver.o \ Solver.o \
VarElimSolver.o \ VarElimSolver.o \
BnBpSolver.o \ BnBpSolver.o \
FgBpSolver.o \ FgBpSolver.o \
CbpSolver.o \ CbpSolver.o \
FoveSolver.o \
Parfactor.o \
ProbFormula.o \
Histogram.o \
ParfactorList.o \
LiftedUtils.o \
Util.o \ Util.o \
xmlParser/xmlParser.o \ xmlParser/xmlParser.o \
HorusCli.o HorusCli.o
@ -145,6 +174,10 @@ clean:
rm -f *.o *~ $(OBJS) $(SOBJS) *.BAK hcli xmlParser/*.o rm -f *.o *~ $(OBJS) $(SOBJS) *.BAK hcli xmlParser/*.o
erase_dots:
rm -f *.dot *.png
depend: $(HEADERS) $(CPP_SOURCES) depend: $(HEADERS) $(CPP_SOURCES)
-@if test "$(GCC)" = yes; then\ -@if test "$(GCC)" = yes; then\
$(CC) -std=c++0x -MM -MG $(CFLAGS) -I$(srcdir) -I$(srcdir)/../../../../include -I$(srcdir)/../../../../H $(CPP_SOURCES) >> Makefile;\ $(CC) -std=c++0x -MM -MG $(CFLAGS) -I$(srcdir) -I$(srcdir)/../../../../include -I$(srcdir)/../../../../H $(CPP_SOURCES) >> Makefile;\

View File

@ -0,0 +1,861 @@
#include "Parfactor.h"
#include "Histogram.h"
#include "Indexer.h"
#include "Horus.h"
Parfactor::Parfactor (
const ProbFormulas& formulas,
const Params& params,
const Tuples& tuples,
unsigned distId)
{
formulas_ = formulas;
params_ = params;
distId_ = distId;
LogVars logVars;
for (unsigned i = 0; i < formulas_.size(); i++) {
ranges_.push_back (formulas_[i].range());
const LogVars& lvs = formulas_[i].logVars();
for (unsigned j = 0; j < lvs.size(); j++) {
if (std::find (logVars.begin(), logVars.end(), lvs[j]) ==
logVars.end()) {
logVars.push_back (lvs[j]);
}
}
}
constr_ = new ConstraintTree (logVars, tuples);
}
Parfactor::Parfactor (const Parfactor* g, const Tuple& tuple)
{
formulas_ = g->formulas();
params_ = g->params();
ranges_ = g->ranges();
distId_ = g->distId();
constr_ = new ConstraintTree (g->logVars(), {tuple});
}
Parfactor::Parfactor (const Parfactor* g, ConstraintTree* constr)
{
formulas_ = g->formulas();
params_ = g->params();
ranges_ = g->ranges();
distId_ = g->distId();
constr_ = constr;
}
Parfactor::Parfactor (const Parfactor& g)
{
formulas_ = g.formulas();
params_ = g.params();
ranges_ = g.ranges();
distId_ = g.distId();
constr_ = new ConstraintTree (*g.constr());
}
Parfactor::~Parfactor (void)
{
delete constr_;
}
LogVarSet
Parfactor::countedLogVars (void) const
{
LogVarSet set;
for (unsigned i = 0; i < formulas_.size(); i++) {
if (formulas_[i].isCounting()) {
set.insert (formulas_[i].countedLogVar());
}
}
return set;
}
LogVarSet
Parfactor::uncountedLogVars (void) const
{
return constr_->logVarSet() - countedLogVars();
}
LogVarSet
Parfactor::elimLogVars (void) const
{
LogVarSet requiredToElim = constr_->logVarSet();
requiredToElim -= constr_->singletons();
requiredToElim -= countedLogVars();
return requiredToElim;
}
LogVarSet
Parfactor::exclusiveLogVars (unsigned fIdx) const
{
assert (fIdx < formulas_.size());
LogVarSet remaining;
for (unsigned i = 0; i < formulas_.size(); i++) {
if (i != fIdx) {
remaining |= formulas_[i].logVarSet();
}
}
return formulas_[fIdx].logVarSet() - remaining;
}
void
Parfactor::setConstraintTree (ConstraintTree* newTree)
{
delete constr_;
constr_ = newTree;
}
void
Parfactor::sumOut (unsigned fIdx)
{
assert (fIdx < formulas_.size());
assert (formulas_[fIdx].contains (elimLogVars()));
LogVarSet excl = exclusiveLogVars (fIdx);
unsigned condCount = constr_->getConditionalCount (excl);
Util::pow (params_, condCount);
vector<unsigned> numAssigns (ranges_[fIdx], 1);
if (formulas_[fIdx].isCounting()) {
unsigned N = constr_->getConditionalCount (
formulas_[fIdx].countedLogVar());
unsigned R = formulas_[fIdx].range();
unsigned H = ranges_[fIdx];
HistogramSet hs (N, R);
unsigned N_factorial = Util::factorial (N);
for (unsigned h = 0; h < H; h++) {
unsigned prod = 1;
for (unsigned r = 0; r < R; r++) {
prod *= Util::factorial (hs[r]);
}
numAssigns[h] = N_factorial / prod;
hs.nextHistogram();
}
cout << endl;
}
Params copy = params_;
params_.clear();
params_.resize (copy.size() / ranges_[fIdx], 0.0);
MapIndexer indexer (ranges_, fIdx);
for (unsigned i = 0; i < copy.size(); i++) {
unsigned h = indexer[fIdx];
// TODO NOT LOG DOMAIN AWARE :(
params_[indexer] += numAssigns[h] * copy[i];
++ indexer;
}
formulas_.erase (formulas_.begin() + fIdx);
ranges_.erase (ranges_.begin() + fIdx);
constr_->remove (excl);
}
void
Parfactor::multiply (Parfactor& g)
{
alignAndExponentiate (this, &g);
bool sharedVars = false;
vector<unsigned> g_varpos;
const ProbFormulas& g_formulas = g.formulas();
const Params& g_params = g.params();
const Ranges& g_ranges = g.ranges();
for (unsigned i = 0; i < g_formulas.size(); i++) {
int group = g_formulas[i].group();
if (indexOfFormulaWithGroup (group) == -1) {
insertDimension (g.ranges()[i]);
formulas_.push_back (g_formulas[i]);
g_varpos.push_back (formulas_.size() - 1);
} else {
sharedVars = true;
g_varpos.push_back (indexOfFormulaWithGroup (group));
}
}
if (sharedVars == false) {
unsigned count = 0;
for (unsigned i = 0; i < params_.size(); i++) {
if (Globals::logDomain) {
params_[i] += g_params[count];
} else {
params_[i] *= g_params[count];
}
count ++;
if (count >= g_params.size()) {
count = 0;
}
}
} else {
StatesIndexer indexer (ranges_, false);
while (indexer.valid()) {
unsigned g_li = 0;
unsigned prod = 1;
for (int j = g_varpos.size() - 1; j >= 0; j--) {
g_li += indexer[g_varpos[j]] * prod;
prod *= g_ranges[j];
}
if (Globals::logDomain) {
params_[indexer] += g_params[g_li];
} else {
params_[indexer] *= g_params[g_li];
}
++ indexer;
}
}
constr_->join (g.constr(), true);
}
void
Parfactor::countConvert (LogVar X)
{
int fIdx = indexOfFormulaWithLogVar (X);
assert (fIdx != -1);
assert (constr_->isCountNormalized (X));
assert (constr_->getConditionalCount (X) > 1);
assert (constr_->isCarteesianProduct (countedLogVars() | X));
unsigned N = constr_->getConditionalCount (X);
unsigned R = ranges_[fIdx];
unsigned H = HistogramSet::nrHistograms (N, R);
vector<Histogram> histograms = HistogramSet::getHistograms (N, R);
StatesIndexer indexer (ranges_);
vector<Params> summout (params_.size() / R);
unsigned count = 0;
while (indexer.valid()) {
summout[count].reserve (R);
for (unsigned r = 0; r < R; r++) {
summout[count].push_back (params_[indexer]);
indexer.increment (fIdx);
}
count ++;
indexer.reset (fIdx);
indexer.incrementExcluding (fIdx);
}
params_.clear();
params_.reserve (summout.size() * H);
vector<bool> mapDims (ranges_.size(), true);
ranges_[fIdx] = H;
mapDims[fIdx] = false;
MapIndexer mapIndexer (ranges_, mapDims);
while (mapIndexer.valid()) {
double prod = 1.0;
unsigned i = mapIndexer.mappedIndex();
unsigned h = mapIndexer[fIdx];
for (unsigned r = 0; r < R; r++) {
// TODO not log domain aware
prod *= Util::pow (summout[i][r], histograms[h][r]);
}
params_.push_back (prod);
++ mapIndexer;
}
formulas_[fIdx].setCountedLogVar (X);
}
void
Parfactor::expandPotential (
LogVar X,
LogVar X_new1,
LogVar X_new2)
{
int fIdx = indexOfFormulaWithLogVar (X);
assert (fIdx != -1);
assert (formulas_[fIdx].isCounting());
unsigned N1 = constr_->getConditionalCount (X_new1);
unsigned N2 = constr_->getConditionalCount (X_new2);
unsigned N = N1 + N2;
unsigned R = formulas_[fIdx].range();
unsigned H1 = HistogramSet::nrHistograms (N1, R);
unsigned H2 = HistogramSet::nrHistograms (N2, R);
unsigned H = ranges_[fIdx];
vector<Histogram> histograms = HistogramSet::getHistograms (N, R);
vector<Histogram> histograms1 = HistogramSet::getHistograms (N1, R);
vector<Histogram> histograms2 = HistogramSet::getHistograms (N2, R);
vector<unsigned> sumIndexes;
sumIndexes.reserve (H1 * H2);
for (unsigned i = 0; i < H1; i++) {
for (unsigned j = 0; j < H2; j++) {
Histogram hist = histograms1[i];
std::transform (
hist.begin(), hist.end(),
histograms2[j].begin(),
hist.begin(),
plus<int>());
sumIndexes.push_back (HistogramSet::findIndex (hist, histograms));
}
}
unsigned size = (params_.size() / H) * H1 * H2;
Params copy = params_;
params_.clear();
params_.reserve (size);
unsigned prod = 1;
vector<unsigned> offsets_ (ranges_.size());
for (int i = ranges_.size() - 1; i >= 0; i--) {
offsets_[i] = prod;
prod *= ranges_[i];
}
unsigned index = 0;
ranges_[fIdx] = H1 * H2;
vector<unsigned> indices (ranges_.size(), 0);
for (unsigned k = 0; k < size; k++) {
params_.push_back (copy[index]);
for (int i = ranges_.size() - 1; i >= 0; i--) {
indices[i] ++;
if (i == fIdx) {
int diff = sumIndexes[indices[i]] - sumIndexes[indices[i] - 1];
index += diff * offsets_[i];
} else {
index += offsets_[i];
}
if (indices[i] != ranges_[i]) {
break;
} else {
if (i == fIdx) {
int diff = sumIndexes[0] - sumIndexes[indices[i]];
index += diff * offsets_[i];
} else {
index -= offsets_[i] * ranges_[i];
}
indices[i] = 0;
}
}
}
formulas_.insert (formulas_.begin() + fIdx + 1, formulas_[fIdx]);
formulas_[fIdx].rename (X, X_new1);
formulas_[fIdx + 1].rename (X, X_new2);
ranges_.insert (ranges_.begin() + fIdx + 1, H2);
ranges_[fIdx] = H1;
}
void
Parfactor::fullExpand (LogVar X)
{
int fIdx = indexOfFormulaWithLogVar (X);
assert (fIdx != -1);
assert (formulas_[fIdx].isCounting());
unsigned N = constr_->getConditionalCount (X);
unsigned R = formulas_[fIdx].range();
unsigned H = ranges_[fIdx];
vector<Histogram> originHists = HistogramSet::getHistograms (N, R);
vector<Histogram> expandHists = HistogramSet::getHistograms (1, R);
vector<unsigned> sumIndexes;
sumIndexes.reserve (N * R);
Ranges expandRanges (N, R);
StatesIndexer indexer (expandRanges);
while (indexer.valid()) {
vector<unsigned> hist (R, 0);
for (unsigned n = 0; n < N; n++) {
std::transform (
hist.begin(), hist.end(),
expandHists[indexer[n]].begin(),
hist.begin(),
plus<int>());
}
sumIndexes.push_back (HistogramSet::findIndex (hist, originHists));
++ indexer;
}
unsigned size = (params_.size() / H) * std::pow (R, N);
Params copy = params_;
params_.clear();
params_.reserve (size);
unsigned prod = 1;
vector<unsigned> offsets_ (ranges_.size());
for (int i = ranges_.size() - 1; i >= 0; i--) {
offsets_[i] = prod;
prod *= ranges_[i];
}
unsigned index = 0;
ranges_[fIdx] = std::pow (R, N);
vector<unsigned> indices (ranges_.size(), 0);
for (unsigned k = 0; k < size; k++) {
params_.push_back (copy[index]);
for (int i = ranges_.size() - 1; i >= 0; i--) {
indices[i] ++;
if (i == fIdx) {
int diff = sumIndexes[indices[i]] - sumIndexes[indices[i] - 1];
index += diff * offsets_[i];
} else {
index += offsets_[i];
}
if (indices[i] != ranges_[i]) {
break;
} else {
if (i == fIdx) {
int diff = sumIndexes[0] - sumIndexes[indices[i]];
index += diff * offsets_[i];
} else {
index -= offsets_[i] * ranges_[i];
}
indices[i] = 0;
}
}
}
ProbFormula f = formulas_[fIdx];
formulas_.erase (formulas_.begin() + fIdx);
ranges_.erase (ranges_.begin() + fIdx);
LogVars newLvs = constr_->expand (X);
assert (newLvs.size() == N);
for (unsigned i = 0 ; i < N; i++) {
ProbFormula newFormula (f.functor(), f.logVars(), f.range());
newFormula.rename (X, newLvs[i]);
formulas_.insert (formulas_.begin() + fIdx + i, newFormula);
ranges_.insert (ranges_.begin() + fIdx + i, R);
}
}
void
Parfactor::reorderAccordingGrounds (const Grounds& grounds)
{
ProbFormulas newFormulas;
for (unsigned i = 0; i < grounds.size(); i++) {
for (unsigned j = 0; j < formulas_.size(); j++) {
if (grounds[i].functor() == formulas_[j].functor() &&
grounds[i].arity() == formulas_[j].arity()) {
constr_->moveToTop (formulas_[j].logVars());
if (constr_->containsTuple (grounds[i].args())) {
newFormulas.push_back (formulas_[j]);
break;
}
}
}
assert (newFormulas.size() == i + 1);
}
reorderFormulas (newFormulas);
}
void
Parfactor::reorderFormulas (const ProbFormulas& newFormulas)
{
assert (newFormulas.size() == formulas_.size());
if (newFormulas == formulas_) {
return;
}
Ranges newRanges;
vector<unsigned> positions;
for (unsigned i = 0; i < newFormulas.size(); i++) {
unsigned idx = indexOf (newFormulas[i]);
newRanges.push_back (ranges_[idx]);
positions.push_back (idx);
}
unsigned N = ranges_.size();
Params newParams (params_.size());
for (unsigned i = 0; i < params_.size(); i++) {
unsigned li = i;
// calculate vector index corresponding to linear index
vector<unsigned> vi (N);
for (int k = N-1; k >= 0; k--) {
vi[k] = li % ranges_[k];
li /= ranges_[k];
}
// convert permuted vector index to corresponding linear index
unsigned prod = 1;
unsigned new_li = 0;
for (int k = N - 1; k >= 0; k--) {
new_li += vi[positions[k]] * prod;
prod *= ranges_[positions[k]];
}
newParams[new_li] = params_[i];
}
formulas_ = newFormulas;
ranges_ = newRanges;
params_ = newParams;
}
void
Parfactor::absorveEvidence (unsigned fIdx, unsigned evidence)
{
LogVarSet excl = exclusiveLogVars (fIdx);
assert (fIdx < formulas_.size());
assert (evidence < formulas_[fIdx].range());
assert (formulas_[fIdx].isCounting() == false);
assert (constr_->isCountNormalized (excl));
Util::pow (params_, constr_->getConditionalCount (excl));
Params copy = params_;
params_.clear();
params_.reserve (copy.size() / formulas_[fIdx].range());
StatesIndexer indexer (ranges_);
for (unsigned i = 0; i < evidence; i++) {
indexer.increment (fIdx);
}
while (indexer.valid()) {
params_.push_back (copy[indexer]);
indexer.incrementExcluding (fIdx);
}
formulas_.erase (formulas_.begin() + fIdx);
ranges_.erase (ranges_.begin() + fIdx);
constr_->remove (excl);
}
void
Parfactor::normalize (void)
{
Util::normalize (params_);
}
void
Parfactor::setFormulaGroup (const ProbFormula& f, int group)
{
assert (indexOf (f) != -1);
formulas_[indexOf (f)].setGroup (group);
}
void
Parfactor::setNewGroups (void)
{
for (unsigned i = 0; i < formulas_.size(); i++) {
formulas_[i].setGroup (ProbFormula::getNewGroup());
}
}
void
Parfactor::applySubstitution (const Substitution& theta)
{
for (unsigned i = 0; i < formulas_.size(); i++) {
LogVars& lvs = formulas_[i].logVars();
for (unsigned j = 0; j < lvs.size(); j++) {
lvs[j] = theta.newNameFor (lvs[j]);
}
if (formulas_[i].isCounting()) {
LogVar clv = formulas_[i].countedLogVar();
formulas_[i].setCountedLogVar (theta.newNameFor (clv));
}
}
constr_->applySubstitution (theta);
}
bool
Parfactor::containsGround (const Ground& ground) const
{
for (unsigned i = 0; i < formulas_.size(); i++) {
if (formulas_[i].functor() == ground.functor() &&
formulas_[i].arity() == ground.arity()) {
constr_->moveToTop (formulas_[i].logVars());
if (constr_->containsTuple (ground.args())) {
return true;
}
}
}
return false;
}
bool
Parfactor::containsGroup (unsigned group) const
{
for (unsigned i = 0; i < formulas_.size(); i++) {
if (formulas_[i].group() == group) {
return true;
}
}
return false;
}
const ProbFormula&
Parfactor::formula (unsigned fIdx) const
{
assert (fIdx < formulas_.size());
return formulas_[fIdx];
}
unsigned
Parfactor::range (unsigned fIdx) const
{
assert (fIdx < ranges_.size());
return ranges_[fIdx];
}
unsigned
Parfactor::nrFormulas (LogVar X) const
{
unsigned count = 0;
for (unsigned i = 0; i < formulas_.size(); i++) {
if (formulas_[i].contains (X)) {
count ++;
}
}
return count;
}
int
Parfactor::indexOf (const ProbFormula& f) const
{
int idx = -1;
for (unsigned i = 0; i < formulas_.size(); i++) {
if (f == formulas_[i]) {
idx = i;
break;
}
}
return idx;
}
int
Parfactor::indexOfFormulaWithLogVar (LogVar X) const
{
int idx = -1;
assert (nrFormulas (X) == 1);
for (unsigned i = 0; i < formulas_.size(); i++) {
if (formulas_[i].contains (X)) {
idx = i;
break;
}
}
return idx;
}
int
Parfactor::indexOfFormulaWithGroup (unsigned group) const
{
int pos = -1;
for (unsigned i = 0; i < formulas_.size(); i++) {
if (formulas_[i].group() == group) {
pos = i;
break;
}
}
return pos;
}
vector<unsigned>
Parfactor::getAllGroups (void) const
{
vector<unsigned> groups (formulas_.size());
for (unsigned i = 0; i < formulas_.size(); i++) {
groups[i] = formulas_[i].group();
}
return groups;
}
string
Parfactor::getHeaderString (void) const
{
stringstream ss;
ss << "phi(" ;
for (unsigned i = 0; i < formulas_.size(); i++) {
if (i != 0) ss << "," ;
ss << formulas_[i];
}
ss << ")" ;
ConstraintTree copy (*constr_);
copy.moveToTop (copy.logVarSet().elements());
ss << "|" << copy.tupleSet();
return ss.str();
}
void
Parfactor::print (bool printParams) const
{
cout << "Formulas: " ;
for (unsigned i = 0; i < formulas_.size(); i++) {
if (i != 0) cout << ", " ;
cout << formulas_[i];
}
cout << endl;
vector<string> groups;
for (unsigned i = 0; i < formulas_.size(); i++) {
groups.push_back (string ("g") + Util::toString (formulas_[i].group()));
}
cout << "Groups: " << groups << endl;
cout << "LogVars: " << constr_->logVars() << endl;
cout << "Ranges: " << ranges_ << endl;
if (printParams == false) {
cout << "Params: " << params_ << endl;
}
cout << "Tuples: " << constr_->tupleSet() << endl;
if (printParams) {
vector<string> jointStrings;
StatesIndexer indexer (ranges_);
while (indexer.valid()) {
stringstream ss;
for (unsigned i = 0; i < formulas_.size(); i++) {
if (i != 0) ss << ", " ;
if (formulas_[i].isCounting()) {
unsigned N = constr_->getConditionalCount (formulas_[i].countedLogVar());
HistogramSet hs (N, formulas_[i].range());
unsigned c = 0;
while (c < indexer[i]) {
hs.nextHistogram();
c ++;
}
ss << hs;
} else {
ss << indexer[i];
}
}
jointStrings.push_back (ss.str());
++ indexer;
}
for (unsigned i = 0; i < params_.size(); i++) {
cout << "f(" << jointStrings[i] << ")" ;
cout << " = " << params_[i] << endl;
}
}
}
void
Parfactor::insertDimension (unsigned range)
{
Params copy = params_;
params_.clear();
params_.reserve (copy.size() * range);
for (unsigned i = 0; i < copy.size(); i++) {
for (unsigned reps = 0; reps < range; reps++) {
params_.push_back (copy[i]);
}
}
ranges_.push_back (range);
}
void
Parfactor::alignAndExponentiate (Parfactor* g1, Parfactor* g2)
{
LogVars X_1, X_2;
const ProbFormulas& formulas1 = g1->formulas();
const ProbFormulas& formulas2 = g2->formulas();
for (unsigned i = 0; i < formulas1.size(); i++) {
for (unsigned j = 0; j < formulas2.size(); j++) {
if (formulas1[i].group() == formulas2[j].group()) {
X_1.insert (X_1.end(),
formulas1[i].logVars().begin(),
formulas1[i].logVars().end());
X_2.insert (X_2.end(),
formulas2[j].logVars().begin(),
formulas2[j].logVars().end());
}
}
}
align (g1, X_1, g2, X_2);
LogVarSet Y_1 = g1->logVarSet() - LogVarSet (X_1);
LogVarSet Y_2 = g2->logVarSet() - LogVarSet (X_2);
assert (g1->constr()->isCountNormalized (Y_1));
assert (g2->constr()->isCountNormalized (Y_2));
unsigned condCount1 = g1->constr()->getConditionalCount (Y_1);
unsigned condCount2 = g2->constr()->getConditionalCount (Y_2);
Util::pow (g1->params(), 1.0 / condCount2);
Util::pow (g2->params(), 1.0 / condCount1);
}
void
Parfactor::align (
Parfactor* g1, const LogVars& alignLvs1,
Parfactor* g2, const LogVars& alignLvs2)
{
LogVar freeLogVar = 0;
Substitution theta1;
Substitution theta2;
const LogVarSet& allLvs1 = g1->logVarSet();
for (unsigned i = 0; i < allLvs1.size(); i++) {
theta1.add (allLvs1[i], freeLogVar);
++ freeLogVar;
}
const LogVarSet& allLvs2 = g2->logVarSet();
for (unsigned i = 0; i < allLvs2.size(); i++) {
theta2.add (allLvs2[i], freeLogVar);
++ freeLogVar;
}
assert (alignLvs1.size() == alignLvs2.size());
for (unsigned i = 0; i < alignLvs1.size(); i++) {
theta1.rename (alignLvs1[i], theta2.newNameFor (alignLvs2[i]));
}
g1->applySubstitution (theta1);
g2->applySubstitution (theta2);
}

View File

@ -0,0 +1,124 @@
#ifndef HORUS_PARFACTOR_H
#define HORUS_PARFACTOR_H
#include <list>
#include <unordered_map>
#include "ProbFormula.h"
#include "ConstraintTree.h"
#include "LiftedUtils.h"
#include "Horus.h"
class Parfactor
{
public:
Parfactor (
const ProbFormulas&,
const Params&,
const Tuples&,
unsigned);
Parfactor (const Parfactor*, const Tuple&);
Parfactor (const Parfactor*, ConstraintTree*);
Parfactor (const Parfactor&);
~Parfactor (void);
ProbFormulas& formulas (void) { return formulas_; }
const ProbFormulas& formulas (void) const { return formulas_; }
unsigned nrFormulas (void) const { return formulas_.size(); }
Params& params (void) { return params_; }
const Params& params (void) const { return params_; }
unsigned size (void) const { return params_.size(); }
const Ranges& ranges (void) const { return ranges_; }
unsigned distId (void) const { return distId_; }
ConstraintTree* constr (void) { return constr_; }
const ConstraintTree* constr (void) const { return constr_; }
const LogVars& logVars (void) const { return constr_->logVars(); }
const LogVarSet& logVarSet (void) const { return constr_->logVarSet(); }
LogVarSet countedLogVars (void) const;
LogVarSet uncountedLogVars (void) const;
LogVarSet elimLogVars (void) const;
LogVarSet exclusiveLogVars (unsigned) const;
void setConstraintTree (ConstraintTree*);
void sumOut (unsigned);
void multiply (Parfactor&);
void countConvert (LogVar);
void expandPotential (LogVar, LogVar, LogVar);
void fullExpand (LogVar);
void reorderAccordingGrounds (const Grounds&);
void reorderFormulas (const ProbFormulas&);
void absorveEvidence (unsigned, unsigned);
void normalize (void);
void setFormulaGroup (const ProbFormula&, int);
void setNewGroups (void);
void applySubstitution (const Substitution&);
bool containsGround (const Ground&) const;
bool containsGroup (unsigned) const;
const ProbFormula& formula (unsigned) const;
unsigned range (unsigned) const;
unsigned nrFormulas (LogVar) const;
int indexOf (const ProbFormula&) const;
int indexOfFormulaWithLogVar (LogVar) const;
int indexOfFormulaWithGroup (unsigned) const;
vector<unsigned> getAllGroups (void) const;
void print (bool = false) const;
string getHeaderString (void) const;
private:
static void alignAndExponentiate (Parfactor*, Parfactor*);
static void align (
Parfactor*, const LogVars&, Parfactor*, const LogVars&);
void insertDimension (unsigned);
ProbFormulas formulas_;
Ranges ranges_;
Params params_;
unsigned distId_;
ConstraintTree* constr_;
};
typedef vector<Parfactor*> Parfactors;
#endif // HORUS_PARFACTOR_H

View File

@ -0,0 +1,308 @@
#include <cassert>
#include "ParfactorList.h"
ParfactorList::ParfactorList (Parfactors& pfs)
{
pfList_.insert (pfList_.end(), pfs.begin(), pfs.end());
}
void
ParfactorList::add (Parfactor* pf)
{
pf->setNewGroups();
pfList_.push_back (pf);
}
void
ParfactorList::add (Parfactors& pfs)
{
for (unsigned i = 0; i < pfs.size(); i++) {
pfs[i]->setNewGroups();
pfList_.push_back (pfs[i]);
}
}
void
ParfactorList::addShattered (Parfactor* pf)
{
pfList_.push_back (pf);
}
list<Parfactor*>::iterator
ParfactorList::remove (list<Parfactor*>::iterator it)
{
return pfList_.erase (it);
}
list<Parfactor*>::iterator
ParfactorList::deleteAndRemove (list<Parfactor*>::iterator it)
{
delete *it;
return pfList_.erase (it);
}
void
ParfactorList::shatter (void)
{
list<Parfactor*> tempList;
Parfactors newPfs;
newPfs.insert (newPfs.end(), pfList_.begin(), pfList_.end());
while (newPfs.empty() == false) {
tempList.insert (tempList.end(), newPfs.begin(), newPfs.end());
newPfs.clear();
list<Parfactor*>::iterator iter1 = tempList.begin();
while (tempList.size() > 1 && iter1 != -- tempList.end()) {
list<Parfactor*>::iterator iter2 = iter1;
++ iter2;
bool incIter1 = true;
while (iter2 != tempList.end()) {
assert (iter1 != iter2);
std::pair<Parfactors, Parfactors> res = shatter (
(*iter1)->formulas(), *iter1, (*iter2)->formulas(), *iter2);
bool incIter2 = true;
if (res.second.empty() == false) {
// cout << "second unshattered" << endl;
delete *iter2;
iter2 = tempList.erase (iter2);
incIter2 = false;
newPfs.insert (
newPfs.begin(), res.second.begin(), res.second.end());
}
if (res.first.empty() == false) {
// cout << "first unshattered" << endl;
delete *iter1;
iter1 = tempList.erase (iter1);
newPfs.insert (
newPfs.begin(), res.first.begin(), res.first.end());
incIter1 = false;
break;
}
if (incIter2) {
++ iter2;
}
}
if (incIter1) {
++ iter1;
}
}
// cout << "|||||||||||||||||||||||||||||||||||||||||||||||||" << endl;
// cout << "||||||||||||| SHATTERING ITERATION ||||||||||||||" << endl;
// cout << "|||||||||||||||||||||||||||||||||||||||||||||||||" << endl;
// printParfactors (newPfs);
// cout << "|||||||||||||||||||||||||||||||||||||||||||||||||" << endl;
}
pfList_.clear();
pfList_.insert (pfList_.end(), tempList.begin(), tempList.end());
}
void
ParfactorList::print (void) const
{
list<Parfactor*>::const_iterator it;
for (it = pfList_.begin(); it != pfList_.end(); ++it) {
(*it)->print();
cout << endl;
}
}
std::pair<Parfactors, Parfactors>
ParfactorList::shatter (
ProbFormulas& formulas1,
Parfactor* g1,
ProbFormulas& formulas2,
Parfactor* g2)
{
assert (g1 != 0 && g2 != 0 && g1 != g2);
for (unsigned i = 0; i < formulas1.size(); i++) {
for (unsigned j = 0; j < formulas2.size(); j++) {
if (formulas1[i].sameSkeletonAs (formulas2[j])) {
std::pair<Parfactors, Parfactors> res
= shatter (formulas1[i], g1, formulas2[j], g2);
if (res.first.empty() == false ||
res.second.empty() == false) {
return res;
}
}
}
}
return make_pair (Parfactors(), Parfactors());
}
std::pair<Parfactors, Parfactors>
ParfactorList::shatter (
ProbFormula& f1,
Parfactor* g1,
ProbFormula& f2,
Parfactor* g2)
{
// cout << endl;
// cout << "-------------------------------------------------" << endl;
// cout << "-> SHATTERING (#" << g1 << ", #" << g2 << ")" << endl;
// g1->print();
// cout << "-> WITH" << endl;
// g2->print();
// cout << "-> ON: " << f1.toString (g1->constr()) << endl;
// cout << "-> ON: " << f2.toString (g2->constr()) << endl;
// cout << "-------------------------------------------------" << endl;
if (f1.isAtom()) {
unsigned group = (f1.group() < f2.group()) ? f1.group() : f2.group();
f1.setGroup (group);
f2.setGroup (group);
return { };
}
assert (g1->constr()->empty() == false);
assert (g2->constr()->empty() == false);
if (f1.group() == f2.group()) {
// assert (identical (f1, g1->constr(), f2, g2->constr()));
return { };
}
g1->constr()->moveToTop (f1.logVars());
g2->constr()->moveToTop (f2.logVars());
std::pair<ConstraintTree*,ConstraintTree*> split1 =
g1->constr()->split (g2->constr(), f1.arity());
ConstraintTree* commCt1 = split1.first;
ConstraintTree* exclCt1 = split1.second;
if (commCt1->empty()) {
// disjoint
delete commCt1;
delete exclCt1;
return { };
}
std::pair<ConstraintTree*,ConstraintTree*> split2 =
g2->constr()->split (g1->constr(), f2.arity());
ConstraintTree* commCt2 = split2.first;
ConstraintTree* exclCt2 = split2.second;
assert (commCt1->tupleSet (f1.arity()) ==
commCt2->tupleSet (f2.arity()));
// stringstream ss1; ss1 << "" << count << "_A.dot" ;
// stringstream ss2; ss2 << "" << count << "_B.dot" ;
// stringstream ss3; ss3 << "" << count << "_A_comm.dot" ;
// stringstream ss4; ss4 << "" << count << "_A_excl.dot" ;
// stringstream ss5; ss5 << "" << count << "_B_comm.dot" ;
// stringstream ss6; ss6 << "" << count << "_B_excl.dot" ;
// ct1->exportToGraphViz (ss1.str().c_str(), true);
// ct2->exportToGraphViz (ss2.str().c_str(), true);
// commCt1->exportToGraphViz (ss3.str().c_str(), true);
// exclCt1->exportToGraphViz (ss4.str().c_str(), true);
// commCt2->exportToGraphViz (ss5.str().c_str(), true);
// exclCt2->exportToGraphViz (ss6.str().c_str(), true);
if (exclCt1->empty() && exclCt2->empty()) {
unsigned group = (f1.group() < f2.group()) ? f1.group() : f2.group();
// identical
f1.setGroup (group);
f2.setGroup (group);
// unifyGroups
delete commCt1;
delete exclCt1;
delete commCt2;
delete exclCt2;
return { };
}
unsigned group;
if (exclCt1->empty()) {
group = f1.group();
} else if (exclCt2->empty()) {
group = f2.group();
} else {
group = ProbFormula::getNewGroup();
}
Parfactors res1 = shatter (g1, f1, commCt1, exclCt1, group);
Parfactors res2 = shatter (g2, f2, commCt2, exclCt2, group);
return make_pair (res1, res2);
}
Parfactors
ParfactorList::shatter (
Parfactor* g,
const ProbFormula& f,
ConstraintTree* commCt,
ConstraintTree* exclCt,
unsigned commGroup)
{
Parfactors result;
if (f.isCounting()) {
LogVar X_new1 = g->constr()->logVarSet().back() + 1;
LogVar X_new2 = g->constr()->logVarSet().back() + 2;
ConstraintTrees cts = g->constr()->jointCountNormalize (
commCt, exclCt, f.countedLogVar(), X_new1, X_new2);
for (unsigned i = 0; i < cts.size(); i++) {
Parfactor* newPf = new Parfactor (g, cts[i]);
if (cts[i]->nrLogVars() == g->constr()->nrLogVars() + 1) {
newPf->expandPotential (f.countedLogVar(), X_new1, X_new2);
assert (g->constr()->getConditionalCount (f.countedLogVar()) ==
cts[i]->getConditionalCount (X_new1) +
cts[i]->getConditionalCount (X_new2));
} else {
assert (g->constr()->getConditionalCount (f.countedLogVar()) ==
cts[i]->getConditionalCount (f.countedLogVar()));
}
newPf->setNewGroups();
result.push_back (newPf);
}
} else {
if (exclCt->empty()) {
delete commCt;
delete exclCt;
g->setFormulaGroup (f, commGroup);
} else {
Parfactor* newPf = new Parfactor (g, commCt);
newPf->setNewGroups();
newPf->setFormulaGroup (f, commGroup);
result.push_back (newPf);
newPf = new Parfactor (g, exclCt);
newPf->setNewGroups();
result.push_back (newPf);
}
}
return result;
}
void
ParfactorList::unifyGroups (unsigned group1, unsigned group2)
{
unsigned newGroup = ProbFormula::getNewGroup();
for (ParfactorList::iterator it = pfList_.begin();
it != pfList_.end(); it++) {
ProbFormulas& formulas = (*it)->formulas();
for (unsigned i = 0; i < formulas.size(); i++) {
if (formulas[i].group() == group1 ||
formulas[i].group() == group2) {
formulas[i].setGroup (newGroup);
}
}
}
}

View File

@ -0,0 +1,70 @@
#ifndef HORUS_PARFACTORLIST_H
#define HORUS_PARFACTORLIST_H
#include <list>
#include "Parfactor.h"
#include "ProbFormula.h"
using namespace std;
class ParfactorList
{
public:
ParfactorList (void) { }
ParfactorList (Parfactors&);
list<Parfactor*>& getParfactors (void) { return pfList_; }
const list<Parfactor*>& getParfactors (void) const { return pfList_; }
void add (Parfactor* pf);
void add (Parfactors& pfs);
void addShattered (Parfactor* pf);
list<Parfactor*>::iterator remove (list<Parfactor*>::iterator);
list<Parfactor*>::iterator deleteAndRemove (list<Parfactor*>::iterator);
void clear (void) { pfList_.clear(); }
unsigned size (void) const { return pfList_.size(); }
void shatter (void);
typedef std::list<Parfactor*>::iterator iterator;
iterator begin (void) { return pfList_.begin(); }
iterator end (void) { return pfList_.end(); }
typedef std::list<Parfactor*>::const_iterator const_iterator;
const_iterator begin (void) const { return pfList_.begin(); }
const_iterator end (void) const { return pfList_.end(); }
void print (void) const;
private:
static std::pair<Parfactors, Parfactors> shatter (
ProbFormulas&,
Parfactor*,
ProbFormulas&,
Parfactor*);
static std::pair<Parfactors, Parfactors> shatter (
ProbFormula&,
Parfactor*,
ProbFormula&,
Parfactor*);
static Parfactors shatter (
Parfactor*,
const ProbFormula&,
ConstraintTree*,
ConstraintTree*,
unsigned);
void unifyGroups (unsigned group1, unsigned group2);
list<Parfactor*> pfList_;
};
#endif // HORUS_PARFACTORLIST_H

View File

@ -0,0 +1,115 @@
#include "ProbFormula.h"
int ProbFormula::freeGroup_ = 0;
bool
ProbFormula::sameSkeletonAs (const ProbFormula& f) const
{
return functor_ == f.functor() && logVars_.size() == f.arity();
}
bool
ProbFormula::contains (LogVar lv) const
{
return std::find (logVars_.begin(), logVars_.end(), lv) !=
logVars_.end();
}
bool
ProbFormula::contains (LogVarSet s) const
{
return LogVarSet (logVars_).contains (s);
}
bool
ProbFormula::isAtom (void) const
{
return logVars_.size() == 0;
}
bool
ProbFormula::isCounting (void) const
{
return countedLogVar_.valid();
}
LogVar
ProbFormula::countedLogVar (void) const
{
assert (isCounting());
return countedLogVar_;
}
void
ProbFormula::setCountedLogVar (LogVar lv)
{
countedLogVar_ = lv;
}
void
ProbFormula::rename (LogVar oldName, LogVar newName)
{
for (unsigned i = 0; i < logVars_.size(); i++) {
if (logVars_[i] == oldName) {
logVars_[i] = newName;
}
}
if (isCounting() && countedLogVar_ == oldName) {
countedLogVar_ = newName;
}
}
bool
ProbFormula::operator== (const ProbFormula& f) const
{
return functor_ == f.functor_ && logVars_ == f.logVars_ ;
}
ostream& operator<< (ostream &os, const ProbFormula& f)
{
os << f.functor_;
if (f.isAtom() == false) {
os << "(" ;
for (unsigned i = 0; i < f.logVars_.size(); i++) {
if (i != 0) os << ",";
if (f.isCounting() && f.logVars_[i] == f.countedLogVar_) {
os << "#" ;
}
os << f.logVars_[i];
}
os << ")" ;
}
os << "::" << f.range_;
return os;
}
unsigned
ProbFormula::getNewGroup (void)
{
freeGroup_ ++;
return freeGroup_;
}

View File

@ -0,0 +1,71 @@
#ifndef HORUS_PROBFORMULA_H
#define HORUS_PROBFORMULA_H
#include <limits>
#include "ConstraintTree.h"
#include "LiftedUtils.h"
#include "Horus.h"
class ProbFormula
{
public:
ProbFormula (Symbol f, const LogVars& lvs, unsigned range)
: functor_(f), logVars_(lvs), range_(range),
countedLogVar_() { }
ProbFormula (Symbol f, unsigned r) : functor_(f), range_(r) { }
Symbol functor (void) const { return functor_; }
unsigned arity (void) const { return logVars_.size(); }
unsigned range (void) const { return range_; }
LogVars& logVars (void) { return logVars_; }
const LogVars& logVars (void) const { return logVars_; }
LogVarSet logVarSet (void) const { return LogVarSet (logVars_); }
unsigned group (void) const { return groupId_; }
void setGroup (unsigned g) { groupId_ = g; }
bool sameSkeletonAs (const ProbFormula&) const;
bool contains (LogVar) const;
bool contains (LogVarSet) const;
bool isAtom (void) const;
bool isCounting (void) const;
LogVar countedLogVar (void) const;
void setCountedLogVar (LogVar);
void rename (LogVar, LogVar);
bool operator== (const ProbFormula& f) const;
friend ostream& operator<< (ostream &out, const ProbFormula& f);
static unsigned getNewGroup (void);
private:
Symbol functor_;
LogVars logVars_;
unsigned range_;
LogVar countedLogVar_;
unsigned groupId_;
static int freeGroup_;
};
typedef vector<ProbFormula> ProbFormulas;
#endif // HORUS_PROBFORMULA_H

View File

@ -1,308 +0,0 @@
#ifndef HORUS_SHARED_H
#define HORUS_SHARED_H
#include <cmath>
#include <cassert>
#include <limits>
#include <vector>
#include <unordered_map>
#include <iostream>
#include <fstream>
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
using namespace std;
class VarNode;
class BayesNet;
class BayesNode;
class Factor;
class FgVarNode;
class FgFacNode;
class SpLink;
class BpLink;
typedef double Param;
typedef vector<Param> ParamSet;
typedef unsigned VarId;
typedef vector<VarId> VarIdSet;
typedef vector<VarNode*> VarNodes;
typedef vector<BayesNode*> BnNodeSet;
typedef vector<FgVarNode*> FgVarSet;
typedef vector<FgFacNode*> FgFacSet;
typedef vector<Factor*> FactorSet;
typedef vector<string> States;
typedef vector<unsigned> Ranges;
typedef vector<unsigned> DConf;
typedef pair<unsigned, unsigned> DConstraint;
// level of debug information
static const unsigned DL = 0;
static const int NO_EVIDENCE = -1;
// number of digits to show when printing a parameter
static const unsigned PRECISION = 5;
static const bool COLLECT_STATISTICS = false;
static const bool EXPORT_TO_GRAPHVIZ = false;
static const unsigned EXPORT_MINIMAL_SIZE = 100;
static const double INF = -numeric_limits<Param>::infinity();
namespace NumberSpace {
enum ns {
NORMAL,
LOGARITHM
};
};
extern NumberSpace::ns NSPACE;
namespace InfAlgorithms {
enum InfAlgs
{
VE, // variable elimination
BN_BP, // bayesian network belief propagation
FG_BP, // factor graph belief propagation
CBP // counting bp solver
};
extern InfAlgs infAlgorithm;
};
namespace BpOptions
{
enum Schedule {
SEQ_FIXED,
SEQ_RANDOM,
PARALLEL,
MAX_RESIDUAL
};
extern Schedule schedule;
extern double accuracy;
extern unsigned maxIter;
extern bool useAlwaysLoopySolver;
}
namespace Util
{
void toLog (ParamSet&);
void fromLog (ParamSet&);
void normalize (ParamSet&);
void logSum (Param&, Param);
void multiply (ParamSet&, const ParamSet&);
void multiply (ParamSet&, const ParamSet&, unsigned);
void add (ParamSet&, const ParamSet&);
void add (ParamSet&, const ParamSet&, unsigned);
void pow (ParamSet&, unsigned);
Param pow (Param, unsigned);
double getL1Distance (const ParamSet&, const ParamSet&);
double getMaxNorm (const ParamSet&, const ParamSet&);
unsigned getNumberOfDigits (int);
bool isInteger (const string&);
string parametersToString (const ParamSet&, unsigned = PRECISION);
BayesNet* generateBayesianNetworkTreeWithLevel (unsigned);
vector<DConf> getDomainConfigurations (const VarNodes&);
vector<string> getJointStateStrings (const VarNodes&);
double tl (Param v);
double fl (Param v);
double multIdenty();
double addIdenty();
double withEvidence();
double noEvidence();
double one();
double zero();
};
inline void
Util::logSum (Param& x, Param y)
{
// x = log (exp (x) + exp (y)); return;
assert (isfinite (x) && finite (y));
// If one value is much smaller than the other, keep the larger value.
if (x < (y - log (1e200))) {
x = y;
return;
}
if (y < (x - log (1e200))) {
return;
}
double diff = x - y;
assert (isfinite (diff) && finite (x) && finite (y));
if (!isfinite (exp (diff))) { // difference is too large
x = x > y ? x : y;
} else { // otherwise return the sum.
x = y + log (static_cast<double>(1.0) + exp (diff));
}
}
inline void
Util::multiply (ParamSet& v1, const ParamSet& v2)
{
assert (v1.size() == v2.size());
for (unsigned i = 0; i < v1.size(); i++) {
v1[i] *= v2[i];
}
}
inline void
Util::multiply (ParamSet& v1, const ParamSet& v2, unsigned repetitions)
{
for (unsigned count = 0; count < v1.size(); ) {
for (unsigned i = 0; i < v2.size(); i++) {
for (unsigned r = 0; r < repetitions; r++) {
v1[count] *= v2[i];
count ++;
}
}
}
}
inline void
Util::add (ParamSet& v1, const ParamSet& v2)
{
assert (v1.size() == v2.size());
for (unsigned i = 0; i < v1.size(); i++) {
v1[i] += v2[i];
}
}
inline void
Util::add (ParamSet& v1, const ParamSet& v2, unsigned repetitions)
{
for (unsigned count = 0; count < v1.size(); ) {
for (unsigned i = 0; i < v2.size(); i++) {
for (unsigned r = 0; r < repetitions; r++) {
v1[count] += v2[i];
count ++;
}
}
}
}
inline double
Util::tl (Param v)
{
return NSPACE == NumberSpace::NORMAL ? v : log(v);
}
inline double
Util::fl (Param v)
{
return NSPACE == NumberSpace::NORMAL ? v : exp(v);
}
inline double
Util::multIdenty() {
return NSPACE == NumberSpace::NORMAL ? 1.0 : 0.0;
}
inline double
Util::addIdenty()
{
return NSPACE == NumberSpace::NORMAL ? 0.0 : INF;
}
inline double
Util::withEvidence()
{
return NSPACE == NumberSpace::NORMAL ? 1.0 : 0.0;
}
inline double
Util::noEvidence() {
return NSPACE == NumberSpace::NORMAL ? 0.0 : INF;
}
inline double
Util::one()
{
return NSPACE == NumberSpace::NORMAL ? 1.0 : 0.0;
}
inline double
Util::zero() {
return NSPACE == NumberSpace::NORMAL ? 0.0 : INF;
}
struct NetInfo
{
NetInfo (unsigned size, bool loopy, unsigned nIters, double time)
{
this->size = size;
this->loopy = loopy;
this->nIters = nIters;
this->time = time;
}
unsigned size;
bool loopy;
unsigned nIters;
double time;
};
struct CompressInfo
{
CompressInfo (unsigned a, unsigned b, unsigned c, unsigned d, unsigned e)
{
nGroundVars = a;
nGroundFactors = b;
nClusterVars = c;
nClusterFactors = d;
nWithoutNeighs = e;
}
unsigned nGroundVars;
unsigned nGroundFactors;
unsigned nClusterVars;
unsigned nClusterFactors;
unsigned nWithoutNeighs;
};
class Statistics
{
public:
static unsigned getSolvedNetworksCounting (void);
static void incrementPrimaryNetworksCounting (void);
static unsigned getPrimaryNetworksCounting (void);
static void updateStatistics (unsigned, bool, unsigned, double);
static void printStatistics (void);
static void writeStatisticsToFile (const char*);
static void updateCompressingStatistics (
unsigned, unsigned, unsigned, unsigned, unsigned);
private:
static string getStatisticString (void);
static vector<NetInfo> netInfo_;
static vector<CompressInfo> compressInfo_;
static unsigned primaryNetCount_;
};
#endif // HORUS_SHARED_H

View File

@ -1,4 +1,5 @@
#include "Solver.h" #include "Solver.h"
#include "Util.h"
void void
@ -7,7 +8,6 @@ Solver::printAllPosterioris (void)
const VarNodes& vars = gm_->getVariableNodes(); const VarNodes& vars = gm_->getVariableNodes();
for (unsigned i = 0; i < vars.size(); i++) { for (unsigned i = 0; i < vars.size(); i++) {
printPosterioriOf (vars[i]->varId()); printPosterioriOf (vars[i]->varId());
cout << endl;
} }
} }
@ -17,7 +17,7 @@ void
Solver::printPosterioriOf (VarId vid) Solver::printPosterioriOf (VarId vid)
{ {
VarNode* var = gm_->getVariableNode (vid); VarNode* var = gm_->getVariableNode (vid);
const ParamSet& posterioriDist = getPosterioriOf (vid); const Params& posterioriDist = getPosterioriOf (vid);
const States& states = var->states(); const States& states = var->states();
for (unsigned i = 0; i < states.size(); i++) { for (unsigned i = 0; i < states.size(); i++) {
cout << "P(" << var->label() << "=" << states[i] << ") = " ; cout << "P(" << var->label() << "=" << states[i] << ") = " ;
@ -30,10 +30,10 @@ Solver::printPosterioriOf (VarId vid)
void void
Solver::printJointDistributionOf (const VarIdSet& vids) Solver::printJointDistributionOf (const VarIds& vids)
{ {
VarNodes vars; VarNodes vars;
VarIdSet vidsWithoutEvidence; VarIds vidsWithoutEvidence;
for (unsigned i = 0; i < vids.size(); i++) { for (unsigned i = 0; i < vids.size(); i++) {
VarNode* var = gm_->getVariableNode (vids[i]); VarNode* var = gm_->getVariableNode (vids[i]);
if (var->hasEvidence() == false) { if (var->hasEvidence() == false) {
@ -41,7 +41,7 @@ Solver::printJointDistributionOf (const VarIdSet& vids)
vidsWithoutEvidence.push_back (vids[i]); vidsWithoutEvidence.push_back (vids[i]);
} }
} }
const ParamSet& jointDist = getJointDistributionOf (vidsWithoutEvidence); const Params& jointDist = getJointDistributionOf (vidsWithoutEvidence);
vector<string> jointStrings = Util::getJointStateStrings (vars); vector<string> jointStrings = Util::getJointStateStrings (vars);
for (unsigned i = 0; i < jointDist.size(); i++) { for (unsigned i = 0; i < jointDist.size(); i++) {
cout << "P(" << jointStrings[i] << ") = " ; cout << "P(" << jointStrings[i] << ") = " ;

View File

@ -17,12 +17,12 @@ class Solver
} }
virtual ~Solver() {} // to ensure that subclass destructor is called virtual ~Solver() {} // to ensure that subclass destructor is called
virtual void runSolver (void) = 0; virtual void runSolver (void) = 0;
virtual ParamSet getPosterioriOf (VarId) = 0; virtual Params getPosterioriOf (VarId) = 0;
virtual ParamSet getJointDistributionOf (const VarIdSet&) = 0; virtual Params getJointDistributionOf (const VarIds&) = 0;
void printAllPosterioris (void); void printAllPosterioris (void);
void printPosterioriOf (VarId vid); void printPosterioriOf (VarId vid);
void printJointDistributionOf (const VarIdSet& vids); void printJointDistributionOf (const VarIds& vids);
private: private:
const GraphicalModel* gm_; const GraphicalModel* gm_;

View File

@ -1,246 +0,0 @@
#ifndef HORUS_STATESINDEXER_H
#define HORUS_STATESINDEXER_H
#include <iomanip>
class StatesIndexer {
public:
StatesIndexer (const Ranges& ranges)
{
maxIndex_ = 1;
states_.resize (ranges.size(), 0);
ranges_ = ranges;
for (unsigned i = 0; i < ranges.size(); i++) {
maxIndex_ *= ranges[i];
}
linearIndex_ = 0;
}
StatesIndexer (const VarNodes& vars)
{
maxIndex_ = 1;
states_.resize (vars.size(), 0);
ranges_.reserve (vars.size());
for (unsigned i = 0; i < vars.size(); i++) {
ranges_.push_back (vars[i]->nrStates());
maxIndex_ *= vars[i]->nrStates();
}
linearIndex_ = 0;
}
StatesIndexer& operator++ (void) {
for (int i = ranges_.size() - 1; i >= 0; i--) {
states_[i] ++;
if (states_[i] == (int)ranges_[i]) {
states_[i] = 0;
} else {
break;
}
}
linearIndex_ ++;
return *this;
}
StatesIndexer& operator-- (void) {
for (int i = ranges_.size() - 1; i >= 0; i--) {
states_[i] --;
if (states_[i] == -1) {
states_[i] = ranges_[i] - 1;
} else {
break;
}
}
linearIndex_ --;
return *this;
}
void incrementState (unsigned whichVar)
{
for (int i = whichVar; i >= 0; i--) {
states_[i] ++;
if (states_[i] == (int)ranges_[i] && i != 0) {
if (i == 0) {
linearIndex_ = maxIndex_;
} else {
states_[i] = 0;
}
} else {
linearIndex_ = getLinearIndexFromStates();
return;
}
}
}
void decrementState (unsigned whichVar)
{
for (int i = whichVar; i >= 0; i--) {
states_[i] --;
if (states_[i] == -1) {
if (i == 0) {
linearIndex_ = -1;
} else {
states_[i] = ranges_[i] - 1;
}
} else {
linearIndex_ = getLinearIndexFromStates();
return;
}
}
}
void nextSameState (unsigned whichVar)
{
for (int i = ranges_.size() - 1; i >= 0; i--) {
if (i != (int)whichVar) {
states_[i] ++;
if (states_[i] == (int)ranges_[i]) {
if (i == 0 || (i-1 == (int)whichVar && whichVar == 0)) {
linearIndex_ = maxIndex_;
} else {
states_[i] = 0;
}
} else {
linearIndex_ = getLinearIndexFromStates();
return;
}
}
}
}
void previousSameState (unsigned whichVar)
{
for (int i = ranges_.size() - 1; i >= 0; i--) {
if (i != (int)whichVar) {
states_[i] --;
if (states_[i] == - 1) {
if (i == 0 || (i-1 == (int)whichVar && whichVar == 0)) {
linearIndex_ = -1;
} else {
states_[i] = ranges_[i] - 1;
}
} else {
linearIndex_ = getLinearIndexFromStates();
return;
}
}
}
}
void moveToBegin (void)
{
std::fill (states_.begin(), states_.end(), 0);
linearIndex_ = 0;
}
void moveToEnd (void)
{
for (unsigned i = 0; i < states_.size(); i++) {
states_[i] = ranges_[i] - 1;
}
linearIndex_ = maxIndex_ - 1;
}
bool valid (void) const
{
return linearIndex_ >= 0 && linearIndex_ < (int)maxIndex_;
}
unsigned getLinearIndex (void) const
{
return linearIndex_;
}
const vector<int>& getStates (void) const
{
return states_;
}
unsigned operator[] (unsigned whichVar) const
{
assert (valid());
assert (whichVar < states_.size());
return states_[whichVar];
}
string toString (void) const
{
stringstream ss;
ss << "linear index=" << setw (3) << linearIndex_ << " " ;
ss << "states= [" << states_[0] ;
for (unsigned i = 1; i < states_.size(); i++) {
ss << ", " << states_[i];
}
ss << "]" ;
return ss.str();
}
private:
unsigned getLinearIndexFromStates (void)
{
unsigned prod = 1;
unsigned linearIndex = 0;
for (int i = states_.size() - 1; i >= 0; i--) {
linearIndex += states_[i] * prod;
prod *= ranges_[i];
}
return linearIndex;
}
int linearIndex_;
int maxIndex_;
vector<int> states_;
vector<unsigned> ranges_;
};
/*
FgVarNode* v1 = new FgVarNode (0, 4);
FgVarNode* v2 = new FgVarNode (1, 3);
FgVarNode* v3 = new FgVarNode (2, 2);
FgVarSet vars = {v1,v2,v3};
ParamSet params = {
0.2, 0.44, 0.1, 0.88, 0.22,0.62,0.32, 0.42, 0.11, 0.88, 0.8,0.5,
0.22, 0.4, 0.11, 0.8, 0.224,0.6,0.21, 0.44, 0.14, 0.68, 0.41,0.6
};
Factor f (vars,params);
StatesIndexer idx (vars);
while (idx.valid())
{
cout << idx.toString() << " p=" << params[idx.getLinearIndex()] << endl;
idx.incrementVariableState (0);
idx.nextSameState (1);
++idx;
}
cout << endl;
idx.moveToEnd();
while (idx.valid())
{
cout << idx.toString() << " p=" << params[idx.getLinearIndex()] << endl;
idx.decrementVariableState (0);
idx.previousSameState (1);
--idx;
}
*/
/*
FgVarNode* x0 = new FgVarNode (0, 2);
FgVarNode* x1 = new FgVarNode (1, 2);
FgVarNode* x2 = new FgVarNode (2, 2);
FgVarNode* x3 = new FgVarNode (2, 2);
FgVarNode* x4 = new FgVarNode (2, 2);
FgVarSet vars_ = {x0,x1,x2,x3,x4};
ParamSet params_ = {
0.2, 0.44, 0.1, 0.88, 0.11, 0.88, 0.8, 0.5,
0.2, 0.44, 0.1, 0.88, 0.11, 0.88, 0.8, 0.5,
0.2, 0.44, 0.1, 0.88, 0.11, 0.88, 0.8, 0.5,
0.2, 0.44, 0.1, 0.88, 0.11, 0.88, 0.8, 0.5
};
Factor ff (vars_,params_);
ff.printFactor();
*/
#endif // HORUS_STATESINDEXER_H

View File

@ -0,0 +1,200 @@
#ifndef HORUS_TINYSET_H
#define HORUS_TINYSET_H
#include <vector>
#include <algorithm>
using namespace std;
template <typename T>
class TinySet
{
public:
TinySet (void) {}
TinySet (const T& t)
{
elements_.push_back (t);
}
TinySet (const vector<T>& elements)
{
elements_.reserve (elements.size());
for (unsigned i = 0; i < elements.size(); i++) {
insert (elements[i]);
}
}
TinySet (const TinySet<T>& s) : elements_(s.elements_) { }
void insert (const T& t)
{
typename vector<T>::iterator it =
std::lower_bound (elements_.begin(), elements_.end(), t);
if (it == elements_.end() || *it != t) {
elements_.insert (it, t);
}
}
void remove (const T& t)
{
typename vector<T>::iterator it =
std::lower_bound (elements_.begin(), elements_.end(), t);
if (it != elements_.end()) {
elements_.erase (it);
}
}
/* set union */
TinySet operator| (const TinySet& s) const
{
TinySet res;
std::set_union (
elements_.begin(),
elements_.end(),
s.elements_.begin(),
s.elements_.end(),
std::back_inserter (res.elements_));
return res;
}
/* set intersection */
TinySet operator& (const TinySet& s) const
{
TinySet res;
std::set_intersection (
elements_.begin(),
elements_.end(),
s.elements_.begin(),
s.elements_.end(),
std::back_inserter (res.elements_));
return res;
}
/* set difference */
TinySet operator- (const TinySet& s) const
{
TinySet res;
std::set_difference (
elements_.begin(),
elements_.end(),
s.elements_.begin(),
s.elements_.end(),
std::back_inserter (res.elements_));
return res;
}
TinySet& operator|= (const TinySet& s)
{
return *this = (*this | s);
}
TinySet& operator&= (const TinySet& s)
{
return *this = (*this & s);
}
TinySet& operator-= (const TinySet& s)
{
return *this = (*this - s);
}
bool contains (const T& t) const
{
return std::binary_search (
elements_.begin(), elements_.end(), t);
}
bool contains (const TinySet& s) const
{
return std::includes (
elements_.begin(),
elements_.end(),
s.elements_.begin(),
s.elements_.end());
}
bool in (const TinySet& s) const
{
return std::includes (
s.elements_.begin(),
s.elements_.end(),
elements_.begin(),
elements_.end());
}
bool intersects (const TinySet& s) const
{
return (*this & s).size() > 0;
}
T operator[] (unsigned i) const
{
return elements_[i];
}
const vector<T>& elements (void) const
{
return elements_;
}
T front (void) const
{
return elements_.front();
}
T back (void) const
{
return elements_.back();
}
unsigned size (void) const
{
return elements_.size();
}
bool empty (void) const
{
return elements_.size() == 0;
}
typedef typename std::vector<T>::const_iterator const_iterator;
const_iterator begin (void) const
{
return elements_.begin();
}
const_iterator end (void) const
{
return elements_.end();
}
friend bool operator== (const TinySet& s1, const TinySet& s2)
{
return s1.elements_ == s2.elements_;
}
friend bool operator!= (const TinySet& s1, const TinySet& s2)
{
return s1.elements_ != s2.elements_;
}
friend std::ostream& operator << (std::ostream& out, const TinySet<T>& s)
{
out << "{" ;
for (unsigned i = 0; i < s.size(); i++) {
out << ((i != 0) ? "," : "") << s.elements()[i];
}
out << "}" ;
return out;
}
protected:
vector<T> elements_;
};
#endif // HORUS_TINYSET_H

View File

@ -1,14 +1,19 @@
#include <sstream> #include <sstream>
#include "BayesNet.h" #include "Util.h"
#include "VarNode.h" #include "Indexer.h"
#include "Shared.h" #include "GraphicalModel.h"
#include "StatesIndexer.h"
namespace Globals {
bool logDomain = false;
};
namespace InfAlgorithms { namespace InfAlgorithms {
InfAlgs infAlgorithm = InfAlgorithms::VE; //InfAlgs infAlgorithm = InfAlgorithms::VE;
//InfAlgs infAlgorithm = InfAlgorithms::BN_BP; //InfAlgs infAlgorithm = InfAlgorithms::BN_BP;
//InfAlgs infAlgorithm = InfAlgorithms::FG_BP; InfAlgs infAlgorithm = InfAlgorithms::FG_BP;
//InfAlgs infAlgorithm = InfAlgorithms::CBP; //InfAlgs infAlgorithm = InfAlgorithms::CBP;
} }
@ -20,12 +25,11 @@ Schedule schedule = BpOptions::Schedule::SEQ_FIXED;
//Schedule schedule = BpOptions::Schedule::MAX_RESIDUAL; //Schedule schedule = BpOptions::Schedule::MAX_RESIDUAL;
double accuracy = 0.0001; double accuracy = 0.0001;
unsigned maxIter = 1000; unsigned maxIter = 1000;
bool useAlwaysLoopySolver = true;
} }
NumberSpace::ns NSPACE = NumberSpace::NORMAL;
unordered_map<VarId,VariableInfo> GraphicalModel::varsInfo_; unordered_map<VarId,VariableInfo> GraphicalModel::varsInfo_;
unordered_map<unsigned,Distribution*> GraphicalModel::distsInfo_;
vector<NetInfo> Statistics::netInfo_; vector<NetInfo> Statistics::netInfo_;
vector<CompressInfo> Statistics::compressInfo_; vector<CompressInfo> Statistics::compressInfo_;
@ -35,7 +39,7 @@ unsigned Statistics::primaryNetCount_;
namespace Util { namespace Util {
void void
toLog (ParamSet& v) toLog (Params& v)
{ {
for (unsigned i = 0; i < v.size(); i++) { for (unsigned i = 0; i < v.size(); i++) {
v[i] = log (v[i]); v[i] = log (v[i]);
@ -45,7 +49,7 @@ toLog (ParamSet& v)
void void
fromLog (ParamSet& v) fromLog (Params& v)
{ {
for (unsigned i = 0; i < v.size(); i++) { for (unsigned i = 0; i < v.size(); i++) {
v[i] = exp (v[i]); v[i] = exp (v[i]);
@ -55,92 +59,113 @@ fromLog (ParamSet& v)
void void
normalize (ParamSet& v) normalize (Params& v)
{ {
double sum; double sum;
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: sum = addIdenty();
sum = 0.0; for (unsigned i = 0; i < v.size(); i++) {
for (unsigned i = 0; i < v.size(); i++) { logSum (sum, v[i]);
sum += v[i]; }
} assert (sum != -numeric_limits<double>::infinity());
assert (sum != 0.0); for (unsigned i = 0; i < v.size(); i++) {
for (unsigned i = 0; i < v.size(); i++) { v[i] -= sum;
v[i] /= sum; }
} } else {
break; sum = 0.0;
case NumberSpace::LOGARITHM: for (unsigned i = 0; i < v.size(); i++) {
sum = addIdenty(); sum += v[i];
for (unsigned i = 0; i < v.size(); i++) { }
logSum (sum, v[i]); assert (sum != 0.0);
} for (unsigned i = 0; i < v.size(); i++) {
assert (sum != -numeric_limits<Param>::infinity()); v[i] /= sum;
for (unsigned i = 0; i < v.size(); i++) { }
v[i] -= sum;
}
} }
} }
void void
pow (ParamSet& v, unsigned expoent) pow (Params& v, double expoent)
{ {
if (expoent == 1) { if (Globals::logDomain) {
return; // optimization for (unsigned i = 0; i < v.size(); i++) {
} v[i] *= expoent;
switch (NSPACE) { }
case NumberSpace::NORMAL: } else {
for (unsigned i = 0; i < v.size(); i++) { for (unsigned i = 0; i < v.size(); i++) {
double value = 1.0; v[i] = std::pow (v[i], expoent);
for (unsigned j = 0; j < expoent; j++) { }
value *= v[i];
}
v[i] = value;
}
break;
case NumberSpace::LOGARITHM:
for (unsigned i = 0; i < v.size(); i++) {
v[i] *= expoent;
}
} }
} }
Param void
pow (Param p, unsigned expoent) pow (Params& v, unsigned expoent)
{ {
double value = 1.0; if (expoent == 1) {
switch (NSPACE) { return;
case NumberSpace::NORMAL: }
for (unsigned i = 0; i < expoent; i++) { if (Globals::logDomain) {
value *= p; for (unsigned i = 0; i < v.size(); i++) {
} v[i] *= expoent;
break; }
case NumberSpace::LOGARITHM: } else {
value = p * expoent; for (unsigned i = 0; i < v.size(); i++) {
v[i] = std::pow (v[i], expoent);
}
} }
return value;
} }
double double
getL1Distance (const ParamSet& v1, const ParamSet& v2) pow (double p, unsigned expoent)
{
return Globals::logDomain ? p * expoent : std::pow (p, expoent);
}
double
factorial (double num)
{
double result = 1.0;
for (int i = 1; i <= num; i++) {
result *= i;
}
return result;
}
unsigned
nrCombinations (unsigned n, unsigned r)
{
assert (n >= r);
unsigned prod = 1;
for (int i = (int)n; i > (int)(n - r); i--) {
prod *= i;
}
return (prod / factorial (r));
}
double
getL1Distance (const Params& v1, const Params& v2)
{ {
assert (v1.size() == v2.size()); assert (v1.size() == v2.size());
double dist = 0.0; double dist = 0.0;
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: for (unsigned i = 0; i < v1.size(); i++) {
for (unsigned i = 0; i < v1.size(); i++) { dist += abs (exp(v1[i]) - exp(v2[i]));
dist += abs (v1[i] - v2[i]); }
} } else {
break; for (unsigned i = 0; i < v1.size(); i++) {
case NumberSpace::LOGARITHM: dist += abs (v1[i] - v2[i]);
for (unsigned i = 0; i < v1.size(); i++) { }
dist += abs (exp(v1[i]) - exp(v2[i]));
}
} }
return dist; return dist;
} }
@ -148,26 +173,24 @@ getL1Distance (const ParamSet& v1, const ParamSet& v2)
double double
getMaxNorm (const ParamSet& v1, const ParamSet& v2) getMaxNorm (const Params& v1, const Params& v2)
{ {
assert (v1.size() == v2.size()); assert (v1.size() == v2.size());
double max = 0.0; double max = 0.0;
switch (NSPACE) { if (Globals::logDomain) {
case NumberSpace::NORMAL: for (unsigned i = 0; i < v1.size(); i++) {
for (unsigned i = 0; i < v1.size(); i++) { double diff = abs (exp(v1[i]) - exp(v2[i]));
double diff = abs (v1[i] - v2[i]); if (diff > max) {
if (diff > max) { max = diff;
max = diff;
}
} }
break; }
case NumberSpace::LOGARITHM: } else {
for (unsigned i = 0; i < v1.size(); i++) { for (unsigned i = 0; i < v1.size(); i++) {
double diff = abs (exp(v1[i]) - exp(v2[i])); double diff = abs (v1[i] - v2[i]);
if (diff > max) { if (diff > max) {
max = diff; max = diff;
}
} }
}
} }
return max; return max;
} }
@ -200,16 +223,14 @@ isInteger (const string& s)
string string
parametersToString (const ParamSet& v, unsigned precision) parametersToString (const Params& v, unsigned precision)
{ {
stringstream ss; stringstream ss;
ss.precision (precision); ss.precision (precision);
ss << "[" ; ss << "[" ;
for (unsigned i = 0; i < v.size() - 1; i++) { for (unsigned i = 0; i < v.size(); i++) {
ss << v[i] << ", " ; if (i != 0) ss << ", " ;
} ss << v[i];
if (v.size() != 0) {
ss << v[v.size() - 1];
} }
ss << "]" ; ss << "]" ;
return ss.str(); return ss.str();
@ -217,69 +238,6 @@ parametersToString (const ParamSet& v, unsigned precision)
BayesNet*
generateBayesianNetworkTreeWithLevel (unsigned level)
{
BayesNet* bn = new BayesNet();
Distribution* dist = new Distribution (ParamSet() = {0.1, 0.5, 0.2, 0.7});
BayesNode* root = bn->addNode (0, 2, -1, BnNodeSet() = {},
new Distribution (ParamSet() = {0.1, 0.5}));
BnNodeSet prevLevel = { root };
BnNodeSet currLevel;
VarId vidCount = 1;
for (unsigned l = 1; l < level; l++) {
currLevel.clear();
for (unsigned i = 0; i < prevLevel.size(); i++) {
currLevel.push_back (
bn->addNode (vidCount, 2, -1, BnNodeSet() = {prevLevel[i]}, dist));
vidCount ++;
currLevel.push_back (
bn->addNode (vidCount, 2, -1, BnNodeSet() = {prevLevel[i]}, dist));
vidCount ++;
}
prevLevel = currLevel;
}
for (unsigned i = 0; i < prevLevel.size(); i++) {
prevLevel[i]->setEvidence (0);
}
bn->setIndexes();
return bn;
}
vector<DConf>
getDomainConfigurations (const VarNodes& vars)
{
// TODO this method must die
unsigned nConfs = 1;
for (unsigned i = 0; i < vars.size(); i++) {
nConfs *= vars[i]->nrStates();
}
vector<DConf> confs (nConfs);
for (unsigned i = 0; i < nConfs; i++) {
confs[i].resize (vars.size());
}
unsigned nReps = 1;
for (int i = vars.size() - 1; i >= 0; i--) {
unsigned index = 0;
while (index < nConfs) {
for (unsigned j = 0; j < vars[i]->nrStates(); j++) {
for (unsigned r = 0; r < nReps; r++) {
confs[index][i] = j;
index++;
}
}
}
nReps *= vars[i]->nrStates();
}
return confs;
}
vector<string> vector<string>
getJointStateStrings (const VarNodes& vars) getJointStateStrings (const VarNodes& vars)
{ {
@ -298,6 +256,7 @@ getJointStateStrings (const VarNodes& vars)
} }
} }
@ -390,11 +349,6 @@ Statistics::getStatisticString (void)
} }
ss1 << "max iterations: " << BpOptions::maxIter << endl; ss1 << "max iterations: " << BpOptions::maxIter << endl;
ss1 << "accuracy " << BpOptions::accuracy << endl; ss1 << "accuracy " << BpOptions::accuracy << endl;
if (BpOptions::useAlwaysLoopySolver) {
ss1 << "always loopy solver: yes" << endl;
} else {
ss1 << "always loopy solver: no" << endl;
}
ss1 << endl << endl; ss1 << endl << endl;
ss2 << "---------------------------------------------------" << endl; ss2 << "---------------------------------------------------" << endl;

View File

@ -0,0 +1,244 @@
#ifndef HORUS_UTIL_H
#define HORUS_UTIL_H
#include <vector>
#include "Horus.h"
using namespace std;
namespace Util {
void toLog (Params&);
void fromLog (Params&);
void normalize (Params&);
void logSum (double&, double);
void multiply (Params&, const Params&);
void multiply (Params&, const Params&, unsigned);
void add (Params&, const Params&);
void add (Params&, const Params&, unsigned);
void pow (Params&, double);
void pow (Params&, unsigned);
double pow (double, unsigned);
double factorial (double);
unsigned nrCombinations (unsigned, unsigned);
double getL1Distance (const Params&, const Params&);
double getMaxNorm (const Params&, const Params&);
unsigned getNumberOfDigits (int);
bool isInteger (const string&);
string parametersToString (const Params&, unsigned = PRECISION);
vector<string> getJointStateStrings (const VarNodes&);
double tl (double);
double fl (double);
double multIdenty();
double addIdenty();
double withEvidence();
double noEvidence();
double one();
double zero();
template <class T>
std::string toString (const T& t)
{
std::stringstream ss;
ss << t;
return ss.str();
}
};
template <typename T>
std::ostream& operator << (std::ostream& os, const vector<T>& v)
{
os << "[" ;
for (unsigned i = 0; i < v.size(); i++) {
os << ((i != 0) ? ", " : "") << v[i];
}
os << "]" ;
return os;
}
inline void
Util::logSum (double& x, double y)
{
x = log (exp (x) + exp (y)); return;
assert (isfinite (x) && isfinite (y));
// If one value is much smaller than the other, keep the larger value.
if (x < (y - log (1e200))) {
x = y;
return;
}
if (y < (x - log (1e200))) {
return;
}
double diff = x - y;
assert (isfinite (diff) && isfinite (x) && isfinite (y));
if (!isfinite (exp (diff))) { // difference is too large
x = x > y ? x : y;
} else { // otherwise return the sum.
x = y + log (static_cast<double>(1.0) + exp (diff));
}
}
inline void
Util::multiply (Params& v1, const Params& v2)
{
assert (v1.size() == v2.size());
for (unsigned i = 0; i < v1.size(); i++) {
v1[i] *= v2[i];
}
}
inline void
Util::multiply (Params& v1, const Params& v2, unsigned repetitions)
{
for (unsigned count = 0; count < v1.size(); ) {
for (unsigned i = 0; i < v2.size(); i++) {
for (unsigned r = 0; r < repetitions; r++) {
v1[count] *= v2[i];
count ++;
}
}
}
}
inline void
Util::add (Params& v1, const Params& v2)
{
assert (v1.size() == v2.size());
for (unsigned i = 0; i < v1.size(); i++) {
v1[i] += v2[i];
}
}
inline void
Util::add (Params& v1, const Params& v2, unsigned repetitions)
{
for (unsigned count = 0; count < v1.size(); ) {
for (unsigned i = 0; i < v2.size(); i++) {
for (unsigned r = 0; r < repetitions; r++) {
v1[count] += v2[i];
count ++;
}
}
}
}
inline double
Util::tl (double v)
{
return Globals::logDomain ? log(v) : v;
}
inline double
Util::fl (double v)
{
return Globals::logDomain ? exp(v) : v;
}
inline double
Util::multIdenty() {
return Globals::logDomain ? 0.0 : 1.0;
}
inline double
Util::addIdenty()
{
return Globals::logDomain ? INF : 0.0;
}
inline double
Util::withEvidence()
{
return Globals::logDomain ? 0.0 : 1.0;
}
inline double
Util::noEvidence() {
return Globals::logDomain ? INF : 0.0;
}
inline double
Util::one()
{
return Globals::logDomain ? 0.0 : 1.0;
}
inline double
Util::zero() {
return Globals::logDomain ? INF : 0.0 ;
}
struct NetInfo
{
NetInfo (unsigned size, bool loopy, unsigned nIters, double time)
{
this->size = size;
this->loopy = loopy;
this->nIters = nIters;
this->time = time;
}
unsigned size;
bool loopy;
unsigned nIters;
double time;
};
struct CompressInfo
{
CompressInfo (unsigned a, unsigned b, unsigned c, unsigned d, unsigned e)
{
nGroundVars = a;
nGroundFactors = b;
nClusterVars = c;
nClusterFactors = d;
nWithoutNeighs = e;
}
unsigned nGroundVars;
unsigned nGroundFactors;
unsigned nClusterVars;
unsigned nClusterFactors;
unsigned nWithoutNeighs;
};
class Statistics
{
public:
static unsigned getSolvedNetworksCounting (void);
static void incrementPrimaryNetworksCounting (void);
static unsigned getPrimaryNetworksCounting (void);
static void updateStatistics (unsigned, bool, unsigned, double);
static void printStatistics (void);
static void writeStatisticsToFile (const char*);
static void updateCompressingStatistics (
unsigned, unsigned, unsigned, unsigned, unsigned);
private:
static string getStatisticString (void);
static vector<NetInfo> netInfo_;
static vector<CompressInfo> compressInfo_;
static unsigned primaryNetCount_;
};
#endif // HORUS_UTIL_H

View File

@ -3,6 +3,7 @@
#include "VarElimSolver.h" #include "VarElimSolver.h"
#include "ElimGraph.h" #include "ElimGraph.h"
#include "Factor.h" #include "Factor.h"
#include "Util.h"
VarElimSolver::VarElimSolver (const BayesNet& bn) : Solver (&bn) VarElimSolver::VarElimSolver (const BayesNet& bn) : Solver (&bn)
@ -30,23 +31,23 @@ VarElimSolver::~VarElimSolver (void)
ParamSet Params
VarElimSolver::getPosterioriOf (VarId vid) VarElimSolver::getPosterioriOf (VarId vid)
{ {
assert (factorGraph_->getFgVarNode (vid));
FgVarNode* vn = factorGraph_->getFgVarNode (vid); FgVarNode* vn = factorGraph_->getFgVarNode (vid);
assert (vn);
if (vn->hasEvidence()) { if (vn->hasEvidence()) {
ParamSet params (vn->nrStates(), 0.0); Params params (vn->nrStates(), 0.0);
params[vn->getEvidence()] = 1.0; params[vn->getEvidence()] = 1.0;
return params; return params;
} }
return getJointDistributionOf (VarIdSet() = {vid}); return getJointDistributionOf (VarIds() = {vid});
} }
ParamSet Params
VarElimSolver::getJointDistributionOf (const VarIdSet& vids) VarElimSolver::getJointDistributionOf (const VarIds& vids)
{ {
factorList_.clear(); factorList_.clear();
varFactors_.clear(); varFactors_.clear();
@ -55,10 +56,11 @@ VarElimSolver::getJointDistributionOf (const VarIdSet& vids)
introduceEvidence(); introduceEvidence();
chooseEliminationOrder (vids); chooseEliminationOrder (vids);
processFactorList (vids); processFactorList (vids);
ParamSet params = factorList_.back()->getParameters(); Params params = factorList_.back()->getParameters();
factorList_.back()->freeDistribution(); if (Globals::logDomain) {
Util::fromLog (params);
}
delete factorList_.back(); delete factorList_.back();
Util::normalize (params);
return params; return params;
} }
@ -99,7 +101,7 @@ VarElimSolver::introduceEvidence (void)
if (factor->nrVariables() == 1) { if (factor->nrVariables() == 1) {
factorList_[idxs[j]] = 0; factorList_[idxs[j]] = 0;
} else { } else {
factorList_[idxs[j]]->removeInconsistentEntries ( factorList_[idxs[j]]->absorveEvidence (
varNodes[i]->varId(), varNodes[i]->getEvidence()); varNodes[i]->varId(), varNodes[i]->getEvidence());
} }
} }
@ -110,10 +112,10 @@ VarElimSolver::introduceEvidence (void)
void void
VarElimSolver::chooseEliminationOrder (const VarIdSet& vids) VarElimSolver::chooseEliminationOrder (const VarIds& vids)
{ {
if (bayesNet_) { if (bayesNet_) {
ElimGraph graph = ElimGraph (*bayesNet_); ElimGraph graph (*bayesNet_);
elimOrder_ = graph.getEliminatingOrder (vids); elimOrder_ = graph.getEliminatingOrder (vids);
} else { } else {
const FgVarSet& varNodes = factorGraph_->getVarNodes(); const FgVarSet& varNodes = factorGraph_->getVarNodes();
@ -130,33 +132,31 @@ VarElimSolver::chooseEliminationOrder (const VarIdSet& vids)
void void
VarElimSolver::processFactorList (const VarIdSet& vids) VarElimSolver::processFactorList (const VarIds& vids)
{ {
for (unsigned i = 0; i < elimOrder_.size(); i++) { for (unsigned i = 0; i < elimOrder_.size(); i++) {
// cout << "-----------------------------------------" << endl;
// cout << "Eliminating " << elimOrder_[i];
// cout << " in the following factors:" << endl;
// printActiveFactors();
eliminate (elimOrder_[i]); eliminate (elimOrder_[i]);
} }
Factor* thisIsTheEnd = new Factor();
Factor* finalFactor = new Factor();
for (unsigned i = 0; i < factorList_.size(); i++) { for (unsigned i = 0; i < factorList_.size(); i++) {
if (factorList_[i]) { if (factorList_[i]) {
thisIsTheEnd->multiplyByFactor (*factorList_[i]); finalFactor->multiply (*factorList_[i]);
factorList_[i]->freeDistribution();
delete factorList_[i]; delete factorList_[i];
factorList_[i] = 0; factorList_[i] = 0;
} }
} }
VarIdSet vidsWithoutEvidence;
VarIds unobservedVids;
for (unsigned i = 0; i < vids.size(); i++) { for (unsigned i = 0; i < vids.size(); i++) {
if (factorGraph_->getFgVarNode (vids[i])->hasEvidence() == false) { if (factorGraph_->getFgVarNode (vids[i])->hasEvidence() == false) {
vidsWithoutEvidence.push_back (vids[i]); unobservedVids.push_back (vids[i]);
} }
} }
thisIsTheEnd->orderVariables (vidsWithoutEvidence);
factorList_.push_back (thisIsTheEnd); finalFactor->reorderVariables (unobservedVids);
finalFactor->normalize();
factorList_.push_back (finalFactor);
} }
@ -164,30 +164,25 @@ VarElimSolver::processFactorList (const VarIdSet& vids)
void void
VarElimSolver::eliminate (VarId elimVar) VarElimSolver::eliminate (VarId elimVar)
{ {
FgVarNode* vn = factorGraph_->getFgVarNode (elimVar);
Factor* result = 0; Factor* result = 0;
FgVarNode* vn = factorGraph_->getFgVarNode (elimVar);
vector<unsigned>& idxs = varFactors_.find (elimVar)->second; vector<unsigned>& idxs = varFactors_.find (elimVar)->second;
//cout << "eliminating " << setw (5) << elimVar << ":" ;
for (unsigned i = 0; i < idxs.size(); i++) { for (unsigned i = 0; i < idxs.size(); i++) {
unsigned idx = idxs[i]; unsigned idx = idxs[i];
if (factorList_[idx]) { if (factorList_[idx]) {
if (result == 0) { if (result == 0) {
result = new Factor(*factorList_[idx]); result = new Factor(*factorList_[idx]);
//cout << " " << factorList_[idx]->label();
} else { } else {
result->multiplyByFactor (*factorList_[idx]); result->multiply (*factorList_[idx]);
//cout << " x " << factorList_[idx]->label();
} }
factorList_[idx]->freeDistribution();
delete factorList_[idx]; delete factorList_[idx];
factorList_[idx] = 0; factorList_[idx] = 0;
} }
} }
if (result != 0 && result->nrVariables() != 1) { if (result != 0 && result->nrVariables() != 1) {
result->removeVariable (vn->varId()); result->sumOut (vn->varId());
factorList_.push_back (result); factorList_.push_back (result);
// cout << endl <<" factor size=" << result->size() << endl; const VarIds& resultVarIds = result->getVarIds();
const VarIdSet& resultVarIds = result->getVarIds();
for (unsigned i = 0; i < resultVarIds.size(); i++) { for (unsigned i = 0; i < resultVarIds.size(); i++) {
vector<unsigned>& idxs = vector<unsigned>& idxs =
varFactors_.find (resultVarIds[i])->second; varFactors_.find (resultVarIds[i])->second;
@ -203,7 +198,7 @@ VarElimSolver::printActiveFactors (void)
{ {
for (unsigned i = 0; i < factorList_.size(); i++) { for (unsigned i = 0; i < factorList_.size(); i++) {
if (factorList_[i] != 0) { if (factorList_[i] != 0) {
factorList_[i]->printFactor(); factorList_[i]->print();
cout << endl; cout << endl;
} }
} }

View File

@ -6,7 +6,7 @@
#include "Solver.h" #include "Solver.h"
#include "FactorGraph.h" #include "FactorGraph.h"
#include "BayesNet.h" #include "BayesNet.h"
#include "Shared.h" #include "Horus.h"
using namespace std; using namespace std;
@ -18,22 +18,22 @@ class VarElimSolver : public Solver
VarElimSolver (const BayesNet&); VarElimSolver (const BayesNet&);
VarElimSolver (const FactorGraph&); VarElimSolver (const FactorGraph&);
~VarElimSolver (void); ~VarElimSolver (void);
void runSolver (void) { } void runSolver (void) { }
ParamSet getPosterioriOf (VarId); Params getPosterioriOf (VarId);
ParamSet getJointDistributionOf (const VarIdSet&); Params getJointDistributionOf (const VarIds&);
private: private:
void createFactorList (void); void createFactorList (void);
void introduceEvidence (void); void introduceEvidence (void);
void chooseEliminationOrder (const VarIdSet&); void chooseEliminationOrder (const VarIds&);
void processFactorList (const VarIdSet&); void processFactorList (const VarIds&);
void eliminate (VarId); void eliminate (VarId);
void printActiveFactors (void); void printActiveFactors (void);
const BayesNet* bayesNet_; const BayesNet* bayesNet_;
const FactorGraph* factorGraph_; const FactorGraph* factorGraph_;
vector<Factor*> factorList_; vector<Factor*> factorList_;
VarIdSet elimOrder_; VarIds elimOrder_;
unordered_map<VarId, vector<unsigned>> varFactors_; unordered_map<VarId, vector<unsigned>> varFactors_;
}; };

View File

@ -1,7 +1,7 @@
#ifndef HORUS_VARNODE_H #ifndef HORUS_VARNODE_H
#define HORUS_VARNODE_H #define HORUS_VARNODE_H
#include "Shared.h" #include "Horus.h"
using namespace std; using namespace std;
@ -30,12 +30,14 @@ class VarNode
bool operator== (const VarNode& var) const bool operator== (const VarNode& var) const
{ {
cout << "equal operator called" << endl;
assert (!(varId_ == var.varId() && nrStates_ != var.nrStates())); assert (!(varId_ == var.varId() && nrStates_ != var.nrStates()));
return varId_ == var.varId(); return varId_ == var.varId();
} }
bool operator!= (const VarNode& var) const bool operator!= (const VarNode& var) const
{ {
cout << "diff operator called" << endl;
assert (!(varId_ == var.varId() && nrStates_ != var.nrStates())); assert (!(varId_ == var.varId() && nrStates_ != var.nrStates()));
return varId_ != var.varId(); return varId_ != var.varId();
} }

View File

@ -1,34 +0,0 @@
:- use_module(library(clpbn)).
:- set_clpbn_flag(solver, bp).
%
% R
% / | \
% / | \
% A B C
%
r(R) :-
{ R = r with p([t, f], [0.35, 0.65]) }.
a(A) :-
r(R),
child_dist(R,Dist),
{ A = a with Dist }.
b(B) :-
r(R),
child_dist(R,Dist),
{ B = b with Dist }.
c(C) :-
r(R),
child_dist(R,Dist),
{ C = c with Dist }.
child_dist(R, p([t, f], [0.3, 0.4, 0.25, 0.05], [R])).

View File

@ -1,76 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<BIF VERSION="0.3">
<NETWORK>
<NAME>Bayes-Ball: The Rational Pastime Network, Figure 4, a)</NAME>
<VARIABLE TYPE="nature">
<NAME>1</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>2</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>3</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>4</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>5</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>6</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>1</FOR>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>2</FOR>
<GIVEN>1</GIVEN>
<GIVEN>3</GIVEN>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>3</FOR>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>4</FOR>
<GIVEN>1</GIVEN>
<GIVEN>5</GIVEN>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>5</FOR>
<GIVEN>2</GIVEN>
<GIVEN>6</GIVEN>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>6</FOR>
<GIVEN>3</GIVEN>
<TABLE>1</TABLE>
</DEFINITION>
</NETWORK>
</BIF>

View File

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<BIF VERSION="0.3">
<NETWORK>
<NAME>Bayes-Ball: The Rational Pastime Network, Figure 4, c)</NAME>
<VARIABLE TYPE="nature">
<NAME>1</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>2</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>3</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>4</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>5</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>6</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>1</FOR>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>2</FOR>
<GIVEN>1</GIVEN>
<GIVEN>3</GIVEN>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>3</FOR>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>4</FOR>
<GIVEN>5</GIVEN>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>5</FOR>
<GIVEN>2</GIVEN>
<GIVEN>6</GIVEN>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>6</FOR>
<TABLE>1</TABLE>
</DEFINITION>
</NETWORK>
</BIF>

View File

@ -1,53 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--
A B
\ /
\ /
C
-->
<BIF VERSION="0.3">
<NETWORK>
<NAME>Neapolitan</NAME>
<VARIABLE TYPE="nature">
<NAME>A</NAME>
<OUTCOME>a1</OUTCOME>
<OUTCOME>a2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>B</NAME>
<OUTCOME>b1</OUTCOME>
<OUTCOME>b2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>C</NAME>
<OUTCOME>c1</OUTCOME>
<OUTCOME>c2</OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>A</FOR>
<TABLE> .695 .305 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>B</FOR>
<TABLE> .25 .75 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>C</FOR>
<GIVEN>A</GIVEN>
<GIVEN>B</GIVEN>
<TABLE> .2 .8 .45 .55 .32 .68 .7 .3 </TABLE>
</DEFINITION>
</NETWORK>
</BIF>

View File

@ -0,0 +1,47 @@
5
1
0
2
2
0 0.001
1 0.999
1
1
2
2
0 0.002
1 0.998
3
1 0 2
2 2 2
8
0 0.95
1 0.94
2 0.29
3 0.001
4 0.05
5 0.06
6 0.71
7 0.999
2
2 3
2 2
4
0 0.9
1 0.05
2 0.1
3 0.95
2
2 4
2 2
4
0 0.7
1 0.01
2 0.3
3 0.99

View File

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--
A
|
|
-
B
|
|
-
C
-->
<BIF VERSION="0.3">
<NETWORK>
<NAME>Simple Chain</NAME>
<VARIABLE TYPE="nature">
<NAME>A</NAME>
<OUTCOME>a1</OUTCOME>
<OUTCOME>a2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>B</NAME>
<OUTCOME>b1</OUTCOME>
<OUTCOME>b2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>C</NAME>
<OUTCOME>c1</OUTCOME>
<OUTCOME>c2</OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>A</FOR>
<TABLE>0.3 0.7</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>B</FOR>
<GIVEN>A</GIVEN>
<TABLE>0.4 0.6 0.2 0.8</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>C</FOR>
<GIVEN>B</GIVEN>
<TABLE>0.9 0.1 0.25 0.75</TABLE>
</DEFINITION>
</NETWORK>
</BIF>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
:- use_module(library(pfl)).
%:- set_clpbn_flag(solver,ve).
%:- set_clpbn_flag(solver,bp), clpbn_bp:set_horus_flag(inf_alg,ve).
:- set_clpbn_flag(solver,fove).
c(x1,y1).
%c(x1,y1).
%c(x2,y2).
bayes hot(Y)::[t,f] ; [0.2, 0.4] ; [c(_,Y)].
bayes attends(X)::[t,f] , hot(Y) ; [0.1, 0.2, 0.3, 0.4] ; [c(X,Y)].
bayes series::[t,f] , attends(X) ; [0.5, 0.6, 0.7, 0.8] ; [c(X,_)].

View File

@ -1,54 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--
A B
\ /
\ /
-
C
-->
<BIF VERSION="0.3">
<NETWORK>
<NAME>Simple Convergence</NAME>
<VARIABLE TYPE="nature">
<NAME>A</NAME>
<OUTCOME>a1</OUTCOME>
<OUTCOME>a2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>B</NAME>
<OUTCOME>b1</OUTCOME>
<OUTCOME>b2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>C</NAME>
<OUTCOME>c1</OUTCOME>
<OUTCOME>c2</OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>A</FOR>
<TABLE>.695 .305</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>B</FOR>
<TABLE>0.25 0.75</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>C</FOR>
<GIVEN>A</GIVEN>
<GIVEN>B</GIVEN>
<TABLE>0.2 0.8 0.45 0.55 0.32 0.68 0.7 0.3</TABLE>
</DEFINITION>
</NETWORK>
</BIF>

View File

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--
A
/ \
/ \
- -
B C
-->
<BIF VERSION="0.3">
<NETWORK>
<NAME>Simple Divergence</NAME>
<VARIABLE TYPE="nature">
<NAME>A</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>B</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>C</NAME>
<OUTCOME></OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>A</FOR>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>B</FOR>
<GIVEN>A</GIVEN>
<TABLE>1</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>C</FOR>
<GIVEN>A</GIVEN>
<TABLE>1</TABLE>
</DEFINITION>
</NETWORK>
</BIF>

View File

@ -0,0 +1,50 @@
:- use_module(library(pfl)).
:- set_clpbn_flag(solver,fove).
c(x1,y1,z1).
c(x1,y1,z2).
c(x1,y1,z3).
c(x1,y1,z4).
c(x1,y1,z5).
c(x1,y1,z6).
c(x1,y1,z7).
c(x1,y2,z1).
c(x1,y2,z2).
c(x1,y2,z3).
c(x1,y2,z4).
c(x1,y2,z5).
c(x1,y2,z6).
c(x1,y2,z7).
c(x2,y1,z1).
c(x2,y1,z2).
c(x2,y1,z3).
c(x2,y1,z4).
c(x2,y1,z5).
c(x2,y1,z6).
c(x2,y1,z7).
c(x2,y2,z1).
c(x2,y2,z2).
c(x2,y2,z3).
c(x2,y2,z4).
c(x2,y2,z5).
c(x2,y2,z6).
c(x2,y2,z7).
bayes p(X,Y,Z)::[t,f] , q(Y), s(Z) ; cpt ; [c(X,Y,Z)].
bayes q(Y)::[t,f] ; [0.50, 0.40] ; [c(_,Y,_)].
bayes s(Z)::[t,f] ; [0.33, 0.46] ; [c(_,_,Z)].
cpt([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]).
?- p(x1,y1,z1,X), s(z1,t), s(z3,f).

View File

@ -0,0 +1,15 @@
:- use_module(library(pfl)).
:- set_clpbn_flag(solver,fove).
t(ann).
t(dave).
bayes p(X)::[t,f] ; [0.1, 0.3] ; [t(X)].
?- p(ann,X), p(ann,f).

View File

@ -0,0 +1,18 @@
:- use_module(library(pfl)).
:- set_clpbn_flag(solver,fove).
t(ann).
t(dave).
bayes p(X)::[t,f] ; [0.1, 0.3] ; [t(X)].
p(ann,t).
?- p(dave,X).

View File

@ -1,106 +0,0 @@
<?XML VERSION="1.0"?>
<!--
Bayesian network in BIF (BayesNet Interchange Format)
Produced by JavaBayes (http://www.cs.cmu.edu/~javabayes/
Output created Fri Nov 14 13:14:15 GMT+00:00 1997
-->
<!-- DTD for the BIF format -->
<!DOCTYPE BIF [
<!ELEMENT PROPERTY (#PCDATA)>
<!ELEMENT TYPE (#PCDATA)>
<!ELEMENT VALUE (#PCDATA)>
<!ELEMENT NAME (#PCDATA)>
<!ELEMENT NETWORK
( NAME, ( PROPERTY | VARIABLE | PROBABILITY )* )>
<!ELEMENT VARIABLE ( NAME, TYPE, ( VALUE | PROPERTY )* ) >
<!ELEMENT PROBABILITY
( FOR | GIVEN | TABLE | ENTRY | DEFAULT | PROPERTY )* >
<!ELEMENT TABLE (#PCDATA)>
<!ELEMENT DEFAULT (TABLE)>
<!ELEMENT ENTRY ( VALUE* , TABLE )>
]>
<BIF>
<NETWORK>
<NAME>John-Mary-Call</NAME>
<!-- Variables -->
<VARIABLE>
<NAME>Burglary</NAME>
<TYPE>discrete</TYPE>
<VALUE>False</VALUE>
<VALUE>True</VALUE>
<PROPERTY>position = (145, 114)</PROPERTY>
</VARIABLE>
<VARIABLE>
<NAME>Earthquake</NAME>
<TYPE>discrete</TYPE>
<VALUE>False</VALUE>
<VALUE>True</VALUE>
<PROPERTY>position = (351, 110)</PROPERTY>
</VARIABLE>
<VARIABLE>
<NAME>Alarm</NAME>
<TYPE>discrete</TYPE>
<VALUE>False</VALUE>
<VALUE>True</VALUE>
<PROPERTY>position = (253, 224)</PROPERTY>
</VARIABLE>
<VARIABLE>
<NAME>JohnCalls</NAME>
<TYPE>discrete</TYPE>
<VALUE>False</VALUE>
<VALUE>True</VALUE>
<PROPERTY>position = (156, 343)</PROPERTY>
</VARIABLE>
<VARIABLE>
<NAME>MaryCalls</NAME>
<TYPE>discrete</TYPE>
<VALUE>False</VALUE>
<VALUE>True</VALUE>
<PROPERTY>position = (344, 341)</PROPERTY>
</VARIABLE>
<!-- Probability distributions -->
<PROBABILITY>
<FOR>Burglary</FOR>
<TABLE>0.999 0.0010 </TABLE>
</PROBABILITY>
<PROBABILITY>
<FOR>Earthquake</FOR>
<TABLE>0.998 0.0020 </TABLE>
</PROBABILITY>
<PROBABILITY>
<FOR>Alarm</FOR>
<GIVEN>Burglary</GIVEN>
<GIVEN>Earthquake</GIVEN>
<TABLE>0.999 0.71 0.06 0.05 0.0010 0.29 0.94 0.95 </TABLE>
</PROBABILITY>
<PROBABILITY>
<FOR>JohnCalls</FOR>
<GIVEN>Alarm</GIVEN>
<TABLE>0.95 0.1 0.05 0.9 </TABLE>
</PROBABILITY>
<PROBABILITY>
<FOR>MaryCalls</FOR>
<GIVEN>Alarm</GIVEN>
<TABLE>0.99 0.3 0.01 0.7 </TABLE>
</PROBABILITY>
</BIF>

View File

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--
P1 P2 P3
\ | /
\ | /
-
C
-->
<BIF VERSION="0.3">
<NETWORK>
<NAME>Simple Convergence</NAME>
<VARIABLE TYPE="nature">
<NAME>P1</NAME>
<OUTCOME>p1</OUTCOME>
<OUTCOME>p2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>P2</NAME>
<OUTCOME>p1</OUTCOME>
<OUTCOME>p2</OUTCOME>
<OUTCOME>p3</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>P3</NAME>
<OUTCOME>p1</OUTCOME>
<OUTCOME>p2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>C</NAME>
<OUTCOME>c1</OUTCOME>
<OUTCOME>c2</OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>P1</FOR>
<TABLE>.695 .305</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>P2</FOR>
<TABLE>0.2 0.3 0.5</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>P3</FOR>
<TABLE>0.25 0.75</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>C</FOR>
<GIVEN>P1</GIVEN>
<GIVEN>P2</GIVEN>
<GIVEN>P3</GIVEN>
<TABLE>0.2 0.8 0.45 0.55 0.32 0.68 0.7 0.3 0.3 0.7 0.55 0.45 0.22 0.78 0.25 0.75 0.11 0.89 0.34 0.66 0.1 0.9 0.6 0.4</TABLE>
</DEFINITION>
</NETWORK>
</BIF>

View File

@ -1,81 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--
A E
/ \ /
/ \ /
B C
\ /
\ /
D
-->
<BIF VERSION="0.3">
<NETWORK>
<NAME>Loop</NAME>
<VARIABLE TYPE="nature">
<NAME>A</NAME>
<OUTCOME>a1</OUTCOME>
<OUTCOME>a2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>B</NAME>
<OUTCOME>b1</OUTCOME>
<OUTCOME>b2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>C</NAME>
<OUTCOME>c1</OUTCOME>
<OUTCOME>c2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>D</NAME>
<OUTCOME>d1</OUTCOME>
<OUTCOME>d2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>E</NAME>
<OUTCOME>e1</OUTCOME>
<OUTCOME>e2</OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>A</FOR>
<TABLE> .01 .09 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>B</FOR>
<GIVEN>A</GIVEN>
<TABLE> .03 .97 .6 .4 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>C</FOR>
<GIVEN>A</GIVEN>
<GIVEN>E</GIVEN>
<TABLE> .24 .76 .12 .88 .2 .4. 5. .6 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>D</FOR>
<GIVEN>B</GIVEN>
<GIVEN>C</GIVEN>
<TABLE> .2 .8 .7 .3 .45 .55 .22 .78 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>E</FOR>
<TABLE> .5 .6</TABLE>
</DEFINITION>
</NETWORK>
</BIF>

View File

@ -1,55 +0,0 @@
:- use_module(library(clpbn)).
:- set_clpbn_flag(solver, bp).
%
% B F
% \ /
% \ /
% A
%
b(B) :-
b_table(BDist),
{ B = b with p([b1, b2], BDist) }.
f(F) :-
f_table(FDist),
{ F = f with p([f1, f2], FDist) }.
a(A) :-
b(B),
f(F),
a_table(ADist),
{ A = a with p([a1, a2], ADist, [B, F]) }.
d(D) :-
a(A),
f(F),
d_table(DDist),
{ D = d with p([d1, d2, d3, d4], DDist, [A, F]) }.
b_table([0.005, 0.995]).
f_table([0.03, 0.97]).
a_table([0.992, 0.99, 0.2, 0.003,
0.008, 0.01, 0.8, 0.997]).
d_table([1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0]).
%d_table([0.997, 0.001, 0.001, 0.001,
% 0.001, 0.997, 0.001, 0.001,
% 0.001, 0.001, 0.997, 0.001,
% 0.001, 0.001, 0.001, 0.997]).
%d_table([0.15, 0.1, 0.7, 0.5,
% 0.25, 0.3, 0.2, 0.25,
% 0.3, 0.15, 0.35, 0.2,
% 0.3, 0.4, 0.2, 0.1]).

View File

@ -1,17 +0,0 @@
MARKOV
3
2 2 2
3
1 0
1 1
3 2 0 1
2
0.005 0.995
2
0.03 0.97
8
0.992 0.99 0.2 0.003
0.008 0.01 0.8 0.997

View File

@ -1,53 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--
B F
\ /
\ /
A
-->
<BIF VERSION="0.3">
<NETWORK>
<NAME>Neapolitan</NAME>
<VARIABLE TYPE="nature">
<NAME>B</NAME>
<OUTCOME>b1</OUTCOME>
<OUTCOME>b2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>F</NAME>
<OUTCOME>f1</OUTCOME>
<OUTCOME>f2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>A</NAME>
<OUTCOME>a1</OUTCOME>
<OUTCOME>a2</OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>B</FOR>
<TABLE> .005 .995 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>F</FOR>
<TABLE> .03 .97 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>A</FOR>
<GIVEN>B</GIVEN>
<GIVEN>F</GIVEN>
<TABLE> .992 .008 .99 .01 .2 .8 .003 .997 </TABLE>
</DEFINITION>
</NETWORK>
</BIF>

View File

@ -1,36 +0,0 @@
:- use_module(library(clpbn)).
:- set_clpbn_flag(solver, bp).
%:- set_clpbn_flag(solver, jt).
%
% B F
% \ /
% \ /
% A
%
b(B) :-
b_table(BDist),
{ B = b with p([b1, b2], BDist) }.
f(F) :-
f_table(FDist),
{ F = f with p([f1, f2], FDist) }.
a(A) :-
b(B),
f(F),
a_table(ADist),
{ A = a with p([a1, a2], ADist, [B, F]) }.
b_table([0.005, 0.995]).
f_table([0.03, 0.97]).
a_table([0.992, 0.99, 0.2, 0.003,
0.008, 0.01, 0.8, 0.997]).

View File

@ -1,128 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--
A B C
\ | /
\ | /
D
/ | \
/ | \
E F G
-->
<BIF VERSION="0.3">
<NETWORK>
<NAME>Node with several parents and childs</NAME>
<VARIABLE TYPE="nature">
<NAME>A</NAME>
<OUTCOME>a1</OUTCOME>
<OUTCOME>a2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>B</NAME>
<OUTCOME>b1</OUTCOME>
<OUTCOME>b2</OUTCOME>
<OUTCOME>b3</OUTCOME>
<OUTCOME>b4</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>C</NAME>
<OUTCOME>c1</OUTCOME>
<OUTCOME>c2</OUTCOME>
<OUTCOME>c3</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>D</NAME>
<OUTCOME>d1</OUTCOME>
<OUTCOME>d2</OUTCOME>
<OUTCOME>d3</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>E</NAME>
<OUTCOME>e1</OUTCOME>
<OUTCOME>e2</OUTCOME>
<OUTCOME>e3</OUTCOME>
<OUTCOME>e4</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>F</NAME>
<OUTCOME>f1</OUTCOME>
<OUTCOME>f2</OUTCOME>
<OUTCOME>f3</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>G</NAME>
<OUTCOME>g1</OUTCOME>
<OUTCOME>g2</OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>A</FOR>
<TABLE> .1 .2 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>B</FOR>
<TABLE> .01 .02 .03 .04 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>C</FOR>
<TABLE> .11 .22 .33 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>D</FOR>
<GIVEN>A</GIVEN>
<GIVEN>B</GIVEN>
<GIVEN>C</GIVEN>
<TABLE>
.522 .008 .99 .01 .2 .8 .003 .457 .423 .007 .92 .04 .5 .232 .033 .227 .112 .048 .91 .21 .24 .18 .005 .227
.212 .04 .59 .21 .6 .1 .023 .215 .913 .017 .96 .01 .55 .422 .013 .417 .272 .068 .61 .11 .26 .28 .205 .322
.142 .028 .19 .11 .5 .67 .013 .437 .163 .067 .12 .06 .1 .262 .063 .167 .512 .028 .11 .41 .14 .68 .015 .92
</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>E</FOR>
<GIVEN>D</GIVEN>
<TABLE>
.111 .11 .1
.222 .22 .2
.333 .33 .3
.444 .44 .4
</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>F</FOR>
<GIVEN>D</GIVEN>
<TABLE>
.112 .111 .110
.223 .222 .221
.334 .333 .332
</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>G</FOR>
<GIVEN>D</GIVEN>
<TABLE>
.101 .102 .103
.201 .202 .203
</TABLE>
</DEFINITION>
</NETWORK>
</BIF>

View File

@ -0,0 +1,120 @@
14
1
6
2
2
0 9.974182
1 1.000000
1
7
2
2
0 9.974182
1 1.000000
1
4
2
2
0 4.055200
1 1.000000
1
5
2
2
0 4.055200
1 1.000000
1
0
2
2
0 7.389056
1 1.000000
1
2
2
2
0 7.389056
1 1.000000
1
1
2
2
0 7.389056
1 1.000000
1
3
2
2
0 7.389056
1 1.000000
2
4 6
2 2
4
0 4.481689
1 1.000000
2 4.481689
3 4.481689
2
5 7
2 2
4
0 4.481689
1 1.000000
2 4.481689
3 4.481689
2
0 4
2 2
4
0 3.004166
1 3.004166
2 3.004166
3 3.004166
3
2 5 4
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
1 4 5
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
2
3 5
2 2
4
0 3.004166
1 3.004166
2 3.004166
3 3.004166

View File

@ -0,0 +1,239 @@
27
1
12
2
2
0 9.974182
1 1.000000
1
13
2
2
0 9.974182
1 1.000000
1
14
2
2
0 9.974182
1 1.000000
1
9
2
2
0 4.055200
1 1.000000
1
10
2
2
0 4.055200
1 1.000000
1
11
2
2
0 4.055200
1 1.000000
1
0
2
2
0 7.389056
1 1.000000
1
3
2
2
0 7.389056
1 1.000000
1
6
2
2
0 7.389056
1 1.000000
1
1
2
2
0 7.389056
1 1.000000
1
4
2
2
0 7.389056
1 1.000000
1
7
2
2
0 7.389056
1 1.000000
1
2
2
2
0 7.389056
1 1.000000
1
5
2
2
0 7.389056
1 1.000000
1
8
2
2
0 7.389056
1 1.000000
2
9 12
2 2
4
0 4.481689
1 1.000000
2 4.481689
3 4.481689
2
10 13
2 2
4
0 4.481689
1 1.000000
2 4.481689
3 4.481689
2
11 14
2 2
4
0 4.481689
1 1.000000
2 4.481689
3 4.481689
2
0 9
2 2
4
0 3.004166
1 3.004166
2 3.004166
3 3.004166
3
3 10 9
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
6 11 9
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
1 9 10
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
2
4 10
2 2
4
0 3.004166
1 3.004166
2 3.004166
3 3.004166
3
7 11 10
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
2 9 11
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
5 10 11
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
2
8 11
2 2
4
0 3.004166
1 3.004166
2 3.004166
3 3.004166

View File

@ -0,0 +1,398 @@
44
1
20
2
2
0 9.974182
1 1.000000
1
21
2
2
0 9.974182
1 1.000000
1
22
2
2
0 9.974182
1 1.000000
1
23
2
2
0 9.974182
1 1.000000
1
16
2
2
0 4.055200
1 1.000000
1
17
2
2
0 4.055200
1 1.000000
1
18
2
2
0 4.055200
1 1.000000
1
19
2
2
0 4.055200
1 1.000000
1
0
2
2
0 7.389056
1 1.000000
1
4
2
2
0 7.389056
1 1.000000
1
8
2
2
0 7.389056
1 1.000000
1
12
2
2
0 7.389056
1 1.000000
1
1
2
2
0 7.389056
1 1.000000
1
5
2
2
0 7.389056
1 1.000000
1
9
2
2
0 7.389056
1 1.000000
1
13
2
2
0 7.389056
1 1.000000
1
2
2
2
0 7.389056
1 1.000000
1
6
2
2
0 7.389056
1 1.000000
1
10
2
2
0 7.389056
1 1.000000
1
14
2
2
0 7.389056
1 1.000000
1
3
2
2
0 7.389056
1 1.000000
1
7
2
2
0 7.389056
1 1.000000
1
11
2
2
0 7.389056
1 1.000000
1
15
2
2
0 7.389056
1 1.000000
2
16 20
2 2
4
0 4.481689
1 1.000000
2 4.481689
3 4.481689
2
17 21
2 2
4
0 4.481689
1 1.000000
2 4.481689
3 4.481689
2
18 22
2 2
4
0 4.481689
1 1.000000
2 4.481689
3 4.481689
2
19 23
2 2
4
0 4.481689
1 1.000000
2 4.481689
3 4.481689
2
0 16
2 2
4
0 3.004166
1 3.004166
2 3.004166
3 3.004166
3
4 17 16
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
8 18 16
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
12 19 16
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
1 16 17
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
2
5 17
2 2
4
0 3.004166
1 3.004166
2 3.004166
3 3.004166
3
9 18 17
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
13 19 17
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
2 16 18
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
6 17 18
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
2
10 18
2 2
4
0 3.004166
1 3.004166
2 3.004166
3 3.004166
3
14 19 18
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
3 16 19
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
7 17 19
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
3
11 18 19
2 2 2
8
0 3.004166
1 3.004166
2 3.004166
3 1.000000
4 3.004166
5 1.000000
6 3.004166
7 3.004166
2
15 19
2 2
4
0 3.004166
1 3.004166
2 3.004166
3 3.004166

View File

@ -1,17 +0,0 @@
MARKOV
3
2 2 2
3
1 0
1 1
3 2 0 1
2
.695 .305
2
.25 .75
8
0.2 0.45 0.32 0.7
0.8 0.55 0.68 0.3

View File

@ -1,36 +0,0 @@
MARKOV
5
4 2 3 2 3
7
1 0
1 1
1 2
1 3
1 4
2 0 1
4 1 2 3 4
4
0.1 0.7 0.43 0.22
2
0.2 0.6
3
0.3 0.5 0.2
2
0.15 0.75
3
0.25 0.45 0.15
8
0.210 0.333 0.457 0.4
0.811 0.000 0.189 0.89
36
0.1 0.15 0.2 0.25 0.3 0.45 0.5 0.55 0.65 0.7 0.75 0.9
0.11 0.22 0.33 0.44 0.55 0.66 0.77 0.88 0.91 0.93 0.95 0.97
0.42 0.22 0.33 0.44 0.15 0.36 0.27 0.28 0.21 0.13 0.25 0.17

View File

@ -1,128 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--
A B C
\ | /
\ | /
D
/ | \
/ | \
E F G
-->
<BIF VERSION="0.3">
<NETWORK>
<NAME>Node with several parents and childs</NAME>
<VARIABLE TYPE="nature">
<NAME>A</NAME>
<OUTCOME>a1</OUTCOME>
<OUTCOME>a2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>B</NAME>
<OUTCOME>b1</OUTCOME>
<OUTCOME>b2</OUTCOME>
<OUTCOME>b3</OUTCOME>
<OUTCOME>b4</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>C</NAME>
<OUTCOME>c1</OUTCOME>
<OUTCOME>c2</OUTCOME>
<OUTCOME>c3</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>D</NAME>
<OUTCOME>d1</OUTCOME>
<OUTCOME>d2</OUTCOME>
<OUTCOME>d3</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>E</NAME>
<OUTCOME>e1</OUTCOME>
<OUTCOME>e2</OUTCOME>
<OUTCOME>e3</OUTCOME>
<OUTCOME>e4</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>F</NAME>
<OUTCOME>f1</OUTCOME>
<OUTCOME>f2</OUTCOME>
<OUTCOME>f3</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>G</NAME>
<OUTCOME>g1</OUTCOME>
<OUTCOME>g2</OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>A</FOR>
<TABLE> .1 .2 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>B</FOR>
<TABLE> .01 .02 .03 .04 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>C</FOR>
<TABLE> .11 .22 .33 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>D</FOR>
<GIVEN>A</GIVEN>
<GIVEN>B</GIVEN>
<GIVEN>C</GIVEN>
<TABLE>
.522 .008 .99 .01 .2 .8 .003 .457 .423 .007 .92 .04 .5 .232 .033 .227 .112 .048 .91 .21 .24 .18 .005 .227
.212 .04 .59 .21 .6 .1 .023 .215 .913 .017 .96 .01 .55 .422 .013 .417 .272 .068 .61 .11 .26 .28 .205 .322
.142 .028 .19 .11 .5 .67 .013 .437 .163 .067 .12 .06 .1 .262 .063 .167 .512 .028 .11 .41 .14 .68 .015 .92
</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>E</FOR>
<GIVEN>D</GIVEN>
<TABLE>
.111 .11 .1
.222 .22 .2
.333 .33 .3
.444 .44 .4
</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>F</FOR>
<GIVEN>D</GIVEN>
<TABLE>
.112 .111 .110
.223 .222 .221
.334 .333 .332
</TABLE>
</DEFINITION>
<DEFINITION>
<FOR>G</FOR>
<GIVEN>D</GIVEN>
<TABLE>
.101 .102 .103
.201 .202 .203
</TABLE>
</DEFINITION>
</NETWORK>
</BIF>

View File

@ -1,36 +0,0 @@
MARKOV
5
4 2 3 2 3
7
1 0
1 1
1 2
1 3
1 4
2 0 1
4 1 2 3 4
4
0.1 0.7 0.43 0.22
2
0.2 0.6
3
0.3 0.5 0.2
2
0.15 0.75
3
0.25 0.45 0.15
8
0.210 0.333 0.457 0.4
0.811 0.000 0.189 0.89
36
0.1 0.15 0.2 0.25 0.3 0.45 0.5 0.55 0.65 0.7 0.75 0.9
0.11 0.22 0.33 0.44 0.55 0.66 0.77 0.88 0.91 0.93 0.95 0.97
0.42 0.22 0.33 0.44 0.15 0.36 0.27 0.28 0.21 0.13 0.25 0.17

View File

@ -1,60 +0,0 @@
#!/bin/bash
cp ~/bin/yap ~/bin/town_comp
YAP=~/bin/town_comp
#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log
OUT_FILE_NAME=bp_compress.log
rm -f $OUT_FILE_NAME
rm -f ignore.$OUT_FILE_NAME
function run_solver
{
if [ $2 = bp ]
then
extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\)
extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\)
extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\)
else
extra_flag1=true
extra_flag2=true
extra_flag3=true
fi
/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME
[$1].
clpbn:set_clpbn_flag(solver,$2),
clpbn_bp:use_log_space,
$extra_flag1, $extra_flag2, $extra_flag3,
run_query(_R),
open("$OUT_FILE_NAME", 'append',S),
format(S, '$3: ~15+ ',[]),
close(S).
EOF
}
function run_all_graphs
{
echo "*******************************************************************" >> "$OUT_FILE_NAME"
echo "results for solver $2" >> $OUT_FILE_NAME
echo "*******************************************************************" >> "$OUT_FILE_NAME"
run_solver town_1000 $1 town_1000 $3 $4 $5
run_solver town_5000 $1 town_5000 $3 $4 $5
run_solver town_10000 $1 town_10000 $3 $4 $5
run_solver town_50000 $1 town_50000 $3 $4 $5
run_solver town_100000 $1 town_100000 $3 $4 $5
run_solver town_500000 $1 town_500000 $3 $4 $5
run_solver town_1000000 $1 town_1000000 $3 $4 $5
run_solver town_2500000 $1 town_2500000 $3 $4 $5
run_solver town_5000000 $1 town_5000000 $3 $4 $5
run_solver town_7500000 $1 town_7500000 $3 $4 $5
run_solver town_10000000 $1 town_10000000 $3 $4 $5
}
run_solver town_10000 "bp(compress,seq_fixed)" town_10000 compress seq_fixed true
exit
##########
run_all_graphs bp "bp(compress,seq_fixed) " compress seq_fixed true

View File

@ -1,51 +0,0 @@
#!/bin/bash
YAP=~/bin/town_conv
#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log
OUT_FILE_NAME=bp_convert.log
rm -f $OUT_FILE_NAME
rm -f ignore.$OUT_FILE_NAME
function run_solver
{
if [ $2 = bp ]
then
extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\)
extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\)
extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\)
else
extra_flag1=true
extra_flag2=true
extra_flag3=true
fi
/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME
[$1].
clpbn:set_clpbn_flag(solver,$2),
clpbn_bp:use_log_space,
$extra_flag1, $extra_flag2, $extra_flag3,
run_query(_R),
open("$OUT_FILE_NAME", 'append',S),
format(S, '$3: ~15+ ',[]),
close(S).
EOF
}
function run_all_graphs
{
echo "*******************************************************************" >> "$OUT_FILE_NAME"
echo "results for solver $2" >> $OUT_FILE_NAME
echo "*******************************************************************" >> "$OUT_FILE_NAME"
run_solver town_1000 $1 town_1000 $3 $4 $5
run_solver town_5000 $1 town_5000 $3 $4 $5
run_solver town_10000 $1 town_10000 $3 $4 $5
run_solver town_50000 $1 town_50000 $3 $4 $5
run_solver town_100000 $1 town_100000 $3 $4 $5
run_solver town_500000 $1 town_500000 $3 $4 $5
run_solver town_1000000 $1 town_1000000 $3 $4 $5
}
run_all_graphs bp "bp(convert,seq_fixed) " convert seq_fixed false

View File

@ -1,50 +0,0 @@
#!/bin/bash
YAP=~/bin/town_norm
#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log
OUT_FILE_NAME=bp_normal.log
rm -f $OUT_FILE_NAME
rm -f ignore.$OUT_FILE_NAME
function run_solver
{
if [ $2 = bp ]
then
extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\)
extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\)
extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\)
else
extra_flag1=true
extra_flag2=true
extra_flag3=true
fi
/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME
[$1].
clpbn:set_clpbn_flag(solver,$2),
clpbn_bp:use_log_space,
$extra_flag1, $extra_flag2, $extra_flag3,
run_query(_R),
open("$OUT_FILE_NAME", 'append',S),
format(S, '$3: ~15+ ',[]),
close(S).
EOF
}
function run_all_graphs
{
echo "*******************************************************************" >> "$OUT_FILE_NAME"
echo "results for solver $2" >> $OUT_FILE_NAME
echo "*******************************************************************" >> "$OUT_FILE_NAME"
run_solver town_1000 $1 town_1000 $3 $4 $5
run_solver town_5000 $1 town_5000 $3 $4 $5
run_solver town_10000 $1 town_10000 $3 $4 $5
run_solver town_50000 $1 town_50000 $3 $4 $5
run_solver town_100000 $1 town_100000 $3 $4 $5
run_solver town_500000 $1 town_500000 $3 $4 $5
run_solver town_1000000 $1 town_1000000 $3 $4 $5
}
run_all_graphs bp "bp(normal,seq_fixed) " normal seq_fixed false

View File

@ -1,51 +0,0 @@
#!/bin/bash
YAP=~/bin/town_gibbs
#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log
OUT_FILE_NAME=gibbs.log
rm -f $OUT_FILE_NAME
rm -f ignore.$OUT_FILE_NAME
function run_solver
{
if [ $2 = bp ]
then
extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\)
extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\)
extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\)
else
extra_flag1=true
extra_flag2=true
extra_flag3=true
fi
/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME
[$1].
clpbn:set_clpbn_flag(solver,$2),
clpbn_bp:use_log_space,
$extra_flag1, $extra_flag2, $extra_flag3,
run_query(_R),
open("$OUT_FILE_NAME", 'append',S),
format(S, '$3: ~15+ ',[]),
close(S).
EOF
}
function run_all_graphs
{
echo "*******************************************************************" >> "$OUT_FILE_NAME"
echo "results for solver $2" >> $OUT_FILE_NAME
echo "*******************************************************************" >> "$OUT_FILE_NAME"
run_solver town_1000 $1 town_1000 $3 $4 $5
run_solver town_5000 $1 town_5000 $3 $4 $5
run_solver town_10000 $1 town_10000 $3 $4 $5
run_solver town_50000 $1 town_50000 $3 $4 $5
run_solver town_100000 $1 town_100000 $3 $4 $5
run_solver town_500000 $1 town_500000 $3 $4 $5
run_solver town_1000000 $1 town_1000000 $3 $4 $5
}
run_all_graphs gibbs "gibbs "

View File

@ -1,51 +0,0 @@
#!/bin/bash
YAP=~/bin/town_jt
#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log
OUT_FILE_NAME=jt.log
rm -f $OUT_FILE_NAME
rm -f ignore.$OUT_FILE_NAME
function run_solver
{
if [ $2 = bp ]
then
extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\)
extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\)
extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\)
else
extra_flag1=true
extra_flag2=true
extra_flag3=true
fi
/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME
[$1].
clpbn:set_clpbn_flag(solver,$2),
clpbn_bp:use_log_space,
$extra_flag1, $extra_flag2, $extra_flag3,
run_query(_R),
open("$OUT_FILE_NAME", 'append',S),
format(S, '$3: ~15+ ',[]),
close(S).
EOF
}
function run_all_graphs
{
echo "*******************************************************************" >> "$OUT_FILE_NAME"
echo "results for solver $2" >> $OUT_FILE_NAME
echo "*******************************************************************" >> "$OUT_FILE_NAME"
run_solver town_1000 $1 town_1000 $3 $4 $5
run_solver town_5000 $1 town_5000 $3 $4 $5
run_solver town_10000 $1 town_10000 $3 $4 $5
run_solver town_50000 $1 town_50000 $3 $4 $5
run_solver town_100000 $1 town_100000 $3 $4 $5
run_solver town_500000 $1 town_500000 $3 $4 $5
run_solver town_1000000 $1 town_1000000 $3 $4 $5
}
run_all_graphs jt "jt "

View File

@ -1,51 +0,0 @@
#!/bin/bash
YAP=~/bin/town_ve
#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log
OUT_FILE_NAME=ve.log
rm -f $OUT_FILE_NAME
rm -f ignore.$OUT_FILE_NAME
function run_solver
{
if [ $2 = bp ]
then
extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\)
extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\)
extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\)
else
extra_flag1=true
extra_flag2=true
extra_flag3=true
fi
/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME
[$1].
clpbn:set_clpbn_flag(solver,$2),
clpbn_bp:use_log_space,
$extra_flag1, $extra_flag2, $extra_flag3,
run_query(_R),
open("$OUT_FILE_NAME", 'append',S),
format(S, '$3: ~15+ ',[]),
close(S).
EOF
}
function run_all_graphs
{
echo "*******************************************************************" >> "$OUT_FILE_NAME"
echo "results for solver $2" >> $OUT_FILE_NAME
echo "*******************************************************************" >> "$OUT_FILE_NAME"
run_solver town_1000 $1 town_1000 $3 $4 $5
run_solver town_5000 $1 town_5000 $3 $4 $5
run_solver town_10000 $1 town_10000 $3 $4 $5
run_solver town_50000 $1 town_50000 $3 $4 $5
run_solver town_100000 $1 town_100000 $3 $4 $5
run_solver town_500000 $1 town_500000 $3 $4 $5
run_solver town_1000000 $1 town_1000000 $3 $4 $5
}
run_all_graphs ve "ve "

View File

@ -1,65 +0,0 @@
conservative_city(City, Cons) :-
cons_table(City, ConsDist),
{ Cons = conservative_city(City) with p([y,n], ConsDist) }.
gender(X, Gender) :-
gender_table(X, GenderDist),
{ Gender = gender(X) with p([m,f], GenderDist) }.
hair_color(X, Color) :-
lives(X, City),
conservative_city(City, Cons),
hair_color_table(X,ColorTable),
{ Color = hair_color(X) with
p([t,f], ColorTable,[Cons]) }.
car_color(X, Color) :-
hair_color(X, HColor),
car_color_table(X,CColorTable),
{ Color = car_color(X) with
p([t,f], CColorTable,[HColor]) }.
height(X, Height) :-
gender(X, Gender),
height_table(X,HeightTable),
{ Height = height(X) with
p([t,f], HeightTable,[Gender]) }.
shoe_size(X, Shoesize) :-
height(X, Height),
shoe_size_table(X,ShoesizeTable),
{ Shoesize = shoe_size(X) with
p([t,f], ShoesizeTable,[Height]) }.
guilty(X, Guilt) :-
guilty_table(X, GuiltDist),
{ Guilt = guilty(X) with p([y,n], GuiltDist) }.
descn(X, Descn) :-
car_color(X, Car),
hair_color(X, Hair),
height(X, Height),
guilty(X, Guilt),
descn_table(X, DescTable),
{ Descn = descn(X) with
p([t,f], DescTable,[Car,Hair,Height,Guilt]) }.
witness(City, Witness) :-
descn(joe, DescnJ),
descn(p2, Descn2),
wit_table(WitTable),
{ Witness = witness(City) with
p([t,f], WitTable,[DescnJ, Descn2]) }.
:- ensure_loaded(tables).

View File

@ -1,46 +0,0 @@
cons_table(amsterdam, [0.2, 0.8]) :- !.
cons_table(_, [0.8, 0.2]).
gender_table(_, [0.55, 0.44]).
hair_color_table(_,
/* conservative_city */
/* y n */
[ 0.05, 0.1,
0.95, 0.9 ]).
car_color_table(_,
/* t f */
[ 0.9, 0.2,
0.1, 0.8 ]).
height_table(_,
/* m f */
[ 0.6, 0.4,
0.4, 0.6 ]).
shoe_size_table(_,
/* t f */
[ 0.9, 0.1,
0.1, 0.9 ]).
guilty_table(_, [0.23, 0.77]).
descn_table(_,
/* color, hair, height, guilt */
/* ttttt tttf ttft ttff tfttt tftf tfft tfff ttttt fttf ftft ftff ffttt fftf ffft ffff */
[ 0.99, 0.5, 0.23, 0.88, 0.41, 0.3, 0.76, 0.87, 0.44, 0.43, 0.29, 0.72, 0.33, 0.91, 0.95, 0.92,
0.01, 0.5, 0.77, 0.12, 0.59, 0.7, 0.24, 0.13, 0.56, 0.57, 0.61, 0.28, 0.77, 0.09, 0.05, 0.08]).
wit_table([0.2, 0.45, 0.24, 0.34,
0.8, 0.55, 0.76, 0.66]).

View File

@ -1,59 +0,0 @@
#!/home/tgomes/bin/yap -L --
/*
Steps:
1. generate N facts lives(I, nyc), 0 <= I < N.
2. generate evidence on descn for N people, *** except for 1 ***
3. Run query ?- guilty(joe, Guilty), witness(joe, t), descn(2,t), descn(3, f), descn(4, f) ...
*/
:- initialization(main).
main :-
unix(argv([H])),
generate_town(H).
generate_town(N) :-
atomic_concat(['town_', N, '.yap'], FileName),
open(FileName, 'write', S),
write(S, ':- source.\n'),
write(S, ':- style_check(all).\n'),
write(S, ':- yap_flag(unknown,error).\n'),
write(S, ':- yap_flag(write_strings,on).\n'),
write(S, ':- use_module(library(clpbn)).\n'),
write(S, ':- set_clpbn_flag(solver, bp).\n'),
write(S, ':- [-schema].\n\n'),
write(S, 'lives(_joe, nyc).\n'),
atom_number(N, N2),
generate_people(S, N2, 2),
write(S, '\nrun_query(Guilty) :- \n'),
write(S, '\tguilty(joe, Guilty),\n'),
write(S, '\twitness(nyc, t),\n'),
write(S, '\trunall(X, ev(X)).\n\n\n'),
write(S, 'runall(G, Wrapper) :-\n'),
write(S, '\tfindall(G, Wrapper, L),\n'),
write(S, '\texecute_all(L).\n\n\n'),
write(S, 'execute_all([]).\n'),
write(S, 'execute_all(G.L) :-\n'),
write(S, '\tcall(G),\n'),
write(S, '\texecute_all(L).\n\n\n'),
generate_query(S, N2, 2),
close(S).
generate_people(_, N, Counting1) :- !.
generate_people(S, N, Counting) :-
format(S, 'lives(p~w, nyc).~n', [Counting]),
Counting1 is Counting + 1,
generate_people(S, N, Counting1).
generate_query(S, N, Counting) :-
Counting > N, !.
generate_query(S, N, Counting) :- !,
format(S, 'ev(descn(p~w, t)).~n', [Counting]),
Counting1 is Counting + 1,
generate_query(S, N, Counting1).

View File

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--
A B
\ /
\ /
C
|
|
D
-->
<BIF VERSION="0.3">
<NETWORK>
<NAME>Simple Loop</NAME>
<VARIABLE TYPE="nature">
<NAME>A</NAME>
<OUTCOME>a1</OUTCOME>
<OUTCOME>a2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>B</NAME>
<OUTCOME>b1</OUTCOME>
<OUTCOME>b2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>C</NAME>
<OUTCOME>c1</OUTCOME>
<OUTCOME>c2</OUTCOME>
</VARIABLE>
<VARIABLE TYPE="nature">
<NAME>D</NAME>
<OUTCOME>d1</OUTCOME>
<OUTCOME>d2</OUTCOME>
</VARIABLE>
<DEFINITION>
<FOR>A</FOR>
<TABLE> .001 .009 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>B</FOR>
<TABLE> .002 .008 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>C</FOR>
<GIVEN>A</GIVEN>
<GIVEN>B</GIVEN>
<TABLE> .95 .05 .94 .06 .29 .71 .001 .999 </TABLE>
</DEFINITION>
<DEFINITION>
<FOR>D</FOR>
<GIVEN>C</GIVEN>
<TABLE> .9 .1 .05 .95 </TABLE>
</DEFINITION>
</NETWORK>
</BIF>