| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file    numericalDerivative.h | 
					
						
							|  |  |  |  * @brief   Some functions to compute numerical derivatives | 
					
						
							|  |  |  |  * @author  Frank Dellaert | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // \callgraph
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-14 13:58:58 +08:00
										 |  |  | #include "Lie.h"
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | #include "Matrix.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  | //#define LINEARIZE_AT_IDENTITY
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-12 12:13:12 +08:00
										 |  |  |   /**
 | 
					
						
							| 
									
										
										
										
											2010-01-11 02:23:47 +08:00
										 |  |  |    * Numerically compute gradient of scalar function | 
					
						
							|  |  |  |    * Class X is the input argument | 
					
						
							|  |  |  |    * The class X needs to have dim, expmap, logmap | 
					
						
							| 
									
										
										
										
											2009-12-12 12:13:12 +08:00
										 |  |  |    */ | 
					
						
							|  |  |  |   template<class X> | 
					
						
							|  |  |  |   Vector numericalGradient(double (*h)(const X&), const X& x, double delta=1e-5) { | 
					
						
							|  |  |  |     double hx = h(x); | 
					
						
							|  |  |  |     double factor = 1.0/(2.0*delta); | 
					
						
							|  |  |  |     const size_t n = x.dim(); | 
					
						
							|  |  |  |     Vector d(n,0.0), g(n,0.0); | 
					
						
							|  |  |  |     for (size_t j=0;j<n;j++) { | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  |       d(j) +=   delta; double hxplus = h(expmap(x,d)); | 
					
						
							|  |  |  |       d(j) -= 2*delta; double hxmin  = h(expmap(x,d)); | 
					
						
							| 
									
										
										
										
											2009-12-12 12:13:12 +08:00
										 |  |  |       d(j) +=   delta; g(j) = (hxplus-hxmin)*factor; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return g; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   /**
 | 
					
						
							| 
									
										
										
										
											2009-12-20 18:32:34 +08:00
										 |  |  |    * Compute numerical derivative in argument 1 of unary function | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |    * @param h unary function yielding m-vector | 
					
						
							|  |  |  |    * @param x n-dimensional value at which to evaluate h | 
					
						
							|  |  |  |    * @param delta increment for numerical derivative | 
					
						
							| 
									
										
										
										
											2010-01-11 02:23:47 +08:00
										 |  |  |    * Class Y is the output argument | 
					
						
							|  |  |  |    * Class X is the input argument | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |    * @return m*n Jacobian computed via central differencing | 
					
						
							| 
									
										
										
										
											2010-01-11 02:23:47 +08:00
										 |  |  |    * Both classes X,Y need dim, expmap, logmap | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |    */ | 
					
						
							|  |  |  |   template<class Y, class X> | 
					
						
							| 
									
										
										
										
											2009-12-12 12:13:12 +08:00
										 |  |  |   Matrix numericalDerivative11(Y (*h)(const X&), const X& x, double delta=1e-5) { | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  |     Y hx = h(x); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |     double factor = 1.0/(2.0*delta); | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  |     const size_t m = dim(hx), n = dim(x); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |     Vector d(n,0.0); | 
					
						
							|  |  |  |     Matrix H = zeros(m,n); | 
					
						
							|  |  |  |     for (size_t j=0;j<n;j++) { | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  | #ifdef LINEARIZE_AT_IDENTITY
 | 
					
						
							|  |  |  |       d(j) +=   delta; Vector hxplus = logmap(h(expmap(x,d))); | 
					
						
							|  |  |  |       d(j) -= 2*delta; Vector hxmin  = logmap(h(expmap(x,d))); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |       d(j) +=   delta; Vector hxplus = logmap(hx, h(expmap(x,d))); | 
					
						
							|  |  |  |       d(j) -= 2*delta; Vector hxmin  = logmap(hx, h(expmap(x,d))); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |       d(j) +=   delta; Vector dh = (hxplus-hxmin)*factor; | 
					
						
							|  |  |  |       for (size_t i=0;i<m;i++) H(i,j) = dh(i); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return H; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /**
 | 
					
						
							|  |  |  |    * Compute numerical derivative in argument 1 of binary function | 
					
						
							|  |  |  |    * @param h binary function yielding m-vector | 
					
						
							|  |  |  |    * @param x1 n-dimensional first argument value | 
					
						
							|  |  |  |    * @param x2 second argument value | 
					
						
							|  |  |  |    * @param delta increment for numerical derivative | 
					
						
							|  |  |  |    * @return m*n Jacobian computed via central differencing | 
					
						
							| 
									
										
										
										
											2010-01-11 02:23:47 +08:00
										 |  |  |    * All classes Y,X1,X2 need dim, expmap, logmap | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2009-12-12 12:13:12 +08:00
										 |  |  |   template<class Y, class X1, class X2> | 
					
						
							|  |  |  |   Matrix numericalDerivative21(Y (*h)(const X1&, const X2&), | 
					
						
							|  |  |  |       const X1& x1, const X2& x2, double delta=1e-5) { | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  |     Y hx = h(x1,x2); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |     double factor = 1.0/(2.0*delta); | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  |     const size_t m = dim(hx), n = dim(x1); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |     Vector d(n,0.0); | 
					
						
							|  |  |  |     Matrix H = zeros(m,n); | 
					
						
							|  |  |  |     for (size_t j=0;j<n;j++) { | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  | #ifdef LINEARIZE_AT_IDENTITY
 | 
					
						
							|  |  |  |       d(j) +=   delta; Vector hxplus = logmap(h(expmap(x1,d),x2)); | 
					
						
							|  |  |  |       d(j) -= 2*delta; Vector hxmin  = logmap(h(expmap(x1,d),x2)); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |       d(j) +=   delta; Vector hxplus = logmap(hx, h(expmap(x1,d),x2)); | 
					
						
							|  |  |  |       d(j) -= 2*delta; Vector hxmin  = logmap(hx, h(expmap(x1,d),x2)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |       d(j) +=   delta; Vector dh = (hxplus-hxmin)*factor; | 
					
						
							|  |  |  |       for (size_t i=0;i<m;i++) H(i,j) = dh(i); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return H; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /**
 | 
					
						
							| 
									
										
										
										
											2009-12-20 18:32:34 +08:00
										 |  |  |    * Compute numerical derivative in argument 2 of binary function | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |    * @param h binary function yielding m-vector | 
					
						
							|  |  |  |    * @param x1 first argument value | 
					
						
							|  |  |  |    * @param x2 n-dimensional second argument value | 
					
						
							|  |  |  |    * @param delta increment for numerical derivative | 
					
						
							|  |  |  |    * @return m*n Jacobian computed via central differencing | 
					
						
							| 
									
										
										
										
											2010-01-11 02:23:47 +08:00
										 |  |  |    * All classes Y,X1,X2 need dim, expmap, logmap | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |    */ | 
					
						
							|  |  |  |   template<class Y, class X1, class X2> | 
					
						
							| 
									
										
										
										
											2010-01-11 02:23:47 +08:00
										 |  |  |   Matrix numericalDerivative22 | 
					
						
							|  |  |  |   (Y (*h)(const X1&, const X2&), | 
					
						
							|  |  |  |       const X1& x1, const X2& x2, double delta=1e-5) | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  |     Y hx = h(x1,x2); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |     double factor = 1.0/(2.0*delta); | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  |     const size_t m = dim(hx), n = dim(x2); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |     Vector d(n,0.0); | 
					
						
							|  |  |  |     Matrix H = zeros(m,n); | 
					
						
							|  |  |  |     for (size_t j=0;j<n;j++) { | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  | #ifdef LINEARIZE_AT_IDENTITY
 | 
					
						
							|  |  |  |       d(j) +=   delta; Vector hxplus = logmap(h(x1,expmap(x2,d))); | 
					
						
							|  |  |  |       d(j) -= 2*delta; Vector hxmin  = logmap(h(x1,expmap(x2,d))); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |       d(j) +=   delta; Vector hxplus = logmap(hx, h(x1,expmap(x2,d))); | 
					
						
							|  |  |  |       d(j) -= 2*delta; Vector hxmin  = logmap(hx, h(x1,expmap(x2,d))); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |       d(j) +=   delta; Vector dh = (hxplus-hxmin)*factor; | 
					
						
							|  |  |  |       for (size_t i=0;i<m;i++) H(i,j) = dh(i); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return H; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /**
 | 
					
						
							|  |  |  |    * Compute numerical derivative in argument 1 of binary function | 
					
						
							|  |  |  |    * @param h binary function yielding m-vector | 
					
						
							|  |  |  |    * @param x1 n-dimensional first argument value | 
					
						
							|  |  |  |    * @param x2 second argument value | 
					
						
							|  |  |  |    * @param delta increment for numerical derivative | 
					
						
							|  |  |  |    * @return m*n Jacobian computed via central differencing | 
					
						
							| 
									
										
										
										
											2010-01-11 02:23:47 +08:00
										 |  |  |    * All classes Y,X1,X2,X3 need dim, expmap, logmap | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |    */ | 
					
						
							|  |  |  |   template<class Y, class X1, class X2, class X3> | 
					
						
							| 
									
										
										
										
											2010-01-11 02:23:47 +08:00
										 |  |  |   Matrix numericalDerivative31 | 
					
						
							|  |  |  |   (Y (*h)(const X1&, const X2&, const X3&), | 
					
						
							|  |  |  |       const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  |     Y hx = h(x1,x2,x3); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |     double factor = 1.0/(2.0*delta); | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  |     const size_t m = dim(hx), n = dim(x1); | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |     Vector d(n,0.0); | 
					
						
							|  |  |  |     Matrix H = zeros(m,n); | 
					
						
							|  |  |  |     for (size_t j=0;j<n;j++) { | 
					
						
							| 
									
										
										
										
											2010-01-08 08:40:17 +08:00
										 |  |  | #ifdef LINEARIZE_AT_IDENTITY
 | 
					
						
							|  |  |  |       d(j) +=   delta; Vector hxplus = logmap(h(expmap(x1,d),x2,x3)); | 
					
						
							|  |  |  |       d(j) -= 2*delta; Vector hxmin  = logmap(h(expmap(x1,d),x2,x3)); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |       d(j) +=   delta; Vector hxplus = logmap(hx, h(expmap(x1,d),x2,x3)); | 
					
						
							|  |  |  |       d(j) -= 2*delta; Vector hxmin  = logmap(hx, h(expmap(x1,d),x2,x3)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-08-22 06:23:24 +08:00
										 |  |  |       d(j) +=   delta; Vector dh = (hxplus-hxmin)*factor; | 
					
						
							|  |  |  |       for (size_t i=0;i<m;i++) H(i,j) = dh(i); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return H; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |