| 
									
										
										
										
											2014-09-29 18:06:04 +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 Expression.h | 
					
						
							|  |  |  |  * @date September 18, 2014 | 
					
						
							|  |  |  |  * @author Frank Dellaert | 
					
						
							|  |  |  |  * @author Paul Furgale | 
					
						
							|  |  |  |  * @brief Expressions for Block Automatic Differentiation | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-30 19:00:37 +08:00
										 |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-30 18:20:02 +08:00
										 |  |  | #include "Expression-inl.h"
 | 
					
						
							| 
									
										
										
										
											2014-10-01 19:12:07 +08:00
										 |  |  | #include <gtsam/inference/Symbol.h>
 | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  | #include <boost/bind.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Expression class that supports automatic differentiation | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<typename T> | 
					
						
							|  |  |  | class Expression { | 
					
						
							| 
									
										
										
										
											2014-10-03 19:18:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Paul's trick shared pointer, polymorphic root of entire expression tree
 | 
					
						
							| 
									
										
										
										
											2014-10-16 17:15:47 +08:00
										 |  |  |   boost::shared_ptr<ExpressionNode<T> > root_; | 
					
						
							| 
									
										
										
										
											2014-10-03 19:18:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  | public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Construct a constant expression
 | 
					
						
							|  |  |  |   Expression(const T& value) : | 
					
						
							| 
									
										
										
										
											2014-10-16 17:15:47 +08:00
										 |  |  |       root_(new ConstantExpression<T>(value)) { | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-01 19:12:07 +08:00
										 |  |  |   // Construct a leaf expression, with Key
 | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  |   Expression(const Key& key) : | 
					
						
							| 
									
										
										
										
											2014-10-16 17:15:47 +08:00
										 |  |  |       root_(new LeafExpression<T>(key)) { | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-01 19:12:07 +08:00
										 |  |  |   // Construct a leaf expression, with Symbol
 | 
					
						
							|  |  |  |   Expression(const Symbol& symbol) : | 
					
						
							| 
									
										
										
										
											2014-10-16 17:15:47 +08:00
										 |  |  |       root_(new LeafExpression<T>(symbol)) { | 
					
						
							| 
									
										
										
										
											2014-10-01 19:12:07 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Construct a leaf expression, creating Symbol
 | 
					
						
							|  |  |  |   Expression(unsigned char c, size_t j) : | 
					
						
							| 
									
										
										
										
											2014-10-16 17:15:47 +08:00
										 |  |  |       root_(new LeafExpression<T>(Symbol(c, j)))  { | 
					
						
							| 
									
										
										
										
											2014-10-01 19:12:07 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-03 18:40:26 +08:00
										 |  |  |   /// Construct a nullary method expression
 | 
					
						
							| 
									
										
										
										
											2014-10-03 19:18:25 +08:00
										 |  |  |   template<typename A> | 
					
						
							|  |  |  |   Expression(const Expression<A>& expression, | 
					
						
							| 
									
										
										
										
											2014-10-28 18:20:02 +08:00
										 |  |  |       T (A::*method)(typename OptionalJacobian<T, A>::type) const) : | 
					
						
							| 
									
										
										
										
											2014-10-16 17:15:47 +08:00
										 |  |  |       root_(new UnaryExpression<T, A>(boost::bind(method, _1, _2), expression)) { | 
					
						
							| 
									
										
										
										
											2014-10-03 18:40:26 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Construct a unary function expression
 | 
					
						
							| 
									
										
										
										
											2014-10-03 19:18:25 +08:00
										 |  |  |   template<typename A> | 
					
						
							|  |  |  |   Expression(typename UnaryExpression<T, A>::Function function, | 
					
						
							| 
									
										
										
										
											2014-10-14 23:46:57 +08:00
										 |  |  |       const Expression<A>& expression) : | 
					
						
							| 
									
										
										
										
											2014-10-16 17:15:47 +08:00
										 |  |  |       root_(new UnaryExpression<T, A>(function, expression)) { | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-03 18:48:28 +08:00
										 |  |  |   /// Construct a unary method expression
 | 
					
						
							| 
									
										
										
										
											2014-10-03 19:18:25 +08:00
										 |  |  |   template<typename A1, typename A2> | 
					
						
							|  |  |  |   Expression(const Expression<A1>& expression1, | 
					
						
							| 
									
										
										
										
											2014-10-28 18:20:02 +08:00
										 |  |  |       T (A1::*method)(const A2&, typename OptionalJacobian<T, A1>::type, | 
					
						
							|  |  |  |           typename OptionalJacobian<T, A2>::type) const, | 
					
						
							| 
									
										
										
										
											2014-10-14 23:46:57 +08:00
										 |  |  |       const Expression<A2>& expression2) : | 
					
						
							|  |  |  |       root_( | 
					
						
							|  |  |  |           new BinaryExpression<T, A1, A2>(boost::bind(method, _1, _2, _3, _4), | 
					
						
							| 
									
										
										
										
											2014-10-16 17:15:47 +08:00
										 |  |  |               expression1, expression2)) { | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-03 18:48:28 +08:00
										 |  |  |   /// Construct a binary function expression
 | 
					
						
							| 
									
										
										
										
											2014-10-03 19:18:25 +08:00
										 |  |  |   template<typename A1, typename A2> | 
					
						
							|  |  |  |   Expression(typename BinaryExpression<T, A1, A2>::Function function, | 
					
						
							| 
									
										
										
										
											2014-10-14 23:46:57 +08:00
										 |  |  |       const Expression<A1>& expression1, const Expression<A2>& expression2) : | 
					
						
							|  |  |  |       root_( | 
					
						
							| 
									
										
										
										
											2014-10-16 17:15:47 +08:00
										 |  |  |           new BinaryExpression<T, A1, A2>(function, expression1, expression2)) { | 
					
						
							| 
									
										
										
										
											2014-09-30 19:19:44 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-06 04:09:24 +08:00
										 |  |  |   /// Construct a ternary function expression
 | 
					
						
							|  |  |  |   template<typename A1, typename A2, typename A3> | 
					
						
							|  |  |  |   Expression(typename TernaryExpression<T, A1, A2, A3>::Function function, | 
					
						
							| 
									
										
										
										
											2014-10-07 07:01:46 +08:00
										 |  |  |       const Expression<A1>& expression1, const Expression<A2>& expression2, | 
					
						
							| 
									
										
										
										
											2014-10-14 23:46:57 +08:00
										 |  |  |       const Expression<A3>& expression3) : | 
					
						
							|  |  |  |       root_( | 
					
						
							|  |  |  |           new TernaryExpression<T, A1, A2, A3>(function, expression1, | 
					
						
							| 
									
										
										
										
											2014-10-16 17:15:47 +08:00
										 |  |  |               expression2, expression3)) { | 
					
						
							| 
									
										
										
										
											2014-10-06 04:09:24 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  |   /// Return keys that play in this expression
 | 
					
						
							|  |  |  |   std::set<Key> keys() const { | 
					
						
							|  |  |  |     return root_->keys(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 18:01:20 +08:00
										 |  |  |   /// Return dimensions for each argument, as a map
 | 
					
						
							|  |  |  |   void dims(std::map<Key, size_t>& map) const { | 
					
						
							|  |  |  |     root_->dims(map); | 
					
						
							| 
									
										
										
										
											2014-10-14 15:53:47 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-11 18:11:22 +08:00
										 |  |  |   // Return size needed for memory buffer in traceExecution
 | 
					
						
							|  |  |  |   size_t traceSize() const { | 
					
						
							|  |  |  |     return root_->traceSize(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-15 16:07:30 +08:00
										 |  |  |   /// trace execution, very unsafe, for testing purposes only //TODO this is not only used for testing, but in value() below!
 | 
					
						
							| 
									
										
										
										
											2014-10-11 17:29:42 +08:00
										 |  |  |   T traceExecution(const Values& values, ExecutionTrace<T>& trace, | 
					
						
							| 
									
										
										
										
											2014-10-11 19:07:58 +08:00
										 |  |  |       char* raw) const { | 
					
						
							| 
									
										
										
										
											2014-10-11 17:29:42 +08:00
										 |  |  |     return root_->traceExecution(values, trace, raw); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Return value and derivatives, reverse AD version
 | 
					
						
							| 
									
										
										
										
											2014-11-01 18:35:49 +08:00
										 |  |  |   T value(const Values& values, JacobianMap& jacobians) const { | 
					
						
							| 
									
										
										
										
											2014-10-19 17:19:09 +08:00
										 |  |  |     // The following piece of code is absolutely crucial for performance.
 | 
					
						
							|  |  |  |     // We allocate a block of memory on the stack, which can be done at runtime
 | 
					
						
							|  |  |  |     // with modern C++ compilers. The traceExecution then fills this memory
 | 
					
						
							|  |  |  |     // with an execution trace, made up entirely of "Record" structs, see
 | 
					
						
							|  |  |  |     // the FunctionalNode class in expression-inl.h
 | 
					
						
							| 
									
										
										
										
											2014-10-11 18:11:22 +08:00
										 |  |  |     size_t size = traceSize(); | 
					
						
							|  |  |  |     char raw[size]; | 
					
						
							| 
									
										
										
										
											2014-10-11 17:03:35 +08:00
										 |  |  |     ExecutionTrace<T> trace; | 
					
						
							| 
									
										
										
										
											2014-10-11 18:11:22 +08:00
										 |  |  |     T value(traceExecution(values, trace, raw)); | 
					
						
							| 
									
										
										
										
											2014-10-13 02:16:08 +08:00
										 |  |  |     trace.startReverseAD(jacobians); | 
					
						
							|  |  |  |     return value; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Return value
 | 
					
						
							|  |  |  |   T value(const Values& values) const { | 
					
						
							|  |  |  |     return root_->value(values); | 
					
						
							| 
									
										
										
										
											2014-10-11 17:29:42 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  |   const boost::shared_ptr<ExpressionNode<T> >& root() const { | 
					
						
							|  |  |  |     return root_; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-10-03 19:18:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-13 19:04:37 +08:00
										 |  |  |   /// Define type so we can apply it as a meta-function
 | 
					
						
							|  |  |  |   typedef Expression<T> type; | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // http://stackoverflow.com/questions/16260445/boost-bind-to-operator
 | 
					
						
							|  |  |  | template<class T> | 
					
						
							|  |  |  | struct apply_compose { | 
					
						
							|  |  |  |   typedef T result_type; | 
					
						
							| 
									
										
										
										
											2014-10-21 07:26:17 +08:00
										 |  |  |   static const int Dim = traits::dimension<T>::value; | 
					
						
							| 
									
										
										
										
											2014-10-19 06:35:25 +08:00
										 |  |  |   typedef Eigen::Matrix<double, Dim, Dim> Jacobian; | 
					
						
							| 
									
										
										
										
											2014-10-07 07:01:46 +08:00
										 |  |  |   T operator()(const T& x, const T& y, boost::optional<Jacobian&> H1, | 
					
						
							|  |  |  |       boost::optional<Jacobian&> H2) const { | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  |     return x.compose(y, H1, H2); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// Construct a product expression, assumes T::compose(T) -> T
 | 
					
						
							|  |  |  | template<typename T> | 
					
						
							|  |  |  | Expression<T> operator*(const Expression<T>& expression1, | 
					
						
							|  |  |  |     const Expression<T>& expression2) { | 
					
						
							|  |  |  |   return Expression<T>(boost::bind(apply_compose<T>(), _1, _2, _3, _4), | 
					
						
							|  |  |  |       expression1, expression2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 16:38:54 +08:00
										 |  |  | /// Construct an array of leaves
 | 
					
						
							|  |  |  | template<typename T> | 
					
						
							|  |  |  | std::vector<Expression<T> > createUnknowns(size_t n, char c, size_t start = 0) { | 
					
						
							|  |  |  |   std::vector<Expression<T> > unknowns; | 
					
						
							|  |  |  |   unknowns.reserve(n); | 
					
						
							|  |  |  |   for (size_t i = start; i < start + n; i++) | 
					
						
							|  |  |  |     unknowns.push_back(Expression<T>(c, i)); | 
					
						
							|  |  |  |   return unknowns; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 |