gtsam/cpp/testIncremental.cpp

162 lines
4.5 KiB
C++

/**
* @file testIncremental.cpp
* @brief Unit tests for graph-based iSAM
* @author Michael Kaess
* @author Viorela Ila
* @author Frank Dellaert
*/
#include <boost/assign/std/list.hpp> // for operator +=
using namespace boost::assign;
#include <CppUnitLite/TestHarness.h>
#include "SymbolicBayesNet.h"
#include "SymbolicFactorGraph.h"
#include "GaussianBayesNet.h"
#include "Ordering.h"
#include "BayesTree-inl.h"
#include "smallExample.h"
using namespace std;
using namespace gtsam;
typedef BayesTree<SymbolicConditional> SymbolicBayesTree;
typedef BayesTree<GaussianConditional> GaussianBayesTree;
/* ************************************************************************* */
SymbolicBayesTree update(const SymbolicBayesTree& initial,
const boost::shared_ptr<SymbolicFactor>& newFactor) {
// create an empty factor graph
SymbolicFactorGraph factorGraph;
// the list of orphaned subtrees
list<SymbolicBayesTree::sharedClique> orphans;
// process each key of the new factor
BOOST_FOREACH(string key, newFactor->keys()) {
// todo: add path to root
// only add if key is not yet in the factor graph
if (!factorGraph.involves(key)) {
// get the clique
SymbolicBayesTree::sharedClique clique = initial[key];
// if in orphans, remove the clique
orphans.remove(clique);
// add children to orphans
BOOST_FOREACH(SymbolicBayesTree::sharedClique child, clique->children_)
orphans.push_back(child);
// convert to factors
FactorGraph<SymbolicFactor> clique_factors(*clique);
// add it to the factor graph
factorGraph.push_back(clique_factors);
}
}
// now add the new factor
factorGraph.push_back(newFactor);
// create an ordering BELS
Ordering ordering = factorGraph.getOrdering();
// eliminate into a Bayes net
SymbolicBayesNet bayesNet = eliminate<SymbolicFactor,SymbolicConditional>(factorGraph,ordering);
// turn back into a Bayes Tree
BayesTree<SymbolicConditional> newTree(bayesNet);
// add orphans to the bottom of the new tree
BOOST_FOREACH(SymbolicBayesTree::sharedClique orphan, orphans) {
BOOST_FOREACH(string key1, orphan->separator_) {
// get clique from new tree to attach to
SymbolicBayesTree::sharedClique candidateParent = newTree[key1];
// check if all conditionals in there, only add once
bool is_subset = true;
BOOST_FOREACH(string key2, orphan->separator_) {
// if any one not included, then we have to stop and search for another clique
list<string> keys = candidateParent->keys();
if (find(keys.begin(), keys.end(), key2) == keys.end()) {
is_subset = false;
break;
}
}
// this clique contains all the keys of the orphan,
// so we can add the orphan as a child
// todo: what about the tree below the orphan?
if (is_subset) {
candidateParent->children_ += orphan;
break;
}
}
}
return newTree;
}
/* ************************************************************************* */
TEST( BayesTree, iSAM )
{
// Conditionals for ASIA example from the tutorial with A and D evidence
SymbolicConditional::shared_ptr
B(new SymbolicConditional("B")),
L(new SymbolicConditional("L", "B")),
E(new SymbolicConditional("E", "B", "L")),
S(new SymbolicConditional("S", "L", "B")),
T(new SymbolicConditional("T", "E", "L")),
X(new SymbolicConditional("X", "E"));
// Create using insert
SymbolicBayesTree bayesTree;
bayesTree.insert(B);
bayesTree.insert(L);
bayesTree.insert(E);
bayesTree.insert(S);
bayesTree.insert(T);
bayesTree.insert(X);
// Now we modify the Bayes tree by inserting a new factor over B and S
// New conditionals in modified top of the tree
SymbolicConditional::shared_ptr
S_(new SymbolicConditional("S")),
L_(new SymbolicConditional("L", "S")),
E_(new SymbolicConditional("E", "L", "S")),
B_(new SymbolicConditional("B", "E", "L", "S"));
// Create expected Bayes tree
SymbolicBayesTree expected;
expected.insert(S_);
expected.insert(L_);
expected.insert(E_);
expected.insert(B_);
expected.insert(T);
expected.insert(X);
// create a new factor to be inserted
list<string> keys;
keys += "B","S";
boost::shared_ptr<SymbolicFactor> newFactor(new SymbolicFactor(keys));
// do incremental inference
SymbolicBayesTree actual = update(bayesTree, newFactor);
// Check whether the same
CHECK(assert_equal(expected,actual));
}
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */