| 
									
										
										
										
											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
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 +=
 | 
					
						
							|  |  |  | using namespace boost::assign; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-09 05:40:09 +08:00
										 |  |  | #include "Conditional.h"
 | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  | #include "BayesTree.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | #include "inference-inl.h"
 | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							| 
									
										
										
										
											2009-11-08 03:31:39 +08:00
										 |  |  | 	BayesTree<Conditional>::Clique::Clique(const sharedConditional& conditional) { | 
					
						
							| 
									
										
										
										
											2009-11-02 13:17:44 +08:00
										 |  |  | 			separator_ = conditional->parents(); | 
					
						
							|  |  |  | 			this->push_back(conditional); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	Ordering BayesTree<Conditional>::Clique::keys() const { | 
					
						
							|  |  |  | 		Ordering frontal_keys = this->ordering(), keys = separator_; | 
					
						
							|  |  |  | 		keys.splice(keys.begin(),frontal_keys); | 
					
						
							|  |  |  | 		return keys; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 	void BayesTree<Conditional>::Clique::print(const string& s) const { | 
					
						
							| 
									
										
										
										
											2009-11-02 13:17:44 +08:00
										 |  |  | 			cout << s; | 
					
						
							| 
									
										
										
										
											2009-11-19 02:22:08 +08:00
										 |  |  | 			BOOST_FOREACH(const sharedConditional& conditional, this->conditionals_) | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 				cout << " " << (string)(conditional->key()); | 
					
						
							| 
									
										
										
										
											2009-11-02 13:17:44 +08:00
										 |  |  | 			if (!separator_.empty()) { | 
					
						
							|  |  |  | 				cout << " :"; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 				BOOST_FOREACH(const Symbol& key, separator_) | 
					
						
							|  |  |  | 					cout << " " << (std::string)key; | 
					
						
							| 
									
										
										
										
											2009-11-02 13:17:44 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			cout << endl; | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 02:05:12 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	size_t BayesTree<Conditional>::Clique::treeSize() const { | 
					
						
							|  |  |  | 		size_t size = 1; | 
					
						
							|  |  |  | 		BOOST_FOREACH(shared_ptr child, children_) | 
					
						
							|  |  |  | 			size += child->treeSize(); | 
					
						
							|  |  |  | 		return size; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 	void BayesTree<Conditional>::Clique::printTree(const string& indent) const { | 
					
						
							| 
									
										
										
										
											2009-11-19 02:05:12 +08:00
										 |  |  | 		print(indent); | 
					
						
							|  |  |  | 		BOOST_FOREACH(shared_ptr child, children_) | 
					
						
							|  |  |  | 			child->printTree(indent+"  "); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +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?
 | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 	template<class Factor> | 
					
						
							| 
									
										
										
										
											2009-11-09 15:04:26 +08:00
										 |  |  | 	BayesNet<Conditional> | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 	BayesTree<Conditional>::Clique::shortcut(shared_ptr R) { | 
					
						
							|  |  |  | 		// A first base case is when this clique or its parent is the root,
 | 
					
						
							|  |  |  | 		// in which case we return an empty Bayes net.
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:04:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (R.get()==this || parent_==R) { | 
					
						
							|  |  |  | 			BayesNet<Conditional> empty; | 
					
						
							|  |  |  | 			return empty; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// The parent clique has a Conditional for each frontal node in Fp
 | 
					
						
							|  |  |  | 		// so we can obtain P(Fp|Sp) in factor graph form
 | 
					
						
							|  |  |  | 		FactorGraph<Factor> p_Fp_Sp(*parent_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// If not the base case, obtain the parent shortcut P(Sp|R) as factors
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:04:26 +08:00
										 |  |  | 		FactorGraph<Factor> p_Sp_R(parent_->shortcut<Factor>(R)); | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// now combine P(Cp|R) = P(Fp|Sp) * P(Sp|R)
 | 
					
						
							|  |  |  | 		FactorGraph<Factor> p_Cp_R = combine(p_Fp_Sp, p_Sp_R); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 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.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Get the key list Cp=Fp+Sp, which will form the basis for the integrands
 | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 		Ordering integrands = parent_->keys(); | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Start ordering with the separator
 | 
					
						
							|  |  |  | 		Ordering ordering = separator_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// remove any variables in the root, after this integrands = Cp\R, ordering = S\R
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		BOOST_FOREACH(const Symbol& key, R->ordering()) { | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 			integrands.remove(key); | 
					
						
							|  |  |  | 			ordering.remove(key); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// remove any variables in the separator, after this integrands = Cp\R\S
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		BOOST_FOREACH(const Symbol& key, separator_) integrands.remove(key); | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// form the ordering as [Cp\R\S S\R]
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		BOOST_REVERSE_FOREACH(const Symbol& key, integrands) ordering.push_front(key); | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// eliminate to get marginal
 | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 		BayesNet<Conditional> p_S_R = eliminate<Factor,Conditional>(p_Cp_R,ordering); | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 		// remove all integrands
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		BOOST_FOREACH(const Symbol& key, integrands) p_S_R.pop_front(); | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 		// return the parent shortcut P(Sp|R)
 | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 		return p_S_R; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +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.
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 	FactorGraph<Factor> | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 	BayesTree<Conditional>::Clique::marginal(shared_ptr R) { | 
					
						
							|  |  |  | 		// 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)
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:04:26 +08:00
										 |  |  | 		BayesNet<Conditional> p_FSR = this->shortcut<Factor>(R); | 
					
						
							|  |  |  | 		p_FSR.push_front(*this); | 
					
						
							|  |  |  | 		p_FSR.push_back(*R); | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Find marginal on the keys we are interested in
 | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 		return marginalize<Factor,Conditional>(p_FSR,keys()); | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// P(C1,C2) = \int_R P(F1|S1) P(S1|R) P(F2|S1) P(S2|R) P(R)
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 	FactorGraph<Factor> | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | 	BayesTree<Conditional>::Clique::joint(shared_ptr C2, shared_ptr R) { | 
					
						
							|  |  |  | 		// For now, assume neither is the root
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Combine P(F1|S1), P(S1|R), P(F2|S2), P(S2|R), and P(R)
 | 
					
						
							| 
									
										
										
										
											2009-11-09 12:45:38 +08:00
										 |  |  | 		sharedBayesNet bn(new BayesNet<Conditional>); | 
					
						
							| 
									
										
										
										
											2009-11-09 15:04:26 +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)
 | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Find the keys of both C1 and C2
 | 
					
						
							|  |  |  | 		Ordering keys12 = keys(); | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		BOOST_FOREACH(const Symbol& key,C2->keys()) keys12.push_back(key); | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | 		keys12.unique(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Calculate the marginal
 | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 		return marginalize<Factor,Conditional>(*bn,keys12); | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 01:40:24 +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
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	bool BayesTree<Conditional>::Cliques::equals(const Cliques& other, double tol) const { | 
					
						
							|  |  |  | 		return other == *this; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	typename BayesTree<Conditional>::sharedClique BayesTree<Conditional>::addClique | 
					
						
							|  |  |  | 	(const sharedConditional& conditional, sharedClique parent_clique) { | 
					
						
							|  |  |  | 		sharedClique new_clique(new Clique(conditional)); | 
					
						
							|  |  |  | 		nodes_.insert(make_pair(conditional->key(), new_clique)); | 
					
						
							|  |  |  | 		if (parent_clique != NULL) { | 
					
						
							|  |  |  | 			new_clique->parent_ = parent_clique; | 
					
						
							|  |  |  | 			parent_clique->children_.push_back(new_clique); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return new_clique; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	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
 | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 	    clique->parent_->children_.remove(clique); | 
					
						
							| 
									
										
										
										
											2009-11-22 05:48:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  // orphan my children
 | 
					
						
							|  |  |  | 		BOOST_FOREACH(sharedClique child, clique->children_) | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 	  	child->parent_.reset(); | 
					
						
							| 
									
										
										
										
											2009-11-22 05:48:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	  BOOST_FOREACH(const Symbol& key, clique->ordering()) { | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 			nodes_.erase(key); | 
					
						
							| 
									
										
										
										
											2009-12-14 04:54:48 +08:00
										 |  |  | 	  } | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	BayesTree<Conditional>::BayesTree() { | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  | 	template<class Conditional> | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 	BayesTree<Conditional>::BayesTree(const BayesNet<Conditional>& bayesNet) { | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | 		typename BayesNet<Conditional>::const_reverse_iterator rit; | 
					
						
							| 
									
										
										
										
											2009-11-03 14:29:56 +08:00
										 |  |  | 		for ( rit=bayesNet.rbegin(); rit != bayesNet.rend(); ++rit ) | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 			insert(*rit); | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  | 	template<class Conditional> | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 	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-01-17 14:06:20 +08:00
										 |  |  | 		cout << s << ": size == " << size() << endl; | 
					
						
							|  |  |  | 		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
 | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	bool check_pair( | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 			const pair<Symbol,typename BayesTree<Conditional>::sharedClique >& v1, | 
					
						
							|  |  |  | 			const pair<Symbol,typename BayesTree<Conditional>::sharedClique >& v2 | 
					
						
							| 
									
										
										
										
											2009-11-19 00:30:57 +08:00
										 |  |  | 	) { | 
					
						
							|  |  |  | 		return v1.first == v2.first && v1.second->equals(*(v2.second)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-10-30 21:03:38 +08:00
										 |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	bool BayesTree<Conditional>::equals(const BayesTree<Conditional>& other, | 
					
						
							|  |  |  | 			double tol) const { | 
					
						
							| 
									
										
										
										
											2009-11-19 00:30:57 +08:00
										 |  |  | 		return size()==other.size() && | 
					
						
							|  |  |  | 				equal(nodes_.begin(),nodes_.end(),other.nodes_.begin(),check_pair<Conditional>); | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							| 
									
										
										
										
											2009-11-08 03:31:39 +08:00
										 |  |  | 	void BayesTree<Conditional>::insert(const sharedConditional& conditional) | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		// get key and parents
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		const Symbol& key = conditional->key(); | 
					
						
							|  |  |  | 		list<Symbol> parents = conditional->parents(); // rtodo: const reference?
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// if no parents, start a new root clique
 | 
					
						
							|  |  |  | 		if (parents.empty()) { | 
					
						
							| 
									
										
										
										
											2009-11-05 13:29:47 +08:00
										 |  |  | 			root_ = addClique(conditional); | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// otherwise, find the parent clique
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		Symbol parent = parents.front(); | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 		sharedClique parent_clique = (*this)[parent]; | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// if the parents and parent clique have the same size, add to parent clique
 | 
					
						
							|  |  |  | 		if (parent_clique->size() == parents.size()) { | 
					
						
							| 
									
										
										
										
											2009-11-05 13:29:47 +08:00
										 |  |  | 			nodes_.insert(make_pair(key, parent_clique)); | 
					
						
							| 
									
										
										
										
											2009-11-03 14:29:56 +08:00
										 |  |  | 			parent_clique->push_front(conditional); | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// otherwise, start a new clique and add it to the tree
 | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 		addClique(conditional,parent_clique); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-06 13:43:03 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 	// First finds clique marginal then marginalizes that
 | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							| 
									
										
										
										
											2009-11-05 14:30:50 +08:00
										 |  |  | 	template<class Factor> | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 	FactorGraph<Factor> | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	BayesTree<Conditional>::marginal(const Symbol& key) const { | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 		// get clique containing key
 | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 		sharedClique clique = (*this)[key]; | 
					
						
							| 
									
										
										
										
											2009-11-05 16:06:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 		// calculate or retrieve its marginal
 | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 		FactorGraph<Factor> cliqueMarginal = clique->marginal<Factor>(root_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// create an ordering where only the requested key is not eliminated
 | 
					
						
							|  |  |  | 		Ordering ord = clique->keys(); | 
					
						
							|  |  |  | 		ord.remove(key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// partially eliminate, remaining factor graph is requested marginal
 | 
					
						
							|  |  |  | 		eliminate<Factor,Conditional>(cliqueMarginal,ord); | 
					
						
							|  |  |  | 		return cliqueMarginal; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							|  |  |  | 	BayesNet<Conditional> | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	BayesTree<Conditional>::marginalBayesNet(const Symbol& key) const { | 
					
						
							| 
									
										
										
										
											2009-11-05 14:30:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 		// calculate marginal as a factor graph
 | 
					
						
							|  |  |  | 	  FactorGraph<Factor> fg = this->marginal<Factor>(key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// eliminate further to Bayes net
 | 
					
						
							|  |  |  | 		return eliminate<Factor,Conditional>(fg,Ordering(key)); | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// Find two cliques, their joint, then marginalizes
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 	FactorGraph<Factor> | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	BayesTree<Conditional>::joint(const Symbol& key1, const Symbol& key2) const { | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// get clique C1 and C2
 | 
					
						
							|  |  |  | 		sharedClique C1 = (*this)[key1], C2 = (*this)[key2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// calculate joint
 | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 		FactorGraph<Factor> p_C1C2 = C1->joint<Factor>(C2,root_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// create an ordering where both requested keys are not eliminated
 | 
					
						
							|  |  |  | 		Ordering ord = p_C1C2.keys(); | 
					
						
							|  |  |  | 		ord.remove(key1); | 
					
						
							|  |  |  | 		ord.remove(key2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// partially eliminate, remaining factor graph is requested joint
 | 
					
						
							|  |  |  | 		// TODO, make eliminate functional
 | 
					
						
							|  |  |  | 		eliminate<Factor,Conditional>(p_C1C2,ord); | 
					
						
							|  |  |  | 		return p_C1C2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							|  |  |  | 	BayesNet<Conditional> | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	BayesTree<Conditional>::jointBayesNet(const Symbol& key1, const Symbol& key2) const { | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// calculate marginal as a factor graph
 | 
					
						
							|  |  |  | 	  FactorGraph<Factor> fg = this->joint<Factor>(key1,key2); | 
					
						
							| 
									
										
										
										
											2009-11-05 14:30:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 		// eliminate further to Bayes net
 | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | 		Ordering ordering; | 
					
						
							|  |  |  | 		ordering += key1, key2; | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 		return eliminate<Factor,Conditional>(fg,ordering); | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-23 00:04:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:57:36 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-21 11:38:13 +08:00
										 |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							| 
									
										
										
										
											2009-11-23 00:46:29 +08:00
										 |  |  |   pair<FactorGraph<Factor>, typename BayesTree<Conditional>::Cliques> | 
					
						
							| 
									
										
										
										
											2009-12-28 07:15:36 +08:00
										 |  |  | 	BayesTree<Conditional>::removePath(sharedClique clique) { | 
					
						
							| 
									
										
										
										
											2009-11-21 11:38:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 00:04:51 +08:00
										 |  |  | 		FactorGraph<Factor> factors; | 
					
						
							| 
									
										
										
										
											2009-11-23 00:46:29 +08:00
										 |  |  | 		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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
 | 
					
						
							| 
									
										
										
										
											2009-12-26 12:44:13 +08:00
										 |  |  | 			boost::tie(factors,orphans) = this->removePath<Factor>(clique->parent_); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 03:34:27 +08:00
										 |  |  | 			// Convert clique to a factor graph, using constructor in FactorGraph
 | 
					
						
							|  |  |  | 			FactorGraph<Factor> clique_factors(*clique); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-26 12:44:13 +08:00
										 |  |  | 			// add to the list of "invalidated" factors
 | 
					
						
							| 
									
										
										
										
											2009-12-18 03:34:27 +08:00
										 |  |  | 			factors.push_back(clique_factors); | 
					
						
							| 
									
										
										
										
											2009-12-26 12:44:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 00:04:51 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return make_pair(factors,orphans); | 
					
						
							| 
									
										
										
										
											2009-11-21 11:38:13 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-23 00:04:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-21 11:38:13 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							| 
									
										
										
										
											2010-01-19 06:37:44 +08:00
										 |  |  |   void BayesTree<Conditional>::removeTop(const list<Symbol>& keys, | 
					
						
							| 
									
										
										
										
											2009-11-23 08:02:06 +08:00
										 |  |  | 		FactorGraph<Factor> &factors, typename BayesTree<Conditional>::Cliques& orphans) { | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// process each key of the new factor
 | 
					
						
							| 
									
										
										
										
											2010-01-19 06:37:44 +08:00
										 |  |  | 		BOOST_FOREACH(const Symbol& key, keys) | 
					
						
							| 
									
										
										
										
											2009-11-23 06:59:56 +08:00
										 |  |  | 			try { | 
					
						
							| 
									
										
										
										
											2009-11-23 02:22:17 +08:00
										 |  |  | 				// get the clique and remove it from orphans (if it exists)
 | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 				sharedClique clique = (*this)[key]; | 
					
						
							| 
									
										
										
										
											2009-11-23 02:22:17 +08:00
										 |  |  | 				orphans.remove(clique); | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 02:22:17 +08:00
										 |  |  | 				// remove path from clique to root
 | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 				FactorGraph<Factor> factors1;	Cliques orphans1; | 
					
						
							| 
									
										
										
										
											2009-12-26 12:44:13 +08:00
										 |  |  | 				boost::tie(factors1,orphans1) = this->removePath<Factor>(clique); | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// add to global factors and orphans
 | 
					
						
							|  |  |  | 				factors.push_back(factors1); | 
					
						
							|  |  |  | 				orphans.splice (orphans.begin(), orphans1); | 
					
						
							| 
									
										
										
										
											2009-12-26 12:44:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 06:59:56 +08:00
										 |  |  | 			} catch (std::invalid_argument e) { | 
					
						
							| 
									
										
										
										
											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
 |