Exotica
autodiff_chain_hessian.h
Go to the documentation of this file.
1 // Copyright (C) 2018
2 //
3 // This Source Code Form is subject to the terms of the Mozilla
4 // Public License v. 2.0. If a copy of the MPL was not distributed
5 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 //
7 // Modified from unsupported/Eigen/src/AutoDiff/AutoDiffJacobian.h
8 
9 #ifndef EIGEN_AUTODIFF_CHAIN_HESSIAN_H_
10 #define EIGEN_AUTODIFF_CHAIN_HESSIAN_H_
11 
15 
16 namespace Eigen
17 {
18 template <typename Functor>
20 {
21 public:
24 // forward constructors
25 #if EIGEN_HAS_VARIADIC_TEMPLATES
26  template <typename... T>
27  AutoDiffChainHessian(const T &... Values) : Functor(Values...)
28  {
29  }
30 #else
31  template <typename T0>
32  AutoDiffChainHessian(const T0 &a0) : Functor(a0)
33  {
34  }
35  template <typename T0, typename T1>
36  AutoDiffChainHessian(const T0 &a0, const T1 &a1) : Functor(a0, a1)
37  {
38  }
39  template <typename T0, typename T1, typename T2>
40  AutoDiffChainHessian(const T0 &a0, const T1 &a1, const T2 &a2) : Functor(a0, a1, a2)
41  {
42  }
43 #endif
44 
45  typedef typename Functor::InputType InputType;
46  typedef typename Functor::ValueType ValueType;
47  typedef typename ValueType::Scalar Scalar;
48 
49  enum
50  {
51  InputsAtCompileTime = InputType::RowsAtCompileTime,
52  ValuesAtCompileTime = ValueType::RowsAtCompileTime,
53  JacobianInputsAtCompileTime = Functor::JacobianColsAtCompileTime // JacobianInputsAtCompileTime no longer have to match InputsAtCompileTime
54  };
55 
56  typedef Matrix<Scalar, ValuesAtCompileTime, JacobianInputsAtCompileTime> JacobianType;
57 
58  typedef Matrix<Scalar, InputsAtCompileTime, JacobianInputsAtCompileTime> InputJacobianType; // Jacobian.cols() matches InputJacobian.cols()
59  typedef Array<Matrix<Scalar, JacobianInputsAtCompileTime, JacobianInputsAtCompileTime>, ValuesAtCompileTime, 1> HessianType;
60  typedef Array<Matrix<Scalar, JacobianInputsAtCompileTime, JacobianInputsAtCompileTime>, InputsAtCompileTime, 1> InputHessianType;
61  typedef typename JacobianType::Index Index;
62 
63  typedef Matrix<Scalar, JacobianInputsAtCompileTime, 1> InnerDerivativeType; // Derivative rows() matches InputJacobian.cols()
65  typedef Matrix<InnerActiveScalar, JacobianInputsAtCompileTime, 1> OuterDerivativeType;
67 
68  typedef Matrix<OuterActiveScalar, InputsAtCompileTime, 1> ActiveInput;
69  typedef Matrix<OuterActiveScalar, ValuesAtCompileTime, 1> ActiveValue;
70 
71 #if EIGEN_HAS_VARIADIC_TEMPLATES
72  // Some compilers don't accept variadic parameters after a default parameter,
73  // i.e., we can't just write _jac=0 but we need to overload operator():
74  EIGEN_STRONG_INLINE
75  void operator()(const InputType &x, ValueType &v) const
76  {
77  this->operator()(x, v);
78  }
79 
80  template <typename... ParamsType>
81  void operator()(const InputType &x, ValueType &v, const ParamsType &... Params) const
82  {
83  this->operator()(x, v, Params...);
84  }
85 
86  template <typename... ParamsType>
87  void operator()(const InputType &x, ValueType &v, JacobianType &jac, const ParamsType &... Params) const
88  {
89  AutoDiffChainJacobian<Functor> autoj(*static_cast<const Functor *>(this));
90  autoj(x, v, jac, Params...);
91  }
92 
93  template <typename... ParamsType>
94  void operator()(const InputType &x, ValueType &v, JacobianType &jac, const InputJacobianType &ijac,
95  const ParamsType &... Params) const
96  {
97  AutoDiffChainJacobian<Functor> autoj(*static_cast<const Functor *>(this));
98  autoj(x, v, jac, ijac, Params...);
99  }
100 
101  template <typename... ParamsType>
102  void operator()(const InputType &x, ValueType &v, JacobianType &jac, HessianType &hess, const ParamsType &... Params) const
103  {
104  this->operator()(x, v, jac, hess, nullptr, nullptr, Params...);
105  }
106 
107  template <typename... ParamsType>
108  void operator()(const InputType &x, ValueType &v, JacobianType &jac, HessianType &hess, const InputJacobianType &ijac, const InputHessianType &ihess,
109  const ParamsType &... Params) const
110  {
111  this->operator()(x, v, jac, hess, &ijac, &ihess, Params...);
112  }
113 
114  // Optional parameter InputJacobian (_ijac)
115  template <typename... ParamsType>
116  void operator()(const InputType &x, ValueType &v, JacobianType &jac, HessianType &hess, const InputJacobianType *_ijac = 0, const InputHessianType *_ihess = 0,
117  const ParamsType &... Params) const
118 #else
119  EIGEN_STRONG_INLINE
120  void operator()(const InputType &x, ValueType &v) const
121  {
122  this->operator()(x, v);
123  }
124 
125  void operator()(const InputType &x, ValueType &v, JacobianType &jac) const
126  {
127  AutoDiffChainJacobian<Functor> autoj(*static_cast<const Functor *>(this));
128  autoj(x, v, jac);
129  }
130 
131  void operator()(const InputType &x, ValueType &v, JacobianType &jac, const InputJacobianType &ijac) const
132  {
133  AutoDiffChainJacobian<Functor> autoj(*static_cast<const Functor *>(this));
134  autoj(x, v, jac, ijac);
135  }
136 
137  void operator()(const InputType &x, ValueType &v, JacobianType &jac, HessianType &hess) const
138  {
139  this->operator()(x, v, jac, hess, nullptr, nullptr);
140  }
141 
142  void operator()(const InputType &x, ValueType &v, JacobianType &jac, HessianType &hess, const InputJacobianType &ijac, const InputHessianType &ihess) const
143  {
144  this->operator()(x, v, jac, hess, &ijac, &ihess);
145  }
146 
147  void operator()(const InputType &x, ValueType &v, JacobianType &jac = 0, HessianType &hess, const InputJacobianType *_ijac = 0, const InputHessianType *_ihess = 0) const
148 #endif
149  {
150  ActiveInput ax = x.template cast<OuterActiveScalar>();
151  ActiveValue av(jac.rows());
152 
153  // Provide either both input jacobian and hessian, or none
154  eigen_assert((_ijac && _ihess) || (!_ijac && !_ihess));
155 
156  if (!_ijac)
157  {
159 
160  if (InputsAtCompileTime == Dynamic)
161  for (Index j = 0; j < jac.rows(); ++j)
162  {
163  av[j].derivatives().resize(x.rows());
164  for (Index k = 0; k < x.rows(); ++k)
165  av[j].derivatives()[k].derivatives().resize(x.rows());
166  }
167 
168  for (Index i = 0; i < x.rows(); ++i)
169  {
170  ax[i].derivatives() = InnerDerivativeType::Unit(x.rows(), i);
171  ax[i].value().derivatives() = InnerDerivativeType::Unit(x.rows(), i);
172  for (Index k = 0; k < x.rows(); ++k)
173  {
174  ax[i].derivatives()(k).derivatives() = InnerDerivativeType::Zero(x.rows());
175  }
176  }
177  }
178  else
179  {
180  // If specified, copy derivatives from InputJacobian
181  const InputJacobianType &ijac = *_ijac;
182  const InputHessianType &ihess = *_ihess;
183 
184  eigen_assert(x.rows() == ihess.rows());
185  eigen_assert(ijac.cols() == ihess[0].rows() && ijac.cols() == ihess[0].cols());
186 
187  if (InputsAtCompileTime == Dynamic)
188  for (Index j = 0; j < jac.rows(); ++j)
189  {
190  av[j].derivatives().resize(ijac.cols());
191  for (Index k = 0; k < ijac.cols(); ++k)
192  av[j].derivatives()[k].derivatives().resize(ijac.cols());
193  }
194 
195  for (Index i = 0; i < x.rows(); ++i)
196  {
197  ax[i].derivatives() = ijac.row(i);
198  ax[i].value().derivatives() = ijac.row(i);
199  for (Index k = 0; k < ijac.cols(); ++k)
200  {
201  ax[i].derivatives()(k).derivatives() = ihess[i].row(k);
202  }
203  }
204  }
205 
206 #if EIGEN_HAS_VARIADIC_TEMPLATES
207  Functor::operator()(ax, av, Params...);
208 #else
209  Functor::operator()(ax, av);
210 #endif
211 
212  Index cols = _ijac ? _ijac->cols() : x.rows();
213  if (JacobianInputsAtCompileTime == Dynamic)
214  {
215  hess.resize(jac.rows());
216  for (Index i = 0; i < jac.rows(); ++i)
217  hess[i].resize(cols, cols);
218  }
219 
220  for (Index i = 0; i < jac.rows(); ++i)
221  {
222  v[i] = av[i].value().value();
223  jac.row(i) = av[i].value().derivatives();
224  for (Index j = 0; j < cols; ++j)
225  hess[i].row(j) = av[i].derivatives()[j].derivatives();
226  }
227  }
228 };
229 
230 } // namespace Eigen
231 
232 #endif // EIGEN_AUTODIFF_CHAIN_HESSIAN_H_
Eigen::AutoDiffChainHessian::AutoDiffChainHessian
AutoDiffChainHessian(const T0 &a0, const T1 &a1, const T2 &a2)
Definition: autodiff_chain_hessian.h:40
autodiff_scalar.h
Eigen
Definition: autodiff_chain_hessian.h:16
Eigen::AutoDiffChainHessian::InputJacobianType
Matrix< Scalar, InputsAtCompileTime, JacobianInputsAtCompileTime > InputJacobianType
Definition: autodiff_chain_hessian.h:58
Eigen::AutoDiffChainHessian::AutoDiffChainHessian
AutoDiffChainHessian(const T0 &a0)
Definition: autodiff_chain_hessian.h:32
Eigen::AutoDiffChainJacobian
Definition: autodiff_chain_jacobian.h:18
Eigen::AutoDiffScalar
Definition: autodiff_scalar.h:48
Eigen::AutoDiffChainHessian::ActiveInput
Matrix< OuterActiveScalar, InputsAtCompileTime, 1 > ActiveInput
Definition: autodiff_chain_hessian.h:68
Eigen::AutoDiffChainHessian::InnerDerivativeType
Matrix< Scalar, JacobianInputsAtCompileTime, 1 > InnerDerivativeType
Definition: autodiff_chain_hessian.h:63
Eigen::AutoDiffChainHessian::InnerActiveScalar
AutoDiffScalar< InnerDerivativeType > InnerActiveScalar
Definition: autodiff_chain_hessian.h:64
Eigen::AutoDiffChainHessian::ActiveValue
Matrix< OuterActiveScalar, ValuesAtCompileTime, 1 > ActiveValue
Definition: autodiff_chain_hessian.h:69
exotica::Functor
FunctorBase< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic > Functor
Definition: functor.h:49
Eigen::AutoDiffChainHessian::operator()
void operator()(const InputType &x, ValueType &v, JacobianType &jac, HessianType &hess, const InputJacobianType &ijac, const InputHessianType &ihess) const
Definition: autodiff_chain_hessian.h:142
Eigen::AutoDiffChainHessian::operator()
EIGEN_STRONG_INLINE void operator()(const InputType &x, ValueType &v) const
Definition: autodiff_chain_hessian.h:120
Eigen::AutoDiffChainHessian::operator()
void operator()(const InputType &x, ValueType &v, JacobianType &jac, HessianType &hess) const
Definition: autodiff_chain_hessian.h:137
Eigen::AutoDiffChainHessian::operator()
void operator()(const InputType &x, ValueType &v, JacobianType &jac=0, HessianType &hess, const InputJacobianType *_ijac=0, const InputHessianType *_ihess=0) const
Definition: autodiff_chain_hessian.h:147
autodiff_chain_jacobian.h
Eigen::AutoDiffChainHessian::ValuesAtCompileTime
@ ValuesAtCompileTime
Definition: autodiff_chain_hessian.h:52
Eigen::AutoDiffChainHessian::InputHessianType
Array< Matrix< Scalar, JacobianInputsAtCompileTime, JacobianInputsAtCompileTime >, InputsAtCompileTime, 1 > InputHessianType
Definition: autodiff_chain_hessian.h:60
Eigen::AutoDiffChainHessian::AutoDiffChainHessian
AutoDiffChainHessian()
Definition: autodiff_chain_hessian.h:22
Eigen::AutoDiffChainHessian::AutoDiffChainHessian
AutoDiffChainHessian(const Functor &f)
Definition: autodiff_chain_hessian.h:23
Eigen::AutoDiffChainHessian::operator()
void operator()(const InputType &x, ValueType &v, JacobianType &jac) const
Definition: autodiff_chain_hessian.h:125
Eigen::AutoDiffChainHessian::ValueType
Functor::ValueType ValueType
Definition: autodiff_chain_hessian.h:46
Eigen::AutoDiffChainHessian::AutoDiffChainHessian
AutoDiffChainHessian(const T0 &a0, const T1 &a1)
Definition: autodiff_chain_hessian.h:36
Eigen::AutoDiffChainHessian::JacobianType
Matrix< Scalar, ValuesAtCompileTime, JacobianInputsAtCompileTime > JacobianType
Definition: autodiff_chain_hessian.h:56
Eigen::AutoDiffChainHessian::OuterActiveScalar
AutoDiffScalar< OuterDerivativeType > OuterActiveScalar
Definition: autodiff_chain_hessian.h:66
Eigen::AutoDiffChainHessian::InputType
Functor::InputType InputType
Definition: autodiff_chain_hessian.h:45
Eigen::AutoDiffChainHessian::operator()
void operator()(const InputType &x, ValueType &v, JacobianType &jac, const InputJacobianType &ijac) const
Definition: autodiff_chain_hessian.h:131
Eigen::AutoDiffChainHessian::InputsAtCompileTime
@ InputsAtCompileTime
Definition: autodiff_chain_hessian.h:51
Eigen::AutoDiffChainHessian
Definition: autodiff_chain_hessian.h:19
Eigen::AutoDiffChainHessian::OuterDerivativeType
Matrix< InnerActiveScalar, JacobianInputsAtCompileTime, 1 > OuterDerivativeType
Definition: autodiff_chain_hessian.h:65
Eigen::AutoDiffChainHessian::JacobianInputsAtCompileTime
@ JacobianInputsAtCompileTime
Definition: autodiff_chain_hessian.h:53
functor.h
Eigen::AutoDiffChainHessian::Index
JacobianType::Index Index
Definition: autodiff_chain_hessian.h:61
Eigen::AutoDiffChainHessian::Scalar
ValueType::Scalar Scalar
Definition: autodiff_chain_hessian.h:47
Eigen::AutoDiffChainHessian::HessianType
Array< Matrix< Scalar, JacobianInputsAtCompileTime, JacobianInputsAtCompileTime >, ValuesAtCompileTime, 1 > HessianType
Definition: autodiff_chain_hessian.h:59