gtsam  4.0.0
gtsam
Expression-inl.h
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
20 #pragma once
21 
22 #include <gtsam/nonlinear/internal/ExpressionNode.h>
23 
24 #include <boost/tuple/tuple.hpp>
25 #include <boost/range/adaptor/map.hpp>
26 #include <boost/range/algorithm.hpp>
27 
28 namespace gtsam {
29 
30 template<typename T>
31 Expression<T>::Expression(const T& value) :
32  root_(new internal::ConstantExpression<T>(value)) {
33 }
34 
35 template<typename T>
37  root_(new internal::LeafExpression<T>(key)) {
38 }
39 
40 template<typename T>
42  root_(new internal::LeafExpression<T>(symbol)) {
43 }
44 
45 template<typename T>
46 Expression<T>::Expression(unsigned char c, std::uint64_t j) :
47  root_(new internal::LeafExpression<T>(Symbol(c, j))) {
48 }
49 
51 template<typename T>
52 template<typename A>
53 Expression<T>::Expression(typename UnaryFunction<A>::type function,
54  const Expression<A>& expression) :
55  root_(new internal::UnaryExpression<T, A>(function, expression)) {
56 }
57 
59 template<typename T>
60 template<typename A1, typename A2>
61 Expression<T>::Expression(typename BinaryFunction<A1, A2>::type function,
62  const Expression<A1>& expression1, const Expression<A2>& expression2) :
63  root_(
64  new internal::BinaryExpression<T, A1, A2>(function, expression1,
65  expression2)) {
66 }
67 
69 template<typename T>
70 template<typename A1, typename A2, typename A3>
71 Expression<T>::Expression(typename TernaryFunction<A1, A2, A3>::type function,
72  const Expression<A1>& expression1, const Expression<A2>& expression2,
73  const Expression<A3>& expression3) :
74  root_(
75  new internal::TernaryExpression<T, A1, A2, A3>(function, expression1,
76  expression2, expression3)) {
77 }
78 
80 template<typename T>
81 template<typename A>
83  T (A::*method)(typename MakeOptionalJacobian<T, A>::type) const) :
84  root_(
85  new internal::UnaryExpression<T, A>(boost::bind(method, _1, _2),
86  expression)) {
87 }
88 
90 template<typename T>
91 template<typename A1, typename A2>
93  T (A1::*method)(const A2&, typename MakeOptionalJacobian<T, A1>::type,
94  typename MakeOptionalJacobian<T, A2>::type) const,
95  const Expression<A2>& expression2) :
96  root_(
97  new internal::BinaryExpression<T, A1, A2>(
98  boost::bind(method, _1, _2, _3, _4), expression1, expression2)) {
99 }
100 
102 template<typename T>
103 template<typename A1, typename A2, typename A3>
105  T (A1::*method)(const A2&, const A3&,
108  typename MakeOptionalJacobian<T, A3>::type) const,
109  const Expression<A2>& expression2, const Expression<A3>& expression3) :
110  root_(
111  new internal::TernaryExpression<T, A1, A2, A3>(
112  boost::bind(method, _1, _2, _3, _4, _5, _6), expression1,
113  expression2, expression3)) {
114 }
115 
116 template<typename T>
117 std::set<Key> Expression<T>::keys() const {
118  return root_->keys();
119 }
120 
121 template<typename T>
122 void Expression<T>::dims(std::map<Key, int>& map) const {
123  root_->dims(map);
124 }
125 
126 template<typename T>
127 void Expression<T>::print(const std::string& s) const {
128  root_->print(s);
129 }
130 
131 template<typename T>
132 T Expression<T>::value(const Values& values,
133  boost::optional<std::vector<Matrix>&> H) const {
134 
135  if (H) {
136  // Call private version that returns derivatives in H
137  KeysAndDims pair = keysAndDims();
138  return valueAndDerivatives(values, pair.first, pair.second, *H);
139  } else
140  // no derivatives needed, just return value
141  return root_->value(values);
142 }
143 
144 template<typename T>
145 const boost::shared_ptr<internal::ExpressionNode<T> >& Expression<T>::root() const {
146  return root_;
147 }
148 
149 template<typename T>
150 size_t Expression<T>::traceSize() const {
151  return root_->traceSize();
152 }
153 
154 // Private methods:
155 
156 template<typename T>
158  const KeyVector& keys, const FastVector<int>& dims,
159  std::vector<Matrix>& H) const {
160 
161  // H should be pre-allocated
162  assert(H.size()==keys.size());
163 
164  // Pre-allocate and zero VerticalBlockMatrix
165  static const int Dim = traits<T>::dimension;
166  VerticalBlockMatrix Ab(dims, Dim);
167  Ab.matrix().setZero();
168  internal::JacobianMap jacobianMap(keys, Ab);
169 
170  // Call unsafe version
171  T result = valueAndJacobianMap(values, jacobianMap);
172 
173  // Copy blocks into the vector of jacobians passed in
174  for (DenseIndex i = 0; i < static_cast<DenseIndex>(keys.size()); i++)
175  H[i] = Ab(i);
176 
177  return result;
178 }
179 
180 template<typename T>
182  internal::ExecutionTrace<T>& trace, void* traceStorage) const {
183  return root_->traceExecution(values, trace,
184  static_cast<internal::ExecutionTraceStorage*>(traceStorage));
185 }
186 
187 template<typename T>
189  internal::JacobianMap& jacobians) const {
190  // The following piece of code is absolutely crucial for performance.
191  // We allocate a block of memory on the stack, which can be done at runtime
192  // with modern C++ compilers. The traceExecution then fills this memory
193  // with an execution trace, made up entirely of "Record" structs, see
194  // the FunctionalNode class in expression-inl.h
195  size_t size = traceSize();
196 
197  // Windows does not support variable length arrays, so memory must be dynamically
198  // allocated on Visual Studio. For more information see the issue below
199  // https://bitbucket.org/gtborg/gtsam/issue/178/vlas-unsupported-in-visual-studio
200 #ifdef _MSC_VER
201  internal::ExecutionTraceStorage* traceStorage = new internal::ExecutionTraceStorage[size];
202 #else
203  internal::ExecutionTraceStorage traceStorage[size];
204 #endif
205 
207  T value(this->traceExecution(values, trace, traceStorage));
208  trace.startReverseAD1(jacobians);
209 
210 #ifdef _MSC_VER
211  delete[] traceStorage;
212 #endif
213 
214  return value;
215 }
216 
217 template<typename T>
219  std::map<Key, int> map;
220  dims(map);
221  size_t n = map.size();
222  KeysAndDims pair = std::make_pair(KeyVector(n), FastVector<int>(n));
223  boost::copy(map | boost::adaptors::map_keys, pair.first.begin());
224  boost::copy(map | boost::adaptors::map_values, pair.second.begin());
225  return pair;
226 }
227 
228 namespace internal {
229 // http://stackoverflow.com/questions/16260445/boost-bind-to-operator
230 template<class T>
232  typedef T result_type;
233  static const int Dim = traits<T>::dimension;
234  T operator()(const T& x, const T& y, OptionalJacobian<Dim, Dim> H1 =
235  boost::none, OptionalJacobian<Dim, Dim> H2 = boost::none) const {
236  return x.compose(y, H1, H2);
237  }
238 };
239 }
240 
241 // Global methods:
242 
244 template<typename T>
246  const Expression<T>& expression2) {
247  return Expression<T>(
248  boost::bind(internal::apply_compose<T>(), _1, _2, _3, _4), expression1,
249  expression2);
250 }
251 
253 template<typename T>
254 std::vector<Expression<T> > createUnknowns(size_t n, char c, size_t start) {
255  std::vector<Expression<T> > unknowns;
256  unknowns.reserve(n);
257  for (size_t i = start; i < start + n; i++)
258  unknowns.push_back(Expression<T>(c, i));
259  return unknowns;
260 }
261 
262 template <typename T>
264  : Expression<T>(boost::make_shared<internal::ScalarMultiplyNode<T>>(s, e)) {}
265 
266 
267 template <typename T>
269  : Expression<T>(boost::make_shared<internal::BinarySumNode<T>>(e1, e2)) {}
270 
271 template <typename T>
273  root_ = boost::make_shared<internal::BinarySumNode<T>>(*this, e);
274  return *this;
275 }
276 
277 } // namespace gtsam
Expression class that supports automatic differentiation.
Definition: Expression.h:49
Definition: Expression.h:41
void print(const std::string &s) const
Print.
Definition: Expression-inl.h:127
Character and index key used in VectorValues, GaussianFactorGraph, GaussianFactor, etc.
Definition: Symbol.h:34
std::pair< KeyVector, FastVector< int > > KeysAndDims
Keys and dimensions in same order.
Definition: Expression.h:186
std::vector< Expression< T > > createUnknowns(size_t n, char c, size_t start)
Construct an array of leaves.
Definition: Expression-inl.h:254
T valueAndDerivatives(const Values &values, const KeyVector &keys, const FastVector< int > &dims, std::vector< Matrix > &H) const
private version that takes keys and dimensions, returns derivatives
Definition: Expression-inl.h:157
OptionalJacobian is an Eigen::Ref like class that can take be constructed using either a fixed size o...
Definition: OptionalJacobian.h:39
Definition: VerticalBlockMatrix.h:41
size_t traceSize() const
Return size needed for memory buffer in traceExecution.
Definition: Expression-inl.h:150
T valueAndJacobianMap(const Values &values, internal::JacobianMap &jacobians) const
brief Return value and derivatives, reverse AD version
Definition: Expression-inl.h:188
A non-templated config holding any types of Manifold-group elements.
Definition: Values.h:70
const Matrix & matrix() const
Access to full matrix (including any portions excluded by rowStart(), rowEnd(), and firstBlock()) ...
Definition: VerticalBlockMatrix.h:187
ptrdiff_t DenseIndex
The index type for Eigen objects.
Definition: types.h:60
FastVector< Key > KeyVector
Useful typedef for operations with Values - allows for matlab interface.
Definition: Key.h:56
T value(const Values &values, boost::optional< std::vector< Matrix > & > H=boost::none) const
Return value and optional derivatives, reverse AD version Notes: this is not terribly efficient...
Definition: Expression-inl.h:132
A manifold defines a space in which there is a notion of a linear tangent space that can be centered ...
Definition: concepts.h:30
Definition: Expression-inl.h:231
Point2 operator*(double s, const Point2 &p)
multiply with scalar
Definition: Point2.h:170
Expression< T > & operator+=(const Expression< T > &e)
Add another expression to this expression.
Definition: Expression-inl.h:272
A BinarySumExpression is a specialization of Expression that adds two expressions together It optimiz...
Definition: Expression.h:227
std::set< Key > keys() const
Return keys that play in this expression.
Definition: Expression-inl.h:117
A ScalarMultiplyExpression is a specialization of Expression that multiplies with a scalar It optimiz...
Definition: Expression.h:214
T traceExecution(const Values &values, internal::ExecutionTrace< T > &trace, void *traceStorage) const
trace execution, very unsafe
Definition: Expression-inl.h:181
const boost::shared_ptr< internal::ExpressionNode< T > > & root() const
Return root.
Definition: Expression-inl.h:145
void dims(std::map< Key, int > &map) const
Return dimensions for each argument, as a map.
Definition: Expression-inl.h:122
Key symbol(unsigned char c, std::uint64_t j)
Create a symbol key from a character and index, i.e.
Definition: Symbol.h:128
Definition: FastSet.h:29
Expression()
Default constructor, for serialization.
Definition: Expression.h:183
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:57
Global functions in a separate testing namespace.
Definition: chartTesting.h:28