| 
									
										
										
										
											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 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #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>
 | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | #include <colamd/colamd.h>
 | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | #include "Ordering.h"
 | 
					
						
							|  |  |  | #include "FactorGraph.h"
 | 
					
						
							| 
									
										
										
										
											2010-01-14 10:07:14 +08:00
										 |  |  | #include "graph-inl.h"
 | 
					
						
							| 
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 |  |  | #include "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 { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 12:56:59 +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++) { | 
					
						
							| 
									
										
										
										
											2009-11-08 03:31:39 +08:00
										 |  |  | 		sharedFactor factor(new Factor(*it)); | 
					
						
							| 
									
										
										
										
											2009-11-05 12:56:59 +08:00
										 |  |  | 		push_back(factor); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-10-29 12:11:23 +08:00
										 |  |  | template<class Factor> | 
					
						
							|  |  |  | void FactorGraph<Factor>::print(const string& s) const { | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | 	cout << s << endl; | 
					
						
							|  |  |  | 	printf("size: %d\n", (int) size()); | 
					
						
							| 
									
										
										
										
											2010-03-08 22:06:07 +08:00
										 |  |  | 	for (size_t i = 0; i < factors_.size(); i++) { | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | 		stringstream ss; | 
					
						
							|  |  |  | 		ss << "factor " << i << ":"; | 
					
						
							|  |  |  | 		if (factors_[i] != NULL) factors_[i]->print(ss.str()); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-10-29 12:11:23 +08:00
										 |  |  | template<class Factor> | 
					
						
							|  |  |  | bool FactorGraph<Factor>::equals | 
					
						
							|  |  |  | 	(const FactorGraph<Factor>& fg, double tol) const { | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | 	/** 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?
 | 
					
						
							| 
									
										
										
										
											2009-11-08 03:31:39 +08:00
										 |  |  | 		sharedFactor f1 = factors_[i], f2 = fg.factors_[i]; | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | 		if (f1 == NULL && f2 == NULL) continue; | 
					
						
							|  |  |  | 		if (f1 == NULL || f2 == NULL) return false; | 
					
						
							|  |  |  | 		if (!f1->equals(*f2, tol)) return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-10-29 12:11:23 +08:00
										 |  |  | template<class Factor> | 
					
						
							|  |  |  | size_t FactorGraph<Factor>::nrFactors() const { | 
					
						
							|  |  |  | 	int size_ = 0; | 
					
						
							|  |  |  | 	for (const_iterator factor = factors_.begin(); factor != factors_.end(); factor++) | 
					
						
							|  |  |  | 		if (*factor != NULL) size_++; | 
					
						
							|  |  |  | 	return size_; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Factor> | 
					
						
							| 
									
										
										
										
											2009-11-08 03:31:39 +08:00
										 |  |  | void FactorGraph<Factor>::push_back(sharedFactor factor) { | 
					
						
							| 
									
										
										
										
											2009-10-29 12:11:23 +08:00
										 |  |  | 	factors_.push_back(factor);                  // add the actual factor
 | 
					
						
							| 
									
										
										
										
											2009-10-29 12:49:13 +08:00
										 |  |  | 	if (factor==NULL) return; | 
					
						
							| 
									
										
										
										
											2009-10-29 12:11:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int i = factors_.size() - 1;                 // index of factor
 | 
					
						
							| 
									
										
										
										
											2009-12-18 08:13:38 +08:00
										 |  |  | 	associateFactor(i, factor); | 
					
						
							| 
									
										
										
										
											2009-10-23 05:33:00 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-19 14:34:07 +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-12-18 08:13:38 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Factor> | 
					
						
							|  |  |  | void FactorGraph<Factor>::replace(int 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)); | 
					
						
							|  |  |  |   //if(factors_[index] == NULL)
 | 
					
						
							|  |  |  |   //  throw invalid_argument(boost::str(boost::format(
 | 
					
						
							|  |  |  |   //      "Factor with index %d is NULL." % index)));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if(factors_[index] != NULL) { | 
					
						
							|  |  |  |     // Remove this factor from its variables' index lists
 | 
					
						
							| 
									
										
										
										
											2010-02-09 06:22:38 +08:00
										 |  |  |     BOOST_FOREACH(const Symbol& key, factors_[index]->keys()) { | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  |     	indices_.at(key).remove(index); | 
					
						
							| 
									
										
										
										
											2009-12-18 08:13:38 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Replace the factor
 | 
					
						
							|  |  |  |   factors_[index] = factor; | 
					
						
							|  |  |  |   associateFactor(index, factor); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Factor> | 
					
						
							|  |  |  | Ordering FactorGraph<Factor>::keys() const { | 
					
						
							|  |  |  | 	Ordering keys; | 
					
						
							| 
									
										
										
										
											2009-11-20 22:18:26 +08:00
										 |  |  | 	transform(indices_.begin(), indices_.end(), | 
					
						
							|  |  |  | 			back_inserter(keys), _Select1st<Indices::value_type>()); | 
					
						
							| 
									
										
										
										
											2009-11-12 12:56:30 +08:00
										 |  |  | 	return keys; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-03 11:36:10 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Factor> | 
					
						
							|  |  |  | std::pair<FactorGraph<Factor>, set<Symbol> > FactorGraph<Factor>::removeSingletons() { | 
					
						
							|  |  |  | 	FactorGraph<Factor> singletonGraph; | 
					
						
							|  |  |  | 	set<Symbol> singletons; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(true) { | 
					
						
							|  |  |  | 		// find all the singleton variables
 | 
					
						
							|  |  |  | 		Ordering new_singletons; | 
					
						
							|  |  |  | 		Symbol key; | 
					
						
							|  |  |  | 		list<int> indices; | 
					
						
							|  |  |  | 		BOOST_FOREACH(boost::tie(key, indices), indices_) { | 
					
						
							|  |  |  | 			// find out the number of factors associated with the current key
 | 
					
						
							|  |  |  | 			int numValidFactors = 0; | 
					
						
							|  |  |  | 			BOOST_FOREACH(const int& i, indices) | 
					
						
							|  |  |  | 				if (factors_[i]!=NULL) numValidFactors++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (numValidFactors == 1) { | 
					
						
							|  |  |  | 				new_singletons.push_back(key); | 
					
						
							|  |  |  | 				BOOST_FOREACH(const int& i, indices) | 
					
						
							|  |  |  | 					if (factors_[i]!=NULL) singletonGraph.push_back(factors_[i]); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		singletons.insert(new_singletons.begin(), new_singletons.end()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BOOST_FOREACH(const Symbol& singleton, new_singletons) | 
					
						
							|  |  |  | 			findAndRemoveFactors(singleton); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// exit when there are no more singletons
 | 
					
						
							|  |  |  | 		if (new_singletons.empty()) break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return make_pair(singletonGraph, singletons); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 05:33:00 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +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 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template <class Key> | 
					
						
							| 
									
										
										
										
											2010-02-24 14:13:11 +08:00
										 |  |  | void colamd(int n_col, int n_row, int nrNonZeros, const map<Key, vector<int> >& columns, Ordering& ordering) { | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Convert to compressed column major format colamd wants it in (== MATLAB format!)
 | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | 	vector<Key> initialOrder; | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | 	int Alen = nrNonZeros*30;     /* colamd arg 3: size of the array A TODO: use Tim's function ! */ | 
					
						
							|  |  |  | 	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 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p[0] = 0; | 
					
						
							|  |  |  | 	int j = 1; | 
					
						
							|  |  |  | 	int count = 0; | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | 	typedef typename map<Key, vector<int> >::const_iterator iterator; | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | 	for(iterator it = columns.begin(); it != columns.end(); it++) { | 
					
						
							|  |  |  | 		const Key& key = it->first; | 
					
						
							| 
									
										
										
										
											2009-10-26 06:27:18 +08:00
										 |  |  | 		const vector<int>& column = it->second; | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | 		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
 | 
					
						
							|  |  |  | 		j+=1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	double* knobs = NULL;    /* colamd arg 6: parameters (uses defaults if NULL) */ | 
					
						
							|  |  |  | 	int stats[COLAMD_STATS]; /* colamd arg 7: colamd output statistics and error codes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// call colamd, result will be in p *************************************************
 | 
					
						
							|  |  |  | 	/* TODO: returns (1) if successful, (0) otherwise*/ | 
					
						
							|  |  |  | 	::colamd(n_row, n_col, Alen, A, p, knobs, stats); | 
					
						
							|  |  |  | 	// **********************************************************************************
 | 
					
						
							|  |  |  | 	delete [] A; // delete symbolic A
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Convert elimination ordering in p to an ordering
 | 
					
						
							|  |  |  | 	for(int j = 0; j < n_col; j++) | 
					
						
							| 
									
										
										
										
											2010-02-24 14:13:11 +08:00
										 |  |  | 		ordering.push_back(initialOrder[p[j]]); | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | 	delete [] p; // delete colamd result vector
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-02-24 14:13:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-10-29 12:11:23 +08:00
										 |  |  | template<class Factor> | 
					
						
							| 
									
										
										
										
											2010-02-24 14:13:11 +08:00
										 |  |  | void FactorGraph<Factor>::getOrdering(Ordering& ordering) const{ | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +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-01-18 03:34:57 +08:00
										 |  |  | 	map<Symbol, vector<int> > columns; // map from keys to a sparse column of non-zero row indices
 | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | 	int nrNonZeros = 0;             // number of non-zero entries
 | 
					
						
							|  |  |  | 	int n_row = factors_.size();    /* colamd arg 1: number of rows in A */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// loop over all factors = rows
 | 
					
						
							|  |  |  | 	for (int i = 0; i < n_row; i++) { | 
					
						
							| 
									
										
										
										
											2009-10-28 04:22:02 +08:00
										 |  |  | 		if (factors_[i]==NULL) continue; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 		list<Symbol> keys = factors_[i]->keys(); | 
					
						
							|  |  |  | 		BOOST_FOREACH(const Symbol& key, keys) columns[key].push_back(i); | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | 		nrNonZeros+= keys.size(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	int n_col = (int)(columns.size()); /* colamd arg 2: number of columns in A */ | 
					
						
							| 
									
										
										
										
											2010-02-24 14:13:11 +08:00
										 |  |  | 	if(n_col != 0) | 
					
						
							| 
									
										
										
										
											2010-02-27 08:04:51 +08:00
										 |  |  | 		colamd(n_col, n_row, nrNonZeros, columns, ordering); | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-12 06:53:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-24 14:13:11 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Factor> | 
					
						
							|  |  |  | boost::shared_ptr<Ordering> FactorGraph<Factor>::getOrdering_() const{ | 
					
						
							|  |  |  | 	boost::shared_ptr<Ordering> ordering(new Ordering); | 
					
						
							|  |  |  | 	getOrdering(*ordering); | 
					
						
							| 
									
										
										
										
											2010-02-27 08:04:51 +08:00
										 |  |  | 	return ordering; | 
					
						
							| 
									
										
										
										
											2010-02-24 14:13:11 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-12 06:53:48 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Factor> | 
					
						
							|  |  |  | Ordering FactorGraph<Factor>::getOrdering() const { | 
					
						
							| 
									
										
										
										
											2010-02-24 14:13:11 +08:00
										 |  |  | 	Ordering ordering; | 
					
						
							|  |  |  | 	getOrdering(ordering); | 
					
						
							|  |  |  | 	return ordering; | 
					
						
							| 
									
										
										
										
											2009-12-12 06:53:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-29 12:49:13 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | /** O(1)                                                                     */ | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Factor> | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | list<int> FactorGraph<Factor>::factors(const Symbol& key) const { | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 	return indices_.at(key); | 
					
						
							| 
									
										
										
										
											2009-10-29 12:49:13 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-29 12:11:23 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | /** find all non-NULL factors for a variable, then set factors to NULL       */ | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Factor> | 
					
						
							|  |  |  | vector<boost::shared_ptr<Factor> > | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | FactorGraph<Factor>::findAndRemoveFactors(const Symbol& key) { | 
					
						
							| 
									
										
										
										
											2009-10-29 12:11:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-26 13:29:45 +08:00
										 |  |  | 	// find all factor indices associated with the key
 | 
					
						
							|  |  |  | 	Indices::const_iterator it = indices_.find(key); | 
					
						
							|  |  |  | 	if (it==indices_.end()) | 
					
						
							|  |  |  | 		throw std::invalid_argument( | 
					
						
							|  |  |  | 				"FactorGraph::findAndRemoveFactors: key " | 
					
						
							|  |  |  | 				+ (string)key + " not found"); | 
					
						
							|  |  |  | 	const list<int>& factorsAssociatedWithKey = it->second; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vector<sharedFactor> found; | 
					
						
							|  |  |  | 	BOOST_FOREACH(const int& i, factorsAssociatedWithKey) { | 
					
						
							|  |  |  | 		sharedFactor& fi = factors_.at(i); // throws exception !
 | 
					
						
							|  |  |  | 		if(fi == NULL) continue; // skip NULL factors
 | 
					
						
							|  |  |  | 		found.push_back(fi);     // add to found
 | 
					
						
							|  |  |  | 		fi.reset();              // set factor to NULL == remove(i)
 | 
					
						
							| 
									
										
										
										
											2009-10-29 12:11:23 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-04-03 11:36:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	indices_.erase(key); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-29 12:11:23 +08:00
										 |  |  | 	return found; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 08:13:38 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Factor> | 
					
						
							|  |  |  | void FactorGraph<Factor>::associateFactor(int index, sharedFactor factor) { | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  |   list<Symbol> keys = factor->keys();          // get keys for factor
 | 
					
						
							|  |  |  |   // rtodo: Can optimize factor->keys to return a const reference
 | 
					
						
							| 
									
										
										
										
											2009-12-18 08:13:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  |   BOOST_FOREACH(const Symbol& key, keys){             // for each key push i onto list
 | 
					
						
							| 
									
										
										
										
											2009-12-18 08:13:38 +08:00
										 |  |  |       Indices::iterator it = indices_.find(key); // old list for that key (if exists)
 | 
					
						
							|  |  |  |       if (it==indices_.end()){                   // there's no list yet
 | 
					
						
							|  |  |  |           list<int> indices(1,index);                  // so make one
 | 
					
						
							|  |  |  |           indices_.insert(make_pair(key,indices)); // insert new indices into factorMap
 | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  |         // rtodo: what is going on with this pointer?
 | 
					
						
							| 
									
										
										
										
											2009-12-18 08:13:38 +08:00
										 |  |  |           list<int> *indices_ptr = &(it->second);  // get the list
 | 
					
						
							|  |  |  |           indices_ptr->push_back(index);               // add the index i to it
 | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-13 09:29:19 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Factor> void FactorGraph<Factor>::checkGraphConsistency() const { | 
					
						
							|  |  |  |   // Consistency check for debugging
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make sure each factor is listed in its variables index lists
 | 
					
						
							|  |  |  |   for(size_t i=0; i<factors_.size(); i++) { | 
					
						
							|  |  |  |   	if(factors_[i] == NULL) { | 
					
						
							|  |  |  |   		cout << "** Warning: factor " << i << " is NULL" << endl; | 
					
						
							|  |  |  |   	} else { | 
					
						
							|  |  |  |   		// Get involved variables
 | 
					
						
							|  |  |  |   		list<Symbol> keys = factors_[i]->keys(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   		// Make sure each involved variable is listed as being associated with this factor
 | 
					
						
							|  |  |  |   		BOOST_FOREACH(const Symbol& var, keys) { | 
					
						
							|  |  |  |   			if(std::find(indices_.at(var).begin(), indices_.at(var).end(), i) == indices_.at(var).end()) | 
					
						
							|  |  |  |   				cout << "*** Factor graph inconsistency: " << (string)var << " is not mapped to factor " << i << endl; | 
					
						
							|  |  |  |   		} | 
					
						
							|  |  |  |   	} | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Make sure each factor listed for a variable actually involves that variable
 | 
					
						
							|  |  |  |   BOOST_FOREACH(const SymbolMap<list<int> >::value_type& var, indices_) { | 
					
						
							|  |  |  |   	BOOST_FOREACH(int i, var.second) { | 
					
						
							|  |  |  |   		if(i >= factors_.size()) { | 
					
						
							|  |  |  |   			cout << "*** Factor graph inconsistency: " << (string)var.first << " lists factor " << | 
					
						
							|  |  |  |   					i << " but the graph does not contain this many factors." << endl; | 
					
						
							|  |  |  |   		} | 
					
						
							|  |  |  |   		if(factors_[i] == NULL) { | 
					
						
							|  |  |  |   			cout << "*** Factor graph inconsistency: " << (string)var.first << " lists factor " << | 
					
						
							|  |  |  |   					i << " but this factor is set to NULL." << endl; | 
					
						
							|  |  |  |   		} | 
					
						
							|  |  |  |     	list<Symbol> keys = factors_[i]->keys(); | 
					
						
							|  |  |  |   		if(std::find(keys.begin(), keys.end(), var.first) == keys.end()) { | 
					
						
							|  |  |  |   			cout << "*** Factor graph inconsistency: " << (string)var.first << " lists factor " << | 
					
						
							|  |  |  |   					i << " but this factor does not involve this variable." << endl; | 
					
						
							|  |  |  |   		} | 
					
						
							|  |  |  |   	} | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-14 07:59:46 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-01-16 09:16:59 +08:00
										 |  |  | template<class Factor> template <class Key, class Factor2> | 
					
						
							| 
									
										
										
										
											2010-01-14 13:24:20 +08:00
										 |  |  | PredecessorMap<Key> FactorGraph<Factor>::findMinimumSpanningTree() const { | 
					
						
							| 
									
										
										
										
											2010-01-06 19:15:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-16 09:16:59 +08:00
										 |  |  | 	SDGraph<Key> g = gtsam::toBoostGraph<FactorGraph<Factor>, Factor2, Key>(*this); | 
					
						
							| 
									
										
										
										
											2010-01-06 19:15:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// find minimum spanning tree
 | 
					
						
							| 
									
										
										
										
											2010-01-14 11:21:07 +08:00
										 |  |  | 	vector<typename SDGraph<Key>::Vertex> p_map(boost::num_vertices(g)); | 
					
						
							| 
									
										
										
										
											2010-01-07 14:25:54 +08:00
										 |  |  | 	prim_minimum_spanning_tree(g, &p_map[0]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// convert edge to string pairs
 | 
					
						
							| 
									
										
										
										
											2010-01-14 13:24:20 +08:00
										 |  |  | 	PredecessorMap<Key> tree; | 
					
						
							| 
									
										
										
										
											2010-01-14 11:21:07 +08:00
										 |  |  | 	typename SDGraph<Key>::vertex_iterator itVertex = boost::vertices(g).first; | 
					
						
							|  |  |  | 	typename vector<typename SDGraph<Key>::Vertex>::iterator vi; | 
					
						
							| 
									
										
										
										
											2010-01-14 07:59:46 +08:00
										 |  |  | 	for (vi = p_map.begin(); vi!=p_map.end(); itVertex++, vi++) { | 
					
						
							| 
									
										
										
										
											2010-01-16 09:16:59 +08:00
										 |  |  | 		Key key = boost::get(boost::vertex_name, g, *itVertex); | 
					
						
							|  |  |  | 		Key parent = boost::get(boost::vertex_name, g, *vi); | 
					
						
							| 
									
										
										
										
											2010-01-15 00:05:04 +08:00
										 |  |  | 		tree.insert(key, parent); | 
					
						
							| 
									
										
										
										
											2010-01-06 19:15:37 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return tree; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-16 09:16:59 +08:00
										 |  |  | template<class Factor> template <class Key, class Factor2> | 
					
						
							|  |  |  | void FactorGraph<Factor>::split(const PredecessorMap<Key>& tree, FactorGraph<Factor>& Ab1, FactorGraph<Factor>& Ab2) const{ | 
					
						
							| 
									
										
										
										
											2010-01-09 03:07:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-12 05:40:56 +08:00
										 |  |  | 	BOOST_FOREACH(const sharedFactor& factor, factors_){ | 
					
						
							| 
									
										
										
										
											2010-01-09 03:07:46 +08:00
										 |  |  | 		if (factor->keys().size() > 2) | 
					
						
							|  |  |  | 			throw(invalid_argument("split: only support factors with at most two keys")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-10 07:39:11 +08:00
										 |  |  | 		if (factor->keys().size() == 1) { | 
					
						
							|  |  |  | 			Ab1.push_back(factor); | 
					
						
							| 
									
										
										
										
											2010-01-09 03:07:46 +08:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2010-01-10 07:39:11 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-01-09 03:07:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-16 09:16:59 +08:00
										 |  |  | 		boost::shared_ptr<Factor2> factor2 = boost::dynamic_pointer_cast<Factor2>(factor); | 
					
						
							|  |  |  | 		if (!factor2) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Key key1 = factor2->key1(); | 
					
						
							|  |  |  | 		Key key2 = factor2->key2(); | 
					
						
							| 
									
										
										
										
											2010-01-09 03:07:46 +08:00
										 |  |  | 		// if the tree contains the key
 | 
					
						
							| 
									
										
										
										
											2010-01-16 09:16:59 +08:00
										 |  |  | 		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); | 
					
						
							| 
									
										
										
										
											2010-01-09 03:07:46 +08:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2010-01-16 09:16:59 +08:00
										 |  |  | 			Ab2.push_back(factor2); | 
					
						
							| 
									
										
										
										
											2010-01-09 03:07:46 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 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
 | 
					
						
							|  |  |  | 	size_t m = nrFactors(); | 
					
						
							|  |  |  | 	for (size_t i=0;i<m;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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-29 13:39:13 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | /* find factors and remove them from the factor graph: O(n)                  */ | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-11 13:12:45 +08:00
										 |  |  | template<class Factor> boost::shared_ptr<Factor> | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | removeAndCombineFactors(FactorGraph<Factor>& factorGraph, const Symbol& key) | 
					
						
							| 
									
										
										
										
											2009-10-29 13:39:13 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-11 13:12:45 +08:00
										 |  |  | 	vector<boost::shared_ptr<Factor> > found = factorGraph.findAndRemoveFactors(key); | 
					
						
							|  |  |  | 	boost::shared_ptr<Factor> new_factor(new Factor(found)); | 
					
						
							| 
									
										
										
										
											2009-10-29 13:39:13 +08:00
										 |  |  | 	return new_factor; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:04:26 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-08 10:50:19 +08:00
										 |  |  | template<class Factor> | 
					
						
							|  |  |  | FactorGraph<Factor> combine(const FactorGraph<Factor>& fg1, const FactorGraph<Factor>& fg2) { | 
					
						
							|  |  |  | 	// create new linear factor graph equal to the first one
 | 
					
						
							| 
									
										
										
										
											2009-11-19 14:34:07 +08:00
										 |  |  | 	FactorGraph<Factor> fg = fg1; | 
					
						
							| 
									
										
										
										
											2009-11-08 10:50:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// add the second factors_ in the graph
 | 
					
						
							| 
									
										
										
										
											2009-11-19 14:34:07 +08:00
										 |  |  | 	fg.push_back(fg2); | 
					
						
							| 
									
										
										
										
											2009-11-08 10:50:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return fg; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | } // namespace gtsam
 |