| 
									
										
										
										
											2009-10-28 04:23:19 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file    BayesTree | 
					
						
							|  |  |  |  * @brief   Bayes Tree is a tree of cliques of a Bayes Chain | 
					
						
							|  |  |  |  * @author  Frank Dellaert | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // \callgraph
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <list>
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | #include <vector>
 | 
					
						
							| 
									
										
										
										
											2009-10-28 04:23:19 +08:00
										 |  |  | #include <boost/serialization/map.hpp>
 | 
					
						
							|  |  |  | #include <boost/serialization/list.hpp>
 | 
					
						
							| 
									
										
										
										
											2009-12-09 05:40:09 +08:00
										 |  |  | #include <stdexcept>
 | 
					
						
							| 
									
										
										
										
											2009-11-02 13:17:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 04:23:19 +08:00
										 |  |  | #include "Testable.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | #include "FactorGraph.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-01 03:53:20 +08:00
										 |  |  | #include "BayesNet.h"
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | #include "Key.h"
 | 
					
						
							| 
									
										
										
										
											2010-01-22 10:27:26 +08:00
										 |  |  | #include "IndexTable.h"
 | 
					
						
							| 
									
										
										
										
											2009-10-28 04:23:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * Bayes tree | 
					
						
							|  |  |  | 	 * Templated on the Conditional class, the type of node in the underlying Bayes chain. | 
					
						
							| 
									
										
										
										
											2009-11-13 00:41:18 +08:00
										 |  |  | 	 * This could be a ConditionalProbabilityTable, a GaussianConditional, or a SymbolicConditional | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	class BayesTree: public Testable<BayesTree<Conditional> > { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 		typedef boost::shared_ptr<Conditional> sharedConditional; | 
					
						
							|  |  |  | 		typedef boost::shared_ptr<BayesNet<Conditional> > sharedBayesNet; | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 		/** A Clique in the tree is an incomplete Bayes net: the variables
 | 
					
						
							| 
									
										
										
										
											2009-11-02 13:17:44 +08:00
										 |  |  | 		 * in the Bayes net are the frontal nodes, and the variables conditioned | 
					
						
							|  |  |  | 		 * on is the separator. We also have pointers up and down the tree. | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 		struct Clique: public BayesNet<Conditional> { | 
					
						
							| 
									
										
										
										
											2009-11-07 23:58:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 			typedef typename boost::shared_ptr<Clique> shared_ptr; | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 			shared_ptr parent_; | 
					
						
							|  |  |  | 			std::list<shared_ptr> children_; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 			std::list<Symbol> separator_; /** separator keys */ | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 			friend class BayesTree<Conditional>; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-02 13:17:44 +08:00
										 |  |  | 			//* Constructor */
 | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 			Clique(const sharedConditional& conditional); | 
					
						
							| 
									
										
										
										
											2009-11-02 13:17:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 			Clique(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 			/** return keys in frontal:separator order */ | 
					
						
							|  |  |  | 			Ordering keys() const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 			/** print this node */ | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 			void print(const std::string& s = "") const; | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-02 13:17:44 +08:00
										 |  |  | 			/** The size *includes* the separator */ | 
					
						
							| 
									
										
										
										
											2009-11-07 23:58:45 +08:00
										 |  |  | 			size_t size() const { | 
					
						
							|  |  |  | 				return this->conditionals_.size() + separator_.size(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-11-02 13:17:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 			/** is this the root of a Bayes tree ? */ | 
					
						
							|  |  |  | 			inline bool isRoot() const { return parent_==NULL;} | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 02:05:12 +08:00
										 |  |  | 			/** The size of subtree rooted at this clique, i.e., nr of Cliques */ | 
					
						
							|  |  |  | 			size_t treeSize() const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 			/** print this node and entire subtree below it */ | 
					
						
							| 
									
										
										
										
											2009-11-23 02:06:28 +08:00
										 |  |  | 			void printTree(const std::string& indent="") const; | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/** return the conditional P(S|Root) on the separator given the root */ | 
					
						
							| 
									
										
										
										
											2009-11-09 15:04:26 +08:00
										 |  |  | 			// TODO: create a cached version
 | 
					
						
							| 
									
										
										
										
											2009-11-08 12:41:01 +08:00
										 |  |  | 			template<class Factor> | 
					
						
							| 
									
										
										
										
											2009-11-09 15:04:26 +08:00
										 |  |  | 			BayesNet<Conditional> shortcut(shared_ptr root); | 
					
						
							| 
									
										
										
										
											2009-11-09 06:51:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/** return the marginal P(C) of the clique */ | 
					
						
							|  |  |  | 			template<class Factor> | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 			FactorGraph<Factor> marginal(shared_ptr root); | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/** return the joint P(C1,C2), where C1==this. TODO: not a method? */ | 
					
						
							|  |  |  | 			template<class Factor> | 
					
						
							| 
									
										
										
										
											2010-02-21 23:24:05 +08:00
										 |  |  | 			std::pair<FactorGraph<Factor>,Ordering> joint(shared_ptr C2, shared_ptr root); | 
					
						
							| 
									
										
										
										
											2009-11-23 00:46:29 +08:00
										 |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 00:46:29 +08:00
										 |  |  | 		// typedef for shared pointers to cliques
 | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 		typedef boost::shared_ptr<Clique> sharedClique; | 
					
						
							| 
									
										
										
										
											2009-11-07 23:58:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 00:46:29 +08:00
										 |  |  | 		// A convenience class for a list of shared cliques
 | 
					
						
							|  |  |  | 		struct Cliques : public std::list<sharedClique>, public Testable<Cliques> { | 
					
						
							| 
									
										
										
										
											2009-11-23 01:40:24 +08:00
										 |  |  | 			void print(const std::string& s = "Cliques") const; | 
					
						
							|  |  |  | 			bool equals(const Cliques& other, double tol = 1e-9) const; | 
					
						
							| 
									
										
										
										
											2009-11-23 00:46:29 +08:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-07 23:58:45 +08:00
										 |  |  | 	private: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 		/** Map from keys to Clique */ | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 		typedef SymbolMap<sharedClique> Nodes; | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 		Nodes nodes_; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 	protected: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | 		/** Root clique */ | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 		sharedClique root_; | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 		/** remove a clique: warning, can result in a forest */ | 
					
						
							|  |  |  | 		void removeClique(sharedClique clique); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/** add a clique (top down) */ | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 		sharedClique addClique(const sharedConditional& conditional, | 
					
						
							| 
									
										
										
										
											2009-11-21 14:07:46 +08:00
										 |  |  | 				sharedClique parent_clique = sharedClique()); | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 		/** add a clique (bottom up) */ | 
					
						
							|  |  |  | 		sharedClique addClique(const sharedConditional& conditional, | 
					
						
							|  |  |  | 				std::list<sharedClique>& child_cliques); | 
					
						
							| 
									
										
										
										
											2009-11-21 11:38:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/** Create an empty Bayes Tree */ | 
					
						
							|  |  |  | 		BayesTree(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | 		/** Create a Bayes Tree from a Bayes Net */ | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 		BayesTree(const BayesNet<Conditional>& bayesNet); | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/** Destructor */ | 
					
						
							| 
									
										
										
										
											2009-11-07 23:58:45 +08:00
										 |  |  | 		virtual ~BayesTree() { | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-10-28 04:23:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 		/** print */ | 
					
						
							|  |  |  | 		void print(const std::string& s = "") const; | 
					
						
							| 
									
										
										
										
											2009-10-28 04:23:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 		/** saves the Tree to a text file in GraphViz format */ | 
					
						
							|  |  |  | 		void saveGraph(const std::string& s) const; | 
					
						
							|  |  |  | 	private: | 
					
						
							|  |  |  | 		void saveGraph(std::ostream &s, sharedClique clique, | 
					
						
							| 
									
										
										
										
											2010-02-10 05:32:14 +08:00
										 |  |  | 				int parentnum = 0) const; | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 		/** check equality */ | 
					
						
							|  |  |  | 		bool equals(const BayesTree<Conditional>& other, double tol = 1e-9) const; | 
					
						
							| 
									
										
										
										
											2009-10-28 04:23:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-22 10:27:26 +08:00
										 |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Find parent clique of a conditional, given an IndexTable constructed from an ordering. | 
					
						
							|  |  |  | 		 * It will look at all parents and return the one with the lowest index in the ordering. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		Symbol findParentClique(const std::list<Symbol>& parents, const IndexTable<Symbol>& index) const; | 
					
						
							| 
									
										
										
										
											2010-01-20 09:52:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 		/** insert a new conditional */ | 
					
						
							| 
									
										
										
										
											2010-01-22 10:27:26 +08:00
										 |  |  | 		void insert(const sharedConditional& conditional, const IndexTable<Symbol>& index); | 
					
						
							| 
									
										
										
										
											2009-10-28 04:23:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-13 15:09:27 +08:00
										 |  |  | 		/** insert a new clique corresponding to the given bayes net.
 | 
					
						
							|  |  |  | 		 * it is the caller's responsibility to decide whether the given bayes net is a valid clique, | 
					
						
							|  |  |  | 		 * i.e. all the variables (frontal and separator) are connected */ | 
					
						
							|  |  |  | 		sharedClique insert(const BayesNet<Conditional>& bayesNet, | 
					
						
							|  |  |  | 				std::list<sharedClique>& children, bool isRootClique = false); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-07 23:58:45 +08:00
										 |  |  | 		/** number of cliques */ | 
					
						
							|  |  |  | 		inline size_t size() const { | 
					
						
							| 
									
										
										
										
											2010-01-20 12:23:35 +08:00
										 |  |  | 			if(root_) | 
					
						
							|  |  |  | 				return root_->treeSize(); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				return 0; | 
					
						
							| 
									
										
										
										
											2009-11-07 23:58:45 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-10-31 22:12:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-31 13:12:39 +08:00
										 |  |  | 		/** return root clique */ | 
					
						
							| 
									
										
										
										
											2009-11-08 01:24:05 +08:00
										 |  |  | 		sharedClique root() const { | 
					
						
							| 
									
										
										
										
											2009-11-07 23:58:45 +08:00
										 |  |  | 			return root_; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-10-28 04:23:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-06 13:55:29 +08:00
										 |  |  | 		/** find the clique to which key belongs */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		sharedClique operator[](const Symbol& key) const { | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 			return nodes_.at(key); | 
					
						
							| 
									
										
										
										
											2009-11-06 13:55:29 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 		/** clique statistics */ | 
					
						
							|  |  |  | 		struct CliqueStats { | 
					
						
							|  |  |  | 			double avgConditionalSize; | 
					
						
							|  |  |  | 			std::size_t maxConditionalSize; | 
					
						
							|  |  |  | 			double avgSeparatorSize; | 
					
						
							|  |  |  | 			std::size_t maxSeparatorSize; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 		struct CliqueData { | 
					
						
							|  |  |  | 			std::vector<std::size_t> conditionalSizes; | 
					
						
							|  |  |  | 			std::vector<std::size_t> separatorSizes; | 
					
						
							|  |  |  | 			CliqueStats getStats() const; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 		CliqueData getCliqueData() const; | 
					
						
							| 
									
										
										
										
											2010-01-23 07:52:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 	private: | 
					
						
							|  |  |  | 		void getCliqueData(CliqueData& stats, sharedClique clique) const; | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-04 11:22:29 +08:00
										 |  |  | 		/** return marginal on any variable */ | 
					
						
							| 
									
										
										
										
											2009-11-05 14:30:50 +08:00
										 |  |  | 		template<class Factor> | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		FactorGraph<Factor> marginal(const Symbol& key) const; | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/** return marginal on any variable, as a Bayes Net */ | 
					
						
							|  |  |  | 		template<class Factor> | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		BayesNet<Conditional> marginalBayesNet(const Symbol& key) const; | 
					
						
							| 
									
										
										
										
											2009-11-09 08:13:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/** return joint on two variables */ | 
					
						
							|  |  |  | 		template<class Factor> | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		FactorGraph<Factor> joint(const Symbol& key1, const Symbol& key2) const; | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/** return joint on two variables as a BayesNet */ | 
					
						
							|  |  |  | 		template<class Factor> | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		BayesNet<Conditional> jointBayesNet(const Symbol& key1, const Symbol& key2) const; | 
					
						
							| 
									
										
										
										
											2009-11-23 00:04:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 12:23:35 +08:00
										 |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Remove all nodes | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		void clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Remove path from clique to root and return that path as factors | 
					
						
							|  |  |  | 		 * plus a list of orphaned subtree roots. Used in removeTop below. | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2010-01-21 08:38:22 +08:00
										 |  |  | 		void removePath(sharedClique clique, BayesNet<Conditional>& bn, Cliques& orphans); | 
					
						
							| 
									
										
										
										
											2009-11-23 00:04:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 		/**
 | 
					
						
							| 
									
										
										
										
											2010-01-19 06:37:44 +08:00
										 |  |  | 		 * Given a list of keys, turn "contaminated" part of the tree back into a factor graph. | 
					
						
							| 
									
										
										
										
											2009-11-23 08:02:06 +08:00
										 |  |  | 		 * Factors and orphans are added to the in/out arguments. | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2010-01-21 08:38:22 +08:00
										 |  |  | 		void removeTop(const std::list<Symbol>& keys,	BayesNet<Conditional>& bn, Cliques& orphans); | 
					
						
							| 
									
										
										
										
											2009-11-23 01:34:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-28 07:15:36 +08:00
										 |  |  | 	}; // BayesTree
 | 
					
						
							| 
									
										
										
										
											2009-10-28 04:23:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | } /// namespace gtsam
 |