ok, second try
This commit is contained in:
parent
3388917aa5
commit
6c77afb3ae
86
packages/CLPBN/horus/BayesBall.cpp
Normal file
86
packages/CLPBN/horus/BayesBall.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "BayesBall.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
|
||||
|
||||
FactorGraph*
|
||||
BayesBall::getMinimalFactorGraph (const VarIds& queryIds)
|
||||
{
|
||||
assert (fg_.isFromBayesNetwork());
|
||||
Scheduling scheduling;
|
||||
for (unsigned i = 0; i < queryIds.size(); i++) {
|
||||
assert (dag_.getNode (queryIds[i]));
|
||||
DAGraphNode* n = dag_.getNode (queryIds[i]);
|
||||
scheduling.push (ScheduleInfo (n, false, true));
|
||||
}
|
||||
|
||||
while (!scheduling.empty()) {
|
||||
ScheduleInfo& sch = scheduling.front();
|
||||
DAGraphNode* n = sch.node;
|
||||
n->setAsVisited();
|
||||
if (n->hasEvidence() == false && sch.visitedFromChild) {
|
||||
if (n->isMarkedOnTop() == false) {
|
||||
n->markOnTop();
|
||||
scheduleParents (n, scheduling);
|
||||
}
|
||||
if (n->isMarkedOnBottom() == false) {
|
||||
n->markOnBottom();
|
||||
scheduleChilds (n, scheduling);
|
||||
}
|
||||
}
|
||||
if (sch.visitedFromParent) {
|
||||
if (n->hasEvidence() && n->isMarkedOnTop() == false) {
|
||||
n->markOnTop();
|
||||
scheduleParents (n, scheduling);
|
||||
}
|
||||
if (n->hasEvidence() == false && n->isMarkedOnBottom() == false) {
|
||||
n->markOnBottom();
|
||||
scheduleChilds (n, scheduling);
|
||||
}
|
||||
}
|
||||
scheduling.pop();
|
||||
}
|
||||
|
||||
FactorGraph* fg = new FactorGraph();
|
||||
constructGraph (fg);
|
||||
return fg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BayesBall::constructGraph (FactorGraph* fg) const
|
||||
{
|
||||
const FacNodes& facNodes = fg_.facNodes();
|
||||
for (unsigned i = 0; i < facNodes.size(); i++) {
|
||||
const DAGraphNode* n = dag_.getNode (
|
||||
facNodes[i]->factor().argument (0));
|
||||
if (n->isMarkedOnTop()) {
|
||||
fg->addFactor (facNodes[i]->factor());
|
||||
} else if (n->hasEvidence() && n->isVisited()) {
|
||||
VarIds varIds = { facNodes[i]->factor().argument (0) };
|
||||
Ranges ranges = { facNodes[i]->factor().range (0) };
|
||||
Params params (ranges[0], LogAware::noEvidence());
|
||||
params[n->getEvidence()] = LogAware::withEvidence();
|
||||
fg->addFactor (Factor (varIds, ranges, params));
|
||||
}
|
||||
}
|
||||
const VarNodes& varNodes = fg_.varNodes();
|
||||
for (unsigned i = 0; i < varNodes.size(); i++) {
|
||||
if (varNodes[i]->hasEvidence()) {
|
||||
VarNode* vn = fg->getVarNode (varNodes[i]->varId());
|
||||
if (vn) {
|
||||
vn->setEvidence (varNodes[i]->getEvidence());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
85
packages/CLPBN/horus/BayesBall.h
Normal file
85
packages/CLPBN/horus/BayesBall.h
Normal file
@ -0,0 +1,85 @@
|
||||
#ifndef HORUS_BAYESBALL_H
|
||||
#define HORUS_BAYESBALL_H
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "FactorGraph.h"
|
||||
#include "BayesNet.h"
|
||||
#include "Horus.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
struct ScheduleInfo
|
||||
{
|
||||
ScheduleInfo (DAGraphNode* n, bool vfp, bool vfc) :
|
||||
node(n), visitedFromParent(vfp), visitedFromChild(vfc) { }
|
||||
|
||||
DAGraphNode* node;
|
||||
bool visitedFromParent;
|
||||
bool visitedFromChild;
|
||||
};
|
||||
|
||||
|
||||
typedef queue<ScheduleInfo, list<ScheduleInfo>> Scheduling;
|
||||
|
||||
|
||||
class BayesBall
|
||||
{
|
||||
public:
|
||||
BayesBall (FactorGraph& fg)
|
||||
: fg_(fg) , dag_(fg.getStructure())
|
||||
{
|
||||
dag_.clear();
|
||||
}
|
||||
|
||||
FactorGraph* getMinimalFactorGraph (const VarIds&);
|
||||
|
||||
static FactorGraph* getMinimalFactorGraph (FactorGraph& fg, VarIds vids)
|
||||
{
|
||||
BayesBall bb (fg);
|
||||
return bb.getMinimalFactorGraph (vids);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void constructGraph (FactorGraph* fg) const;
|
||||
|
||||
void scheduleParents (const DAGraphNode* n, Scheduling& sch) const;
|
||||
|
||||
void scheduleChilds (const DAGraphNode* n, Scheduling& sch) const;
|
||||
|
||||
FactorGraph& fg_;
|
||||
|
||||
DAGraph& dag_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline void
|
||||
BayesBall::scheduleParents (const DAGraphNode* n, Scheduling& sch) const
|
||||
{
|
||||
const vector<DAGraphNode*>& ps = n->parents();
|
||||
for (vector<DAGraphNode*>::const_iterator it = ps.begin();
|
||||
it != ps.end(); it++) {
|
||||
sch.push (ScheduleInfo (*it, false, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void
|
||||
BayesBall::scheduleChilds (const DAGraphNode* n, Scheduling& sch) const
|
||||
{
|
||||
const vector<DAGraphNode*>& cs = n->childs();
|
||||
for (vector<DAGraphNode*>::const_iterator it = cs.begin();
|
||||
it != cs.end(); it++) {
|
||||
sch.push (ScheduleInfo (*it, true, false));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HORUS_BAYESBALL_H
|
||||
|
107
packages/CLPBN/horus/BayesNet.cpp
Normal file
107
packages/CLPBN/horus/BayesNet.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "BayesNet.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
void
|
||||
DAGraph::addNode (DAGraphNode* n)
|
||||
{
|
||||
assert (Util::contains (varMap_, n->varId()) == false);
|
||||
nodes_.push_back (n);
|
||||
varMap_[n->varId()] = n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
DAGraph::addEdge (VarId vid1, VarId vid2)
|
||||
{
|
||||
unordered_map<VarId, DAGraphNode*>::iterator it1;
|
||||
unordered_map<VarId, DAGraphNode*>::iterator it2;
|
||||
it1 = varMap_.find (vid1);
|
||||
it2 = varMap_.find (vid2);
|
||||
assert (it1 != varMap_.end());
|
||||
assert (it2 != varMap_.end());
|
||||
it1->second->addChild (it2->second);
|
||||
it2->second->addParent (it1->second);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const DAGraphNode*
|
||||
DAGraph::getNode (VarId vid) const
|
||||
{
|
||||
unordered_map<VarId, DAGraphNode*>::const_iterator it;
|
||||
it = varMap_.find (vid);
|
||||
return it != varMap_.end() ? it->second : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DAGraphNode*
|
||||
DAGraph::getNode (VarId vid)
|
||||
{
|
||||
unordered_map<VarId, DAGraphNode*>::const_iterator it;
|
||||
it = varMap_.find (vid);
|
||||
return it != varMap_.end() ? it->second : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
DAGraph::setIndexes (void)
|
||||
{
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
nodes_[i]->setIndex (i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
DAGraph::clear (void)
|
||||
{
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
nodes_[i]->clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
DAGraph::exportToGraphViz (const char* fileName)
|
||||
{
|
||||
ofstream out (fileName);
|
||||
if (!out.is_open()) {
|
||||
cerr << "error: cannot open file to write at " ;
|
||||
cerr << "DAGraph::exportToDotFile()" << endl;
|
||||
abort();
|
||||
}
|
||||
out << "digraph {" << endl;
|
||||
out << "ranksep=1" << endl;
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
out << nodes_[i]->varId() ;
|
||||
out << " [" ;
|
||||
out << "label=\"" << nodes_[i]->label() << "\"" ;
|
||||
if (nodes_[i]->hasEvidence()) {
|
||||
out << ",style=filled, fillcolor=yellow" ;
|
||||
}
|
||||
out << "]" << endl;
|
||||
}
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
const vector<DAGraphNode*>& childs = nodes_[i]->childs();
|
||||
for (unsigned j = 0; j < childs.size(); j++) {
|
||||
out << nodes_[i]->varId() << " -> " << childs[j]->varId();
|
||||
out << " [style=bold]" << endl ;
|
||||
}
|
||||
}
|
||||
out << "}" << endl;
|
||||
out.close();
|
||||
}
|
||||
|
88
packages/CLPBN/horus/BayesNet.h
Normal file
88
packages/CLPBN/horus/BayesNet.h
Normal file
@ -0,0 +1,88 @@
|
||||
#ifndef HORUS_BAYESNET_H
|
||||
#define HORUS_BAYESNET_H
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "Var.h"
|
||||
#include "Horus.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
class Var;
|
||||
|
||||
class DAGraphNode : public Var
|
||||
{
|
||||
public:
|
||||
DAGraphNode (Var* v) : Var (v) , visited_(false),
|
||||
markedOnTop_(false), markedOnBottom_(false) { }
|
||||
|
||||
const vector<DAGraphNode*>& childs (void) const { return childs_; }
|
||||
|
||||
vector<DAGraphNode*>& childs (void) { return childs_; }
|
||||
|
||||
const vector<DAGraphNode*>& parents (void) const { return parents_; }
|
||||
|
||||
vector<DAGraphNode*>& parents (void) { return parents_; }
|
||||
|
||||
void addParent (DAGraphNode* p) { parents_.push_back (p); }
|
||||
|
||||
void addChild (DAGraphNode* c) { childs_.push_back (c); }
|
||||
|
||||
bool isVisited (void) const { return visited_; }
|
||||
|
||||
void setAsVisited (void) { visited_ = true; }
|
||||
|
||||
bool isMarkedOnTop (void) const { return markedOnTop_; }
|
||||
|
||||
void markOnTop (void) { markedOnTop_ = true; }
|
||||
|
||||
bool isMarkedOnBottom (void) const { return markedOnBottom_; }
|
||||
|
||||
void markOnBottom (void) { markedOnBottom_ = true; }
|
||||
|
||||
void clear (void) { visited_ = markedOnTop_ = markedOnBottom_ = false; }
|
||||
|
||||
private:
|
||||
bool visited_;
|
||||
bool markedOnTop_;
|
||||
bool markedOnBottom_;
|
||||
|
||||
vector<DAGraphNode*> childs_;
|
||||
vector<DAGraphNode*> parents_;
|
||||
};
|
||||
|
||||
|
||||
class DAGraph
|
||||
{
|
||||
public:
|
||||
DAGraph (void) { }
|
||||
|
||||
void addNode (DAGraphNode* n);
|
||||
|
||||
void addEdge (VarId vid1, VarId vid2);
|
||||
|
||||
const DAGraphNode* getNode (VarId vid) const;
|
||||
|
||||
DAGraphNode* getNode (VarId vid);
|
||||
|
||||
bool empty (void) const { return nodes_.empty(); }
|
||||
|
||||
void setIndexes (void);
|
||||
|
||||
void clear (void);
|
||||
|
||||
void exportToGraphViz (const char*);
|
||||
|
||||
private:
|
||||
vector<DAGraphNode*> nodes_;
|
||||
|
||||
unordered_map<VarId, DAGraphNode*> varMap_;
|
||||
};
|
||||
|
||||
#endif // HORUS_BAYESNET_H
|
||||
|
526
packages/CLPBN/horus/BpSolver.cpp
Normal file
526
packages/CLPBN/horus/BpSolver.cpp
Normal file
@ -0,0 +1,526 @@
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "BpSolver.h"
|
||||
#include "FactorGraph.h"
|
||||
#include "Factor.h"
|
||||
#include "Indexer.h"
|
||||
#include "Horus.h"
|
||||
|
||||
|
||||
BpSolver::BpSolver (const FactorGraph& fg) : Solver (fg)
|
||||
{
|
||||
fg_ = &fg;
|
||||
runned_ = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BpSolver::~BpSolver (void)
|
||||
{
|
||||
for (unsigned i = 0; i < varsI_.size(); i++) {
|
||||
delete varsI_[i];
|
||||
}
|
||||
for (unsigned i = 0; i < facsI_.size(); i++) {
|
||||
delete facsI_[i];
|
||||
}
|
||||
for (unsigned i = 0; i < links_.size(); i++) {
|
||||
delete links_[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
BpSolver::solveQuery (VarIds queryVids)
|
||||
{
|
||||
assert (queryVids.empty() == false);
|
||||
if (queryVids.size() == 1) {
|
||||
return getPosterioriOf (queryVids[0]);
|
||||
} else {
|
||||
return getJointDistributionOf (queryVids);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpSolver::printSolverFlags (void) const
|
||||
{
|
||||
stringstream ss;
|
||||
ss << "belief propagation [" ;
|
||||
ss << "schedule=" ;
|
||||
typedef BpOptions::Schedule Sch;
|
||||
switch (BpOptions::schedule) {
|
||||
case Sch::SEQ_FIXED: ss << "seq_fixed"; break;
|
||||
case Sch::SEQ_RANDOM: ss << "seq_random"; break;
|
||||
case Sch::PARALLEL: ss << "parallel"; break;
|
||||
case Sch::MAX_RESIDUAL: ss << "max_residual"; break;
|
||||
}
|
||||
ss << ",max_iter=" << Util::toString (BpOptions::maxIter);
|
||||
ss << ",accuracy=" << Util::toString (BpOptions::accuracy);
|
||||
ss << ",log_domain=" << Util::toString (Globals::logDomain);
|
||||
ss << "]" ;
|
||||
cout << ss.str() << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
BpSolver::getPosterioriOf (VarId vid)
|
||||
{
|
||||
if (runned_ == false) {
|
||||
runSolver();
|
||||
}
|
||||
assert (fg_->getVarNode (vid));
|
||||
VarNode* var = fg_->getVarNode (vid);
|
||||
Params probs;
|
||||
if (var->hasEvidence()) {
|
||||
probs.resize (var->range(), LogAware::noEvidence());
|
||||
probs[var->getEvidence()] = LogAware::withEvidence();
|
||||
} else {
|
||||
probs.resize (var->range(), LogAware::multIdenty());
|
||||
const SpLinkSet& links = ninf(var)->getLinks();
|
||||
if (Globals::logDomain) {
|
||||
for (unsigned i = 0; i < links.size(); i++) {
|
||||
Util::add (probs, links[i]->getMessage());
|
||||
}
|
||||
LogAware::normalize (probs);
|
||||
Util::fromLog (probs);
|
||||
} else {
|
||||
for (unsigned i = 0; i < links.size(); i++) {
|
||||
Util::multiply (probs, links[i]->getMessage());
|
||||
}
|
||||
LogAware::normalize (probs);
|
||||
}
|
||||
}
|
||||
return probs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
BpSolver::getJointDistributionOf (const VarIds& jointVarIds)
|
||||
{
|
||||
if (runned_ == false) {
|
||||
runSolver();
|
||||
}
|
||||
int idx = -1;
|
||||
VarNode* vn = fg_->getVarNode (jointVarIds[0]);
|
||||
const FacNodes& facNodes = vn->neighbors();
|
||||
for (unsigned i = 0; i < facNodes.size(); i++) {
|
||||
if (facNodes[i]->factor().contains (jointVarIds)) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == -1) {
|
||||
return getJointByConditioning (jointVarIds);
|
||||
} else {
|
||||
Factor res (facNodes[idx]->factor());
|
||||
const SpLinkSet& links = ninf(facNodes[idx])->getLinks();
|
||||
for (unsigned i = 0; i < links.size(); i++) {
|
||||
Factor msg ({links[i]->getVariable()->varId()},
|
||||
{links[i]->getVariable()->range()},
|
||||
getVar2FactorMsg (links[i]));
|
||||
res.multiply (msg);
|
||||
}
|
||||
res.sumOutAllExcept (jointVarIds);
|
||||
res.reorderArguments (jointVarIds);
|
||||
res.normalize();
|
||||
Params jointDist = res.params();
|
||||
if (Globals::logDomain) {
|
||||
Util::fromLog (jointDist);
|
||||
}
|
||||
return jointDist;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpSolver::runSolver (void)
|
||||
{
|
||||
clock_t start;
|
||||
if (Constants::COLLECT_STATS) {
|
||||
start = clock();
|
||||
}
|
||||
initializeSolver();
|
||||
nIters_ = 0;
|
||||
while (!converged() && nIters_ < BpOptions::maxIter) {
|
||||
nIters_ ++;
|
||||
if (Globals::verbosity > 1) {
|
||||
Util::printHeader (string ("Iteration ") + Util::toString (nIters_));
|
||||
}
|
||||
switch (BpOptions::schedule) {
|
||||
case BpOptions::Schedule::SEQ_RANDOM:
|
||||
random_shuffle (links_.begin(), links_.end());
|
||||
// no break
|
||||
case BpOptions::Schedule::SEQ_FIXED:
|
||||
for (unsigned i = 0; i < links_.size(); i++) {
|
||||
calculateAndUpdateMessage (links_[i]);
|
||||
}
|
||||
break;
|
||||
case BpOptions::Schedule::PARALLEL:
|
||||
for (unsigned i = 0; i < links_.size(); i++) {
|
||||
calculateMessage (links_[i]);
|
||||
}
|
||||
for (unsigned i = 0; i < links_.size(); i++) {
|
||||
updateMessage(links_[i]);
|
||||
}
|
||||
break;
|
||||
case BpOptions::Schedule::MAX_RESIDUAL:
|
||||
maxResidualSchedule();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Globals::verbosity > 0) {
|
||||
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;
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
unsigned size = fg_->varNodes().size();
|
||||
if (Constants::COLLECT_STATS) {
|
||||
unsigned nIters = 0;
|
||||
bool loopy = fg_->isTree() == false;
|
||||
if (loopy) nIters = nIters_;
|
||||
double time = (double (clock() - start)) / CLOCKS_PER_SEC;
|
||||
Statistics::updateStatistics (size, loopy, nIters, time);
|
||||
}
|
||||
runned_ = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpSolver::createLinks (void)
|
||||
{
|
||||
const FacNodes& facNodes = fg_->facNodes();
|
||||
for (unsigned i = 0; i < facNodes.size(); i++) {
|
||||
const VarNodes& neighbors = facNodes[i]->neighbors();
|
||||
for (unsigned j = 0; j < neighbors.size(); j++) {
|
||||
links_.push_back (new SpLink (facNodes[i], neighbors[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpSolver::maxResidualSchedule (void)
|
||||
{
|
||||
if (nIters_ == 1) {
|
||||
for (unsigned i = 0; i < links_.size(); i++) {
|
||||
calculateMessage (links_[i]);
|
||||
SortedOrder::iterator it = sortedOrder_.insert (links_[i]);
|
||||
linkMap_.insert (make_pair (links_[i], it));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned c = 0; c < links_.size(); c++) {
|
||||
if (Globals::verbosity > 1) {
|
||||
cout << "current residuals:" << endl;
|
||||
for (SortedOrder::iterator it = sortedOrder_.begin();
|
||||
it != sortedOrder_.end(); it ++) {
|
||||
cout << " " << setw (30) << left << (*it)->toString();
|
||||
cout << "residual = " << (*it)->getResidual() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
SortedOrder::iterator it = sortedOrder_.begin();
|
||||
SpLink* link = *it;
|
||||
if (link->getResidual() < BpOptions::accuracy) {
|
||||
return;
|
||||
}
|
||||
updateMessage (link);
|
||||
link->clearResidual();
|
||||
sortedOrder_.erase (it);
|
||||
linkMap_.find (link)->second = sortedOrder_.insert (link);
|
||||
|
||||
// update the messages that depend on message source --> destin
|
||||
const FacNodes& factorNeighbors = link->getVariable()->neighbors();
|
||||
for (unsigned i = 0; i < factorNeighbors.size(); i++) {
|
||||
if (factorNeighbors[i] != link->getFactor()) {
|
||||
const SpLinkSet& links = ninf(factorNeighbors[i])->getLinks();
|
||||
for (unsigned j = 0; j < links.size(); j++) {
|
||||
if (links[j]->getVariable() != link->getVariable()) {
|
||||
calculateMessage (links[j]);
|
||||
SpLinkMap::iterator iter = linkMap_.find (links[j]);
|
||||
sortedOrder_.erase (iter->second);
|
||||
iter->second = sortedOrder_.insert (links[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Globals::verbosity > 1) {
|
||||
Util::printDashedLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpSolver::calculateFactor2VariableMsg (SpLink* link)
|
||||
{
|
||||
FacNode* src = link->getFactor();
|
||||
const VarNode* dst = link->getVariable();
|
||||
const SpLinkSet& links = ninf(src)->getLinks();
|
||||
// calculate the product of messages that were sent
|
||||
// to factor `src', except from var `dst'
|
||||
unsigned msgSize = 1;
|
||||
for (unsigned i = 0; i < links.size(); i++) {
|
||||
msgSize *= links[i]->getVariable()->range();
|
||||
}
|
||||
unsigned repetitions = 1;
|
||||
Params msgProduct (msgSize, LogAware::multIdenty());
|
||||
if (Globals::logDomain) {
|
||||
for (int i = links.size() - 1; i >= 0; i--) {
|
||||
if (links[i]->getVariable() != dst) {
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " message from " << links[i]->getVariable()->label();
|
||||
cout << ": " ;
|
||||
}
|
||||
Util::add (msgProduct, getVar2FactorMsg (links[i]), repetitions);
|
||||
repetitions *= links[i]->getVariable()->range();
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << endl;
|
||||
}
|
||||
} else {
|
||||
unsigned range = links[i]->getVariable()->range();
|
||||
Util::add (msgProduct, Params (range, 0.0), repetitions);
|
||||
repetitions *= range;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = links.size() - 1; i >= 0; i--) {
|
||||
if (links[i]->getVariable() != dst) {
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " message from " << links[i]->getVariable()->label();
|
||||
cout << ": " ;
|
||||
}
|
||||
Util::multiply (msgProduct, getVar2FactorMsg (links[i]), repetitions);
|
||||
repetitions *= links[i]->getVariable()->range();
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << endl;
|
||||
}
|
||||
} else {
|
||||
unsigned range = links[i]->getVariable()->range();
|
||||
Util::multiply (msgProduct, Params (range, 1.0), repetitions);
|
||||
repetitions *= range;
|
||||
}
|
||||
}
|
||||
}
|
||||
Factor result (src->factor().arguments(),
|
||||
src->factor().ranges(), msgProduct);
|
||||
result.multiply (src->factor());
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " message product: " << msgProduct << endl;
|
||||
cout << " original factor: " << src->factor().params() << endl;
|
||||
cout << " factor product: " << result.params() << endl;
|
||||
}
|
||||
result.sumOutAllExcept (dst->varId());
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " marginalized: " << result.params() << endl;
|
||||
}
|
||||
link->getNextMessage() = result.params();
|
||||
LogAware::normalize (link->getNextMessage());
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " curr msg: " << link->getMessage() << endl;
|
||||
cout << " next msg: " << link->getNextMessage() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
BpSolver::getVar2FactorMsg (const SpLink* link) const
|
||||
{
|
||||
const VarNode* src = link->getVariable();
|
||||
const FacNode* dst = link->getFactor();
|
||||
Params msg;
|
||||
if (src->hasEvidence()) {
|
||||
msg.resize (src->range(), LogAware::noEvidence());
|
||||
msg[src->getEvidence()] = LogAware::withEvidence();
|
||||
} else {
|
||||
msg.resize (src->range(), LogAware::one());
|
||||
}
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << msg;
|
||||
}
|
||||
const SpLinkSet& links = ninf (src)->getLinks();
|
||||
if (Globals::logDomain) {
|
||||
SpLinkSet::const_iterator it;
|
||||
for (it = links.begin(); it != links.end(); ++ it) {
|
||||
Util::add (msg, (*it)->getMessage());
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " x " << (*it)->getMessage();
|
||||
}
|
||||
}
|
||||
Util::subtract (msg, link->getMessage());
|
||||
} else {
|
||||
for (unsigned i = 0; i < links.size(); i++) {
|
||||
if (links[i]->getFactor() != dst) {
|
||||
Util::multiply (msg, links[i]->getMessage());
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " x " << links[i]->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " = " << msg;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
BpSolver::getJointByConditioning (const VarIds& jointVarIds) const
|
||||
{
|
||||
VarNodes jointVars;
|
||||
for (unsigned i = 0; i < jointVarIds.size(); i++) {
|
||||
assert (fg_->getVarNode (jointVarIds[i]));
|
||||
jointVars.push_back (fg_->getVarNode (jointVarIds[i]));
|
||||
}
|
||||
|
||||
FactorGraph* fg = new FactorGraph (*fg_);
|
||||
BpSolver 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;
|
||||
Vars observedVars;
|
||||
for (unsigned j = 0; j < observedVids.size(); j++) {
|
||||
observedVars.push_back (fg->getVarNode (observedVids[j]));
|
||||
}
|
||||
StatesIndexer idx (observedVars, false);
|
||||
while (idx.valid()) {
|
||||
for (unsigned j = 0; j < observedVars.size(); j++) {
|
||||
observedVars[j]->setEvidence (idx[j]);
|
||||
}
|
||||
++ idx;
|
||||
BpSolver 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]->range() == 0) {
|
||||
count ++;
|
||||
}
|
||||
newBeliefs[j] *= prevBeliefs[count];
|
||||
}
|
||||
prevBeliefs = newBeliefs;
|
||||
observedVids.push_back (jointVars[i]->varId());
|
||||
}
|
||||
return prevBeliefs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpSolver::initializeSolver (void)
|
||||
{
|
||||
const VarNodes& varNodes = fg_->varNodes();
|
||||
varsI_.reserve (varNodes.size());
|
||||
for (unsigned i = 0; i < varNodes.size(); i++) {
|
||||
varsI_.push_back (new SPNodeInfo());
|
||||
}
|
||||
const FacNodes& facNodes = fg_->facNodes();
|
||||
facsI_.reserve (facNodes.size());
|
||||
for (unsigned i = 0; i < facNodes.size(); i++) {
|
||||
facsI_.push_back (new SPNodeInfo());
|
||||
}
|
||||
createLinks();
|
||||
for (unsigned i = 0; i < links_.size(); i++) {
|
||||
FacNode* src = links_[i]->getFactor();
|
||||
VarNode* dst = links_[i]->getVariable();
|
||||
ninf (dst)->addSpLink (links_[i]);
|
||||
ninf (src)->addSpLink (links_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BpSolver::converged (void)
|
||||
{
|
||||
if (links_.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
if (nIters_ == 0) {
|
||||
return false;
|
||||
}
|
||||
if (Globals::verbosity > 2) {
|
||||
cout << endl;
|
||||
}
|
||||
if (nIters_ == 1) {
|
||||
if (Globals::verbosity > 1) {
|
||||
cout << "no residuals" << endl << endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool converged = true;
|
||||
if (BpOptions::schedule == BpOptions::Schedule::MAX_RESIDUAL) {
|
||||
double maxResidual = (*(sortedOrder_.begin()))->getResidual();
|
||||
if (maxResidual > BpOptions::accuracy) {
|
||||
converged = false;
|
||||
} else {
|
||||
converged = true;
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < links_.size(); i++) {
|
||||
double residual = links_[i]->getResidual();
|
||||
if (Globals::verbosity > 1) {
|
||||
cout << links_[i]->toString() + " residual = " << residual << endl;
|
||||
}
|
||||
if (residual > BpOptions::accuracy) {
|
||||
converged = false;
|
||||
if (Globals::verbosity < 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Globals::verbosity > 1) {
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
return converged;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpSolver::printLinkInformation (void) const
|
||||
{
|
||||
for (unsigned i = 0; i < links_.size(); i++) {
|
||||
SpLink* l = links_[i];
|
||||
cout << l->toString() << ":" << endl;
|
||||
cout << " curr msg = " ;
|
||||
cout << l->getMessage() << endl;
|
||||
cout << " next msg = " ;
|
||||
cout << l->getNextMessage() << endl;
|
||||
cout << " residual = " << l->getResidual() << endl;
|
||||
}
|
||||
}
|
||||
|
190
packages/CLPBN/horus/BpSolver.h
Normal file
190
packages/CLPBN/horus/BpSolver.h
Normal file
@ -0,0 +1,190 @@
|
||||
#ifndef HORUS_BPSOLVER_H
|
||||
#define HORUS_BPSOLVER_H
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include "Solver.h"
|
||||
#include "Factor.h"
|
||||
#include "FactorGraph.h"
|
||||
#include "Util.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
class SpLink
|
||||
{
|
||||
public:
|
||||
SpLink (FacNode* fn, VarNode* vn)
|
||||
{
|
||||
fac_ = fn;
|
||||
var_ = vn;
|
||||
v1_.resize (vn->range(), LogAware::tl (1.0 / vn->range()));
|
||||
v2_.resize (vn->range(), LogAware::tl (1.0 / vn->range()));
|
||||
currMsg_ = &v1_;
|
||||
nextMsg_ = &v2_;
|
||||
msgSended_ = false;
|
||||
residual_ = 0.0;
|
||||
}
|
||||
|
||||
virtual ~SpLink (void) { };
|
||||
|
||||
FacNode* getFactor (void) const { return fac_; }
|
||||
|
||||
VarNode* getVariable (void) const { return var_; }
|
||||
|
||||
const Params& getMessage (void) const { return *currMsg_; }
|
||||
|
||||
Params& getNextMessage (void) { return *nextMsg_; }
|
||||
|
||||
bool messageWasSended (void) const { return msgSended_; }
|
||||
|
||||
double getResidual (void) const { return residual_; }
|
||||
|
||||
void clearResidual (void) { residual_ = 0.0; }
|
||||
|
||||
void updateResidual (void)
|
||||
{
|
||||
residual_ = LogAware::getMaxNorm (v1_,v2_);
|
||||
}
|
||||
|
||||
virtual void updateMessage (void)
|
||||
{
|
||||
swap (currMsg_, nextMsg_);
|
||||
msgSended_ = true;
|
||||
}
|
||||
|
||||
string toString (void) const
|
||||
{
|
||||
stringstream ss;
|
||||
ss << fac_->getLabel();
|
||||
ss << " -- " ;
|
||||
ss << var_->label();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
protected:
|
||||
FacNode* fac_;
|
||||
VarNode* var_;
|
||||
Params v1_;
|
||||
Params v2_;
|
||||
Params* currMsg_;
|
||||
Params* nextMsg_;
|
||||
bool msgSended_;
|
||||
double residual_;
|
||||
};
|
||||
|
||||
typedef vector<SpLink*> SpLinkSet;
|
||||
|
||||
|
||||
class SPNodeInfo
|
||||
{
|
||||
public:
|
||||
void addSpLink (SpLink* link) { links_.push_back (link); }
|
||||
const SpLinkSet& getLinks (void) { return links_; }
|
||||
private:
|
||||
SpLinkSet links_;
|
||||
};
|
||||
|
||||
|
||||
class BpSolver : public Solver
|
||||
{
|
||||
public:
|
||||
BpSolver (const FactorGraph&);
|
||||
|
||||
virtual ~BpSolver (void);
|
||||
|
||||
Params solveQuery (VarIds);
|
||||
|
||||
virtual void printSolverFlags (void) const;
|
||||
|
||||
virtual Params getPosterioriOf (VarId);
|
||||
|
||||
virtual Params getJointDistributionOf (const VarIds&);
|
||||
|
||||
protected:
|
||||
void runSolver (void);
|
||||
|
||||
virtual void createLinks (void);
|
||||
|
||||
virtual void maxResidualSchedule (void);
|
||||
|
||||
virtual void calculateFactor2VariableMsg (SpLink*);
|
||||
|
||||
virtual Params getVar2FactorMsg (const SpLink*) const;
|
||||
|
||||
virtual Params getJointByConditioning (const VarIds&) const;
|
||||
|
||||
SPNodeInfo* ninf (const VarNode* var) const
|
||||
{
|
||||
return varsI_[var->getIndex()];
|
||||
}
|
||||
|
||||
SPNodeInfo* ninf (const FacNode* fac) const
|
||||
{
|
||||
return facsI_[fac->getIndex()];
|
||||
}
|
||||
|
||||
void calculateAndUpdateMessage (SpLink* link, bool calcResidual = true)
|
||||
{
|
||||
if (Globals::verbosity > 2) {
|
||||
cout << "calculating & updating " << link->toString() << endl;
|
||||
}
|
||||
calculateFactor2VariableMsg (link);
|
||||
if (calcResidual) {
|
||||
link->updateResidual();
|
||||
}
|
||||
link->updateMessage();
|
||||
}
|
||||
|
||||
void calculateMessage (SpLink* link, bool calcResidual = true)
|
||||
{
|
||||
if (Globals::verbosity > 2) {
|
||||
cout << "calculating " << link->toString() << endl;
|
||||
}
|
||||
calculateFactor2VariableMsg (link);
|
||||
if (calcResidual) {
|
||||
link->updateResidual();
|
||||
}
|
||||
}
|
||||
|
||||
void updateMessage (SpLink* link)
|
||||
{
|
||||
link->updateMessage();
|
||||
if (Globals::verbosity > 2) {
|
||||
cout << "updating " << link->toString() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
struct CompareResidual
|
||||
{
|
||||
inline bool operator() (const SpLink* link1, const SpLink* link2)
|
||||
{
|
||||
return link1->getResidual() > link2->getResidual();
|
||||
}
|
||||
};
|
||||
|
||||
SpLinkSet links_;
|
||||
unsigned nIters_;
|
||||
vector<SPNodeInfo*> varsI_;
|
||||
vector<SPNodeInfo*> facsI_;
|
||||
bool runned_;
|
||||
const FactorGraph* fg_;
|
||||
|
||||
typedef multiset<SpLink*, CompareResidual> SortedOrder;
|
||||
SortedOrder sortedOrder_;
|
||||
|
||||
typedef unordered_map<SpLink*, SortedOrder::iterator> SpLinkMap;
|
||||
SpLinkMap linkMap_;
|
||||
|
||||
private:
|
||||
void initializeSolver (void);
|
||||
|
||||
bool converged (void);
|
||||
|
||||
virtual void printLinkInformation (void) const;
|
||||
};
|
||||
|
||||
#endif // HORUS_BPSOLVER_H
|
||||
|
320
packages/CLPBN/horus/CFactorGraph.cpp
Normal file
320
packages/CLPBN/horus/CFactorGraph.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
#include "CFactorGraph.h"
|
||||
#include "Factor.h"
|
||||
|
||||
|
||||
bool CFactorGraph::checkForIdenticalFactors = true;
|
||||
|
||||
CFactorGraph::CFactorGraph (const FactorGraph& fg)
|
||||
: freeColor_(0), groundFg_(&fg)
|
||||
{
|
||||
findIdenticalFactors();
|
||||
setInitialColors();
|
||||
createGroups();
|
||||
}
|
||||
|
||||
|
||||
|
||||
CFactorGraph::~CFactorGraph (void)
|
||||
{
|
||||
for (unsigned i = 0; i < varClusters_.size(); i++) {
|
||||
delete varClusters_[i];
|
||||
}
|
||||
for (unsigned i = 0; i < facClusters_.size(); i++) {
|
||||
delete facClusters_[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CFactorGraph::findIdenticalFactors()
|
||||
{
|
||||
if (checkForIdenticalFactors == false) {
|
||||
return;
|
||||
}
|
||||
const FacNodes& facNodes = groundFg_->facNodes();
|
||||
for (unsigned i = 0; i < facNodes.size(); i++) {
|
||||
facNodes[i]->factor().setDistId (Util::maxUnsigned());
|
||||
}
|
||||
unsigned groupCount = 1;
|
||||
for (unsigned i = 0; i < facNodes.size(); i++) {
|
||||
Factor& f1 = facNodes[i]->factor();
|
||||
if (f1.distId() != Util::maxUnsigned()) {
|
||||
continue;
|
||||
}
|
||||
f1.setDistId (groupCount);
|
||||
for (unsigned j = i + 1; j < facNodes.size(); j++) {
|
||||
Factor& f2 = facNodes[j]->factor();
|
||||
if (f2.distId() != Util::maxUnsigned()) {
|
||||
continue;
|
||||
}
|
||||
if (f1.size() == f2.size() &&
|
||||
f1.ranges() == f2.ranges() &&
|
||||
f1.params() == f2.params()) {
|
||||
f2.setDistId (groupCount);
|
||||
}
|
||||
}
|
||||
groupCount ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CFactorGraph::setInitialColors (void)
|
||||
{
|
||||
varColors_.resize (groundFg_->nrVarNodes());
|
||||
facColors_.resize (groundFg_->nrFacNodes());
|
||||
|
||||
// create the initial variable colors
|
||||
VarColorMap colorMap;
|
||||
const VarNodes& varNodes = groundFg_->varNodes();
|
||||
for (unsigned i = 0; i < varNodes.size(); i++) {
|
||||
unsigned dsize = varNodes[i]->range();
|
||||
VarColorMap::iterator it = colorMap.find (dsize);
|
||||
if (it == colorMap.end()) {
|
||||
it = colorMap.insert (make_pair (
|
||||
dsize, Colors (dsize+1,-1))).first;
|
||||
}
|
||||
unsigned idx;
|
||||
if (varNodes[i]->hasEvidence()) {
|
||||
idx = varNodes[i]->getEvidence();
|
||||
} else {
|
||||
idx = dsize;
|
||||
}
|
||||
Colors& stateColors = it->second;
|
||||
if (stateColors[idx] == -1) {
|
||||
stateColors[idx] = getFreeColor();
|
||||
}
|
||||
setColor (varNodes[i], stateColors[idx]);
|
||||
}
|
||||
const FacNodes& facNodes = groundFg_->facNodes();
|
||||
// create the initial factor colors
|
||||
DistColorMap distColors;
|
||||
for (unsigned i = 0; i < facNodes.size(); i++) {
|
||||
unsigned distId = facNodes[i]->factor().distId();
|
||||
DistColorMap::iterator it = distColors.find (distId);
|
||||
if (it == distColors.end()) {
|
||||
it = distColors.insert (make_pair (distId, getFreeColor())).first;
|
||||
}
|
||||
setColor (facNodes[i], it->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CFactorGraph::createGroups (void)
|
||||
{
|
||||
VarSignMap varGroups;
|
||||
FacSignMap facGroups;
|
||||
unsigned nIters = 0;
|
||||
bool groupsHaveChanged = true;
|
||||
const VarNodes& varNodes = groundFg_->varNodes();
|
||||
const FacNodes& facNodes = groundFg_->facNodes();
|
||||
|
||||
while (groupsHaveChanged || nIters == 1) {
|
||||
nIters ++;
|
||||
|
||||
// set a new color to the variables with the same signature
|
||||
unsigned prevVarGroupsSize = varGroups.size();
|
||||
varGroups.clear();
|
||||
for (unsigned i = 0; i < varNodes.size(); i++) {
|
||||
const VarSignature& signature = getSignature (varNodes[i]);
|
||||
VarSignMap::iterator it = varGroups.find (signature);
|
||||
if (it == varGroups.end()) {
|
||||
it = varGroups.insert (make_pair (signature, VarNodes())).first;
|
||||
}
|
||||
it->second.push_back (varNodes[i]);
|
||||
}
|
||||
for (VarSignMap::iterator it = varGroups.begin();
|
||||
it != varGroups.end(); it++) {
|
||||
Color newColor = getFreeColor();
|
||||
VarNodes& groupMembers = it->second;
|
||||
for (unsigned i = 0; i < groupMembers.size(); i++) {
|
||||
setColor (groupMembers[i], newColor);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned prevFactorGroupsSize = facGroups.size();
|
||||
facGroups.clear();
|
||||
// set a new color to the factors with the same signature
|
||||
for (unsigned i = 0; i < facNodes.size(); i++) {
|
||||
const FacSignature& signature = getSignature (facNodes[i]);
|
||||
FacSignMap::iterator it = facGroups.find (signature);
|
||||
if (it == facGroups.end()) {
|
||||
it = facGroups.insert (make_pair (signature, FacNodes())).first;
|
||||
}
|
||||
it->second.push_back (facNodes[i]);
|
||||
}
|
||||
for (FacSignMap::iterator it = facGroups.begin();
|
||||
it != facGroups.end(); it++) {
|
||||
Color newColor = getFreeColor();
|
||||
FacNodes& groupMembers = it->second;
|
||||
for (unsigned i = 0; i < groupMembers.size(); i++) {
|
||||
setColor (groupMembers[i], newColor);
|
||||
}
|
||||
}
|
||||
|
||||
groupsHaveChanged = prevVarGroupsSize != varGroups.size()
|
||||
|| prevFactorGroupsSize != facGroups.size();
|
||||
}
|
||||
// printGroups (varGroups, facGroups);
|
||||
createClusters (varGroups, facGroups);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CFactorGraph::createClusters (
|
||||
const VarSignMap& varGroups,
|
||||
const FacSignMap& facGroups)
|
||||
{
|
||||
varClusters_.reserve (varGroups.size());
|
||||
for (VarSignMap::const_iterator it = varGroups.begin();
|
||||
it != varGroups.end(); it++) {
|
||||
const VarNodes& groupVars = it->second;
|
||||
VarCluster* vc = new VarCluster (groupVars);
|
||||
for (unsigned i = 0; i < groupVars.size(); i++) {
|
||||
vid2VarCluster_.insert (make_pair (groupVars[i]->varId(), vc));
|
||||
}
|
||||
varClusters_.push_back (vc);
|
||||
}
|
||||
|
||||
facClusters_.reserve (facGroups.size());
|
||||
for (FacSignMap::const_iterator it = facGroups.begin();
|
||||
it != facGroups.end(); it++) {
|
||||
FacNode* groupFactor = it->second[0];
|
||||
const VarNodes& neighs = groupFactor->neighbors();
|
||||
VarClusters varClusters;
|
||||
varClusters.reserve (neighs.size());
|
||||
for (unsigned i = 0; i < neighs.size(); i++) {
|
||||
VarId vid = neighs[i]->varId();
|
||||
varClusters.push_back (vid2VarCluster_.find (vid)->second);
|
||||
}
|
||||
facClusters_.push_back (new FacCluster (it->second, varClusters));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
VarSignature
|
||||
CFactorGraph::getSignature (const VarNode* varNode)
|
||||
{
|
||||
const FacNodes& neighs = varNode->neighbors();
|
||||
VarSignature sign;
|
||||
sign.reserve (neighs.size() + 1);
|
||||
for (unsigned i = 0; i < neighs.size(); i++) {
|
||||
sign.push_back (make_pair (
|
||||
getColor (neighs[i]),
|
||||
neighs[i]->factor().indexOf (varNode->varId())));
|
||||
}
|
||||
std::sort (sign.begin(), sign.end());
|
||||
sign.push_back (make_pair (getColor (varNode), 0));
|
||||
return sign;
|
||||
}
|
||||
|
||||
|
||||
|
||||
FacSignature
|
||||
CFactorGraph::getSignature (const FacNode* facNode)
|
||||
{
|
||||
const VarNodes& neighs = facNode->neighbors();
|
||||
FacSignature sign;
|
||||
sign.reserve (neighs.size() + 1);
|
||||
for (unsigned i = 0; i < neighs.size(); i++) {
|
||||
sign.push_back (getColor (neighs[i]));
|
||||
}
|
||||
sign.push_back (getColor (facNode));
|
||||
return sign;
|
||||
}
|
||||
|
||||
|
||||
|
||||
FactorGraph*
|
||||
CFactorGraph::getGroundFactorGraph (void)
|
||||
{
|
||||
FactorGraph* fg = new FactorGraph();
|
||||
for (unsigned i = 0; i < varClusters_.size(); i++) {
|
||||
VarNode* newVar = new VarNode (varClusters_[i]->first());
|
||||
varClusters_[i]->setRepresentative (newVar);
|
||||
fg->addVarNode (newVar);
|
||||
}
|
||||
for (unsigned i = 0; i < facClusters_.size(); i++) {
|
||||
Vars vars;
|
||||
const VarClusters& clusters = facClusters_[i]->varClusters();
|
||||
for (unsigned j = 0; j < clusters.size(); j++) {
|
||||
vars.push_back (clusters[j]->representative());
|
||||
}
|
||||
const Factor& groundFac = facClusters_[i]->first()->factor();
|
||||
FacNode* fn = new FacNode (Factor (
|
||||
vars, groundFac.params(), groundFac.distId()));
|
||||
facClusters_[i]->setRepresentative (fn);
|
||||
fg->addFacNode (fn);
|
||||
for (unsigned j = 0; j < vars.size(); j++) {
|
||||
fg->addEdge (static_cast<VarNode*> (vars[j]), fn);
|
||||
}
|
||||
}
|
||||
return fg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
CFactorGraph::getEdgeCount (
|
||||
const FacCluster* fc,
|
||||
const VarCluster* vc,
|
||||
unsigned index) const
|
||||
{
|
||||
unsigned count = 0;
|
||||
VarId reprVid = vc->representative()->varId();
|
||||
VarNode* groundVar = groundFg_->getVarNode (reprVid);
|
||||
const FacNodes& neighs = groundVar->neighbors();
|
||||
for (unsigned i = 0; i < neighs.size(); i++) {
|
||||
FacNodes::const_iterator it;
|
||||
it = std::find (fc->members().begin(), fc->members().end(), neighs[i]);
|
||||
if (it != fc->members().end() &&
|
||||
(*it)->factor().indexOf (reprVid) == (int)index) {
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CFactorGraph::printGroups (
|
||||
const VarSignMap& varGroups,
|
||||
const FacSignMap& facGroups) const
|
||||
{
|
||||
unsigned count = 1;
|
||||
cout << "variable groups:" << endl;
|
||||
for (VarSignMap::const_iterator it = varGroups.begin();
|
||||
it != varGroups.end(); it++) {
|
||||
const VarNodes& groupMembers = it->second;
|
||||
if (groupMembers.size() > 0) {
|
||||
cout << count << ": " ;
|
||||
for (unsigned i = 0; i < groupMembers.size(); i++) {
|
||||
cout << groupMembers[i]->label() << " " ;
|
||||
}
|
||||
count ++;
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
count = 1;
|
||||
cout << endl << "factor groups:" << endl;
|
||||
for (FacSignMap::const_iterator it = facGroups.begin();
|
||||
it != facGroups.end(); it++) {
|
||||
const FacNodes& groupMembers = it->second;
|
||||
if (groupMembers.size() > 0) {
|
||||
cout << ++count << ": " ;
|
||||
for (unsigned i = 0; i < groupMembers.size(); i++) {
|
||||
cout << groupMembers[i]->getLabel() << " " ;
|
||||
}
|
||||
count ++;
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
176
packages/CLPBN/horus/CFactorGraph.h
Normal file
176
packages/CLPBN/horus/CFactorGraph.h
Normal file
@ -0,0 +1,176 @@
|
||||
#ifndef HORUS_CFACTORGRAPH_H
|
||||
#define HORUS_CFACTORGRAPH_H
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "FactorGraph.h"
|
||||
#include "Factor.h"
|
||||
#include "Util.h"
|
||||
#include "Horus.h"
|
||||
|
||||
class VarCluster;
|
||||
class FacCluster;
|
||||
class VarSignatureHash;
|
||||
class FacSignatureHash;
|
||||
|
||||
typedef long Color;
|
||||
typedef vector<Color> Colors;
|
||||
typedef vector<std::pair<Color,unsigned>> VarSignature;
|
||||
typedef vector<Color> FacSignature;
|
||||
|
||||
typedef unordered_map<unsigned, Color> DistColorMap;
|
||||
typedef unordered_map<unsigned, Colors> VarColorMap;
|
||||
|
||||
typedef unordered_map<VarSignature, VarNodes, VarSignatureHash> VarSignMap;
|
||||
typedef unordered_map<FacSignature, FacNodes, FacSignatureHash> FacSignMap;
|
||||
|
||||
typedef vector<VarCluster*> VarClusters;
|
||||
typedef vector<FacCluster*> FacClusters;
|
||||
|
||||
typedef unordered_map<VarId, VarCluster*> VarId2VarCluster;
|
||||
|
||||
|
||||
struct VarSignatureHash
|
||||
{
|
||||
size_t operator() (const VarSignature &sig) const
|
||||
{
|
||||
size_t val = hash<size_t>()(sig.size());
|
||||
for (unsigned i = 0; i < sig.size(); i++) {
|
||||
val ^= hash<size_t>()(sig[i].first);
|
||||
val ^= hash<size_t>()(sig[i].second);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct FacSignatureHash
|
||||
{
|
||||
size_t operator() (const FacSignature &sig) const
|
||||
{
|
||||
size_t val = hash<size_t>()(sig.size());
|
||||
for (unsigned i = 0; i < sig.size(); i++) {
|
||||
val ^= hash<size_t>()(sig[i]);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class VarCluster
|
||||
{
|
||||
public:
|
||||
VarCluster (const VarNodes& vs) : members_(vs) { }
|
||||
|
||||
const VarNode* first (void) const { return members_.front(); }
|
||||
|
||||
const VarNodes& members (void) const { return members_; }
|
||||
|
||||
VarNode* representative (void) const { return repr_; }
|
||||
|
||||
void setRepresentative (VarNode* vn) { repr_ = vn; }
|
||||
|
||||
private:
|
||||
VarNodes members_;
|
||||
VarNode* repr_;
|
||||
};
|
||||
|
||||
|
||||
class FacCluster
|
||||
{
|
||||
public:
|
||||
FacCluster (const FacNodes& fcs, const VarClusters& vcs)
|
||||
: members_(fcs), varClusters_(vcs) { }
|
||||
|
||||
const FacNode* first (void) const { return members_.front(); }
|
||||
|
||||
const FacNodes& members (void) const { return members_; }
|
||||
|
||||
VarClusters& varClusters (void) { return varClusters_; }
|
||||
|
||||
FacNode* representative (void) const { return repr_; }
|
||||
|
||||
void setRepresentative (FacNode* fn) { repr_ = fn; }
|
||||
|
||||
private:
|
||||
FacNodes members_;
|
||||
VarClusters varClusters_;
|
||||
FacNode* repr_;
|
||||
};
|
||||
|
||||
|
||||
class CFactorGraph
|
||||
{
|
||||
public:
|
||||
CFactorGraph (const FactorGraph&);
|
||||
|
||||
~CFactorGraph (void);
|
||||
|
||||
const VarClusters& varClusters (void) { return varClusters_; }
|
||||
|
||||
const FacClusters& facClusters (void) { return facClusters_; }
|
||||
|
||||
VarNode* getEquivalent (VarId vid)
|
||||
{
|
||||
VarCluster* vc = vid2VarCluster_.find (vid)->second;
|
||||
return vc->representative();
|
||||
}
|
||||
|
||||
FactorGraph* getGroundFactorGraph (void);
|
||||
|
||||
unsigned getEdgeCount (const FacCluster*,
|
||||
const VarCluster*, unsigned index) const;
|
||||
|
||||
static bool checkForIdenticalFactors;
|
||||
|
||||
private:
|
||||
Color getFreeColor (void)
|
||||
{
|
||||
++ freeColor_;
|
||||
return freeColor_ - 1;
|
||||
}
|
||||
|
||||
Color getColor (const VarNode* vn) const
|
||||
{
|
||||
return varColors_[vn->getIndex()];
|
||||
}
|
||||
Color getColor (const FacNode* fn) const {
|
||||
return facColors_[fn->getIndex()];
|
||||
}
|
||||
|
||||
void setColor (const VarNode* vn, Color c)
|
||||
{
|
||||
varColors_[vn->getIndex()] = c;
|
||||
}
|
||||
|
||||
void setColor (const FacNode* fn, Color c)
|
||||
{
|
||||
facColors_[fn->getIndex()] = c;
|
||||
}
|
||||
|
||||
void findIdenticalFactors (void);
|
||||
|
||||
void setInitialColors (void);
|
||||
|
||||
void createGroups (void);
|
||||
|
||||
void createClusters (const VarSignMap&, const FacSignMap&);
|
||||
|
||||
VarSignature getSignature (const VarNode*);
|
||||
|
||||
FacSignature getSignature (const FacNode*);
|
||||
|
||||
void printGroups (const VarSignMap&, const FacSignMap&) const;
|
||||
|
||||
Color freeColor_;
|
||||
Colors varColors_;
|
||||
Colors facColors_;
|
||||
VarClusters varClusters_;
|
||||
FacClusters facClusters_;
|
||||
VarId2VarCluster vid2VarCluster_;
|
||||
const FactorGraph* groundFg_;
|
||||
};
|
||||
|
||||
#endif // HORUS_CFACTORGRAPH_H
|
||||
|
369
packages/CLPBN/horus/CbpSolver.cpp
Normal file
369
packages/CLPBN/horus/CbpSolver.cpp
Normal file
@ -0,0 +1,369 @@
|
||||
#include "CbpSolver.h"
|
||||
|
||||
|
||||
CbpSolver::CbpSolver (const FactorGraph& fg) : BpSolver (fg)
|
||||
{
|
||||
unsigned nrGroundVars, nrGroundFacs, nrNeighborless;
|
||||
if (Constants::COLLECT_STATS) {
|
||||
nrGroundVars = fg_->varNodes().size();
|
||||
nrGroundFacs = fg_->facNodes().size();
|
||||
const VarNodes& vars = fg_->varNodes();
|
||||
nrNeighborless = 0;
|
||||
for (unsigned i = 0; i < vars.size(); i++) {
|
||||
const FacNodes& factors = vars[i]->neighbors();
|
||||
if (factors.size() == 1 && factors[0]->neighbors().size() == 1) {
|
||||
nrNeighborless ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
cfg_ = new CFactorGraph (fg);
|
||||
fg_ = cfg_->getGroundFactorGraph();
|
||||
if (Constants::COLLECT_STATS) {
|
||||
unsigned nrClusterVars = fg_->varNodes().size();
|
||||
unsigned nrClusterFacs = fg_->facNodes().size();
|
||||
Statistics::updateCompressingStatistics (nrGroundVars,
|
||||
nrGroundFacs, nrClusterVars, nrClusterFacs, nrNeighborless);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
CbpSolver::~CbpSolver (void)
|
||||
{
|
||||
delete cfg_;
|
||||
delete fg_;
|
||||
for (unsigned i = 0; i < links_.size(); i++) {
|
||||
delete links_[i];
|
||||
}
|
||||
links_.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CbpSolver::printSolverFlags (void) const
|
||||
{
|
||||
stringstream ss;
|
||||
ss << "counting bp [" ;
|
||||
ss << "schedule=" ;
|
||||
typedef BpOptions::Schedule Sch;
|
||||
switch (BpOptions::schedule) {
|
||||
case Sch::SEQ_FIXED: ss << "seq_fixed"; break;
|
||||
case Sch::SEQ_RANDOM: ss << "seq_random"; break;
|
||||
case Sch::PARALLEL: ss << "parallel"; break;
|
||||
case Sch::MAX_RESIDUAL: ss << "max_residual"; break;
|
||||
}
|
||||
ss << ",max_iter=" << BpOptions::maxIter;
|
||||
ss << ",accuracy=" << BpOptions::accuracy;
|
||||
ss << ",log_domain=" << Util::toString (Globals::logDomain);
|
||||
ss << ",chkif=" <<
|
||||
Util::toString (CFactorGraph::checkForIdenticalFactors);
|
||||
ss << "]" ;
|
||||
cout << ss.str() << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
CbpSolver::getPosterioriOf (VarId vid)
|
||||
{
|
||||
if (runned_ == false) {
|
||||
runSolver();
|
||||
}
|
||||
assert (cfg_->getEquivalent (vid));
|
||||
VarNode* var = cfg_->getEquivalent (vid);
|
||||
Params probs;
|
||||
if (var->hasEvidence()) {
|
||||
probs.resize (var->range(), LogAware::noEvidence());
|
||||
probs[var->getEvidence()] = LogAware::withEvidence();
|
||||
} else {
|
||||
probs.resize (var->range(), LogAware::multIdenty());
|
||||
const SpLinkSet& links = ninf(var)->getLinks();
|
||||
if (Globals::logDomain) {
|
||||
for (unsigned i = 0; i < links.size(); i++) {
|
||||
CbpSolverLink* l = static_cast<CbpSolverLink*> (links[i]);
|
||||
Util::add (probs, l->poweredMessage());
|
||||
}
|
||||
LogAware::normalize (probs);
|
||||
Util::fromLog (probs);
|
||||
} else {
|
||||
for (unsigned i = 0; i < links.size(); i++) {
|
||||
CbpSolverLink* l = static_cast<CbpSolverLink*> (links[i]);
|
||||
Util::multiply (probs, l->poweredMessage());
|
||||
}
|
||||
LogAware::normalize (probs);
|
||||
}
|
||||
}
|
||||
return probs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
CbpSolver::getJointDistributionOf (const VarIds& jointVids)
|
||||
{
|
||||
VarIds eqVarIds;
|
||||
for (unsigned i = 0; i < jointVids.size(); i++) {
|
||||
VarNode* vn = cfg_->getEquivalent (jointVids[i]);
|
||||
eqVarIds.push_back (vn->varId());
|
||||
}
|
||||
return BpSolver::getJointDistributionOf (eqVarIds);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CbpSolver::createLinks (void)
|
||||
{
|
||||
if (Globals::verbosity > 0) {
|
||||
cout << "compressed factor graph contains " ;
|
||||
cout << fg_->nrVarNodes() << " variables and " ;
|
||||
cout << fg_->nrFacNodes() << " factors " << endl;
|
||||
cout << endl;
|
||||
}
|
||||
const FacClusters& fcs = cfg_->facClusters();
|
||||
for (unsigned i = 0; i < fcs.size(); i++) {
|
||||
const VarClusters& vcs = fcs[i]->varClusters();
|
||||
for (unsigned j = 0; j < vcs.size(); j++) {
|
||||
unsigned count = cfg_->getEdgeCount (fcs[i], vcs[j], j);
|
||||
if (Globals::verbosity > 1) {
|
||||
cout << "creating link " ;
|
||||
cout << fcs[i]->representative()->getLabel();
|
||||
cout << " -- " ;
|
||||
cout << vcs[j]->representative()->label();
|
||||
cout << " idx=" << j << ", count=" << count << endl;
|
||||
}
|
||||
links_.push_back (new CbpSolverLink (
|
||||
fcs[i]->representative(), vcs[j]->representative(), j, count));
|
||||
}
|
||||
}
|
||||
if (Globals::verbosity > 1) {
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CbpSolver::maxResidualSchedule (void)
|
||||
{
|
||||
if (nIters_ == 1) {
|
||||
for (unsigned i = 0; i < links_.size(); i++) {
|
||||
calculateMessage (links_[i]);
|
||||
SortedOrder::iterator it = sortedOrder_.insert (links_[i]);
|
||||
linkMap_.insert (make_pair (links_[i], it));
|
||||
if (Globals::verbosity >= 1) {
|
||||
cout << "calculating " << links_[i]->toString() << endl;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned c = 0; c < links_.size(); c++) {
|
||||
if (Globals::verbosity > 1) {
|
||||
cout << endl << "current residuals:" << endl;
|
||||
for (SortedOrder::iterator it = sortedOrder_.begin();
|
||||
it != sortedOrder_.end(); it ++) {
|
||||
cout << " " << setw (30) << left << (*it)->toString();
|
||||
cout << "residual = " << (*it)->getResidual() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
SortedOrder::iterator it = sortedOrder_.begin();
|
||||
SpLink* link = *it;
|
||||
if (Globals::verbosity >= 1) {
|
||||
cout << "updating " << (*sortedOrder_.begin())->toString() << endl;
|
||||
}
|
||||
if (link->getResidual() < BpOptions::accuracy) {
|
||||
return;
|
||||
}
|
||||
link->updateMessage();
|
||||
link->clearResidual();
|
||||
sortedOrder_.erase (it);
|
||||
linkMap_.find (link)->second = sortedOrder_.insert (link);
|
||||
|
||||
// update the messages that depend on message source --> destin
|
||||
const FacNodes& factorNeighbors = link->getVariable()->neighbors();
|
||||
for (unsigned i = 0; i < factorNeighbors.size(); i++) {
|
||||
const SpLinkSet& links = ninf(factorNeighbors[i])->getLinks();
|
||||
for (unsigned j = 0; j < links.size(); j++) {
|
||||
if (links[j]->getVariable() != link->getVariable()) {
|
||||
if (Globals::verbosity > 1) {
|
||||
cout << " calculating " << links[j]->toString() << endl;
|
||||
}
|
||||
calculateMessage (links[j]);
|
||||
SpLinkMap::iterator iter = linkMap_.find (links[j]);
|
||||
sortedOrder_.erase (iter->second);
|
||||
iter->second = sortedOrder_.insert (links[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// in counting bp, the message that a variable X sends to
|
||||
// to a factor F depends on the message that F sent to the X
|
||||
const SpLinkSet& links = ninf(link->getFactor())->getLinks();
|
||||
for (unsigned i = 0; i < links.size(); i++) {
|
||||
if (links[i]->getVariable() != link->getVariable()) {
|
||||
if (Globals::verbosity > 1) {
|
||||
cout << " calculating " << links[i]->toString() << endl;
|
||||
}
|
||||
calculateMessage (links[i]);
|
||||
SpLinkMap::iterator iter = linkMap_.find (links[i]);
|
||||
sortedOrder_.erase (iter->second);
|
||||
iter->second = sortedOrder_.insert (links[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CbpSolver::calculateFactor2VariableMsg (SpLink* _link)
|
||||
{
|
||||
CbpSolverLink* link = static_cast<CbpSolverLink*> (_link);
|
||||
FacNode* src = link->getFactor();
|
||||
const VarNode* dst = link->getVariable();
|
||||
const SpLinkSet& links = ninf(src)->getLinks();
|
||||
// calculate the product of messages that were sent
|
||||
// to factor `src', except from var `dst'
|
||||
unsigned msgSize = 1;
|
||||
for (unsigned i = 0; i < links.size(); i++) {
|
||||
msgSize *= links[i]->getVariable()->range();
|
||||
}
|
||||
unsigned repetitions = 1;
|
||||
Params msgProduct (msgSize, LogAware::multIdenty());
|
||||
if (Globals::logDomain) {
|
||||
for (int i = links.size() - 1; i >= 0; i--) {
|
||||
const CbpSolverLink* cl = static_cast<const CbpSolverLink*> (links[i]);
|
||||
if ( ! (cl->getVariable() == dst && cl->index() == link->index())) {
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " message from " << links[i]->getVariable()->label();
|
||||
cout << ": " ;
|
||||
}
|
||||
Util::add (msgProduct, getVar2FactorMsg (links[i]), repetitions);
|
||||
repetitions *= links[i]->getVariable()->range();
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << endl;
|
||||
}
|
||||
} else {
|
||||
unsigned range = links[i]->getVariable()->range();
|
||||
Util::add (msgProduct, Params (range, 0.0), repetitions);
|
||||
repetitions *= range;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = links.size() - 1; i >= 0; i--) {
|
||||
const CbpSolverLink* cl = static_cast<const CbpSolverLink*> (links[i]);
|
||||
if ( ! (cl->getVariable() == dst && cl->index() == link->index())) {
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " message from " << links[i]->getVariable()->label();
|
||||
cout << ": " ;
|
||||
}
|
||||
Util::multiply (msgProduct, getVar2FactorMsg (links[i]), repetitions);
|
||||
repetitions *= links[i]->getVariable()->range();
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << endl;
|
||||
}
|
||||
} else {
|
||||
unsigned range = links[i]->getVariable()->range();
|
||||
Util::multiply (msgProduct, Params (range, 1.0), repetitions);
|
||||
repetitions *= range;
|
||||
}
|
||||
}
|
||||
}
|
||||
Factor result (src->factor().arguments(),
|
||||
src->factor().ranges(), msgProduct);
|
||||
assert (msgProduct.size() == src->factor().size());
|
||||
if (Globals::logDomain) {
|
||||
for (unsigned i = 0; i < result.size(); i++) {
|
||||
result[i] += src->factor()[i];
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < result.size(); i++) {
|
||||
result[i] *= src->factor()[i];
|
||||
}
|
||||
}
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " message product: " << msgProduct << endl;
|
||||
cout << " original factor: " << src->factor().params() << endl;
|
||||
cout << " factor product: " << result.params() << endl;
|
||||
}
|
||||
result.sumOutAllExceptIndex (link->index());
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " marginalized: " << result.params() << endl;
|
||||
}
|
||||
link->getNextMessage() = result.params();
|
||||
LogAware::normalize (link->getNextMessage());
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " curr msg: " << link->getMessage() << endl;
|
||||
cout << " next msg: " << link->getNextMessage() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
CbpSolver::getVar2FactorMsg (const SpLink* _link) const
|
||||
{
|
||||
const CbpSolverLink* link = static_cast<const CbpSolverLink*> (_link);
|
||||
const VarNode* src = link->getVariable();
|
||||
const FacNode* dst = link->getFactor();
|
||||
Params msg;
|
||||
if (src->hasEvidence()) {
|
||||
msg.resize (src->range(), LogAware::noEvidence());
|
||||
double value = link->getMessage()[src->getEvidence()];
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
msg[src->getEvidence()] = value;
|
||||
cout << msg << "^" << link->nrEdges() << "-1" ;
|
||||
}
|
||||
msg[src->getEvidence()] = LogAware::pow (value, link->nrEdges() - 1);
|
||||
} else {
|
||||
msg = link->getMessage();
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << msg << "^" << link->nrEdges() << "-1" ;
|
||||
}
|
||||
LogAware::pow (msg, link->nrEdges() - 1);
|
||||
}
|
||||
const SpLinkSet& links = ninf(src)->getLinks();
|
||||
if (Globals::logDomain) {
|
||||
for (unsigned i = 0; i < links.size(); i++) {
|
||||
CbpSolverLink* cl = static_cast<CbpSolverLink*> (links[i]);
|
||||
if ( ! (cl->getFactor() == dst && cl->index() == link->index())) {
|
||||
CbpSolverLink* cl = static_cast<CbpSolverLink*> (links[i]);
|
||||
Util::add (msg, cl->poweredMessage());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < links.size(); i++) {
|
||||
CbpSolverLink* cl = static_cast<CbpSolverLink*> (links[i]);
|
||||
if ( ! (cl->getFactor() == dst && cl->index() == link->index())) {
|
||||
Util::multiply (msg, cl->poweredMessage());
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " x " << cl->getNextMessage() << "^" << link->nrEdges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Constants::SHOW_BP_CALCS) {
|
||||
cout << " = " << msg;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CbpSolver::printLinkInformation (void) const
|
||||
{
|
||||
for (unsigned i = 0; i < links_.size(); i++) {
|
||||
CbpSolverLink* cl = static_cast<CbpSolverLink*> (links_[i]);
|
||||
cout << cl->toString() << ":" << endl;
|
||||
cout << " curr msg = " << cl->getMessage() << endl;
|
||||
cout << " next msg = " << cl->getNextMessage() << endl;
|
||||
cout << " index = " << cl->index() << endl;
|
||||
cout << " nr edges = " << cl->nrEdges() << endl;
|
||||
cout << " powered = " << cl->poweredMessage() << endl;
|
||||
cout << " residual = " << cl->getResidual() << endl;
|
||||
}
|
||||
}
|
||||
|
67
packages/CLPBN/horus/CbpSolver.h
Normal file
67
packages/CLPBN/horus/CbpSolver.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef HORUS_CBP_H
|
||||
#define HORUS_CBP_H
|
||||
|
||||
#include "BpSolver.h"
|
||||
#include "CFactorGraph.h"
|
||||
|
||||
class Factor;
|
||||
|
||||
class CbpSolverLink : public SpLink
|
||||
{
|
||||
public:
|
||||
CbpSolverLink (FacNode* fn, VarNode* vn, unsigned idx, unsigned count)
|
||||
: SpLink (fn, vn), index_(idx), nrEdges_(count),
|
||||
pwdMsg_(vn->range(), LogAware::one()) { }
|
||||
|
||||
unsigned index (void) const { return index_; }
|
||||
|
||||
unsigned nrEdges (void) const { return nrEdges_; }
|
||||
|
||||
const Params& poweredMessage (void) const { return pwdMsg_; }
|
||||
|
||||
void updateMessage (void)
|
||||
{
|
||||
pwdMsg_ = *nextMsg_;
|
||||
swap (currMsg_, nextMsg_);
|
||||
msgSended_ = true;
|
||||
LogAware::pow (pwdMsg_, nrEdges_);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned index_;
|
||||
unsigned nrEdges_;
|
||||
Params pwdMsg_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CbpSolver : public BpSolver
|
||||
{
|
||||
public:
|
||||
CbpSolver (const FactorGraph& fg);
|
||||
|
||||
~CbpSolver (void);
|
||||
|
||||
void printSolverFlags (void) const;
|
||||
|
||||
Params getPosterioriOf (VarId);
|
||||
|
||||
Params getJointDistributionOf (const VarIds&);
|
||||
|
||||
private:
|
||||
|
||||
void createLinks (void);
|
||||
|
||||
void maxResidualSchedule (void);
|
||||
|
||||
void calculateFactor2VariableMsg (SpLink*);
|
||||
|
||||
Params getVar2FactorMsg (const SpLink*) const;
|
||||
|
||||
void printLinkInformation (void) const;
|
||||
|
||||
CFactorGraph* cfg_;
|
||||
};
|
||||
|
||||
#endif // HORUS_CBP_H
|
||||
|
1132
packages/CLPBN/horus/ConstraintTree.cpp
Normal file
1132
packages/CLPBN/horus/ConstraintTree.cpp
Normal file
File diff suppressed because it is too large
Load Diff
231
packages/CLPBN/horus/ConstraintTree.h
Normal file
231
packages/CLPBN/horus/ConstraintTree.h
Normal file
@ -0,0 +1,231 @@
|
||||
#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:
|
||||
|
||||
struct CompareSymbol
|
||||
{
|
||||
bool operator() (const CTNode* n1, const CTNode* n2) const
|
||||
{
|
||||
return n1->symbol() < n2->symbol();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
typedef TinySet<CTNode*, CompareSymbol> CTChilds_;
|
||||
|
||||
public:
|
||||
|
||||
CTNode (const CTNode& n, const CTChilds_& chs = CTChilds_())
|
||||
: symbol_(n.symbol()), childs_(chs), level_(n.level()) { }
|
||||
|
||||
CTNode (Symbol s, unsigned l, const CTChilds_& chs = CTChilds_())
|
||||
: symbol_(s), childs_(chs), 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; }
|
||||
|
||||
public:
|
||||
|
||||
CTChilds_& childs (void) { return childs_; }
|
||||
|
||||
const CTChilds_& 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(); }
|
||||
|
||||
CTChilds_::iterator findSymbol (Symbol symb)
|
||||
{
|
||||
CTNode tmp (symb, 0);
|
||||
return childs_.find (&tmp);
|
||||
}
|
||||
|
||||
void mergeSubtree (CTNode*, bool = true);
|
||||
|
||||
void removeChild (CTNode*);
|
||||
|
||||
void removeChilds (void);
|
||||
|
||||
void removeAndDeleteChild (CTNode*);
|
||||
|
||||
void removeAndDeleteAllChilds (void);
|
||||
|
||||
SymbolSet childSymbols (void) const;
|
||||
|
||||
static CTNode* copySubtree (const CTNode*);
|
||||
|
||||
static void deleteSubtree (CTNode*);
|
||||
|
||||
private:
|
||||
void updateChildLevels (CTNode*, unsigned);
|
||||
|
||||
Symbol symbol_;
|
||||
CTChilds_ childs_;
|
||||
unsigned level_;
|
||||
};
|
||||
|
||||
ostream& operator<< (ostream &out, const CTNode&);
|
||||
|
||||
|
||||
typedef TinySet<CTNode*, CTNode::CompareSymbol> CTChilds;
|
||||
|
||||
|
||||
class ConstraintTree
|
||||
{
|
||||
public:
|
||||
ConstraintTree (unsigned);
|
||||
|
||||
ConstraintTree (const LogVars&);
|
||||
|
||||
ConstraintTree (const LogVars&, const Tuples&);
|
||||
|
||||
ConstraintTree (const ConstraintTree&);
|
||||
|
||||
ConstraintTree (const CTChilds& rootChilds, const LogVars& logVars)
|
||||
: root_(new CTNode (0, 0, rootChilds)),
|
||||
logVars_(logVars),
|
||||
logVarSet_(logVars) { }
|
||||
|
||||
~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 oneTwoOne = 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 isCartesianProduct (const LogVarSet&);
|
||||
|
||||
std::pair<ConstraintTree*, ConstraintTree*> split (const Tuple&);
|
||||
|
||||
std::pair<ConstraintTree*, ConstraintTree*> split (
|
||||
const LogVars&, ConstraintTree*, const LogVars&);
|
||||
|
||||
ConstraintTrees countNormalize (const LogVarSet&);
|
||||
|
||||
ConstraintTrees jointCountNormalize (
|
||||
ConstraintTree*, ConstraintTree*, LogVar, LogVar, LogVar);
|
||||
|
||||
LogVars expand (LogVar);
|
||||
|
||||
ConstraintTrees ground (LogVar);
|
||||
|
||||
void copyLogVar (LogVar,LogVar);
|
||||
|
||||
private:
|
||||
unsigned countTuples (const CTNode*) const;
|
||||
|
||||
CTNodes getNodesBelow (CTNode*) const;
|
||||
|
||||
CTNodes getNodesAtLevel (unsigned) const;
|
||||
|
||||
unsigned nrNodes (const CTNode* n) const;
|
||||
|
||||
void appendOnBottom (CTNode* n1, const CTChilds&);
|
||||
|
||||
void swapLogVar (LogVar);
|
||||
|
||||
bool join (CTNode*, const Tuple&, unsigned, CTNode*);
|
||||
|
||||
void getTuples (CTNode*, Tuples, unsigned, Tuples&, CTNodes&) const;
|
||||
|
||||
vector<std::pair<CTNode*, unsigned>> countNormalize (
|
||||
const CTNode*, unsigned);
|
||||
|
||||
static void split (
|
||||
CTNode*, CTNode*, CTChilds&, CTChilds&, unsigned);
|
||||
|
||||
CTNode* root_;
|
||||
LogVars logVars_;
|
||||
LogVarSet logVarSet_;
|
||||
};
|
||||
|
||||
|
||||
#endif // HORUS_CONSTRAINTTREE_H
|
||||
|
222
packages/CLPBN/horus/ElimGraph.cpp
Normal file
222
packages/CLPBN/horus/ElimGraph.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
#include <limits>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "ElimGraph.h"
|
||||
|
||||
ElimHeuristic ElimGraph::elimHeuristic = MIN_NEIGHBORS;
|
||||
|
||||
|
||||
ElimGraph::ElimGraph (const vector<Factor*>& factors)
|
||||
{
|
||||
for (unsigned i = 0; i < factors.size(); i++) {
|
||||
if (factors[i] == 0) { // if contained just one var with evidence
|
||||
continue;
|
||||
}
|
||||
const VarIds& vids = factors[i]->arguments();
|
||||
for (unsigned j = 0; j < vids.size() - 1; j++) {
|
||||
EgNode* n1 = getEgNode (vids[j]);
|
||||
if (n1 == 0) {
|
||||
n1 = new EgNode (vids[j], factors[i]->range (j));
|
||||
addNode (n1);
|
||||
}
|
||||
for (unsigned k = j + 1; k < vids.size(); k++) {
|
||||
EgNode* n2 = getEgNode (vids[k]);
|
||||
if (n2 == 0) {
|
||||
n2 = new EgNode (vids[k], factors[i]->range (k));
|
||||
addNode (n2);
|
||||
}
|
||||
if (neighbors (n1, n2) == false) {
|
||||
addEdge (n1, n2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vids.size() == 1) {
|
||||
if (getEgNode (vids[0]) == 0) {
|
||||
addNode (new EgNode (vids[0], factors[i]->range (0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ElimGraph::~ElimGraph (void)
|
||||
{
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
delete nodes_[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
VarIds
|
||||
ElimGraph::getEliminatingOrder (const VarIds& exclude)
|
||||
{
|
||||
VarIds elimOrder;
|
||||
unmarked_.reserve (nodes_.size());
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
if (Util::contains (exclude, nodes_[i]->varId()) == false) {
|
||||
unmarked_.insert (nodes_[i]);
|
||||
}
|
||||
}
|
||||
unsigned nVarsToEliminate = nodes_.size() - exclude.size();
|
||||
for (unsigned i = 0; i < nVarsToEliminate; i++) {
|
||||
EgNode* node = getLowestCostNode();
|
||||
unmarked_.remove (node);
|
||||
const EGNeighs& neighs = node->neighbors();
|
||||
for (unsigned j = 0; j < neighs.size(); j++) {
|
||||
neighs[j]->removeNeighbor (node);
|
||||
}
|
||||
elimOrder.push_back (node->varId());
|
||||
connectAllNeighbors (node);
|
||||
}
|
||||
return elimOrder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ElimGraph::print (void) const
|
||||
{
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
cout << "node " << nodes_[i]->label() << " neighs:" ;
|
||||
EGNeighs neighs = nodes_[i]->neighbors();
|
||||
for (unsigned j = 0; j < neighs.size(); j++) {
|
||||
cout << " " << neighs[j]->label();
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ElimGraph::exportToGraphViz (
|
||||
const char* fileName,
|
||||
bool showNeighborless,
|
||||
const VarIds& highlightVarIds) const
|
||||
{
|
||||
ofstream out (fileName);
|
||||
if (!out.is_open()) {
|
||||
cerr << "error: cannot open file to write at " ;
|
||||
cerr << "Markov::exportToDotFile()" << endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
out << "strict graph {" << endl;
|
||||
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
if (showNeighborless || nodes_[i]->neighbors().size() != 0) {
|
||||
out << '"' << nodes_[i]->label() << '"' << endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < highlightVarIds.size(); i++) {
|
||||
EgNode* node =getEgNode (highlightVarIds[i]);
|
||||
if (node) {
|
||||
out << '"' << node->label() << '"' ;
|
||||
out << " [shape=box3d]" << endl;
|
||||
} else {
|
||||
cout << "error: invalid variable id: " << highlightVarIds[i] << endl;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < nodes_.size(); i++) {
|
||||
EGNeighs neighs = nodes_[i]->neighbors();
|
||||
for (unsigned j = 0; j < neighs.size(); j++) {
|
||||
out << '"' << nodes_[i]->label() << '"' << " -- " ;
|
||||
out << '"' << neighs[j]->label() << '"' << endl;
|
||||
}
|
||||
}
|
||||
|
||||
out << "}" << endl;
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
VarIds
|
||||
ElimGraph::getEliminationOrder (
|
||||
const vector<Factor*> factors,
|
||||
VarIds excludedVids)
|
||||
{
|
||||
ElimGraph graph (factors);
|
||||
// graph.print();
|
||||
// graph.exportToGraphViz ("_egg.dot");
|
||||
return graph.getEliminatingOrder (excludedVids);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ElimGraph::addNode (EgNode* n)
|
||||
{
|
||||
nodes_.push_back (n);
|
||||
n->setIndex (nodes_.size() - 1);
|
||||
varMap_.insert (make_pair (n->varId(), n));
|
||||
}
|
||||
|
||||
|
||||
|
||||
EgNode*
|
||||
ElimGraph::getEgNode (VarId vid) const
|
||||
{
|
||||
unordered_map<VarId, EgNode*>::const_iterator it;
|
||||
it = varMap_.find (vid);
|
||||
return (it != varMap_.end()) ? it->second : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
EgNode*
|
||||
ElimGraph::getLowestCostNode (void) const
|
||||
{
|
||||
EgNode* bestNode = 0;
|
||||
unsigned minCost = std::numeric_limits<unsigned>::max();
|
||||
unsigned cost = 0;
|
||||
EGNeighs::const_iterator it;
|
||||
switch (elimHeuristic) {
|
||||
case MIN_NEIGHBORS: {
|
||||
for (it = unmarked_.begin(); it != unmarked_.end(); ++ it) {
|
||||
cost = getNeighborsCost (*it);
|
||||
if (cost < minCost) {
|
||||
bestNode = *it;
|
||||
minCost = cost;
|
||||
}
|
||||
}}
|
||||
break;
|
||||
case MIN_WEIGHT:
|
||||
//cost = getWeightCost (unmarked_[i]);
|
||||
break;
|
||||
case MIN_FILL:
|
||||
//cost = getFillCost (unmarked_[i]);
|
||||
break;
|
||||
case WEIGHTED_MIN_FILL:
|
||||
//cost = getWeightedFillCost (unmarked_[i]);
|
||||
break;
|
||||
default:
|
||||
assert (false);
|
||||
}
|
||||
assert (bestNode);
|
||||
return bestNode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ElimGraph::connectAllNeighbors (const EgNode* n)
|
||||
{
|
||||
const EGNeighs& neighs = n->neighbors();
|
||||
if (neighs.size() > 0) {
|
||||
for (unsigned i = 0; i < neighs.size() - 1; i++) {
|
||||
for (unsigned j = i+1; j < neighs.size(); j++) {
|
||||
if ( ! neighbors (neighs[i], neighs[j])) {
|
||||
addEdge (neighs[i], neighs[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
138
packages/CLPBN/horus/ElimGraph.h
Normal file
138
packages/CLPBN/horus/ElimGraph.h
Normal file
@ -0,0 +1,138 @@
|
||||
#ifndef HORUS_ELIMGRAPH_H
|
||||
#define HORUS_ELIMGRAPH_H
|
||||
|
||||
#include "unordered_map"
|
||||
|
||||
#include "FactorGraph.h"
|
||||
#include "TinySet.h"
|
||||
#include "Horus.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
enum ElimHeuristic
|
||||
{
|
||||
MIN_NEIGHBORS,
|
||||
MIN_WEIGHT,
|
||||
MIN_FILL,
|
||||
WEIGHTED_MIN_FILL
|
||||
};
|
||||
|
||||
|
||||
class EgNode;
|
||||
|
||||
typedef TinySet<EgNode*> EGNeighs;
|
||||
|
||||
|
||||
class EgNode : public Var
|
||||
{
|
||||
public:
|
||||
EgNode (VarId vid, unsigned range) : Var (vid, range) { }
|
||||
|
||||
void addNeighbor (EgNode* n) { neighs_.insert (n); }
|
||||
|
||||
void removeNeighbor (EgNode* n) { neighs_.remove (n); }
|
||||
|
||||
bool isNeighbor (EgNode* n) const { return neighs_.contains (n); }
|
||||
|
||||
const EGNeighs& neighbors (void) const { return neighs_; }
|
||||
|
||||
private:
|
||||
EGNeighs neighs_;
|
||||
};
|
||||
|
||||
|
||||
class ElimGraph
|
||||
{
|
||||
public:
|
||||
ElimGraph (const vector<Factor*>&); // TODO
|
||||
|
||||
~ElimGraph (void);
|
||||
|
||||
VarIds getEliminatingOrder (const VarIds&);
|
||||
|
||||
void print (void) const;
|
||||
|
||||
void exportToGraphViz (const char*, bool = true,
|
||||
const VarIds& = VarIds()) const;
|
||||
|
||||
static VarIds getEliminationOrder (const vector<Factor*>, VarIds);
|
||||
|
||||
static ElimHeuristic elimHeuristic;
|
||||
|
||||
private:
|
||||
|
||||
void addEdge (EgNode* n1, EgNode* n2)
|
||||
{
|
||||
assert (n1 != n2);
|
||||
n1->addNeighbor (n2);
|
||||
n2->addNeighbor (n1);
|
||||
}
|
||||
|
||||
unsigned getNeighborsCost (const EgNode* n) const
|
||||
{
|
||||
return n->neighbors().size();
|
||||
}
|
||||
|
||||
unsigned getWeightCost (const EgNode* n) const
|
||||
{
|
||||
unsigned cost = 1;
|
||||
const EGNeighs& neighs = n->neighbors();
|
||||
for (unsigned i = 0; i < neighs.size(); i++) {
|
||||
cost *= neighs[i]->range();
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
unsigned getFillCost (const EgNode* n) const
|
||||
{
|
||||
unsigned cost = 0;
|
||||
const EGNeighs& neighs = n->neighbors();
|
||||
if (neighs.size() > 0) {
|
||||
for (unsigned i = 0; i < neighs.size() - 1; i++) {
|
||||
for (unsigned j = i + 1; j < neighs.size(); j++) {
|
||||
if ( ! neighbors (neighs[i], neighs[j])) {
|
||||
cost ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
unsigned getWeightedFillCost (const EgNode* n) const
|
||||
{
|
||||
unsigned cost = 0;
|
||||
const EGNeighs& neighs = n->neighbors();
|
||||
if (neighs.size() > 0) {
|
||||
for (unsigned i = 0; i < neighs.size() - 1; i++) {
|
||||
for (unsigned j = i+1; j < neighs.size(); j++) {
|
||||
if ( ! neighbors (neighs[i], neighs[j])) {
|
||||
cost += neighs[i]->range() * neighs[j]->range();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
bool neighbors (EgNode* n1, EgNode* n2) const
|
||||
{
|
||||
return n1->isNeighbor (n2);
|
||||
}
|
||||
|
||||
void addNode (EgNode*);
|
||||
|
||||
EgNode* getEgNode (VarId) const;
|
||||
|
||||
EgNode* getLowestCostNode (void) const;
|
||||
|
||||
void connectAllNeighbors (const EgNode*);
|
||||
|
||||
vector<EgNode*> nodes_;
|
||||
TinySet<EgNode*> unmarked_;
|
||||
unordered_map<VarId, EgNode*> varMap_;
|
||||
};
|
||||
|
||||
#endif // HORUS_ELIMGRAPH_H
|
||||
|
288
packages/CLPBN/horus/Factor.cpp
Normal file
288
packages/CLPBN/horus/Factor.cpp
Normal file
@ -0,0 +1,288 @@
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "Factor.h"
|
||||
#include "Indexer.h"
|
||||
|
||||
|
||||
Factor::Factor (const Factor& g)
|
||||
{
|
||||
copyFromFactor (g);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Factor::Factor (
|
||||
const VarIds& vids,
|
||||
const Ranges& ranges,
|
||||
const Params& params,
|
||||
unsigned distId)
|
||||
{
|
||||
args_ = vids;
|
||||
ranges_ = ranges;
|
||||
params_ = params;
|
||||
distId_ = distId;
|
||||
assert (params_.size() == Util::expectedSize (ranges_));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Factor::Factor (
|
||||
const Vars& vars,
|
||||
const Params& params,
|
||||
unsigned distId)
|
||||
{
|
||||
for (unsigned i = 0; i < vars.size(); i++) {
|
||||
args_.push_back (vars[i]->varId());
|
||||
ranges_.push_back (vars[i]->range());
|
||||
}
|
||||
params_ = params;
|
||||
distId_ = distId;
|
||||
assert (params_.size() == Util::expectedSize (ranges_));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Factor::sumOut (VarId vid)
|
||||
{
|
||||
int idx = indexOf (vid);
|
||||
assert (idx != -1);
|
||||
if (vid == args_.back()) {
|
||||
sumOutLastVariable(); // optimization
|
||||
return;
|
||||
}
|
||||
if (vid == args_.front()) {
|
||||
sumOutFirstVariable(); // optimization
|
||||
return;
|
||||
}
|
||||
sumOutIndex (idx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Factor::sumOutAllExcept (VarId vid)
|
||||
{
|
||||
assert (indexOf (vid) != -1);
|
||||
while (args_.back() != vid) {
|
||||
sumOutLastVariable();
|
||||
}
|
||||
while (args_.front() != vid) {
|
||||
sumOutFirstVariable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Factor::sumOutAllExcept (const VarIds& vids)
|
||||
{
|
||||
for (int i = 0; i < (int)args_.size(); i++) {
|
||||
if (Util::contains (vids, args_[i]) == false) {
|
||||
sumOut (args_[i]);
|
||||
i --;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Factor::sumOutIndex (unsigned idx)
|
||||
{
|
||||
assert (idx < args_.size());
|
||||
// number of parameters separating a different state of `var',
|
||||
// with the states of the remaining variables fixed
|
||||
unsigned varOffset = 1;
|
||||
|
||||
// number of parameters separating a different state of the variable
|
||||
// on the left of `var', with the states of the remaining vars fixed
|
||||
unsigned leftVarOffset = 1;
|
||||
|
||||
for (int i = args_.size() - 1; i > (int)idx; i--) {
|
||||
varOffset *= ranges_[i];
|
||||
leftVarOffset *= ranges_[i];
|
||||
}
|
||||
leftVarOffset *= ranges_[idx];
|
||||
|
||||
unsigned offset = 0;
|
||||
unsigned count1 = 0;
|
||||
unsigned count2 = 0;
|
||||
unsigned newpsSize = params_.size() / ranges_[idx];
|
||||
|
||||
Params newps;
|
||||
newps.reserve (newpsSize);
|
||||
|
||||
while (newps.size() < newpsSize) {
|
||||
double sum = LogAware::addIdenty();
|
||||
for (unsigned i = 0; i < ranges_[idx]; i++) {
|
||||
if (Globals::logDomain) {
|
||||
sum = Util::logSum (sum, params_[offset]);
|
||||
} else {
|
||||
sum += params_[offset];
|
||||
}
|
||||
offset += varOffset;
|
||||
}
|
||||
newps.push_back (sum);
|
||||
count1 ++;
|
||||
if (idx == args_.size() - 1) {
|
||||
offset = count1 * ranges_[idx];
|
||||
} else {
|
||||
if (((offset - varOffset + 1) % leftVarOffset) == 0) {
|
||||
count1 = 0;
|
||||
count2 ++;
|
||||
}
|
||||
offset = (leftVarOffset * count2) + count1;
|
||||
}
|
||||
}
|
||||
args_.erase (args_.begin() + idx);
|
||||
ranges_.erase (ranges_.begin() + idx);
|
||||
params_ = newps;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Factor::sumOutAllExceptIndex (unsigned idx)
|
||||
{
|
||||
assert (idx < args_.size());
|
||||
while (args_.size() > idx + 1) {
|
||||
sumOutLastVariable();
|
||||
}
|
||||
for (unsigned i = 0; i < idx; i++) {
|
||||
sumOutFirstVariable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Factor::sumOutFirstVariable (void)
|
||||
{
|
||||
assert (args_.size() > 1);
|
||||
unsigned range = ranges_.front();
|
||||
unsigned sep = params_.size() / range;
|
||||
if (Globals::logDomain) {
|
||||
for (unsigned i = sep; i < params_.size(); i++) {
|
||||
params_[i % sep] = Util::logSum (params_[i % sep], params_[i]);
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = sep; i < params_.size(); i++) {
|
||||
params_[i % sep] += params_[i];
|
||||
}
|
||||
}
|
||||
params_.resize (sep);
|
||||
args_.erase (args_.begin());
|
||||
ranges_.erase (ranges_.begin());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Factor::sumOutLastVariable (void)
|
||||
{
|
||||
assert (args_.size() > 1);
|
||||
unsigned range = ranges_.back();
|
||||
unsigned idx1 = 0;
|
||||
unsigned idx2 = 0;
|
||||
if (Globals::logDomain) {
|
||||
while (idx1 < params_.size()) {
|
||||
params_[idx2] = params_[idx1];
|
||||
idx1 ++;
|
||||
for (unsigned j = 1; j < range; j++) {
|
||||
params_[idx2] = Util::logSum (params_[idx2], params_[idx1]);
|
||||
idx1 ++;
|
||||
}
|
||||
idx2 ++;
|
||||
}
|
||||
} else {
|
||||
while (idx1 < params_.size()) {
|
||||
params_[idx2] = params_[idx1];
|
||||
idx1 ++;
|
||||
for (unsigned j = 1; j < range; j++) {
|
||||
params_[idx2] += params_[idx1];
|
||||
idx1 ++;
|
||||
}
|
||||
idx2 ++;
|
||||
}
|
||||
}
|
||||
params_.resize (idx2);
|
||||
args_.pop_back();
|
||||
ranges_.pop_back();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Factor::multiply (Factor& g)
|
||||
{
|
||||
if (args_.size() == 0) {
|
||||
copyFromFactor (g);
|
||||
return;
|
||||
}
|
||||
TFactor<VarId>::multiply (g);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Factor::reorderAccordingVarIds (void)
|
||||
{
|
||||
VarIds sortedVarIds = args_;
|
||||
sort (sortedVarIds.begin(), sortedVarIds.end());
|
||||
reorderArguments (sortedVarIds);
|
||||
}
|
||||
|
||||
|
||||
|
||||
string
|
||||
Factor::getLabel (void) const
|
||||
{
|
||||
stringstream ss;
|
||||
ss << "f(" ;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (i != 0) ss << "," ;
|
||||
ss << Var (args_[i], ranges_[i]).label();
|
||||
}
|
||||
ss << ")" ;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Factor::print (void) const
|
||||
{
|
||||
Vars vars;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
vars.push_back (new Var (args_[i], ranges_[i]));
|
||||
}
|
||||
vector<string> jointStrings = Util::getStateLines (vars);
|
||||
for (unsigned i = 0; i < params_.size(); i++) {
|
||||
// cout << "[" << distId_ << "] " ;
|
||||
cout << "f(" << jointStrings[i] << ")" ;
|
||||
cout << " = " << params_[i] << endl;
|
||||
}
|
||||
cout << endl;
|
||||
for (unsigned i = 0; i < vars.size(); i++) {
|
||||
delete vars[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Factor::copyFromFactor (const Factor& g)
|
||||
{
|
||||
args_ = g.arguments();
|
||||
ranges_ = g.ranges();
|
||||
params_ = g.params();
|
||||
distId_ = g.distId();
|
||||
}
|
||||
|
305
packages/CLPBN/horus/Factor.h
Normal file
305
packages/CLPBN/horus/Factor.h
Normal file
@ -0,0 +1,305 @@
|
||||
#ifndef HORUS_FACTOR_H
|
||||
#define HORUS_FACTOR_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Var.h"
|
||||
#include "Indexer.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
template <typename T>
|
||||
class TFactor
|
||||
{
|
||||
public:
|
||||
const vector<T>& arguments (void) const { return args_; }
|
||||
|
||||
vector<T>& arguments (void) { return args_; }
|
||||
|
||||
const Ranges& ranges (void) const { return ranges_; }
|
||||
|
||||
const Params& params (void) const { return params_; }
|
||||
|
||||
Params& params (void) { return params_; }
|
||||
|
||||
unsigned nrArguments (void) const { return args_.size(); }
|
||||
|
||||
unsigned size (void) const { return params_.size(); }
|
||||
|
||||
unsigned distId (void) const { return distId_; }
|
||||
|
||||
void setDistId (unsigned id) { distId_ = id; }
|
||||
|
||||
void normalize (void) { LogAware::normalize (params_); }
|
||||
|
||||
void setParams (const Params& newParams)
|
||||
{
|
||||
params_ = newParams;
|
||||
assert (params_.size() == Util::expectedSize (ranges_));
|
||||
}
|
||||
|
||||
int indexOf (const T& t) const
|
||||
{
|
||||
int idx = -1;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (args_[i] == t) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
const T& argument (unsigned idx) const
|
||||
{
|
||||
assert (idx < args_.size());
|
||||
return args_[idx];
|
||||
}
|
||||
|
||||
T& argument (unsigned idx)
|
||||
{
|
||||
assert (idx < args_.size());
|
||||
return args_[idx];
|
||||
}
|
||||
|
||||
unsigned range (unsigned idx) const
|
||||
{
|
||||
assert (idx < ranges_.size());
|
||||
return ranges_[idx];
|
||||
}
|
||||
|
||||
void multiply (TFactor<T>& g)
|
||||
{
|
||||
const vector<T>& g_args = g.arguments();
|
||||
const Ranges& g_ranges = g.ranges();
|
||||
const Params& g_params = g.params();
|
||||
if (args_ == g_args) {
|
||||
// optimization: if the factors contain the same set of args,
|
||||
// we can do a 1 to 1 operation on the parameters
|
||||
if (Globals::logDomain) {
|
||||
Util::add (params_, g_params);
|
||||
} else {
|
||||
Util::multiply (params_, g_params);
|
||||
}
|
||||
} else {
|
||||
bool sharedArgs = false;
|
||||
vector<unsigned> gvarpos;
|
||||
for (unsigned i = 0; i < g_args.size(); i++) {
|
||||
int idx = indexOf (g_args[i]);
|
||||
if (idx == -1) {
|
||||
ullong newSize = params_.size() * g_ranges[i];
|
||||
if (newSize > params_.max_size()) {
|
||||
cerr << "error: an overflow occurred on factor multiplication" ;
|
||||
cerr << endl;
|
||||
abort();
|
||||
}
|
||||
insertArgument (g_args[i], g_ranges[i]);
|
||||
gvarpos.push_back (args_.size() - 1);
|
||||
} else {
|
||||
sharedArgs = true;
|
||||
gvarpos.push_back (idx);
|
||||
}
|
||||
}
|
||||
if (sharedArgs == false) {
|
||||
// optimization: if the original factors doesn't have common args,
|
||||
// we don't need to marry the states of the common args
|
||||
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 = gvarpos.size() - 1; j >= 0; j--) {
|
||||
g_li += indexer[gvarpos[j]] * prod;
|
||||
prod *= g_ranges[j];
|
||||
}
|
||||
if (Globals::logDomain) {
|
||||
params_[indexer] += g_params[g_li];
|
||||
} else {
|
||||
params_[indexer] *= g_params[g_li];
|
||||
}
|
||||
++ indexer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void absorveEvidence (const T& arg, unsigned evidence)
|
||||
{
|
||||
int idx = indexOf (arg);
|
||||
assert (idx != -1);
|
||||
assert (evidence < ranges_[idx]);
|
||||
Params copy = params_;
|
||||
params_.clear();
|
||||
params_.reserve (copy.size() / ranges_[idx]);
|
||||
StatesIndexer indexer (ranges_);
|
||||
for (unsigned i = 0; i < evidence; i++) {
|
||||
indexer.increment (idx);
|
||||
}
|
||||
while (indexer.valid()) {
|
||||
params_.push_back (copy[indexer]);
|
||||
indexer.incrementExcluding (idx);
|
||||
}
|
||||
args_.erase (args_.begin() + idx);
|
||||
ranges_.erase (ranges_.begin() + idx);
|
||||
}
|
||||
|
||||
void reorderArguments (const vector<T> newArgs)
|
||||
{
|
||||
assert (newArgs.size() == args_.size());
|
||||
if (newArgs == args_) {
|
||||
return; // already in the wanted order
|
||||
}
|
||||
Ranges newRanges;
|
||||
vector<unsigned> positions;
|
||||
for (unsigned i = 0; i < newArgs.size(); i++) {
|
||||
unsigned idx = indexOf (newArgs[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];
|
||||
}
|
||||
args_ = newArgs;
|
||||
ranges_ = newRanges;
|
||||
params_ = newParams;
|
||||
}
|
||||
|
||||
bool contains (const T& arg) const
|
||||
{
|
||||
return Util::contains (args_, arg);
|
||||
}
|
||||
|
||||
bool contains (const vector<T>& args) const
|
||||
{
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (contains (args[i]) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
double& operator[] (psize_t idx)
|
||||
{
|
||||
assert (idx < params_.size());
|
||||
return params_[idx];
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
vector<T> args_;
|
||||
Ranges ranges_;
|
||||
Params params_;
|
||||
unsigned distId_;
|
||||
|
||||
private:
|
||||
void insertArgument (const T& arg, unsigned range)
|
||||
{
|
||||
assert (indexOf (arg) == -1);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
args_.push_back (arg);
|
||||
ranges_.push_back (range);
|
||||
}
|
||||
|
||||
void insertArguments (const vector<T>& args, const Ranges& ranges)
|
||||
{
|
||||
Params copy = params_;
|
||||
unsigned nrStates = 1;
|
||||
for (unsigned i = 0; i < args.size(); i++) {
|
||||
assert (indexOf (args[i]) == -1);
|
||||
args_.push_back (args[i]);
|
||||
ranges_.push_back (ranges[i]);
|
||||
nrStates *= ranges[i];
|
||||
}
|
||||
params_.clear();
|
||||
params_.reserve (copy.size() * nrStates);
|
||||
for (unsigned i = 0; i < copy.size(); i++) {
|
||||
for (unsigned reps = 0; reps < nrStates; reps++) {
|
||||
params_.push_back (copy[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Factor : public TFactor<VarId>
|
||||
{
|
||||
public:
|
||||
Factor (void) { }
|
||||
|
||||
Factor (const Factor&);
|
||||
|
||||
Factor (const VarIds&, const Ranges&, const Params&,
|
||||
unsigned = Util::maxUnsigned());
|
||||
|
||||
Factor (const Vars&, const Params&,
|
||||
unsigned = Util::maxUnsigned());
|
||||
|
||||
void sumOut (VarId);
|
||||
|
||||
void sumOutAllExcept (VarId);
|
||||
|
||||
void sumOutAllExcept (const VarIds&);
|
||||
|
||||
void sumOutIndex (unsigned idx);
|
||||
|
||||
void sumOutAllExceptIndex (unsigned idx);
|
||||
|
||||
void sumOutFirstVariable (void);
|
||||
|
||||
void sumOutLastVariable (void);
|
||||
|
||||
void multiply (Factor&);
|
||||
|
||||
void reorderAccordingVarIds (void);
|
||||
|
||||
string getLabel (void) const;
|
||||
|
||||
void print (void) const;
|
||||
|
||||
private:
|
||||
void copyFromFactor (const Factor& f);
|
||||
|
||||
};
|
||||
|
||||
#endif // HORUS_FACTOR_H
|
||||
|
465
packages/CLPBN/horus/FactorGraph.cpp
Normal file
465
packages/CLPBN/horus/FactorGraph.cpp
Normal file
@ -0,0 +1,465 @@
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "FactorGraph.h"
|
||||
#include "Factor.h"
|
||||
#include "BayesNet.h"
|
||||
#include "BayesBall.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
FactorGraph::FactorGraph (const FactorGraph& fg)
|
||||
{
|
||||
const VarNodes& varNodes = fg.varNodes();
|
||||
for (unsigned i = 0; i < varNodes.size(); i++) {
|
||||
addVarNode (new VarNode (varNodes[i]));
|
||||
}
|
||||
const FacNodes& facNodes = fg.facNodes();
|
||||
for (unsigned i = 0; i < facNodes.size(); i++) {
|
||||
FacNode* facNode = new FacNode (facNodes[i]->factor());
|
||||
addFacNode (facNode);
|
||||
const VarNodes& neighs = facNodes[i]->neighbors();
|
||||
for (unsigned j = 0; j < neighs.size(); j++) {
|
||||
addEdge (varNodes_[neighs[j]->getIndex()], facNode);
|
||||
}
|
||||
}
|
||||
fromBayesNet_ = fg.isFromBayesNetwork();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::readFromUaiFormat (const char* fileName)
|
||||
{
|
||||
std::ifstream is (fileName);
|
||||
if (!is.is_open()) {
|
||||
cerr << "error: cannot read from file " << fileName << endl;
|
||||
abort();
|
||||
}
|
||||
ignoreLines (is);
|
||||
string line;
|
||||
getline (is, line);
|
||||
if (line != "MARKOV") {
|
||||
cerr << "error: the network must be a MARKOV network " << endl;
|
||||
abort();
|
||||
}
|
||||
// read the number of vars
|
||||
ignoreLines (is);
|
||||
unsigned nrVars;
|
||||
is >> nrVars;
|
||||
// read the range of each var
|
||||
ignoreLines (is);
|
||||
Ranges ranges (nrVars);
|
||||
for (unsigned i = 0; i < nrVars; i++) {
|
||||
is >> ranges[i];
|
||||
}
|
||||
unsigned nrFactors;
|
||||
unsigned nrArgs;
|
||||
unsigned vid;
|
||||
is >> nrFactors;
|
||||
vector<VarIds> factorVarIds;
|
||||
vector<Ranges> factorRanges;
|
||||
for (unsigned i = 0; i < nrFactors; i++) {
|
||||
ignoreLines (is);
|
||||
is >> nrArgs;
|
||||
factorVarIds.push_back ({ });
|
||||
factorRanges.push_back ({ });
|
||||
for (unsigned j = 0; j < nrArgs; j++) {
|
||||
is >> vid;
|
||||
if (vid >= ranges.size()) {
|
||||
cerr << "error: invalid variable identifier `" << vid << "'" << endl;
|
||||
cerr << "identifiers must be between 0 and " << ranges.size() - 1 ;
|
||||
cerr << endl;
|
||||
abort();
|
||||
}
|
||||
factorVarIds.back().push_back (vid);
|
||||
factorRanges.back().push_back (ranges[vid]);
|
||||
}
|
||||
}
|
||||
// read the parameters
|
||||
unsigned nrParams;
|
||||
for (unsigned i = 0; i < nrFactors; i++) {
|
||||
ignoreLines (is);
|
||||
is >> nrParams;
|
||||
if (nrParams != Util::expectedSize (factorRanges[i])) {
|
||||
cerr << "error: invalid number of parameters for factor nº " << i ;
|
||||
cerr << ", expected: " << Util::expectedSize (factorRanges[i]);
|
||||
cerr << ", given: " << nrParams << endl;
|
||||
abort();
|
||||
}
|
||||
Params params (nrParams);
|
||||
for (unsigned j = 0; j < nrParams; j++) {
|
||||
is >> params[j];
|
||||
}
|
||||
if (Globals::logDomain) {
|
||||
Util::toLog (params);
|
||||
}
|
||||
addFactor (Factor (factorVarIds[i], factorRanges[i], params));
|
||||
}
|
||||
is.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::readFromLibDaiFormat (const char* fileName)
|
||||
{
|
||||
std::ifstream is (fileName);
|
||||
if (!is.is_open()) {
|
||||
cerr << "error: cannot read from file " << fileName << endl;
|
||||
abort();
|
||||
}
|
||||
ignoreLines (is);
|
||||
unsigned nrFactors;
|
||||
unsigned nrArgs;
|
||||
VarId vid;
|
||||
is >> nrFactors;
|
||||
for (unsigned i = 0; i < nrFactors; i++) {
|
||||
ignoreLines (is);
|
||||
// read the factor arguments
|
||||
is >> nrArgs;
|
||||
VarIds vids;
|
||||
for (unsigned j = 0; j < nrArgs; j++) {
|
||||
ignoreLines (is);
|
||||
is >> vid;
|
||||
vids.push_back (vid);
|
||||
}
|
||||
// read ranges
|
||||
Ranges ranges (nrArgs);
|
||||
for (unsigned j = 0; j < nrArgs; j++) {
|
||||
ignoreLines (is);
|
||||
is >> ranges[j];
|
||||
VarNode* var = getVarNode (vids[j]);
|
||||
if (var != 0 && ranges[j] != var->range()) {
|
||||
cerr << "error: variable `" << vids[j] << "' appears in two or " ;
|
||||
cerr << "more factors with a different range" << endl;
|
||||
}
|
||||
}
|
||||
// read parameters
|
||||
ignoreLines (is);
|
||||
unsigned nNonzeros;
|
||||
is >> nNonzeros;
|
||||
Params params (Util::expectedSize (ranges), 0);
|
||||
for (unsigned j = 0; j < nNonzeros; j++) {
|
||||
ignoreLines (is);
|
||||
unsigned index;
|
||||
is >> index;
|
||||
ignoreLines (is);
|
||||
double val;
|
||||
is >> val;
|
||||
params[index] = val;
|
||||
}
|
||||
if (Globals::logDomain) {
|
||||
Util::toLog (params);
|
||||
}
|
||||
reverse (vids.begin(), vids.end());
|
||||
Factor f (vids, ranges, params);
|
||||
reverse (vids.begin(), vids.end());
|
||||
f.reorderArguments (vids);
|
||||
addFactor (f);
|
||||
}
|
||||
is.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
FactorGraph::~FactorGraph (void)
|
||||
{
|
||||
for (unsigned i = 0; i < varNodes_.size(); i++) {
|
||||
delete varNodes_[i];
|
||||
}
|
||||
for (unsigned i = 0; i < facNodes_.size(); i++) {
|
||||
delete facNodes_[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::addFactor (const Factor& factor)
|
||||
{
|
||||
FacNode* fn = new FacNode (factor);
|
||||
addFacNode (fn);
|
||||
const VarIds& vids = fn->factor().arguments();
|
||||
for (unsigned i = 0; i < vids.size(); i++) {
|
||||
VarMap::const_iterator it = varMap_.find (vids[i]);
|
||||
if (it != varMap_.end()) {
|
||||
addEdge (it->second, fn);
|
||||
} else {
|
||||
VarNode* vn = new VarNode (vids[i], fn->factor().range (i));
|
||||
addVarNode (vn);
|
||||
addEdge (vn, fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::addVarNode (VarNode* vn)
|
||||
{
|
||||
varNodes_.push_back (vn);
|
||||
vn->setIndex (varNodes_.size() - 1);
|
||||
varMap_.insert (make_pair (vn->varId(), vn));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::addFacNode (FacNode* fn)
|
||||
{
|
||||
facNodes_.push_back (fn);
|
||||
fn->setIndex (facNodes_.size() - 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::addEdge (VarNode* vn, FacNode* fn)
|
||||
{
|
||||
vn->addNeighbor (fn);
|
||||
fn->addNeighbor (vn);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
FactorGraph::isTree (void) const
|
||||
{
|
||||
return !containsCycle();
|
||||
}
|
||||
|
||||
|
||||
|
||||
DAGraph&
|
||||
FactorGraph::getStructure (void)
|
||||
{
|
||||
assert (fromBayesNet_);
|
||||
if (structure_.empty()) {
|
||||
for (unsigned i = 0; i < varNodes_.size(); i++) {
|
||||
structure_.addNode (new DAGraphNode (varNodes_[i]));
|
||||
}
|
||||
for (unsigned i = 0; i < facNodes_.size(); i++) {
|
||||
const VarIds& vids = facNodes_[i]->factor().arguments();
|
||||
for (unsigned j = 1; j < vids.size(); j++) {
|
||||
structure_.addEdge (vids[j], vids[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return structure_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::print (void) const
|
||||
{
|
||||
for (unsigned i = 0; i < varNodes_.size(); i++) {
|
||||
cout << "var id = " << varNodes_[i]->varId() << endl;
|
||||
cout << "label = " << varNodes_[i]->label() << endl;
|
||||
cout << "range = " << varNodes_[i]->range() << endl;
|
||||
cout << "evidence = " << varNodes_[i]->getEvidence() << endl;
|
||||
cout << "factors = " ;
|
||||
for (unsigned j = 0; j < varNodes_[i]->neighbors().size(); j++) {
|
||||
cout << varNodes_[i]->neighbors()[j]->getLabel() << " " ;
|
||||
}
|
||||
cout << endl << endl;
|
||||
}
|
||||
for (unsigned i = 0; i < facNodes_.size(); i++) {
|
||||
facNodes_[i]->factor().print();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::exportToGraphViz (const char* fileName) const
|
||||
{
|
||||
ofstream out (fileName);
|
||||
if (!out.is_open()) {
|
||||
cerr << "error: cannot open file to write at " ;
|
||||
cerr << "FactorGraph::exportToDotFile()" << endl;
|
||||
abort();
|
||||
}
|
||||
out << "graph \"" << fileName << "\" {" << endl;
|
||||
for (unsigned i = 0; i < varNodes_.size(); i++) {
|
||||
if (varNodes_[i]->hasEvidence()) {
|
||||
out << '"' << varNodes_[i]->label() << '"' ;
|
||||
out << " [style=filled, fillcolor=yellow]" << endl;
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < facNodes_.size(); i++) {
|
||||
out << '"' << facNodes_[i]->getLabel() << '"' ;
|
||||
out << " [label=\"" << facNodes_[i]->getLabel();
|
||||
out << "\"" << ", shape=box]" << endl;
|
||||
}
|
||||
for (unsigned i = 0; i < facNodes_.size(); i++) {
|
||||
const VarNodes& myVars = facNodes_[i]->neighbors();
|
||||
for (unsigned j = 0; j < myVars.size(); j++) {
|
||||
out << '"' << facNodes_[i]->getLabel() << '"' ;
|
||||
out << " -- " ;
|
||||
out << '"' << myVars[j]->label() << '"' << endl;
|
||||
}
|
||||
}
|
||||
out << "}" << endl;
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::exportToUaiFormat (const char* fileName) const
|
||||
{
|
||||
ofstream out (fileName);
|
||||
if (!out.is_open()) {
|
||||
cerr << "error: cannot open file " << fileName << endl;
|
||||
abort();
|
||||
}
|
||||
out << "MARKOV" << endl;
|
||||
out << varNodes_.size() << endl;
|
||||
for (unsigned i = 0; i < varNodes_.size(); i++) {
|
||||
out << varNodes_[i]->range() << " " ;
|
||||
}
|
||||
out << endl;
|
||||
out << facNodes_.size() << endl;
|
||||
for (unsigned i = 0; i < facNodes_.size(); i++) {
|
||||
const VarNodes& factorVars = facNodes_[i]->neighbors();
|
||||
out << factorVars.size();
|
||||
for (unsigned j = 0; j < factorVars.size(); j++) {
|
||||
out << " " << factorVars[j]->getIndex();
|
||||
}
|
||||
out << endl;
|
||||
}
|
||||
for (unsigned i = 0; i < facNodes_.size(); i++) {
|
||||
Params params = facNodes_[i]->factor().params();
|
||||
if (Globals::logDomain) {
|
||||
Util::fromLog (params);
|
||||
}
|
||||
out << endl << params.size() << endl << " " ;
|
||||
for (unsigned j = 0; j < params.size(); j++) {
|
||||
out << params[j] << " " ;
|
||||
}
|
||||
out << endl;
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::exportToLibDaiFormat (const char* fileName) const
|
||||
{
|
||||
ofstream out (fileName);
|
||||
if (!out.is_open()) {
|
||||
cerr << "error: cannot open file " << fileName << endl;
|
||||
abort();
|
||||
}
|
||||
out << facNodes_.size() << endl << endl;
|
||||
for (unsigned i = 0; i < facNodes_.size(); i++) {
|
||||
const VarNodes& factorVars = facNodes_[i]->neighbors();
|
||||
out << factorVars.size() << endl;
|
||||
for (int j = factorVars.size() - 1; j >= 0; j--) {
|
||||
out << factorVars[j]->varId() << " " ;
|
||||
}
|
||||
out << endl;
|
||||
for (unsigned j = 0; j < factorVars.size(); j++) {
|
||||
out << factorVars[j]->range() << " " ;
|
||||
}
|
||||
out << endl;
|
||||
Params params = facNodes_[i]->factor().params();
|
||||
if (Globals::logDomain) {
|
||||
Util::fromLog (params);
|
||||
}
|
||||
out << params.size() << endl;
|
||||
for (unsigned j = 0; j < params.size(); j++) {
|
||||
out << j << " " << params[j] << endl;
|
||||
}
|
||||
out << endl;
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FactorGraph::ignoreLines (std::ifstream& is) const
|
||||
{
|
||||
string ignoreStr;
|
||||
while (is.peek() == '#' || is.peek() == '\n') {
|
||||
getline (is, ignoreStr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
FactorGraph::containsCycle (void) const
|
||||
{
|
||||
vector<bool> visitedVars (varNodes_.size(), false);
|
||||
vector<bool> visitedFactors (facNodes_.size(), false);
|
||||
for (unsigned i = 0; i < varNodes_.size(); i++) {
|
||||
int v = varNodes_[i]->getIndex();
|
||||
if (!visitedVars[v]) {
|
||||
if (containsCycle (varNodes_[i], 0, visitedVars, visitedFactors)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
FactorGraph::containsCycle (
|
||||
const VarNode* v,
|
||||
const FacNode* p,
|
||||
vector<bool>& visitedVars,
|
||||
vector<bool>& visitedFactors) const
|
||||
{
|
||||
visitedVars[v->getIndex()] = true;
|
||||
const FacNodes& adjacencies = v->neighbors();
|
||||
for (unsigned i = 0; i < adjacencies.size(); i++) {
|
||||
int w = adjacencies[i]->getIndex();
|
||||
if (!visitedFactors[w]) {
|
||||
if (containsCycle (adjacencies[i], v, visitedVars, visitedFactors)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (visitedFactors[w] && adjacencies[i] != p) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // no cycle detected in this component
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
FactorGraph::containsCycle (
|
||||
const FacNode* v,
|
||||
const VarNode* p,
|
||||
vector<bool>& visitedVars,
|
||||
vector<bool>& visitedFactors) const
|
||||
{
|
||||
visitedFactors[v->getIndex()] = true;
|
||||
const VarNodes& adjacencies = v->neighbors();
|
||||
for (unsigned i = 0; i < adjacencies.size(); i++) {
|
||||
int w = adjacencies[i]->getIndex();
|
||||
if (!visitedVars[w]) {
|
||||
if (containsCycle (adjacencies[i], v, visitedVars, visitedFactors)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (visitedVars[w] && adjacencies[i] != p) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // no cycle detected in this component
|
||||
}
|
||||
|
145
packages/CLPBN/horus/FactorGraph.h
Normal file
145
packages/CLPBN/horus/FactorGraph.h
Normal file
@ -0,0 +1,145 @@
|
||||
#ifndef HORUS_FACTORGRAPH_H
|
||||
#define HORUS_FACTORGRAPH_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Factor.h"
|
||||
#include "BayesNet.h"
|
||||
#include "Horus.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
class FacNode;
|
||||
|
||||
class VarNode : public Var
|
||||
{
|
||||
public:
|
||||
VarNode (VarId varId, unsigned nrStates,
|
||||
int evidence = Constants::NO_EVIDENCE)
|
||||
: Var (varId, nrStates, evidence) { }
|
||||
|
||||
VarNode (const Var* v) : Var (v) { }
|
||||
|
||||
void addNeighbor (FacNode* fn) { neighs_.push_back (fn); }
|
||||
|
||||
const FacNodes& neighbors (void) const { return neighs_; }
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (VarNode);
|
||||
|
||||
FacNodes neighs_;
|
||||
};
|
||||
|
||||
|
||||
class FacNode
|
||||
{
|
||||
public:
|
||||
FacNode (const Factor& f) : factor_(f), index_(-1) { }
|
||||
|
||||
const Factor& factor (void) const { return factor_; }
|
||||
|
||||
Factor& factor (void) { return factor_; }
|
||||
|
||||
void addNeighbor (VarNode* vn) { neighs_.push_back (vn); }
|
||||
|
||||
const VarNodes& neighbors (void) const { return neighs_; }
|
||||
|
||||
int getIndex (void) const { return index_; }
|
||||
|
||||
void setIndex (int index) { index_ = index; }
|
||||
|
||||
string getLabel (void) { return factor_.getLabel(); }
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (FacNode);
|
||||
|
||||
VarNodes neighs_;
|
||||
Factor factor_;
|
||||
int index_;
|
||||
};
|
||||
|
||||
|
||||
struct CompVarId
|
||||
{
|
||||
bool operator() (const Var* v1, const Var* v2) const
|
||||
{
|
||||
return v1->varId() < v2->varId();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class FactorGraph
|
||||
{
|
||||
public:
|
||||
FactorGraph (bool fbn = false) : fromBayesNet_(fbn) { }
|
||||
|
||||
FactorGraph (const FactorGraph&);
|
||||
|
||||
~FactorGraph (void);
|
||||
|
||||
const VarNodes& varNodes (void) const { return varNodes_; }
|
||||
|
||||
const FacNodes& facNodes (void) const { return facNodes_; }
|
||||
|
||||
bool isFromBayesNetwork (void) const { return fromBayesNet_ ; }
|
||||
|
||||
unsigned nrVarNodes (void) const { return varNodes_.size(); }
|
||||
|
||||
unsigned nrFacNodes (void) const { return facNodes_.size(); }
|
||||
|
||||
VarNode* getVarNode (VarId vid) const
|
||||
{
|
||||
VarMap::const_iterator it = varMap_.find (vid);
|
||||
return it != varMap_.end() ? it->second : 0;
|
||||
}
|
||||
|
||||
void readFromUaiFormat (const char*);
|
||||
|
||||
void readFromLibDaiFormat (const char*);
|
||||
|
||||
void addFactor (const Factor& factor);
|
||||
|
||||
void addVarNode (VarNode*);
|
||||
|
||||
void addFacNode (FacNode*);
|
||||
|
||||
void addEdge (VarNode*, FacNode*);
|
||||
|
||||
bool isTree (void) const;
|
||||
|
||||
DAGraph& getStructure (void);
|
||||
|
||||
void print (void) const;
|
||||
|
||||
void exportToGraphViz (const char*) const;
|
||||
|
||||
void exportToUaiFormat (const char*) const;
|
||||
|
||||
void exportToLibDaiFormat (const char*) const;
|
||||
|
||||
private:
|
||||
// DISALLOW_COPY_AND_ASSIGN (FactorGraph);
|
||||
|
||||
void ignoreLines (std::ifstream&) const;
|
||||
|
||||
bool containsCycle (void) const;
|
||||
|
||||
bool containsCycle (const VarNode*, const FacNode*,
|
||||
vector<bool>&, vector<bool>&) const;
|
||||
|
||||
bool containsCycle (const FacNode*, const VarNode*,
|
||||
vector<bool>&, vector<bool>&) const;
|
||||
|
||||
VarNodes varNodes_;
|
||||
FacNodes facNodes_;
|
||||
|
||||
DAGraph structure_;
|
||||
bool fromBayesNet_;
|
||||
|
||||
typedef unordered_map<unsigned, VarNode*> VarMap;
|
||||
VarMap varMap_;
|
||||
};
|
||||
|
||||
#endif // HORUS_FACTORGRAPH_H
|
||||
|
1000
packages/CLPBN/horus/FoveSolver.cpp
Normal file
1000
packages/CLPBN/horus/FoveSolver.cpp
Normal file
File diff suppressed because it is too large
Load Diff
168
packages/CLPBN/horus/FoveSolver.h
Normal file
168
packages/CLPBN/horus/FoveSolver.h
Normal file
@ -0,0 +1,168 @@
|
||||
#ifndef HORUS_FOVESOLVER_H
|
||||
#define HORUS_FOVESOLVER_H
|
||||
|
||||
|
||||
#include "ParfactorList.h"
|
||||
|
||||
|
||||
class LiftedOperator
|
||||
{
|
||||
public:
|
||||
virtual double getLogCost (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&);
|
||||
|
||||
static vector<ParfactorList::iterator> getParfactorsWithGroup (
|
||||
ParfactorList&, unsigned group);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ProductOperator : public LiftedOperator
|
||||
{
|
||||
public:
|
||||
ProductOperator (
|
||||
ParfactorList::iterator g1, ParfactorList::iterator g2,
|
||||
ParfactorList& pfList) : g1_(g1), g2_(g2), pfList_(pfList) { }
|
||||
|
||||
double getLogCost (void);
|
||||
|
||||
void apply (void);
|
||||
|
||||
static vector<ProductOperator*> getValidOps (ParfactorList&);
|
||||
|
||||
string toString (void);
|
||||
|
||||
private:
|
||||
static bool validOp (Parfactor*, Parfactor*);
|
||||
|
||||
ParfactorList::iterator g1_;
|
||||
ParfactorList::iterator g2_;
|
||||
ParfactorList& pfList_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SumOutOperator : public LiftedOperator
|
||||
{
|
||||
public:
|
||||
SumOutOperator (unsigned group, ParfactorList& pfList)
|
||||
: group_(group), pfList_(pfList) { }
|
||||
|
||||
double getLogCost (void);
|
||||
|
||||
void apply (void);
|
||||
|
||||
static vector<SumOutOperator*> getValidOps (
|
||||
ParfactorList&, const Grounds&);
|
||||
|
||||
string toString (void);
|
||||
|
||||
private:
|
||||
static bool validOp (unsigned, ParfactorList&, const Grounds&);
|
||||
|
||||
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) { }
|
||||
|
||||
double getLogCost (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 (
|
||||
unsigned group,
|
||||
unsigned lvIndex,
|
||||
ParfactorList& pfList)
|
||||
: group_(group), lvIndex_(lvIndex), pfList_(pfList) { }
|
||||
|
||||
double getLogCost (void);
|
||||
|
||||
void apply (void);
|
||||
|
||||
static vector<GroundOperator*> getValidOps (ParfactorList&);
|
||||
|
||||
string toString (void);
|
||||
|
||||
private:
|
||||
vector<pair<unsigned, unsigned>> getAffectedFormulas (void);
|
||||
|
||||
unsigned group_;
|
||||
unsigned lvIndex_;
|
||||
ParfactorList& pfList_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class FoveSolver
|
||||
{
|
||||
public:
|
||||
FoveSolver (const ParfactorList& pfList) : pfList_(pfList) { }
|
||||
|
||||
Params getPosterioriOf (const Ground&);
|
||||
|
||||
Params getJointDistributionOf (const Grounds&);
|
||||
|
||||
void printSolverFlags (void) const;
|
||||
|
||||
static void absorveEvidence (
|
||||
ParfactorList& pfList, ObservedFormulas& obsFormulas);
|
||||
|
||||
static Parfactors countNormalize (Parfactor*, const LogVarSet&);
|
||||
|
||||
static Parfactor calcGroundMultiplication (Parfactor pf);
|
||||
|
||||
private:
|
||||
void runSolver (const Grounds&);
|
||||
|
||||
LiftedOperator* getBestOperation (const Grounds&);
|
||||
|
||||
void runWeakBayesBall (const Grounds&);
|
||||
|
||||
void shatterAgainstQuery (const Grounds&);
|
||||
|
||||
static Parfactors absorve (ObservedFormula&, Parfactor*);
|
||||
|
||||
ParfactorList pfList_;
|
||||
|
||||
double largestCost_;
|
||||
};
|
||||
|
||||
#endif // HORUS_FOVESOLVER_H
|
||||
|
145
packages/CLPBN/horus/Histogram.cpp
Normal file
145
packages/CLPBN/horus/Histogram.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
#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 HistogramSet::nrHistograms (size_, hist_.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
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& h,
|
||||
const vector<Histogram>& hists)
|
||||
{
|
||||
vector<Histogram>::const_iterator it = std::lower_bound (
|
||||
hists.begin(), hists.end(), h, std::greater<Histogram>());
|
||||
assert (it != hists.end() && *it == h);
|
||||
return std::distance (hists.begin(), it);
|
||||
}
|
||||
|
||||
|
||||
|
||||
vector<double>
|
||||
HistogramSet::getNumAssigns (unsigned N, unsigned R)
|
||||
{
|
||||
HistogramSet hs (N, R);
|
||||
double N_fac = Util::logFactorial (N);
|
||||
unsigned H = hs.nrHistograms();
|
||||
vector<double> numAssigns;
|
||||
numAssigns.reserve (H);
|
||||
for (unsigned h = 0; h < H; h++) {
|
||||
double prod = 0.0;
|
||||
for (unsigned r = 0; r < R; r++) {
|
||||
prod += Util::logFactorial (hs[r]);
|
||||
}
|
||||
double res = N_fac - prod;
|
||||
numAssigns.push_back (Globals::logDomain ? res : std::exp (res));
|
||||
hs.nextHistogram();
|
||||
}
|
||||
return numAssigns;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
45
packages/CLPBN/horus/Histogram.h
Normal file
45
packages/CLPBN/horus/Histogram.h
Normal file
@ -0,0 +1,45 @@
|
||||
#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>&);
|
||||
|
||||
static vector<double> getNumAssigns (unsigned, unsigned);
|
||||
|
||||
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
|
||||
|
81
packages/CLPBN/horus/Horus.h
Normal file
81
packages/CLPBN/horus/Horus.h
Normal file
@ -0,0 +1,81 @@
|
||||
#ifndef HORUS_HORUS_H
|
||||
#define HORUS_HORUS_H
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Var;
|
||||
class Factor;
|
||||
class VarNode;
|
||||
class FacNode;
|
||||
|
||||
typedef vector<double> Params;
|
||||
typedef unsigned VarId;
|
||||
typedef vector<VarId> VarIds;
|
||||
typedef vector<Var*> Vars;
|
||||
typedef vector<VarNode*> VarNodes;
|
||||
typedef vector<FacNode*> FacNodes;
|
||||
typedef vector<Factor*> Factors;
|
||||
typedef vector<string> States;
|
||||
typedef vector<unsigned> Ranges;
|
||||
typedef Params::size_type psize_t;
|
||||
typedef unsigned long long ullong;
|
||||
|
||||
|
||||
enum InfAlgorithms
|
||||
{
|
||||
VE, // variable elimination
|
||||
BP, // belief propagation
|
||||
CBP // counting belief propagation
|
||||
};
|
||||
|
||||
|
||||
namespace Globals {
|
||||
|
||||
extern bool logDomain;
|
||||
|
||||
// level of debug information
|
||||
extern unsigned verbosity;
|
||||
|
||||
extern InfAlgorithms infAlgorithm;
|
||||
|
||||
};
|
||||
|
||||
|
||||
namespace Constants {
|
||||
|
||||
// show message calculation for belief propagation
|
||||
const bool SHOW_BP_CALCS = false;
|
||||
|
||||
const int NO_EVIDENCE = -1;
|
||||
|
||||
// number of digits to show when printing a parameter
|
||||
const unsigned PRECISION = 6;
|
||||
|
||||
const bool COLLECT_STATS = false;
|
||||
|
||||
};
|
||||
|
||||
|
||||
namespace BpOptions
|
||||
{
|
||||
enum Schedule {
|
||||
SEQ_FIXED,
|
||||
SEQ_RANDOM,
|
||||
PARALLEL,
|
||||
MAX_RESIDUAL
|
||||
};
|
||||
extern Schedule schedule;
|
||||
extern double accuracy;
|
||||
extern unsigned maxIter;
|
||||
}
|
||||
|
||||
#endif // HORUS_HORUS_H
|
||||
|
188
packages/CLPBN/horus/HorusCli.cpp
Normal file
188
packages/CLPBN/horus/HorusCli.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
#include <cstdlib>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "FactorGraph.h"
|
||||
#include "VarElimSolver.h"
|
||||
#include "BpSolver.h"
|
||||
#include "CbpSolver.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int readHorusFlags (int, const char* []);
|
||||
void readFactorGraph (FactorGraph&, const char*);
|
||||
VarIds readQueryAndEvidence (FactorGraph&, int, const char* [], int);
|
||||
|
||||
void runSolver (const FactorGraph&, const VarIds&);
|
||||
|
||||
const string USAGE = "usage: ./hcli [HORUS_FLAG=VALUE] \
|
||||
NETWORK_FILE [VARIABLE | OBSERVED_VARIABLE=EVIDENCE] ..." ;
|
||||
|
||||
|
||||
int
|
||||
main (int argc, const char* argv[])
|
||||
{
|
||||
if (argc <= 1) {
|
||||
cerr << "error: no graphical model specified" << endl;
|
||||
cerr << USAGE << endl;
|
||||
exit (0);
|
||||
}
|
||||
int idx = readHorusFlags (argc, argv);
|
||||
FactorGraph fg;
|
||||
readFactorGraph (fg, argv[idx]);
|
||||
VarIds queryIds = readQueryAndEvidence (fg, argc, argv, idx + 1);
|
||||
runSolver (fg, queryIds);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
readHorusFlags (int argc, const char* argv[])
|
||||
{
|
||||
int i = 1;
|
||||
for (; i < argc; i++) {
|
||||
const string& arg = argv[i];
|
||||
size_t pos = arg.find ('=');
|
||||
if (pos == std::string::npos) {
|
||||
return i;
|
||||
}
|
||||
string leftArg = arg.substr (0, pos);
|
||||
string rightArg = arg.substr (pos + 1);
|
||||
if (leftArg.empty()) {
|
||||
cerr << "error: missing left argument" << endl;
|
||||
cerr << USAGE << endl;
|
||||
exit (0);
|
||||
}
|
||||
if (rightArg.empty()) {
|
||||
cerr << "error: missing right argument" << endl;
|
||||
cerr << USAGE << endl;
|
||||
exit (0);
|
||||
}
|
||||
Util::setHorusFlag (leftArg, rightArg);
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
readFactorGraph (FactorGraph& fg, const char* s)
|
||||
{
|
||||
string fileName (s);
|
||||
string extension = fileName.substr (fileName.find_last_of ('.') + 1);
|
||||
if (extension == "uai") {
|
||||
fg.readFromUaiFormat (fileName.c_str());
|
||||
} else if (extension == "fg") {
|
||||
fg.readFromLibDaiFormat (fileName.c_str());
|
||||
} else {
|
||||
cerr << "error: the graphical model must be defined either " ;
|
||||
cerr << "in a UAI or libDAI file" << endl;
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
VarIds
|
||||
readQueryAndEvidence (
|
||||
FactorGraph& fg,
|
||||
int argc,
|
||||
const char* argv[],
|
||||
int start)
|
||||
{
|
||||
VarIds queryIds;
|
||||
for (int i = start; i < argc; i++) {
|
||||
const string& arg = argv[i];
|
||||
if (arg.find ('=') == std::string::npos) {
|
||||
if (Util::isInteger (arg) == false) {
|
||||
cerr << "error: `" << arg << "' " ;
|
||||
cerr << "is not a variable id" ;
|
||||
cerr << endl;
|
||||
exit (0);
|
||||
}
|
||||
VarId vid = Util::stringToUnsigned (arg);
|
||||
VarNode* queryVar = fg.getVarNode (vid);
|
||||
if (queryVar == false) {
|
||||
cerr << "error: unknow variable with id " ;
|
||||
cerr << "`" << vid << "'" << endl;
|
||||
exit (0);
|
||||
}
|
||||
queryIds.push_back (vid);
|
||||
} else {
|
||||
size_t pos = arg.find ('=');
|
||||
string leftArg = arg.substr (0, pos);
|
||||
string rightArg = arg.substr (pos + 1);
|
||||
if (leftArg.empty()) {
|
||||
cerr << "error: missing left argument" << endl;
|
||||
cerr << USAGE << endl;
|
||||
exit (0);
|
||||
}
|
||||
if (Util::isInteger (leftArg) == false) {
|
||||
cerr << "error: `" << leftArg << "' " ;
|
||||
cerr << "is not a variable id" << endl ;
|
||||
exit (0);
|
||||
continue;
|
||||
}
|
||||
VarId vid = Util::stringToUnsigned (leftArg);
|
||||
VarNode* observedVar = fg.getVarNode (vid);
|
||||
if (observedVar == false) {
|
||||
cerr << "error: unknow variable with id " ;
|
||||
cerr << "`" << vid << "'" << endl;
|
||||
exit (0);
|
||||
}
|
||||
if (rightArg.empty()) {
|
||||
cerr << "error: missing right argument" << endl;
|
||||
cerr << USAGE << endl;
|
||||
exit (0);
|
||||
}
|
||||
if (Util::isInteger (rightArg) == false) {
|
||||
cerr << "error: `" << rightArg << "' " ;
|
||||
cerr << "is not a state index" << endl ;
|
||||
exit (0);
|
||||
}
|
||||
unsigned stateIdx = Util::stringToUnsigned (rightArg);
|
||||
if (observedVar->isValidState (stateIdx) == false) {
|
||||
cerr << "error: `" << stateIdx << "' " ;
|
||||
cerr << "is not a valid state index for variable with id " ;
|
||||
cerr << "`" << vid << "'" << endl;
|
||||
exit (0);
|
||||
}
|
||||
observedVar->setEvidence (stateIdx);
|
||||
}
|
||||
}
|
||||
return queryIds;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
runSolver (const FactorGraph& fg, const VarIds& queryIds)
|
||||
{
|
||||
Solver* solver = 0;
|
||||
switch (Globals::infAlgorithm) {
|
||||
case InfAlgorithms::VE:
|
||||
solver = new VarElimSolver (fg);
|
||||
break;
|
||||
case InfAlgorithms::BP:
|
||||
solver = new BpSolver (fg);
|
||||
break;
|
||||
case InfAlgorithms::CBP:
|
||||
solver = new CbpSolver (fg);
|
||||
break;
|
||||
default:
|
||||
assert (false);
|
||||
}
|
||||
if (Globals::verbosity > 0) {
|
||||
solver->printSolverFlags();
|
||||
cout << endl;
|
||||
}
|
||||
if (queryIds.size() == 0) {
|
||||
solver->printAllPosterioris();
|
||||
} else {
|
||||
solver->printAnswer (queryIds);
|
||||
}
|
||||
delete solver;
|
||||
}
|
||||
|
586
packages/CLPBN/horus/HorusYap.cpp
Normal file
586
packages/CLPBN/horus/HorusYap.cpp
Normal file
@ -0,0 +1,586 @@
|
||||
#include <cstdlib>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <YapInterface.h>
|
||||
|
||||
#include "ParfactorList.h"
|
||||
#include "FactorGraph.h"
|
||||
#include "FoveSolver.h"
|
||||
#include "VarElimSolver.h"
|
||||
#include "BpSolver.h"
|
||||
#include "CbpSolver.h"
|
||||
#include "ElimGraph.h"
|
||||
#include "BayesBall.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
typedef std::pair<ParfactorList*, ObservedFormulas*> LiftedNetwork;
|
||||
|
||||
|
||||
Params readParameters (YAP_Term);
|
||||
|
||||
vector<unsigned> readUnsignedList (YAP_Term);
|
||||
|
||||
void readLiftedEvidence (YAP_Term, ObservedFormulas&);
|
||||
|
||||
Parfactor* readParfactor (YAP_Term);
|
||||
|
||||
void runVeSolver (FactorGraph* fg, const vector<VarIds>& tasks,
|
||||
vector<Params>& results);
|
||||
|
||||
void runBpSolver (FactorGraph* fg, const vector<VarIds>& tasks,
|
||||
vector<Params>& results);
|
||||
|
||||
|
||||
|
||||
|
||||
vector<unsigned>
|
||||
readUnsignedList (YAP_Term list)
|
||||
{
|
||||
vector<unsigned> vec;
|
||||
while (list != YAP_TermNil()) {
|
||||
vec.push_back ((unsigned) YAP_IntOfTerm (YAP_HeadOfTerm (list)));
|
||||
list = YAP_TailOfTerm (list);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int createLiftedNetwork (void)
|
||||
{
|
||||
Parfactors parfactors;
|
||||
YAP_Term parfactorList = YAP_ARG1;
|
||||
while (parfactorList != YAP_TermNil()) {
|
||||
YAP_Term pfTerm = YAP_HeadOfTerm (parfactorList);
|
||||
parfactors.push_back (readParfactor (pfTerm));
|
||||
parfactorList = YAP_TailOfTerm (parfactorList);
|
||||
}
|
||||
|
||||
// LiftedUtils::printSymbolDictionary();
|
||||
if (Globals::verbosity > 2) {
|
||||
Util::printHeader ("INITIAL PARFACTORS");
|
||||
for (unsigned i = 0; i < parfactors.size(); i++) {
|
||||
parfactors[i]->print();
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
ParfactorList* pfList = new ParfactorList (parfactors);
|
||||
|
||||
if (Globals::verbosity > 2) {
|
||||
Util::printHeader ("SHATTERED PARFACTORS");
|
||||
pfList->print();
|
||||
}
|
||||
|
||||
// read evidence
|
||||
ObservedFormulas* obsFormulas = new ObservedFormulas();
|
||||
readLiftedEvidence (YAP_ARG2, *(obsFormulas));
|
||||
|
||||
LiftedNetwork* net = new LiftedNetwork (pfList, obsFormulas);
|
||||
YAP_Int p = (YAP_Int) (net);
|
||||
return YAP_Unify (YAP_MkIntTerm (p), YAP_ARG3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Parfactor* readParfactor (YAP_Term pfTerm)
|
||||
{
|
||||
// read dist id
|
||||
unsigned distId = YAP_IntOfTerm (YAP_ArgOfTerm (1, pfTerm));
|
||||
|
||||
// read the ranges
|
||||
Ranges ranges;
|
||||
YAP_Term rangeList = YAP_ArgOfTerm (3, pfTerm);
|
||||
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, pfTerm);
|
||||
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 = readParameters (YAP_ArgOfTerm (4, pfTerm));
|
||||
|
||||
// read the constraint
|
||||
Tuples tuples;
|
||||
if (lvMap.size() >= 1) {
|
||||
YAP_Term tupleList = YAP_ArgOfTerm (5, pfTerm);
|
||||
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: constraint has free variables" << endl;
|
||||
abort();
|
||||
}
|
||||
string name ((char*) YAP_AtomName (YAP_AtomOfTerm (ti)));
|
||||
tuple[i - 1] = LiftedUtils::getSymbol (name);
|
||||
}
|
||||
tuples.push_back (tuple);
|
||||
tupleList = YAP_TailOfTerm (tupleList);
|
||||
}
|
||||
}
|
||||
return new Parfactor (formulas, params, tuples, distId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void readLiftedEvidence (
|
||||
YAP_Term observedList,
|
||||
ObservedFormulas& obsFormulas)
|
||||
{
|
||||
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;
|
||||
cout << "has evidence()" << endl;
|
||||
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 (ObservedFormula (functor, evidence, args));
|
||||
}
|
||||
observedList = YAP_TailOfTerm (observedList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
createGroundNetwork (void)
|
||||
{
|
||||
string factorsType ((char*) YAP_AtomName (YAP_AtomOfTerm (YAP_ARG1)));
|
||||
bool fromBayesNet = factorsType == "bayes";
|
||||
FactorGraph* fg = new FactorGraph (fromBayesNet);
|
||||
YAP_Term factorList = YAP_ARG2;
|
||||
while (factorList != YAP_TermNil()) {
|
||||
YAP_Term factor = YAP_HeadOfTerm (factorList);
|
||||
// read the var ids
|
||||
VarIds varIds = readUnsignedList (YAP_ArgOfTerm (1, factor));
|
||||
// read the ranges
|
||||
Ranges ranges = readUnsignedList (YAP_ArgOfTerm (2, factor));
|
||||
// read the parameters
|
||||
Params params = readParameters (YAP_ArgOfTerm (3, factor));
|
||||
// read dist id
|
||||
unsigned distId = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (4, factor));
|
||||
fg->addFactor (Factor (varIds, ranges, params, distId));
|
||||
factorList = YAP_TailOfTerm (factorList);
|
||||
}
|
||||
|
||||
unsigned nrObservedVars = 0;
|
||||
YAP_Term evidenceList = YAP_ARG3;
|
||||
while (evidenceList != YAP_TermNil()) {
|
||||
YAP_Term evTerm = YAP_HeadOfTerm (evidenceList);
|
||||
unsigned vid = (unsigned) YAP_IntOfTerm ((YAP_ArgOfTerm (1, evTerm)));
|
||||
unsigned ev = (unsigned) YAP_IntOfTerm ((YAP_ArgOfTerm (2, evTerm)));
|
||||
assert (fg->getVarNode (vid));
|
||||
fg->getVarNode (vid)->setEvidence (ev);
|
||||
evidenceList = YAP_TailOfTerm (evidenceList);
|
||||
nrObservedVars ++;
|
||||
}
|
||||
if (Globals::verbosity > 0) {
|
||||
cout << "factor graph contains " ;
|
||||
cout << fg->nrVarNodes() << " variables " ;
|
||||
cout << "(" << nrObservedVars << " observed) and " ;
|
||||
cout << fg->nrFacNodes() << " factors " << endl;
|
||||
}
|
||||
YAP_Int p = (YAP_Int) (fg);
|
||||
return YAP_Unify (YAP_MkIntTerm (p), YAP_ARG4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
readParameters (YAP_Term paramL)
|
||||
{
|
||||
Params params;
|
||||
assert (YAP_IsPairTerm (paramL));
|
||||
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)
|
||||
{
|
||||
LiftedNetwork* network = (LiftedNetwork*) YAP_IntOfTerm (YAP_ARG1);
|
||||
YAP_Term taskList = YAP_ARG2;
|
||||
vector<Params> results;
|
||||
ParfactorList pfListCopy (*network->first);
|
||||
FoveSolver::absorveEvidence (pfListCopy, *network->second);
|
||||
while (taskList != YAP_TermNil()) {
|
||||
Grounds queryVars;
|
||||
YAP_Term jointList = YAP_HeadOfTerm (taskList);
|
||||
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 (pfListCopy);
|
||||
if (Globals::verbosity > 0 && taskList == YAP_ARG2) {
|
||||
solver.printSolverFlags();
|
||||
cout << endl;
|
||||
}
|
||||
if (queryVars.size() == 1) {
|
||||
results.push_back (solver.getPosterioriOf (queryVars[0]));
|
||||
} else {
|
||||
results.push_back (solver.getJointDistributionOf (queryVars));
|
||||
}
|
||||
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
|
||||
runGroundSolver (void)
|
||||
{
|
||||
FactorGraph* fg = (FactorGraph*) YAP_IntOfTerm (YAP_ARG1);
|
||||
vector<VarIds> tasks;
|
||||
YAP_Term taskList = YAP_ARG2;
|
||||
while (taskList != YAP_TermNil()) {
|
||||
tasks.push_back (readUnsignedList (YAP_HeadOfTerm (taskList)));
|
||||
taskList = YAP_TailOfTerm (taskList);
|
||||
}
|
||||
|
||||
vector<Params> results;
|
||||
if (Globals::infAlgorithm == InfAlgorithms::VE) {
|
||||
runVeSolver (fg, tasks, results);
|
||||
} else {
|
||||
runBpSolver (fg, tasks, results);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void runVeSolver (
|
||||
FactorGraph* fg,
|
||||
const vector<VarIds>& tasks,
|
||||
vector<Params>& results)
|
||||
{
|
||||
results.reserve (tasks.size());
|
||||
for (unsigned i = 0; i < tasks.size(); i++) {
|
||||
FactorGraph* mfg = fg;
|
||||
if (fg->isFromBayesNetwork()) {
|
||||
// mfg = BayesBall::getMinimalFactorGraph (*fg, tasks[i]);
|
||||
}
|
||||
// VarElimSolver solver (*mfg);
|
||||
VarElimSolver solver (*fg); //FIXME
|
||||
if (Globals::verbosity > 0 && i == 0) {
|
||||
solver.printSolverFlags();
|
||||
cout << endl;
|
||||
}
|
||||
results.push_back (solver.solveQuery (tasks[i]));
|
||||
if (fg->isFromBayesNetwork()) {
|
||||
// delete mfg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void runBpSolver (
|
||||
FactorGraph* fg,
|
||||
const vector<VarIds>& tasks,
|
||||
vector<Params>& results)
|
||||
{
|
||||
std::set<VarId> vids;
|
||||
for (unsigned i = 0; i < tasks.size(); i++) {
|
||||
Util::addToSet (vids, tasks[i]);
|
||||
}
|
||||
Solver* solver = 0;
|
||||
FactorGraph* mfg = fg;
|
||||
if (fg->isFromBayesNetwork()) {
|
||||
//mfg = BayesBall::getMinimalFactorGraph (
|
||||
// *fg, VarIds (vids.begin(),vids.end()));
|
||||
}
|
||||
if (Globals::infAlgorithm == InfAlgorithms::BP) {
|
||||
solver = new BpSolver (*fg); // FIXME
|
||||
} else if (Globals::infAlgorithm == InfAlgorithms::CBP) {
|
||||
CFactorGraph::checkForIdenticalFactors = false;
|
||||
solver = new CbpSolver (*fg); // FIXME
|
||||
} else {
|
||||
cerr << "error: unknow solver" << endl;
|
||||
abort();
|
||||
}
|
||||
if (Globals::verbosity > 0) {
|
||||
solver->printSolverFlags();
|
||||
cout << endl;
|
||||
}
|
||||
results.reserve (tasks.size());
|
||||
for (unsigned i = 0; i < tasks.size(); i++) {
|
||||
results.push_back (solver->solveQuery (tasks[i]));
|
||||
}
|
||||
if (fg->isFromBayesNetwork()) {
|
||||
//delete mfg;
|
||||
}
|
||||
delete solver;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
setParfactorsParams (void)
|
||||
{
|
||||
LiftedNetwork* network = (LiftedNetwork*) YAP_IntOfTerm (YAP_ARG1);
|
||||
ParfactorList* pfList = network->first;
|
||||
YAP_Term distList = YAP_ARG2;
|
||||
unordered_map<unsigned, Params> paramsMap;
|
||||
while (distList != YAP_TermNil()) {
|
||||
YAP_Term dist = YAP_HeadOfTerm (distList);
|
||||
unsigned distId = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (1, dist));
|
||||
assert (Util::contains (paramsMap, distId) == false);
|
||||
paramsMap[distId] = readParameters (YAP_ArgOfTerm (2, dist));
|
||||
distList = YAP_TailOfTerm (distList);
|
||||
}
|
||||
ParfactorList::iterator it = pfList->begin();
|
||||
while (it != pfList->end()) {
|
||||
assert (Util::contains (paramsMap, (*it)->distId()));
|
||||
// (*it)->setParams (paramsMap[(*it)->distId()]);
|
||||
++ it;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
setFactorsParams (void)
|
||||
{
|
||||
return TRUE; // TODO
|
||||
FactorGraph* fg = (FactorGraph*) YAP_IntOfTerm (YAP_ARG1);
|
||||
YAP_Term distList = YAP_ARG2;
|
||||
unordered_map<unsigned, Params> paramsMap;
|
||||
while (distList != YAP_TermNil()) {
|
||||
YAP_Term dist = YAP_HeadOfTerm (distList);
|
||||
unsigned distId = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (1, dist));
|
||||
assert (Util::contains (paramsMap, distId) == false);
|
||||
paramsMap[distId] = readParameters (YAP_ArgOfTerm (2, dist));
|
||||
distList = YAP_TailOfTerm (distList);
|
||||
}
|
||||
const FacNodes& facNodes = fg->facNodes();
|
||||
for (unsigned i = 0; i < facNodes.size(); i++) {
|
||||
unsigned distId = facNodes[i]->factor().distId();
|
||||
assert (Util::contains (paramsMap, distId));
|
||||
facNodes[i]->factor().setParams (paramsMap[distId]);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
setVarsInformation (void)
|
||||
{
|
||||
Var::clearVarsInfo();
|
||||
vector<string> labels;
|
||||
YAP_Term labelsL = YAP_ARG1;
|
||||
while (labelsL != YAP_TermNil()) {
|
||||
YAP_Atom atom = YAP_AtomOfTerm (YAP_HeadOfTerm (labelsL));
|
||||
labels.push_back ((char*) YAP_AtomName (atom));
|
||||
labelsL = YAP_TailOfTerm (labelsL);
|
||||
}
|
||||
unsigned count = 0;
|
||||
YAP_Term stateNamesL = YAP_ARG2;
|
||||
while (stateNamesL != YAP_TermNil()) {
|
||||
States states;
|
||||
YAP_Term namesL = YAP_HeadOfTerm (stateNamesL);
|
||||
while (namesL != YAP_TermNil()) {
|
||||
YAP_Atom atom = YAP_AtomOfTerm (YAP_HeadOfTerm (namesL));
|
||||
states.push_back ((char*) YAP_AtomName (atom));
|
||||
namesL = YAP_TailOfTerm (namesL);
|
||||
}
|
||||
Var::addVarInfo (count, labels[count], states);
|
||||
count ++;
|
||||
stateNamesL = YAP_TailOfTerm (stateNamesL);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
setHorusFlag (void)
|
||||
{
|
||||
string key ((char*) YAP_AtomName (YAP_AtomOfTerm (YAP_ARG1)));
|
||||
string value;
|
||||
if (key == "verbosity") {
|
||||
stringstream ss;
|
||||
ss << (int) YAP_IntOfTerm (YAP_ARG2);
|
||||
ss >> value;
|
||||
} else if (key == "accuracy") {
|
||||
stringstream ss;
|
||||
ss << (float) YAP_FloatOfTerm (YAP_ARG2);
|
||||
ss >> value;
|
||||
} else if (key == "max_iter") {
|
||||
stringstream ss;
|
||||
ss << (int) YAP_IntOfTerm (YAP_ARG2);
|
||||
ss >> value;
|
||||
} else {
|
||||
value = ((char*) YAP_AtomName (YAP_AtomOfTerm (YAP_ARG2)));
|
||||
}
|
||||
return Util::setHorusFlag (key, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
freeGroundNetwork (void)
|
||||
{
|
||||
delete (FactorGraph*) YAP_IntOfTerm (YAP_ARG1);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
freeParfactors (void)
|
||||
{
|
||||
LiftedNetwork* network = (LiftedNetwork*) YAP_IntOfTerm (YAP_ARG1);
|
||||
delete network->first;
|
||||
delete network->second;
|
||||
delete network;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C" void
|
||||
init_predicates (void)
|
||||
{
|
||||
YAP_UserCPredicate ("create_lifted_network", createLiftedNetwork, 3);
|
||||
YAP_UserCPredicate ("create_ground_network", createGroundNetwork, 4);
|
||||
YAP_UserCPredicate ("run_lifted_solver", runLiftedSolver, 3);
|
||||
YAP_UserCPredicate ("run_ground_solver", runGroundSolver, 3);
|
||||
YAP_UserCPredicate ("set_parfactors_params", setParfactorsParams, 2);
|
||||
YAP_UserCPredicate ("set_factors_params", setFactorsParams, 2);
|
||||
YAP_UserCPredicate ("set_vars_information", setVarsInformation, 2);
|
||||
YAP_UserCPredicate ("set_horus_flag", setHorusFlag, 2);
|
||||
YAP_UserCPredicate ("free_parfactors", freeParfactors, 1);
|
||||
YAP_UserCPredicate ("free_ground_network", freeGroundNetwork, 1);
|
||||
}
|
||||
|
296
packages/CLPBN/horus/Indexer.h
Normal file
296
packages/CLPBN/horus/Indexer.h
Normal file
@ -0,0 +1,296 @@
|
||||
#ifndef HORUS_STATESINDEXER_H
|
||||
#define HORUS_STATESINDEXER_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <functional>
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "Var.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 Vars& 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]->range());
|
||||
size_ *= vars[i]->range();
|
||||
}
|
||||
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 &os, const StatesIndexer& idx)
|
||||
{
|
||||
os << "(" << std::setw (2) << std::setfill('0') << idx.li_ << ") " ;
|
||||
os << idx.indices_;
|
||||
return os;
|
||||
}
|
||||
|
||||
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 &os, const MapIndexer& idx)
|
||||
{
|
||||
os << "(" << std::setw (2) << std::setfill('0') << idx.index_ << ") " ;
|
||||
os << idx.indices_;
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned index_;
|
||||
bool valid_;
|
||||
vector<unsigned> ranges_;
|
||||
vector<unsigned> indices_;
|
||||
vector<unsigned> offsets_;
|
||||
};
|
||||
|
||||
|
||||
#endif // HORUS_STATESINDEXER_H
|
||||
|
131
packages/CLPBN/horus/LiftedUtils.cpp
Normal file
131
packages/CLPBN/horus/LiftedUtils.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LogVars
|
||||
Substitution::getDiscardedLogVars (void) const
|
||||
{
|
||||
LogVars discardedLvs;
|
||||
set<LogVar> doneLvs;
|
||||
unordered_map<LogVar, LogVar>::const_iterator it;
|
||||
it = subs_.begin();
|
||||
while (it != subs_.end()) {
|
||||
if (Util::contains (doneLvs, it->second)) {
|
||||
discardedLvs.push_back (it->first);
|
||||
} else {
|
||||
doneLvs.insert (it->second);
|
||||
}
|
||||
it ++;
|
||||
}
|
||||
return discardedLvs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ostream& operator<< (ostream &os, const Substitution& theta)
|
||||
{
|
||||
unordered_map<LogVar, LogVar>::const_iterator it;
|
||||
os << "[" ;
|
||||
it = theta.subs_.begin();
|
||||
while (it != theta.subs_.end()) {
|
||||
if (it != theta.subs_.begin()) os << ", " ;
|
||||
os << it->first << "->" << it->second ;
|
||||
++ it;
|
||||
}
|
||||
os << "]" ;
|
||||
return os;
|
||||
}
|
||||
|
166
packages/CLPBN/horus/LiftedUtils.h
Normal file
166
packages/CLPBN/horus/LiftedUtils.h
Normal file
@ -0,0 +1,166 @@
|
||||
#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_(Util::maxUnsigned()) { }
|
||||
|
||||
Symbol (unsigned id) : id_(id) { }
|
||||
|
||||
operator unsigned (void) const { return id_; }
|
||||
|
||||
bool valid (void) const { return id_ != Util::maxUnsigned(); }
|
||||
|
||||
static Symbol invalid (void) { return Symbol(); }
|
||||
|
||||
friend ostream& operator<< (ostream &os, const Symbol& s);
|
||||
|
||||
private:
|
||||
unsigned id_;
|
||||
};
|
||||
|
||||
|
||||
class LogVar
|
||||
{
|
||||
public:
|
||||
LogVar (void) : id_(Util::maxUnsigned()) { }
|
||||
|
||||
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_ != Util::maxUnsigned();
|
||||
}
|
||||
|
||||
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 Substitution
|
||||
{
|
||||
public:
|
||||
void add (LogVar X_old, LogVar X_new)
|
||||
{
|
||||
assert (Util::contains (subs_, X_old) == false);
|
||||
subs_.insert (make_pair (X_old, X_new));
|
||||
}
|
||||
|
||||
void rename (LogVar X_old, LogVar X_new)
|
||||
{
|
||||
assert (Util::contains (subs_, X_old));
|
||||
subs_.find (X_old)->second = X_new;
|
||||
}
|
||||
|
||||
LogVar newNameFor (LogVar X) const
|
||||
{
|
||||
unordered_map<LogVar, LogVar>::const_iterator it;
|
||||
it = subs_.find (X);
|
||||
if (it != subs_.end()) {
|
||||
return subs_.find (X)->second;
|
||||
}
|
||||
return X;
|
||||
}
|
||||
|
||||
bool containsReplacementFor (LogVar X) const
|
||||
{
|
||||
return Util::contains (subs_, X);
|
||||
}
|
||||
|
||||
unsigned nrReplacements (void) const { return subs_.size(); }
|
||||
|
||||
LogVars getDiscardedLogVars (void) const;
|
||||
|
||||
friend ostream& operator<< (ostream &os, const Substitution& theta);
|
||||
|
||||
private:
|
||||
unordered_map<LogVar, LogVar> subs_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // HORUS_LIFTEDUTILS_H
|
||||
|
177
packages/CLPBN/horus/Makefile.in
Normal file
177
packages/CLPBN/horus/Makefile.in
Normal file
@ -0,0 +1,177 @@
|
||||
#
|
||||
# default base directory for YAP installation
|
||||
# (EROOT for architecture-dependent files)
|
||||
#
|
||||
GCC = @GCC@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
ROOTDIR = $(prefix)
|
||||
EROOTDIR = @exec_prefix@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
#
|
||||
# where the binary should be
|
||||
#
|
||||
BINDIR = $(EROOTDIR)/bin
|
||||
#
|
||||
# where YAP should look for libraries
|
||||
#
|
||||
LIBDIR=@libdir@
|
||||
YAPLIBDIR=@libdir@/Yap
|
||||
#
|
||||
#
|
||||
CC=@CC@
|
||||
CXX=@CXX@
|
||||
|
||||
# normal
|
||||
#CXXFLAGS= -std=c++0x @SHLIB_CXXFLAGS@ $(YAP_EXTRAS) $(DEFS) -D_YAP_NOT_INSTALLED_=1 -I$(srcdir) -I../../../.. -I$(srcdir)/../../../../include @CPPFLAGS@ -DNDEBUG
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
# You shouldn't need to change what follows.
|
||||
#
|
||||
INSTALL=@INSTALL@
|
||||
INSTALL_DATA=@INSTALL_DATA@
|
||||
INSTALL_PROGRAM=@INSTALL_PROGRAM@
|
||||
SHELL=/bin/sh
|
||||
RANLIB=@RANLIB@
|
||||
srcdir=@srcdir@
|
||||
SO=@SO@
|
||||
#4.1VPATH=@srcdir@:@srcdir@/OPTYap
|
||||
CWD=$(PWD)
|
||||
|
||||
|
||||
HEADERS = \
|
||||
$(srcdir)/BayesNet.h \
|
||||
$(srcdir)/BayesBall.h \
|
||||
$(srcdir)/ElimGraph.h \
|
||||
$(srcdir)/FactorGraph.h \
|
||||
$(srcdir)/Factor.h \
|
||||
$(srcdir)/CFactorGraph.h \
|
||||
$(srcdir)/ConstraintTree.h \
|
||||
$(srcdir)/Solver.h \
|
||||
$(srcdir)/VarElimSolver.h \
|
||||
$(srcdir)/BpSolver.h \
|
||||
$(srcdir)/CbpSolver.h \
|
||||
$(srcdir)/FoveSolver.h \
|
||||
$(srcdir)/Var.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
|
||||
|
||||
CPP_SOURCES = \
|
||||
$(srcdir)/BayesNet.cpp \
|
||||
$(srcdir)/BayesBall.cpp \
|
||||
$(srcdir)/ElimGraph.cpp \
|
||||
$(srcdir)/FactorGraph.cpp \
|
||||
$(srcdir)/Factor.cpp \
|
||||
$(srcdir)/CFactorGraph.cpp \
|
||||
$(srcdir)/ConstraintTree.cpp \
|
||||
$(srcdir)/Var.cpp \
|
||||
$(srcdir)/Solver.cpp \
|
||||
$(srcdir)/VarElimSolver.cpp \
|
||||
$(srcdir)/BpSolver.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)/HorusYap.cpp \
|
||||
$(srcdir)/HorusCli.cpp
|
||||
|
||||
OBJS = \
|
||||
BayesNet.o \
|
||||
BayesBall.o \
|
||||
ElimGraph.o \
|
||||
FactorGraph.o \
|
||||
Factor.o \
|
||||
CFactorGraph.o \
|
||||
ConstraintTree.o \
|
||||
Var.o \
|
||||
Solver.o \
|
||||
VarElimSolver.o \
|
||||
BpSolver.o \
|
||||
CbpSolver.o \
|
||||
FoveSolver.o \
|
||||
Parfactor.o \
|
||||
ProbFormula.o \
|
||||
Histogram.o \
|
||||
ParfactorList.o \
|
||||
LiftedUtils.o \
|
||||
Util.o \
|
||||
HorusYap.o
|
||||
|
||||
HCLI_OBJS = \
|
||||
BayesNet.o \
|
||||
BayesBall.o \
|
||||
ElimGraph.o \
|
||||
FactorGraph.o \
|
||||
Factor.o \
|
||||
CFactorGraph.o \
|
||||
ConstraintTree.o \
|
||||
Var.o \
|
||||
Solver.o \
|
||||
VarElimSolver.o \
|
||||
BpSolver.o \
|
||||
CbpSolver.o \
|
||||
FoveSolver.o \
|
||||
Parfactor.o \
|
||||
ProbFormula.o \
|
||||
Histogram.o \
|
||||
ParfactorList.o \
|
||||
LiftedUtils.o \
|
||||
Util.o \
|
||||
HorusCli.o
|
||||
|
||||
SOBJS=horus.@SO@
|
||||
|
||||
|
||||
all: $(SOBJS) hcli
|
||||
|
||||
# default rule
|
||||
%.o : $(srcdir)/%.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
|
||||
@DO_SECOND_LD@horus.@SO@: $(OBJS)
|
||||
@DO_SECOND_LD@ @SHLIB_CXX_LD@ -o horus.@SO@ $(OBJS) @EXTRA_LIBS_FOR_SWIDLLS@
|
||||
|
||||
|
||||
hcli: $(HCLI_OBJS)
|
||||
$(CXX) -o hcli $(HCLI_OBJS)
|
||||
|
||||
|
||||
install: all
|
||||
$(INSTALL_PROGRAM) $(SOBJS) $(DESTDIR) $(YAPLIBDIR)
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ $(OBJS) $(SOBJS) *.BAK hcli
|
||||
|
||||
|
||||
erase_dots:
|
||||
rm -f *.dot *.png
|
||||
|
||||
|
||||
depend: $(HEADERS) $(CPP_SOURCES)
|
||||
-@if test "$(GCC)" = yes; then\
|
||||
$(CC) -std=c++0x -MM -MG $(CFLAGS) -I$(srcdir) -I$(srcdir)/../../../../include -I$(srcdir)/../../../../H $(CPP_SOURCES) >> Makefile;\
|
||||
else\
|
||||
makedepend -f - -- $(CFLAGS) -I$(srcdir)/../../../../H -I$(srcdir)/../../../../include -- $(CPP_SOURCES) |\
|
||||
sed 's|.*/\([^:]*\):|\1:|' >> Makefile ;\
|
||||
fi
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
911
packages/CLPBN/horus/Parfactor.cpp
Normal file
911
packages/CLPBN/horus/Parfactor.cpp
Normal file
@ -0,0 +1,911 @@
|
||||
|
||||
#include "Parfactor.h"
|
||||
#include "Histogram.h"
|
||||
#include "Indexer.h"
|
||||
#include "Util.h"
|
||||
#include "Horus.h"
|
||||
|
||||
|
||||
Parfactor::Parfactor (
|
||||
const ProbFormulas& formulas,
|
||||
const Params& params,
|
||||
const Tuples& tuples,
|
||||
unsigned distId)
|
||||
{
|
||||
args_ = formulas;
|
||||
params_ = params;
|
||||
distId_ = distId;
|
||||
|
||||
LogVars logVars;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
ranges_.push_back (args_[i].range());
|
||||
const LogVars& lvs = args_[i].logVars();
|
||||
for (unsigned j = 0; j < lvs.size(); j++) {
|
||||
if (Util::contains (logVars, lvs[j]) == false) {
|
||||
logVars.push_back (lvs[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
constr_ = new ConstraintTree (logVars, tuples);
|
||||
assert (params_.size() == Util::expectedSize (ranges_));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Parfactor::Parfactor (const Parfactor* g, const Tuple& tuple)
|
||||
{
|
||||
args_ = g->arguments();
|
||||
params_ = g->params();
|
||||
ranges_ = g->ranges();
|
||||
distId_ = g->distId();
|
||||
constr_ = new ConstraintTree (g->logVars(), {tuple});
|
||||
assert (params_.size() == Util::expectedSize (ranges_));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Parfactor::Parfactor (const Parfactor* g, ConstraintTree* constr)
|
||||
{
|
||||
args_ = g->arguments();
|
||||
params_ = g->params();
|
||||
ranges_ = g->ranges();
|
||||
distId_ = g->distId();
|
||||
constr_ = constr;
|
||||
assert (params_.size() == Util::expectedSize (ranges_));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Parfactor::Parfactor (const Parfactor& g)
|
||||
{
|
||||
args_ = g.arguments();
|
||||
params_ = g.params();
|
||||
ranges_ = g.ranges();
|
||||
distId_ = g.distId();
|
||||
constr_ = new ConstraintTree (*g.constr());
|
||||
assert (params_.size() == Util::expectedSize (ranges_));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Parfactor::~Parfactor (void)
|
||||
{
|
||||
delete constr_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LogVarSet
|
||||
Parfactor::countedLogVars (void) const
|
||||
{
|
||||
LogVarSet set;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (args_[i].isCounting()) {
|
||||
set.insert (args_[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 < args_.size());
|
||||
LogVarSet remaining;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (i != fIdx) {
|
||||
remaining |= args_[i].logVarSet();
|
||||
}
|
||||
}
|
||||
return args_[fIdx].logVarSet() - remaining;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::setConstraintTree (ConstraintTree* newTree)
|
||||
{
|
||||
delete constr_;
|
||||
constr_ = newTree;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::sumOut (unsigned fIdx)
|
||||
{
|
||||
assert (fIdx < args_.size());
|
||||
assert (args_[fIdx].contains (elimLogVars()));
|
||||
|
||||
if (args_[fIdx].isCounting()) {
|
||||
unsigned N = constr_->getConditionalCount (
|
||||
args_[fIdx].countedLogVar());
|
||||
unsigned R = args_[fIdx].range();
|
||||
vector<double> numAssigns = HistogramSet::getNumAssigns (N, R);
|
||||
StatesIndexer sindexer (ranges_, fIdx);
|
||||
while (sindexer.valid()) {
|
||||
unsigned h = sindexer[fIdx];
|
||||
if (Globals::logDomain) {
|
||||
params_[sindexer] += numAssigns[h];
|
||||
} else {
|
||||
params_[sindexer] *= numAssigns[h];
|
||||
}
|
||||
++ sindexer;
|
||||
}
|
||||
}
|
||||
|
||||
Params copy = params_;
|
||||
params_.clear();
|
||||
params_.resize (copy.size() / ranges_[fIdx], LogAware::addIdenty());
|
||||
MapIndexer indexer (ranges_, fIdx);
|
||||
if (Globals::logDomain) {
|
||||
for (unsigned i = 0; i < copy.size(); i++) {
|
||||
params_[indexer] = Util::logSum (params_[indexer], copy[i]);
|
||||
++ indexer;
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < copy.size(); i++) {
|
||||
params_[indexer] += copy[i];
|
||||
++ indexer;
|
||||
}
|
||||
}
|
||||
|
||||
LogVarSet excl = exclusiveLogVars (fIdx);
|
||||
if (args_[fIdx].isCounting()) {
|
||||
// counting log vars were already raised on counting conversion
|
||||
LogAware::pow (params_, constr_->getConditionalCount (
|
||||
excl - args_[fIdx].countedLogVar()));
|
||||
} else {
|
||||
LogAware::pow (params_, constr_->getConditionalCount (excl));
|
||||
}
|
||||
constr_->remove (excl);
|
||||
|
||||
args_.erase (args_.begin() + fIdx);
|
||||
ranges_.erase (ranges_.begin() + fIdx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::multiply (Parfactor& g)
|
||||
{
|
||||
alignAndExponentiate (this, &g);
|
||||
TFactor<ProbFormula>::multiply (g);
|
||||
constr_->join (g.constr(), true);
|
||||
simplifyGrounds();
|
||||
assert (constr_->isCartesianProduct (countedLogVars()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
Parfactor::canCountConvert (LogVar X)
|
||||
{
|
||||
if (nrFormulas (X) != 1) {
|
||||
return false;
|
||||
}
|
||||
int fIdx = indexOfLogVar (X);
|
||||
if (args_[fIdx].isCounting()) {
|
||||
return false;
|
||||
}
|
||||
if (constr_->isCountNormalized (X) == false) {
|
||||
return false;
|
||||
}
|
||||
if (constr_->getConditionalCount (X) == 1) {
|
||||
return false;
|
||||
}
|
||||
if (constr_->isCartesianProduct (countedLogVars() | X) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::countConvert (LogVar X)
|
||||
{
|
||||
int fIdx = indexOfLogVar (X);
|
||||
assert (constr_->isCountNormalized (X));
|
||||
assert (constr_->getConditionalCount (X) > 1);
|
||||
assert (canCountConvert (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> sumout (params_.size() / R);
|
||||
unsigned count = 0;
|
||||
while (indexer.valid()) {
|
||||
sumout[count].reserve (R);
|
||||
for (unsigned r = 0; r < R; r++) {
|
||||
sumout[count].push_back (params_[indexer]);
|
||||
indexer.increment (fIdx);
|
||||
}
|
||||
count ++;
|
||||
indexer.reset (fIdx);
|
||||
indexer.incrementExcluding (fIdx);
|
||||
}
|
||||
|
||||
params_.clear();
|
||||
params_.reserve (sumout.size() * H);
|
||||
|
||||
ranges_[fIdx] = H;
|
||||
MapIndexer mapIndexer (ranges_, fIdx);
|
||||
while (mapIndexer.valid()) {
|
||||
double prod = LogAware::multIdenty();
|
||||
unsigned i = mapIndexer.mappedIndex();
|
||||
unsigned h = mapIndexer[fIdx];
|
||||
for (unsigned r = 0; r < R; r++) {
|
||||
if (Globals::logDomain) {
|
||||
prod += LogAware::pow (sumout[i][r], histograms[h][r]);
|
||||
} else {
|
||||
prod *= LogAware::pow (sumout[i][r], histograms[h][r]);
|
||||
}
|
||||
}
|
||||
params_.push_back (prod);
|
||||
++ mapIndexer;
|
||||
}
|
||||
args_[fIdx].setCountedLogVar (X);
|
||||
simplifyCountingFormulas (fIdx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::expand (LogVar X, LogVar X_new1, LogVar X_new2)
|
||||
{
|
||||
int fIdx = indexOfLogVar (X);
|
||||
assert (fIdx != -1);
|
||||
assert (args_[fIdx].isCounting());
|
||||
|
||||
unsigned N1 = constr_->getConditionalCount (X_new1);
|
||||
unsigned N2 = constr_->getConditionalCount (X_new2);
|
||||
unsigned N = N1 + N2;
|
||||
unsigned R = args_[fIdx].range();
|
||||
unsigned H1 = HistogramSet::nrHistograms (N1, R);
|
||||
unsigned H2 = HistogramSet::nrHistograms (N2, R);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
expandPotential (fIdx, H1 * H2, sumIndexes);
|
||||
|
||||
args_.insert (args_.begin() + fIdx + 1, args_[fIdx]);
|
||||
args_[fIdx].rename (X, X_new1);
|
||||
args_[fIdx + 1].rename (X, X_new2);
|
||||
if (H1 == 2) {
|
||||
args_[fIdx].clearCountedLogVar();
|
||||
}
|
||||
if (H2 == 2) {
|
||||
args_[fIdx + 1].clearCountedLogVar();
|
||||
}
|
||||
ranges_.insert (ranges_.begin() + fIdx + 1, H2);
|
||||
ranges_[fIdx] = H1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::fullExpand (LogVar X)
|
||||
{
|
||||
int fIdx = indexOfLogVar (X);
|
||||
assert (fIdx != -1);
|
||||
assert (args_[fIdx].isCounting());
|
||||
|
||||
unsigned N = constr_->getConditionalCount (X);
|
||||
unsigned R = args_[fIdx].range();
|
||||
vector<Histogram> originHists = HistogramSet::getHistograms (N, R);
|
||||
vector<Histogram> expandHists = HistogramSet::getHistograms (1, R);
|
||||
assert (ranges_[fIdx] == originHists.size());
|
||||
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;
|
||||
}
|
||||
|
||||
expandPotential (fIdx, std::pow (R, N), sumIndexes);
|
||||
|
||||
ProbFormula f = args_[fIdx];
|
||||
args_.erase (args_.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]);
|
||||
args_.insert (args_.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 < args_.size(); j++) {
|
||||
if (grounds[i].functor() == args_[j].functor() &&
|
||||
grounds[i].arity() == args_[j].arity()) {
|
||||
constr_->moveToTop (args_[j].logVars());
|
||||
if (constr_->containsTuple (grounds[i].args())) {
|
||||
newFormulas.push_back (args_[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert (newFormulas.size() == i + 1);
|
||||
}
|
||||
reorderArguments (newFormulas);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::absorveEvidence (const ProbFormula& formula, unsigned evidence)
|
||||
{
|
||||
int fIdx = indexOf (formula);
|
||||
assert (fIdx != -1);
|
||||
LogVarSet excl = exclusiveLogVars (fIdx);
|
||||
assert (args_[fIdx].isCounting() == false);
|
||||
assert (constr_->isCountNormalized (excl));
|
||||
LogAware::pow (params_, constr_->getConditionalCount (excl));
|
||||
TFactor<ProbFormula>::absorveEvidence (formula, evidence);
|
||||
constr_->remove (excl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::setNewGroups (void)
|
||||
{
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
args_[i].setGroup (ProbFormula::getNewGroup());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::applySubstitution (const Substitution& theta)
|
||||
{
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
LogVars& lvs = args_[i].logVars();
|
||||
for (unsigned j = 0; j < lvs.size(); j++) {
|
||||
lvs[j] = theta.newNameFor (lvs[j]);
|
||||
}
|
||||
if (args_[i].isCounting()) {
|
||||
LogVar clv = args_[i].countedLogVar();
|
||||
args_[i].setCountedLogVar (theta.newNameFor (clv));
|
||||
}
|
||||
}
|
||||
constr_->applySubstitution (theta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
Parfactor::findGroup (const Ground& ground) const
|
||||
{
|
||||
int group = -1;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (args_[i].functor() == ground.functor() &&
|
||||
args_[i].arity() == ground.arity()) {
|
||||
constr_->moveToTop (args_[i].logVars());
|
||||
if (constr_->containsTuple (ground.args())) {
|
||||
group = args_[i].group();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
Parfactor::containsGround (const Ground& ground) const
|
||||
{
|
||||
return findGroup (ground) != -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
Parfactor::containsGroup (unsigned group) const
|
||||
{
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (args_[i].group() == group) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
Parfactor::nrFormulas (LogVar X) const
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (args_[i].contains (X)) {
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
Parfactor::indexOfLogVar (LogVar X) const
|
||||
{
|
||||
int idx = -1;
|
||||
assert (nrFormulas (X) == 1);
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (args_[i].contains (X)) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
Parfactor::indexOfGroup (unsigned group) const
|
||||
{
|
||||
int pos = -1;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (args_[i].group() == group) {
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
Parfactor::nrFormulasWithGroup (unsigned group) const
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (args_[i].group() == group) {
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
vector<unsigned>
|
||||
Parfactor::getAllGroups (void) const
|
||||
{
|
||||
vector<unsigned> groups (args_.size());
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
groups[i] = args_[i].group();
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
|
||||
|
||||
string
|
||||
Parfactor::getLabel (void) const
|
||||
{
|
||||
stringstream ss;
|
||||
ss << "phi(" ;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (i != 0) ss << "," ;
|
||||
ss << args_[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 < args_.size(); i++) {
|
||||
if (i != 0) cout << ", " ;
|
||||
cout << args_[i];
|
||||
}
|
||||
cout << endl;
|
||||
if (args_[0].group() != Util::maxUnsigned()) {
|
||||
vector<string> groups;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
groups.push_back (string ("g") + Util::toString (args_[i].group()));
|
||||
}
|
||||
cout << "Groups: " << groups << endl;
|
||||
}
|
||||
cout << "LogVars: " << constr_->logVarSet() << endl;
|
||||
cout << "Ranges: " << ranges_ << endl;
|
||||
if (printParams == false) {
|
||||
cout << "Params: " ;
|
||||
if (params_.size() <= 32) {
|
||||
cout.precision(10);
|
||||
cout << params_ << endl;
|
||||
} else {
|
||||
cout << "|" << params_.size() << "|" << endl;
|
||||
}
|
||||
}
|
||||
ConstraintTree copy (*constr_);
|
||||
copy.moveToTop (copy.logVarSet().elements());
|
||||
cout << "Tuples: " << copy.tupleSet() << endl;
|
||||
if (printParams) {
|
||||
printParameters();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::printParameters (void) const
|
||||
{
|
||||
vector<string> jointStrings;
|
||||
StatesIndexer indexer (ranges_);
|
||||
while (indexer.valid()) {
|
||||
stringstream ss;
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if (i != 0) ss << ", " ;
|
||||
if (args_[i].isCounting()) {
|
||||
unsigned N = constr_->getConditionalCount (
|
||||
args_[i].countedLogVar());
|
||||
HistogramSet hs (N, args_[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::printProjections (void) const
|
||||
{
|
||||
ConstraintTree copy (*constr_);
|
||||
|
||||
LogVarSet Xs = copy.logVarSet();
|
||||
for (unsigned i = 0; i < Xs.size(); i++) {
|
||||
cout << "-> projection of " << Xs[i] << ": " ;
|
||||
cout << copy.tupleSet ({Xs[i]}) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::expandPotential (
|
||||
int fIdx,
|
||||
unsigned newRange,
|
||||
const vector<unsigned>& sumIndexes)
|
||||
{
|
||||
ullong newSize = (params_.size() / ranges_[fIdx]) * newRange;
|
||||
if (newSize > params_.max_size()) {
|
||||
cerr << "error: an overflow occurred when performing expansion" ;
|
||||
cerr << endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
Params copy = params_;
|
||||
params_.clear();
|
||||
params_.reserve (newSize);
|
||||
|
||||
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] = newRange;
|
||||
vector<unsigned> indices (ranges_.size(), 0);
|
||||
for (unsigned k = 0; k < newSize; k++) {
|
||||
if (index >= copy.size()) {
|
||||
abort();
|
||||
}
|
||||
assert (index < copy.size());
|
||||
params_.push_back (copy[index]);
|
||||
for (int i = ranges_.size() - 1; i >= 0; i--) {
|
||||
indices[i] ++;
|
||||
if (i == fIdx) {
|
||||
if (indices[i] != ranges_[i]) {
|
||||
int diff = sumIndexes[indices[i]] - sumIndexes[indices[i] - 1];
|
||||
index += diff * offsets_[i];
|
||||
break;
|
||||
} else {
|
||||
// last index contains the old range minus 1
|
||||
index -= sumIndexes.back() * offsets_[i];
|
||||
indices[i] = 0;
|
||||
}
|
||||
} else {
|
||||
if (indices[i] != ranges_[i]) {
|
||||
index += offsets_[i];
|
||||
break;
|
||||
} else {
|
||||
index -= (ranges_[i] - 1) * offsets_[i];
|
||||
indices[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::simplifyCountingFormulas (int fIdx)
|
||||
{
|
||||
// check if we can simplify the parfactor
|
||||
for (unsigned i = 0; i < args_.size(); i++) {
|
||||
if ((int)i != fIdx &&
|
||||
args_[i].isCounting() &&
|
||||
args_[i].group() == args_[fIdx].group()) {
|
||||
// if they only differ in the name of the counting log var
|
||||
if ((args_[i].logVarSet() - args_[i].countedLogVar()) ==
|
||||
(args_[fIdx].logVarSet()) - args_[fIdx].countedLogVar() &&
|
||||
ranges_[i] == ranges_[fIdx]) {
|
||||
simplifyParfactor (fIdx, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::simplifyGrounds (void)
|
||||
{
|
||||
LogVarSet singletons = constr_->singletons();
|
||||
for (int i = 0; i < (int)args_.size() - 1; i++) {
|
||||
for (unsigned j = i + 1; j < args_.size(); j++) {
|
||||
if (args_[i].group() == args_[j].group() &&
|
||||
singletons.contains (args_[i].logVarSet()) &&
|
||||
singletons.contains (args_[j].logVarSet())) {
|
||||
simplifyParfactor (i, j);
|
||||
i --;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
Parfactor::canMultiply (Parfactor* g1, Parfactor* g2)
|
||||
{
|
||||
std::pair<LogVars, LogVars> res = getAlignLogVars (g1, g2);
|
||||
LogVarSet Xs_1 (res.first);
|
||||
LogVarSet Xs_2 (res.second);
|
||||
LogVarSet Y_1 = g1->logVarSet() - Xs_1;
|
||||
LogVarSet Y_2 = g2->logVarSet() - Xs_2;
|
||||
Y_1 -= g1->countedLogVars();
|
||||
Y_2 -= g2->countedLogVars();
|
||||
return g1->constr()->isCountNormalized (Y_1) &&
|
||||
g2->constr()->isCountNormalized (Y_2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::simplifyParfactor (unsigned fIdx1, unsigned fIdx2)
|
||||
{
|
||||
Params copy = params_;
|
||||
params_.clear();
|
||||
StatesIndexer indexer (ranges_);
|
||||
while (indexer.valid()) {
|
||||
if (indexer[fIdx1] == indexer[fIdx2]) {
|
||||
params_.push_back (copy[indexer]);
|
||||
}
|
||||
++ indexer;
|
||||
}
|
||||
for (unsigned i = 0; i < args_[fIdx2].logVars().size(); i++) {
|
||||
if (nrFormulas (args_[fIdx2].logVars()[i]) == 1) {
|
||||
constr_->remove ({ args_[fIdx2].logVars()[i] });
|
||||
}
|
||||
}
|
||||
args_.erase (args_.begin() + fIdx2);
|
||||
ranges_.erase (ranges_.begin() + fIdx2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::pair<LogVars, LogVars>
|
||||
Parfactor::getAlignLogVars (Parfactor* g1, Parfactor* g2)
|
||||
{
|
||||
g1->simplifyGrounds();
|
||||
g2->simplifyGrounds();
|
||||
LogVars Xs_1, Xs_2;
|
||||
TinySet<unsigned> matchedI;
|
||||
TinySet<unsigned> matchedJ;
|
||||
ProbFormulas& formulas1 = g1->arguments();
|
||||
ProbFormulas& formulas2 = g2->arguments();
|
||||
for (unsigned i = 0; i < formulas1.size(); i++) {
|
||||
for (unsigned j = 0; j < formulas2.size(); j++) {
|
||||
if (formulas1[i].group() == formulas2[j].group() &&
|
||||
g1->range (i) == g2->range (j) &&
|
||||
matchedI.contains (i) == false &&
|
||||
matchedJ.contains (j) == false) {
|
||||
Util::addToVector (Xs_1, formulas1[i].logVars());
|
||||
Util::addToVector (Xs_2, formulas2[j].logVars());
|
||||
matchedI.insert (i);
|
||||
matchedJ.insert (j);
|
||||
}
|
||||
}
|
||||
}
|
||||
return make_pair (Xs_1, Xs_2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::alignAndExponentiate (Parfactor* g1, Parfactor* g2)
|
||||
{
|
||||
alignLogicalVars (g1, g2);
|
||||
LogVarSet comm = g1->logVarSet() & g2->logVarSet();
|
||||
LogVarSet Y_1 = g1->logVarSet() - comm;
|
||||
LogVarSet Y_2 = g2->logVarSet() - comm;
|
||||
Y_1 -= g1->countedLogVars();
|
||||
Y_2 -= g2->countedLogVars();
|
||||
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);
|
||||
LogAware::pow (g1->params(), 1.0 / condCount2);
|
||||
LogAware::pow (g2->params(), 1.0 / condCount1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Parfactor::alignLogicalVars (Parfactor* g1, Parfactor* g2)
|
||||
{
|
||||
std::pair<LogVars, LogVars> res = getAlignLogVars (g1, g2);
|
||||
const LogVars& alignLvs1 = res.first;
|
||||
const LogVars& alignLvs2 = res.second;
|
||||
// cout << "ALIGNING :::::::::::::::::" << endl;
|
||||
// g1->print();
|
||||
// cout << "AND" << endl;
|
||||
// g2->print();
|
||||
// cout << "-> align lvs1 = " << alignLvs1 << endl;
|
||||
// cout << "-> align lvs2 = " << alignLvs2 << endl;
|
||||
LogVar freeLogVar (0);
|
||||
Substitution theta1, theta2;
|
||||
for (unsigned i = 0; i < alignLvs1.size(); i++) {
|
||||
bool b1 = theta1.containsReplacementFor (alignLvs1[i]);
|
||||
bool b2 = theta2.containsReplacementFor (alignLvs2[i]);
|
||||
if (b1 == false && b2 == false) {
|
||||
theta1.add (alignLvs1[i], freeLogVar);
|
||||
theta2.add (alignLvs2[i], freeLogVar);
|
||||
++ freeLogVar;
|
||||
} else if (b1 == false && b2) {
|
||||
theta1.add (alignLvs1[i], theta2.newNameFor (alignLvs2[i]));
|
||||
} else if (b1 && b2 == false) {
|
||||
theta2.add (alignLvs2[i], theta1.newNameFor (alignLvs1[i]));
|
||||
}
|
||||
}
|
||||
|
||||
const LogVarSet& allLvs1 = g1->logVarSet();
|
||||
for (unsigned i = 0; i < allLvs1.size(); i++) {
|
||||
if (theta1.containsReplacementFor (allLvs1[i]) == false) {
|
||||
theta1.add (allLvs1[i], freeLogVar);
|
||||
++ freeLogVar;
|
||||
}
|
||||
}
|
||||
const LogVarSet& allLvs2 = g2->logVarSet();
|
||||
for (unsigned i = 0; i < allLvs2.size(); i++) {
|
||||
if (theta2.containsReplacementFor (allLvs2[i]) == false) {
|
||||
theta2.add (allLvs2[i], freeLogVar);
|
||||
++ freeLogVar;
|
||||
}
|
||||
}
|
||||
|
||||
// handle this type of situation:
|
||||
// g1 = p(X), q(X) ; X in {(p1),(p2)}
|
||||
// g2 = p(X), q(Y) ; (X,Y) in {(p1,p2),(p2,p1)}
|
||||
LogVars discardedLvs1 = theta1.getDiscardedLogVars();
|
||||
for (unsigned i = 0; i < discardedLvs1.size(); i++) {
|
||||
if (g1->constr()->isSingleton (discardedLvs1[i]) &&
|
||||
g1->nrFormulas (discardedLvs1[i]) == 1) {
|
||||
g1->constr()->remove (discardedLvs1[i]);
|
||||
} else {
|
||||
LogVar X_new = ++ g1->constr()->logVarSet().back();
|
||||
theta1.rename (discardedLvs1[i], X_new);
|
||||
}
|
||||
}
|
||||
LogVars discardedLvs2 = theta2.getDiscardedLogVars();
|
||||
for (unsigned i = 0; i < discardedLvs2.size(); i++) {
|
||||
if (g2->constr()->isSingleton (discardedLvs2[i]) &&
|
||||
g2->nrFormulas (discardedLvs2[i]) == 1) {
|
||||
g2->constr()->remove (discardedLvs2[i]);
|
||||
} else {
|
||||
LogVar X_new = ++ g2->constr()->logVarSet().back();
|
||||
theta2.rename (discardedLvs2[i], X_new);
|
||||
}
|
||||
}
|
||||
|
||||
// cout << "theta1: " << theta1 << endl;
|
||||
// cout << "theta2: " << theta2 << endl;
|
||||
g1->applySubstitution (theta1);
|
||||
g2->applySubstitution (theta2);
|
||||
}
|
||||
|
121
packages/CLPBN/horus/Parfactor.h
Normal file
121
packages/CLPBN/horus/Parfactor.h
Normal file
@ -0,0 +1,121 @@
|
||||
#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"
|
||||
|
||||
#include "Factor.h"
|
||||
|
||||
class Parfactor : public TFactor<ProbFormula>
|
||||
{
|
||||
public:
|
||||
Parfactor (
|
||||
const ProbFormulas&,
|
||||
const Params&,
|
||||
const Tuples&,
|
||||
unsigned);
|
||||
|
||||
Parfactor (const Parfactor*, const Tuple&);
|
||||
|
||||
Parfactor (const Parfactor*, ConstraintTree*);
|
||||
|
||||
Parfactor (const Parfactor&);
|
||||
|
||||
~Parfactor (void);
|
||||
|
||||
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 fIdx);
|
||||
|
||||
void multiply (Parfactor&);
|
||||
|
||||
bool canCountConvert (LogVar X);
|
||||
|
||||
void countConvert (LogVar);
|
||||
|
||||
void expand (LogVar, LogVar, LogVar);
|
||||
|
||||
void fullExpand (LogVar);
|
||||
|
||||
void reorderAccordingGrounds (const Grounds&);
|
||||
|
||||
void absorveEvidence (const ProbFormula&, unsigned);
|
||||
|
||||
void setNewGroups (void);
|
||||
|
||||
void applySubstitution (const Substitution&);
|
||||
|
||||
int findGroup (const Ground&) const;
|
||||
|
||||
bool containsGround (const Ground&) const;
|
||||
|
||||
bool containsGroup (unsigned) const;
|
||||
|
||||
unsigned nrFormulas (LogVar) const;
|
||||
|
||||
int indexOfLogVar (LogVar) const;
|
||||
|
||||
int indexOfGroup (unsigned) const;
|
||||
|
||||
unsigned nrFormulasWithGroup (unsigned) const;
|
||||
|
||||
vector<unsigned> getAllGroups (void) const;
|
||||
|
||||
void print (bool = false) const;
|
||||
|
||||
void printParameters (void) const;
|
||||
|
||||
void printProjections (void) const;
|
||||
|
||||
string getLabel (void) const;
|
||||
|
||||
void simplifyGrounds (void);
|
||||
|
||||
static bool canMultiply (Parfactor*, Parfactor*);
|
||||
|
||||
private:
|
||||
|
||||
void simplifyCountingFormulas (int fIdx);
|
||||
|
||||
void simplifyParfactor (unsigned fIdx1, unsigned fIdx2);
|
||||
|
||||
static std::pair<LogVars, LogVars> getAlignLogVars (
|
||||
Parfactor* g1, Parfactor* g2);
|
||||
|
||||
void expandPotential (int fIdx, unsigned newRange,
|
||||
const vector<unsigned>& sumIndexes);
|
||||
|
||||
static void alignAndExponentiate (Parfactor*, Parfactor*);
|
||||
|
||||
static void alignLogicalVars (Parfactor*, Parfactor*);
|
||||
|
||||
ConstraintTree* constr_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
typedef vector<Parfactor*> Parfactors;
|
||||
|
||||
#endif // HORUS_PARFACTOR_H
|
||||
|
619
packages/CLPBN/horus/ParfactorList.cpp
Normal file
619
packages/CLPBN/horus/ParfactorList.cpp
Normal file
@ -0,0 +1,619 @@
|
||||
#include <cassert>
|
||||
|
||||
#include "ParfactorList.h"
|
||||
|
||||
|
||||
ParfactorList::ParfactorList (const ParfactorList& pfList)
|
||||
{
|
||||
ParfactorList::const_iterator it = pfList.begin();
|
||||
while (it != pfList.end()) {
|
||||
addShattered (new Parfactor (**it));
|
||||
++ it;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
ParfactorList::ParfactorList (const Parfactors& pfs)
|
||||
{
|
||||
add (pfs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ParfactorList::~ParfactorList (void)
|
||||
{
|
||||
ParfactorList::const_iterator it = pfList_.begin();
|
||||
while (it != pfList_.end()) {
|
||||
delete *it;
|
||||
++ it;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ParfactorList::add (Parfactor* pf)
|
||||
{
|
||||
pf->setNewGroups();
|
||||
addToShatteredList (pf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ParfactorList::add (const Parfactors& pfs)
|
||||
{
|
||||
for (unsigned i = 0; i < pfs.size(); i++) {
|
||||
pfs[i]->setNewGroups();
|
||||
addToShatteredList (pfs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ParfactorList::addShattered (Parfactor* pf)
|
||||
{
|
||||
assert (isAllShattered());
|
||||
pfList_.push_back (pf);
|
||||
assert (isAllShattered());
|
||||
}
|
||||
|
||||
|
||||
|
||||
list<Parfactor*>::iterator
|
||||
ParfactorList::insertShattered (
|
||||
list<Parfactor*>::iterator it,
|
||||
Parfactor* pf)
|
||||
{
|
||||
return pfList_.insert (it, pf);
|
||||
assert (isAllShattered());
|
||||
}
|
||||
|
||||
|
||||
|
||||
list<Parfactor*>::iterator
|
||||
ParfactorList::remove (list<Parfactor*>::iterator it)
|
||||
{
|
||||
return pfList_.erase (it);
|
||||
}
|
||||
|
||||
|
||||
|
||||
list<Parfactor*>::iterator
|
||||
ParfactorList::removeAndDelete (list<Parfactor*>::iterator it)
|
||||
{
|
||||
delete *it;
|
||||
return pfList_.erase (it);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ParfactorList::isAllShattered (void) const
|
||||
{
|
||||
if (pfList_.size() <= 1) {
|
||||
return true;
|
||||
}
|
||||
vector<Parfactor*> pfs (pfList_.begin(), pfList_.end());
|
||||
for (unsigned i = 0; i < pfs.size(); i++) {
|
||||
assert (isShattered (pfs[i]));
|
||||
}
|
||||
for (unsigned i = 0; i < pfs.size() - 1; i++) {
|
||||
for (unsigned j = i + 1; j < pfs.size(); j++) {
|
||||
if (isShattered (pfs[i], pfs[j]) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ParfactorList::print (void) const
|
||||
{
|
||||
Parfactors pfVec (pfList_.begin(), pfList_.end());
|
||||
std::sort (pfVec.begin(), pfVec.end(), sortByParams());
|
||||
for (unsigned i = 0; i < pfVec.size(); i++) {
|
||||
pfVec[i]->print();
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ParfactorList::isShattered (const Parfactor* g) const
|
||||
{
|
||||
const ProbFormulas& formulas = g->arguments();
|
||||
if (formulas.size() < 2) {
|
||||
return true;
|
||||
}
|
||||
ConstraintTree ct (*g->constr());
|
||||
for (unsigned i = 0; i < formulas.size() - 1; i++) {
|
||||
for (unsigned j = i + 1; j < formulas.size(); j++) {
|
||||
if (formulas[i].group() == formulas[j].group()) {
|
||||
if (identical (
|
||||
formulas[i], *(g->constr()),
|
||||
formulas[j], *(g->constr())) == false) {
|
||||
g->print();
|
||||
cout << "-> not identical on positions " ;
|
||||
cout << i << " and " << j << endl;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (disjoint (
|
||||
formulas[i], *(g->constr()),
|
||||
formulas[j], *(g->constr())) == false) {
|
||||
g->print();
|
||||
cout << "-> not disjoint on positions " ;
|
||||
cout << i << " and " << j << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ParfactorList::isShattered (
|
||||
const Parfactor* g1,
|
||||
const Parfactor* g2) const
|
||||
{
|
||||
assert (g1 != g2);
|
||||
const ProbFormulas& fms1 = g1->arguments();
|
||||
const ProbFormulas& fms2 = g2->arguments();
|
||||
|
||||
for (unsigned i = 0; i < fms1.size(); i++) {
|
||||
for (unsigned j = 0; j < fms2.size(); j++) {
|
||||
if (fms1[i].group() == fms2[j].group()) {
|
||||
if (identical (
|
||||
fms1[i], *(g1->constr()),
|
||||
fms2[j], *(g2->constr())) == false) {
|
||||
g1->print();
|
||||
cout << "^" << endl;
|
||||
g2->print();
|
||||
cout << "-> not identical on group " << fms1[i].group() << endl;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (disjoint (
|
||||
fms1[i], *(g1->constr()),
|
||||
fms2[j], *(g2->constr())) == false) {
|
||||
g1->print();
|
||||
cout << "^" << endl;
|
||||
g2->print();
|
||||
cout << "-> not disjoint on groups " << fms1[i].group();
|
||||
cout << " and " << fms2[j].group() << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ParfactorList::addToShatteredList (Parfactor* g)
|
||||
{
|
||||
queue<Parfactor*> residuals;
|
||||
residuals.push (g);
|
||||
while (residuals.empty() == false) {
|
||||
Parfactor* pf = residuals.front();
|
||||
bool pfSplitted = false;
|
||||
list<Parfactor*>::iterator pfIter;
|
||||
pfIter = pfList_.begin();
|
||||
while (pfIter != pfList_.end()) {
|
||||
std::pair<Parfactors, Parfactors> shattRes;
|
||||
shattRes = shatter (*pfIter, pf);
|
||||
if (shattRes.first.empty() == false) {
|
||||
pfIter = removeAndDelete (pfIter);
|
||||
Util::addToQueue (residuals, shattRes.first);
|
||||
} else {
|
||||
++ pfIter;
|
||||
}
|
||||
if (shattRes.second.empty() == false) {
|
||||
delete pf;
|
||||
Util::addToQueue (residuals, shattRes.second);
|
||||
pfSplitted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
residuals.pop();
|
||||
if (pfSplitted == false) {
|
||||
Parfactors res = shatterAgainstMySelf (pf);
|
||||
if (res.empty()) {
|
||||
addShattered (pf);
|
||||
} else {
|
||||
Util::addToQueue (residuals, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert (isAllShattered());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Parfactors
|
||||
ParfactorList::shatterAgainstMySelf (Parfactor* g)
|
||||
{
|
||||
Parfactors pfs;
|
||||
queue<Parfactor*> residuals;
|
||||
residuals.push (g);
|
||||
bool shattered = true;
|
||||
while (residuals.empty() == false) {
|
||||
Parfactor* pf = residuals.front();
|
||||
Parfactors res = shatterAgainstMySelf2 (pf);
|
||||
if (res.empty()) {
|
||||
assert (isShattered (pf));
|
||||
if (shattered) {
|
||||
return { };
|
||||
}
|
||||
pfs.push_back (pf);
|
||||
} else {
|
||||
shattered = false;
|
||||
for (unsigned i = 0; i < res.size(); i++) {
|
||||
assert (res[i]->constr()->empty() == false);
|
||||
residuals.push (res[i]);
|
||||
}
|
||||
delete pf;
|
||||
}
|
||||
residuals.pop();
|
||||
}
|
||||
return pfs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Parfactors
|
||||
ParfactorList::shatterAgainstMySelf2 (Parfactor* g)
|
||||
{
|
||||
// slip a parfactor with overlapping formulas:
|
||||
// e.g. {s(X),s(Y)}, with (X,Y) in {(p1,p2),(p1,p3),(p4,p1)}
|
||||
const ProbFormulas& formulas = g->arguments();
|
||||
for (unsigned i = 0; i < formulas.size() - 1; i++) {
|
||||
for (unsigned j = i + 1; j < formulas.size(); j++) {
|
||||
if (formulas[i].sameSkeletonAs (formulas[j])) {
|
||||
Parfactors res = shatterAgainstMySelf (g, i, j);
|
||||
if (res.empty() == false) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Parfactors();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Parfactors
|
||||
ParfactorList::shatterAgainstMySelf (
|
||||
Parfactor* g,
|
||||
unsigned fIdx1,
|
||||
unsigned fIdx2)
|
||||
{
|
||||
/*
|
||||
Util::printDashedLine();
|
||||
cout << "-> SHATTERING" << endl;
|
||||
g->print();
|
||||
cout << "-> ON: " << g->argument (fIdx1) << "|" ;
|
||||
cout << g->constr()->tupleSet (g->argument (fIdx1).logVars()) << endl;
|
||||
cout << "-> ON: " << g->argument (fIdx2) << "|" ;
|
||||
cout << g->constr()->tupleSet (g->argument (fIdx2).logVars()) << endl;
|
||||
Util::printDashedLine();
|
||||
*/
|
||||
ProbFormula& f1 = g->argument (fIdx1);
|
||||
ProbFormula& f2 = g->argument (fIdx2);
|
||||
if (f1.isAtom()) {
|
||||
cerr << "error: a ground occurs twice in a parfactor" << endl;
|
||||
cerr << endl;
|
||||
abort();
|
||||
}
|
||||
assert (g->constr()->empty() == false);
|
||||
ConstraintTree ctCopy (*g->constr());
|
||||
if (f1.group() == f2.group()) {
|
||||
assert (identical (f1, *(g->constr()), f2, ctCopy));
|
||||
return { };
|
||||
}
|
||||
|
||||
g->constr()->moveToTop (f1.logVars());
|
||||
ctCopy.moveToTop (f2.logVars());
|
||||
|
||||
std::pair<ConstraintTree*,ConstraintTree*> split1 =
|
||||
g->constr()->split (f1.logVars(), &ctCopy, f2.logVars());
|
||||
ConstraintTree* commCt1 = split1.first;
|
||||
ConstraintTree* exclCt1 = split1.second;
|
||||
|
||||
if (commCt1->empty()) {
|
||||
// disjoint
|
||||
delete commCt1;
|
||||
delete exclCt1;
|
||||
return { };
|
||||
}
|
||||
|
||||
unsigned newGroup = ProbFormula::getNewGroup();
|
||||
Parfactors res1 = shatter (g, fIdx1, commCt1, exclCt1, newGroup);
|
||||
if (res1.empty()) {
|
||||
res1.push_back (g);
|
||||
}
|
||||
|
||||
Parfactors res;
|
||||
ctCopy.moveToTop (f1.logVars());
|
||||
for (unsigned i = 0; i < res1.size(); i++) {
|
||||
res1[i]->constr()->moveToTop (f2.logVars());
|
||||
std::pair<ConstraintTree*, ConstraintTree*> split2;
|
||||
split2 = res1[i]->constr()->split (f2.logVars(), &ctCopy, f1.logVars());
|
||||
ConstraintTree* commCt2 = split2.first;
|
||||
ConstraintTree* exclCt2 = split2.second;
|
||||
if (commCt2->empty()) {
|
||||
if (res1[i] != g) {
|
||||
res.push_back (res1[i]);
|
||||
}
|
||||
delete commCt2;
|
||||
delete exclCt2;
|
||||
continue;
|
||||
}
|
||||
newGroup = ProbFormula::getNewGroup();
|
||||
Parfactors res2 = shatter (res1[i], fIdx2, commCt2, exclCt2, newGroup);
|
||||
if (res2.empty()) {
|
||||
if (res1[i] != g) {
|
||||
res.push_back (res1[i]);
|
||||
}
|
||||
} else {
|
||||
Util::addToVector (res, res2);
|
||||
for (unsigned j = 0; j < res2.size(); j++) {
|
||||
}
|
||||
if (res1[i] != g) {
|
||||
delete res1[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (res.empty()) {
|
||||
g->argument (fIdx2).setGroup (g->argument (fIdx1).group());
|
||||
updateGroups (f2.group(), f1.group());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::pair<Parfactors, Parfactors>
|
||||
ParfactorList::shatter (Parfactor* g1, Parfactor* g2)
|
||||
{
|
||||
ProbFormulas& formulas1 = g1->arguments();
|
||||
ProbFormulas& formulas2 = g2->arguments();
|
||||
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;
|
||||
res = shatter (i, g1, j, g2);
|
||||
if (res.first.empty() == false ||
|
||||
res.second.empty() == false) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return make_pair (Parfactors(), Parfactors());
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::pair<Parfactors, Parfactors>
|
||||
ParfactorList::shatter (
|
||||
unsigned fIdx1, Parfactor* g1,
|
||||
unsigned fIdx2, Parfactor* g2)
|
||||
{
|
||||
ProbFormula& f1 = g1->argument (fIdx1);
|
||||
ProbFormula& f2 = g2->argument (fIdx2);
|
||||
/*
|
||||
Util::printDashedLine();
|
||||
cout << "-> SHATTERING" << endl;
|
||||
g1->print();
|
||||
cout << "-> WITH" << endl;
|
||||
g2->print();
|
||||
cout << "-> ON: " << f1 << "|" ;
|
||||
cout << g1->constr()->tupleSet (f1.logVars()) << endl;
|
||||
cout << "-> ON: " << f2 << "|" ;
|
||||
cout << g2->constr()->tupleSet (f2.logVars()) << endl;
|
||||
Util::printDashedLine();
|
||||
*/
|
||||
if (f1.isAtom()) {
|
||||
f2.setGroup (f1.group());
|
||||
updateGroups (f2.group(), f1.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 (f1.logVars(), g2->constr(), f2.logVars());
|
||||
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 (f2.logVars(), g1->constr(), f1.logVars());
|
||||
ConstraintTree* commCt2 = split2.first;
|
||||
ConstraintTree* exclCt2 = split2.second;
|
||||
|
||||
assert (commCt1->tupleSet (f1.logVars()) ==
|
||||
commCt2->tupleSet (f2.logVars()));
|
||||
|
||||
// unsigned static count = 0; count ++;
|
||||
// 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" ;
|
||||
// g1->constr()->exportToGraphViz (ss1.str().c_str(), true);
|
||||
// g2->constr()->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()) {
|
||||
// identical
|
||||
f2.setGroup (f1.group());
|
||||
updateGroups (f2.group(), f1.group());
|
||||
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, fIdx1, commCt1, exclCt1, group);
|
||||
Parfactors res2 = shatter (g2, fIdx2, commCt2, exclCt2, group);
|
||||
return make_pair (res1, res2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Parfactors
|
||||
ParfactorList::shatter (
|
||||
Parfactor* g,
|
||||
unsigned fIdx,
|
||||
ConstraintTree* commCt,
|
||||
ConstraintTree* exclCt,
|
||||
unsigned commGroup)
|
||||
{
|
||||
ProbFormula& f = g->argument (fIdx);
|
||||
if (exclCt->empty()) {
|
||||
delete commCt;
|
||||
delete exclCt;
|
||||
f.setGroup (commGroup);
|
||||
return { };
|
||||
}
|
||||
|
||||
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->expand (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);
|
||||
}
|
||||
delete commCt;
|
||||
delete exclCt;
|
||||
} else {
|
||||
Parfactor* newPf = new Parfactor (g, commCt);
|
||||
newPf->setNewGroups();
|
||||
newPf->argument (fIdx).setGroup (commGroup);
|
||||
result.push_back (newPf);
|
||||
newPf = new Parfactor (g, exclCt);
|
||||
newPf->setNewGroups();
|
||||
result.push_back (newPf);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ParfactorList::updateGroups (unsigned oldGroup, unsigned newGroup)
|
||||
{
|
||||
for (ParfactorList::iterator it = pfList_.begin();
|
||||
it != pfList_.end(); it++) {
|
||||
ProbFormulas& formulas = (*it)->arguments();
|
||||
for (unsigned i = 0; i < formulas.size(); i++) {
|
||||
if (formulas[i].group() == oldGroup) {
|
||||
formulas[i].setGroup (newGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ParfactorList::proper (
|
||||
const ProbFormula& f1, ConstraintTree ct1,
|
||||
const ProbFormula& f2, ConstraintTree ct2) const
|
||||
{
|
||||
return disjoint (f1, ct1, f2, ct2)
|
||||
|| identical (f1, ct1, f2, ct2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ParfactorList::identical (
|
||||
const ProbFormula& f1, ConstraintTree ct1,
|
||||
const ProbFormula& f2, ConstraintTree ct2) const
|
||||
{
|
||||
if (f1.sameSkeletonAs (f2) == false) {
|
||||
return false;
|
||||
}
|
||||
if (f1.isAtom()) {
|
||||
return true;
|
||||
}
|
||||
TupleSet ts1 = ct1.tupleSet (f1.logVars());
|
||||
TupleSet ts2 = ct2.tupleSet (f2.logVars());
|
||||
return ts1 == ts2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ParfactorList::disjoint (
|
||||
const ProbFormula& f1, ConstraintTree ct1,
|
||||
const ProbFormula& f2, ConstraintTree ct2) const
|
||||
{
|
||||
if (f1.sameSkeletonAs (f2) == false) {
|
||||
return true;
|
||||
}
|
||||
if (f1.isAtom()) {
|
||||
return false;
|
||||
}
|
||||
TupleSet ts1 = ct1.tupleSet (f1.logVars());
|
||||
TupleSet ts2 = ct2.tupleSet (f2.logVars());
|
||||
return (ts1 & ts2).empty();
|
||||
}
|
||||
|
120
packages/CLPBN/horus/ParfactorList.h
Normal file
120
packages/CLPBN/horus/ParfactorList.h
Normal file
@ -0,0 +1,120 @@
|
||||
#ifndef HORUS_PARFACTORLIST_H
|
||||
#define HORUS_PARFACTORLIST_H
|
||||
|
||||
#include <list>
|
||||
#include <queue>
|
||||
|
||||
#include "Parfactor.h"
|
||||
#include "ProbFormula.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
class ParfactorList
|
||||
{
|
||||
public:
|
||||
ParfactorList (void) { }
|
||||
|
||||
ParfactorList (const ParfactorList&);
|
||||
|
||||
ParfactorList (const Parfactors&);
|
||||
|
||||
~ParfactorList (void);
|
||||
|
||||
const list<Parfactor*>& parfactors (void) const { return pfList_; }
|
||||
|
||||
void clear (void) { pfList_.clear(); }
|
||||
|
||||
unsigned size (void) const { return pfList_.size(); }
|
||||
|
||||
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 add (Parfactor* pf);
|
||||
|
||||
void add (const Parfactors& pfs);
|
||||
|
||||
void addShattered (Parfactor* pf);
|
||||
|
||||
list<Parfactor*>::iterator insertShattered (
|
||||
list<Parfactor*>::iterator, Parfactor*);
|
||||
|
||||
list<Parfactor*>::iterator remove (list<Parfactor*>::iterator);
|
||||
|
||||
list<Parfactor*>::iterator removeAndDelete (list<Parfactor*>::iterator);
|
||||
|
||||
bool isAllShattered (void) const;
|
||||
|
||||
void print (void) const;
|
||||
|
||||
private:
|
||||
|
||||
bool isShattered (const Parfactor*) const;
|
||||
|
||||
bool isShattered (const Parfactor*, const Parfactor*) const;
|
||||
|
||||
void addToShatteredList (Parfactor*);
|
||||
|
||||
Parfactors shatterAgainstMySelf (Parfactor* g);
|
||||
|
||||
Parfactors shatterAgainstMySelf2 (Parfactor* g);
|
||||
|
||||
Parfactors shatterAgainstMySelf (
|
||||
Parfactor* g, unsigned fIdx1, unsigned fIdx2);
|
||||
|
||||
std::pair<Parfactors, Parfactors> shatter (
|
||||
Parfactor*, Parfactor*);
|
||||
|
||||
std::pair<Parfactors, Parfactors> shatter (
|
||||
unsigned, Parfactor*, unsigned, Parfactor*);
|
||||
|
||||
Parfactors shatter (
|
||||
Parfactor*,
|
||||
unsigned,
|
||||
ConstraintTree*,
|
||||
ConstraintTree*,
|
||||
unsigned);
|
||||
|
||||
void updateGroups (unsigned group1, unsigned group2);
|
||||
|
||||
bool proper (
|
||||
const ProbFormula&, ConstraintTree,
|
||||
const ProbFormula&, ConstraintTree) const;
|
||||
|
||||
bool identical (
|
||||
const ProbFormula&, ConstraintTree,
|
||||
const ProbFormula&, ConstraintTree) const;
|
||||
|
||||
bool disjoint (
|
||||
const ProbFormula&, ConstraintTree,
|
||||
const ProbFormula&, ConstraintTree) const;
|
||||
|
||||
struct sortByParams
|
||||
{
|
||||
inline bool operator() (const Parfactor* pf1, const Parfactor* pf2)
|
||||
{
|
||||
if (pf1->params().size() < pf2->params().size()) {
|
||||
return true;
|
||||
} else if (pf1->params().size() == pf2->params().size() &&
|
||||
pf1->params() < pf2->params()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
list<Parfactor*> pfList_;
|
||||
};
|
||||
|
||||
#endif // HORUS_PARFACTORLIST_H
|
||||
|
139
packages/CLPBN/horus/ProbFormula.cpp
Normal file
139
packages/CLPBN/horus/ProbFormula.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
#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 Util::contains (logVars_, lv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ProbFormula::contains (LogVarSet s) const
|
||||
{
|
||||
return LogVarSet (logVars_).contains (s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
ProbFormula::indexOf (LogVar X) const
|
||||
{
|
||||
return Util::indexOf (logVars_, X);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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::clearCountedLogVar (void)
|
||||
{
|
||||
countedLogVar_ = LogVar();
|
||||
}
|
||||
|
||||
|
||||
|
||||
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 operator== (const ProbFormula& f1, const ProbFormula& f2)
|
||||
{
|
||||
return f1.group_ == f2.group_ &&
|
||||
f1.logVars_ == f2.logVars_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::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_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ostream& operator<< (ostream &os, const ObservedFormula& of)
|
||||
{
|
||||
os << of.functor_ << "/" << of.arity_;
|
||||
os << "|" << of.constr_.tupleSet();
|
||||
os << " [evidence=" << of.evidence_ << "]";
|
||||
return os;
|
||||
}
|
||||
|
112
packages/CLPBN/horus/ProbFormula.h
Normal file
112
packages/CLPBN/horus/ProbFormula.h
Normal file
@ -0,0 +1,112 @@
|
||||
#ifndef HORUS_PROBFORMULA_H
|
||||
#define HORUS_PROBFORMULA_H
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "ConstraintTree.h"
|
||||
#include "LiftedUtils.h"
|
||||
#include "Horus.h"
|
||||
|
||||
typedef unsigned PrvGroup;
|
||||
|
||||
class ProbFormula
|
||||
{
|
||||
public:
|
||||
ProbFormula (Symbol f, const LogVars& lvs, unsigned range)
|
||||
: functor_(f), logVars_(lvs), range_(range),
|
||||
countedLogVar_(), group_(Util::maxUnsigned()) { }
|
||||
|
||||
ProbFormula (Symbol f, unsigned r)
|
||||
: functor_(f), range_(r), group_(Util::maxUnsigned()) { }
|
||||
|
||||
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 group_; }
|
||||
|
||||
void setGroup (unsigned g) { group_ = g; }
|
||||
|
||||
bool sameSkeletonAs (const ProbFormula&) const;
|
||||
|
||||
bool contains (LogVar) const;
|
||||
|
||||
bool contains (LogVarSet) const;
|
||||
|
||||
int indexOf (LogVar) const;
|
||||
|
||||
bool isAtom (void) const;
|
||||
|
||||
bool isCounting (void) const;
|
||||
|
||||
LogVar countedLogVar (void) const;
|
||||
|
||||
void setCountedLogVar (LogVar);
|
||||
|
||||
void clearCountedLogVar (void);
|
||||
|
||||
void rename (LogVar, LogVar);
|
||||
|
||||
static unsigned getNewGroup (void);
|
||||
|
||||
friend std::ostream& operator<< (ostream &os, const ProbFormula& f);
|
||||
|
||||
friend bool operator== (const ProbFormula& f1, const ProbFormula& f2);
|
||||
|
||||
private:
|
||||
Symbol functor_;
|
||||
LogVars logVars_;
|
||||
unsigned range_;
|
||||
LogVar countedLogVar_;
|
||||
unsigned group_;
|
||||
static int freeGroup_;
|
||||
};
|
||||
|
||||
typedef vector<ProbFormula> ProbFormulas;
|
||||
|
||||
|
||||
class ObservedFormula
|
||||
{
|
||||
public:
|
||||
ObservedFormula (Symbol f, unsigned a, unsigned ev)
|
||||
: functor_(f), arity_(a), evidence_(ev), constr_(a) { }
|
||||
|
||||
ObservedFormula (Symbol f, unsigned ev, const Tuple& tuple)
|
||||
: functor_(f), arity_(tuple.size()), evidence_(ev), constr_(arity_)
|
||||
{
|
||||
constr_.addTuple (tuple);
|
||||
}
|
||||
|
||||
Symbol functor (void) const { return functor_; }
|
||||
|
||||
unsigned arity (void) const { return arity_; }
|
||||
|
||||
unsigned evidence (void) const { return evidence_; }
|
||||
|
||||
ConstraintTree& constr (void) { return constr_; }
|
||||
|
||||
bool isAtom (void) const { return arity_ == 0; }
|
||||
|
||||
void addTuple (const Tuple& tuple) { constr_.addTuple (tuple); }
|
||||
|
||||
friend ostream& operator<< (ostream &os, const ObservedFormula& of);
|
||||
|
||||
private:
|
||||
Symbol functor_;
|
||||
unsigned arity_;
|
||||
unsigned evidence_;
|
||||
ConstraintTree constr_;
|
||||
};
|
||||
|
||||
typedef vector<ObservedFormula> ObservedFormulas;
|
||||
|
||||
#endif // HORUS_PROBFORMULA_H
|
||||
|
42
packages/CLPBN/horus/Solver.cpp
Normal file
42
packages/CLPBN/horus/Solver.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "Solver.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
void
|
||||
Solver::printAnswer (const VarIds& vids)
|
||||
{
|
||||
Vars unobservedVars;
|
||||
VarIds unobservedVids;
|
||||
for (unsigned i = 0; i < vids.size(); i++) {
|
||||
VarNode* vn = fg.getVarNode (vids[i]);
|
||||
if (vn->hasEvidence() == false) {
|
||||
unobservedVars.push_back (vn);
|
||||
unobservedVids.push_back (vids[i]);
|
||||
}
|
||||
}
|
||||
Params res = solveQuery (unobservedVids);
|
||||
vector<string> stateLines = Util::getStateLines (unobservedVars);
|
||||
for (unsigned i = 0; i < res.size(); i++) {
|
||||
cout << "P(" << stateLines[i] << ") = " ;
|
||||
cout << std::setprecision (Constants::PRECISION) << res[i];
|
||||
cout << endl;
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Solver::printAllPosterioris (void)
|
||||
{
|
||||
VarIds vids;
|
||||
const VarNodes& vars = fg.varNodes();
|
||||
for (unsigned i = 0; i < vars.size(); i++) {
|
||||
vids.push_back (vars[i]->varId());
|
||||
}
|
||||
std::sort (vids.begin(), vids.end());
|
||||
for (unsigned i = 0; i < vids.size(); i++) {
|
||||
printAnswer ({vids[i]});
|
||||
}
|
||||
}
|
||||
|
32
packages/CLPBN/horus/Solver.h
Normal file
32
packages/CLPBN/horus/Solver.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef HORUS_SOLVER_H
|
||||
#define HORUS_SOLVER_H
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#include "Var.h"
|
||||
#include "FactorGraph.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Solver
|
||||
{
|
||||
public:
|
||||
Solver (const FactorGraph& factorGraph) : fg(factorGraph) { }
|
||||
|
||||
virtual ~Solver() { } // ensure that subclass destructor is called
|
||||
|
||||
virtual Params solveQuery (VarIds queryVids) = 0;
|
||||
|
||||
virtual void printSolverFlags (void) const = 0;
|
||||
|
||||
void printAnswer (const VarIds& vids);
|
||||
|
||||
void printAllPosterioris (void);
|
||||
|
||||
protected:
|
||||
const FactorGraph& fg;
|
||||
};
|
||||
|
||||
#endif // HORUS_SOLVER_H
|
||||
|
12
packages/CLPBN/horus/TODO
Normal file
12
packages/CLPBN/horus/TODO
Normal file
@ -0,0 +1,12 @@
|
||||
- Refactor sum out in factor
|
||||
- Add a way to sum out several vars at the same time
|
||||
- Receive ranges as a constant reference in Indexer
|
||||
- Check if evidence remains in the compressed factor graph
|
||||
- Consider using hashs instead of vectors of colors to calculate the groups in
|
||||
counting bp
|
||||
- use more psize_t instead of unsigned for looping through params
|
||||
- Find a way to decrease the time required to find an
|
||||
elimination order for variable elimination
|
||||
- Add a sequential elimination heuristic
|
||||
|
||||
|
243
packages/CLPBN/horus/TinySet.h
Normal file
243
packages/CLPBN/horus/TinySet.h
Normal file
@ -0,0 +1,243 @@
|
||||
#ifndef HORUS_TINYSET_H
|
||||
#define HORUS_TINYSET_H
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
template <typename T, typename Compare = std::less<T>>
|
||||
class TinySet
|
||||
{
|
||||
public:
|
||||
|
||||
TinySet (const TinySet& s)
|
||||
: vec_(s.vec_), cmp_(s.cmp_) { }
|
||||
|
||||
TinySet (const Compare& cmp = Compare())
|
||||
: vec_(), cmp_(cmp) { }
|
||||
|
||||
TinySet (const T& t, const Compare& cmp = Compare())
|
||||
: vec_(1, t), cmp_(cmp) { }
|
||||
|
||||
TinySet (const vector<T>& elements, const Compare& cmp = Compare())
|
||||
: vec_(elements), cmp_(cmp)
|
||||
{
|
||||
std::sort (begin(), end(), cmp_);
|
||||
}
|
||||
|
||||
typedef typename vector<T>::iterator iterator;
|
||||
typedef typename vector<T>::const_iterator const_iterator;
|
||||
|
||||
iterator insert (const T& t)
|
||||
{
|
||||
iterator it = std::lower_bound (begin(), end(), t, cmp_);
|
||||
if (it == end() || cmp_(t, *it)) {
|
||||
vec_.insert (it, t);
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
void insert_sorted (const T& t)
|
||||
{
|
||||
vec_.push_back (t);
|
||||
assert (consistent());
|
||||
}
|
||||
|
||||
void remove (const T& t)
|
||||
{
|
||||
iterator it = std::lower_bound (begin(), end(), t, cmp_);
|
||||
if (it != end()) {
|
||||
vec_.erase (it);
|
||||
}
|
||||
}
|
||||
|
||||
const_iterator find (const T& t) const
|
||||
{
|
||||
const_iterator it = std::lower_bound (begin(), end(), t, cmp_);
|
||||
return it == end() || cmp_(t, *it) ? end() : it;
|
||||
}
|
||||
|
||||
iterator find (const T& t)
|
||||
{
|
||||
iterator it = std::lower_bound (begin(), end(), t, cmp_);
|
||||
return it == end() || cmp_(t, *it) ? end() : it;
|
||||
}
|
||||
|
||||
/* set union */
|
||||
TinySet operator| (const TinySet& s) const
|
||||
{
|
||||
TinySet res;
|
||||
std::set_union (
|
||||
vec_.begin(), vec_.end(),
|
||||
s.vec_.begin(), s.vec_.end(),
|
||||
std::back_inserter (res.vec_),
|
||||
cmp_);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* set intersection */
|
||||
TinySet operator& (const TinySet& s) const
|
||||
{
|
||||
TinySet res;
|
||||
std::set_intersection (
|
||||
vec_.begin(), vec_.end(),
|
||||
s.vec_.begin(), s.vec_.end(),
|
||||
std::back_inserter (res.vec_),
|
||||
cmp_);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* set difference */
|
||||
TinySet operator- (const TinySet& s) const
|
||||
{
|
||||
TinySet res;
|
||||
std::set_difference (
|
||||
vec_.begin(), vec_.end(),
|
||||
s.vec_.begin(), s.vec_.end(),
|
||||
std::back_inserter (res.vec_),
|
||||
cmp_);
|
||||
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 (
|
||||
vec_.begin(), vec_.end(), t, cmp_);
|
||||
}
|
||||
|
||||
bool contains (const TinySet& s) const
|
||||
{
|
||||
return std::includes (
|
||||
vec_.begin(),
|
||||
vec_.end(),
|
||||
s.vec_.begin(),
|
||||
s.vec_.end(),
|
||||
cmp_);
|
||||
}
|
||||
|
||||
bool in (const TinySet& s) const
|
||||
{
|
||||
return std::includes (
|
||||
s.vec_.begin(),
|
||||
s.vec_.end(),
|
||||
vec_.begin(),
|
||||
vec_.end(),
|
||||
cmp_);
|
||||
}
|
||||
|
||||
bool intersects (const TinySet& s) const
|
||||
{
|
||||
return (*this & s).size() > 0;
|
||||
}
|
||||
|
||||
const T& operator[] (typename vector<T>::size_type i) const
|
||||
{
|
||||
return vec_[i];
|
||||
}
|
||||
|
||||
T front (void) const
|
||||
{
|
||||
return vec_.front();
|
||||
}
|
||||
|
||||
T& front (void)
|
||||
{
|
||||
return vec_.front();
|
||||
}
|
||||
|
||||
T back (void) const
|
||||
{
|
||||
return vec_.back();
|
||||
}
|
||||
|
||||
T& back (void)
|
||||
{
|
||||
return vec_.back();
|
||||
}
|
||||
|
||||
const vector<T>& elements (void) const
|
||||
{
|
||||
return vec_;
|
||||
}
|
||||
|
||||
bool empty (void) const
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
typename vector<T>::size_type size (void) const
|
||||
{
|
||||
return vec_.size();
|
||||
}
|
||||
|
||||
void clear (void)
|
||||
{
|
||||
vec_.clear();
|
||||
}
|
||||
|
||||
void reserve (typename vector<T>::size_type size)
|
||||
{
|
||||
vec_.reserve (size);
|
||||
}
|
||||
|
||||
iterator begin (void) { return vec_.begin(); }
|
||||
iterator end (void) { return vec_.end(); }
|
||||
const_iterator begin (void) const { return vec_.begin(); }
|
||||
const_iterator end (void) const { return vec_.end(); }
|
||||
|
||||
friend bool operator== (const TinySet& s1, const TinySet& s2)
|
||||
{
|
||||
return s1.vec_ == s2.vec_;
|
||||
}
|
||||
|
||||
friend bool operator!= (const TinySet& s1, const TinySet& s2)
|
||||
{
|
||||
return ! (s1.vec_ == s2.vec_);
|
||||
}
|
||||
|
||||
friend std::ostream& operator << (std::ostream& out, const TinySet& s)
|
||||
{
|
||||
out << "{" ;
|
||||
typename vector<T>::size_type i;
|
||||
for (i = 0; i < s.size(); i++) {
|
||||
out << ((i != 0) ? "," : "") << s.vec_[i];
|
||||
}
|
||||
out << "}" ;
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
bool consistent (void) const
|
||||
{
|
||||
typename vector<T>::size_type i;
|
||||
for (i = 0; i < vec_.size() - 1; i++) {
|
||||
if (cmp_(vec_[i], vec_[i + 1]) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
vector<T> vec_;
|
||||
Compare cmp_;
|
||||
};
|
||||
|
||||
#endif // HORUS_TINYSET_H
|
||||
|
643
packages/CLPBN/horus/Util.cpp
Normal file
643
packages/CLPBN/horus/Util.cpp
Normal file
@ -0,0 +1,643 @@
|
||||
#include <limits>
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#include "Util.h"
|
||||
#include "Indexer.h"
|
||||
#include "ElimGraph.h"
|
||||
|
||||
|
||||
namespace Globals {
|
||||
bool logDomain = false;
|
||||
|
||||
unsigned verbosity = 0;
|
||||
|
||||
InfAlgorithms infAlgorithm = InfAlgorithms::VE;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
namespace BpOptions {
|
||||
Schedule schedule = BpOptions::Schedule::SEQ_FIXED;
|
||||
//Schedule schedule = BpOptions::Schedule::SEQ_RANDOM;
|
||||
//Schedule schedule = BpOptions::Schedule::PARALLEL;
|
||||
//Schedule schedule = BpOptions::Schedule::MAX_RESIDUAL;
|
||||
double accuracy = 0.0001;
|
||||
unsigned maxIter = 1000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
vector<NetInfo> Statistics::netInfo_;
|
||||
vector<CompressInfo> Statistics::compressInfo_;
|
||||
unsigned Statistics::primaryNetCount_;
|
||||
|
||||
|
||||
namespace Util {
|
||||
|
||||
|
||||
template <> std::string
|
||||
toString (const bool& b)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::boolalpha << b;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
stringToUnsigned (string str)
|
||||
{
|
||||
int val;
|
||||
stringstream ss;
|
||||
ss << str;
|
||||
ss >> val;
|
||||
if (val < 0) {
|
||||
cerr << "error: the readed number is negative" << endl;
|
||||
abort();
|
||||
}
|
||||
return static_cast<unsigned> (val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
stringToDouble (string str)
|
||||
{
|
||||
double val;
|
||||
stringstream ss;
|
||||
ss << str;
|
||||
ss >> val;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
toLog (Params& v)
|
||||
{
|
||||
for (unsigned i = 0; i < v.size(); i++) {
|
||||
v[i] = log (v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
fromLog (Params& v)
|
||||
{
|
||||
for (unsigned i = 0; i < v.size(); i++) {
|
||||
v[i] = exp (v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
factorial (unsigned num)
|
||||
{
|
||||
double result = 1.0;
|
||||
for (unsigned i = 1; i <= num; i++) {
|
||||
result *= i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
logFactorial (unsigned num)
|
||||
{
|
||||
double result = 0.0;
|
||||
if (num < 150) {
|
||||
result = std::log (factorial (num));
|
||||
} else {
|
||||
for (unsigned i = 1; i <= num; i++) {
|
||||
result += std::log (i);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
nrCombinations (unsigned n, unsigned k)
|
||||
{
|
||||
assert (n >= k);
|
||||
int diff = n - k;
|
||||
unsigned result = 0;
|
||||
if (n < 150) {
|
||||
unsigned prod = 1;
|
||||
for (int i = n; i > diff; i--) {
|
||||
prod *= i;
|
||||
}
|
||||
result = prod / factorial (k);
|
||||
} else {
|
||||
double prod = 0.0;
|
||||
for (int i = n; i > diff; i--) {
|
||||
prod += std::log (i);
|
||||
}
|
||||
prod -= logFactorial (k);
|
||||
result = static_cast<unsigned> (std::exp (prod));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
expectedSize (const Ranges& ranges)
|
||||
{
|
||||
unsigned prod = 1;
|
||||
for (unsigned i = 0; i < ranges.size(); i++) {
|
||||
prod *= ranges[i];
|
||||
}
|
||||
return prod;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
getNumberOfDigits (int num)
|
||||
{
|
||||
unsigned count = 1;
|
||||
while (num >= 10) {
|
||||
num /= 10;
|
||||
count ++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
isInteger (const string& s)
|
||||
{
|
||||
stringstream ss1 (s);
|
||||
stringstream ss2;
|
||||
int integer;
|
||||
ss1 >> integer;
|
||||
ss2 << integer;
|
||||
return (ss1.str() == ss2.str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
string
|
||||
parametersToString (const Params& v, unsigned precision)
|
||||
{
|
||||
stringstream ss;
|
||||
ss.precision (precision);
|
||||
ss << "[" ;
|
||||
for (unsigned i = 0; i < v.size(); i++) {
|
||||
if (i != 0) ss << ", " ;
|
||||
ss << v[i];
|
||||
}
|
||||
ss << "]" ;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
vector<string>
|
||||
getStateLines (const Vars& vars)
|
||||
{
|
||||
StatesIndexer idx (vars);
|
||||
vector<string> jointStrings;
|
||||
while (idx.valid()) {
|
||||
stringstream ss;
|
||||
for (unsigned i = 0; i < vars.size(); i++) {
|
||||
if (i != 0) ss << ", " ;
|
||||
ss << vars[i]->label() << "=" << vars[i]->states()[(idx[i])];
|
||||
}
|
||||
jointStrings.push_back (ss.str());
|
||||
++ idx;
|
||||
}
|
||||
return jointStrings;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
setHorusFlag (string key, string value)
|
||||
{
|
||||
bool returnVal = true;
|
||||
if (key == "verbosity") {
|
||||
stringstream ss;
|
||||
ss << value;
|
||||
ss >> Globals::verbosity;
|
||||
} else if (key == "inf_alg") {
|
||||
if ( value == "ve") {
|
||||
Globals::infAlgorithm = InfAlgorithms::VE;
|
||||
} else if (value == "bp") {
|
||||
Globals::infAlgorithm = InfAlgorithms::BP;
|
||||
} else if (value == "cbp") {
|
||||
Globals::infAlgorithm = InfAlgorithms::CBP;
|
||||
} else {
|
||||
cerr << "warning: invalid value `" << value << "' " ;
|
||||
cerr << "for `" << key << "'" << endl;
|
||||
returnVal = false;
|
||||
}
|
||||
} else if (key == "elim_heuristic") {
|
||||
if ( value == "min_neighbors") {
|
||||
ElimGraph::elimHeuristic = ElimHeuristic::MIN_NEIGHBORS;
|
||||
} else if (value == "min_weight") {
|
||||
ElimGraph::elimHeuristic = ElimHeuristic::MIN_WEIGHT;
|
||||
} else if (value == "min_fill") {
|
||||
ElimGraph::elimHeuristic = ElimHeuristic::MIN_FILL;
|
||||
} else if (value == "weighted_min_fill") {
|
||||
ElimGraph::elimHeuristic = ElimHeuristic::WEIGHTED_MIN_FILL;
|
||||
} else {
|
||||
cerr << "warning: invalid value `" << value << "' " ;
|
||||
cerr << "for `" << key << "'" << endl;
|
||||
returnVal = false;
|
||||
}
|
||||
} else if (key == "schedule") {
|
||||
if ( value == "seq_fixed") {
|
||||
BpOptions::schedule = BpOptions::Schedule::SEQ_FIXED;
|
||||
} else if (value == "seq_random") {
|
||||
BpOptions::schedule = BpOptions::Schedule::SEQ_RANDOM;
|
||||
} else if (value == "parallel") {
|
||||
BpOptions::schedule = BpOptions::Schedule::PARALLEL;
|
||||
} else if (value == "max_residual") {
|
||||
BpOptions::schedule = BpOptions::Schedule::MAX_RESIDUAL;
|
||||
} else {
|
||||
cerr << "warning: invalid value `" << value << "' " ;
|
||||
cerr << "for `" << key << "'" << endl;
|
||||
returnVal = false;
|
||||
}
|
||||
} else if (key == "accuracy") {
|
||||
stringstream ss;
|
||||
ss << value;
|
||||
ss >> BpOptions::accuracy;
|
||||
} else if (key == "max_iter") {
|
||||
stringstream ss;
|
||||
ss << value;
|
||||
ss >> BpOptions::maxIter;
|
||||
} else if (key == "use_logarithms") {
|
||||
if ( value == "true") {
|
||||
Globals::logDomain = true;
|
||||
} else if (value == "false") {
|
||||
Globals::logDomain = false;
|
||||
} else {
|
||||
cerr << "warning: invalid value `" << value << "' " ;
|
||||
cerr << "for `" << key << "'" << endl;
|
||||
returnVal = false;
|
||||
}
|
||||
} else {
|
||||
cerr << "warning: invalid key `" << key << "'" << endl;
|
||||
returnVal = false;
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
printHeader (string header, std::ostream& os)
|
||||
{
|
||||
printAsteriskLine (os);
|
||||
os << header << endl;
|
||||
printAsteriskLine (os);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
printSubHeader (string header, std::ostream& os)
|
||||
{
|
||||
printDashedLine (os);
|
||||
os << header << endl;
|
||||
printDashedLine (os);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
printAsteriskLine (std::ostream& os)
|
||||
{
|
||||
os << "********************************" ;
|
||||
os << "********************************" ;
|
||||
os << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
printDashedLine (std::ostream& os)
|
||||
{
|
||||
os << "--------------------------------" ;
|
||||
os << "--------------------------------" ;
|
||||
os << endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace LogAware {
|
||||
|
||||
void
|
||||
normalize (Params& v)
|
||||
{
|
||||
double sum = LogAware::addIdenty();
|
||||
if (Globals::logDomain) {
|
||||
for (unsigned i = 0; i < v.size(); i++) {
|
||||
sum = Util::logSum (sum, v[i]);
|
||||
}
|
||||
assert (sum != -numeric_limits<double>::infinity());
|
||||
for (unsigned i = 0; i < v.size(); i++) {
|
||||
v[i] -= sum;
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < v.size(); i++) {
|
||||
sum += v[i];
|
||||
}
|
||||
assert (sum != 0.0);
|
||||
for (unsigned i = 0; i < v.size(); i++) {
|
||||
v[i] /= sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
getL1Distance (const Params& v1, const Params& v2)
|
||||
{
|
||||
assert (v1.size() == v2.size());
|
||||
double dist = 0.0;
|
||||
if (Globals::logDomain) {
|
||||
for (unsigned i = 0; i < v1.size(); i++) {
|
||||
dist += abs (exp(v1[i]) - exp(v2[i]));
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < v1.size(); i++) {
|
||||
dist += abs (v1[i] - v2[i]);
|
||||
}
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
getMaxNorm (const Params& v1, const Params& v2)
|
||||
{
|
||||
assert (v1.size() == v2.size());
|
||||
double max = 0.0;
|
||||
if (Globals::logDomain) {
|
||||
for (unsigned i = 0; i < v1.size(); i++) {
|
||||
double diff = abs (exp(v1[i]) - exp(v2[i]));
|
||||
if (diff > max) {
|
||||
max = diff;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < v1.size(); i++) {
|
||||
double diff = abs (v1[i] - v2[i]);
|
||||
if (diff > max) {
|
||||
max = diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
pow (double p, unsigned expoent)
|
||||
{
|
||||
return Globals::logDomain ? p * expoent : std::pow (p, expoent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
pow (double p, double expoent)
|
||||
{
|
||||
// assumes that `expoent' is never in log domain
|
||||
return Globals::logDomain ? p * expoent : std::pow (p, expoent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
pow (Params& v, unsigned expoent)
|
||||
{
|
||||
if (expoent == 1) {
|
||||
return;
|
||||
}
|
||||
if (Globals::logDomain) {
|
||||
for (unsigned i = 0; i < v.size(); i++) {
|
||||
v[i] *= expoent;
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < v.size(); i++) {
|
||||
v[i] = std::pow (v[i], expoent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
pow (Params& v, double expoent)
|
||||
{
|
||||
// assumes that `expoent' is never in log domain
|
||||
if (Globals::logDomain) {
|
||||
for (unsigned i = 0; i < v.size(); i++) {
|
||||
v[i] *= expoent;
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < v.size(); i++) {
|
||||
v[i] = std::pow (v[i], expoent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
Statistics::getSolvedNetworksCounting (void)
|
||||
{
|
||||
return netInfo_.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Statistics::incrementPrimaryNetworksCounting (void)
|
||||
{
|
||||
primaryNetCount_ ++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
Statistics::getPrimaryNetworksCounting (void)
|
||||
{
|
||||
return primaryNetCount_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Statistics::updateStatistics (
|
||||
unsigned size,
|
||||
bool loopy,
|
||||
unsigned nIters,
|
||||
double time)
|
||||
{
|
||||
netInfo_.push_back (NetInfo (size, loopy, nIters, time));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Statistics::printStatistics (void)
|
||||
{
|
||||
cout << getStatisticString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Statistics::writeStatistics (const char* fileName)
|
||||
{
|
||||
ofstream out (fileName);
|
||||
if (!out.is_open()) {
|
||||
cerr << "error: cannot open file to write at " ;
|
||||
cerr << "Statistics::writeStats()" << endl;
|
||||
abort();
|
||||
}
|
||||
out << getStatisticString();
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Statistics::updateCompressingStatistics (
|
||||
unsigned nrGroundVars,
|
||||
unsigned nrGroundFactors,
|
||||
unsigned nrClusterVars,
|
||||
unsigned nrClusterFactors,
|
||||
unsigned nrNeighborless)
|
||||
{
|
||||
compressInfo_.push_back (CompressInfo (nrGroundVars, nrGroundFactors,
|
||||
nrClusterVars, nrClusterFactors, nrNeighborless));
|
||||
}
|
||||
|
||||
|
||||
|
||||
string
|
||||
Statistics::getStatisticString (void)
|
||||
{
|
||||
stringstream ss2, ss3, ss4, ss1;
|
||||
ss1 << "running mode: " ;
|
||||
switch (Globals::infAlgorithm) {
|
||||
case InfAlgorithms::VE: ss1 << "ve" << endl; break;
|
||||
case InfAlgorithms::BP: ss1 << "bp" << endl; break;
|
||||
case InfAlgorithms::CBP: ss1 << "cbp" << endl; break;
|
||||
}
|
||||
ss1 << "message schedule: " ;
|
||||
switch (BpOptions::schedule) {
|
||||
case BpOptions::Schedule::SEQ_FIXED:
|
||||
ss1 << "sequential fixed" << endl;
|
||||
break;
|
||||
case BpOptions::Schedule::SEQ_RANDOM:
|
||||
ss1 << "sequential random" << endl;
|
||||
break;
|
||||
case BpOptions::Schedule::PARALLEL:
|
||||
ss1 << "parallel" << endl;
|
||||
break;
|
||||
case BpOptions::Schedule::MAX_RESIDUAL:
|
||||
ss1 << "max residual" << endl;
|
||||
break;
|
||||
}
|
||||
ss1 << "max iterations: " << BpOptions::maxIter << endl;
|
||||
ss1 << "accuracy " << BpOptions::accuracy << endl;
|
||||
ss1 << endl << endl;
|
||||
Util::printSubHeader ("Network information", ss2);
|
||||
ss2 << left;
|
||||
ss2 << setw (15) << "Network Size" ;
|
||||
ss2 << setw (9) << "Loopy" ;
|
||||
ss2 << setw (15) << "Iterations" ;
|
||||
ss2 << setw (15) << "Solving Time" ;
|
||||
ss2 << endl;
|
||||
unsigned nLoopyNets = 0;
|
||||
unsigned nUnconvergedRuns = 0;
|
||||
double totalSolvingTime = 0.0;
|
||||
for (unsigned i = 0; i < netInfo_.size(); i++) {
|
||||
ss2 << setw (15) << netInfo_[i].size;
|
||||
if (netInfo_[i].loopy) {
|
||||
ss2 << setw (9) << "yes";
|
||||
nLoopyNets ++;
|
||||
} else {
|
||||
ss2 << setw (9) << "no";
|
||||
}
|
||||
if (netInfo_[i].nIters == 0) {
|
||||
ss2 << setw (15) << "n/a" ;
|
||||
} else {
|
||||
ss2 << setw (15) << netInfo_[i].nIters;
|
||||
if (netInfo_[i].nIters > BpOptions::maxIter) {
|
||||
nUnconvergedRuns ++;
|
||||
}
|
||||
}
|
||||
ss2 << setw (15) << netInfo_[i].time;
|
||||
totalSolvingTime += netInfo_[i].time;
|
||||
ss2 << endl;
|
||||
}
|
||||
ss2 << endl << endl;
|
||||
|
||||
unsigned c1 = 0, c2 = 0, c3 = 0, c4 = 0;
|
||||
if (compressInfo_.size() > 0) {
|
||||
Util::printSubHeader ("Compress information", ss3);
|
||||
ss3 << left;
|
||||
ss3 << "Ground Cluster Ground Cluster Neighborless" << endl;
|
||||
ss3 << "Vars Vars Factors Factors Vars" << endl;
|
||||
for (unsigned i = 0; i < compressInfo_.size(); i++) {
|
||||
ss3 << setw (9) << compressInfo_[i].nrGroundVars;
|
||||
ss3 << setw (10) << compressInfo_[i].nrClusterVars;
|
||||
ss3 << setw (10) << compressInfo_[i].nrGroundFactors;
|
||||
ss3 << setw (10) << compressInfo_[i].nrClusterFactors;
|
||||
ss3 << setw (10) << compressInfo_[i].nrNeighborless;
|
||||
ss3 << endl;
|
||||
c1 += compressInfo_[i].nrGroundVars - compressInfo_[i].nrNeighborless;
|
||||
c2 += compressInfo_[i].nrClusterVars;
|
||||
c3 += compressInfo_[i].nrGroundFactors - compressInfo_[i].nrNeighborless;
|
||||
c4 += compressInfo_[i].nrClusterFactors;
|
||||
if (compressInfo_[i].nrNeighborless != 0) {
|
||||
c2 --;
|
||||
c4 --;
|
||||
}
|
||||
}
|
||||
ss3 << endl << endl;
|
||||
}
|
||||
|
||||
ss4 << "primary networks: " << primaryNetCount_ << endl;
|
||||
ss4 << "solved networks: " << netInfo_.size() << endl;
|
||||
ss4 << "loopy networks: " << nLoopyNets << endl;
|
||||
ss4 << "unconverged runs: " << nUnconvergedRuns << endl;
|
||||
ss4 << "total solving time: " << totalSolvingTime << endl;
|
||||
if (compressInfo_.size() > 0) {
|
||||
double pc1 = (1.0 - (c2 / (double)c1)) * 100.0;
|
||||
double pc2 = (1.0 - (c4 / (double)c3)) * 100.0;
|
||||
ss4 << setprecision (5);
|
||||
ss4 << "variable compression: " << pc1 << "%" << endl;
|
||||
ss4 << "factor compression: " << pc2 << "%" << endl;
|
||||
}
|
||||
ss4 << endl << endl;
|
||||
|
||||
ss1 << ss4.str() << ss2.str() << ss3.str();
|
||||
return ss1.str();
|
||||
}
|
||||
|
422
packages/CLPBN/horus/Util.h
Normal file
422
packages/CLPBN/horus/Util.h
Normal file
@ -0,0 +1,422 @@
|
||||
#ifndef HORUS_UTIL_H
|
||||
#define HORUS_UTIL_H
|
||||
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "Horus.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace Util {
|
||||
|
||||
template <typename T> void addToVector (vector<T>&, const vector<T>&);
|
||||
|
||||
template <typename T> void addToSet (set<T>&, const vector<T>&);
|
||||
|
||||
template <typename T> void addToQueue (queue<T>&, const vector<T>&);
|
||||
|
||||
template <typename T> bool contains (const vector<T>&, const T&);
|
||||
|
||||
template <typename T> bool contains (const set<T>&, const T&);
|
||||
|
||||
template <typename K, typename V> bool contains (
|
||||
const unordered_map<K, V>&, const K&);
|
||||
|
||||
template <typename T> int indexOf (const vector<T>&, const T&);
|
||||
|
||||
template <typename T> std::string toString (const T&);
|
||||
|
||||
template <> std::string toString (const bool&);
|
||||
|
||||
unsigned stringToUnsigned (string);
|
||||
|
||||
double stringToDouble (string);
|
||||
|
||||
void toLog (Params&);
|
||||
|
||||
void fromLog (Params&);
|
||||
|
||||
double logSum (double, double);
|
||||
|
||||
void multiply (Params&, const Params&);
|
||||
|
||||
void multiply (Params&, const Params&, unsigned);
|
||||
|
||||
void add (Params&, const Params&);
|
||||
|
||||
void subtract (Params&, const Params&);
|
||||
|
||||
void add (Params&, const Params&, unsigned);
|
||||
|
||||
unsigned maxUnsigned (void);
|
||||
|
||||
double factorial (unsigned);
|
||||
|
||||
double logFactorial (unsigned);
|
||||
|
||||
unsigned nrCombinations (unsigned, unsigned);
|
||||
|
||||
unsigned expectedSize (const Ranges&);
|
||||
|
||||
unsigned getNumberOfDigits (int);
|
||||
|
||||
bool isInteger (const string&);
|
||||
|
||||
string parametersToString (const Params&, unsigned = Constants::PRECISION);
|
||||
|
||||
vector<string> getStateLines (const Vars&);
|
||||
|
||||
bool setHorusFlag (string key, string value);
|
||||
|
||||
void printHeader (string, std::ostream& os = std::cout);
|
||||
|
||||
void printSubHeader (string, std::ostream& os = std::cout);
|
||||
|
||||
void printAsteriskLine (std::ostream& os = std::cout);
|
||||
|
||||
void printDashedLine (std::ostream& os = std::cout);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename T> void
|
||||
Util::addToVector (vector<T>& v, const vector<T>& elements)
|
||||
{
|
||||
v.insert (v.end(), elements.begin(), elements.end());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T> void
|
||||
Util::addToSet (set<T>& s, const vector<T>& elements)
|
||||
{
|
||||
s.insert (elements.begin(), elements.end());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T> void
|
||||
Util::addToQueue (queue<T>& q, const vector<T>& elements)
|
||||
{
|
||||
for (unsigned i = 0; i < elements.size(); i++) {
|
||||
q.push (elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T> bool
|
||||
Util::contains (const vector<T>& v, const T& e)
|
||||
{
|
||||
return std::find (v.begin(), v.end(), e) != v.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T> bool
|
||||
Util::contains (const set<T>& s, const T& e)
|
||||
{
|
||||
return s.find (e) != s.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename K, typename V> bool
|
||||
Util::contains (const unordered_map<K, V>& m, const K& k)
|
||||
{
|
||||
return m.find (k) != m.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T> int
|
||||
Util::indexOf (const vector<T>& v, const T& e)
|
||||
{
|
||||
int pos = std::distance (v.begin(),
|
||||
std::find (v.begin(), v.end(), e));
|
||||
if (pos == (int)v.size()) {
|
||||
pos = -1;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T> std::string
|
||||
Util::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;
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
const double NEG_INF = -numeric_limits<double>::infinity();
|
||||
};
|
||||
|
||||
|
||||
inline double
|
||||
Util::logSum (double x, double y)
|
||||
{
|
||||
// std::log (std::exp (x) + std::exp (y)) can overflow!
|
||||
assert (std::isnan (x) == false);
|
||||
assert (std::isnan (y) == false);
|
||||
if (x == NEG_INF) {
|
||||
return y;
|
||||
}
|
||||
if (y == NEG_INF) {
|
||||
return x;
|
||||
}
|
||||
// if one value is much smaller than the other,
|
||||
// keep the larger value
|
||||
const double tol = 460.517; // log (1e200)
|
||||
if (x < y - tol) {
|
||||
return y;
|
||||
}
|
||||
if (y < x - tol) {
|
||||
return x;
|
||||
}
|
||||
assert (std::isnan (x - y) == false);
|
||||
const double exp_diff = std::exp (x - y);
|
||||
if (std::isfinite (exp_diff) == false) {
|
||||
// difference is too large
|
||||
return x > y ? x : y;
|
||||
}
|
||||
// otherwise return the sum
|
||||
return y + std::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());
|
||||
std::transform (v1.begin(), v1.end(), v2.begin(),
|
||||
v1.begin(), plus<double>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void
|
||||
Util::subtract (Params& v1, const Params& v2)
|
||||
{
|
||||
assert (v1.size() == v2.size());
|
||||
std::transform (v1.begin(), v1.end(), v2.begin(),
|
||||
v1.begin(), minus<double>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
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 unsigned
|
||||
Util::maxUnsigned (void)
|
||||
{
|
||||
return numeric_limits<unsigned>::max();
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace LogAware {
|
||||
|
||||
inline double
|
||||
one()
|
||||
{
|
||||
return Globals::logDomain ? 0.0 : 1.0;
|
||||
}
|
||||
|
||||
|
||||
inline double
|
||||
zero() {
|
||||
return Globals::logDomain ? NEG_INF : 0.0 ;
|
||||
}
|
||||
|
||||
|
||||
inline double
|
||||
addIdenty()
|
||||
{
|
||||
return Globals::logDomain ? NEG_INF : 0.0;
|
||||
}
|
||||
|
||||
|
||||
inline double
|
||||
multIdenty()
|
||||
{
|
||||
return Globals::logDomain ? 0.0 : 1.0;
|
||||
}
|
||||
|
||||
|
||||
inline double
|
||||
withEvidence()
|
||||
{
|
||||
return Globals::logDomain ? 0.0 : 1.0;
|
||||
}
|
||||
|
||||
|
||||
inline double
|
||||
noEvidence() {
|
||||
return Globals::logDomain ? NEG_INF : 0.0;
|
||||
}
|
||||
|
||||
|
||||
inline double
|
||||
tl (double v)
|
||||
{
|
||||
return Globals::logDomain ? log (v) : v;
|
||||
}
|
||||
|
||||
|
||||
inline double
|
||||
fl (double v)
|
||||
{
|
||||
return Globals::logDomain ? exp (v) : v;
|
||||
}
|
||||
|
||||
|
||||
void normalize (Params&);
|
||||
|
||||
double getL1Distance (const Params&, const Params&);
|
||||
|
||||
double getMaxNorm (const Params&, const Params&);
|
||||
|
||||
double pow (double, unsigned);
|
||||
|
||||
double pow (double, double);
|
||||
|
||||
void pow (Params&, unsigned);
|
||||
|
||||
void pow (Params&, double);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
nrGroundVars = a;
|
||||
nrGroundFactors = b;
|
||||
nrClusterVars = c;
|
||||
nrClusterFactors = d;
|
||||
nrNeighborless = e;
|
||||
}
|
||||
unsigned nrGroundVars;
|
||||
unsigned nrGroundFactors;
|
||||
unsigned nrClusterVars;
|
||||
unsigned nrClusterFactors;
|
||||
unsigned nrNeighborless;
|
||||
};
|
||||
|
||||
|
||||
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 writeStatistics (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
|
||||
|
102
packages/CLPBN/horus/Var.cpp
Normal file
102
packages/CLPBN/horus/Var.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "Var.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
unordered_map<VarId, VarInfo> Var::varsInfo_;
|
||||
|
||||
|
||||
Var::Var (const Var* v)
|
||||
{
|
||||
varId_ = v->varId();
|
||||
range_ = v->range();
|
||||
evidence_ = v->getEvidence();
|
||||
index_ = std::numeric_limits<unsigned>::max();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Var::Var (VarId varId, unsigned range, int evidence)
|
||||
{
|
||||
assert (range != 0);
|
||||
assert (evidence < (int) range);
|
||||
varId_ = varId;
|
||||
range_ = range;
|
||||
evidence_ = evidence;
|
||||
index_ = std::numeric_limits<unsigned>::max();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
Var::isValidState (int stateIndex)
|
||||
{
|
||||
return stateIndex >= 0 && stateIndex < (int) range_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
Var::isValidState (const string& stateName)
|
||||
{
|
||||
States states = Var::getVarInfo (varId_).states;
|
||||
return Util::contains (states, stateName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Var::setEvidence (int ev)
|
||||
{
|
||||
assert (ev < (int) range_);
|
||||
evidence_ = ev;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Var::setEvidence (const string& ev)
|
||||
{
|
||||
States states = Var::getVarInfo (varId_).states;
|
||||
for (unsigned i = 0; i < states.size(); i++) {
|
||||
if (states[i] == ev) {
|
||||
evidence_ = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert (false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
string
|
||||
Var::label (void) const
|
||||
{
|
||||
if (Var::varsHaveInfo()) {
|
||||
return Var::getVarInfo (varId_).label;
|
||||
}
|
||||
stringstream ss;
|
||||
ss << "x" << varId_;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
States
|
||||
Var::states (void) const
|
||||
{
|
||||
if (Var::varsHaveInfo()) {
|
||||
return Var::getVarInfo (varId_).states;
|
||||
}
|
||||
States states;
|
||||
for (unsigned i = 0; i < range_; i++) {
|
||||
stringstream ss;
|
||||
ss << i ;
|
||||
states.push_back (ss.str());
|
||||
}
|
||||
return states;
|
||||
}
|
||||
|
108
packages/CLPBN/horus/Var.h
Normal file
108
packages/CLPBN/horus/Var.h
Normal file
@ -0,0 +1,108 @@
|
||||
#ifndef HORUS_Var_H
|
||||
#define HORUS_Var_H
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "Util.h"
|
||||
#include "Horus.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
struct VarInfo
|
||||
{
|
||||
VarInfo (string l, const States& sts) : label(l), states(sts) { }
|
||||
string label;
|
||||
States states;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Var
|
||||
{
|
||||
public:
|
||||
Var (const Var*);
|
||||
|
||||
Var (VarId, unsigned, int = Constants::NO_EVIDENCE);
|
||||
|
||||
virtual ~Var (void) { };
|
||||
|
||||
unsigned varId (void) const { return varId_; }
|
||||
|
||||
unsigned range (void) const { return range_; }
|
||||
|
||||
int getEvidence (void) const { return evidence_; }
|
||||
|
||||
unsigned getIndex (void) const { return index_; }
|
||||
|
||||
void setIndex (unsigned idx) { index_ = idx; }
|
||||
|
||||
operator unsigned () const { return index_; }
|
||||
|
||||
bool hasEvidence (void) const
|
||||
{
|
||||
return evidence_ != Constants::NO_EVIDENCE;
|
||||
}
|
||||
|
||||
bool operator== (const Var& var) const
|
||||
{
|
||||
assert (!(varId_ == var.varId() && range_ != var.range()));
|
||||
return varId_ == var.varId();
|
||||
}
|
||||
|
||||
bool operator!= (const Var& var) const
|
||||
{
|
||||
assert (!(varId_ == var.varId() && range_ != var.range()));
|
||||
return varId_ != var.varId();
|
||||
}
|
||||
|
||||
bool isValidState (int);
|
||||
|
||||
bool isValidState (const string&);
|
||||
|
||||
void setEvidence (int);
|
||||
|
||||
void setEvidence (const string&);
|
||||
|
||||
string label (void) const;
|
||||
|
||||
States states (void) const;
|
||||
|
||||
static void addVarInfo (
|
||||
VarId vid, string label, const States& states)
|
||||
{
|
||||
assert (Util::contains (varsInfo_, vid) == false);
|
||||
varsInfo_.insert (make_pair (vid, VarInfo (label, states)));
|
||||
}
|
||||
|
||||
static VarInfo getVarInfo (VarId vid)
|
||||
{
|
||||
assert (Util::contains (varsInfo_, vid));
|
||||
return varsInfo_.find (vid)->second;
|
||||
}
|
||||
|
||||
static bool varsHaveInfo (void)
|
||||
{
|
||||
return varsInfo_.size() != 0;
|
||||
}
|
||||
|
||||
static void clearVarsInfo (void)
|
||||
{
|
||||
varsInfo_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
VarId varId_;
|
||||
unsigned range_;
|
||||
int evidence_;
|
||||
unsigned index_;
|
||||
|
||||
static unordered_map<VarId, VarInfo> varsInfo_;
|
||||
|
||||
};
|
||||
|
||||
#endif // BP_Var_H
|
||||
|
216
packages/CLPBN/horus/VarElimSolver.cpp
Normal file
216
packages/CLPBN/horus/VarElimSolver.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "VarElimSolver.h"
|
||||
#include "ElimGraph.h"
|
||||
#include "Factor.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
VarElimSolver::~VarElimSolver (void)
|
||||
{
|
||||
delete factorList_.back();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Params
|
||||
VarElimSolver::solveQuery (VarIds queryVids)
|
||||
{
|
||||
if (Globals::verbosity > 1) {
|
||||
cout << "Solving query on " ;
|
||||
for (unsigned i = 0; i < queryVids.size(); i++) {
|
||||
if (i != 0) cout << ", " ;
|
||||
cout << fg.getVarNode (queryVids[i])->label();
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
factorList_.clear();
|
||||
varFactors_.clear();
|
||||
elimOrder_.clear();
|
||||
createFactorList();
|
||||
absorveEvidence();
|
||||
findEliminationOrder (queryVids);
|
||||
processFactorList (queryVids);
|
||||
Params params = factorList_.back()->params();
|
||||
if (Globals::logDomain) {
|
||||
Util::fromLog (params);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
VarElimSolver::printSolverFlags (void) const
|
||||
{
|
||||
stringstream ss;
|
||||
ss << "variable elimination [" ;
|
||||
ss << "elim_heuristic=" ;
|
||||
ElimHeuristic eh = ElimGraph::elimHeuristic;
|
||||
switch (eh) {
|
||||
case MIN_NEIGHBORS: ss << "min_neighbors"; break;
|
||||
case MIN_WEIGHT: ss << "min_weight"; break;
|
||||
case MIN_FILL: ss << "min_fill"; break;
|
||||
case WEIGHTED_MIN_FILL: ss << "weighted_min_fill"; break;
|
||||
}
|
||||
ss << ",log_domain=" << Util::toString (Globals::logDomain);
|
||||
ss << "]" ;
|
||||
cout << ss.str() << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
VarElimSolver::createFactorList (void)
|
||||
{
|
||||
const FacNodes& facNodes = fg.facNodes();
|
||||
factorList_.reserve (facNodes.size() * 2);
|
||||
for (unsigned i = 0; i < facNodes.size(); i++) {
|
||||
factorList_.push_back (new Factor (facNodes[i]->factor()));
|
||||
const VarNodes& neighs = facNodes[i]->neighbors();
|
||||
for (unsigned j = 0; j < neighs.size(); j++) {
|
||||
unordered_map<VarId,vector<unsigned> >::iterator it
|
||||
= varFactors_.find (neighs[j]->varId());
|
||||
if (it == varFactors_.end()) {
|
||||
it = varFactors_.insert (make_pair (
|
||||
neighs[j]->varId(), vector<unsigned>())).first;
|
||||
}
|
||||
it->second.push_back (i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
VarElimSolver::absorveEvidence (void)
|
||||
{
|
||||
if (Globals::verbosity > 2) {
|
||||
Util::printDashedLine();
|
||||
cout << "(initial factor list)" << endl;
|
||||
printActiveFactors();
|
||||
}
|
||||
const VarNodes& varNodes = fg.varNodes();
|
||||
for (unsigned i = 0; i < varNodes.size(); i++) {
|
||||
if (varNodes[i]->hasEvidence()) {
|
||||
if (Globals::verbosity > 1) {
|
||||
cout << "-> aborving evidence on ";
|
||||
cout << varNodes[i]->label() << " = " ;
|
||||
cout << varNodes[i]->getEvidence() << endl;
|
||||
}
|
||||
const vector<unsigned>& idxs =
|
||||
varFactors_.find (varNodes[i]->varId())->second;
|
||||
for (unsigned j = 0; j < idxs.size(); j++) {
|
||||
Factor* factor = factorList_[idxs[j]];
|
||||
if (factor->nrArguments() == 1) {
|
||||
factorList_[idxs[j]] = 0;
|
||||
} else {
|
||||
factorList_[idxs[j]]->absorveEvidence (
|
||||
varNodes[i]->varId(), varNodes[i]->getEvidence());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
VarElimSolver::findEliminationOrder (const VarIds& vids)
|
||||
{
|
||||
elimOrder_ = ElimGraph::getEliminationOrder (factorList_, vids);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
VarElimSolver::processFactorList (const VarIds& vids)
|
||||
{
|
||||
totalFactorSize_ = 0;
|
||||
largestFactorSize_ = 0;
|
||||
for (unsigned i = 0; i < elimOrder_.size(); i++) {
|
||||
if (Globals::verbosity >= 2) {
|
||||
if (Globals::verbosity >= 3) {
|
||||
Util::printDashedLine();
|
||||
printActiveFactors();
|
||||
}
|
||||
cout << "-> summing out " ;
|
||||
cout << fg.getVarNode (elimOrder_[i])->label() << endl;
|
||||
}
|
||||
eliminate (elimOrder_[i]);
|
||||
}
|
||||
|
||||
Factor* finalFactor = new Factor();
|
||||
for (unsigned i = 0; i < factorList_.size(); i++) {
|
||||
if (factorList_[i]) {
|
||||
finalFactor->multiply (*factorList_[i]);
|
||||
delete factorList_[i];
|
||||
factorList_[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
VarIds unobservedVids;
|
||||
for (unsigned i = 0; i < vids.size(); i++) {
|
||||
if (fg.getVarNode (vids[i])->hasEvidence() == false) {
|
||||
unobservedVids.push_back (vids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
finalFactor->reorderArguments (unobservedVids);
|
||||
finalFactor->normalize();
|
||||
factorList_.push_back (finalFactor);
|
||||
if (Globals::verbosity > 0) {
|
||||
cout << "total factor size: " << totalFactorSize_ << endl;
|
||||
cout << "largest factor size: " << largestFactorSize_ << endl;
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
VarElimSolver::eliminate (VarId elimVar)
|
||||
{
|
||||
Factor* result = 0;
|
||||
vector<unsigned>& idxs = varFactors_.find (elimVar)->second;
|
||||
for (unsigned i = 0; i < idxs.size(); i++) {
|
||||
unsigned idx = idxs[i];
|
||||
if (factorList_[idx]) {
|
||||
if (result == 0) {
|
||||
result = new Factor (*factorList_[idx]);
|
||||
} else {
|
||||
result->multiply (*factorList_[idx]);
|
||||
}
|
||||
delete factorList_[idx];
|
||||
factorList_[idx] = 0;
|
||||
}
|
||||
}
|
||||
totalFactorSize_ += result->size();
|
||||
if (result->size() > largestFactorSize_) {
|
||||
largestFactorSize_ = result->size();
|
||||
}
|
||||
if (result != 0 && result->nrArguments() != 1) {
|
||||
result->sumOut (elimVar);
|
||||
factorList_.push_back (result);
|
||||
const VarIds& resultVarIds = result->arguments();
|
||||
for (unsigned i = 0; i < resultVarIds.size(); i++) {
|
||||
vector<unsigned>& idxs =
|
||||
varFactors_.find (resultVarIds[i])->second;
|
||||
idxs.push_back (factorList_.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
VarElimSolver::printActiveFactors (void)
|
||||
{
|
||||
for (unsigned i = 0; i < factorList_.size(); i++) {
|
||||
if (factorList_[i] != 0) {
|
||||
cout << factorList_[i]->getLabel() << " " ;
|
||||
cout << factorList_[i]->params() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
46
packages/CLPBN/horus/VarElimSolver.h
Normal file
46
packages/CLPBN/horus/VarElimSolver.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef HORUS_VARELIMSOLVER_H
|
||||
#define HORUS_VARELIMSOLVER_H
|
||||
|
||||
#include "unordered_map"
|
||||
|
||||
#include "Solver.h"
|
||||
#include "FactorGraph.h"
|
||||
#include "Horus.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
class VarElimSolver : public Solver
|
||||
{
|
||||
public:
|
||||
VarElimSolver (const FactorGraph& fg) : Solver (fg) { }
|
||||
|
||||
~VarElimSolver (void);
|
||||
|
||||
Params solveQuery (VarIds);
|
||||
|
||||
void printSolverFlags (void) const;
|
||||
|
||||
private:
|
||||
void createFactorList (void);
|
||||
|
||||
void absorveEvidence (void);
|
||||
|
||||
void findEliminationOrder (const VarIds&);
|
||||
|
||||
void processFactorList (const VarIds&);
|
||||
|
||||
void eliminate (VarId);
|
||||
|
||||
void printActiveFactors (void);
|
||||
|
||||
Factors factorList_;
|
||||
VarIds elimOrder_;
|
||||
unsigned largestFactorSize_;
|
||||
unsigned totalFactorSize_;
|
||||
unordered_map<VarId, vector<unsigned>> varFactors_;
|
||||
};
|
||||
|
||||
#endif // HORUS_VARELIMSOLVER_H
|
||||
|
78
packages/CLPBN/horus/benchmarks/benchs.sh
Executable file
78
packages/CLPBN/horus/benchmarks/benchs.sh
Executable file
@ -0,0 +1,78 @@
|
||||
|
||||
|
||||
function prepare_new_run
|
||||
{
|
||||
YAP=~/bin/$SHORTNAME-$SOLVER
|
||||
|
||||
LOG_FILE=$SOLVER.log
|
||||
#LOG_FILE=results`date "+ %H:%M:%S %d-%m-%Y"`.
|
||||
|
||||
rm -f $LOG_FILE
|
||||
rm -f ignore.$LOG_FILE
|
||||
|
||||
cp ~/bin/yap $YAP
|
||||
}
|
||||
|
||||
|
||||
|
||||
function run_solver
|
||||
{
|
||||
constraint=$1
|
||||
solver_flag=true
|
||||
if [ -n "$2" ]; then
|
||||
if [ $SOLVER = hve ]; then
|
||||
solver_flag=clpbn_horus:set_horus_flag\(elim_heuristic,$2\)
|
||||
elif [ $SOLVER = bp ]; then
|
||||
solver_flag=clpbn_horus:set_horus_flag\(schedule,$2\)
|
||||
elif [ $SOLVER = cbp ]; then
|
||||
solver_flag=clpbn_horus:set_horus_flag\(schedule,$2\)
|
||||
else
|
||||
echo "unknow flag $2"
|
||||
fi
|
||||
fi
|
||||
/usr/bin/time -o $LOG_FILE -a -f "%U\t%S\t%e\t%M" \
|
||||
$YAP << EOF >> $LOG_FILE &>> ignore.$LOG_FILE
|
||||
nogc.
|
||||
[$NETWORK].
|
||||
[$constraint].
|
||||
clpbn_horus:set_solver($SOLVER).
|
||||
clpbn_horus:set_horus_flag(use_logarithms, true).
|
||||
clpbn_horus:set_horus_flag(verbosity, 1).
|
||||
$solver_flag.
|
||||
$QUERY.
|
||||
open("$LOG_FILE", 'append', S), format(S, '$constraint ~15+ ', []), close(S).
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
|
||||
function clear_log_files
|
||||
{
|
||||
rm -f *~
|
||||
rm -f ../*~
|
||||
rm -f school/*.log school/*~
|
||||
rm -f ../school/*.log ../school/*~
|
||||
rm -f city/*.log city/*~
|
||||
rm -f ../city/*.log ../city/*~
|
||||
rm -f workshop_attrs/*.log workshop_attrs/*~
|
||||
rm -f ../workshop_attrs/*.log ../workshop_attrs/*~
|
||||
echo all done!
|
||||
}
|
||||
|
||||
|
||||
|
||||
function write_header
|
||||
{
|
||||
echo -n "****************************************" >> $LOG_FILE
|
||||
echo "****************************************" >> $LOG_FILE
|
||||
echo "results for solver $1 user(s) sys(s) real(s), mem(kB)" >> $LOG_FILE
|
||||
echo -n "****************************************" >> $LOG_FILE
|
||||
echo "****************************************" >> $LOG_FILE
|
||||
}
|
||||
|
||||
|
||||
if [ $1 ] && [ $1 == "clean" ]; then
|
||||
clear_log_files
|
||||
fi
|
||||
|
||||
|
4
packages/CLPBN/horus/benchmarks/city/bp.log
Normal file
4
packages/CLPBN/horus/benchmarks/city/bp.log
Normal file
@ -0,0 +1,4 @@
|
||||
************************************************************************
|
||||
results for solver bp(shedule=seq_fixed)
|
||||
************************************************************************
|
||||
city1000: real:0:00.20 user:0.12 sys:0.02
|
37
packages/CLPBN/horus/benchmarks/city/bp_tests.sh
Executable file
37
packages/CLPBN/horus/benchmarks/city/bp_tests.sh
Executable file
@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
source city.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="bp"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver city1000 $2
|
||||
run_solver city5000 $2
|
||||
run_solver city10000 $2
|
||||
run_solver city15000 $2
|
||||
run_solver city20000 $2
|
||||
run_solver city25000 $2
|
||||
run_solver city30000 $2
|
||||
run_solver city35000 $2
|
||||
run_solver city40000 $2
|
||||
run_solver city45000 $2
|
||||
run_solver city50000 $2
|
||||
run_solver city55000 $2
|
||||
run_solver city60000 $2
|
||||
run_solver city65000 $2
|
||||
return
|
||||
run_solver city70000 $2
|
||||
run_solver city75000 $2
|
||||
run_solver city80000 $2
|
||||
run_solver city85000 $2
|
||||
run_solver city90000 $2
|
||||
run_solver city95000 $2
|
||||
run_solver city100000 $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "bp(shedule=seq_fixed) " seq_fixed
|
||||
|
36
packages/CLPBN/horus/benchmarks/city/cbp_tests.sh
Executable file
36
packages/CLPBN/horus/benchmarks/city/cbp_tests.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
source city.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="cbp"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver city1000 $2
|
||||
run_solver city5000 $2
|
||||
run_solver city10000 $2
|
||||
run_solver city15000 $2
|
||||
run_solver city20000 $2
|
||||
run_solver city25000 $2
|
||||
run_solver city30000 $2
|
||||
run_solver city35000 $2
|
||||
run_solver city40000 $2
|
||||
run_solver city45000 $2
|
||||
run_solver city50000 $2
|
||||
run_solver city55000 $2
|
||||
run_solver city60000 $2
|
||||
run_solver city65000 $2
|
||||
run_solver city70000 $2
|
||||
run_solver city75000 $2
|
||||
run_solver city80000 $2
|
||||
run_solver city85000 $2
|
||||
run_solver city90000 $2
|
||||
run_solver city95000 $2
|
||||
run_solver city100000 $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "cbp(shedule=seq_fixed) " seq_fixed
|
||||
|
6
packages/CLPBN/horus/benchmarks/city/city.sh
Executable file
6
packages/CLPBN/horus/benchmarks/city/city.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
NETWORK="'../../examples/city'"
|
||||
SHORTNAME="city"
|
||||
QUERY="is_joe_guilty(X)"
|
||||
|
36
packages/CLPBN/horus/benchmarks/city/fove_tests.sh
Executable file
36
packages/CLPBN/horus/benchmarks/city/fove_tests.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
source city.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="fove"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver city1000 $2
|
||||
run_solver city5000 $2
|
||||
run_solver city10000 $2
|
||||
run_solver city15000 $2
|
||||
run_solver city20000 $2
|
||||
run_solver city25000 $2
|
||||
run_solver city30000 $2
|
||||
run_solver city35000 $2
|
||||
run_solver city40000 $2
|
||||
run_solver city45000 $2
|
||||
run_solver city50000 $2
|
||||
run_solver city55000 $2
|
||||
run_solver city60000 $2
|
||||
run_solver city65000 $2
|
||||
run_solver city70000 $2
|
||||
run_solver city75000 $2
|
||||
run_solver city80000 $2
|
||||
run_solver city85000 $2
|
||||
run_solver city90000 $2
|
||||
run_solver city95000 $2
|
||||
run_solver city100000 $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "fove "
|
||||
|
33
packages/CLPBN/horus/benchmarks/city/gen_city.sh
Executable file
33
packages/CLPBN/horus/benchmarks/city/gen_city.sh
Executable file
@ -0,0 +1,33 @@
|
||||
#! /home/tgomes/bin/yap -L --
|
||||
|
||||
|
||||
:- initialization(main).
|
||||
|
||||
|
||||
main :-
|
||||
unix(argv([N])),
|
||||
atomic_concat(['city', N, '.yap'], FileName),
|
||||
open(FileName, 'write', S),
|
||||
atom_number(N, N2),
|
||||
generate_people(S, N2, 1),
|
||||
write(S, '\n'),
|
||||
generate_evidence(S, N2, 1),
|
||||
write(S, '\n'),
|
||||
close(S).
|
||||
|
||||
|
||||
generate_people(S, N, Counting) :-
|
||||
Counting > N, !.
|
||||
generate_people(S, N, Counting) :-
|
||||
format(S, 'people(p~w, nyc).~n', [Counting]),
|
||||
Counting1 is Counting + 1,
|
||||
generate_people(S, N, Counting1).
|
||||
|
||||
|
||||
generate_evidence(S, N, Counting) :-
|
||||
Counting > N, !.
|
||||
generate_evidence(S, N, Counting) :- !,
|
||||
format(S, 'ev(descn(p~w, t)).~n', [Counting]),
|
||||
Counting1 is Counting + 1,
|
||||
generate_evidence(S, N, Counting1).
|
||||
|
37
packages/CLPBN/horus/benchmarks/city/hve_tests.sh
Executable file
37
packages/CLPBN/horus/benchmarks/city/hve_tests.sh
Executable file
@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
source city.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="hve"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver city1000 $2
|
||||
run_solver city5000 $2
|
||||
run_solver city10000 $2
|
||||
run_solver city15000 $2
|
||||
run_solver city20000 $2
|
||||
run_solver city25000 $2
|
||||
run_solver city30000 $2
|
||||
run_solver city35000 $2
|
||||
run_solver city40000 $2
|
||||
run_solver city45000 $2
|
||||
run_solver city50000 $2
|
||||
run_solver city55000 $2
|
||||
run_solver city60000 $2
|
||||
run_solver city65000 $2
|
||||
run_solver city70000 $2
|
||||
|
||||
run_solver city75000 $2
|
||||
run_solver city80000 $2
|
||||
run_solver city85000 $2
|
||||
run_solver city90000 $2
|
||||
run_solver city95000 $2
|
||||
run_solver city100000 $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "hve(elim_heuristic=min_neighbors) " min_neighbors
|
||||
|
96
packages/CLPBN/horus/benchmarks/city/ignore.bp.log
Normal file
96
packages/CLPBN/horus/benchmarks/city/ignore.bp.log
Normal file
@ -0,0 +1,96 @@
|
||||
YAP 6.3.2 (i686-linux): Sáb Abr 28 13:56:07 WEST 2012
|
||||
yes
|
||||
% consulting /home/tiago/yap-6.3/packages/CLPBN/clpbn/bp/examples/city.yap...
|
||||
% reconsulting /home/tiago/share/Yap/pfl.yap...
|
||||
% reconsulting /home/tiago/share/Yap/lists.yap...
|
||||
% reconsulting /home/tiago/share/Yap/error.pl...
|
||||
% reconsulted /home/tiago/share/Yap/error.pl in module error, 4 msec 27448 bytes
|
||||
% reconsulted /home/tiago/share/Yap/lists.yap in module lists, 4 msec 60536 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn.yap...
|
||||
% reconsulting /home/tiago/share/Yap/atts.yap...
|
||||
% reconsulted /home/tiago/share/Yap/atts.yap in module attributes, 0 msec 22808 bytes
|
||||
% reconsulting /home/tiago/share/Yap/terms.yap...
|
||||
% reconsulted /home/tiago/share/Yap/terms.yap in module terms, 0 msec 1480 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/ve.yap...
|
||||
% reconsulting /home/tiago/share/Yap/ordsets.yap...
|
||||
% reconsulted /home/tiago/share/Yap/ordsets.yap in module ordsets, 4 msec 23928 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/xbif.yap...
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/dists.yap...
|
||||
% reconsulting /home/tiago/share/Yap/matrix.yap...
|
||||
% reconsulted /home/tiago/share/Yap/matrix.yap in module matrix, 0 msec 20608 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/matrix_cpt_utils.yap...
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/matrix_cpt_utils.yap in module clpbn_matrix_utils, 0 msec 33504 bytes
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/dists.yap in module clpbn_dist, 4 msec 97560 bytes
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/xbif.yap in module xbif, 4 msec 109176 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/graphviz.yap...
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/graphviz.yap in module clpbn_gviz, 0 msec 7784 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/utils.yap...
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/utils.yap in module clpbn_utils, 0 msec 13912 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/display.yap...
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/display.yap in module clpbn_display, 0 msec 11232 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/connected.yap...
|
||||
% reconsulting /home/tiago/share/Yap/dgraphs.yap...
|
||||
% reconsulting /home/tiago/share/Yap/rbtrees.yap...
|
||||
% reconsulted /home/tiago/share/Yap/rbtrees.yap in module rbtrees, 8 msec 117496 bytes
|
||||
% reconsulting /home/tiago/share/Yap/wdgraphs.yap...
|
||||
% reconsulting /home/tiago/share/Yap/heaps.yap...
|
||||
% reconsulted /home/tiago/share/Yap/heaps.yap in module heaps, 4 msec 13520 bytes
|
||||
% reconsulted /home/tiago/share/Yap/wdgraphs.yap in module wdgraphs, 4 msec 72176 bytes
|
||||
% reconsulted /home/tiago/share/Yap/dgraphs.yap in module dgraphs, 16 msec 243240 bytes
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/connected.yap in module clpbn_connected, 16 msec 261736 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/aggregates.yap...
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/aggregates.yap in module clpbn_aggregates, 0 msec 36512 bytes
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/ve.yap in module clpbn_ve, 36 msec 500808 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/bp.yap...
|
||||
% reconsulting /home/tiago/share/Yap/charsio.yap...
|
||||
% reconsulted /home/tiago/share/Yap/charsio.yap in module charsio, 0 msec 10592 bytes
|
||||
% reconsulting /home/tiago/share/Yap/bhash.yap...
|
||||
% reconsulted /home/tiago/share/Yap/bhash.yap in module b_hash, 0 msec 30624 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/horus.yap...
|
||||
% Warning: (/home/tiago/share/Yap/clpbn/horus.yap:23).
|
||||
% Importing private predicate pfl:set_pfl_flag/2 to clpbn_horus.
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/horus.yap in module clpbn_horus, 4 msec 14248 bytes
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/bp.yap in module clpbn_bp, 8 msec 87944 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/fove.yap...
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/fove.yap in module clpbn_fove, 4 msec 17464 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/jt.yap...
|
||||
% reconsulting /home/tiago/share/Yap/undgraphs.yap...
|
||||
% reconsulting /home/tiago/share/Yap/wundgraphs.yap...
|
||||
% reconsulted /home/tiago/share/Yap/wundgraphs.yap in module wundgraphs, 4 msec 37816 bytes
|
||||
% reconsulted /home/tiago/share/Yap/undgraphs.yap in module undgraphs, 8 msec 66048 bytes
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/jt.yap in module jt, 12 msec 143960 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/bdd.yap...
|
||||
% reconsulting /home/tiago/share/Yap/hacks.yap...
|
||||
% reconsulted /home/tiago/share/Yap/hacks.yap in module yap_hacks, 0 msec 4968 bytes
|
||||
ERROR!! (/home/tiago/share/Yap/clpbn/bdd.yap:54).
|
||||
PERMISSION ERROR- use_module(library(bdd)): cannot read from library(bdd)
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/bdd.yap in module clpbn_bdd, 8 msec 152336 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/gibbs.yap...
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/topsort.yap...
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/topsort.yap in module topsort, 0 msec 5848 bytes
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/gibbs.yap in module clpbn_gibbs, 0 msec 79344 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/pgrammar.yap...
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/pgrammar.yap in module clpbn_pgrammar, 4 msec 44088 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/graphs.yap...
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/graphs.yap in module clpbn2graph, 0 msec 8408 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/evidence.yap...
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/evidence.yap in module clpbn_evidence, 4 msec 21256 bytes
|
||||
% reconsulting /home/tiago/share/Yap/clpbn/ground_factors.yap...
|
||||
% reconsulted /home/tiago/share/Yap/clpbn/ground_factors.yap in module clpbn_ground_factors, 4 msec 16360 bytes
|
||||
% reconsulted /home/tiago/share/Yap/clpbn.yap in module clpbn, 92 msec 1188576 bytes
|
||||
% reconsulted /home/tiago/share/Yap/pfl.yap in module pfl, 96 msec 1277856 bytes
|
||||
% consulted /home/tiago/yap-6.3/packages/CLPBN/clpbn/bp/examples/city.yap in module user, 96 msec 1313552 bytes
|
||||
yes
|
||||
ERROR!!
|
||||
PERMISSION ERROR- consult(city1000): cannot read from city1000
|
||||
yes
|
||||
yes
|
||||
yes
|
||||
yes
|
||||
belief propagation [schedule=seq_fixed,max_iter=1000,accuracy=0.0001,log_domain=true]
|
||||
|
||||
Sum-Product converged in 6 iterations
|
||||
|
||||
p(X=y)= 0.2383192848945889,
|
||||
p(X=n)= 0.761680715105411
|
||||
S = '<stream>'(0xa0288d8)
|
31
packages/CLPBN/horus/benchmarks/comp_workshops/bp_tests.sh
Executable file
31
packages/CLPBN/horus/benchmarks/comp_workshops/bp_tests.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
|
||||
source cw.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="bp"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver p1000w$N_WORKSHOPS $2
|
||||
run_solver p5000w$N_WORKSHOPS $2
|
||||
run_solver p10000w$N_WORKSHOPS $2
|
||||
run_solver p15000w$N_WORKSHOPS $2
|
||||
run_solver p20000w$N_WORKSHOPS $2
|
||||
run_solver p25000w$N_WORKSHOPS $2
|
||||
return
|
||||
run_solver p30000w$N_WORKSHOPS $2
|
||||
run_solver p35000w$N_WORKSHOPS $2
|
||||
run_solver p40000w$N_WORKSHOPS $2
|
||||
run_solver p45000w$N_WORKSHOPS $2
|
||||
run_solver p50000w$N_WORKSHOPS $2
|
||||
run_solver p55000w$N_WORKSHOPS $2
|
||||
run_solver p60000w$N_WORKSHOPS $2
|
||||
run_solver p65000w$N_WORKSHOPS $2
|
||||
run_solver p70000w$N_WORKSHOPS $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "bp(shedule=seq_fixed) " seq_fixed
|
||||
|
30
packages/CLPBN/horus/benchmarks/comp_workshops/cbp_tests.sh
Executable file
30
packages/CLPBN/horus/benchmarks/comp_workshops/cbp_tests.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
source cw.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="cbp"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver p1000w$N_WORKSHOPS $2
|
||||
run_solver p5000w$N_WORKSHOPS $2
|
||||
run_solver p10000w$N_WORKSHOPS $2
|
||||
run_solver p15000w$N_WORKSHOPS $2
|
||||
run_solver p20000w$N_WORKSHOPS $2
|
||||
run_solver p25000w$N_WORKSHOPS $2
|
||||
run_solver p30000w$N_WORKSHOPS $2
|
||||
run_solver p35000w$N_WORKSHOPS $2
|
||||
run_solver p40000w$N_WORKSHOPS $2
|
||||
run_solver p45000w$N_WORKSHOPS $2
|
||||
run_solver p50000w$N_WORKSHOPS $2
|
||||
run_solver p55000w$N_WORKSHOPS $2
|
||||
run_solver p60000w$N_WORKSHOPS $2
|
||||
run_solver p65000w$N_WORKSHOPS $2
|
||||
run_solver p70000w$N_WORKSHOPS $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "cbp(shedule=seq_fixed) " seq_fixed
|
||||
|
8
packages/CLPBN/horus/benchmarks/comp_workshops/cw.sh
Executable file
8
packages/CLPBN/horus/benchmarks/comp_workshops/cw.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
NETWORK="'../../examples/comp_workshops'"
|
||||
SHORTNAME="cw"
|
||||
QUERY="series(X)"
|
||||
|
||||
N_WORKSHOPS=10
|
||||
|
31
packages/CLPBN/horus/benchmarks/comp_workshops/fove_tests.sh
Executable file
31
packages/CLPBN/horus/benchmarks/comp_workshops/fove_tests.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
|
||||
source cw.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="fove"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver p1000w$N_WORKSHOPS $2
|
||||
run_solver p5000w$N_WORKSHOPS $2
|
||||
run_solver p10000w$N_WORKSHOPS $2
|
||||
run_solver p15000w$N_WORKSHOPS $2
|
||||
run_solver p20000w$N_WORKSHOPS $2
|
||||
run_solver p25000w$N_WORKSHOPS $2
|
||||
run_solver p30000w$N_WORKSHOPS $2
|
||||
run_solver p35000w$N_WORKSHOPS $2
|
||||
run_solver p40000w$N_WORKSHOPS $2
|
||||
run_solver p45000w$N_WORKSHOPS $2
|
||||
run_solver p50000w$N_WORKSHOPS $2
|
||||
run_solver p55000w$N_WORKSHOPS $2
|
||||
run_solver p60000w$N_WORKSHOPS $2
|
||||
run_solver p65000w$N_WORKSHOPS $2
|
||||
run_solver p70000w$N_WORKSHOPS $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "fove "
|
||||
|
||||
|
35
packages/CLPBN/horus/benchmarks/comp_workshops/gen_workshops.sh
Executable file
35
packages/CLPBN/horus/benchmarks/comp_workshops/gen_workshops.sh
Executable file
@ -0,0 +1,35 @@
|
||||
#!/home/tgomes/bin/yap -L --
|
||||
|
||||
:- use_module(library(lists)).
|
||||
|
||||
:- initialization(main).
|
||||
|
||||
|
||||
main :-
|
||||
unix(argv(Args)),
|
||||
nth(1, Args, NP), % number of invitees
|
||||
nth(2, Args, NW), % number of workshops
|
||||
atomic_concat(['p', NP , 'w', NW, '.yap'], FileName),
|
||||
open(FileName, 'write', S),
|
||||
atom_number(NP, NP2),
|
||||
atom_number(NW, NW2),
|
||||
gen(S, NP2, NW2, 1),
|
||||
write(S, '\n'),
|
||||
close(S).
|
||||
|
||||
|
||||
gen(_, NP, _, Count) :-
|
||||
Count > NP, !.
|
||||
gen(S, NP, NW, Count) :-
|
||||
gen_workshops(S, Count, NW, 1),
|
||||
Count1 is Count + 1,
|
||||
gen(S, NP, NW, Count1).
|
||||
|
||||
|
||||
gen_workshops(_, _, NW, Count) :-
|
||||
Count > NW, !.
|
||||
gen_workshops(S, P, NW, Count) :-
|
||||
format(S, 'c(p~w,w~w).~n', [P,Count]),
|
||||
Count1 is Count + 1,
|
||||
gen_workshops(S, P, NW, Count1).
|
||||
|
30
packages/CLPBN/horus/benchmarks/comp_workshops/hve_tests.sh
Executable file
30
packages/CLPBN/horus/benchmarks/comp_workshops/hve_tests.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
source cw.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="hve"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver p1000w$N_WORKSHOPS $2
|
||||
run_solver p5000w$N_WORKSHOPS $2
|
||||
run_solver p10000w$N_WORKSHOPS $2
|
||||
run_solver p15000w$N_WORKSHOPS $2
|
||||
run_solver p20000w$N_WORKSHOPS $2
|
||||
run_solver p25000w$N_WORKSHOPS $2
|
||||
run_solver p30000w$N_WORKSHOPS $2
|
||||
run_solver p35000w$N_WORKSHOPS $2
|
||||
run_solver p40000w$N_WORKSHOPS $2
|
||||
run_solver p45000w$N_WORKSHOPS $2
|
||||
run_solver p50000w$N_WORKSHOPS $2
|
||||
run_solver p55000w$N_WORKSHOPS $2
|
||||
run_solver p60000w$N_WORKSHOPS $2
|
||||
run_solver p65000w$N_WORKSHOPS $2
|
||||
run_solver p70000w$N_WORKSHOPS $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "hve(elim_heuristic=min_neighbors) " min_neighbors
|
||||
|
1
packages/CLPBN/horus/benchmarks/school/missing10.yap
Normal file
1
packages/CLPBN/horus/benchmarks/school/missing10.yap
Normal file
File diff suppressed because one or more lines are too long
1
packages/CLPBN/horus/benchmarks/school/missing20.yap
Normal file
1
packages/CLPBN/horus/benchmarks/school/missing20.yap
Normal file
File diff suppressed because one or more lines are too long
1
packages/CLPBN/horus/benchmarks/school/missing30.yap
Normal file
1
packages/CLPBN/horus/benchmarks/school/missing30.yap
Normal file
File diff suppressed because one or more lines are too long
1
packages/CLPBN/horus/benchmarks/school/missing40.yap
Normal file
1
packages/CLPBN/horus/benchmarks/school/missing40.yap
Normal file
File diff suppressed because one or more lines are too long
1
packages/CLPBN/horus/benchmarks/school/missing5.yap
Normal file
1
packages/CLPBN/horus/benchmarks/school/missing5.yap
Normal file
File diff suppressed because one or more lines are too long
1
packages/CLPBN/horus/benchmarks/school/missing50.yap
Normal file
1
packages/CLPBN/horus/benchmarks/school/missing50.yap
Normal file
File diff suppressed because one or more lines are too long
95
packages/CLPBN/horus/benchmarks/school/run_school_tests.sh
Executable file
95
packages/CLPBN/horus/benchmarks/school/run_school_tests.sh
Executable file
@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
|
||||
#cp ~/bin/yap ~/bin/school_all
|
||||
#YAP=~/bin/school_all
|
||||
YAP=~/bin/yap
|
||||
|
||||
#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log
|
||||
OUT_FILE_NAME=results.log
|
||||
rm -f $OUT_FILE_NAME
|
||||
rm -f ignore.$OUT_FILE_NAME
|
||||
|
||||
# yap -g "['../../../../examples/School/sch32'], [missing5], use_module(library(clpbn/learning/em)), graph(L), clpbn:set_clpbn_flag(em_solver,bp), clpbn_horus:set_horus_flag(inf_alg, bp), statistics(runtime, _), em(L,0.01,10,_,Lik), statistics(runtime, [T,_])."
|
||||
|
||||
function run_solver
|
||||
{
|
||||
if [ $2 = bp ]
|
||||
then
|
||||
if [ $4 = ve ]
|
||||
then
|
||||
extra_flag1=clpbn_horus:set_horus_flag\(inf_alg,$4\)
|
||||
extra_flag2=clpbn_horus:set_horus_flag\(elim_heuristic,$5\)
|
||||
else
|
||||
extra_flag1=clpbn_horus:set_horus_flag\(inf_alg,$4\)
|
||||
extra_flag2=clpbn_horus:set_horus_flag\(schedule,$5\)
|
||||
fi
|
||||
else
|
||||
extra_flag1=true
|
||||
extra_flag2=true
|
||||
fi
|
||||
/usr/bin/time -o "$OUT_FILE_NAME" -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF &>> "ignore.$OUT_FILE_NAME"
|
||||
:- [pos:train].
|
||||
:- ['../../../../examples/School/sch32'].
|
||||
:- use_module(library(clpbn/learning/em)).
|
||||
:- use_module(library(clpbn/bp)).
|
||||
[$1].
|
||||
graph(L),
|
||||
clpbn:set_clpbn_flag(em_solver,$2),
|
||||
$extra_flag1, $extra_flag2,
|
||||
em(L,0.01,10,_,Lik),
|
||||
open("$OUT_FILE_NAME", 'append',S),
|
||||
format(S, '$3: ~11+ Lik = ~3f, ',[Lik]),
|
||||
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 missing5 $1 missing5 $3 $4 $5
|
||||
run_solver missing10 $1 missing10 $3 $4 $5
|
||||
#run_solver missing20 $1 missing20 $3 $4 $5
|
||||
#run_solver missing30 $1 missing30 $3 $4 $5
|
||||
#run_solver missing40 $1 missing40 $3 $4 $5
|
||||
#run_solver missing50 $1 missing50 $3 $4 $5
|
||||
}
|
||||
|
||||
|
||||
#run_all_graphs bp "hve(min_neighbors) " ve min_neighbors
|
||||
#run_all_graphs bp "bp(seq_fixed) " bp seq_fixed
|
||||
#run_all_graphs bp "cbp(seq_fixed) " cbp seq_fixed
|
||||
exit
|
||||
|
||||
|
||||
run_all_graphs bp "hve(min_neighbors) " ve min_neighbors
|
||||
run_all_graphs bp "hve(min_weight) " ve min_weight
|
||||
run_all_graphs bp "hve(min_fill) " ve min_fill
|
||||
run_all_graphs bp "hve(w_min_fill) " ve weighted_min_fill
|
||||
run_all_graphs bp "bp(seq_fixed) " bp seq_fixed
|
||||
run_all_graphs bp "bp(max_residual) " bp max_residual
|
||||
run_all_graphs bp "cbp(seq_fixed) " cbp seq_fixed
|
||||
run_all_graphs bp "cbp(max_residual) " cbp max_residual
|
||||
run_all_graphs gibbs "gibbs "
|
||||
echo "************************************************************************" >> "$OUT_FILE_NAME"
|
||||
echo "results for solver ve" >> "$OUT_FILE_NAME"
|
||||
echo "************************************************************************" >> "$OUT_FILE_NAME"
|
||||
run_solver missing5 ve missing5 $3 $4 $5
|
||||
run_solver missing10 ve missing10 $3 $4 $5
|
||||
run_solver missing20 ve missing20 $3 $4 $5
|
||||
run_solver missing30 ve missing30 $3 $4 $5
|
||||
run_solver missing40 ve missing40 $3 $4 $5
|
||||
#run_solver missing50 ve missing50 $3 $4 $5 #+24h!
|
||||
echo "************************************************************************" >> "$OUT_FILE_NAME"
|
||||
echo "results for solver jt" >> "$OUT_FILE_NAME"
|
||||
echo "************************************************************************" >> "$OUT_FILE_NAME"
|
||||
run_solver missing5 jt missing5 $3 $4 $5
|
||||
run_solver missing10 jt missing10 $3 $4 $5
|
||||
run_solver missing20 jt missing20 $3 $4 $5
|
||||
#run_solver missing30 jt missing30 $3 $4 $5 #+24h!
|
||||
#run_solver missing40 jt missing40 $3 $4 $5 #+24h!
|
||||
#run_solver missing50 jt missing50 $3 $4 $5 #+24h!
|
||||
exit
|
||||
|
30
packages/CLPBN/horus/benchmarks/smokers/bp_tests.sh
Executable file
30
packages/CLPBN/horus/benchmarks/smokers/bp_tests.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
source sm.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="bp"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver pop100 $2
|
||||
run_solver pop200 $2
|
||||
run_solver pop300 $2
|
||||
run_solver pop400 $2
|
||||
run_solver pop500 $2
|
||||
run_solver pop600 $2
|
||||
run_solver pop700 $2
|
||||
run_solver pop800 $2
|
||||
run_solver pop900 $2
|
||||
run_solver pop1000 $2
|
||||
run_solver pop1100 $2
|
||||
run_solver pop1200 $2
|
||||
run_solver pop1300 $2
|
||||
run_solver pop1400 $2
|
||||
run_solver pop1500 $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "bp(shedule=seq_fixed) " seq_fixed
|
||||
|
30
packages/CLPBN/horus/benchmarks/smokers/cbp_tests.sh
Executable file
30
packages/CLPBN/horus/benchmarks/smokers/cbp_tests.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
source sm.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="cbp"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver pop100 $2
|
||||
run_solver pop200 $2
|
||||
run_solver pop300 $2
|
||||
run_solver pop400 $2
|
||||
run_solver pop500 $2
|
||||
run_solver pop600 $2
|
||||
run_solver pop700 $2
|
||||
run_solver pop800 $2
|
||||
run_solver pop900 $2
|
||||
run_solver pop1000 $2
|
||||
run_solver pop1100 $2
|
||||
run_solver pop1200 $2
|
||||
run_solver pop1300 $2
|
||||
run_solver pop1400 $2
|
||||
run_solver pop1500 $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "cbp(shedule=seq_fixed) " seq_fixed
|
||||
|
31
packages/CLPBN/horus/benchmarks/smokers/fove_tests.sh
Executable file
31
packages/CLPBN/horus/benchmarks/smokers/fove_tests.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
|
||||
source sm.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="fove"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver pop100 $2
|
||||
run_solver pop200 $2
|
||||
run_solver pop300 $2
|
||||
run_solver pop400 $2
|
||||
run_solver pop500 $2
|
||||
run_solver pop600 $2
|
||||
run_solver pop700 $2
|
||||
run_solver pop800 $2
|
||||
run_solver pop900 $2
|
||||
run_solver pop1000 $2
|
||||
run_solver pop1100 $2
|
||||
run_solver pop1200 $2
|
||||
run_solver pop1300 $2
|
||||
run_solver pop1400 $2
|
||||
run_solver pop1500 $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "fove "
|
||||
|
||||
|
23
packages/CLPBN/horus/benchmarks/smokers/gen_people.sh
Executable file
23
packages/CLPBN/horus/benchmarks/smokers/gen_people.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/home/tgomes/bin/yap -L --
|
||||
|
||||
|
||||
:- initialization(main).
|
||||
|
||||
|
||||
main :-
|
||||
unix(argv([N])),
|
||||
atomic_concat(['pop', N, '.yap'], FileName),
|
||||
open(FileName, 'write', S),
|
||||
atom_number(N, N2),
|
||||
generate_people(S, N2, 4),
|
||||
write(S, '\n'),
|
||||
close(S).
|
||||
|
||||
|
||||
generate_people(S, N, Counting) :-
|
||||
Counting > N, !.
|
||||
generate_people(S, N, Counting) :-
|
||||
format(S, 'people(p~w).~n', [Counting]),
|
||||
Counting1 is Counting + 1,
|
||||
generate_people(S, N, Counting1).
|
||||
|
33
packages/CLPBN/horus/benchmarks/smokers/hve_tests.sh
Executable file
33
packages/CLPBN/horus/benchmarks/smokers/hve_tests.sh
Executable file
@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
|
||||
source sm.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="hve"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver pop100 $2
|
||||
#run_solver pop200 $2
|
||||
#run_solver pop300 $2
|
||||
#run_solver pop400 $2
|
||||
#run_solver pop500 $2
|
||||
#run_solver pop600 $2
|
||||
#run_solver pop700 $2
|
||||
#run_solver pop800 $2
|
||||
#run_solver pop900 $2
|
||||
#run_solver pop1000 $2
|
||||
#run_solver pop1100 $2
|
||||
#run_solver pop1200 $2
|
||||
#run_solver pop1300 $2
|
||||
#run_solver pop1400 $2
|
||||
#run_solver pop1500 $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "hve(elim_heuristic=min_neighbors) " min_neighbors
|
||||
#run_all_graphs "hve(elim_heuristic=min_weight) " min_weight
|
||||
#run_all_graphs "hve(elim_heuristic=min_fill) " min_fill
|
||||
#run_all_graphs "hve(elim_heuristic=weighted_min_fill) " weighted_min_fill
|
||||
|
6
packages/CLPBN/horus/benchmarks/smokers/sm.sh
Executable file
6
packages/CLPBN/horus/benchmarks/smokers/sm.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
NETWORK="'../../examples/smokers2'"
|
||||
SHORTNAME="sm"
|
||||
QUERY="smokes(p1,t), smokes(p2,t), friends(p1,p2,X)"
|
||||
|
37
packages/CLPBN/horus/benchmarks/workshop_attrs/bp_tests.sh
Executable file
37
packages/CLPBN/horus/benchmarks/workshop_attrs/bp_tests.sh
Executable file
@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
source wa.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="bp"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver p1000attrs$N_ATTRS $2
|
||||
run_solver p5000attrs$N_ATTRS $2
|
||||
run_solver p10000attrs$N_ATTRS $2
|
||||
run_solver p15000attrs$N_ATTRS $2
|
||||
run_solver p20000attrs$N_ATTRS $2
|
||||
run_solver p25000attrs$N_ATTRS $2
|
||||
run_solver p30000attrs$N_ATTRS $2
|
||||
run_solver p35000attrs$N_ATTRS $2
|
||||
return
|
||||
run_solver p40000attrs$N_ATTRS $2
|
||||
run_solver p45000attrs$N_ATTRS $2
|
||||
run_solver p50000attrs$N_ATTRS $2
|
||||
run_solver p55000attrs$N_ATTRS $2
|
||||
run_solver p60000attrs$N_ATTRS $2
|
||||
run_solver p65000attrs$N_ATTRS $2
|
||||
run_solver p70000attrs$N_ATTRS $2
|
||||
run_solver p75000attrs$N_ATTRS $2
|
||||
run_solver p80000attrs$N_ATTRS $2
|
||||
run_solver p85000attrs$N_ATTRS $2
|
||||
run_solver p90000attrs$N_ATTRS $2
|
||||
run_solver p95000attrs$N_ATTRS $2
|
||||
run_solver p100000attrs$N_ATTRS $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "bp(shedule=seq_fixed) " seq_fixed
|
||||
|
36
packages/CLPBN/horus/benchmarks/workshop_attrs/cbp_tests.sh
Executable file
36
packages/CLPBN/horus/benchmarks/workshop_attrs/cbp_tests.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
source wa.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="cbp"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver p1000attrs$N_ATTRS $2
|
||||
run_solver p5000attrs$N_ATTRS $2
|
||||
run_solver p10000attrs$N_ATTRS $2
|
||||
run_solver p15000attrs$N_ATTRS $2
|
||||
run_solver p20000attrs$N_ATTRS $2
|
||||
run_solver p25000attrs$N_ATTRS $2
|
||||
run_solver p30000attrs$N_ATTRS $2
|
||||
run_solver p35000attrs$N_ATTRS $2
|
||||
run_solver p40000attrs$N_ATTRS $2
|
||||
run_solver p45000attrs$N_ATTRS $2
|
||||
run_solver p50000attrs$N_ATTRS $2
|
||||
run_solver p55000attrs$N_ATTRS $2
|
||||
run_solver p60000attrs$N_ATTRS $2
|
||||
run_solver p65000attrs$N_ATTRS $2
|
||||
run_solver p70000attrs$N_ATTRS $2
|
||||
run_solver p75000attrs$N_ATTRS $2
|
||||
run_solver p80000attrs$N_ATTRS $2
|
||||
run_solver p85000attrs$N_ATTRS $2
|
||||
run_solver p90000attrs$N_ATTRS $2
|
||||
run_solver p95000attrs$N_ATTRS $2
|
||||
run_solver p100000attrs$N_ATTRS $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "cbp(shedule=seq_fixed) " seq_fixed
|
||||
|
37
packages/CLPBN/horus/benchmarks/workshop_attrs/fove_tests.sh
Executable file
37
packages/CLPBN/horus/benchmarks/workshop_attrs/fove_tests.sh
Executable file
@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
source wa.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="fove"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver p1000attrs$N_ATTRS $2
|
||||
run_solver p5000attrs$N_ATTRS $2
|
||||
run_solver p10000attrs$N_ATTRS $2
|
||||
run_solver p15000attrs$N_ATTRS $2
|
||||
run_solver p20000attrs$N_ATTRS $2
|
||||
run_solver p25000attrs$N_ATTRS $2
|
||||
run_solver p30000attrs$N_ATTRS $2
|
||||
run_solver p35000attrs$N_ATTRS $2
|
||||
run_solver p40000attrs$N_ATTRS $2
|
||||
run_solver p45000attrs$N_ATTRS $2
|
||||
run_solver p50000attrs$N_ATTRS $2
|
||||
run_solver p55000attrs$N_ATTRS $2
|
||||
run_solver p60000attrs$N_ATTRS $2
|
||||
run_solver p65000attrs$N_ATTRS $2
|
||||
run_solver p70000attrs$N_ATTRS $2
|
||||
run_solver p75000attrs$N_ATTRS $2
|
||||
run_solver p80000attrs$N_ATTRS $2
|
||||
run_solver p85000attrs$N_ATTRS $2
|
||||
run_solver p90000attrs$N_ATTRS $2
|
||||
run_solver p95000attrs$N_ATTRS $2
|
||||
run_solver p100000attrs$N_ATTRS $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "fove "
|
||||
|
||||
|
39
packages/CLPBN/horus/benchmarks/workshop_attrs/gen_attrs.sh
Executable file
39
packages/CLPBN/horus/benchmarks/workshop_attrs/gen_attrs.sh
Executable file
@ -0,0 +1,39 @@
|
||||
#!/home/tgomes/bin/yap -L --
|
||||
|
||||
:- use_module(library(lists)).
|
||||
|
||||
:- initialization(main).
|
||||
|
||||
|
||||
main :-
|
||||
unix(argv(Args)),
|
||||
nth(1, Args, NP), % number of invitees
|
||||
nth(2, Args, NA), % number of attributes
|
||||
atomic_concat(['p', NP , 'attrs', NA, '.yap'], FileName),
|
||||
open(FileName, 'write', S),
|
||||
atom_number(NP, NP2),
|
||||
atom_number(NA, NA2),
|
||||
generate_people(S, NP2, 1),
|
||||
write(S, '\n'),
|
||||
generate_attrs(S, NA2, 7),
|
||||
write(S, '\n'),
|
||||
close(S).
|
||||
|
||||
|
||||
generate_people(S, N, Counting) :-
|
||||
Counting > N, !.
|
||||
generate_people(S, N, Counting) :-
|
||||
format(S, 'people(p~w).~n', [Counting]),
|
||||
Counting1 is Counting + 1,
|
||||
generate_people(S, N, Counting1).
|
||||
|
||||
|
||||
generate_attrs(S, N, Counting) :-
|
||||
Counting > N, !.
|
||||
generate_attrs(S, N, Counting) :-
|
||||
%format(S, 'people(p~w).~n', [Counting]),
|
||||
format(S, 'markov attends(P)::[t,f], attr~w::[t,f]', [Counting]),
|
||||
format(S, '; [0.7, 0.3, 0.3, 0.3] ; [people(P)].~n',[]),
|
||||
Counting1 is Counting + 1,
|
||||
generate_attrs(S, N, Counting1).
|
||||
|
36
packages/CLPBN/horus/benchmarks/workshop_attrs/hve_tests.sh
Executable file
36
packages/CLPBN/horus/benchmarks/workshop_attrs/hve_tests.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
source wa.sh
|
||||
source ../benchs.sh
|
||||
|
||||
SOLVER="hve"
|
||||
|
||||
function run_all_graphs
|
||||
{
|
||||
write_header $1
|
||||
run_solver p1000attrs$N_ATTRS $2
|
||||
run_solver p5000attrs$N_ATTRS $2
|
||||
run_solver p10000attrs$N_ATTRS $2
|
||||
run_solver p15000attrs$N_ATTRS $2
|
||||
run_solver p20000attrs$N_ATTRS $2
|
||||
run_solver p25000attrs$N_ATTRS $2
|
||||
run_solver p30000attrs$N_ATTRS $2
|
||||
run_solver p35000attrs$N_ATTRS $2
|
||||
run_solver p40000attrs$N_ATTRS $2
|
||||
run_solver p45000attrs$N_ATTRS $2
|
||||
run_solver p50000attrs$N_ATTRS $2
|
||||
run_solver p55000attrs$N_ATTRS $2
|
||||
run_solver p60000attrs$N_ATTRS $2
|
||||
run_solver p65000attrs$N_ATTRS $2
|
||||
run_solver p70000attrs$N_ATTRS $2
|
||||
run_solver p75000attrs$N_ATTRS $2
|
||||
run_solver p80000attrs$N_ATTRS $2
|
||||
run_solver p85000attrs$N_ATTRS $2
|
||||
run_solver p90000attrs$N_ATTRS $2
|
||||
run_solver p95000attrs$N_ATTRS $2
|
||||
run_solver p100000attrs$N_ATTRS $2
|
||||
}
|
||||
|
||||
prepare_new_run
|
||||
run_all_graphs "hve(elim_heuristic=min_neighbors) " min_neighbors
|
||||
|
9
packages/CLPBN/horus/benchmarks/workshop_attrs/wa.sh
Executable file
9
packages/CLPBN/horus/benchmarks/workshop_attrs/wa.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
NETWORK="'../../examples/workshop_attrs'"
|
||||
SHORTNAME="wa"
|
||||
QUERY="series(X)"
|
||||
|
||||
N_ATTRS=6
|
||||
|
||||
|
47
packages/CLPBN/horus/examples/burglary-alarm.fg
Normal file
47
packages/CLPBN/horus/examples/burglary-alarm.fg
Normal 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
|
||||
|
28
packages/CLPBN/horus/examples/burglary-alarm.uai
Normal file
28
packages/CLPBN/horus/examples/burglary-alarm.uai
Normal file
@ -0,0 +1,28 @@
|
||||
MARKOV
|
||||
5
|
||||
2 2 2 2 2
|
||||
5
|
||||
1 0
|
||||
1 1
|
||||
3 2 0 1
|
||||
2 3 2
|
||||
2 4 2
|
||||
|
||||
2
|
||||
.001 .999
|
||||
|
||||
2
|
||||
.002 .998
|
||||
|
||||
8
|
||||
.95 .94 .29 .001
|
||||
.05 .06 .71 .999
|
||||
|
||||
4
|
||||
.9 .05
|
||||
.1 .95
|
||||
|
||||
4
|
||||
.7 .01
|
||||
.3 .99
|
||||
|
41
packages/CLPBN/horus/examples/burglary-alarm.yap
Normal file
41
packages/CLPBN/horus/examples/burglary-alarm.yap
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
:- use_module(library(pfl)).
|
||||
|
||||
%:- set_pfl_flag(solver,ve).
|
||||
:- set_pfl_flag(solver,bp), clpbn_horus:set_horus_flag(inf_alg,ve).
|
||||
%:- set_pfl_flag(solver,bp), clpbn_horus:set_horus_flag(inf_alg,bp).
|
||||
%:- set_pfl_flag(solver,fove).
|
||||
|
||||
% :- yap_flag(write_strings, off).
|
||||
|
||||
|
||||
bayes burglary::[b1,b3] ; [0.001, 0.999] ; [].
|
||||
|
||||
bayes earthquake::[e1,e2] ; [0.002, 0.998]; [].
|
||||
|
||||
bayes alarm::[a1,a2] , burglary, earthquake ; [0.95, 0.94, 0.29, 0.001, 0.05, 0.06, 0.71, 0.999] ; [].
|
||||
|
||||
bayes john_calls::[j1,j2] , alarm ; [0.9, 0.05, 0.1, 0.95] ; [].
|
||||
|
||||
bayes mary_calls::[m1,m2] , alarm ; [0.7, 0.01, 0.3, 0.99] ; [].
|
||||
|
||||
|
||||
b_cpt([0.001, 0.999]).
|
||||
|
||||
e_cpt([0.002, 0.998]).
|
||||
|
||||
a_cpt([0.95, 0.94, 0.29, 0.001,
|
||||
0.05, 0.06, 0.71, 0.999]).
|
||||
|
||||
jc_cpt([0.9, 0.05,
|
||||
0.1, 0.95]).
|
||||
|
||||
mc_cpt([0.7, 0.01,
|
||||
0.3, 0.99]).
|
||||
|
||||
% ?- alarm(A).
|
||||
?- john_calls(J), mary_calls(m1).
|
||||
%?- john_calls(J), mary_calls(m1), alarm(a1).
|
||||
%?- john_calls(J), alarm(a1).
|
||||
|
||||
|
15
packages/CLPBN/horus/examples/cbp_example.uai
Normal file
15
packages/CLPBN/horus/examples/cbp_example.uai
Normal file
@ -0,0 +1,15 @@
|
||||
# example in counting belief propagation paper
|
||||
|
||||
MARKOV
|
||||
3
|
||||
2 2 2
|
||||
2
|
||||
2 0 1
|
||||
2 2 1
|
||||
|
||||
4
|
||||
1.2 1.4 2.0 0.4
|
||||
|
||||
4
|
||||
1.2 1.4 2.0 0.4
|
||||
|
105
packages/CLPBN/horus/examples/city.yap
Normal file
105
packages/CLPBN/horus/examples/city.yap
Normal file
@ -0,0 +1,105 @@
|
||||
:- use_module(library(pfl)).
|
||||
|
||||
%:- set_solver(fove).
|
||||
%:- set_solver(hve).
|
||||
%:- set_solver(bp).
|
||||
%:- set_solver(cbp).
|
||||
|
||||
:- multifile people/2.
|
||||
:- multifile ev/1.
|
||||
|
||||
people(joe,nyc).
|
||||
people(p2, nyc).
|
||||
people(p3, nyc).
|
||||
people(p4, nyc).
|
||||
people(p5, nyc).
|
||||
|
||||
ev(descn(p2, t)).
|
||||
ev(descn(p3, t)).
|
||||
ev(descn(p4, t)).
|
||||
ev(descn(p5, t)).
|
||||
|
||||
bayes city_conservativeness(C)::[y,n] ; cons_table(C) ; [people(_,C)].
|
||||
|
||||
bayes gender(P)::[m,f] ; gender_table(P) ; [people(P,_)].
|
||||
|
||||
bayes hair_color(P)::[t,f], city_conservativeness(C) ; hair_color_table(P) ; [people(P,C)].
|
||||
|
||||
bayes car_color(P)::[t,f], hair_color(P) ; car_color_table(P); [people(P,_)].
|
||||
|
||||
bayes height(P)::[t,f], gender(P) ; height_table(P) ; [people(P,_)].
|
||||
|
||||
bayes shoe_size(P):[t,f], height(P) ; shoe_size_table(P); [people(P,_)].
|
||||
|
||||
bayes guilty(P)::[y,n] ; guilty_table(P) ; [people(P,_)].
|
||||
|
||||
bayes descn(P)::[t,f], car_color(P), hair_color(P), height(P), guilty(P) ; descn_table(P) ; [people(P,_)].
|
||||
|
||||
bayes witness(C)::[t,f], descn(Joe), descn(P2) ; wit_table ; [people(_,C), Joe=joe, P2=p2].
|
||||
|
||||
% FIXME
|
||||
%cons_table(amsterdam, [0.2, 0.8]) :- !.
|
||||
cons_table(_, [0.8, 0.2]).
|
||||
|
||||
|
||||
gender_table(_, [0.55, 0.45]).
|
||||
|
||||
|
||||
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.23, 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.71, 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]).
|
||||
|
||||
|
||||
runall(G, Wrapper) :-
|
||||
findall(G, Wrapper, L),
|
||||
execute_all(L).
|
||||
|
||||
|
||||
execute_all([]).
|
||||
execute_all(G.L) :-
|
||||
call(G),
|
||||
execute_all(L).
|
||||
|
||||
|
||||
is_joe_guilty(Guilty) :-
|
||||
witness(nyc, t),
|
||||
runall(X, ev(X)),
|
||||
guilty(joe, Guilty).
|
||||
|
||||
|
||||
% ?- is_joe_guilty(Guilty)
|
||||
|
33
packages/CLPBN/horus/examples/comp_workshops.yap
Normal file
33
packages/CLPBN/horus/examples/comp_workshops.yap
Normal file
@ -0,0 +1,33 @@
|
||||
:- use_module(library(pfl)).
|
||||
|
||||
%:- set_solver(fove).
|
||||
%:- set_solver(hve).
|
||||
%:- set_solver(bp).
|
||||
%:- set_solver(cbp).
|
||||
|
||||
:- yap_flag(write_strings, off).
|
||||
|
||||
:- multifile c/2.
|
||||
|
||||
c(p1,w1).
|
||||
c(p1,w2).
|
||||
c(p1,w3).
|
||||
c(p2,w1).
|
||||
c(p2,w2).
|
||||
c(p2,w3).
|
||||
c(p3,w1).
|
||||
c(p3,w2).
|
||||
c(p3,w3).
|
||||
c(p4,w1).
|
||||
c(p4,w2).
|
||||
c(p4,w3).
|
||||
c(p5,w1).
|
||||
c(p5,w2).
|
||||
c(p5,w3).
|
||||
|
||||
markov attends(P)::[t,f], hot(W)::[t,f] ; [0.2, 0.8, 0.8, 0.8] ; [c(P,W)].
|
||||
|
||||
markov attends(P)::[t,f], series::[t,f] ; [0.501, 0.499, 0.499, 0.499] ; [c(P,_)].
|
||||
|
||||
% ?- series(X).
|
||||
|
21
packages/CLPBN/horus/examples/fail1.yap
Normal file
21
packages/CLPBN/horus/examples/fail1.yap
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
:- use_module(library(pfl)).
|
||||
|
||||
:- set_pfl_flag(solver,fove).
|
||||
%:- set_pfl_flag(solver,bp), clpbn_horus:set_horus_flag(inf_alg,ve).
|
||||
%:- set_pfl_flag(solver,bp), clpbn_horus:set_horus_flag(inf_alg,bp).
|
||||
%:- set_pfl_flag(solver,bp), clpbn_horus:set_horus_flag(inf_alg,cbp).
|
||||
|
||||
|
||||
t(ann).
|
||||
t(dave).
|
||||
|
||||
% p(ann,t).
|
||||
|
||||
markov p(X)::[t,f] ; [0.1, 0.3] ; [t(X)].
|
||||
|
||||
% use standard Prolog queries: provide evidence first.
|
||||
|
||||
?- p(ann,t), p(ann,X).
|
||||
% ?- p(ann,X).
|
||||
|
21
packages/CLPBN/horus/examples/fail2.yap
Normal file
21
packages/CLPBN/horus/examples/fail2.yap
Normal file
@ -0,0 +1,21 @@
|
||||
:- use_module(library(pfl)).
|
||||
|
||||
:- set_solver(fove).
|
||||
%:- set_solver(hve).
|
||||
%:- set_solver(bp).
|
||||
%:- set_solver(cbp).
|
||||
|
||||
:- yap_flag(write_strings, off).
|
||||
|
||||
:- clpbn_horus:set_horus_flag(verbosity,5).
|
||||
|
||||
people(p1,p1).
|
||||
people(p1,p2).
|
||||
people(p2,p1).
|
||||
people(p2,p2).
|
||||
|
||||
markov p(A,A)::[t,f] ; [1.0,4.5] ; [people(A,_)].
|
||||
|
||||
markov p(A,B)::[t,f] ; [1.0,4.5] ; [people(A,B)].
|
||||
|
||||
?- p(p1,p1,X).
|
31
packages/CLPBN/horus/examples/smokers1.yap
Normal file
31
packages/CLPBN/horus/examples/smokers1.yap
Normal file
@ -0,0 +1,31 @@
|
||||
:- use_module(library(pfl)).
|
||||
|
||||
%:- set_solver(fove).
|
||||
%:- set_solver(hve).
|
||||
%:- set_solver(bp).
|
||||
%:- set_solver(cbp).
|
||||
|
||||
:- yap_flag(write_strings, off).
|
||||
|
||||
:- multifile people/1.
|
||||
|
||||
people @ 5.
|
||||
|
||||
people(X,Y) :-
|
||||
people(X),
|
||||
people(Y),
|
||||
X \== Y.
|
||||
|
||||
markov smokes(X)::[t,f]; [1.0, 4.0552]; [people(X)].
|
||||
|
||||
markov cancer(X)::[t,f]; [1.0, 9.9742]; [people(X)].
|
||||
|
||||
markov friends(X,Y)::[t,f] ; [1.0, 99.48432] ; [people(X,Y)].
|
||||
|
||||
markov smokes(X)::[t,f], cancer(X)::[t,f] ; [4.48169, 4.48169, 1.0, 4.48169] ; [people(X)].
|
||||
|
||||
markov friends(X,Y)::[t,f], smokes(X)::[t,f], smokes(Y)::[t,f] ;
|
||||
[3.004166, 3.004166, 3.004166, 3.004166, 3.004166, 1.0, 1.0, 3.004166] ; [people(X,Y)].
|
||||
|
||||
% ?- friends(p1,p2,X).
|
||||
|
31
packages/CLPBN/horus/examples/smokers2.yap
Normal file
31
packages/CLPBN/horus/examples/smokers2.yap
Normal file
@ -0,0 +1,31 @@
|
||||
:- use_module(library(pfl)).
|
||||
|
||||
%:- set_solver(fove).
|
||||
%:- set_solver(hve).
|
||||
%:- set_solver(bp).
|
||||
%:- set_solver(cbp).
|
||||
|
||||
:- yap_flag(write_strings, off).
|
||||
|
||||
:- multifile people/1.
|
||||
|
||||
people @ 5.
|
||||
|
||||
people(X,Y) :-
|
||||
people(X),
|
||||
people(Y).
|
||||
% X \== Y.
|
||||
|
||||
markov smokes(X)::[t,f]; [1.0, 4.0552]; [people(X)].
|
||||
|
||||
markov asthma(X)::[t,f]; [1.0, 9.9742] ; [people(X)].
|
||||
|
||||
markov friends(X,Y)::[t,f]; [1.0, 99.48432] ; [people(X,Y)].
|
||||
|
||||
markov asthma(X)::[t,f], smokes(X)::[t,f]; [4.48169, 4.48169, 1.0, 4.48169] ; [people(X)].
|
||||
|
||||
markov asthma(X)::[t,f], friends(X,Y)::[t,f], smokes(Y)::[t,f];
|
||||
[3.004166, 3.004166, 3.004166, 3.004166, 3.004166, 1.0, 1.0, 3.004166] ; [people(X,Y)].
|
||||
|
||||
% ?- smokes(p1,t), smokes(p2,t), friends(p1,p2,X)
|
||||
|
239
packages/CLPBN/horus/examples/smokers27.fg
Normal file
239
packages/CLPBN/horus/examples/smokers27.fg
Normal 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
|
||||
|
110
packages/CLPBN/horus/examples/test_city.yap
Normal file
110
packages/CLPBN/horus/examples/test_city.yap
Normal file
@ -0,0 +1,110 @@
|
||||
:- use_module(library(pfl)).
|
||||
|
||||
:- set_solver(fove).
|
||||
%:- set_solver(hve).
|
||||
%:- set_solver(bp).
|
||||
%:- set_solver(cbp).
|
||||
|
||||
:- multifile people/2.
|
||||
:- multifile ev/1.
|
||||
|
||||
:- clpbn_horus:set_horus_flag(verbosity,5).
|
||||
|
||||
people(joe,nyc).
|
||||
people(p2, nyc).
|
||||
people(p3, nyc).
|
||||
people(p4, nyc).
|
||||
people(p5, nyc).
|
||||
people(p6, nyc).
|
||||
people(p7, nyc).
|
||||
people(p8, nyc).
|
||||
|
||||
%ev(descn(p2, t)).
|
||||
%ev(descn(p3, t)).
|
||||
%ev(descn(p4, t)).
|
||||
%ev(descn(p5, t)).
|
||||
|
||||
bayes city_conservativeness(C)::[y,n] ; cons_table(C) ; [people(_,C)].
|
||||
|
||||
bayes gender(P)::[m,f] ; gender_table(P) ; [people(P,_)].
|
||||
|
||||
bayes hair_color(P)::[t,f], city_conservativeness(C) ; hair_color_table(P) ; [people(P,C)].
|
||||
|
||||
bayes car_color(P)::[t,f], hair_color(P) ; car_color_table(P); [people(P,_)].
|
||||
|
||||
bayes height(P)::[t,f], gender(P) ; height_table(P) ; [people(P,_)].
|
||||
|
||||
bayes shoe_size(P):[t,f], height(P) ; shoe_size_table(P); [people(P,_)].
|
||||
|
||||
bayes guilty(P)::[y,n] ; guilty_table(P) ; [people(P,_)].
|
||||
|
||||
bayes descn(P)::[t,f], car_color(P), hair_color(P), height(P), guilty(P) ; descn_table(P) ; [people(P,_)].
|
||||
|
||||
bayes witness(C)::[t,f], descn(Joe), descn(P2) ; wit_table ; [people(_,C), Joe=joe, P2=p2].
|
||||
|
||||
% FIXME
|
||||
%cons_table(amsterdam, [0.2, 0.8]) :- !.
|
||||
cons_table(_, [0.8, 0.2]).
|
||||
|
||||
|
||||
gender_table(_, [0.55, 0.45]).
|
||||
|
||||
|
||||
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.23, 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.71, 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]).
|
||||
|
||||
|
||||
runall(G, Wrapper) :-
|
||||
findall(G, Wrapper, L),
|
||||
execute_all(L).
|
||||
|
||||
|
||||
execute_all([]).
|
||||
execute_all(G.L) :-
|
||||
call(G),
|
||||
execute_all(L).
|
||||
|
||||
|
||||
is_joe_guilty(Guilty) :-
|
||||
witness(nyc, t),
|
||||
runall(X, ev(X)),
|
||||
guilty(joe, Guilty).
|
||||
|
||||
|
||||
?- is_joe_guilty(Guilty).
|
||||
|
33
packages/CLPBN/horus/examples/test_smokers1.yap
Normal file
33
packages/CLPBN/horus/examples/test_smokers1.yap
Normal file
@ -0,0 +1,33 @@
|
||||
:- use_module(library(pfl)).
|
||||
|
||||
:- set_solver(fove).
|
||||
%:- set_solver(hve).
|
||||
%:- set_solver(bp).
|
||||
%:- set_solver(cbp).
|
||||
|
||||
:- yap_flag(write_strings, off).
|
||||
|
||||
:- multifile people/1.
|
||||
|
||||
:- clpbn_horus:set_horus_flag(verbosity,5).
|
||||
|
||||
people @ 5.
|
||||
|
||||
people(X,Y) :-
|
||||
people(X),
|
||||
people(Y),
|
||||
X \== Y.
|
||||
|
||||
markov smokes(X)::[t,f]; [1.0, 4.0552]; [people(X)].
|
||||
|
||||
markov cancer(X)::[t,f]; [1.0, 9.9742]; [people(X)].
|
||||
|
||||
markov friends(X,Y)::[t,f] ; [1.0, 99.48432] ; [people(X,Y)].
|
||||
|
||||
markov smokes(X)::[t,f], cancer(X)::[t,f] ; [4.48169, 4.48169, 1.0, 4.48169] ; [people(X)].
|
||||
|
||||
markov friends(X,Y)::[t,f], smokes(X)::[t,f], smokes(Y)::[t,f] ;
|
||||
[3.004166, 3.004166, 3.004166, 3.004166, 3.004166, 1.0, 1.0, 3.004166] ; [people(X,Y)].
|
||||
|
||||
?- friends(p1,p2,X).
|
||||
|
33
packages/CLPBN/horus/examples/test_smokers2.yap
Normal file
33
packages/CLPBN/horus/examples/test_smokers2.yap
Normal file
@ -0,0 +1,33 @@
|
||||
:- use_module(library(pfl)).
|
||||
|
||||
:- set_solver(fove).
|
||||
%:- set_solver(hve).
|
||||
%:- set_solver(bp).
|
||||
%:- set_solver(cbp).
|
||||
|
||||
:- yap_flag(write_strings, off).
|
||||
|
||||
:- clpbn_horus:set_horus_flag(verbosity,5).
|
||||
:- clpbn_horus:set_horus_flag(use_logarithms,true).
|
||||
|
||||
:- multifile people/1.
|
||||
|
||||
people @ 12.
|
||||
|
||||
people(X,Y) :-
|
||||
people(X),
|
||||
people(Y).
|
||||
|
||||
markov smokes(X)::[t,f]; [1.0, 4.0]; [people(X)].
|
||||
|
||||
markov asthma(X)::[t,f]; [2.5, 9.0] ; [people(X)].
|
||||
|
||||
markov friends(X,Y)::[t,f]; [1.0, 14.0] ; [people(X,Y)].
|
||||
|
||||
markov asthma(X)::[t,f], smokes(X)::[t,f]; [4.5, 4.3, 2.0, 1.45] ; [people(X)].
|
||||
|
||||
markov asthma(X)::[t,f], friends(X,Y)::[t,f], smokes(Y)::[t,f];
|
||||
[2.1, 3.3, 7.4, 3.9, 1.6, 5.0, 4.0, 3.0] ; [people(X,Y)].
|
||||
|
||||
?- friends(p1,p2,X).
|
||||
|
29
packages/CLPBN/horus/examples/workshop_attrs.yap
Normal file
29
packages/CLPBN/horus/examples/workshop_attrs.yap
Normal file
@ -0,0 +1,29 @@
|
||||
:- use_module(library(pfl)).
|
||||
|
||||
%:- set_solver(fove).
|
||||
%:- set_solver(hve).
|
||||
%:- set_solver(bp).
|
||||
%:- set_solver(cbp).
|
||||
|
||||
:- yap_flag(write_strings, off).
|
||||
|
||||
:- multifile people/1.
|
||||
|
||||
people @ 5.
|
||||
|
||||
markov attends(P)::[t,f], attr1::[t,f] ; [0.7, 0.3, 0.3, 0.3] ; [people(P)].
|
||||
|
||||
markov attends(P)::[t,f], attr2::[t,f] ; [0.7, 0.3, 0.3, 0.3] ; [people(P)].
|
||||
|
||||
markov attends(P)::[t,f], attr3::[t,f] ; [0.7, 0.3, 0.3, 0.3] ; [people(P)].
|
||||
|
||||
markov attends(P)::[t,f], attr4::[t,f] ; [0.7, 0.3, 0.3, 0.3] ; [people(P)].
|
||||
|
||||
markov attends(P)::[t,f], attr5::[t,f] ; [0.7, 0.3, 0.3, 0.3] ; [people(P)].
|
||||
|
||||
markov attends(P)::[t,f], attr6::[t,f] ; [0.7, 0.3, 0.3, 0.3] ; [people(P)].
|
||||
|
||||
markov attends(P)::[t,f], series::[t,f] ; [0.501, 0.499, 0.499, 0.499] ; [people(P)].
|
||||
|
||||
% ?- series(X).
|
||||
|
4236
packages/CLPBN/horus/fove.log
Normal file
4236
packages/CLPBN/horus/fove.log
Normal file
File diff suppressed because it is too large
Load Diff
BIN
packages/CLPBN/horus/hcli
Executable file
BIN
packages/CLPBN/horus/hcli
Executable file
Binary file not shown.
Reference in New Issue
Block a user