| 
									
										
										
										
											2014-11-21 22:48:02 +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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * @file CallRecord.h | 
					
						
							|  |  |  |  * @date November 21, 2014 | 
					
						
							|  |  |  |  * @author Frank Dellaert | 
					
						
							|  |  |  |  * @author Paul Furgale | 
					
						
							|  |  |  |  * @author Hannes Sommer | 
					
						
							|  |  |  |  * @brief Internals for Expression.h, not for general consumption | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <gtsam/base/VerticalBlockMatrix.h>
 | 
					
						
							|  |  |  | #include <gtsam/base/FastVector.h>
 | 
					
						
							|  |  |  | #include <gtsam/base/Matrix.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-23 04:48:36 +08:00
										 |  |  | #include <boost/mpl/transform.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class JacobianMap; | 
					
						
							|  |  |  | // forward declaration
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //-----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * MaxVirtualStaticRows defines how many separate virtual reverseAD with specific | 
					
						
							|  |  |  |  * static rows (1..MaxVirtualStaticRows) methods will be part of the CallRecord interface. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const int MaxVirtualStaticRows = 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace internal { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * ConvertToDynamicIf converts to a dense matrix with dynamic rows iff | 
					
						
							|  |  |  |  * ConvertToDynamicRows (colums stay as they are) otherwise | 
					
						
							|  |  |  |  * it just passes dense Eigen matrices through. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<bool ConvertToDynamicRows> | 
					
						
							| 
									
										
										
										
											2014-11-24 17:48:15 +08:00
										 |  |  | struct ConvertToVirtualFunctionSupportedMatrixType { | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  |   template<typename Derived> | 
					
						
							|  |  |  |   static Eigen::Matrix<double, Eigen::Dynamic, Derived::ColsAtCompileTime> convert( | 
					
						
							|  |  |  |       const Eigen::MatrixBase<Derived> & x) { | 
					
						
							|  |  |  |     return x; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> | 
					
						
							| 
									
										
										
										
											2014-11-24 17:48:15 +08:00
										 |  |  | struct ConvertToVirtualFunctionSupportedMatrixType<false> { | 
					
						
							|  |  |  |   template<typename Derived> | 
					
						
							|  |  |  |   static const Eigen::Matrix<double, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime> convert( | 
					
						
							|  |  |  |       const Eigen::MatrixBase<Derived> & x) { | 
					
						
							|  |  |  |     return x; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   // special treatment of matrices that don't need conversion
 | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  |   template<int Rows, int Cols> | 
					
						
							|  |  |  |   static const Eigen::Matrix<double, Rows, Cols> & convert( | 
					
						
							|  |  |  |       const Eigen::Matrix<double, Rows, Cols> & x) { | 
					
						
							|  |  |  |     return x; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Recursive definition of an interface having several purely | 
					
						
							|  |  |  |  * virtual _reverseAD(const Eigen::Matrix<double, Rows, Cols> &, JacobianMap&) | 
					
						
							|  |  |  |  * with Rows in 1..MaxSupportedStaticRows | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<int MaxSupportedStaticRows, int Cols> | 
					
						
							| 
									
										
										
										
											2014-11-23 04:48:36 +08:00
										 |  |  | struct ReverseADInterface: ReverseADInterface<MaxSupportedStaticRows - 1, Cols> { | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  |   using ReverseADInterface<MaxSupportedStaticRows - 1, Cols>::_reverseAD; | 
					
						
							|  |  |  |   virtual void _reverseAD( | 
					
						
							|  |  |  |       const Eigen::Matrix<double, MaxSupportedStaticRows, Cols> & dFdT, | 
					
						
							|  |  |  |       JacobianMap& jacobians) const = 0; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<int Cols> | 
					
						
							|  |  |  | struct ReverseADInterface<0, Cols> { | 
					
						
							| 
									
										
										
										
											2014-11-22 04:13:24 +08:00
										 |  |  |   virtual void _reverseAD( | 
					
						
							|  |  |  |       const Eigen::Matrix<double, Eigen::Dynamic, Cols> & dFdT, | 
					
						
							|  |  |  |       JacobianMap& jacobians) const = 0; | 
					
						
							|  |  |  |   virtual void _reverseAD(const Matrix & dFdT, | 
					
						
							|  |  |  |       JacobianMap& jacobians) const = 0; | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2014-11-22 04:13:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-23 02:19:17 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * ReverseADImplementor is a utility class used by CallRecordImplementor to | 
					
						
							|  |  |  |  * implementing the recursive ReverseADInterface interface. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2014-11-22 04:13:24 +08:00
										 |  |  | template<typename Derived, int MaxSupportedStaticRows, int Cols> | 
					
						
							| 
									
										
										
										
											2014-11-23 02:19:17 +08:00
										 |  |  | struct ReverseADImplementor: ReverseADImplementor<Derived, | 
					
						
							|  |  |  |     MaxSupportedStaticRows - 1, Cols> { | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2014-11-23 04:48:36 +08:00
										 |  |  |   using ReverseADImplementor<Derived, MaxSupportedStaticRows - 1, Cols>::_reverseAD; | 
					
						
							| 
									
										
										
										
											2014-11-23 02:19:17 +08:00
										 |  |  |   virtual void _reverseAD( | 
					
						
							|  |  |  |       const Eigen::Matrix<double, MaxSupportedStaticRows, Cols> & dFdT, | 
					
						
							|  |  |  |       JacobianMap& jacobians) const { | 
					
						
							|  |  |  |     static_cast<const Derived *>(this)->reverseAD(dFdT, jacobians); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-11-23 04:48:36 +08:00
										 |  |  |   friend struct internal::ReverseADImplementor<Derived, | 
					
						
							|  |  |  |       MaxSupportedStaticRows + 1, Cols>; | 
					
						
							| 
									
										
										
										
											2014-11-23 02:19:17 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename Derived, int Cols> | 
					
						
							| 
									
										
										
										
											2014-11-23 04:48:36 +08:00
										 |  |  | struct ReverseADImplementor<Derived, 0, Cols> : virtual internal::ReverseADInterface< | 
					
						
							|  |  |  |     MaxVirtualStaticRows, Cols> { | 
					
						
							| 
									
										
										
										
											2014-11-23 02:19:17 +08:00
										 |  |  | private: | 
					
						
							|  |  |  |   using internal::ReverseADInterface<MaxVirtualStaticRows, Cols>::_reverseAD; | 
					
						
							|  |  |  |   const Derived & derived() const { | 
					
						
							|  |  |  |     return static_cast<const Derived&>(*this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   virtual void _reverseAD( | 
					
						
							|  |  |  |       const Eigen::Matrix<double, Eigen::Dynamic, Cols> & dFdT, | 
					
						
							|  |  |  |       JacobianMap& jacobians) const { | 
					
						
							|  |  |  |     derived().reverseAD(dFdT, jacobians); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   virtual void _reverseAD(const Matrix & dFdT, JacobianMap& jacobians) const { | 
					
						
							|  |  |  |     derived().reverseAD(dFdT, jacobians); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   friend struct internal::ReverseADImplementor<Derived, 1, Cols>; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace internal
 | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * The CallRecord class stores the Jacobians of applying a function | 
					
						
							| 
									
										
										
										
											2014-11-23 02:19:17 +08:00
										 |  |  |  * with respect to each of its arguments. It also stores an execution trace | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  |  * (defined below) for each of its arguments. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * It is implemented in the function-style ExpressionNode's nested Record class below. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<int Cols> | 
					
						
							| 
									
										
										
										
											2014-11-23 04:48:36 +08:00
										 |  |  | struct CallRecord: virtual private internal::ReverseADInterface< | 
					
						
							|  |  |  |     MaxVirtualStaticRows, Cols> { | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   inline void print(const std::string& indent) const { | 
					
						
							|  |  |  |     _print(indent); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   inline void startReverseAD(JacobianMap& jacobians) const { | 
					
						
							|  |  |  |     _startReverseAD(jacobians); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-24 17:48:15 +08:00
										 |  |  |   template<typename Derived> | 
					
						
							|  |  |  |   inline void reverseAD(const Eigen::MatrixBase<Derived> & dFdT, | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  |       JacobianMap& jacobians) const { | 
					
						
							|  |  |  |     _reverseAD( | 
					
						
							| 
									
										
										
										
											2014-11-24 17:48:15 +08:00
										 |  |  |         internal::ConvertToVirtualFunctionSupportedMatrixType<(Derived::RowsAtCompileTime > MaxVirtualStaticRows)>::convert( | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  |             dFdT), jacobians); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-23 04:48:36 +08:00
										 |  |  |   inline void reverseAD(const Matrix & dFdT, JacobianMap& jacobians) const { | 
					
						
							| 
									
										
										
										
											2014-11-22 05:36:32 +08:00
										 |  |  |     _reverseAD(dFdT, jacobians); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  |   virtual ~CallRecord() { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |   virtual void _print(const std::string& indent) const = 0; | 
					
						
							|  |  |  |   virtual void _startReverseAD(JacobianMap& jacobians) const = 0; | 
					
						
							| 
									
										
										
										
											2014-11-23 04:48:36 +08:00
										 |  |  |   using internal::ReverseADInterface<MaxVirtualStaticRows, Cols>::_reverseAD; | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace internal { | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * The CallRecordImplementor implements the CallRecord interface for a Derived class by | 
					
						
							|  |  |  |  * delegating to its corresponding (templated) non-virtual methods. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<typename Derived, int Cols> | 
					
						
							| 
									
										
										
										
											2014-11-23 02:19:17 +08:00
										 |  |  | struct CallRecordImplementor: public CallRecord<Cols>, | 
					
						
							| 
									
										
										
										
											2014-11-23 04:48:36 +08:00
										 |  |  |     private ReverseADImplementor<Derived, MaxVirtualStaticRows, Cols> { | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  | private: | 
					
						
							|  |  |  |   const Derived & derived() const { | 
					
						
							|  |  |  |     return static_cast<const Derived&>(*this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   virtual void _print(const std::string& indent) const { | 
					
						
							|  |  |  |     derived().print(indent); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   virtual void _startReverseAD(JacobianMap& jacobians) const { | 
					
						
							|  |  |  |     derived().startReverseAD(jacobians); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-11-23 04:48:36 +08:00
										 |  |  |   template<typename D, int R, int C> friend struct ReverseADImplementor; | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-23 02:19:17 +08:00
										 |  |  | } // namespace internal
 | 
					
						
							| 
									
										
										
										
											2014-11-21 22:48:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | } // gtsam
 |