| 
									
										
										
										
											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> | 
					
						
							|  |  |  | 	bool JunctionTree<FG>::Clique::equals(const JunctionTree<FG>::Clique& other) const { | 
					
						
							|  |  |  | 		if (!frontal_.equals(other.frontal_)) | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!separator_.equals(other.separator_)) | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (children_.size() != other.children_.size()) | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		typename vector<shared_ptr>::const_iterator it1 = children_.begin(); | 
					
						
							|  |  |  | 		typename vector<shared_ptr>::const_iterator it2 = other.children_.begin(); | 
					
						
							|  |  |  | 		for(; it1!=children_.end(); it1++, it2++) | 
					
						
							|  |  |  | 			if (!(*it1)->equals(**it2)) return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	/**
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	 * JunctionTree | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	template <class FG> | 
					
						
							|  |  |  | 	void JunctionTree<FG>::Clique::print(const string& indent) const { | 
					
						
							|  |  |  | 		// FG::print(indent);
 | 
					
						
							|  |  |  | 		cout << "kai1" << endl; | 
					
						
							|  |  |  | 		cout << indent; | 
					
						
							|  |  |  | 		BOOST_FOREACH(const Symbol& key, frontal_) | 
					
						
							|  |  |  | 		cout << (string)key << " "; | 
					
						
							|  |  |  | 		cout << ":"; | 
					
						
							|  |  |  | 		BOOST_FOREACH(const Symbol& key, separator_) | 
					
						
							|  |  |  | 		cout << (string)key << " "; | 
					
						
							|  |  |  | 		cout << endl; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template <class FG> | 
					
						
							|  |  |  | 	void JunctionTree<FG>::Clique::printTree(const string& indent) const { | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 		print(indent); | 
					
						
							|  |  |  | 		BOOST_FOREACH(const shared_ptr& child, children_) | 
					
						
							|  |  |  | 			child->printTree(indent+"  "); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	template <class FG> | 
					
						
							|  |  |  | 	JunctionTree<FG>::JunctionTree(FG& fg, const Ordering& ordering) { | 
					
						
							|  |  |  | 		// Symbolic factorization: GaussianFactorGraph -> SymbolicFactorGraph -> SymbolicBayesNet -> SymbolicBayesTree
 | 
					
						
							|  |  |  | 		SymbolicFactorGraph sfg(fg); | 
					
						
							|  |  |  | 		SymbolicBayesNet sbn = sfg.eliminate(ordering); | 
					
						
							|  |  |  | 		BayesTree<SymbolicConditional> sbt(sbn); | 
					
						
							|  |  |  | 		sbt.print("sbt"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// distribtue factors
 | 
					
						
							|  |  |  | 		root_ = distributeFactors(fg, sbt.root()); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template <class FG> | 
					
						
							|  |  |  | 	typename JunctionTree<FG>::sharedClique JunctionTree<FG>::distributeFactors(FG& fg, | 
					
						
							|  |  |  | 			const BayesTree<SymbolicConditional>::sharedClique bayesClique) { | 
					
						
							|  |  |  | 		// create a new clique in the junction tree
 | 
					
						
							|  |  |  | 		sharedClique clique(new Clique()); | 
					
						
							|  |  |  | 		clique->frontal_ = bayesClique->ordering(); | 
					
						
							|  |  |  | 		clique->separator_.insert(bayesClique->separator_.begin(), bayesClique->separator_.end()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 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_) { | 
					
						
							|  |  |  | 			Factors factors = fg.template findAndRemoveFactors<Factors>(frontal); | 
					
						
							|  |  |  | 			BOOST_FOREACH(const typename FG::sharedFactor& factor_, factors) { | 
					
						
							|  |  |  | 				clique->push_back(factor_); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return clique; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template <class FG> template <class Conditional> | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 	pair<FG, typename BayesTree<Conditional>::sharedClique> | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	JunctionTree<FG>::eliminateOneClique(sharedClique current, BayesTree<Conditional>& bayesTree) { | 
					
						
							|  |  |  | 		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-09 15:31:15 +08:00
										 |  |  | 		list<sharedBtreeClique> children; | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 		fg.push_back(*current); // add the local factor graph
 | 
					
						
							| 
									
										
										
										
											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-09 15:31:15 +08:00
										 |  |  | 			FG fgChild; sharedBtreeClique cliqueChild; | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 			boost::tie(fgChild, cliqueChild) = eliminateOneClique(child, bayesTree); | 
					
						
							|  |  |  | 			if (!cliqueChild.get()) throw runtime_error("eliminateOneClique: child clique is invalid!"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			fg.push_back(fgChild); | 
					
						
							|  |  |  | 			children.push_back(cliqueChild); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// eliminate the combined factors
 | 
					
						
							|  |  |  | 		// warning: fg is being eliminated in-place and will contain marginal afterwards
 | 
					
						
							|  |  |  | //		BayesNet<Conditional> bn = fg.eliminate(current->frontal_);
 | 
					
						
							|  |  |  | 		BayesNet<Conditional> bn = fg.eliminateFrontals(current->frontal_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// create a new clique corresponding the combined factors
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 		sharedBtreeClique new_clique = bayesTree.insert(bn, children); | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return make_pair(fg, new_clique); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	template <class FG> template <class Conditional> | 
					
						
							|  |  |  | 	BayesTree<Conditional> JunctionTree<FG>::eliminate() { | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 		BayesTree<Conditional> bayesTree; | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 		eliminateOneClique(root_, bayesTree); | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 		return bayesTree; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	template <class FG> | 
					
						
							|  |  |  | 	bool JunctionTree<FG>::equals(const JunctionTree<FG>& other, double tol) const { | 
					
						
							|  |  |  | 		if (!root_ || !other.root_) return false; | 
					
						
							|  |  |  | 		return root_->equals(*other.root_); | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	/**
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	 * GaussianJunctionTree | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	template <class FG> | 
					
						
							|  |  |  | 	void GaussianJunctionTree<FG>::btreeBackSubstitue(typename BayesTree<GaussianConditional>::sharedClique current, VectorConfig& config) { | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 		// solve the bayes net in the current node
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 		typename BayesNet<GaussianConditional>::const_reverse_iterator it = current->rbegin(); | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 		for (; it!=current->rend(); it++) { | 
					
						
							|  |  |  | 			Vector x = (*it)->solve(config); // Solve for that variable
 | 
					
						
							|  |  |  | 			config.insert((*it)->key(),x);   // store result in partial solution
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// solve the bayes nets in the child nodes
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 		typedef typename BayesTree<GaussianConditional>::sharedClique sharedBayesClique; | 
					
						
							|  |  |  | 		BOOST_FOREACH(sharedBayesClique child, current->children_) { | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 			btreeBackSubstitue(child, config); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 	template <class FG> | 
					
						
							|  |  |  | 	VectorConfig GaussianJunctionTree<FG>::optimize() { | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 		// eliminate from leaves to the root
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 		typedef JunctionTree<FG> Base; | 
					
						
							|  |  |  | 		BayesTree<GaussianConditional> bayesTree = this->eliminate<GaussianConditional>(); | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:31:15 +08:00
										 |  |  | 		// back-substitution
 | 
					
						
							| 
									
										
										
										
											2010-07-08 05:41:50 +08:00
										 |  |  | 		VectorConfig result; | 
					
						
							|  |  |  | 		btreeBackSubstitue(bayesTree.root(), result); | 
					
						
							|  |  |  | 		return result; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } //namespace gtsam
 |