| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file   FactorGraph-inl.h | 
					
						
							|  |  |  |  * This is a template definition file, include it where needed (only!) | 
					
						
							|  |  |  |  * so that the appropriate code is generated and link errors avoided. | 
					
						
							|  |  |  |  * @brief  Factor Graph Base Class | 
					
						
							|  |  |  |  * @author Carlos Nieto | 
					
						
							|  |  |  |  * @author Frank Dellaert | 
					
						
							|  |  |  |  * @author Alireza Fathi | 
					
						
							| 
									
										
										
										
											2010-07-10 02:15:54 +08:00
										 |  |  |  * @author Michael Kaess | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-07 02:25:04 +08:00
										 |  |  | #include <list>
 | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | #include <sstream>
 | 
					
						
							| 
									
										
										
										
											2009-11-18 05:47:42 +08:00
										 |  |  | #include <stdexcept>
 | 
					
						
							| 
									
										
										
										
											2009-11-20 22:18:26 +08:00
										 |  |  | #include <functional>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | #include <boost/foreach.hpp>
 | 
					
						
							|  |  |  | #include <boost/tuple/tuple.hpp>
 | 
					
						
							| 
									
										
										
										
											2009-12-18 08:13:38 +08:00
										 |  |  | #include <boost/format.hpp>
 | 
					
						
							| 
									
										
										
										
											2010-01-07 14:25:54 +08:00
										 |  |  | #include <boost/graph/prim_minimum_spanning_tree.hpp>
 | 
					
						
							| 
									
										
										
										
											2010-08-20 01:23:19 +08:00
										 |  |  | #include <gtsam/colamd/ccolamd.h>
 | 
					
						
							|  |  |  | #include <gtsam/inference/FactorGraph.h>
 | 
					
						
							|  |  |  | #include <gtsam/inference/graph-inl.h>
 | 
					
						
							|  |  |  | #include <gtsam/base/DSF.h>
 | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-16 09:16:59 +08:00
										 |  |  | #define INSTANTIATE_FACTOR_GRAPH(F) \
 | 
					
						
							|  |  |  |   template class FactorGraph<F>; \ | 
					
						
							|  |  |  |   /*template boost::shared_ptr<F> removeAndCombineFactors(FactorGraph<F>&, const std::string&);*/ \ | 
					
						
							|  |  |  |   template FactorGraph<F> combine(const FactorGraph<F>&, const FactorGraph<F>&); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 05:33:00 +08:00
										 |  |  | using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-14 21:55:32 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							|  |  |  | 	template<class Conditional> | 
					
						
							|  |  |  | 	FactorGraph<Factor>::FactorGraph(const BayesNet<Conditional>& bayesNet) { | 
					
						
							|  |  |  | 		typename BayesNet<Conditional>::const_iterator it = bayesNet.begin(); | 
					
						
							|  |  |  | 		for (; it != bayesNet.end(); it++) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 			sharedFactor factor(new Factor(**it)); | 
					
						
							| 
									
										
										
										
											2010-07-14 21:55:32 +08:00
										 |  |  | 			push_back(factor); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //  /* ************************************************************************* */
 | 
					
						
							|  |  |  | //  template<class Conditional>
 | 
					
						
							|  |  |  | //  FactorGraph::FactorGraph(const BayesNet<Conditional>& bayesNet, const Inference::Permutation& permutation) {
 | 
					
						
							|  |  |  | //  }
 | 
					
						
							| 
									
										
										
										
											2010-07-14 21:55:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							|  |  |  | 	void FactorGraph<Factor>::push_back(const FactorGraph<Factor>& factors) { | 
					
						
							|  |  |  | 		const_iterator factor = factors.begin(); | 
					
						
							|  |  |  | 		for (; factor != factors.end(); factor++) | 
					
						
							|  |  |  | 			push_back(*factor); | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-14 21:55:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							|  |  |  | 	void FactorGraph<Factor>::print(const string& s) const { | 
					
						
							|  |  |  | 		cout << s << endl; | 
					
						
							|  |  |  | 		printf("size: %d\n", (int) size()); | 
					
						
							|  |  |  | 		for (size_t i = 0; i < factors_.size(); i++) { | 
					
						
							|  |  |  | 			stringstream ss; | 
					
						
							|  |  |  | 			ss << "factor " << i << ":"; | 
					
						
							|  |  |  | 			if (factors_[i] != NULL) factors_[i]->print(ss.str()); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							|  |  |  | 	bool FactorGraph<Factor>::equals(const FactorGraph<Factor>& fg, double tol) const { | 
					
						
							|  |  |  | 		/** check whether the two factor graphs have the same number of factors_ */ | 
					
						
							|  |  |  | 		if (factors_.size() != fg.size()) return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/** check whether the factors_ are the same */ | 
					
						
							|  |  |  | 		for (size_t i = 0; i < factors_.size(); i++) { | 
					
						
							|  |  |  | 			// TODO: Doesn't this force order of factor insertion?
 | 
					
						
							|  |  |  | 			sharedFactor f1 = factors_[i], f2 = fg.factors_[i]; | 
					
						
							|  |  |  | 			if (f1 == NULL && f2 == NULL) continue; | 
					
						
							|  |  |  | 			if (f1 == NULL || f2 == NULL) return false; | 
					
						
							|  |  |  | 			if (!f1->equals(*f2, tol)) return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-14 21:55:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							|  |  |  | 	size_t FactorGraph<Factor>::nrFactors() const { | 
					
						
							|  |  |  | 		size_t size_ = 0; | 
					
						
							|  |  |  | 		for (const_iterator factor = factors_.begin(); factor != factors_.end(); factor++) | 
					
						
							|  |  |  | 			if (*factor != NULL) size_++; | 
					
						
							|  |  |  | 		return size_; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //	/* ************************************************************************* *
 | 
					
						
							|  |  |  | //	 * Call colamd given a column-major symbolic matrix A
 | 
					
						
							|  |  |  | //	 * @param n_col colamd arg 1: number of rows in A
 | 
					
						
							|  |  |  | //	 * @param n_row colamd arg 2: number of columns in A
 | 
					
						
							|  |  |  | //	 * @param nrNonZeros number of non-zero entries in A
 | 
					
						
							|  |  |  | //	 * @param columns map from keys to a sparse column of non-zero row indices
 | 
					
						
							|  |  |  | //	 * @param lastKeys set of keys that should appear last in the ordering
 | 
					
						
							|  |  |  | //	 * ************************************************************************* */
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //	static void colamd(int n_col, int n_row, int nrNonZeros, const map<Index, vector<int> >& columns,
 | 
					
						
							|  |  |  | //	    Ordering& ordering, const set<Index>& lastKeys) {
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | //		// Convert to compressed column major format colamd wants it in (== MATLAB format!)
 | 
					
						
							|  |  |  | //		int Alen = ccolamd_recommended(nrNonZeros, n_row, n_col); /* colamd arg 3: size of the array A */
 | 
					
						
							|  |  |  | //		int * A = new int[Alen]; /* colamd arg 4: row indices of A, of size Alen */
 | 
					
						
							|  |  |  | //		int * p = new int[n_col + 1]; /* colamd arg 5: column pointers of A, of size n_col+1 */
 | 
					
						
							|  |  |  | //		int * cmember = new int[n_col]; /* Constraint set of A, of size n_col */
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		p[0] = 0;
 | 
					
						
							|  |  |  | //		int j = 1;
 | 
					
						
							|  |  |  | //		int count = 0;
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //		typedef map<Index, vector<int> >::const_iterator iterator;
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		bool front_exists = false;
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //		vector<Index> initialOrder;
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		for (iterator it = columns.begin(); it != columns.end(); it++) {
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //			Index key = it->first;
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //			const vector<int>& column = it->second;
 | 
					
						
							|  |  |  | //			initialOrder.push_back(key);
 | 
					
						
							|  |  |  | //			BOOST_FOREACH(int i, column)
 | 
					
						
							|  |  |  | //							A[count++] = i; // copy sparse column
 | 
					
						
							|  |  |  | //			p[j] = count; // column j (base 1) goes from A[j-1] to A[j]-1
 | 
					
						
							|  |  |  | //			if (lastKeys.find(key) == lastKeys.end()) {
 | 
					
						
							|  |  |  | //				cmember[j - 1] = 0;
 | 
					
						
							|  |  |  | //				front_exists = true;
 | 
					
						
							|  |  |  | //			} else {
 | 
					
						
							|  |  |  | //				cmember[j - 1] = 1; // force lastKeys to be at the end
 | 
					
						
							|  |  |  | //			}
 | 
					
						
							|  |  |  | //			j += 1;
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | //		if (!front_exists) { // if only 1 entries, set everything to 0...
 | 
					
						
							|  |  |  | //			for (int j = 0; j < n_col; j++)
 | 
					
						
							|  |  |  | //				cmember[j] = 0;
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		double* knobs = NULL; /* colamd arg 6: parameters (uses defaults if NULL) */
 | 
					
						
							|  |  |  | //		int stats[CCOLAMD_STATS]; /* colamd arg 7: colamd output statistics and error codes */
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// call colamd, result will be in p *************************************************
 | 
					
						
							|  |  |  | //		/* TODO: returns (1) if successful, (0) otherwise*/
 | 
					
						
							|  |  |  | //		::ccolamd(n_row, n_col, Alen, A, p, knobs, stats, cmember);
 | 
					
						
							|  |  |  | //		// **********************************************************************************
 | 
					
						
							|  |  |  | //		delete[] A; // delete symbolic A
 | 
					
						
							|  |  |  | //		delete[] cmember;
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// Convert elimination ordering in p to an ordering
 | 
					
						
							|  |  |  | //		for (int j = 0; j < n_col; j++)
 | 
					
						
							|  |  |  | //			ordering.push_back(initialOrder[p[j]]);
 | 
					
						
							|  |  |  | //		delete[] p; // delete colamd result vector
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	template<class Factor>
 | 
					
						
							|  |  |  | //	void FactorGraph<Factor>::getOrdering(Ordering& ordering,
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //			const set<Index>& lastKeys,
 | 
					
						
							|  |  |  | //			boost::optional<const set<Index>&> scope) const {
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | //		// A factor graph is really laid out in row-major format, each factor a row
 | 
					
						
							|  |  |  | //		// Below, we compute a symbolic matrix stored in sparse columns.
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //		map<Index, vector<int> > columns; // map from keys to a sparse column of non-zero row indices
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		int nrNonZeros = 0; // number of non-zero entries
 | 
					
						
							|  |  |  | //		int n_row = 0; /* colamd arg 1: number of rows in A */
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// loop over all factors = rows
 | 
					
						
							|  |  |  | //		bool inserted;
 | 
					
						
							|  |  |  | //		bool hasInterested = scope.is_initialized();
 | 
					
						
							|  |  |  | //		BOOST_FOREACH(const sharedFactor& factor, factors_) {
 | 
					
						
							|  |  |  | //				if (factor == NULL) continue;
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //				const vector<Index>& keys(factor->keys());
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //				inserted = false;
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //				BOOST_FOREACH(Index key, keys) {
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //						if (!hasInterested || scope->find(key) != scope->end()) {
 | 
					
						
							|  |  |  | //							columns[key].push_back(n_row);
 | 
					
						
							|  |  |  | //							nrNonZeros++;
 | 
					
						
							|  |  |  | //							inserted = true;
 | 
					
						
							|  |  |  | //						}
 | 
					
						
							|  |  |  | //					}
 | 
					
						
							|  |  |  | //				if (inserted) n_row++;
 | 
					
						
							|  |  |  | //			}
 | 
					
						
							|  |  |  | //		int n_col = (int) (columns.size()); /* colamd arg 2: number of columns in A */
 | 
					
						
							|  |  |  | //		if (n_col != 0) colamd(n_col, n_row, nrNonZeros, columns, ordering, lastKeys);
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	template<class Factor>
 | 
					
						
							|  |  |  | //	Ordering FactorGraph<Factor>::getOrdering() const {
 | 
					
						
							|  |  |  | //		Ordering ordering;
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //		set<Index> lastKeys;
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		getOrdering(ordering, lastKeys);
 | 
					
						
							|  |  |  | //		return ordering;
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	template<class Factor>
 | 
					
						
							|  |  |  | //	boost::shared_ptr<Ordering> FactorGraph<Factor>::getOrdering_() const {
 | 
					
						
							|  |  |  | //		boost::shared_ptr<Ordering> ordering(new Ordering);
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //		set<Index> lastKeys;
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		getOrdering(*ordering, lastKeys);
 | 
					
						
							|  |  |  | //		return ordering;
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	template<class Factor>
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //	Ordering FactorGraph<Factor>::getOrdering(const set<Index>& scope) const {
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		Ordering ordering;
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //		set<Index> lastKeys;
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		getOrdering(ordering, lastKeys, scope);
 | 
					
						
							|  |  |  | //		return ordering;
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	template<class Factor>
 | 
					
						
							|  |  |  | //	Ordering FactorGraph<Factor>::getConstrainedOrdering(
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //			const set<Index>& lastKeys) const {
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		Ordering ordering;
 | 
					
						
							|  |  |  | //		getOrdering(ordering, lastKeys);
 | 
					
						
							|  |  |  | //		return ordering;
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	template<class Factor> template<class Key, class Factor2>
 | 
					
						
							|  |  |  | //	PredecessorMap<Key> FactorGraph<Factor>::findMinimumSpanningTree() const {
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		SDGraph<Key> g = gtsam::toBoostGraph<FactorGraph<Factor> , Factor2, Key>(
 | 
					
						
							|  |  |  | //				*this);
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// find minimum spanning tree
 | 
					
						
							|  |  |  | //		vector<typename SDGraph<Key>::Vertex> p_map(boost::num_vertices(g));
 | 
					
						
							|  |  |  | //		prim_minimum_spanning_tree(g, &p_map[0]);
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// convert edge to string pairs
 | 
					
						
							|  |  |  | //		PredecessorMap<Key> tree;
 | 
					
						
							|  |  |  | //		typename SDGraph<Key>::vertex_iterator itVertex = boost::vertices(g).first;
 | 
					
						
							|  |  |  | //		typename vector<typename SDGraph<Key>::Vertex>::iterator vi;
 | 
					
						
							|  |  |  | //		for (vi = p_map.begin(); vi != p_map.end(); itVertex++, vi++) {
 | 
					
						
							|  |  |  | //			Key key = boost::get(boost::vertex_name, g, *itVertex);
 | 
					
						
							|  |  |  | //			Key parent = boost::get(boost::vertex_name, g, *vi);
 | 
					
						
							|  |  |  | //			tree.insert(key, parent);
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		return tree;
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	template<class Factor> template<class Key, class Factor2>
 | 
					
						
							|  |  |  | //	void FactorGraph<Factor>::split(const PredecessorMap<Key>& tree, FactorGraph<
 | 
					
						
							|  |  |  | //			Factor>& Ab1, FactorGraph<Factor>& Ab2) const {
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		BOOST_FOREACH(const sharedFactor& factor, factors_)
 | 
					
						
							|  |  |  | //					{
 | 
					
						
							|  |  |  | //						if (factor->keys().size() > 2) throw(invalid_argument(
 | 
					
						
							|  |  |  | //								"split: only support factors with at most two keys"));
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //						if (factor->keys().size() == 1) {
 | 
					
						
							|  |  |  | //							Ab1.push_back(factor);
 | 
					
						
							|  |  |  | //							continue;
 | 
					
						
							|  |  |  | //						}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //						boost::shared_ptr<Factor2> factor2 = boost::dynamic_pointer_cast<
 | 
					
						
							|  |  |  | //								Factor2>(factor);
 | 
					
						
							|  |  |  | //						if (!factor2) continue;
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //						Key key1 = factor2->key1();
 | 
					
						
							|  |  |  | //						Key key2 = factor2->key2();
 | 
					
						
							|  |  |  | //						// if the tree contains the key
 | 
					
						
							|  |  |  | //						if ((tree.find(key1) != tree.end()
 | 
					
						
							|  |  |  | //								&& tree.find(key1)->second.compare(key2) == 0) || (tree.find(
 | 
					
						
							|  |  |  | //								key2) != tree.end() && tree.find(key2)->second.compare(key1)
 | 
					
						
							|  |  |  | //								== 0))
 | 
					
						
							|  |  |  | //							Ab1.push_back(factor2);
 | 
					
						
							|  |  |  | //						else
 | 
					
						
							|  |  |  | //							Ab2.push_back(factor2);
 | 
					
						
							|  |  |  | //					}
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	template<class Factor>
 | 
					
						
							|  |  |  | //	std::pair<FactorGraph<Factor> , FactorGraph<Factor> > FactorGraph<Factor>::splitMinimumSpanningTree() const {
 | 
					
						
							|  |  |  | //		//	create an empty factor graph T (tree) and factor graph C (constraints)
 | 
					
						
							|  |  |  | //		FactorGraph<Factor> T;
 | 
					
						
							|  |  |  | //		FactorGraph<Factor> C;
 | 
					
						
							|  |  |  | //		DSF<Symbol> dsf(keys());
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		//	while G is nonempty and T is not yet spanning
 | 
					
						
							|  |  |  | //		for (size_t i = 0; i < size(); i++) {
 | 
					
						
							|  |  |  | //			const sharedFactor& f = factors_[i];
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //			// retrieve the labels of all the keys
 | 
					
						
							|  |  |  | //			set<Symbol> labels;
 | 
					
						
							|  |  |  | //			BOOST_FOREACH(const Symbol& key, f->keys())
 | 
					
						
							|  |  |  | //							labels.insert(dsf.findSet(key));
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //			//	if that factor connects two different trees, then add it to T
 | 
					
						
							|  |  |  | //			if (labels.size() > 1) {
 | 
					
						
							|  |  |  | //				T.push_back(f);
 | 
					
						
							|  |  |  | //				set<Symbol>::const_iterator it = labels.begin();
 | 
					
						
							|  |  |  | //				Symbol root = *it;
 | 
					
						
							|  |  |  | //				for (it++; it != labels.end(); it++)
 | 
					
						
							|  |  |  | //					dsf = dsf.makeUnion(root, *it);
 | 
					
						
							|  |  |  | //			} else
 | 
					
						
							|  |  |  | //				//	otherwise add that factor to C
 | 
					
						
							|  |  |  | //				C.push_back(f);
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | //		return make_pair(T, C);
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							| 
									
										
										
										
											2010-04-03 11:36:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-14 21:55:32 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Factor> | 
					
						
							|  |  |  | 	void FactorGraph<Factor>::replace(size_t index, sharedFactor factor) { | 
					
						
							|  |  |  | 		if (index >= factors_.size()) throw invalid_argument(boost::str( | 
					
						
							|  |  |  | 				boost::format("Factor graph does not contain a factor with index %d.") | 
					
						
							|  |  |  | 						% index)); | 
					
						
							|  |  |  | 		// Replace the factor
 | 
					
						
							|  |  |  | 		factors_[index] = factor; | 
					
						
							| 
									
										
										
										
											2010-01-06 19:15:37 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	template<class Factor>
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //	std::pair<FactorGraph<Factor> , set<Index> > FactorGraph<Factor>::removeSingletons() {
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //		FactorGraph<Factor> singletonGraph;
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //		set<Index> singletons;
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | //		while (true) {
 | 
					
						
							|  |  |  | //			// find all the singleton variables
 | 
					
						
							|  |  |  | //			Ordering new_singletons;
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //			Index key;
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //			list<size_t> indices;
 | 
					
						
							|  |  |  | //			BOOST_FOREACH(boost::tie(key, indices), indices_)
 | 
					
						
							|  |  |  | //						{
 | 
					
						
							|  |  |  | //							// find out the number of factors associated with the current key
 | 
					
						
							|  |  |  | //							size_t numValidFactors = 0;
 | 
					
						
							|  |  |  | //							BOOST_FOREACH(const size_t& i, indices)
 | 
					
						
							|  |  |  | //											if (factors_[i] != NULL) numValidFactors++;
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //							if (numValidFactors == 1) {
 | 
					
						
							|  |  |  | //								new_singletons.push_back(key);
 | 
					
						
							|  |  |  | //								BOOST_FOREACH(const size_t& i, indices)
 | 
					
						
							|  |  |  | //												if (factors_[i] != NULL) singletonGraph.push_back(
 | 
					
						
							|  |  |  | //														factors_[i]);
 | 
					
						
							|  |  |  | //							}
 | 
					
						
							|  |  |  | //						}
 | 
					
						
							|  |  |  | //			singletons.insert(new_singletons.begin(), new_singletons.end());
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //			BOOST_FOREACH(const Index& singleton, new_singletons)
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //							findAndRemoveFactors(singleton);
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //			// exit when there are no more singletons
 | 
					
						
							|  |  |  | //			if (new_singletons.empty()) break;
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		return make_pair(singletonGraph, singletons);
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							| 
									
										
										
										
											2010-07-14 21:55:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 	template<class FactorGraph> | 
					
						
							|  |  |  | 	FactorGraph combine(const FactorGraph& fg1, const FactorGraph& fg2) { | 
					
						
							| 
									
										
										
										
											2010-07-14 21:55:32 +08:00
										 |  |  | 		// create new linear factor graph equal to the first one
 | 
					
						
							| 
									
										
										
										
											2010-10-10 11:10:03 +08:00
										 |  |  | 		FactorGraph fg = fg1; | 
					
						
							| 
									
										
										
										
											2010-07-14 21:55:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// add the second factors_ in the graph
 | 
					
						
							|  |  |  | 		fg.push_back(fg2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return fg; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //	/* ************************************************************************* */
 | 
					
						
							|  |  |  | //	template<class Factor> boost::shared_ptr<Factor> removeAndCombineFactors(
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //			FactorGraph<Factor>& factorGraph, const Index& key) {
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | //		// find and remove the factors associated with key
 | 
					
						
							|  |  |  | //		vector<boost::shared_ptr<Factor> > found = factorGraph.findAndRemoveFactors(key);
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// make a vector out of them and create a new factor
 | 
					
						
							|  |  |  | //		boost::shared_ptr<Factor> new_factor(new Factor(found));
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// return it
 | 
					
						
							|  |  |  | //		return new_factor;
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							| 
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-14 21:55:32 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 |  |  | } // namespace gtsam
 |