Graphical Model + BOOST
This commit is contained in:
@@ -8,6 +8,7 @@ set(SOURCES
|
||||
assignment
|
||||
factor_template
|
||||
factor_graph
|
||||
naive_inference
|
||||
inference
|
||||
logarithm
|
||||
gm
|
||||
|
||||
@@ -6,29 +6,34 @@ BEGIN_GRAPHICAL_MODEL_NAMESPACE;
|
||||
// check if the values are in variables' value set
|
||||
bool Assignment::checkFiniteValueIntegrity() const
|
||||
{
|
||||
for (Assignment::const_iterator it = this->begin(); it != this->end(); it++)
|
||||
BOOST_FOREACH (const value_type& pair, *this)
|
||||
{
|
||||
if (it->first->type() != VARIABLE_FINITE) return false;
|
||||
const Variable* var = (const Variable*) it->first;
|
||||
const Value& val = it->second;
|
||||
if (pair.first->type() != VARIABLE_FINITE) return false;
|
||||
const Variable* var = (const Variable*) pair.first;
|
||||
const Value& val = pair.second;
|
||||
if ((int) val < var->cardinality()) return false;
|
||||
}
|
||||
return true;
|
||||
// for (Assignment::const_iterator it = this->begin(); it != this->end(); it++)
|
||||
// {
|
||||
// if (it->first->type() != VARIABLE_FINITE) return false;
|
||||
// const Variable* var = (const Variable*) it->first;
|
||||
// const Value& val = it->second;
|
||||
// if ((int) val < var->cardinality()) return false;
|
||||
// }
|
||||
// return true;
|
||||
}
|
||||
|
||||
void Assignment::print(const std::string& name) const
|
||||
{
|
||||
cout << name; if (!name.empty()) cout << " = ";
|
||||
const Assignment& a = *this;
|
||||
if (a.begin() == a.end())
|
||||
int i = 0;
|
||||
cout << "(";
|
||||
BOOST_FOREACH (const value_type& p, (*this))
|
||||
{
|
||||
cout << "()" << endl;
|
||||
return;
|
||||
if (i++ > 0) cout << ", ";
|
||||
cout << p.first->name() << " = " << FINITE_VALUE(p.second);
|
||||
}
|
||||
gm::Assignment::const_iterator jt = a.begin();
|
||||
cout << "(" << jt->first->name() << " = " << FINITE_VALUE(jt->second);
|
||||
for (jt++; jt != a.end(); jt++)
|
||||
cout << ", " << jt->first->name() << " = " << FINITE_VALUE(jt->second);
|
||||
cout << ")" << endl;
|
||||
}
|
||||
|
||||
@@ -37,10 +42,10 @@ void Assignment::print(const std::string& name) const
|
||||
bool Assignment::agree(const Assignment& a) const
|
||||
{
|
||||
ValueCompare less;
|
||||
for (Assignment::const_iterator it = this->begin(); it != this->end(); it++)
|
||||
BOOST_FOREACH (const value_type& p, (*this))
|
||||
{
|
||||
const Variable* var = it->first;
|
||||
const Value& val = it->second;
|
||||
const Variable* var = p.first;
|
||||
const Value& val = p.second;
|
||||
|
||||
Assignment::const_iterator aIt = a.find(var);
|
||||
if (aIt == a.end()) continue; // a does not have assignment for var
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
#include "gm.h"
|
||||
|
||||
BEGIN_GRAPHICAL_MODEL_NAMESPACE;
|
||||
@@ -25,9 +24,9 @@ template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
|
||||
class Vector : public std::vector<_Tp, _Alloc>
|
||||
{
|
||||
public:
|
||||
typedef typename std::vector<_Tp, _Alloc>::value_type value_type;
|
||||
typedef typename std::vector<_Tp, _Alloc>::size_type size_type;
|
||||
typedef typename std::vector<_Tp, _Alloc>::allocator_type allocator_type;
|
||||
typedef typename std::vector<_Tp, _Alloc>::value_type value_type;
|
||||
typedef typename std::vector<_Tp, _Alloc>::size_type size_type;
|
||||
typedef typename std::vector<_Tp, _Alloc>::allocator_type allocator_type;
|
||||
public:
|
||||
Vector () : std::vector<_Tp, _Alloc>() {}
|
||||
Vector(const allocator_type& __a) : std::vector<_Tp, _Alloc>(__a) {}
|
||||
@@ -35,6 +34,10 @@ public:
|
||||
const allocator_type& __a = allocator_type()) : std::vector<_Tp, _Alloc>(__n, __value, __a) {}
|
||||
|
||||
Vector& operator << (const value_type& x) { this->push_back(x); return *this; }
|
||||
void fill(const value_type& x)
|
||||
{
|
||||
for (unsigned int i = 0; i < this->size(); i++) (*this)[i] = x;
|
||||
}
|
||||
};
|
||||
|
||||
/** Augment the std::Map with contains() */
|
||||
@@ -43,9 +46,9 @@ template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
|
||||
class Map : public std::map<_Key, _Tp, _Compare, _Alloc>
|
||||
{
|
||||
public:
|
||||
typedef typename std::map<_Key, _Tp, _Compare, _Alloc>::key_type key_type;
|
||||
typedef typename std::map<_Key, _Tp, _Compare, _Alloc>::value_type value_type;
|
||||
typedef typename std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type mapped_type;
|
||||
typedef typename std::map<_Key, _Tp, _Compare, _Alloc>::key_type key_type;
|
||||
typedef typename std::map<_Key, _Tp, _Compare, _Alloc>::value_type value_type;
|
||||
typedef typename std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type mapped_type;
|
||||
|
||||
bool contains(const key_type& x) const { return this->find(x) != this->end(); }
|
||||
};
|
||||
@@ -54,9 +57,10 @@ public:
|
||||
template <typename A, typename B> class DualMap
|
||||
{
|
||||
public:
|
||||
typedef std::pair<A, B> pair_type;
|
||||
typedef Map<A, B> forward_map_type;
|
||||
typedef Map<B, A> reverse_map_type;
|
||||
typedef std::pair<A, B> pair_type;
|
||||
typedef std::pair<A, B> reverse_pair_type;
|
||||
typedef Map<A, B> forward_map_type;
|
||||
typedef Map<B, A> reverse_map_type;
|
||||
public:
|
||||
void set(const A& a, const B& b) { mapA[a] = b; mapB[b] = a; }
|
||||
bool containsForward(const A& a) const { return mapA.contains(a); }
|
||||
@@ -64,13 +68,13 @@ public:
|
||||
B getForward(const A& a) const
|
||||
{
|
||||
typename forward_map_type::const_iterator it = mapA.find(a);
|
||||
assert(it != mapA.end());
|
||||
DEBUG_ASSERT(it != mapA.end());
|
||||
return (it->second);
|
||||
}
|
||||
A getReverse(const B& b) const
|
||||
{
|
||||
typename reverse_map_type::const_iterator it = mapB.find(b);
|
||||
assert(it != mapB.end());
|
||||
DEBUG_ASSERT(it != mapB.end());
|
||||
return (it->second);
|
||||
}
|
||||
int size() const { return mapA.size(); }
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
#ifndef FACTOR_GRAPH_H
|
||||
#define FACTOR_GRAPH_H
|
||||
#include <cassert>
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "gm.h"
|
||||
@@ -95,10 +88,10 @@ template <typename _F> void FactorGraph<_F>::add(const factor_type& f)
|
||||
|
||||
vertexMap_[(void*) f_] = vf_;
|
||||
const Domain& dom = f_->domain();
|
||||
for (unsigned int i = 0; i < dom.size(); i++)
|
||||
BOOST_FOREACH(const Variable* var, dom)
|
||||
{
|
||||
vertex_type v;
|
||||
void* key = (void*) dom[i];
|
||||
void* key = (void*) var;
|
||||
if (vertexMap_.contains(key))
|
||||
v = vertexMap_[key];
|
||||
else
|
||||
@@ -116,18 +109,16 @@ template <typename _F> void FactorGraph<_F>::add(const factor_type& f)
|
||||
|
||||
template <typename _F> void FactorGraph<_F>::print() const
|
||||
{
|
||||
for (unsigned int i = 0; i < vertices_.size(); i++)
|
||||
BOOST_FOREACH(const vertex_type& u, vertices_)
|
||||
{
|
||||
const vertex_type& u = vertices_[i];
|
||||
const vertex_vector_type& nb = neighbors(u);
|
||||
|
||||
cout << "Vertex: " << (u->isVariable() ? "Variable " : "Factor ");
|
||||
if (u->isVariable()) { u->variable()->print(); cout << endl; }
|
||||
else { cout << endl; factor(u).print(); }
|
||||
cout << " Neighbors:";
|
||||
for (unsigned int j = 0; j < nb.size(); j++)
|
||||
BOOST_FOREACH(const vertex_type& v, nb)
|
||||
{
|
||||
const vertex_type& v = nb[j];
|
||||
cout << " " << (v->type() == 0 ? v->variable()->name() + " (Variable)" : "(Factor)");
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef FACTOR_TEMPLATE_H
|
||||
#define FACTOR_TEMPLATE_H
|
||||
|
||||
#include <algorithm>
|
||||
#include "gm.h"
|
||||
|
||||
BEGIN_GRAPHICAL_MODEL_NAMESPACE;
|
||||
@@ -34,7 +35,7 @@ public:
|
||||
factor_value_type& operator[](const Assignment& a);
|
||||
|
||||
/** For get(a), the assignment could be a superset of the domain */
|
||||
factor_value_type get(const Assignment& a);
|
||||
factor_value_type get(const Assignment& a) const;
|
||||
|
||||
/** Return the domain of this factor */
|
||||
const Domain& domain();
|
||||
@@ -85,26 +86,22 @@ template <typename _V>
|
||||
TableF<_V>::TableF(const Domain& dom, const Assignment& res) : dom_(dom)
|
||||
{
|
||||
Assignment temp;
|
||||
for (unsigned int i = 0; i < dom.size(); i++)
|
||||
DEBUG_ASSERT(dom[i]->type() == VARIABLE_FINITE);
|
||||
BOOST_FOREACH(const Variable* v, dom)
|
||||
DEBUG_ASSERT(v->type() == VARIABLE_FINITE);
|
||||
genAssignments(dom, 0, res, temp);
|
||||
}
|
||||
|
||||
// remove assignments that do not agree with variable in a assignment
|
||||
template <typename _V>
|
||||
void TableF<_V>::restricted(const Assignment& a)
|
||||
{
|
||||
Vector<typename TableF::iterator> its;
|
||||
for (typename TableF::iterator it = this->begin(); it != this->end(); it++)
|
||||
for (typename TableF::iterator it = this->begin(); it != this->end();)
|
||||
{
|
||||
const Assignment& b = it->first;
|
||||
if (!b.agree(a)) {
|
||||
// b.print("erase");
|
||||
its << it;
|
||||
}
|
||||
if (!b.agree(a))
|
||||
this->erase(it++);
|
||||
else
|
||||
it++;
|
||||
}
|
||||
for (typename Vector<typename TableF::iterator>::iterator it = its.begin(); it != its.end(); it++)
|
||||
this->erase(*it);
|
||||
}
|
||||
|
||||
template <typename _V>
|
||||
@@ -124,24 +121,24 @@ template <typename _V>
|
||||
void TableF<_V>::print(const std::string& name) const
|
||||
{
|
||||
cout << name; if (!name.empty()) cout << " = " << endl;
|
||||
for (typename TableF::const_iterator it = this->begin(); it != this->end(); it++)
|
||||
BOOST_FOREACH(const typename TableF::value_type& p, *this)
|
||||
{
|
||||
const gm::Assignment& a = it->first;
|
||||
const factor_value_type& val = it->second;
|
||||
const gm::Assignment& a = p.first;
|
||||
const factor_value_type& val = p.second;
|
||||
cout << val << " <-- "; a.print();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename _V>
|
||||
typename TableF<_V>::factor_value_type TableF<_V>::get(const Assignment& a)
|
||||
typename TableF<_V>::factor_value_type TableF<_V>::get(const Assignment& a) const
|
||||
{
|
||||
// check if dom is a subset of variables in a
|
||||
Assignment temp;
|
||||
for (unsigned int i = 0; i < dom_.size(); i++)
|
||||
BOOST_FOREACH(const Variable* v, dom_)
|
||||
{
|
||||
Assignment::const_iterator it = a.find(dom_[i]);
|
||||
Assignment::const_iterator it = a.find(v);
|
||||
if (it == a.end()) return 0.0;
|
||||
else temp[dom_[i]] = (*it).second;
|
||||
else temp[v] = (*it).second;
|
||||
}
|
||||
return this->operator [](temp);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
// the following order of include statements is important
|
||||
#include <fastlib/fastlib.h>
|
||||
#include <boost/foreach.hpp>
|
||||
#include "common_types.h"
|
||||
#include "value.h"
|
||||
#include "variable.h"
|
||||
|
||||
@@ -15,10 +15,10 @@ int main(int argc, char** argv)
|
||||
template <typename Inference, typename Variable>
|
||||
void printBelief(typename Inference::belief_type blf, Variable* var)
|
||||
{
|
||||
for (typename Inference::belief_type::iterator it = blf.begin(); it != blf.end(); it++)
|
||||
BOOST_FOREACH(const typename Inference::belief_type::value_type& p, blf)
|
||||
// for (typename Inference::belief_type::iterator it = blf.begin(); it != blf.end(); it++)
|
||||
{
|
||||
const gm::Value& val = (*it).first;
|
||||
cout << (var->valueMap()->getForward(FINITE_VALUE(val))) << " = (" << (*it).second << ") ";
|
||||
cout << (var->valueMap()->getForward(FINITE_VALUE(p.first))) << " = (" << p.second << ") ";
|
||||
}
|
||||
cout << endl;
|
||||
// cout << "equal = " << (b.size() < 2 ? 0 : b[0] == b[1]) << endl;
|
||||
@@ -78,6 +78,7 @@ void testNaiveInference()
|
||||
e[sprinklet] = 1;
|
||||
f1.restricted(e);
|
||||
f2.restricted(e);
|
||||
e.print("Evidence");
|
||||
|
||||
Graph fg;
|
||||
fg.add(f1);
|
||||
@@ -89,10 +90,10 @@ void testNaiveInference()
|
||||
bp.run();
|
||||
|
||||
belief_map_type beliefs = bp.beliefs();
|
||||
for (belief_map_type::iterator it = beliefs.begin(); it != beliefs.end(); it++)
|
||||
BOOST_FOREACH (const belief_map_type::value_type& blf, beliefs)
|
||||
{
|
||||
cout << (*it).first->name() << " belief: ";
|
||||
printBelief<Inference, Variable>((*it).second, (Variable*) (it->first));
|
||||
cout << blf.first->name() << " belief: ";
|
||||
printBelief<Inference, Variable>(blf.second, (Variable*) (blf.first));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,183 +1,6 @@
|
||||
#ifndef INFERENCE_H
|
||||
#define INFERENCE_H
|
||||
|
||||
#include "gm.h"
|
||||
|
||||
BEGIN_GRAPHICAL_MODEL_NAMESPACE;
|
||||
|
||||
/**
|
||||
* Naive inference implementation, use for testing correctness of other inference algorithm
|
||||
* It calculates the belief of each variable node in the graph by summing up all possible
|
||||
* products of factors in the graph
|
||||
*/
|
||||
template <typename _F>
|
||||
class NaiveInference
|
||||
{
|
||||
public:
|
||||
typedef _F factor_type;
|
||||
typedef FactorGraph<_F> graph_type;
|
||||
typedef typename _F::const_iterator assignment_const_iterator;
|
||||
typedef typename _F::factor_value_type factor_value_type;
|
||||
typedef typename FactorGraph<_F>::vertex_type vertex_type;
|
||||
typedef typename FactorGraph<_F>::vertex_vector_type vertex_vector_type;
|
||||
typedef Map<Value, factor_value_type, ValueCompare> belief_type;
|
||||
typedef Map<const Variable*, belief_type> belief_map_type;
|
||||
public:
|
||||
/** Constructor, preparing to make inference on a factor graph */
|
||||
NaiveInference(const graph_type& graph);
|
||||
|
||||
/** The inference algorithm */
|
||||
void run();
|
||||
|
||||
/** Return the result as a belief map (from variables to their beliefs) */
|
||||
belief_map_type beliefs() const { return beliefs_; }
|
||||
|
||||
/** Return belief of certain variable */
|
||||
belief_type belief(const Variable* var) const;
|
||||
protected:
|
||||
const graph_type& graph_;
|
||||
|
||||
/** To mark visited vertex and cluster index (connected component) of each factor */
|
||||
Map<vertex_type, bool> visited_;
|
||||
Map<int, vertex_vector_type> factorClusters_;
|
||||
|
||||
/** The result */
|
||||
belief_map_type beliefs_;
|
||||
|
||||
/** The main calculation, summing up all possible products of factor */
|
||||
void visitFactors(const vertex_vector_type& factors, unsigned int index, factor_value_type currentVal, const Assignment& currentAsgn);
|
||||
|
||||
/** Prepare the order of calculation by depth first search the graph */
|
||||
void DFSvisit(const vertex_type& u, int cluster);
|
||||
void DFSorder();
|
||||
|
||||
/** Initialize and normalize the beliefs */
|
||||
void initBeliefs();
|
||||
void normalizeBeliefs();
|
||||
};
|
||||
|
||||
template <typename _F> NaiveInference<_F>::NaiveInference(const graph_type& graph)
|
||||
: graph_(graph)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename _F> void NaiveInference<_F>::run()
|
||||
{
|
||||
// preparing the order of calculation
|
||||
DFSorder();
|
||||
initBeliefs();
|
||||
// visit the factors according to theirs connected components
|
||||
for (typename Map<int, vertex_vector_type>::const_iterator it = factorClusters_.begin();
|
||||
it != factorClusters_.end(); it++)
|
||||
{
|
||||
const vertex_vector_type& factors = (*it).second;
|
||||
visitFactors(factors, 0, factor_value_type(1.0), Assignment());
|
||||
}
|
||||
// normalize the results
|
||||
normalizeBeliefs();
|
||||
}
|
||||
|
||||
// Find the connected components of all factors by DFS
|
||||
template <typename _F> void NaiveInference<_F>::DFSorder()
|
||||
{
|
||||
const vertex_vector_type& vertices = graph_.vertices();
|
||||
for (unsigned int i = 0; i < vertices.size(); i++)
|
||||
visited_[vertices[i]] = false;
|
||||
factorClusters_.clear();
|
||||
int cluster = 0;
|
||||
for (unsigned int i = 0; i < vertices.size(); i++) if (!visited_[vertices[i]])
|
||||
{
|
||||
DFSvisit(vertices[i], cluster);
|
||||
cluster++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename _F> void NaiveInference<_F>::DFSvisit(const vertex_type& u, int cluster)
|
||||
{
|
||||
if (u->isFactor()) factorClusters_[cluster] << u;
|
||||
visited_[u] = true;
|
||||
|
||||
const vertex_vector_type& nb = graph_.neighbors(u);
|
||||
for (unsigned int i = 0; i < nb.size(); i++)
|
||||
{
|
||||
const vertex_type& v = nb[i];
|
||||
if (!visited_[v]) DFSvisit(v, cluster);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename _F> void NaiveInference<_F>::visitFactors(const vertex_vector_type& factors, unsigned int index,
|
||||
factor_value_type currentVal, const Assignment& currentAsgn)
|
||||
{
|
||||
if (index == factors.size()) // if we have the product of factors
|
||||
{
|
||||
for (Assignment::const_iterator it = currentAsgn.begin(); it != currentAsgn.end(); it++)
|
||||
{
|
||||
const Variable* var = (*it).first;
|
||||
const Value& val = (*it).second;
|
||||
beliefs_[var][val] += currentVal; // add it to the belief of each variable in the assignment
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const factor_type& f = graph_.factor(factors[index]);
|
||||
for (assignment_const_iterator it = f.begin(); it != f.end(); it++) // iterate through all assignment that agrees with the current assignment
|
||||
{
|
||||
const Assignment& a = (*it).first;
|
||||
factor_value_type val = (*it).second;
|
||||
if (!currentAsgn.agree(a)) continue; // only proceed if current assignmet agrees with new assignment
|
||||
Assignment newAsgn(currentAsgn);
|
||||
newAsgn.insert(a.begin(), a.end());
|
||||
|
||||
visitFactors(factors, index+1, currentVal*val, newAsgn);
|
||||
}
|
||||
}
|
||||
|
||||
// set the belief of all variables to zeros
|
||||
template <typename _F> void NaiveInference<_F>::initBeliefs()
|
||||
{
|
||||
const vertex_vector_type& vertices = graph_.vertices();
|
||||
for (unsigned int i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
const vertex_type& u = vertices[i];
|
||||
if (u->isVariable())
|
||||
{
|
||||
const Variable* var = (const Variable*) u->variable();
|
||||
for (int val = 0; val < var->cardinality(); val++)
|
||||
beliefs_[var][val] = factor_value_type(0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// normalize the beliefs
|
||||
template <typename _F> void NaiveInference<_F>::normalizeBeliefs()
|
||||
{
|
||||
for (typename belief_map_type::iterator it = beliefs_.begin(); it != beliefs_.end(); it++)
|
||||
{
|
||||
factor_value_type sum = factor_value_type(0.0);
|
||||
belief_type& blf = (*it).second;
|
||||
for (typename belief_type::iterator bIt = blf.begin(); bIt != blf.end(); bIt++)
|
||||
sum += (*bIt).second;
|
||||
if (sum < factor_value_type(1e-15)) // sum is ZERO
|
||||
{
|
||||
for (typename belief_type::iterator bIt = blf.begin(); bIt != blf.end(); bIt++)
|
||||
(*bIt).second = factor_value_type(1.0) / factor_value_type(blf.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
for (typename belief_type::iterator bIt = blf.begin(); bIt != blf.end(); bIt++)
|
||||
(*bIt).second /= sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename _F>
|
||||
typename NaiveInference<_F>::belief_type NaiveInference<_F>::belief(const Variable* var) const
|
||||
{
|
||||
typename belief_map_type::const_iterator it = beliefs_.find(var);
|
||||
DEBUG_ASSERT(it != beliefs_.end());
|
||||
return (*it).second;
|
||||
}
|
||||
|
||||
END_GRAPHICAL_MODEL_NAMESPACE;
|
||||
#include "naive_inference.h"
|
||||
|
||||
#endif // INFERENCE_H
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
#ifndef NAIVE_INFERENCE_H
|
||||
#define NAIVE_INFERENCE_H
|
||||
|
||||
#include "gm.h"
|
||||
|
||||
BEGIN_GRAPHICAL_MODEL_NAMESPACE;
|
||||
|
||||
/**
|
||||
* Naive inference implementation, use for testing correctness of other inference algorithm
|
||||
* It calculates the belief of each variable node in the graph by summing up all possible
|
||||
* products of factors in the graph
|
||||
*/
|
||||
template <typename _F>
|
||||
class NaiveInference
|
||||
{
|
||||
public:
|
||||
typedef _F factor_type;
|
||||
typedef FactorGraph<_F> graph_type;
|
||||
typedef typename _F::const_iterator assignment_const_iterator;
|
||||
typedef typename _F::factor_value_type factor_value_type;
|
||||
typedef typename FactorGraph<_F>::vertex_type vertex_type;
|
||||
typedef typename FactorGraph<_F>::vertex_vector_type vertex_vector_type;
|
||||
typedef Map<Value, factor_value_type, ValueCompare> belief_type;
|
||||
typedef Map<const Variable*, belief_type> belief_map_type;
|
||||
public:
|
||||
/** Constructor, preparing to make inference on a factor graph */
|
||||
NaiveInference(const graph_type& graph);
|
||||
|
||||
/** The inference algorithm */
|
||||
void run();
|
||||
|
||||
/** Return the result as a belief map (from variables to their beliefs) */
|
||||
belief_map_type beliefs() const { return beliefs_; }
|
||||
|
||||
/** Return belief of certain variable */
|
||||
belief_type belief(const Variable* var) const;
|
||||
protected:
|
||||
const graph_type& graph_;
|
||||
|
||||
/** To mark visited vertex and cluster index (connected component) of each factor */
|
||||
Map<vertex_type, bool> visited_;
|
||||
Map<int, vertex_vector_type> factorClusters_;
|
||||
|
||||
/** The result */
|
||||
belief_map_type beliefs_;
|
||||
|
||||
/** The main calculation, summing up all possible products of factor */
|
||||
void visitFactors(const vertex_vector_type& factors, unsigned int index, factor_value_type currentVal, const Assignment& currentAsgn);
|
||||
|
||||
/** Prepare the order of calculation by depth first search the graph */
|
||||
void DFSvisit(const vertex_type& u, int cluster);
|
||||
void DFSorder();
|
||||
|
||||
/** Initialize and normalize the beliefs */
|
||||
void initBeliefs();
|
||||
void normalizeBeliefs();
|
||||
};
|
||||
|
||||
template <typename _F> NaiveInference<_F>::NaiveInference(const graph_type& graph)
|
||||
: graph_(graph)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename _F> void NaiveInference<_F>::run()
|
||||
{
|
||||
// preparing the order of calculation
|
||||
DFSorder();
|
||||
initBeliefs();
|
||||
// visit the factors according to theirs connected components
|
||||
typedef Map<int, vertex_vector_type> map_t;
|
||||
BOOST_FOREACH(const typename map_t::value_type& p, factorClusters_)
|
||||
{
|
||||
const vertex_vector_type& factors = p.second;
|
||||
visitFactors(factors, 0, factor_value_type(1.0), Assignment());
|
||||
}
|
||||
// normalize the results
|
||||
normalizeBeliefs();
|
||||
}
|
||||
|
||||
// Find the connected components of all factors by DFS
|
||||
template <typename _F> void NaiveInference<_F>::DFSorder()
|
||||
{
|
||||
const vertex_vector_type& vertices = graph_.vertices();
|
||||
for (unsigned int i = 0; i < vertices.size(); i++)
|
||||
visited_[vertices[i]] = false;
|
||||
factorClusters_.clear();
|
||||
int cluster = 0;
|
||||
BOOST_FOREACH (const vertex_type& u, vertices)
|
||||
if (!visited_[u])
|
||||
{
|
||||
DFSvisit(u, cluster);
|
||||
cluster++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename _F> void NaiveInference<_F>::DFSvisit(const vertex_type& u, int cluster)
|
||||
{
|
||||
if (u->isFactor()) factorClusters_[cluster] << u;
|
||||
visited_[u] = true;
|
||||
|
||||
const vertex_vector_type& nb = graph_.neighbors(u);
|
||||
BOOST_FOREACH (const vertex_type& v, nb)
|
||||
if (!visited_[v]) DFSvisit(v, cluster);
|
||||
}
|
||||
|
||||
template <typename _F> void NaiveInference<_F>::visitFactors(const vertex_vector_type& factors, unsigned int index,
|
||||
factor_value_type currentVal, const Assignment& currentAsgn)
|
||||
{
|
||||
if (index == factors.size()) // if we have the product of factors
|
||||
{
|
||||
BOOST_FOREACH(const Assignment::value_type& p, currentAsgn)
|
||||
{
|
||||
const Variable* var = p.first;
|
||||
const Value& val = p.second;
|
||||
beliefs_[var][val] += currentVal; // add it to the belief of each variable in the assignment
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const factor_type& f = graph_.factor(factors[index]);
|
||||
BOOST_FOREACH (const typename factor_type::value_type& p, f) // iterate through all assignment that agrees with the current assignment
|
||||
{
|
||||
const Assignment& a = p.first;
|
||||
const factor_value_type& val = p.second;
|
||||
if (!currentAsgn.agree(a)) continue; // only proceed if current assignmet agrees with new assignment
|
||||
Assignment newAsgn(currentAsgn);
|
||||
newAsgn.insert(a.begin(), a.end());
|
||||
|
||||
visitFactors(factors, index+1, currentVal*val, newAsgn);
|
||||
}
|
||||
}
|
||||
|
||||
// set the belief of all variables to zeros
|
||||
template <typename _F> void NaiveInference<_F>::initBeliefs()
|
||||
{
|
||||
const vertex_vector_type& vertices = graph_.vertices();
|
||||
BOOST_FOREACH (const vertex_type& u, vertices)
|
||||
{
|
||||
if (u->isVariable())
|
||||
{
|
||||
const Variable* var = (const Variable*) u->variable();
|
||||
for (int val = 0; val < var->cardinality(); val++)
|
||||
beliefs_[var][val] = factor_value_type(0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// normalize the beliefs
|
||||
template <typename _F> void NaiveInference<_F>::normalizeBeliefs()
|
||||
{
|
||||
for (typename belief_map_type::iterator it = beliefs_.begin(); it != beliefs_.end(); it++)
|
||||
{
|
||||
factor_value_type sum = factor_value_type(0.0);
|
||||
belief_type& blf = (*it).second;
|
||||
for (typename belief_type::iterator bIt = blf.begin(); bIt != blf.end(); bIt++)
|
||||
sum += (*bIt).second;
|
||||
if (sum < factor_value_type(1e-15)) // sum is ZERO
|
||||
{
|
||||
for (typename belief_type::iterator bIt = blf.begin(); bIt != blf.end(); bIt++)
|
||||
(*bIt).second = factor_value_type(1.0) / factor_value_type(blf.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
for (typename belief_type::iterator bIt = blf.begin(); bIt != blf.end(); bIt++)
|
||||
(*bIt).second /= sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename _F>
|
||||
typename NaiveInference<_F>::belief_type NaiveInference<_F>::belief(const Variable* var) const
|
||||
{
|
||||
typename belief_map_type::const_iterator it = beliefs_.find(var);
|
||||
DEBUG_ASSERT(it != beliefs_.end());
|
||||
return (*it).second;
|
||||
}
|
||||
|
||||
END_GRAPHICAL_MODEL_NAMESPACE;
|
||||
|
||||
#endif // NAIVE_INFERENCE_H
|
||||
@@ -73,9 +73,8 @@ public:
|
||||
void print(const std::string& name = "") const
|
||||
{
|
||||
cout << name; if (!name.empty()) cout << " = " << endl;
|
||||
for (gm::Universe::const_iterator i = this->begin(); i != this->end(); i++)
|
||||
BOOST_FOREACH(const Variable* var, *this)
|
||||
{
|
||||
const gm::Variable* var = (*i);
|
||||
var->print();
|
||||
cout << endl;
|
||||
// std::cout << "name = " << var->name();
|
||||
|
||||
@@ -77,9 +77,10 @@ public:
|
||||
void print() const
|
||||
{
|
||||
cout << "name = " << name_ << " (discrete):";
|
||||
const typename int_value_map_type::forward_map_type& map = valueMap_->forwardMap();
|
||||
for (typename int_value_map_type::forward_map_type::const_iterator it = map.begin(); it != map.end(); it++)
|
||||
cout << " " << (it->first) << " <--> " << (it->second);
|
||||
typedef typename int_value_map_type::forward_map_type map_t;
|
||||
const map_t& map = valueMap_->forwardMap();
|
||||
BOOST_FOREACH (const typename map_t::value_type& p, map)
|
||||
cout << " " << (p.first) << " <--> " << (p.second);
|
||||
}
|
||||
protected:
|
||||
int cardinality_;
|
||||
|
||||
Reference in New Issue
Block a user