| 
									
										
										
										
											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
 | 
					
						
							|  |  |  |   boost::shared_ptr<ExpressionNode<T> > root_; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 18:06:04 +08:00
										 |  |  | public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Construct a constant expression
 | 
					
						
							|  |  |  |   Expression(const T& value) : | 
					
						
							|  |  |  |       root_(new ConstantExpression<T>(value)) { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) : | 
					
						
							|  |  |  |       root_(new LeafExpression<T>(key)) { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-01 19:12:07 +08:00
										 |  |  |   // Construct a leaf expression, with Symbol
 | 
					
						
							|  |  |  |   Expression(const Symbol& symbol) : | 
					
						
							|  |  |  |       root_(new LeafExpression<T>(symbol)) { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Construct a leaf expression, creating Symbol
 | 
					
						
							|  |  |  |   Expression(unsigned char c, size_t j) : | 
					
						
							|  |  |  |       root_(new LeafExpression<T>(Symbol(c, j))) { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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, | 
					
						
							|  |  |  |       T (A::*method)(boost::optional<Matrix&>) const) { | 
					
						
							|  |  |  |     root_.reset( | 
					
						
							|  |  |  |         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, | 
					
						
							|  |  |  |       const Expression<A>& expression) { | 
					
						
							|  |  |  |     root_.reset(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, | 
					
						
							|  |  |  |       T (A1::*method)(const A2&, boost::optional<Matrix&>, | 
					
						
							|  |  |  |           boost::optional<Matrix&>) const, const Expression<A2>& expression2) { | 
					
						
							|  |  |  |     root_.reset( | 
					
						
							|  |  |  |         new BinaryExpression<T, A1, A2>(boost::bind(method, _1, _2, _3, _4), | 
					
						
							|  |  |  |             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, | 
					
						
							|  |  |  |       const Expression<A1>& expression1, const Expression<A2>& expression2) { | 
					
						
							|  |  |  |     root_.reset( | 
					
						
							|  |  |  |         new BinaryExpression<T, A1, A2>(function, expression1, expression2)); | 
					
						
							| 
									
										
										
										
											2014-09-30 19:19:44 +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(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Return value and optional derivatives
 | 
					
						
							| 
									
										
										
										
											2014-10-03 16:25:02 +08:00
										 |  |  |   T value(const Values& values) const { | 
					
						
							|  |  |  |     return root_->value(values); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Return value and derivatives
 | 
					
						
							|  |  |  |   Augmented<T> augmented(const Values& values) const { | 
					
						
							| 
									
										
										
										
											2014-10-05 21:00:10 +08:00
										 |  |  | #define REVERSE_AD
 | 
					
						
							|  |  |  | #ifdef REVERSE_AD
 | 
					
						
							| 
									
										
										
										
											2014-10-05 23:20:55 +08:00
										 |  |  |     boost::shared_ptr<JacobianTrace<T> > trace = root_->traceExecution(values); | 
					
						
							| 
									
										
										
										
											2014-10-05 23:12:38 +08:00
										 |  |  |     Augmented<T> augmented(trace->value()); | 
					
						
							| 
									
										
										
										
											2014-10-05 19:27:41 +08:00
										 |  |  |     size_t n = T::Dim(); | 
					
						
							| 
									
										
										
										
											2014-10-05 23:20:55 +08:00
										 |  |  |     trace->reverseAD(Eigen::MatrixXd::Identity(n, n), augmented.jacobians()); | 
					
						
							| 
									
										
										
										
											2014-10-05 23:12:38 +08:00
										 |  |  |     return augmented; | 
					
						
							| 
									
										
										
										
											2014-10-05 21:00:10 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     return root_->forward(values); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											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-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; | 
					
						
							|  |  |  |   T operator()(const T& x, const T& y, boost::optional<Matrix&> H1, | 
					
						
							|  |  |  |       boost::optional<Matrix&> H2) const { | 
					
						
							|  |  |  |     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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |