| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * JunctionTree-inl.h | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *   Created on: Feb 4, 2010 | 
					
						
							|  |  |  |  *       Author: nikai | 
					
						
							|  |  |  |  *  Description: the junction tree | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-08 07:00:03 +08:00
										 |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | #include <boost/foreach.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | #include "SymbolicFactorGraph.h"
 | 
					
						
							|  |  |  | #include "BayesTree-inl.h"
 | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | #include "JunctionTree.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	template <class FG> | 
					
						
							|  |  |  | 	JunctionTree<FG>::JunctionTree(FG& fg, const Ordering& ordering) { | 
					
						
							| 
									
										
										
										
											2010-07-14 12:32:58 +08:00
										 |  |  | 		// Symbolic factorization: GaussianFactorGraph -> SymbolicFactorGraph
 | 
					
						
							|  |  |  | 		// -> SymbolicBayesNet -> SymbolicBayesTree
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 		SymbolicFactorGraph sfg(fg); | 
					
						
							|  |  |  | 		SymbolicBayesNet sbn = sfg.eliminate(ordering); | 
					
						
							|  |  |  | 		BayesTree<SymbolicConditional> sbt(sbn); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// distribtue factors
 | 
					
						
							| 
									
										
										
										
											2010-07-14 12:32:58 +08:00
										 |  |  | 		this->root_ = distributeFactors(fg, sbt.root()); | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-07-14 12:32:58 +08:00
										 |  |  | 	template<class FG> | 
					
						
							|  |  |  | 	typename JunctionTree<FG>::sharedClique JunctionTree<FG>::distributeFactors( | 
					
						
							|  |  |  | 			FG& fg, const BayesTree<SymbolicConditional>::sharedClique bayesClique) { | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 		// create a new clique in the junction tree
 | 
					
						
							|  |  |  | 		sharedClique clique(new Clique()); | 
					
						
							|  |  |  | 		clique->frontal_ = bayesClique->ordering(); | 
					
						
							| 
									
										
										
										
											2010-07-14 12:32:58 +08:00
										 |  |  | 		clique->separator_.insert(bayesClique->separator_.begin(), | 
					
						
							|  |  |  | 				bayesClique->separator_.end()); | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// recursively call the children
 | 
					
						
							|  |  |  | 		BOOST_FOREACH(const BayesTree<SymbolicConditional>::sharedClique bayesChild, bayesClique->children()) { | 
					
						
							|  |  |  | 			sharedClique child = distributeFactors(fg, bayesChild); | 
					
						
							|  |  |  | 			clique->children_.push_back(child); | 
					
						
							|  |  |  | 			child->parent_ = clique; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// collect the factors
 | 
					
						
							|  |  |  | 		typedef vector<typename FG::sharedFactor> Factors; | 
					
						
							|  |  |  | 		BOOST_FOREACH(const Symbol& frontal, clique->frontal_) { | 
					
						
							| 
									
										
										
										
											2010-07-14 21:55:32 +08:00
										 |  |  | 			Factors factors = fg.template findAndRemoveFactors(frontal); | 
					
						
							|  |  |  | 			BOOST_FOREACH(const typename FG::sharedFactor& factor_, factors) | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 				clique->push_back(factor_); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return clique; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template <class FG> template <class Conditional> | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 	pair<FG, BayesTree<Conditional> > | 
					
						
							|  |  |  | 	JunctionTree<FG>::eliminateOneClique(sharedClique current) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //		current->frontal_.print("current clique:");
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 		typedef typename BayesTree<Conditional>::sharedClique sharedBtreeClique; | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 		FG fg; // factor graph will be assembled from local factors and marginalized children
 | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 		list<BayesTree<Conditional> > children; | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 		fg.push_back(*current); // add the local factor graph
 | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | //		BOOST_FOREACH(const typename FG::sharedFactor& factor_, fg)
 | 
					
						
							|  |  |  | //			Ordering(factor_->keys()).print("local factor:");
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 		BOOST_FOREACH(sharedClique& child, current->children_) { | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 			// receive the factors from the child and its clique point
 | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 			FG fgChild; BayesTree<Conditional> childTree; | 
					
						
							|  |  |  | 			boost::tie(fgChild, childTree) = eliminateOneClique<Conditional>(child); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //			BOOST_FOREACH(const typename FG::sharedFactor& factor_, fgChild)
 | 
					
						
							|  |  |  | //				Ordering(factor_->keys()).print("factor from child:");
 | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			fg.push_back(fgChild); | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 			children.push_back(childTree); | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// eliminate the combined factors
 | 
					
						
							|  |  |  | 		// warning: fg is being eliminated in-place and will contain marginal afterwards
 | 
					
						
							|  |  |  | 		BayesNet<Conditional> bn = fg.eliminateFrontals(current->frontal_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// create a new clique corresponding the combined factors
 | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 		BayesTree<Conditional> bayesTree(bn, children); | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 		return make_pair(fg, bayesTree); | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	template <class FG> template <class Conditional> | 
					
						
							|  |  |  | 	BayesTree<Conditional> JunctionTree<FG>::eliminate() { | 
					
						
							| 
									
										
										
										
											2010-07-14 12:32:58 +08:00
										 |  |  | 		pair<FG, BayesTree<Conditional> > ret = this->eliminateOneClique<Conditional>(this->root()); | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 		if (ret.first.nrFactors() != 0) | 
					
						
							|  |  |  | 			throw runtime_error("JuntionTree::eliminate: elimination failed because of factors left over!"); | 
					
						
							|  |  |  | 		return ret.second; | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } //namespace gtsam
 |