- 3.0.2 core module.
DerivativesCppad.h
Go to the documentation of this file.
1 /**********************************************************************************************************************
2 This file is part of the Control Toolbox (https://github.com/ethz-adrl/control-toolbox), copyright by ETH Zurich.
3 Licensed under the BSD-2 license (see LICENSE file in main directory)
4 **********************************************************************************************************************/
5 
6 #pragma once
7 
9 
10 namespace ct {
11 namespace core {
12 
13 #ifdef CPPAD
14 
16 
29 template <int IN_DIM, int OUT_DIM>
30 class DerivativesCppad : public Derivatives<IN_DIM, OUT_DIM, double> // double on purpose!
31 {
32 public:
33  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
34 
35  typedef ADScalar AD_SCALAR;
36 
37  typedef Eigen::Matrix<AD_SCALAR, IN_DIM, 1> IN_TYPE_AD;
38  typedef Eigen::Matrix<AD_SCALAR, OUT_DIM, 1> OUT_TYPE_AD;
39 
40  typedef Eigen::Matrix<double, IN_DIM, 1> IN_TYPE_D;
41  typedef Eigen::Matrix<double, OUT_DIM, 1> OUT_TYPE_D;
42  typedef Eigen::Matrix<double, OUT_DIM, IN_DIM> JAC_TYPE_D;
43  typedef Eigen::Matrix<double, OUT_DIM, IN_DIM, Eigen::RowMajor>
44  JAC_TYPE_ROW_MAJOR;
45  typedef Eigen::Matrix<double, IN_DIM, IN_DIM> HES_TYPE_D;
46  typedef Eigen::Matrix<double, IN_DIM, IN_DIM, Eigen::RowMajor> HES_TYPE_ROW_MAJOR;
47 
48  typedef std::function<OUT_TYPE_AD(const IN_TYPE_AD&)> FUN_TYPE_AD;
49 
50  typedef Derivatives<IN_DIM, OUT_DIM> DerivativesBase;
51 
52 
66  DerivativesCppad(FUN_TYPE_AD& f, int inputDim = IN_DIM, int outputDim = OUT_DIM)
67  : DerivativesBase(), adStdFun_(f), inputDim_(inputDim), outputDim_(outputDim)
68  {
69  update(f, inputDim, outputDim);
70  }
71 
73  DerivativesCppad(const DerivativesCppad& arg)
74  : DerivativesBase(arg), adStdFun_(arg.adStdFun_), inputDim_(arg.inputDim_), outputDim_(arg.outputDim_)
75  {
76  adCppadFun_ = arg.adCppadFun_;
77  }
78 
79 
81 
89  void update(FUN_TYPE_AD& f, const size_t inputDim = IN_DIM, const size_t outputDim = OUT_DIM)
90  {
91  adStdFun_ = f;
92  outputDim_ = outputDim;
93  inputDim_ = inputDim;
94  if (outputDim_ > 0 && inputDim_ > 0)
95  recordAd();
96  }
97 
99  virtual ~DerivativesCppad() {}
101  DerivativesCppad* clone() const { return new DerivativesCppad<IN_DIM, OUT_DIM>(*this); }
102  virtual OUT_TYPE_D forwardZero(const Eigen::VectorXd& x) { return adCppadFun_.Forward(0, x); }
103  virtual JAC_TYPE_D jacobian(const Eigen::VectorXd& x)
104  {
105  if (outputDim_ <= 0)
106  throw std::runtime_error("Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
107 
108 
109  Eigen::VectorXd jac = adCppadFun_.Jacobian(x);
110 
111  JAC_TYPE_D out(outputDim_, x.rows());
112  out = JAC_TYPE_ROW_MAJOR::Map(jac.data(), outputDim_, x.rows());
113  return out;
114  }
115 
116  virtual void sparseJacobian(const Eigen::VectorXd& x,
117  Eigen::VectorXd& jac,
118  Eigen::VectorXi& iRow,
119  Eigen::VectorXi& jCol)
120  {
121  if (outputDim_ <= 0)
122  throw std::runtime_error("Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
123 
124  jac = adCppadFun_.SparseJacobian(x);
125  }
126 
127  virtual Eigen::VectorXd sparseJacobianValues(const Eigen::VectorXd& x)
128  {
129  if (outputDim_ <= 0)
130  throw std::runtime_error("Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
131 
132  return adCppadFun_.SparseJacobian(x);
133  }
134 
135 
136  virtual HES_TYPE_D hessian(const Eigen::VectorXd& x, const Eigen::VectorXd& lambda)
137  {
138  if (outputDim_ <= 0)
139  throw std::runtime_error("Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
140 
141  Eigen::VectorXd hessian = adCppadFun_.Hessian(x, lambda);
142  HES_TYPE_D out(x.rows(), x.rows());
143  out = HES_TYPE_ROW_MAJOR::Map(hessian.data(), x.rows(), x.rows());
144  return out;
145  }
146 
147  virtual void sparseHessian(const Eigen::VectorXd& x,
148  const Eigen::VectorXd& lambda,
149  Eigen::VectorXd& hes,
150  Eigen::VectorXi& iRow,
151  Eigen::VectorXi& jCol)
152  {
153  if (outputDim_ <= 0)
154  throw std::runtime_error("Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
155 
156  hes = adCppadFun_.SparseHessian(x, lambda);
157  }
158 
159 
160  virtual Eigen::VectorXd sparseHessianValues(const Eigen::VectorXd& x, const Eigen::VectorXd& lambda)
161  {
162  if (outputDim_ <= 0)
163  throw std::runtime_error("Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
164 
165  return adCppadFun_.SparseHessian(x, lambda);
166  }
167 
168 private:
172  void recordAd()
173  {
174  // input vector, needs to be dynamic size
175  Eigen::Matrix<AD_SCALAR, Eigen::Dynamic, 1> x(inputDim_);
176 
177  // declare x as independent
178  CppAD::Independent(x);
179 
180  // output vector, needs to be dynamic size
181  Eigen::Matrix<AD_SCALAR, Eigen::Dynamic, 1> y(outputDim_);
182 
183  y = adStdFun_(x);
184 
185  // store operation sequence in f: x -> y and stop recording
186  CppAD::ADFun<double> fAd(x, y);
187 
188  fAd.optimize();
189 
190  std::cout << "AD FUn recorded" << std::endl;
191 
192  adCppadFun_ = fAd;
193  }
194 
195  std::function<OUT_TYPE_AD(const IN_TYPE_AD&)> adStdFun_;
196 
197  int inputDim_;
198  int outputDim_;
199 
200  CppAD::ADFun<double> adCppadFun_;
201 };
202 
203 #endif
204 
205 } /* namespace core */
206 } /* namespace ct */