- 3.0.2 core module.
JacobianCGTest.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 **********************************************************************************************************************/
14 #pragma once
15 
16 // define the input and output sizes of the function
17 const size_t inDim = 3;
18 const size_t outDim = 2;
19 const bool verbose = false;
20 
22 typedef DerivativesCppadJIT<inDim, outDim> derivativesCppadJIT;
23 typedef DerivativesCppadCG<inDim, outDim> derivativesCppadCG;
24 typedef DerivativesCppad<inDim, outDim> derivativesCppad;
25 
32 template <typename SCALAR>
33 Eigen::Matrix<SCALAR, outDim, 1> testFunction(const Eigen::Matrix<SCALAR, inDim, 1>& x)
34 {
35  Eigen::Matrix<SCALAR, outDim, 1> y;
36 
37  y(0) = 3 * x(0) + 2 * x(0) * x(0) - x(1) * x(2);
38  y(1) = x(2) + x(1) + 3;
39 
40  return y;
41 }
42 
49 template <typename SCALAR>
50 Eigen::Matrix<SCALAR, outDim, inDim> jacobianCheck(const Eigen::Matrix<SCALAR, inDim, 1>& x)
51 {
52  Eigen::Matrix<SCALAR, outDim, inDim> jac;
53 
54  jac << 3 + 4 * x(0), -x(2), -x(1), 0, 1, 1;
55 
56  return jac;
57 }
58 
59 template <typename SCALAR>
60 Eigen::Matrix<SCALAR, inDim, inDim> hessianCheck(const Eigen::Matrix<SCALAR, inDim, 1>& x,
61  const Eigen::Matrix<SCALAR, outDim, 1>& w)
62 {
63  Eigen::Matrix<SCALAR, inDim, inDim> hes;
64 
65  hes << 4, 0, 0, 0, 0, -1, 0, -1, 0;
66 
67  return w(0) * hes;
68 }
69 
70 
71 void executeForwardZeroTest(const bool useDynamicLib)
72 {
73  // create a function handle (also works for class methods, lambdas, function pointers, ...)
74  typename derivativesCppadJIT::FUN_TYPE_CG f_cg = testFunction<derivativesCppadJIT::CG_SCALAR>;
75  typename derivativesCppad::FUN_TYPE_AD f_ad = testFunction<derivativesCppad::AD_SCALAR>;
76 
77  // initialize the Auto-Diff Codegen Jacobian
78  derivativesCppadJIT jacCG(f_cg);
79  derivativesCppad jacAd(f_ad);
80 
81  DerivativesCppadSettings settings;
82  settings.createForwardZero_ = true;
83  settings.createJacobian_ = true;
84  settings.useDynamicLibrary_ = useDynamicLib;
85 
86  // create a random double vector
87  Eigen::VectorXd someVec(inDim);
88  someVec.setRandom();
89 
90  // test evaluation of forward zero before compilation
91  Eigen::VectorXd vecOut = jacAd.forwardZero(someVec);
92 
93  // compile the Jacobian
94  jacCG.compileJIT(settings, "forwardZeroTestLib", verbose);
95 
96  // test evaluation of forward zero after compilation
97  Eigen::VectorXd vecOut2 = jacCG.forwardZero(someVec);
98 
99  // verify the outputs
100  ASSERT_LT((vecOut - vecOut2).array().abs().maxCoeff(), 1e-10);
101 }
102 
103 
104 void executeJITCompilationTest(bool useDynamicLib)
105 {
106  // create a function handle (also works for class methods, lambdas, function pointers, ...)
107  typename derivativesCppadJIT::FUN_TYPE_CG f = testFunction<derivativesCppadJIT::CG_SCALAR>;
108  typename derivativesCppad::FUN_TYPE_AD f_ad = testFunction<derivativesCppad::AD_SCALAR>;
109 
110  // initialize the Auto-Diff Codegen Jacobian
111  derivativesCppadJIT jacCG(f);
112  derivativesCppad jacAd(f_ad);
113 
114  DerivativesCppadSettings settings;
115  settings.createJacobian_ = true;
116  settings.useDynamicLibrary_ = useDynamicLib;
117 
118  // compile the Jacobian
119  jacCG.compileJIT(settings, "jacobianCGLib", verbose);
120 
121  // create an input vector
122  Eigen::Matrix<double, inDim, 1> x;
123 
124  for (size_t i = 0; i < 1000; i++)
125  {
126  // create a random input
127  x.setRandom();
128 
129  // verify agains the analytical Jacobian
130  ASSERT_LT((jacCG.jacobian(x) - jacobianCheck(x)).array().abs().maxCoeff(), 1e-10);
131  ASSERT_LT((jacAd.jacobian(x) - jacobianCheck(x)).array().abs().maxCoeff(), 1e-10);
132  ASSERT_LT((jacCG.jacobian(x) - jacAd.jacobian(x)).array().abs().maxCoeff(), 1e-10);
133  }
134 }
135 
136 
137 void executeJitHessianTest(bool useDynamicLib)
138 {
139  typename derivativesCppadJIT::FUN_TYPE_CG f = testFunction<derivativesCppadJIT::CG_SCALAR>;
140  typename derivativesCppad::FUN_TYPE_AD f_ad = testFunction<derivativesCppad::AD_SCALAR>;
141 
142  derivativesCppadJIT hessianCg(f);
143  derivativesCppad hessianAd(f_ad);
144 
145  DerivativesCppadSettings settings;
146  settings.createHessian_ = true;
147  settings.useDynamicLibrary_ = useDynamicLib;
148 
149  hessianCg.compileJIT(settings, "hessianCGLib", verbose);
150 
151  Eigen::Matrix<double, inDim, 1> x;
152  Eigen::Matrix<double, outDim, 1> w;
153 
154  for (size_t i = 0; i < 1000; ++i)
155  {
156  x.setRandom();
157  w.setRandom();
158 
159  ASSERT_LT((hessianCg.hessian(x, w) - hessianCheck(x, w)).array().abs().maxCoeff(), 1e-10);
160  ASSERT_LT((hessianAd.hessian(x, w) - hessianCheck(x, w)).array().abs().maxCoeff(), 1e-10);
161  ASSERT_LT((hessianCg.hessian(x, w) - hessianAd.hessian(x, w)).array().abs().maxCoeff(), 1e-10);
162  }
163 }
164 
165 
166 void executeJITCloneTest(bool useDynamicLib)
167 {
168  typename derivativesCppadJIT::FUN_TYPE_CG f = testFunction<derivativesCppadJIT::CG_SCALAR>;
169  typename derivativesCppad::FUN_TYPE_AD f_ad = testFunction<derivativesCppad::AD_SCALAR>;
170 
171  // initialize the Auto-Diff Codegen Jacobian
172  std::shared_ptr<derivativesCppadJIT> jacCG(new derivativesCppadJIT(f));
173  std::shared_ptr<derivativesCppad> jacAd(new derivativesCppad(f_ad));
174 
175  DerivativesCppadSettings settings;
176  settings.createJacobian_ = true;
177  settings.useDynamicLibrary_ = useDynamicLib;
178 
179  // compile the Jacobian
180  jacCG->compileJIT(settings, "jacobianCGLib", verbose);
181 
182  // create an input vector
183  Eigen::Matrix<double, inDim, 1> x;
184 
185  std::shared_ptr<derivativesCppadJIT> jacCG_cloned(jacCG->clone());
186 
187  // make sure the underlying dynamic libraries are not identical
188  if (useDynamicLib && (jacCG_cloned->getDynamicLib() == jacCG->getDynamicLib()))
189  {
190  std::cout << "FATAL ERROR: dynamic library not cloned correctly in JIT." << std::endl;
191  ASSERT_TRUE(false);
192  }
193 #ifdef LLVM
194  if (!useDynamicLib && (jacCG_cloned->getLlvmLib() == jacCG->getLlvmLib()))
195  {
196  std::cout << "FATAL ERROR: Llvm library not cloned correctly in JIT." << std::endl;
197  ASSERT_TRUE(false);
198  }
199 #endif
200 
201  for (size_t i = 0; i < 100; i++)
202  {
203  // create a random input
204  x.setRandom();
205 
206  // verify agains the analytical Jacobian
207  ASSERT_LT((jacCG_cloned->jacobian(x) - jacobianCheck(x)).array().abs().maxCoeff(), 1e-10);
208  ASSERT_LT((jacCG_cloned->jacobian(x) - jacAd->jacobian(x)).array().abs().maxCoeff(), 1e-10);
209  }
210 }
211 
215 TEST(JacobianCGTest, ForwardZeroTest)
216 {
217  try
218  {
219  executeForwardZeroTest(true); // using dynamic library
220 #ifdef LLVM
221  executeForwardZeroTest(false); //using llvm jit
222 #endif
223 
224  } catch (std::exception& e)
225  {
226  std::cout << "Exception thrown: " << e.what() << std::endl;
227  ASSERT_TRUE(false);
228  }
229 }
230 
234 TEST(JacobianCGTest, JITCompilationTest)
235 {
236  try
237  {
238  executeJITCompilationTest(true); // using dynamic library
239 #ifdef LLVM
240  executeJITCompilationTest(false); //using llvm jit
241 #endif
242 
243  } catch (std::exception& e)
244  {
245  std::cout << "Exception thrown: " << e.what() << std::endl;
246  ASSERT_TRUE(false);
247  }
248 }
249 
250 TEST(HessianCGTest, JITHessianTest)
251 {
252  try
253  {
254  executeJitHessianTest(true); // using dynamic library
255 #ifdef LLVM
256  executeJitHessianTest(false); //using llvm jit
257 #endif
258  } catch (std::exception& e)
259  {
260  std::cout << "Exception thrown: " << e.what() << std::endl;
261  ASSERT_TRUE(false);
262  }
263 }
264 
268 TEST(JacobianCGTest, DISABLED_LlvmCloneTest)
269 {
270  try
271  {
272  executeJITCloneTest(false); // Jit using llvm in-memory library
273  } catch (std::exception& e)
274  {
275  std::cout << "Exception thrown: " << e.what() << std::endl;
276  ASSERT_TRUE(false);
277  }
278 }
279 
283 TEST(JacobianCGTest, JitCloneTest)
284 {
285  try
286  {
287  executeJITCloneTest(true); // Jit using dynamic library
288  } catch (std::exception& e)
289  {
290  std::cout << "Exception thrown: " << e.what() << std::endl;
291  ASSERT_TRUE(false);
292  }
293 }
294 
295 
296 // /*!
297 // * Test for writing the codegenerated Jacobian to file
298 // */
299 TEST(JacobianCGTest, CodegenTest)
300 {
301  // create a function handle (also works for class methods, lambdas, function pointers, ...)
302  typename derivativesCppadCG::FUN_TYPE_CG f = testFunction<derivativesCppadCG::CG_SCALAR>;
303 
304  // initialize the Auto-Diff Codegen Jacobian
305  derivativesCppadCG jacCG(f);
306 
307  // generate code for the Jacobian, similar to jacobianCheck()
308  jacCG.generateJacobianSource("TestJacobian");
309 
310  // generate code for the actual function, will evaluate to the same as testFunction()
311  jacCG.generateForwardZeroSource("TestForwardZero");
312 
313  jacCG.generateHessianSource("TestHessian");
314 }
void executeForwardZeroTest(const bool useDynamicLib)
Definition: JacobianCGTest.h:71
void executeJITCompilationTest(bool useDynamicLib)
Definition: JacobianCGTest.h:104
TEST(JacobianCGTest, ForwardZeroTest)
Definition: JacobianCGTest.h:215
Eigen::Matrix< SCALAR, outDim, 1 > testFunction(const Eigen::Matrix< SCALAR, inDim, 1 > &x)
Definition: JacobianCGTest.h:33
const size_t outDim
dimension of y
Definition: JacobianCGTest.h:18
void executeJITCloneTest(bool useDynamicLib)
Definition: JacobianCGTest.h:166
DerivativesCppadCG< inDim, outDim > derivativesCppadCG
Definition: JacobianCGTest.h:23
DerivativesCppad< inDim, outDim > derivativesCppad
Definition: JacobianCGTest.h:24
void executeJitHessianTest(bool useDynamicLib)
Definition: JacobianCGTest.h:137
DerivativesCppadJIT< inDim, outDim > derivativesCppadJIT
the Jacobian codegen class
Definition: JacobianCGTest.h:22
for i
ct::core::StateVector< state_dim > x
const size_t inDim
dimension of x
Definition: JacobianCGTest.h:17
const bool verbose
Definition: JacobianCGTest.h:19
Eigen::Matrix< SCALAR, inDim, inDim > hessianCheck(const Eigen::Matrix< SCALAR, inDim, 1 > &x, const Eigen::Matrix< SCALAR, outDim, 1 > &w)
Definition: JacobianCGTest.h:60
Eigen::Matrix< SCALAR, outDim, inDim > jacobianCheck(const Eigen::Matrix< SCALAR, inDim, 1 > &x)
Definition: JacobianCGTest.h:50