| 
									
										
										
										
											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; | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-19 05:17:25 +08:00
										 |  |  | typedef pair<Symbol,Matrix> NamedMatrix; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | GaussianFactor::GaussianFactor(const Vector& b_in) : | 
					
						
							|  |  |  | 	b_(b_in) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | GaussianFactor::GaussianFactor(const Symbol& key1, const Matrix& A1, | 
					
						
							|  |  |  | 		const Vector& b, const SharedDiagonal& model) : | 
					
						
							|  |  |  | 	model_(model),b_(b) { | 
					
						
							|  |  |  | 	As_[key1] = A1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | GaussianFactor::GaussianFactor(const Symbol& key1, const Matrix& A1, | 
					
						
							|  |  |  | 		const Symbol& key2, const Matrix& A2, | 
					
						
							|  |  |  | 		const Vector& b, const SharedDiagonal& model) : | 
					
						
							|  |  |  | 	model_(model), b_(b)  { | 
					
						
							|  |  |  | 	As_[key1] = A1; | 
					
						
							|  |  |  | 	As_[key2] = A2; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | GaussianFactor::GaussianFactor(const Symbol& key1, const Matrix& A1, | 
					
						
							|  |  |  | 		const Symbol& key2, const Matrix& A2, | 
					
						
							|  |  |  | 		const Symbol& key3, const Matrix& A3, | 
					
						
							|  |  |  | 		const Vector& b, const SharedDiagonal& model) : | 
					
						
							|  |  |  |         model_(model),b_(b)  { | 
					
						
							|  |  |  | 	As_[key1] = A1; | 
					
						
							|  |  |  | 	As_[key2] = A2; | 
					
						
							|  |  |  | 	As_[key3] = A3; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | GaussianFactor::GaussianFactor(const std::vector<std::pair<Symbol, Matrix> > &terms, | 
					
						
							|  |  |  |     const Vector &b, const SharedDiagonal& model) : | 
					
						
							|  |  |  | 	model_(model), b_(b)  { | 
					
						
							|  |  |  | 	BOOST_FOREACH(const NamedMatrix& pair, terms) | 
					
						
							|  |  |  |     As_.insert(pair); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | GaussianFactor::GaussianFactor(const std::list<std::pair<Symbol, Matrix> > &terms, | 
					
						
							|  |  |  |     const Vector &b, const SharedDiagonal& model) : | 
					
						
							|  |  |  | 	model_(model), b_(b)  { | 
					
						
							|  |  |  | 	BOOST_FOREACH(const NamedMatrix& pair, terms) | 
					
						
							|  |  |  | 		As_.insert(pair); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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()) { | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 	As_.insert(NamedMatrix(cg->key(), cg->get_R())); | 
					
						
							| 
									
										
										
										
											2010-01-22 12:41:40 +08:00
										 |  |  | 	SymbolMap<Matrix>::const_iterator it = cg->parentsBegin(); | 
					
						
							| 
									
										
										
										
											2010-02-26 12:03:56 +08:00
										 |  |  | 	for (; it != cg->parentsEnd(); it++) | 
					
						
							|  |  |  | 		As_.insert(*it); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 	// set sigmas from precisions
 | 
					
						
							|  |  |  | 	size_t n = b_.size(); | 
					
						
							| 
									
										
										
										
											2010-05-17 01:08:14 +08:00
										 |  |  | 	model_ = noiseModel::Diagonal::Sigmas(cg->get_sigmas(), true); | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2010-02-22 01:06:11 +08:00
										 |  |  |   BOOST_FOREACH(const shared_ptr& factor, factors) m += factor->numberOfRows(); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   b_ = Vector(m); | 
					
						
							| 
									
										
										
										
											2010-01-19 12:39:28 +08:00
										 |  |  |   Vector sigmas(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
 | 
					
						
							| 
									
										
										
										
											2010-01-27 12:39:35 +08:00
										 |  |  |   bool constrained = false; | 
					
						
							| 
									
										
										
										
											2010-02-22 01:06:11 +08:00
										 |  |  |   BOOST_FOREACH(const 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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-19 12:39:28 +08:00
										 |  |  |     // copy the model_
 | 
					
						
							|  |  |  |     for (size_t i=0; i<mf; i++) sigmas(pos+i) = factor->model_->sigma(i); | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // update the matrices
 | 
					
						
							|  |  |  |     append_factor(factor,m,pos); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-27 12:39:35 +08:00
										 |  |  |     // check if there are constraints
 | 
					
						
							|  |  |  |     if (verbose) factor->model_->print("Checking for zeros"); | 
					
						
							|  |  |  |     if (!constrained && factor->model_->isConstrained()) { | 
					
						
							|  |  |  |     	constrained = true; | 
					
						
							|  |  |  |     	if (verbose) cout << "Found a constraint!" << endl; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  |     pos += mf; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-01-27 12:39:35 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (verbose) cout << "GaussianFactor::GaussianFactor done" << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (constrained) { | 
					
						
							|  |  |  | 	  model_ = noiseModel::Constrained::MixedSigmas(sigmas); | 
					
						
							|  |  |  | 	  if (verbose) model_->print("Just created Constraint ^"); | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  | 	  model_ = noiseModel::Diagonal::Sigmas(sigmas); | 
					
						
							|  |  |  | 	  if (verbose) model_->print("Just created Diagonal"); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  |   	BOOST_FOREACH(const NamedMatrix& jA, As_) | 
					
						
							|  |  |  |   		gtsam::print(jA.second, "A["+(string)jA.first+"]=\n"); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |     gtsam::print(b_,"b="); | 
					
						
							| 
									
										
										
										
											2010-01-19 12:39:28 +08:00
										 |  |  |     model_->print("model"); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | size_t GaussianFactor::getDim(const Symbol& 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  |   // check whether each row is up to a sign
 | 
					
						
							|  |  |  |   for (int i=0; i<b_.size(); i++) { | 
					
						
							|  |  |  |   	list<Vector> row1; | 
					
						
							|  |  |  |   	list<Vector> row2; | 
					
						
							|  |  |  |   	row1.push_back(Vector_(1,     b_(i))); | 
					
						
							|  |  |  |   	row2.push_back(Vector_(1, lf->b_(i))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   	for(; it1 != As_.end(); it1++, it2++) { | 
					
						
							|  |  |  |   		const Symbol& j1 = it1->first, j2 = it2->first; | 
					
						
							|  |  |  |   		const Matrix A1 = it1->second, A2 = it2->second; | 
					
						
							|  |  |  |   		if (j1 != j2) return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   		row1.push_back(row_(A1,i)); | 
					
						
							|  |  |  |   		row2.push_back(row_(A2,i)); | 
					
						
							|  |  |  |   	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   	Vector r1 = concatVectors(row1); | 
					
						
							|  |  |  |   	Vector r2 = concatVectors(row2); | 
					
						
							|  |  |  |   	if( !::equal_with_abs_tol(r1,      r2, tol) && | 
					
						
							|  |  |  |   			!::equal_with_abs_tol(r1*(-1), r2, tol)) { | 
					
						
							|  |  |  |   		return false; | 
					
						
							|  |  |  |   	} | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-19 12:39:28 +08:00
										 |  |  |   return model_->equals(*(lf->model_),tol); | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 01:23:24 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-12-12 02:03:43 +08:00
										 |  |  | Vector GaussianFactor::unweighted_error(const VectorConfig& c) const { | 
					
						
							| 
									
										
										
										
											2009-12-12 01:42:54 +08:00
										 |  |  |   Vector e = -b_; | 
					
						
							|  |  |  |   if (empty()) return e; | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 	BOOST_FOREACH(const NamedMatrix& jA, As_) | 
					
						
							|  |  |  |     e += (jA.second * c[jA.first]); | 
					
						
							| 
									
										
										
										
											2009-12-12 02:03:43 +08:00
										 |  |  |   return e; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | Vector GaussianFactor::error_vector(const VectorConfig& c) const { | 
					
						
							| 
									
										
										
										
											2010-01-19 12:39:28 +08:00
										 |  |  | 	if (empty()) return model_->whiten(-b_); | 
					
						
							|  |  |  | 	return model_->whiten(unweighted_error(c)); | 
					
						
							| 
									
										
										
										
											2009-12-12 01:42:54 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | double GaussianFactor::error(const VectorConfig& c) const { | 
					
						
							|  |  |  |   if (empty()) return 0; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  |   Vector weighted = error_vector(c); // rtodo: copying vector here?
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  |   return 0.5 * inner_prod(weighted,weighted); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-12 11:50:44 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | list<Symbol> GaussianFactor::keys() const { | 
					
						
							|  |  |  | 	list<Symbol> result; | 
					
						
							| 
									
										
										
										
											2010-01-19 05:17:25 +08:00
										 |  |  | 	typedef pair<Symbol,Matrix> NamedMatrix; | 
					
						
							|  |  |  | 	BOOST_FOREACH(const NamedMatrix& jA, As_) | 
					
						
							|  |  |  |     result.push_back(jA.first); | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  |   BOOST_FOREACH(const NamedMatrix& jA, As_) | 
					
						
							|  |  |  | 		result.insert(std::pair<Symbol,int>(jA.first,jA.second.size2())); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | void GaussianFactor::tally_separator(const Symbol& key, set<Symbol>& separator) const { | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   if(involves(key)) { | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  |     BOOST_FOREACH(const NamedMatrix& jA, As_) | 
					
						
							|  |  |  |       if(jA.first != key) separator.insert(jA.first); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-27 20:13:31 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | Vector GaussianFactor::operator*(const VectorConfig& x) const { | 
					
						
							|  |  |  | 	Vector Ax = zero(b_.size()); | 
					
						
							|  |  |  |   if (empty()) return Ax; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Just iterate over all A matrices and multiply in correct config part
 | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  |   BOOST_FOREACH(const NamedMatrix& jA, As_) | 
					
						
							|  |  |  |     Ax += (jA.second * x[jA.first]); | 
					
						
							| 
									
										
										
										
											2009-12-27 20:13:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-19 12:39:28 +08:00
										 |  |  |   return model_->whiten(Ax); | 
					
						
							| 
									
										
										
										
											2009-12-27 20:13:31 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | VectorConfig GaussianFactor::operator^(const Vector& e) const { | 
					
						
							| 
									
										
										
										
											2010-01-19 12:39:28 +08:00
										 |  |  |   Vector E = model_->whiten(e); | 
					
						
							| 
									
										
										
										
											2009-12-27 20:13:31 +08:00
										 |  |  | 	VectorConfig x; | 
					
						
							|  |  |  |   // Just iterate over all A matrices and insert Ai^e into VectorConfig
 | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  |   BOOST_FOREACH(const NamedMatrix& jA, As_) | 
					
						
							|  |  |  |     x.insert(jA.first,jA.second^E); | 
					
						
							| 
									
										
										
										
											2009-12-27 20:13:31 +08:00
										 |  |  | 	return x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-31 11:33:53 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | void GaussianFactor::transposeMultiplyAdd(double alpha, const Vector& e, | 
					
						
							|  |  |  | 		VectorConfig& x) const { | 
					
						
							|  |  |  | 	Vector E = alpha * model_->whiten(e); | 
					
						
							|  |  |  | 	// Just iterate over all A matrices and insert Ai^e into VectorConfig
 | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 	BOOST_FOREACH(const NamedMatrix& jA, As_) | 
					
						
							|  |  |  | 		gtsam::transposeMultiplyAdd(1.0, jA.second, E, x[jA.first]); | 
					
						
							| 
									
										
										
										
											2010-01-31 11:33:53 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | /* ************************************************************************* */   | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  |   // rtodo: this is called in eliminate, potential function to optimize?
 | 
					
						
							| 
									
										
										
										
											2009-11-06 21:43:39 +08:00
										 |  |  | 	// get pointers to the matrices
 | 
					
						
							|  |  |  | 	vector<const Matrix *> matrices; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	BOOST_FOREACH(const Symbol& j, ordering) { | 
					
						
							| 
									
										
										
										
											2009-11-06 21:43:39 +08:00
										 |  |  | 		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|
 | 
					
						
							| 
									
										
										
										
											2010-01-19 12:39:28 +08:00
										 |  |  | 	if (weight) model_->WhitenSystem(A,b); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-01-20 00:52:01 +08:00
										 |  |  | Matrix GaussianFactor::matrix_augmented(const Ordering& ordering, bool weight) const { | 
					
						
							| 
									
										
										
										
											2009-11-05 23:08:58 +08:00
										 |  |  | 	// get pointers to the matrices
 | 
					
						
							|  |  |  | 	vector<const Matrix *> matrices; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	BOOST_FOREACH(const Symbol& j, ordering) { | 
					
						
							| 
									
										
										
										
											2009-11-05 23:08:58 +08:00
										 |  |  | 		const Matrix& Aj = get_A(j); | 
					
						
							|  |  |  | 		matrices.push_back(&Aj); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// load b into a matrix
 | 
					
						
							| 
									
										
										
										
											2010-01-20 22:09:44 +08:00
										 |  |  | 	size_t rows = b_.size(); | 
					
						
							|  |  |  | 	Matrix B_mat(rows, 1); | 
					
						
							|  |  |  | 	memcpy(B_mat.data().begin(), b_.data().begin(), rows*sizeof(double)); | 
					
						
							| 
									
										
										
										
											2009-11-05 23:08:58 +08:00
										 |  |  | 	matrices.push_back(&B_mat); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 00:52:01 +08:00
										 |  |  | 	// divide in sigma so error is indeed 0.5*|Ax-b|
 | 
					
						
							|  |  |  | 	Matrix Ab = collect(matrices); | 
					
						
							|  |  |  | 	if (weight) model_->WhitenInPlace(Ab); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Ab; | 
					
						
							| 
									
										
										
										
											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-12-12 14:18:29 +08:00
										 |  |  | GaussianFactor::sparse(const Dimensions& columnIndices) const { | 
					
						
							| 
									
										
										
										
											2009-11-06 13:43:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// declare return values
 | 
					
						
							|  |  |  | 	list<int> I,J; | 
					
						
							|  |  |  | 	list<double> S; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-12 14:18:29 +08:00
										 |  |  | 	// iterate over all matrices in the factor
 | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 	BOOST_FOREACH(const NamedMatrix& jA, As_) { | 
					
						
							| 
									
										
										
										
											2009-12-12 14:18:29 +08:00
										 |  |  | 		// find first column index for this key
 | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 		int column_start = columnIndices.at(jA.first); | 
					
						
							|  |  |  | 		for (size_t i = 0; i < jA.second.size1(); i++) { | 
					
						
							| 
									
										
										
										
											2010-01-19 12:39:28 +08:00
										 |  |  | 			double sigma_i = model_->sigma(i); | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 			for (size_t j = 0; j < jA.second.size2(); j++) | 
					
						
							|  |  |  | 				if (jA.second(i, j) != 0.0) { | 
					
						
							| 
									
										
										
										
											2009-12-12 14:18:29 +08:00
										 |  |  | 					I.push_back(i + 1); | 
					
						
							|  |  |  | 					J.push_back(j + column_start); | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 					S.push_back(jA.second(i, j) / sigma_i); | 
					
						
							| 
									
										
										
										
											2009-12-12 14:18:29 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-11-06 13:43:03 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// return the result
 | 
					
						
							|  |  |  | 	return boost::tuple<list<int>, list<int>, list<double> >(I,J,S); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-12-05 10:00:20 +08:00
										 |  |  | void GaussianFactor::append_factor(GaussianFactor::shared_ptr f, size_t m, size_t pos) { | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-24 12:07:32 +08:00
										 |  |  | 	// iterate over all matrices from the factor f
 | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 	BOOST_FOREACH(const NamedMatrix& p, f->As_) { | 
					
						
							|  |  |  | 		const Symbol& key = p.first; | 
					
						
							|  |  |  | 		const Matrix& Aj = p.second; | 
					
						
							| 
									
										
										
										
											2009-10-24 12:07:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// find the corresponding matrix among As
 | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 		iterator mine = As_.find(key); | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 		const bool exists = mine != As_.end(); | 
					
						
							| 
									
										
										
										
											2009-10-24 12:07:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-05 10:00:20 +08:00
										 |  |  | 		// find rows and columns
 | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 		const size_t n = Aj.size2(); | 
					
						
							| 
									
										
										
										
											2009-12-05 10:00:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// use existing or create new matrix
 | 
					
						
							|  |  |  | 		if (exists) | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 		  copy(Aj.data().begin(), Aj.data().end(), (mine->second).data().begin()+pos*n); | 
					
						
							| 
									
										
										
										
											2009-12-05 05:03:32 +08:00
										 |  |  | 		else { | 
					
						
							|  |  |  | 			Matrix Z = zeros(m, n); | 
					
						
							| 
									
										
										
										
											2010-02-26 11:20:15 +08:00
										 |  |  | 			copy(Aj.data().begin(), Aj.data().end(), Z.data().begin()+pos*n); | 
					
						
							|  |  |  | 			insert(key, Z); | 
					
						
							| 
									
										
										
										
											2009-12-05 05:03:32 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-05 10:00:20 +08:00
										 |  |  | 	} // FOREACH
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-01-21 02:32:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <boost/numeric/ublas/triangular.hpp>
 | 
					
						
							|  |  |  | #include <boost/numeric/ublas/io.hpp>
 | 
					
						
							|  |  |  | #include <boost/numeric/ublas/matrix_proxy.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pair<GaussianConditional::shared_ptr, GaussianFactor::shared_ptr> | 
					
						
							| 
									
										
										
										
											2010-02-01 01:49:33 +08:00
										 |  |  | GaussianFactor::eliminateMatrix(Matrix& Ab, SharedDiagonal model, | 
					
						
							| 
									
										
										
										
											2010-07-09 17:06:58 +08:00
										 |  |  | 		        const Ordering& frontal, const Ordering& separator, | 
					
						
							| 
									
										
										
										
											2010-02-01 01:49:33 +08:00
										 |  |  | 		        const Dimensions& dimensions) { | 
					
						
							| 
									
										
										
										
											2010-01-27 12:39:35 +08:00
										 |  |  | 	bool verbose = false; | 
					
						
							| 
									
										
										
										
											2010-01-21 02:32:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Use in-place QR on dense Ab appropriate to NoiseModel
 | 
					
						
							| 
									
										
										
										
											2010-02-01 01:49:33 +08:00
										 |  |  | 	if (verbose) model->print("Before QR"); | 
					
						
							|  |  |  | 	SharedDiagonal noiseModel = model->QR(Ab); | 
					
						
							|  |  |  | 	if (verbose) model->print("After QR"); | 
					
						
							| 
									
										
										
										
											2010-01-21 02:32:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// get dimensions of the eliminated variable
 | 
					
						
							|  |  |  | 	// TODO: this is another map find that should be avoided !
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:06:58 +08:00
										 |  |  | 	size_t n1 = dimensions.at(frontal.front()), n = Ab.size2() - 1; | 
					
						
							| 
									
										
										
										
											2010-01-21 02:32:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// if m<n1, this factor cannot be eliminated
 | 
					
						
							|  |  |  | 	size_t maxRank = noiseModel->dim(); | 
					
						
							|  |  |  | 	if (maxRank<n1) { | 
					
						
							|  |  |  | 		cout << "Perhaps your factor graph is singular." << endl; | 
					
						
							|  |  |  | 		cout << "Here are the keys involved in the factor now being eliminated:" << endl; | 
					
						
							| 
									
										
										
										
											2010-07-09 17:06:58 +08:00
										 |  |  | 		separator.print("Keys"); | 
					
						
							|  |  |  | 		cout << "The first key, '" << (string)frontal.front() << "', corresponds to the variable being eliminated" << endl; | 
					
						
							| 
									
										
										
										
											2010-01-21 02:32:48 +08:00
										 |  |  | 		throw(domain_error("GaussianFactor::eliminate: fewer constraints than unknowns")); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Get alias to augmented RHS d
 | 
					
						
							|  |  |  | 	ublas::matrix_column<Matrix> d(Ab,n); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// create base conditional Gaussian
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:06:58 +08:00
										 |  |  | 	GaussianConditional::shared_ptr conditional(new GaussianConditional(frontal.front(), | 
					
						
							| 
									
										
										
										
											2010-01-21 02:32:48 +08:00
										 |  |  | 			sub(d,  0, n1),                   // form d vector
 | 
					
						
							|  |  |  | 			sub(Ab, 0, n1, 0, n1),            // form R matrix
 | 
					
						
							|  |  |  | 			sub(noiseModel->sigmas(),0,n1))); // get standard deviations
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// extract the block matrices for parents in both CG and LF
 | 
					
						
							|  |  |  | 	GaussianFactor::shared_ptr factor(new GaussianFactor); | 
					
						
							|  |  |  | 	size_t j = n1; | 
					
						
							| 
									
										
										
										
											2010-07-09 17:06:58 +08:00
										 |  |  | 	BOOST_FOREACH(const Symbol& cur_key, separator) | 
					
						
							|  |  |  | 		if (cur_key!=frontal.front()) { | 
					
						
							| 
									
										
										
										
											2010-02-01 01:49:33 +08:00
										 |  |  | 			size_t dim = dimensions.at(cur_key); // TODO avoid find !
 | 
					
						
							| 
									
										
										
										
											2010-01-21 02:32:48 +08:00
										 |  |  | 			conditional->add(cur_key, sub(Ab, 0, n1, j, j+dim)); | 
					
						
							| 
									
										
										
										
											2010-01-27 12:39:35 +08:00
										 |  |  | 			factor->insert(cur_key, sub(Ab, n1, maxRank, j, j+dim)); // TODO: handle zeros properly
 | 
					
						
							| 
									
										
										
										
											2009-11-05 04:59:16 +08:00
										 |  |  | 			j+=dim; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Set sigmas
 | 
					
						
							| 
									
										
										
										
											2010-01-27 12:39:35 +08:00
										 |  |  | 	// set the right model here
 | 
					
						
							|  |  |  | 	if (noiseModel->isConstrained()) | 
					
						
							|  |  |  | 		factor->model_ = noiseModel::Constrained::MixedSigmas(sub(noiseModel->sigmas(),n1,maxRank)); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		factor->model_ = noiseModel::Diagonal::Sigmas(sub(noiseModel->sigmas(),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)); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 01:06:11 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-02-01 01:49:33 +08:00
										 |  |  | pair<GaussianConditional::shared_ptr, GaussianFactor::shared_ptr> | 
					
						
							|  |  |  | GaussianFactor::eliminate(const Symbol& key) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	bool verbose = false; | 
					
						
							|  |  |  | 	// if this factor does not involve key, we exit with empty CG and LF
 | 
					
						
							|  |  |  | 	const_iterator it = As_.find(key); | 
					
						
							|  |  |  | 	if (it==As_.end()) { | 
					
						
							|  |  |  | 		// Conditional Gaussian is just a parent-less node with P(x)=1
 | 
					
						
							|  |  |  | 		GaussianFactor::shared_ptr lf(new GaussianFactor); | 
					
						
							|  |  |  | 		GaussianConditional::shared_ptr cg(new GaussianConditional(key)); | 
					
						
							|  |  |  | 		return make_pair(cg,lf); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// create an internal ordering that eliminates key first
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:06:58 +08:00
										 |  |  | 	Ordering frontal, ordering; | 
					
						
							|  |  |  | 	frontal += key; | 
					
						
							| 
									
										
										
										
											2010-02-01 01:49:33 +08:00
										 |  |  | 	ordering += key; | 
					
						
							|  |  |  | 	BOOST_FOREACH(const Symbol& k, keys()) | 
					
						
							|  |  |  | 		if (k != key) ordering += k; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// extract [A b] from the combined linear factor (ensure that x is leading)
 | 
					
						
							|  |  |  | 	Matrix Ab = matrix_augmented(ordering,false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TODO: this is where to split
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:06:58 +08:00
										 |  |  | 	ordering.pop_front(); | 
					
						
							|  |  |  | 	return eliminateMatrix(Ab, model_, frontal, ordering, dimensions()); | 
					
						
							| 
									
										
										
										
											2010-02-01 01:49:33 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ |