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  {
158  eigen_assert(InputsAtCompileTime == JacobianInputsAtCompileTime);
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_
void operator()(const InputType &x, ValueType &v, JacobianType &jac=0, HessianType &hess, const InputJacobianType *_ijac=0, const InputHessianType *_ihess=0) const
Array< Matrix< Scalar, JacobianInputsAtCompileTime, JacobianInputsAtCompileTime >, ValuesAtCompileTime, 1 > HessianType
void operator()(const InputType &x, ValueType &v, JacobianType &jac, HessianType &hess) const
Matrix< Scalar, ValuesAtCompileTime, JacobianInputsAtCompileTime > JacobianType
Matrix< Scalar, JacobianInputsAtCompileTime, 1 > InnerDerivativeType
AutoDiffChainHessian(const T0 &a0, const T1 &a1, const T2 &a2)
FunctorBase< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic > Functor
Definition: functor.h:49
AutoDiffScalar< InnerDerivativeType > InnerActiveScalar
Array< Matrix< Scalar, JacobianInputsAtCompileTime, JacobianInputsAtCompileTime >, InputsAtCompileTime, 1 > InputHessianType
AutoDiffScalar< OuterDerivativeType > OuterActiveScalar
AutoDiffChainHessian(const T0 &a0, const T1 &a1)
Matrix< Scalar, InputsAtCompileTime, JacobianInputsAtCompileTime > InputJacobianType
Matrix< InnerActiveScalar, JacobianInputsAtCompileTime, 1 > OuterDerivativeType
Matrix< OuterActiveScalar, InputsAtCompileTime, 1 > ActiveInput
void operator()(const InputType &x, ValueType &v, JacobianType &jac, const InputJacobianType &ijac) const
Matrix< OuterActiveScalar, ValuesAtCompileTime, 1 > ActiveValue
EIGEN_STRONG_INLINE void operator()(const InputType &x, ValueType &v) const
void operator()(const InputType &x, ValueType &v, JacobianType &jac) const
double x
void operator()(const InputType &x, ValueType &v, JacobianType &jac, HessianType &hess, const InputJacobianType &ijac, const InputHessianType &ihess) const


exotica_core
Author(s): Yiming Yang, Michael Camilleri
autogenerated on Sat Apr 10 2021 02:34:49