| 
									
										
										
										
											2009-11-18 05:47:42 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file    testIncremental.cpp | 
					
						
							|  |  |  |  * @brief   Unit tests for graph-based iSAM | 
					
						
							|  |  |  |  * @author  Michael Kaess | 
					
						
							| 
									
										
										
										
											2009-11-19 14:37:06 +08:00
										 |  |  |  * @author  Viorela Ila | 
					
						
							|  |  |  |  * @author  Frank Dellaert | 
					
						
							| 
									
										
										
										
											2009-11-18 05:47:42 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/assign/std/list.hpp> // for operator +=
 | 
					
						
							|  |  |  | using namespace boost::assign; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <CppUnitLite/TestHarness.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "SymbolicBayesNet.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-19 01:03:19 +08:00
										 |  |  | #include "SymbolicFactorGraph.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-18 05:47:42 +08:00
										 |  |  | #include "GaussianBayesNet.h"
 | 
					
						
							|  |  |  | #include "Ordering.h"
 | 
					
						
							|  |  |  | #include "BayesTree-inl.h"
 | 
					
						
							|  |  |  | #include "smallExample.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef BayesTree<SymbolicConditional> SymbolicBayesTree; | 
					
						
							|  |  |  | typedef BayesTree<GaussianConditional> GaussianBayesTree; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 00:31:19 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 01:03:19 +08:00
										 |  |  | SymbolicBayesTree update(const SymbolicBayesTree& initial, | 
					
						
							|  |  |  | 		const boost::shared_ptr<SymbolicFactor>& newFactor) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 02:22:08 +08:00
										 |  |  | 	// create an empty factor graph
 | 
					
						
							| 
									
										
										
										
											2009-11-19 01:03:19 +08:00
										 |  |  | 	SymbolicFactorGraph factorGraph; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 13:23:47 +08:00
										 |  |  | 	// the list of orphaned subtrees
 | 
					
						
							|  |  |  | 	std::list<SymbolicBayesTree::sharedClique> orphans; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 07:25:03 +08:00
										 |  |  | 	// process each key of the new factor
 | 
					
						
							|  |  |  | 	BOOST_FOREACH(string key, newFactor->keys()) { | 
					
						
							|  |  |  | 		// todo: add path to root
 | 
					
						
							| 
									
										
										
										
											2009-11-19 01:28:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 07:25:03 +08:00
										 |  |  | 		// only add if key is not yet in the factor graph
 | 
					
						
							| 
									
										
										
										
											2009-11-20 13:23:47 +08:00
										 |  |  | 		if (!factorGraph.involves(key)) { | 
					
						
							| 
									
										
										
										
											2009-11-19 01:28:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 07:25:03 +08:00
										 |  |  | 			// get the clique
 | 
					
						
							|  |  |  | 			SymbolicBayesTree::sharedClique clique = initial[key]; | 
					
						
							| 
									
										
										
										
											2009-11-20 13:23:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// 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
 | 
					
						
							| 
									
										
										
										
											2009-11-20 07:25:03 +08:00
										 |  |  | 			FactorGraph<SymbolicFactor> clique_factors(*clique); | 
					
						
							| 
									
										
										
										
											2009-11-19 01:28:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 07:25:03 +08:00
										 |  |  | 			// add it to the factor graph
 | 
					
						
							|  |  |  | 			factorGraph.push_back(clique_factors); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 02:22:08 +08:00
										 |  |  | 	// now add the new factor
 | 
					
						
							|  |  |  | 	factorGraph.push_back(newFactor); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 14:37:06 +08:00
										 |  |  | 	// create an ordering BELS
 | 
					
						
							|  |  |  | 	Ordering ordering = factorGraph.getOrdering(); | 
					
						
							| 
									
										
										
										
											2009-11-19 01:03:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// eliminate into a Bayes net
 | 
					
						
							|  |  |  | 	SymbolicBayesNet bayesNet = eliminate<SymbolicFactor,SymbolicConditional>(factorGraph,ordering); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// turn back into a Bayes Tree
 | 
					
						
							|  |  |  | 	BayesTree<SymbolicConditional> newTree(bayesNet); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 02:22:08 +08:00
										 |  |  | 	// add orphans to the bottom of the new tree
 | 
					
						
							| 
									
										
										
										
											2009-11-20 07:25:03 +08:00
										 |  |  | 	BOOST_FOREACH(SymbolicBayesTree::sharedClique orphan, orphans) { | 
					
						
							|  |  |  | 		std::list<std::string>::const_iterator it = orphan->separator_.begin(); | 
					
						
							|  |  |  | 		for (; it != orphan->separator_.end(); it++) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// get clique from new tree to attach to
 | 
					
						
							|  |  |  | 			SymbolicBayesTree::sharedClique clique = newTree[*it]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// check if all conditionals in there, only add once
 | 
					
						
							|  |  |  | 			bool is_subset = true; | 
					
						
							|  |  |  | 			std::list<std::string>::const_iterator it2 = orphan->separator_.begin(); | 
					
						
							|  |  |  | 			for (; it2 != orphan->separator_.end(); it2++) { | 
					
						
							|  |  |  | 				// if any one is not included, then we have to stop and search for another clique
 | 
					
						
							|  |  |  | 				std::list<std::string> keys = clique->keys(); | 
					
						
							|  |  |  | 				if (find(keys.begin(), keys.end(), *it2) == 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) { | 
					
						
							|  |  |  | 				clique->children_ += orphan; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-19 01:03:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return newTree; | 
					
						
							| 
									
										
										
										
											2009-11-19 00:31:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-18 05:47:42 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-18 23:37:19 +08:00
										 |  |  | TEST( BayesTree, iSAM ) | 
					
						
							| 
									
										
										
										
											2009-11-18 05:47:42 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-19 14:37:06 +08:00
										 |  |  | 	// 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")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-18 23:37:19 +08:00
										 |  |  | 	// Create using insert
 | 
					
						
							|  |  |  | 	SymbolicBayesTree bayesTree; | 
					
						
							|  |  |  | 	bayesTree.insert(B); | 
					
						
							|  |  |  | 	bayesTree.insert(L); | 
					
						
							|  |  |  | 	bayesTree.insert(E); | 
					
						
							| 
									
										
										
										
											2009-11-19 14:37:06 +08:00
										 |  |  | 	bayesTree.insert(S); | 
					
						
							| 
									
										
										
										
											2009-11-18 23:37:19 +08:00
										 |  |  | 	bayesTree.insert(T); | 
					
						
							|  |  |  | 	bayesTree.insert(X); | 
					
						
							| 
									
										
										
										
											2009-11-19 00:31:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 07:25:03 +08:00
										 |  |  | 	// Now we modify the Bayes tree by inserting a new factor over B and S
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 14:37:06 +08:00
										 |  |  | 	// 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")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 00:31:19 +08:00
										 |  |  | 	// Create expected Bayes tree
 | 
					
						
							|  |  |  | 	SymbolicBayesTree expected; | 
					
						
							| 
									
										
										
										
											2009-11-19 14:37:06 +08:00
										 |  |  | 	expected.insert(S_); | 
					
						
							|  |  |  | 	expected.insert(L_); | 
					
						
							|  |  |  | 	expected.insert(E_); | 
					
						
							|  |  |  | 	expected.insert(B_); | 
					
						
							| 
									
										
										
										
											2009-11-19 00:31:19 +08:00
										 |  |  | 	expected.insert(T); | 
					
						
							|  |  |  | 	expected.insert(X); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// create a new factor to be inserted
 | 
					
						
							|  |  |  | 	list<string> keys; | 
					
						
							|  |  |  | 	keys += "B","S"; | 
					
						
							| 
									
										
										
										
											2009-11-19 01:03:19 +08:00
										 |  |  | 	boost::shared_ptr<SymbolicFactor> newFactor(new SymbolicFactor(keys)); | 
					
						
							| 
									
										
										
										
											2009-11-19 00:31:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// do incremental inference
 | 
					
						
							|  |  |  | 	SymbolicBayesTree actual = update(bayesTree, newFactor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check whether the same
 | 
					
						
							| 
									
										
										
										
											2009-11-19 12:52:46 +08:00
										 |  |  |   CHECK(assert_equal(expected,actual)); | 
					
						
							| 
									
										
										
										
											2009-11-18 05:47:42 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | int main() { | 
					
						
							|  |  |  | 	TestResult tr; | 
					
						
							|  |  |  | 	return TestRegistry::runAllTests(tr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ |