| 
									
										
										
										
											2010-10-14 12:54:38 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * GTSAM Copyright 2010, Georgia Tech Research Corporation,  | 
					
						
							|  |  |  |  * Atlanta, Georgia 30332-0415 | 
					
						
							|  |  |  |  * All Rights Reserved | 
					
						
							|  |  |  |  * Authors: Frank Dellaert, et al. (see THANKS for the full author list) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * See LICENSE for the license information | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * SubgraphPreconditioner.cpp | 
					
						
							|  |  |  |  * Created on: Dec 31, 2009 | 
					
						
							|  |  |  |  * @author: Frank Dellaert | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/foreach.hpp>
 | 
					
						
							| 
									
										
										
										
											2010-08-20 01:23:19 +08:00
										 |  |  | #include <gtsam/linear/SubgraphPreconditioner.h>
 | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 	SubgraphPreconditioner::SubgraphPreconditioner(sharedFG& Ab1, sharedFG& Ab2, | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 			sharedBayesNet& Rc1, sharedValues& xbar) : | 
					
						
							| 
									
										
										
										
											2010-01-23 08:57:54 +08:00
										 |  |  | 		Ab1_(Ab1), Ab2_(Ab2), Rc1_(Rc1), xbar_(xbar), b2bar_(Ab2_->errors_(*xbar)) { | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// x = xbar + inv(R1)*y
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues SubgraphPreconditioner::x(const VectorValues& y) const { | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | #ifdef VECTORBTREE
 | 
					
						
							|  |  |  | 		if (!y.cloned(*xbar_)) throw | 
					
						
							|  |  |  | 			invalid_argument("SubgraphPreconditioner::x: y needs to be cloned from xbar"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 		VectorValues x = y; | 
					
						
							| 
									
										
										
										
											2010-01-31 12:39:41 +08:00
										 |  |  | 		backSubstituteInPlace(*Rc1_,x); | 
					
						
							|  |  |  | 		x += *xbar_; | 
					
						
							|  |  |  | 		return x; | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-19 03:29:16 +08:00
										 |  |  |     SubgraphPreconditioner SubgraphPreconditioner::add_priors(double sigma) const { | 
					
						
							|  |  |  |     	SubgraphPreconditioner result = *this ; | 
					
						
							|  |  |  |     	result.Ab2_ = sharedFG(new GaussianFactorGraph(Ab2_->add_priors(sigma))) ; | 
					
						
							|  |  |  |     	return result ; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	double SubgraphPreconditioner::error(const VectorValues& y) const { | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-15 00:08:16 +08:00
										 |  |  | //		Errors e;
 | 
					
						
							|  |  |  | //		// Use BayesNet order to add y contributions in order
 | 
					
						
							|  |  |  | //		BOOST_FOREACH(GaussianConditional::shared_ptr cg, *Rc1_) {
 | 
					
						
							|  |  |  | //			const Symbol& j = cg->key();
 | 
					
						
							|  |  |  | //			e.push_back(y[j]); // append y
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | //		// Add A2 contribution
 | 
					
						
							|  |  |  | //		VectorValues x = this->x(y);
 | 
					
						
							|  |  |  | //		Errors e2 = Ab2_->errors(x);
 | 
					
						
							|  |  |  | //		e.splice(e.end(), e2);
 | 
					
						
							|  |  |  | //		return 0.5 * dot(e, e);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-19 03:29:16 +08:00
										 |  |  | 		Errors e(y); | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 		VectorValues x = this->x(y); | 
					
						
							| 
									
										
										
										
											2010-01-19 18:46:12 +08:00
										 |  |  | 		Errors e2 = Ab2_->errors(x); | 
					
						
							| 
									
										
										
										
											2010-10-15 10:40:46 +08:00
										 |  |  | 		return 0.5 * (dot(e, e) + dot(e2,e2)); | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// gradient is y + inv(R1')*A2'*(A2*inv(R1)*y-b2bar),
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues SubgraphPreconditioner::gradient(const VectorValues& y) const { | 
					
						
							|  |  |  | 		VectorValues x = this->x(y); // x = inv(R1)*y
 | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 		Errors e2 = Ab2_->errors(x); | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 		VectorValues gx2 = VectorValues::zero(y); | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 		Ab2_->transposeMultiplyAdd(1.0,e2,gx2); // A2'*e2;
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 		VectorValues gy2 = gtsam::backSubstituteTranspose(*Rc1_, gx2); // inv(R1')*gx2
 | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 		return y + gy2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// Apply operator A, A*y = [I;A2*inv(R1)]*y = [y; A2*inv(R1)*y]
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	Errors SubgraphPreconditioner::operator*(const VectorValues& y) const { | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-15 00:08:16 +08:00
										 |  |  | //		Errors e;
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// Use BayesNet order to add y contributions in order
 | 
					
						
							|  |  |  | //		BOOST_FOREACH(GaussianConditional::shared_ptr cg, *Rc1_) {
 | 
					
						
							|  |  |  | //			const Symbol& j = cg->key();
 | 
					
						
							|  |  |  | //			e.push_back(y[j]); // append y
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-15 00:08:16 +08:00
										 |  |  | 		Errors e(y); | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Add A2 contribution
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 		VectorValues x = y; // TODO avoid ?
 | 
					
						
							| 
									
										
										
										
											2010-01-31 12:39:41 +08:00
										 |  |  | 		gtsam::backSubstituteInPlace(*Rc1_, x); // x=inv(R1)*y
 | 
					
						
							| 
									
										
										
										
											2010-01-19 18:46:12 +08:00
										 |  |  | 		Errors e2 = *Ab2_ * x; // A2*x
 | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 		e.splice(e.end(), e2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return e; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-31 01:31:05 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// In-place version that overwrites e
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	void SubgraphPreconditioner::multiplyInPlace(const VectorValues& y, Errors& e) const { | 
					
						
							| 
									
										
										
										
											2010-01-31 01:31:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-15 00:08:16 +08:00
										 |  |  | //		Errors::iterator ei = e.begin();
 | 
					
						
							|  |  |  | //		// Use BayesNet order to add y contributions in order
 | 
					
						
							|  |  |  | //		BOOST_FOREACH(GaussianConditional::shared_ptr cg, *Rc1_) {
 | 
					
						
							|  |  |  | //			const Symbol& j = cg->key();
 | 
					
						
							|  |  |  | //			*ei = y[j]; // append y
 | 
					
						
							|  |  |  | //			ei++;
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | //		// Add A2 contribution
 | 
					
						
							|  |  |  | //		VectorValues x = y; // TODO avoid ?
 | 
					
						
							|  |  |  | //		gtsam::backSubstituteInPlace(*Rc1_, x); // x=inv(R1)*y
 | 
					
						
							|  |  |  | //		Ab2_->multiplyInPlace(x,ei); // use iterator version
 | 
					
						
							| 
									
										
										
										
											2010-01-31 01:31:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-15 00:08:16 +08:00
										 |  |  | 		Errors::iterator ei = e.begin(); | 
					
						
							| 
									
										
										
										
											2010-10-19 03:29:16 +08:00
										 |  |  | 		for ( Index i = 0 ; i < y.size() ; ++i, ++ei ) { | 
					
						
							| 
									
										
										
										
											2010-10-15 00:08:16 +08:00
										 |  |  | 			*ei = y[i]; | 
					
						
							| 
									
										
										
										
											2010-01-31 01:31:05 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Add A2 contribution
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 		VectorValues x = y; // TODO avoid ?
 | 
					
						
							| 
									
										
										
										
											2010-01-31 12:39:41 +08:00
										 |  |  | 		gtsam::backSubstituteInPlace(*Rc1_, x); // x=inv(R1)*y
 | 
					
						
							| 
									
										
										
										
											2010-01-31 01:31:05 +08:00
										 |  |  | 		Ab2_->multiplyInPlace(x,ei); // use iterator version
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// Apply operator A', A'*e = [I inv(R1')*A2']*e = e1 + inv(R1')*A2'*e2
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 	VectorValues SubgraphPreconditioner::operator^(const Errors& e) const { | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-15 10:40:46 +08:00
										 |  |  | //		VectorValues y;
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// Use BayesNet order to remove y contributions in order
 | 
					
						
							|  |  |  | //		Errors::const_iterator it = e.begin();
 | 
					
						
							|  |  |  | //		BOOST_FOREACH(GaussianConditional::shared_ptr cg, *Rc1_) {
 | 
					
						
							|  |  |  | //			const Symbol& j = cg->key();
 | 
					
						
							|  |  |  | //			const Vector& ej = *(it++);
 | 
					
						
							|  |  |  | //			y.insert(j,ej);
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		// get A2 part
 | 
					
						
							|  |  |  | //		transposeMultiplyAdd2(1.0,it,e.end(),y);
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		return y;
 | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Errors::const_iterator it = e.begin(); | 
					
						
							| 
									
										
										
										
											2010-10-15 10:40:46 +08:00
										 |  |  | 		VectorValues y = zero(); | 
					
						
							| 
									
										
										
										
											2010-10-19 03:29:16 +08:00
										 |  |  | 		for ( Index i = 0 ; i < y.size() ; ++i, ++it ) | 
					
						
							| 
									
										
										
										
											2010-10-15 10:40:46 +08:00
										 |  |  | 			y[i] = *it ; | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 		transposeMultiplyAdd2(1.0,it,e.end(),y); | 
					
						
							| 
									
										
										
										
											2010-01-31 07:59:29 +08:00
										 |  |  | 		return y; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// y += alpha*A'*e
 | 
					
						
							|  |  |  | 	void SubgraphPreconditioner::transposeMultiplyAdd | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 		(double alpha, const Errors& e, VectorValues& y) const { | 
					
						
							| 
									
										
										
										
											2010-01-31 07:59:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-15 10:40:46 +08:00
										 |  |  | //		// Use BayesNet order to remove y contributions in order
 | 
					
						
							|  |  |  | //		Errors::const_iterator it = e.begin();
 | 
					
						
							|  |  |  | //		BOOST_FOREACH(GaussianConditional::shared_ptr cg, *Rc1_) {
 | 
					
						
							|  |  |  | //			const Symbol& j = cg->key();
 | 
					
						
							|  |  |  | //			const Vector& ej = *(it++);
 | 
					
						
							|  |  |  | //			axpy(alpha,ej,y[j]);
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | //		// get A2 part
 | 
					
						
							|  |  |  | //		transposeMultiplyAdd2(alpha,it,e.end(),y);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-31 07:59:29 +08:00
										 |  |  | 		Errors::const_iterator it = e.begin(); | 
					
						
							| 
									
										
										
										
											2010-10-19 03:29:16 +08:00
										 |  |  | 		for ( Index i = 0 ; i < y.size() ; ++i, ++it ) { | 
					
						
							| 
									
										
										
										
											2010-10-15 10:40:46 +08:00
										 |  |  | 			const Vector& ei = *it; | 
					
						
							|  |  |  | 			axpy(alpha,ei,y[i]) ; | 
					
						
							| 
									
										
										
										
											2010-01-31 07:59:29 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 		transposeMultiplyAdd2(alpha,it,e.end(),y); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// y += alpha*inv(R1')*A2'*e2
 | 
					
						
							|  |  |  | 	void SubgraphPreconditioner::transposeMultiplyAdd2 (double alpha, | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 		Errors::const_iterator it, Errors::const_iterator end, VectorValues& y) const { | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-31 07:59:29 +08:00
										 |  |  | 		// create e2 with what's left of e
 | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 		// TODO can we avoid creating e2 by passing iterator to transposeMultiplyAdd ?
 | 
					
						
							| 
									
										
										
										
											2010-01-31 07:59:29 +08:00
										 |  |  | 		Errors e2; | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 		while (it != end) | 
					
						
							| 
									
										
										
										
											2010-01-31 07:59:29 +08:00
										 |  |  | 		e2.push_back(*(it++)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 		// Old code:
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 		// VectorValues x = *Ab2_ ^ e2; // x = A2'*e2
 | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 		// y += alpha * gtsam::backSubstituteTranspose(*Rc1_, x); // inv(R1')*x;
 | 
					
						
							|  |  |  | 		// New Code:
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  | 		VectorValues x = VectorValues::zero(y); // x = 0
 | 
					
						
							| 
									
										
										
										
											2010-02-17 11:29:12 +08:00
										 |  |  | 		Ab2_->transposeMultiplyAdd(1.0,e2,x);   // x += A2'*e2
 | 
					
						
							|  |  |  | 		axpy(alpha, gtsam::backSubstituteTranspose(*Rc1_, x), y); // y += alpha*inv(R1')*x
 | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-01-11 16:32:59 +08:00
										 |  |  | 	void SubgraphPreconditioner::print(const std::string& s) const { | 
					
						
							|  |  |  | 		cout << s << endl; | 
					
						
							| 
									
										
										
										
											2010-01-19 18:46:12 +08:00
										 |  |  | 		Ab2_->print(); | 
					
						
							| 
									
										
										
										
											2010-01-11 16:32:59 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-31 20:56:47 +08:00
										 |  |  | } // nsamespace gtsam
 |