| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  |  * @file    GaussianFactor.cpp | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |  * @brief   Linear Factor....A Gaussian | 
					
						
							|  |  |  |  * @brief   linearFactor | 
					
						
							|  |  |  |  * @author  Christian Potthast | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/foreach.hpp>
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | #include <boost/assign/list_inserter.hpp> // for 'insert()'
 | 
					
						
							|  |  |  | #include <boost/assign/std/list.hpp> // for operator += in Ordering
 | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "Matrix.h"
 | 
					
						
							|  |  |  | #include "Ordering.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-13 00:41:18 +08:00
										 |  |  | #include "GaussianConditional.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | #include "GaussianFactor.h"
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | using namespace boost::assign; | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | namespace ublas = boost::numeric::ublas; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // trick from some reading group
 | 
					
						
							|  |  |  | #define FOREACH_PAIR( KEY, VAL, COL) BOOST_FOREACH (boost::tie(KEY,VAL),COL) 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef pair<const string, Matrix>& mypair; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-13 00:41:18 +08:00
										 |  |  | GaussianFactor::GaussianFactor(const boost::shared_ptr<GaussianConditional>& cg) : | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 	b_(cg->get_d()) { | 
					
						
							|  |  |  | 	As_.insert(make_pair(cg->key(), cg->get_R())); | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | 	std::map<std::string, Matrix>::const_iterator it = cg->parentsBegin(); | 
					
						
							|  |  |  | 	for (; it != cg->parentsEnd(); it++) { | 
					
						
							|  |  |  | 		const std::string& j = it->first; | 
					
						
							|  |  |  | 		const Matrix& Aj = it->second; | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 		As_.insert(make_pair(j, Aj)); | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 	// set sigmas from precisions
 | 
					
						
							|  |  |  | 	size_t n = b_.size(); | 
					
						
							| 
									
										
										
										
											2009-11-05 14:59:59 +08:00
										 |  |  | 	sigmas_ = cg->get_sigmas(); | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | GaussianFactor::GaussianFactor(const vector<shared_ptr> & factors) | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 	bool verbose = false; | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | 	if (verbose) cout << "GaussianFactor::GaussianFactor (factors)" << endl; | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 14:59:59 +08:00
										 |  |  | 	// Create RHS and sigmas of right size by adding together row counts
 | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  |   size_t m = 0; | 
					
						
							|  |  |  |   BOOST_FOREACH(shared_ptr factor, factors) m += factor->numberOfRows(); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   b_ = Vector(m); | 
					
						
							|  |  |  |   sigmas_ = Vector(m); | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   size_t pos = 0; // save last position inserted into the new rhs vector
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // iterate over all factors
 | 
					
						
							|  |  |  |   BOOST_FOREACH(shared_ptr factor, factors){ | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   	if (verbose) factor->print(); | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  |     // number of rows for factor f
 | 
					
						
							|  |  |  |     const size_t mf = factor->numberOfRows(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // copy the rhs vector from factor to b
 | 
					
						
							|  |  |  |     const Vector bf = factor->get_b(); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |     for (size_t i=0; i<mf; i++) b_(pos+i) = bf(i); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 14:59:59 +08:00
										 |  |  |     // copy the sigmas_
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |     for (size_t i=0; i<mf; i++) sigmas_(pos+i) = factor->sigmas_(i); | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // update the matrices
 | 
					
						
							|  |  |  |     append_factor(factor,m,pos); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pos += mf; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | 	if (verbose) cout << "GaussianFactor::GaussianFactor done" << endl; | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | void GaussianFactor::print(const string& s) const { | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   cout << s << endl; | 
					
						
							|  |  |  |   if (empty()) cout << " empty" << endl;  | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     string j; Matrix A; | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |     FOREACH_PAIR(j,A,As_) gtsam::print(A, "A["+j+"]=\n"); | 
					
						
							|  |  |  |     gtsam::print(b_,"b="); | 
					
						
							|  |  |  |     gtsam::print(sigmas_, "sigmas = "); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | size_t GaussianFactor::getDim(const std::string& key) const { | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 	const_iterator it = As_.find(key); | 
					
						
							|  |  |  | 	if (it != As_.end()) | 
					
						
							|  |  |  | 		return it->second.size2(); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | // Check if two linear factors are equal
 | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | bool GaussianFactor::equals(const Factor<VectorConfig>& f, double tol) const { | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  |   const GaussianFactor* lf = dynamic_cast<const GaussianFactor*>(&f); | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  |   if (lf == NULL) return false; | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  |   if (empty()) return (lf->empty()); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   const_iterator it1 = As_.begin(), it2 = lf->As_.begin(); | 
					
						
							|  |  |  |   if(As_.size() != lf->As_.size()) return false; | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   for(; it1 != As_.end(); it1++, it2++) { | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |     const string& j1 = it1->first, j2 = it2->first; | 
					
						
							|  |  |  |     const Matrix A1 = it1->second, A2 = it2->second; | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  |     if (j1 != j2) return false; | 
					
						
							|  |  |  |     if (!equal_with_abs_tol(A1,A2,tol)) | 
					
						
							|  |  |  |       return false; | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   if( !(::equal_with_abs_tol(b_, (lf->b_),tol)) ) | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  |     return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   if( !(::equal_with_abs_tol(sigmas_, (lf->sigmas_),tol)) ) | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | // we might have multiple As, so iterate and subtract from b
 | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | double GaussianFactor::error(const VectorConfig& c) const { | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  |   if (empty()) return 0; | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   Vector e = b_; | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  |   string j; Matrix Aj; | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   FOREACH_PAIR(j, Aj, As_) | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  |     e -= Vector(Aj * c[j]); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   Vector weighted = ediv(e,sigmas_); | 
					
						
							|  |  |  |   return 0.5 * inner_prod(weighted,weighted); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-12 11:50:44 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | list<string> GaussianFactor::keys() const { | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  | 	list<string> result; | 
					
						
							| 
									
										
										
										
											2009-09-12 11:50:44 +08:00
										 |  |  |   string j; Matrix A; | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   FOREACH_PAIR(j,A,As_) | 
					
						
							| 
									
										
										
										
											2009-09-13 12:13:03 +08:00
										 |  |  |     result.push_back(j); | 
					
						
							| 
									
										
										
										
											2009-09-12 11:50:44 +08:00
										 |  |  |   return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | Dimensions GaussianFactor::dimensions() const { | 
					
						
							| 
									
										
										
										
											2009-11-06 13:43:03 +08:00
										 |  |  |   Dimensions result; | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   string j; Matrix A; | 
					
						
							| 
									
										
										
										
											2009-11-06 13:43:03 +08:00
										 |  |  |   FOREACH_PAIR(j,A,As_) | 
					
						
							|  |  |  |     result.insert(make_pair(j,A.size2())); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | void GaussianFactor::tally_separator(const string& key, set<string>& separator) const { | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   if(involves(key)) { | 
					
						
							|  |  |  |     string j; Matrix A; | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |     FOREACH_PAIR(j,A,As_) | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |       if(j != key) separator.insert(j); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */   | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | pair<Matrix,Vector> GaussianFactor::matrix(const Ordering& ordering, bool weight) const { | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-06 21:43:39 +08:00
										 |  |  | 	// get pointers to the matrices
 | 
					
						
							|  |  |  | 	vector<const Matrix *> matrices; | 
					
						
							|  |  |  | 	BOOST_FOREACH(string j, ordering) { | 
					
						
							|  |  |  | 		const Matrix& Aj = get_A(j); | 
					
						
							|  |  |  | 		matrices.push_back(&Aj); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-11 22:42:09 +08:00
										 |  |  | 	// assemble
 | 
					
						
							|  |  |  | 	Matrix A = collect(matrices); | 
					
						
							| 
									
										
										
										
											2009-11-06 21:43:39 +08:00
										 |  |  | 	Vector b(b_); | 
					
						
							| 
									
										
										
										
											2009-11-11 22:42:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// divide in sigma so error is indeed 0.5*|Ax-b|
 | 
					
						
							|  |  |  | 	if (weight) { | 
					
						
							|  |  |  | 		Vector t = ediv(ones(sigmas_.size()),sigmas_); | 
					
						
							|  |  |  | 		A = vector_scale(A, t); | 
					
						
							|  |  |  | 		for (int i=0; i<b_.size(); ++i) | 
					
						
							|  |  |  | 			b(i) *= t(i); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-06 21:43:39 +08:00
										 |  |  | 	return make_pair(A, b); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 23:08:58 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | Matrix GaussianFactor::matrix_augmented(const Ordering& ordering) const { | 
					
						
							| 
									
										
										
										
											2009-11-05 23:08:58 +08:00
										 |  |  | 	// get pointers to the matrices
 | 
					
						
							|  |  |  | 	vector<const Matrix *> matrices; | 
					
						
							|  |  |  | 	BOOST_FOREACH(string j, ordering) { | 
					
						
							|  |  |  | 		const Matrix& Aj = get_A(j); | 
					
						
							|  |  |  | 		matrices.push_back(&Aj); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// load b into a matrix
 | 
					
						
							|  |  |  | 	Matrix B_mat(numberOfRows(), 1); | 
					
						
							|  |  |  | 	for (int i=0; i<b_.size(); ++i) | 
					
						
							|  |  |  | 		B_mat(i,0) = b_(i); | 
					
						
							|  |  |  | 	matrices.push_back(&B_mat); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 05:34:20 +08:00
										 |  |  | 	return collect(matrices); | 
					
						
							| 
									
										
										
										
											2009-11-05 23:08:58 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-06 13:43:03 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | boost::tuple<list<int>, list<int>, list<double> > | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | GaussianFactor::sparse(const Ordering& ordering, const Dimensions& variables) const { | 
					
						
							| 
									
										
										
										
											2009-11-06 13:43:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// declare return values
 | 
					
						
							|  |  |  | 	list<int> I,J; | 
					
						
							|  |  |  | 	list<double> S; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// loop over all variables in correct order
 | 
					
						
							|  |  |  | 	size_t column_start = 1; | 
					
						
							|  |  |  | 	BOOST_FOREACH(string key, ordering) { | 
					
						
							|  |  |  | 		try { | 
					
						
							|  |  |  | 			const Matrix& Aj = get_A(key); | 
					
						
							|  |  |  | 			for (size_t i = 0; i < Aj.size1(); i++) { | 
					
						
							|  |  |  | 				double sigma_i = sigmas_(i); | 
					
						
							|  |  |  | 				for (size_t j = 0; j < Aj.size2(); j++) | 
					
						
							|  |  |  | 					if (Aj(i, j) != 0.0) { | 
					
						
							|  |  |  | 						I.push_back(i + 1); | 
					
						
							|  |  |  | 						J.push_back(j + column_start); | 
					
						
							|  |  |  | 						S.push_back(Aj(i, j) / sigma_i); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} catch (std::invalid_argument& exception) { | 
					
						
							|  |  |  | 			// it's ok to not have a key in the ordering
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// find dimension for this key
 | 
					
						
							|  |  |  | 		Dimensions::const_iterator it = variables.find(key); | 
					
						
							|  |  |  | 		// TODO: check if end() and throw exception if not found
 | 
					
						
							|  |  |  | 		int dim = it->second; | 
					
						
							|  |  |  | 		// advance column index to next block by adding dim(key)
 | 
					
						
							|  |  |  | 		column_start += dim; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// return the result
 | 
					
						
							|  |  |  | 	return boost::tuple<list<int>, list<int>, list<double> >(I,J,S); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | void GaussianFactor::append_factor(GaussianFactor::shared_ptr f, const size_t m, | 
					
						
							| 
									
										
										
										
											2009-10-24 12:07:32 +08:00
										 |  |  | 		const size_t pos) { | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 	bool verbose = false; | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | 	if (verbose) cout << "GaussianFactor::append_factor" << endl; | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-24 12:07:32 +08:00
										 |  |  | 	// iterate over all matrices from the factor f
 | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | 	GaussianFactor::const_iterator it = f->begin(); | 
					
						
							| 
									
										
										
										
											2009-10-24 12:07:32 +08:00
										 |  |  | 	for (; it != f->end(); it++) { | 
					
						
							|  |  |  | 		string j = it->first; | 
					
						
							|  |  |  | 		Matrix A = it->second; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// find rows and columns
 | 
					
						
							|  |  |  | 		const size_t mrhs = A.size1(), n = A.size2(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// find the corresponding matrix among As
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 		const_iterator mine = As_.find(j); | 
					
						
							|  |  |  | 		const bool exists = mine != As_.end(); | 
					
						
							| 
									
										
										
										
											2009-10-24 12:07:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// create the matrix or use existing
 | 
					
						
							|  |  |  | 		Matrix Anew = exists ? mine->second : zeros(m, n); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// copy the values in the existing matrix
 | 
					
						
							|  |  |  | 		for (size_t i = 0; i < mrhs; i++) | 
					
						
							|  |  |  | 			for (size_t j = 0; j < n; j++) | 
					
						
							|  |  |  | 				Anew(pos + i, j) = A(i, j); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// insert the matrix into the factor
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 		if (exists) As_.erase(j); | 
					
						
							| 
									
										
										
										
											2009-10-24 12:07:32 +08:00
										 |  |  | 		insert(j, Anew); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | 	if (verbose) cout << "GaussianFactor::append_factor done" << endl; | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | /* Note, in place !!!!
 | 
					
						
							|  |  |  |  * Do incomplete QR factorization for the first n columns | 
					
						
							|  |  |  |  * We will do QR on all matrices and on RHS | 
					
						
							| 
									
										
										
										
											2009-11-13 00:41:18 +08:00
										 |  |  |  * Then take first n rows and make a GaussianConditional, | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |  * and last rows to make a new joint linear factor on separator | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-13 00:41:18 +08:00
										 |  |  | pair<GaussianConditional::shared_ptr, GaussianFactor::shared_ptr> | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | GaussianFactor::eliminate(const string& key) const | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 	bool verbose = false; | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | 	if (verbose) cout << "GaussianFactor::eliminate(" << key << ")" << endl; | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// if this factor does not involve key, we exit with empty CG and LF
 | 
					
						
							| 
									
										
										
										
											2009-11-12 12:53:28 +08:00
										 |  |  | 	const_iterator it = As_.find(key); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 	if (it==As_.end()) { | 
					
						
							|  |  |  | 		// Conditional Gaussian is just a parent-less node with P(x)=1
 | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | 		GaussianFactor::shared_ptr lf(new GaussianFactor); | 
					
						
							| 
									
										
										
										
											2009-11-13 00:41:18 +08:00
										 |  |  | 		GaussianConditional::shared_ptr cg(new GaussianConditional(key)); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 		return make_pair(cg,lf); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// create an internal ordering that eliminates key first
 | 
					
						
							|  |  |  | 	Ordering ordering; | 
					
						
							|  |  |  | 	ordering += key; | 
					
						
							|  |  |  | 	BOOST_FOREACH(string k, keys()) | 
					
						
							|  |  |  | 		if (k != key) ordering += k; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// extract A, b from the combined linear factor (ensure that x is leading)
 | 
					
						
							| 
									
										
										
										
											2009-11-11 22:42:09 +08:00
										 |  |  | 	Matrix A; Vector b; | 
					
						
							|  |  |  | 	boost::tie(A, b) = matrix(ordering, false); | 
					
						
							|  |  |  | 	size_t n = A.size2(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Do in-place QR to get R, d of the augmented system
 | 
					
						
							| 
									
										
										
										
											2009-11-13 14:13:58 +08:00
										 |  |  | 	if (verbose) ::print(A,"A"); | 
					
						
							|  |  |  | 	if (verbose) ::print(b,"b = "); | 
					
						
							|  |  |  | 	if (verbose) ::print(sigmas_,"sigmas = "); | 
					
						
							| 
									
										
										
										
											2009-11-11 22:42:09 +08:00
										 |  |  | 	std::list<boost::tuple<Vector, double, double> > solution = | 
					
						
							|  |  |  | 							weighted_eliminate(A, b, sigmas_); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// get dimensions of the eliminated variable
 | 
					
						
							|  |  |  | 	size_t n1 = getDim(key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// if m<n1, this factor cannot be eliminated
 | 
					
						
							| 
									
										
										
										
											2009-11-11 22:42:09 +08:00
										 |  |  | 	size_t maxRank = solution.size(); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 	if (maxRank<n1) | 
					
						
							| 
									
										
										
										
											2009-11-13 00:16:32 +08:00
										 |  |  | 		throw(domain_error("GaussianFactor::eliminate: fewer constraints than unknowns")); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-11 22:42:09 +08:00
										 |  |  | 	// unpack the solutions
 | 
					
						
							|  |  |  | 	Matrix R(maxRank, n); | 
					
						
							|  |  |  | 	Vector r, d(maxRank), newSigmas(maxRank); double di, sigma; | 
					
						
							|  |  |  | 	Matrix::iterator2 Rit = R.begin2(); | 
					
						
							|  |  |  | 	size_t i = 0; | 
					
						
							|  |  |  | 	BOOST_FOREACH(boost::tie(r, di, sigma), solution) { | 
					
						
							|  |  |  | 		copy(r.begin(), r.end(), Rit); // copy r vector
 | 
					
						
							|  |  |  | 		d(i) = di;                     // copy in rhs
 | 
					
						
							|  |  |  | 		newSigmas(i) = sigma;          // copy in new sigmas
 | 
					
						
							|  |  |  | 		Rit += n; i += 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// create base conditional Gaussian
 | 
					
						
							| 
									
										
										
										
											2009-11-13 14:13:58 +08:00
										 |  |  | 	GaussianConditional::shared_ptr conditional(new GaussianConditional(key, | 
					
						
							| 
									
										
										
										
											2009-11-11 22:42:09 +08:00
										 |  |  | 			sub(d, 0, n1),            // form d vector
 | 
					
						
							|  |  |  | 			sub(R, 0, n1, 0, n1),     // form R matrix
 | 
					
						
							|  |  |  | 			sub(newSigmas, 0, n1)));  // get standard deviations
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// extract the block matrices for parents in both CG and LF
 | 
					
						
							| 
									
										
										
										
											2009-11-13 14:13:58 +08:00
										 |  |  | 	GaussianFactor::shared_ptr factor(new GaussianFactor); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 	size_t j = n1; | 
					
						
							|  |  |  | 	BOOST_FOREACH(string cur_key, ordering) | 
					
						
							|  |  |  | 		if (cur_key!=key) { | 
					
						
							|  |  |  | 			size_t dim = getDim(cur_key); | 
					
						
							| 
									
										
										
										
											2009-11-13 14:13:58 +08:00
										 |  |  | 			conditional->add(cur_key, sub(R, 0, n1, j, j+dim)); | 
					
						
							|  |  |  | 			factor->insert(cur_key, sub(R, n1, maxRank, j, j+dim)); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 			j+=dim; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Set sigmas
 | 
					
						
							| 
									
										
										
										
											2009-11-13 14:13:58 +08:00
										 |  |  | 	factor->sigmas_ = sub(newSigmas,n1,maxRank); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// extract ds vector for the new b
 | 
					
						
							| 
									
										
										
										
											2009-11-13 14:13:58 +08:00
										 |  |  | 	factor->set_b(sub(d, n1, maxRank)); | 
					
						
							|  |  |  | 	if (verbose) conditional->print("Conditional"); | 
					
						
							|  |  |  | 	if (verbose) factor->print("Factor"); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 14:13:58 +08:00
										 |  |  | 	return make_pair(conditional, factor); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-10-27 21:33:44 +08:00
										 |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	string symbol(char c, int index) { | 
					
						
							|  |  |  | 		stringstream ss; | 
					
						
							|  |  |  | 		ss << c << index; | 
					
						
							|  |  |  | 		return ss.str(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ |