| 
									
										
										
										
											2010-10-14 12:54:38 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * GTSAM Copyright 2010, Georgia Tech Research Corporation,  | 
					
						
							|  |  |  |  * Atlanta, Georgia 30332-0415 | 
					
						
							|  |  |  |  * All Rights Reserved | 
					
						
							|  |  |  |  * Authors: Frank Dellaert, et al. (see THANKS for the full author list) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * See LICENSE for the license information | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file    BayesTree.cpp | 
					
						
							|  |  |  |  * @brief   Bayes Tree is a tree of cliques of a Bayes Chain | 
					
						
							|  |  |  |  * @author  Frank Dellaert | 
					
						
							| 
									
										
										
										
											2009-11-23 07:35:13 +08:00
										 |  |  |  * @author  Michael Kaess | 
					
						
							|  |  |  |  * @author  Viorela Ila | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-08 07:00:03 +08:00
										 |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-23 02:02:55 +08:00
										 |  |  | #include <gtsam/base/FastSet.h>
 | 
					
						
							|  |  |  | #include <gtsam/inference/BayesTree.h>
 | 
					
						
							|  |  |  | #include <gtsam/inference/inference-inl.h>
 | 
					
						
							|  |  |  | #include <gtsam/inference/GenericSequentialSolver-inl.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | #include <iostream>
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | #include <algorithm>
 | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | #include <boost/foreach.hpp>
 | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | #include <boost/assign/std/list.hpp> // for operator +=
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | #include <boost/format.hpp>
 | 
					
						
							|  |  |  | #include <boost/lambda/lambda.hpp>
 | 
					
						
							|  |  |  | #include <boost/iterator/transform_iterator.hpp>
 | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | #include <boost/pool/pool_alloc.hpp>
 | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | #include <fstream>
 | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | using namespace boost::assign; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | namespace lam = boost::lambda; | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	BayesTree<CONDITIONAL>::Clique::Clique() {} | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	BayesTree<CONDITIONAL>::Clique::Clique(const sharedConditional& conditional) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		separator_.assign(conditional->parents().begin(), conditional->parents().end()); | 
					
						
							| 
									
										
										
										
											2010-07-31 15:19:03 +08:00
										 |  |  | 		this->push_back(conditional); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	BayesTree<CONDITIONAL>::Clique::Clique(const BayesNet<CONDITIONAL>& bayesNet) | 
					
						
							|  |  |  | 	: BayesNet<CONDITIONAL>(bayesNet) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	  if(bayesNet.size() > 0) { | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  | 	    // Debug check that each parent variable is either a frontal variable in
 | 
					
						
							|  |  |  | 	    // a later conditional in the Bayes net fragment, or that the parent is
 | 
					
						
							|  |  |  | 	    // also a parent of the last conditional.  This checks that the fragment
 | 
					
						
							|  |  |  | 	    // is "enough like a clique".  todo: this should really check that the
 | 
					
						
							|  |  |  | 	    // fragment *is* a clique.
 | 
					
						
							|  |  |  | 	    if(bayesNet.size() > 1) { | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	      typename BayesNet<CONDITIONAL>::const_reverse_iterator cond = bayesNet.rbegin(); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	      ++ cond; | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	      typename CONDITIONAL::shared_ptr lastConditional = *cond; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	      for( ; cond != bayesNet.rend(); ++cond) | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	        for(typename CONDITIONAL::const_iterator parent=(*cond)->beginParents(); parent!=(*cond)->endParents(); ++parent) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	          bool infragment = false; | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	          typename BayesNet<CONDITIONAL>::const_reverse_iterator parentCond = cond; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	          do { | 
					
						
							|  |  |  | 	            if(*parent == (*parentCond)->key()) | 
					
						
							|  |  |  | 	              infragment = true; | 
					
						
							|  |  |  | 	            --parentCond; | 
					
						
							|  |  |  | 	          } while(parentCond != bayesNet.rbegin()); | 
					
						
							|  |  |  | 	          assert(infragment || find(lastConditional->beginParents(), lastConditional->endParents(), *parent) != lastConditional->endParents()); | 
					
						
							|  |  |  | 	        } | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //	    separator_.assign((*bayesNet.rbegin())->parents().begin(), (*bayesNet.rbegin())->parents().end());
 | 
					
						
							|  |  |  | 	    separator_.assign((*bayesNet.rbegin())->beginParents(), (*bayesNet.rbegin())->endParents()); | 
					
						
							|  |  |  | 	  } | 
					
						
							| 
									
										
										
										
											2010-07-31 15:19:03 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	vector<Index> BayesTree<CONDITIONAL>::Clique::keys() const { | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | 	  vector<Index> keys; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	  keys.reserve(this->size() + separator_.size()); | 
					
						
							|  |  |  | 	  BOOST_FOREACH(const sharedConditional conditional, *this) { | 
					
						
							|  |  |  | 	    keys.push_back(conditional->key()); | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  keys.insert(keys.end(), separator_.begin(), separator_.end()); | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 		return keys; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::Clique::print(const string& s) const { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 			cout << s << "Clique "; | 
					
						
							|  |  |  | 			BOOST_FOREACH(const sharedConditional& conditional, this->conditionals_) { cout << conditional->key() << " "; } | 
					
						
							|  |  |  | 			cout << "| "; | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | 			BOOST_FOREACH(const Index sep, separator_) { cout << sep << " "; } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 			cout << "\n"; | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 			BOOST_FOREACH(const sharedConditional& conditional, this->conditionals_) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 				conditional->print("  " + s + "conditional"); | 
					
						
							|  |  |  | //				cout << " " << conditional->key();
 | 
					
						
							| 
									
										
										
										
											2009-11-02 13:17:44 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //			if (!separator_.empty()) {
 | 
					
						
							|  |  |  | //				cout << " :";
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //				BOOST_FOREACH(Index key, separator_)
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //					cout << " " << key;
 | 
					
						
							|  |  |  | //			}
 | 
					
						
							|  |  |  | //			cout << endl;
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 02:05:12 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	size_t BayesTree<CONDITIONAL>::Clique::treeSize() const { | 
					
						
							| 
									
										
										
										
											2009-11-19 02:05:12 +08:00
										 |  |  | 		size_t size = 1; | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 		BOOST_FOREACH(const shared_ptr& child, children_) | 
					
						
							| 
									
										
										
										
											2009-11-19 02:05:12 +08:00
										 |  |  | 			size += child->treeSize(); | 
					
						
							|  |  |  | 		return size; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::Clique::printTree(const string& indent) const { | 
					
						
							| 
									
										
										
										
											2009-11-19 02:05:12 +08:00
										 |  |  | 		print(indent); | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 		BOOST_FOREACH(const shared_ptr& child, children_) | 
					
						
							| 
									
										
										
										
											2009-11-19 02:05:12 +08:00
										 |  |  | 			child->printTree(indent+"  "); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  |   template<class CONDITIONAL> | 
					
						
							|  |  |  |   void BayesTree<CONDITIONAL>::Clique::permuteWithInverse(const Permutation& inversePermutation) { | 
					
						
							|  |  |  |     BayesNet<CONDITIONAL>::permuteWithInverse(inversePermutation); | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |     BOOST_FOREACH(Index& separatorKey, separator_) { separatorKey = inversePermutation[separatorKey]; } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |     if(cachedFactor_) cachedFactor_->permuteWithInverse(inversePermutation); | 
					
						
							|  |  |  |     BOOST_FOREACH(const shared_ptr& child, children_) { | 
					
						
							|  |  |  |       child->permuteWithInverse(inversePermutation); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  |   template<class CONDITIONAL> | 
					
						
							|  |  |  |   bool BayesTree<CONDITIONAL>::Clique::permuteSeparatorWithInverse(const Permutation& inversePermutation) { | 
					
						
							|  |  |  |     bool changed = BayesNet<CONDITIONAL>::permuteSeparatorWithInverse(inversePermutation); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  |     if(!changed) { | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |       BOOST_FOREACH(Index& separatorKey, separator_) { assert(separatorKey == inversePermutation[separatorKey]); } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |       BOOST_FOREACH(const shared_ptr& child, children_) { | 
					
						
							|  |  |  |         assert(child->permuteSeparatorWithInverse(inversePermutation) == false); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     if(changed) { | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |       BOOST_FOREACH(Index& separatorKey, separator_) { separatorKey = inversePermutation[separatorKey]; } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |       if(cachedFactor_) cachedFactor_->permuteWithInverse(inversePermutation); | 
					
						
							|  |  |  |       BOOST_FOREACH(const shared_ptr& child, children_) { | 
					
						
							|  |  |  |         (void)child->permuteSeparatorWithInverse(inversePermutation); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return changed; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	typename BayesTree<CONDITIONAL>::CliqueData | 
					
						
							|  |  |  | 	BayesTree<CONDITIONAL>::getCliqueData() const { | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 		CliqueData data; | 
					
						
							|  |  |  | 		getCliqueData(data, root_); | 
					
						
							|  |  |  | 		return data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::getCliqueData(CliqueData& data, | 
					
						
							|  |  |  | 			BayesTree<CONDITIONAL>::sharedClique clique) const { | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 		data.conditionalSizes.push_back(clique->conditionals_.size()); | 
					
						
							|  |  |  | 		data.separatorSizes.push_back(clique->separator_.size()); | 
					
						
							|  |  |  | 		BOOST_FOREACH(sharedClique c, clique->children_) { | 
					
						
							|  |  |  | 			getCliqueData(data, c); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::saveGraph(const std::string &s) const { | 
					
						
							| 
									
										
										
										
											2010-02-20 06:44:45 +08:00
										 |  |  | 		if (!root_.get()) throw invalid_argument("the root of bayes tree has not been initialized!"); | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 		ofstream of(s.c_str()); | 
					
						
							|  |  |  | 		of<< "digraph G{\n"; | 
					
						
							|  |  |  | 		saveGraph(of, root_); | 
					
						
							|  |  |  | 		of<<"}"; | 
					
						
							|  |  |  | 		of.close(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::saveGraph(ostream &s, | 
					
						
							|  |  |  | 			BayesTree<CONDITIONAL>::sharedClique clique, | 
					
						
							| 
									
										
										
										
											2010-02-10 05:32:14 +08:00
										 |  |  | 			int parentnum) const { | 
					
						
							|  |  |  | 		static int num = 0; | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 		bool first = true; | 
					
						
							|  |  |  | 		std::stringstream out; | 
					
						
							|  |  |  | 		out << num; | 
					
						
							|  |  |  | 		string parent = out.str(); | 
					
						
							|  |  |  | 		parent += "[label=\""; | 
					
						
							| 
									
										
										
										
											2010-02-10 05:32:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 		BOOST_FOREACH(boost::shared_ptr<CONDITIONAL> c, clique->conditionals_) { | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 			if(!first) parent += ","; first = false; | 
					
						
							|  |  |  | 			parent += (string(c->key())).c_str(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-02-10 05:32:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 		if( clique != root_){ | 
					
						
							|  |  |  | 			parent += " : "; | 
					
						
							|  |  |  | 			s << parentnum << "->" << num << "\n"; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-02-10 05:32:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 		first = true; | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | 		BOOST_FOREACH(Index sep, clique->separator_) { | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 			if(!first) parent += ","; first = false; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 			parent += (boost::format("%1%")%sep).str(); | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		parent += "\"];\n"; | 
					
						
							|  |  |  | 		s << parent; | 
					
						
							|  |  |  | 		parentnum = num; | 
					
						
							| 
									
										
										
										
											2010-02-10 05:32:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 		BOOST_FOREACH(sharedClique c, clique->children_) { | 
					
						
							| 
									
										
										
										
											2010-02-10 05:32:14 +08:00
										 |  |  | 			num++; | 
					
						
							|  |  |  | 			saveGraph(s, c, parentnum); | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	typename BayesTree<CONDITIONAL>::CliqueStats | 
					
						
							|  |  |  | 	BayesTree<CONDITIONAL>::CliqueData::getStats() const { | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 		CliqueStats stats; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		double sum = 0.0; | 
					
						
							|  |  |  | 		size_t max = 0; | 
					
						
							|  |  |  | 		BOOST_FOREACH(size_t s, conditionalSizes) { | 
					
						
							|  |  |  | 			sum += (double)s; | 
					
						
							|  |  |  | 			if(s > max) max = s; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		stats.avgConditionalSize = sum / (double)conditionalSizes.size(); | 
					
						
							|  |  |  | 		stats.maxConditionalSize = max; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		sum = 0.0; | 
					
						
							|  |  |  | 		max = 1; | 
					
						
							|  |  |  | 		BOOST_FOREACH(size_t s, separatorSizes) { | 
					
						
							|  |  |  | 			sum += (double)s; | 
					
						
							|  |  |  | 			if(s > max) max = s; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		stats.avgSeparatorSize = sum / (double)separatorSizes.size(); | 
					
						
							|  |  |  | 		stats.maxSeparatorSize = max; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return stats; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// The shortcut density is a conditional P(S|R) of the separator of this
 | 
					
						
							|  |  |  | 	// clique on the root. We can compute it recursively from the parent shortcut
 | 
					
						
							|  |  |  | 	// P(Sp|R) as \int P(Fp|Sp) P(Sp|R), where Fp are the frontal nodes in p
 | 
					
						
							|  |  |  | 	// TODO, why do we actually return a shared pointer, why does eliminate?
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	BayesNet<CONDITIONAL> | 
					
						
							|  |  |  | 	BayesTree<CONDITIONAL>::Clique::shortcut(shared_ptr R) { | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  static const bool debug = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 		// A first base case is when this clique or its parent is the root,
 | 
					
						
							|  |  |  | 		// in which case we return an empty Bayes net.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  sharedClique parent(parent_.lock()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (R.get()==this || parent==R) { | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 			BayesNet<CONDITIONAL> empty; | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 			return empty; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		// The root conditional
 | 
					
						
							|  |  |  | 		FactorGraph<typename CONDITIONAL::Factor> p_R(*R); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 		// The parent clique has a CONDITIONAL for each frontal node in Fp
 | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 		// so we can obtain P(Fp|Sp) in factor graph form
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		FactorGraph<typename CONDITIONAL::Factor> p_Fp_Sp(*parent); | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// If not the base case, obtain the parent shortcut P(Sp|R) as factors
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		FactorGraph<typename CONDITIONAL::Factor> p_Sp_R(parent->shortcut(R)); | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// now combine P(Cp|R) = P(Fp|Sp) * P(Sp|R)
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		FactorGraph<typename CONDITIONAL::Factor> p_Cp_R; | 
					
						
							|  |  |  | 		p_Cp_R.push_back(p_R); | 
					
						
							|  |  |  | 		p_Cp_R.push_back(p_Fp_Sp); | 
					
						
							|  |  |  | 		p_Cp_R.push_back(p_Sp_R); | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Eliminate into a Bayes net with ordering designed to integrate out
 | 
					
						
							|  |  |  | 		// any variables not in *our* separator. Variables to integrate out must be
 | 
					
						
							|  |  |  | 		// eliminated first hence the desired ordering is [Cp\S S].
 | 
					
						
							|  |  |  | 		// However, an added wrinkle is that Cp might overlap with the root.
 | 
					
						
							|  |  |  | 		// Keys corresponding to the root should not be added to the ordering at all.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		if(debug) { | 
					
						
							|  |  |  | 		  p_R.print("p_R: "); | 
					
						
							|  |  |  | 		  p_Fp_Sp.print("p_Fp_Sp: "); | 
					
						
							|  |  |  | 		  p_Sp_R.print("p_Sp_R: "); | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		// We want to factor into a conditional of the clique variables given the
 | 
					
						
							|  |  |  | 		// root and the marginal on the root, integrating out all other variables.
 | 
					
						
							|  |  |  | 		// The integrands include any parents of this clique and the variables of
 | 
					
						
							|  |  |  | 		// the parent clique.
 | 
					
						
							|  |  |  | 		vector<Index> variablesAtBack; | 
					
						
							|  |  |  | 		variablesAtBack.reserve(this->size() + R->size()); | 
					
						
							|  |  |  | 		BOOST_FOREACH(const Index separatorIndex, this->separator_) { | 
					
						
							|  |  |  | 		  variablesAtBack.push_back(separatorIndex); | 
					
						
							|  |  |  | 		  if(debug) cout << "At back (this): " << separatorIndex << endl; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		BOOST_FOREACH(const sharedConditional& conditional, *R) { | 
					
						
							|  |  |  | 		  variablesAtBack.push_back(conditional->key()); | 
					
						
							|  |  |  | 		  if(debug) cout << "At back (root): " << conditional->key() << endl; | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		Permutation toBack = Permutation::PushToBack(variablesAtBack, R->back()->key() + 1); | 
					
						
							|  |  |  |     Permutation::shared_ptr toBackInverse(toBack.inverse()); | 
					
						
							|  |  |  |     BOOST_FOREACH(const typename CONDITIONAL::Factor::shared_ptr& factor, p_Cp_R) { | 
					
						
							|  |  |  |       factor->permuteWithInverse(*toBackInverse); } | 
					
						
							|  |  |  | 		typename BayesNet<CONDITIONAL>::shared_ptr eliminated(EliminationTree<typename CONDITIONAL::Factor>::Create(p_Cp_R)->eliminate()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// take only the conditionals for p(S|R)
 | 
					
						
							|  |  |  | 		BayesNet<CONDITIONAL> p_S_R; | 
					
						
							|  |  |  | 		typename BayesNet<CONDITIONAL>::const_reverse_iterator conditional = eliminated->rbegin(); | 
					
						
							|  |  |  | 		BOOST_FOREACH(const sharedConditional& c, *R) { | 
					
						
							|  |  |  | 		  (void)c; ++conditional; } | 
					
						
							|  |  |  | 		BOOST_FOREACH(const Index c, this->separator_) { | 
					
						
							|  |  |  | 		  if(debug) | 
					
						
							|  |  |  | 		    (*conditional)->print("Taking C|R conditional: "); | 
					
						
							|  |  |  | 		  (void)c; p_S_R.push_front(*(conditional++)); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //		for(Index j=0; j<integrands.size(); ++j)
 | 
					
						
							|  |  |  | //		  p_S_R.pop_front();
 | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Undo the permutation on the shortcut
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		p_S_R.permuteWithInverse(toBack); | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// return the parent shortcut P(Sp|R)
 | 
					
						
							|  |  |  | 		return p_S_R; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 00:02:01 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// P(C) = \int_R P(F|S) P(S|R) P(R)
 | 
					
						
							|  |  |  | 	// TODO: Maybe we should integrate given parent marginal P(Cp),
 | 
					
						
							|  |  |  | 	// \int(Cp\S) P(F|S)P(S|Cp)P(Cp)
 | 
					
						
							|  |  |  | 	// Because the root clique could be very big.
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 	FactorGraph<typename CONDITIONAL::Factor> BayesTree<CONDITIONAL>::Clique::marginal(shared_ptr R) { | 
					
						
							| 
									
										
										
										
											2010-10-12 00:02:01 +08:00
										 |  |  | 		// If we are the root, just return this root
 | 
					
						
							|  |  |  | 		if (R.get()==this) return *R; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Combine P(F|S), P(S|R), and P(R)
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		BayesNet<CONDITIONAL> p_FSR = this->shortcut(R); | 
					
						
							| 
									
										
										
										
											2010-10-12 00:02:01 +08:00
										 |  |  | 		p_FSR.push_front(*this); | 
					
						
							|  |  |  | 		p_FSR.push_back(*R); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Find marginal on the keys we are interested in
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		FactorGraph<typename CONDITIONAL::Factor> p_FSRfg(p_FSR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return *GenericSequentialSolver<typename CONDITIONAL::Factor>(p_FSR).joint(keys()); | 
					
						
							| 
									
										
										
										
											2010-10-12 00:02:01 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	// P(C1,C2) = \int_R P(F1|S1) P(S1|R) P(F2|S1) P(S2|R) P(R)
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | //	template<class CONDITIONAL>
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //	template<class Factor>
 | 
					
						
							|  |  |  | //	pair<FactorGraph<Factor>, Ordering>
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | //	BayesTree<CONDITIONAL>::Clique::joint(shared_ptr C2, shared_ptr R) {
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		// For now, assume neither is the root
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// Combine P(F1|S1), P(S1|R), P(F2|S2), P(S2|R), and P(R)
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | //		sharedBayesNet bn(new BayesNet<CONDITIONAL>);
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		if (!isRoot())     bn->push_back(*this);                   // P(F1|S1)
 | 
					
						
							|  |  |  | //		if (!isRoot())     bn->push_back(shortcut<Factor>(R));     // P(S1|R)
 | 
					
						
							|  |  |  | //		if (!C2->isRoot()) bn->push_back(*C2);                     // P(F2|S2)
 | 
					
						
							|  |  |  | //		if (!C2->isRoot()) bn->push_back(C2->shortcut<Factor>(R)); // P(S2|R)
 | 
					
						
							|  |  |  | //		bn->push_back(*R);                                         // P(R)
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// Find the keys of both C1 and C2
 | 
					
						
							|  |  |  | //		Ordering keys12 = keys();
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //		BOOST_FOREACH(Index key,C2->keys()) keys12.push_back(key);
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		keys12.unique();
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// Calculate the marginal
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | //		return make_pair(marginalize<Factor,CONDITIONAL>(*bn,keys12), keys12);
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //	}
 | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 01:40:24 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::Cliques::print(const std::string& s) const { | 
					
						
							| 
									
										
										
										
											2009-11-23 02:06:28 +08:00
										 |  |  | 		cout << s << ":\n"; | 
					
						
							| 
									
										
										
										
											2009-11-23 01:40:24 +08:00
										 |  |  | 		BOOST_FOREACH(sharedClique clique, *this) | 
					
						
							| 
									
										
										
										
											2009-11-23 02:06:28 +08:00
										 |  |  | 				clique->printTree(); | 
					
						
							| 
									
										
										
										
											2009-11-23 01:40:24 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	bool BayesTree<CONDITIONAL>::Cliques::equals(const Cliques& other, double tol) const { | 
					
						
							| 
									
										
										
										
											2009-11-23 01:40:24 +08:00
										 |  |  | 		return other == *this; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	typename BayesTree<CONDITIONAL>::sharedClique BayesTree<CONDITIONAL>::addClique( | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	    const sharedConditional& conditional, sharedClique parent_clique) { | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 		sharedClique new_clique(new Clique(conditional)); | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | 		Index key = conditional->key(); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		nodes_.resize(std::max(key+1, nodes_.size())); | 
					
						
							|  |  |  | 		nodes_[key] = new_clique; | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 		if (parent_clique != NULL) { | 
					
						
							|  |  |  | 			new_clique->parent_ = parent_clique; | 
					
						
							|  |  |  | 			parent_clique->children_.push_back(new_clique); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return new_clique; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	typename BayesTree<CONDITIONAL>::sharedClique BayesTree<CONDITIONAL>::addClique( | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	    const sharedConditional& conditional, list<sharedClique>& child_cliques) { | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 		sharedClique new_clique(new Clique(conditional)); | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |     Index key = conditional->key(); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |     nodes_.resize(max(key+1, nodes_.size())); | 
					
						
							|  |  |  |     nodes_[key] = new_clique; | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 		new_clique->children_ = child_cliques; | 
					
						
							|  |  |  | 		BOOST_FOREACH(sharedClique& child, child_cliques) | 
					
						
							|  |  |  | 			child->parent_ = new_clique; | 
					
						
							|  |  |  | 		return new_clique; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	inline void BayesTree<CONDITIONAL>::addToCliqueFront(const sharedConditional& conditional, const sharedClique& clique) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	  static const bool debug = false; | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  | 	  // Debug check to make sure the conditional variable is ordered lower than
 | 
					
						
							|  |  |  | 	  // its parents and that all of its parents are present either in this
 | 
					
						
							|  |  |  | 	  // clique or its separator.
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | 	  BOOST_FOREACH(Index parent, conditional->parents()) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	    assert(parent > conditional->key()); | 
					
						
							|  |  |  | 	    bool hasParent = false; | 
					
						
							|  |  |  | 	    const Clique& cliquer(*clique); | 
					
						
							|  |  |  | 	    BOOST_FOREACH(const sharedConditional& child, cliquer) { | 
					
						
							|  |  |  | 	      if(child->key() == parent) { | 
					
						
							|  |  |  | 	        hasParent = true; | 
					
						
							|  |  |  | 	        break; | 
					
						
							|  |  |  | 	      } | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	    if(!hasParent) | 
					
						
							|  |  |  | 	      if(find(clique->separator_.begin(), clique->separator_.end(), parent) != clique->separator_.end()) | 
					
						
							|  |  |  | 	        hasParent = true; | 
					
						
							|  |  |  | 	    assert(hasParent); | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	  if(debug) conditional->print("Adding conditional "); | 
					
						
							|  |  |  | 	  if(debug) clique->print("To clique "); | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | 	  Index key = conditional->key(); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	  nodes_.resize(std::max(key+1, nodes_.size())); | 
					
						
							|  |  |  | 	  nodes_[key] = clique; | 
					
						
							|  |  |  | 	  clique->push_front(conditional); | 
					
						
							|  |  |  | 	  if(debug) clique->print("Expanded clique is "); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::removeClique(sharedClique clique) { | 
					
						
							| 
									
										
										
										
											2009-11-22 05:48:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (clique->isRoot()) | 
					
						
							|  |  |  | 			root_.reset(); | 
					
						
							|  |  |  | 		else // detach clique from parent
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	    clique->parent_.lock()->children_.remove(clique); | 
					
						
							| 
									
										
										
										
											2009-11-22 05:48:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  // orphan my children
 | 
					
						
							|  |  |  | 		BOOST_FOREACH(sharedClique child, clique->children_) | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	  	child->parent_ = typename BayesTree<CONDITIONAL>::Clique::weak_ptr(); | 
					
						
							| 
									
										
										
										
											2009-11-22 05:48:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | 	  BOOST_FOREACH(Index key, clique->separator_) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 			nodes_[key].reset(); | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  const Clique& cliquer(*clique); | 
					
						
							|  |  |  | 	  BOOST_FOREACH(const sharedConditional& conditional, cliquer) { | 
					
						
							|  |  |  | 	    nodes_[conditional->key()].reset(); | 
					
						
							| 
									
										
										
										
											2009-12-14 04:54:48 +08:00
										 |  |  | 	  } | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	BayesTree<CONDITIONAL>::BayesTree() { | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	BayesTree<CONDITIONAL>::BayesTree(const BayesNet<CONDITIONAL>& bayesNet) { | 
					
						
							|  |  |  | 		typename BayesNet<CONDITIONAL>::const_reverse_iterator rit; | 
					
						
							| 
									
										
										
										
											2009-11-03 14:29:56 +08:00
										 |  |  | 		for ( rit=bayesNet.rbegin(); rit != bayesNet.rend(); ++rit ) | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 			insert(*rit); | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	BayesTree<CONDITIONAL>::BayesTree(const BayesNet<CONDITIONAL>& bayesNet, std::list<BayesTree<CONDITIONAL> > subtrees) { | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 		if (bayesNet.size() == 0) | 
					
						
							|  |  |  | 			throw invalid_argument("BayesTree::insert: empty bayes net!"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// get the roots of child subtrees and merge their nodes_
 | 
					
						
							|  |  |  | 		list<sharedClique> childRoots; | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 		BOOST_FOREACH(const BayesTree<CONDITIONAL>& subtree, subtrees) { | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 			nodes_.insert(subtree.nodes_.begin(), subtree.nodes_.end()); | 
					
						
							|  |  |  | 			childRoots.push_back(subtree.root()); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// create a new clique and add all the conditionals to the clique
 | 
					
						
							|  |  |  | 		sharedClique new_clique; | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 		typename BayesNet<CONDITIONAL>::sharedConditional conditional; | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 		BOOST_REVERSE_FOREACH(conditional, bayesNet) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 			if (!new_clique.get()) | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 				new_clique = addClique(conditional,childRoots); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 			else | 
					
						
							|  |  |  | 			  addToCliqueFront(conditional, new_clique); | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		root_ = new_clique; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::print(const string& s) const { | 
					
						
							| 
									
										
										
										
											2009-12-26 12:44:13 +08:00
										 |  |  | 		if (root_.use_count() == 0) { | 
					
						
							| 
									
										
										
										
											2010-01-17 14:06:20 +08:00
										 |  |  | 			printf("WARNING: BayesTree.print encountered a forest...\n"); | 
					
						
							| 
									
										
										
										
											2009-12-26 12:44:13 +08:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 		cout << s << ": clique size == " << size() << ", node size == " << nodes_.size() <<  endl; | 
					
						
							| 
									
										
										
										
											2010-01-17 14:06:20 +08:00
										 |  |  | 		if (nodes_.empty()) return; | 
					
						
							| 
									
										
										
										
											2009-11-05 13:29:47 +08:00
										 |  |  | 		root_->printTree(""); | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 00:30:57 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// binary predicate to test equality of a pair for use in equals
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	bool check_sharedCliques( | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 			const typename BayesTree<CONDITIONAL>::sharedClique& v1, | 
					
						
							|  |  |  | 			const typename BayesTree<CONDITIONAL>::sharedClique& v2 | 
					
						
							| 
									
										
										
										
											2009-11-19 00:30:57 +08:00
										 |  |  | 	) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		return v1->equals(*v2); | 
					
						
							| 
									
										
										
										
											2009-11-19 00:30:57 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	bool BayesTree<CONDITIONAL>::equals(const BayesTree<CONDITIONAL>& other, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  | 			double tol) const { | 
					
						
							| 
									
										
										
										
											2009-11-19 00:30:57 +08:00
										 |  |  | 		return size()==other.size() && | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 				std::equal(nodes_.begin(), nodes_.end(), other.nodes_.begin(), &check_sharedCliques<CONDITIONAL>); | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 09:52:40 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							| 
									
										
										
										
											2010-10-20 09:10:27 +08:00
										 |  |  | 	template<class CONTAINER> | 
					
						
							|  |  |  | 	inline Index BayesTree<CONDITIONAL>::findParentClique(const CONTAINER& parents) const { | 
					
						
							|  |  |  | 	  typename CONTAINER::const_iterator lowestOrderedParent = min_element(parents.begin(), parents.end()); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	  assert(lowestOrderedParent != parents.end()); | 
					
						
							|  |  |  | 	  return *lowestOrderedParent; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //		boost::optional<Index> parentCliqueRepresentative;
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		boost::optional<size_t> lowest;
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //		BOOST_FOREACH(Index p, parents) {
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //			size_t i = index(p);
 | 
					
						
							|  |  |  | //			if (!lowest || i<*lowest) {
 | 
					
						
							|  |  |  | //				lowest.reset(i);
 | 
					
						
							|  |  |  | //				parentCliqueRepresentative.reset(p);
 | 
					
						
							|  |  |  | //			}
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | //		if (!lowest) throw
 | 
					
						
							|  |  |  | //			invalid_argument("BayesTree::findParentClique: no parents given or key not present in index");
 | 
					
						
							|  |  |  | //		return *parentCliqueRepresentative;
 | 
					
						
							| 
									
										
										
										
											2010-01-20 09:52:40 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::insert(const sharedConditional& conditional) | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	  static const bool debug = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 		// get key and parents
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 		typename CONDITIONAL::Parents parents = conditional->parents(); // todo: const reference?
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if(debug) conditional->print("Adding conditional "); | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// if no parents, start a new root clique
 | 
					
						
							|  |  |  | 		if (parents.empty()) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		  if(debug) cout << "No parents so making root" << endl; | 
					
						
							| 
									
										
										
										
											2009-11-05 13:29:47 +08:00
										 |  |  | 			root_ = addClique(conditional); | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-22 10:27:26 +08:00
										 |  |  | 		// otherwise, find the parent clique by using the index data structure
 | 
					
						
							|  |  |  | 		// to find the lowest-ordered parent
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | 		Index parentRepresentative = findParentClique(parents); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		if(debug) cout << "First-eliminated parent is " << parentRepresentative << endl; | 
					
						
							| 
									
										
										
										
											2010-01-22 10:27:26 +08:00
										 |  |  | 		sharedClique parent_clique = (*this)[parentRepresentative]; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		if(debug) parent_clique->print("Parent clique is "); | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// if the parents and parent clique have the same size, add to parent clique
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		if (parent_clique->size() == size_t(parents.size())) { | 
					
						
							|  |  |  | 		  if(debug) cout << "Adding to parent clique" << endl; | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  | 		  // Debug check that the parent keys of the new conditional match the keys
 | 
					
						
							|  |  |  | 		  // currently in the clique.
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //		  list<Index>::const_iterator parent = parents.begin();
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		  typename Clique::const_iterator cond = parent_clique->begin();
 | 
					
						
							|  |  |  | //		  while(parent != parents.end()) {
 | 
					
						
							|  |  |  | //		    assert(cond != parent_clique->end());
 | 
					
						
							|  |  |  | //		    assert(*parent == (*cond)->key());
 | 
					
						
							|  |  |  | //		    ++ parent;
 | 
					
						
							|  |  |  | //		    ++ cond;
 | 
					
						
							|  |  |  | //		  }
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		  addToCliqueFront(conditional, parent_clique); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 		  if(debug) cout << "Starting new clique" << endl; | 
					
						
							|  |  |  | 		  // otherwise, start a new clique and add it to the tree
 | 
					
						
							|  |  |  | 		  addClique(conditional,parent_clique); | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-07-11 15:30:27 +08:00
										 |  |  | 	//TODO: remove this function after removing TSAM.cpp
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	typename BayesTree<CONDITIONAL>::sharedClique BayesTree<CONDITIONAL>::insert( | 
					
						
							|  |  |  | 			const BayesNet<CONDITIONAL>& bayesNet, list<sharedClique>& children, bool isRootClique) | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	  static const bool debug = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 		if (bayesNet.size() == 0) | 
					
						
							|  |  |  | 			throw invalid_argument("BayesTree::insert: empty bayes net!"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// create a new clique and add all the conditionals to the clique
 | 
					
						
							|  |  |  | 		sharedClique new_clique; | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 		typename BayesNet<CONDITIONAL>::sharedConditional conditional; | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 		BOOST_REVERSE_FOREACH(conditional, bayesNet) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		  if(debug) conditional->print("Inserting conditional: "); | 
					
						
							|  |  |  | 			if (!new_clique.get()) | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 				new_clique = addClique(conditional,children); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 			else | 
					
						
							|  |  |  | 			  addToCliqueFront(conditional, new_clique); | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (isRootClique) root_ = new_clique; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return new_clique; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::fillNodesIndex(const sharedClique& subtree) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	  // Add each frontal variable of this root node
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	  BOOST_FOREACH(const typename CONDITIONAL::shared_ptr& cond, *subtree) { nodes_[cond->key()] = subtree; } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	  // Fill index for each child
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	  BOOST_FOREACH(const typename BayesTree<CONDITIONAL>::sharedClique& child, subtree->children_) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	    fillNodesIndex(child); } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::insert(const sharedClique& subtree) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	  if(subtree) { | 
					
						
							|  |  |  | 	    // Find the parent clique of the new subtree.  By the running intersection
 | 
					
						
							|  |  |  | 	    // property, those separator variables in the subtree that are ordered
 | 
					
						
							|  |  |  | 	    // lower than the highest frontal variable of the subtree root will all
 | 
					
						
							|  |  |  | 	    // appear in the separator of the subtree root.
 | 
					
						
							|  |  |  | 	    if(subtree->separator_.empty()) { | 
					
						
							|  |  |  | 	      assert(!root_); | 
					
						
							|  |  |  | 	      root_ = subtree; | 
					
						
							|  |  |  | 	    } else { | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | 	      Index parentRepresentative = findParentClique(subtree->separator_); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	      sharedClique parent = (*this)[parentRepresentative]; | 
					
						
							|  |  |  | 	      parent->children_ += subtree; | 
					
						
							|  |  |  | 	      subtree->parent_ = parent; // set new parent!
 | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	    // Now fill in the nodes index
 | 
					
						
							|  |  |  | 	    if(subtree->back()->key() > (nodes_.size() - 1)) | 
					
						
							|  |  |  | 	      nodes_.resize(subtree->back()->key() + 1); | 
					
						
							|  |  |  | 	    fillNodesIndex(subtree); | 
					
						
							|  |  |  | 	  } | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 00:02:01 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// First finds clique marginal then marginalizes that
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 	typename CONDITIONAL::Factor::shared_ptr BayesTree<CONDITIONAL>::marginal(Index key) const { | 
					
						
							| 
									
										
										
										
											2010-10-12 00:02:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// get clique containing key
 | 
					
						
							|  |  |  | 		sharedClique clique = (*this)[key]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// calculate or retrieve its marginal
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		FactorGraph<typename CONDITIONAL::Factor> cliqueMarginal = clique->marginal(root_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return GenericSequentialSolver<typename CONDITIONAL::Factor>(cliqueMarginal).marginal(key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //		// Reorder so that only the requested key is not eliminated
 | 
					
						
							|  |  |  | //		typename FACTORGRAPH::variableindex_type varIndex(cliqueMarginal);
 | 
					
						
							|  |  |  | //		vector<Index> keyAsVector(1); keyAsVector[0] = key;
 | 
					
						
							|  |  |  | //		Permutation toBack(Permutation::PushToBack(keyAsVector, varIndex.size()));
 | 
					
						
							|  |  |  | //		Permutation::shared_ptr toBackInverse(toBack.inverse());
 | 
					
						
							|  |  |  | //		varIndex.permute(toBack);
 | 
					
						
							|  |  |  | //		BOOST_FOREACH(const typename FACTORGRAPH::sharedFactor& factor, cliqueMarginal) {
 | 
					
						
							|  |  |  | //		  factor->permuteWithInverse(*toBackInverse);
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// partially eliminate, remaining factor graph is requested marginal
 | 
					
						
							|  |  |  | //		SymbolicSequentialSolver::EliminateUntil(cliqueMarginal, varIndex.size()-1, varIndex);
 | 
					
						
							|  |  |  | //    BOOST_FOREACH(const typename FACTORGRAPH::sharedFactor& factor, cliqueMarginal) {
 | 
					
						
							|  |  |  | //      if(factor)
 | 
					
						
							|  |  |  | //        factor->permuteWithInverse(toBack);
 | 
					
						
							|  |  |  | //    }
 | 
					
						
							|  |  |  | //		return cliqueMarginal;
 | 
					
						
							| 
									
										
										
										
											2010-10-12 00:02:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 	typename BayesNet<CONDITIONAL>::shared_ptr BayesTree<CONDITIONAL>::marginalBayesNet(Index key) const { | 
					
						
							| 
									
										
										
										
											2010-10-12 00:02:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// calculate marginal as a factor graph
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 	  typename FactorGraph<typename CONDITIONAL::Factor>::shared_ptr fg( | 
					
						
							|  |  |  | 	      new FactorGraph<typename CONDITIONAL::Factor>()); | 
					
						
							|  |  |  | 	  fg->push_back(this->marginal(key)); | 
					
						
							| 
									
										
										
										
											2010-10-12 00:02:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// eliminate further to Bayes net
 | 
					
						
							| 
									
										
										
										
											2010-10-22 06:59:54 +08:00
										 |  |  | 		return GenericSequentialSolver<typename CONDITIONAL::Factor>(*fg).eliminate(); | 
					
						
							| 
									
										
										
										
											2010-10-12 00:02:01 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	// Find two cliques, their joint, then marginalizes
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | //	template<class CONDITIONAL>
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //	template<class Factor>
 | 
					
						
							|  |  |  | //	FactorGraph<Factor>
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | //	BayesTree<CONDITIONAL>::joint(Index key1, Index key2) const {
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | //		// get clique C1 and C2
 | 
					
						
							|  |  |  | //		sharedClique C1 = (*this)[key1], C2 = (*this)[key2];
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// calculate joint
 | 
					
						
							|  |  |  | //		Ordering ord;
 | 
					
						
							|  |  |  | //		FactorGraph<Factor> p_C1C2;
 | 
					
						
							|  |  |  | //		boost::tie(p_C1C2,ord) = C1->joint<Factor>(C2,root_);
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// create an ordering where both requested keys are not eliminated
 | 
					
						
							|  |  |  | //		ord.remove(key1);
 | 
					
						
							|  |  |  | //		ord.remove(key2);
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// partially eliminate, remaining factor graph is requested joint
 | 
					
						
							|  |  |  | //		// TODO, make eliminate functional
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | //		eliminate<Factor,CONDITIONAL>(p_C1C2,ord);
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		return p_C1C2;
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | //	template<class CONDITIONAL>
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //	template<class Factor>
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | //	BayesNet<CONDITIONAL>
 | 
					
						
							|  |  |  | //	BayesTree<CONDITIONAL>::jointBayesNet(Index key1, Index key2) const {
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | //		// calculate marginal as a factor graph
 | 
					
						
							|  |  |  | //	  FactorGraph<Factor> fg = this->joint<Factor>(key1,key2);
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// eliminate further to Bayes net
 | 
					
						
							|  |  |  | //		Ordering ordering;
 | 
					
						
							|  |  |  | //		ordering += key1, key2;
 | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | //		return eliminate<Factor,CONDITIONAL>(fg,ordering);
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //	}
 | 
					
						
							| 
									
										
										
										
											2009-11-23 00:04:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 12:23:35 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::clear() { | 
					
						
							| 
									
										
										
										
											2010-01-20 12:23:35 +08:00
										 |  |  | 		// Remove all nodes and clear the root pointer
 | 
					
						
							|  |  |  | 		nodes_.clear(); | 
					
						
							|  |  |  | 		root_.reset(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							|  |  |  | 	void BayesTree<CONDITIONAL>::removePath(sharedClique clique, | 
					
						
							|  |  |  | 			BayesNet<CONDITIONAL>& bn, typename BayesTree<CONDITIONAL>::Cliques& orphans) { | 
					
						
							| 
									
										
										
										
											2009-11-21 11:38:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 00:04:51 +08:00
										 |  |  | 		// base case is NULL, if so we do nothing and return empties above
 | 
					
						
							|  |  |  | 		if (clique!=NULL) { | 
					
						
							| 
									
										
										
										
											2009-11-22 07:41:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 09:24:32 +08:00
										 |  |  | 			// remove the clique from orphans in case it has been added earlier
 | 
					
						
							|  |  |  | 			orphans.remove(clique); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 01:40:24 +08:00
										 |  |  | 			// remove me
 | 
					
						
							| 
									
										
										
										
											2009-12-26 12:44:13 +08:00
										 |  |  | 			this->removeClique(clique); | 
					
						
							| 
									
										
										
										
											2009-11-23 01:40:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 00:04:51 +08:00
										 |  |  | 			// remove path above me
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 			this->removePath(clique->parent_.lock(), bn, orphans); | 
					
						
							| 
									
										
										
										
											2009-11-21 11:38:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-14 04:54:48 +08:00
										 |  |  | 			// add children to list of orphans (splice also removed them from clique->children_)
 | 
					
						
							| 
									
										
										
										
											2009-11-23 06:59:56 +08:00
										 |  |  | 			orphans.splice (orphans.begin(), clique->children_); | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-21 08:38:22 +08:00
										 |  |  | 			bn.push_back(*clique); | 
					
						
							| 
									
										
										
										
											2009-11-23 00:04:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 09:24:32 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-11-21 11:38:13 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-23 00:04:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-21 11:38:13 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  | 	template<class CONDITIONAL> | 
					
						
							| 
									
										
										
										
											2010-10-20 09:10:27 +08:00
										 |  |  |   template<class CONTAINER> | 
					
						
							|  |  |  |   void BayesTree<CONDITIONAL>::removeTop(const CONTAINER& keys, | 
					
						
							| 
									
										
										
										
											2010-10-20 02:13:04 +08:00
										 |  |  |   		BayesNet<CONDITIONAL>& bn, typename BayesTree<CONDITIONAL>::Cliques& orphans) { | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// process each key of the new factor
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | 	  BOOST_FOREACH(const Index& key, keys) { | 
					
						
							| 
									
										
										
										
											2010-07-13 04:20:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	    // get the clique
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	    if(key < nodes_.size()) { | 
					
						
							|  |  |  | 	      const sharedClique& clique(nodes_[key]); | 
					
						
							|  |  |  | 	      if(clique) { | 
					
						
							|  |  |  | 	        // remove path from clique to root
 | 
					
						
							|  |  |  | 	        this->removePath(clique, bn, orphans); | 
					
						
							|  |  |  | 	      } | 
					
						
							| 
									
										
										
										
											2010-07-13 04:20:24 +08:00
										 |  |  | 	    } | 
					
						
							|  |  |  | 	  } | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-14 14:01:15 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | /// namespace gtsam
 |