| 
									
										
										
										
											2009-12-29 00:26:16 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * iterative-inl.h | 
					
						
							|  |  |  |  * @brief Iterative methods, template implementation | 
					
						
							|  |  |  |  * @author Frank Dellaert | 
					
						
							|  |  |  |  * Created on: Dec 28, 2009 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-11 06:15:34 +08:00
										 |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-29 00:26:16 +08:00
										 |  |  | #include "GaussianFactorGraph.h"
 | 
					
						
							|  |  |  | #include "iterative.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-01-11 16:32:59 +08:00
										 |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * conjugate gradient method. | 
					
						
							|  |  |  | 	 * S: linear system, V: step vector, E: errors | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2009-12-29 00:26:16 +08:00
										 |  |  | 	template<class S, class V, class E> | 
					
						
							| 
									
										
										
										
											2010-01-11 16:32:59 +08:00
										 |  |  | 	V conjugateGradients(const S& Ab, V x, bool verbose, double epsilon, double epsilon_abs, | 
					
						
							| 
									
										
										
										
											2009-12-29 00:26:16 +08:00
										 |  |  | 			size_t maxIterations, bool steepest = false) { | 
					
						
							|  |  |  | 		if (maxIterations == 0) maxIterations = dim(x) * (steepest ? 10 : 1); | 
					
						
							| 
									
										
										
										
											2009-12-31 18:27:39 +08:00
										 |  |  | 		size_t reset = (size_t)(sqrt(dim(x))+0.5); // when to reset
 | 
					
						
							| 
									
										
										
										
											2009-12-29 00:26:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Start with g0 = A'*(A*x0-b), d0 = - g0
 | 
					
						
							|  |  |  | 		// i.e., first step is in direction of negative gradient
 | 
					
						
							| 
									
										
										
										
											2009-12-29 01:28:48 +08:00
										 |  |  | 		V g = Ab.gradient(x); | 
					
						
							| 
									
										
										
										
											2009-12-29 00:26:16 +08:00
										 |  |  | 		V d = -g; | 
					
						
							|  |  |  | 		double dotg0 = dot(g, g), prev_dotg = dotg0; | 
					
						
							| 
									
										
										
										
											2010-01-11 16:32:59 +08:00
										 |  |  | 		if (dotg0 < epsilon_abs) return x; | 
					
						
							| 
									
										
										
										
											2009-12-29 00:26:16 +08:00
										 |  |  | 		double threshold = epsilon * epsilon * dotg0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (verbose) cout << "CG: epsilon = " << epsilon << ", maxIterations = " | 
					
						
							|  |  |  | 				<< maxIterations << ", ||g0||^2 = " << dotg0 << ", threshold = " | 
					
						
							|  |  |  | 				<< threshold << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// loop maxIterations times
 | 
					
						
							| 
									
										
										
										
											2009-12-29 01:28:48 +08:00
										 |  |  | 		for (size_t k = 1;; k++) { | 
					
						
							| 
									
										
										
										
											2009-12-29 00:26:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// calculate optimal step-size
 | 
					
						
							|  |  |  | 			E Ad = Ab * d; | 
					
						
							|  |  |  | 			double alpha = -dot(d, g) / dot(Ad, Ad); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// do step in new search direction
 | 
					
						
							|  |  |  | 			x = x + alpha * d; | 
					
						
							| 
									
										
										
										
											2009-12-29 01:28:48 +08:00
										 |  |  | 			if (k==maxIterations) break; | 
					
						
							| 
									
										
										
										
											2009-12-29 00:26:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-31 18:27:39 +08:00
										 |  |  | 			// update gradient (or re-calculate at reset time)
 | 
					
						
							| 
									
										
										
										
											2010-01-17 23:09:28 +08:00
										 |  |  | 			 g = (k%reset==0) ? Ab.gradient(x) : g + alpha * (Ab ^ Ad); | 
					
						
							|  |  |  | //			 g = g + alpha * (Ab ^ Ad);
 | 
					
						
							|  |  |  | //			 g = Ab.gradient(x);
 | 
					
						
							| 
									
										
										
										
											2009-12-29 00:26:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// check for convergence
 | 
					
						
							|  |  |  | 			double dotg = dot(g, g); | 
					
						
							|  |  |  | 			if (verbose) cout << "iteration " << k << ": alpha = " << alpha | 
					
						
							|  |  |  | 					<< ", dotg = " << dotg << endl; | 
					
						
							|  |  |  | 			if (dotg < threshold) break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// calculate new search direction
 | 
					
						
							|  |  |  | 			if (steepest) | 
					
						
							|  |  |  | 				d = -g; | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				double beta = dotg / prev_dotg; | 
					
						
							|  |  |  | 				prev_dotg = dotg; | 
					
						
							|  |  |  | 				d = -g + beta * d; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return x; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace gtsam
 |