14 template <
int IN_DIM,
int OUT_DIM>
15 DerivativesCppadJIT<IN_DIM, OUT_DIM>::DerivativesCppadJIT(FUN_TYPE_CG& f,
int inputDim,
int outputDim)
19 outputDim_(outputDim),
23 #ifdef LLVM_VERSION_MAJOR
25 llvmModelLib_(nullptr)
28 update(f, inputDim, outputDim);
31 template <
int IN_DIM,
int OUT_DIM>
32 DerivativesCppadJIT<IN_DIM, OUT_DIM>::DerivativesCppadJIT(
const DerivativesCppadJIT& arg)
33 : DerivativesBase(arg),
34 cgStdFun_(arg.cgStdFun_),
35 inputDim_(arg.inputDim_),
36 outputDim_(arg.outputDim_),
37 compiled_(arg.compiled_),
38 libName_(arg.libName_),
40 #ifdef LLVM_VERSION_MAJOR
42 llvmModelLib_(nullptr)
45 cgCppadFun_ = arg.cgCppadFun_;
50 dynamicLib_ = internal::CGHelpers::loadDynamicLibCppad<double>(libName_);
51 model_ = std::shared_ptr<CppAD::cg::GenericModel<double>>(dynamicLib_->model(libName_));
53 #ifdef LLVM_VERSION_MAJOR 54 else if (arg.llvmModelLib_)
56 throw std::runtime_error(
"DerivativesCppadJIT: cloning of LLVM-JIT libraries is currently not supported.");
57 llvmModelLib_ = arg.llvmModelLib_;
58 model_ = std::shared_ptr<CppAD::cg::GenericModel<double>>(llvmModelLib_->model(libName_));
62 throw std::runtime_error(
"DerivativesCppadJIT: undefined behaviour in copy constructor.");
66 template <
int IN_DIM,
int OUT_DIM>
67 void DerivativesCppadJIT<IN_DIM, OUT_DIM>::update(FUN_TYPE_CG& f,
const size_t inputDim,
const size_t outputDim)
70 outputDim_ = outputDim;
72 if (outputDim_ > 0 && inputDim_ > 0)
77 dynamicLib_ =
nullptr;
82 template <
int IN_DIM,
int OUT_DIM>
83 auto DerivativesCppadJIT<IN_DIM, OUT_DIM>::clone() const -> DerivativesCppadJIT*
85 return new DerivativesCppadJIT<IN_DIM, OUT_DIM>(*this);
88 template <
int IN_DIM,
int OUT_DIM>
89 auto DerivativesCppadJIT<IN_DIM, OUT_DIM>::forwardZero(
const Eigen::VectorXd& x) -> OUT_TYPE_D
93 assert(model_->isForwardZeroAvailable() ==
true);
94 return model_->ForwardZero(x);
98 throw std::runtime_error(
"Error: Compile the library first by calling compileJIT(..)");
102 template <
int IN_DIM,
int OUT_DIM>
103 auto DerivativesCppadJIT<IN_DIM, OUT_DIM>::jacobian(
const Eigen::VectorXd& x) -> JAC_TYPE_D
106 throw std::runtime_error(
"Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
112 assert(model_->isJacobianAvailable() ==
true);
113 jac = model_->Jacobian(x);
114 JAC_TYPE_D out(outputDim_,
x.rows());
115 out = JAC_TYPE_ROW_MAJOR::Map(jac.data(), outputDim_,
x.rows());
119 throw std::runtime_error(
"Error: Compile the library first by calling compileJIT(..)");
122 template <
int IN_DIM,
int OUT_DIM>
123 void DerivativesCppadJIT<IN_DIM, OUT_DIM>::sparseJacobian(
const Eigen::VectorXd& x,
124 Eigen::VectorXd& jac,
125 Eigen::VectorXi& iRow,
126 Eigen::VectorXi& jCol)
129 throw std::runtime_error(
"Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
133 assert(model_->isSparseJacobianAvailable() ==
true);
134 std::vector<double> input(x.data(), x.data() + x.rows() * x.cols());
135 std::vector<double> output;
136 model_->SparseJacobian(input, output, sparsityRowsJacobian_, sparsityColsJacobian_);
137 jac = Eigen::Map<Eigen::VectorXd>(output.data(), output.size(), 1);
138 iRow = sparsityRowsJacobianEigen_;
139 jCol = sparsityColsJacobianEigen_;
142 throw std::runtime_error(
"Error: Compile the library first by calling compileJIT(..)");
145 template <
int IN_DIM,
int OUT_DIM>
146 Eigen::VectorXd DerivativesCppadJIT<IN_DIM, OUT_DIM>::sparseJacobianValues(
const Eigen::VectorXd& x)
149 throw std::runtime_error(
"Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
153 assert(model_->isSparseJacobianAvailable() ==
true);
154 std::vector<double> input(x.data(), x.data() + x.rows() * x.cols());
155 std::vector<double> output;
156 model_->SparseJacobian(input, output, sparsityRowsJacobian_, sparsityColsJacobian_);
157 return Eigen::Map<Eigen::VectorXd>(output.data(), output.size(), 1);
160 throw std::runtime_error(
"Error: Compile the library first by calling compileJIT(..)");
163 template <
int IN_DIM,
int OUT_DIM>
164 auto DerivativesCppadJIT<IN_DIM, OUT_DIM>::hessian(
const Eigen::VectorXd& x,
const Eigen::VectorXd& lambda)
168 throw std::runtime_error(
"Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
172 assert(model_->isHessianAvailable() ==
true);
173 Eigen::VectorXd hessian = model_->Hessian(x, lambda);
174 HES_TYPE_D out(x.rows(), x.rows());
175 out = HES_TYPE_ROW_MAJOR::Map(hessian.data(), x.rows(), x.rows());
180 throw std::runtime_error(
"Error: Compile the library first by calling compileJIT(..)");
184 template <
int IN_DIM,
int OUT_DIM>
185 void DerivativesCppadJIT<IN_DIM, OUT_DIM>::sparseHessian(
const Eigen::VectorXd& x,
186 const Eigen::VectorXd& lambda,
187 Eigen::VectorXd& hes,
188 Eigen::VectorXi& iRow,
189 Eigen::VectorXi& jCol)
192 throw std::runtime_error(
"Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
196 assert(model_->isSparseJacobianAvailable() ==
true);
197 std::vector<double> input(x.data(), x.data() + x.rows() * x.cols());
198 std::vector<double> inputLambda(lambda.data(), lambda.data() + lambda.rows() * lambda.cols());
199 std::vector<double> output;
200 model_->SparseHessian(input, inputLambda, output, sparsityRowsHessian_, sparsityColsHessian_);
201 hes = Eigen::Map<Eigen::VectorXd>(output.data(), output.size(), 1);
202 iRow = sparsityRowsHessianEigen_;
203 jCol = sparsityColsHessianEigen_;
206 throw std::runtime_error(
"Error: Compile the library first by calling compileJIT(..)");
209 template <
int IN_DIM,
int OUT_DIM>
210 Eigen::VectorXd DerivativesCppadJIT<IN_DIM, OUT_DIM>::sparseHessianValues(
const Eigen::VectorXd& x,
211 const Eigen::VectorXd& lambda)
214 throw std::runtime_error(
"Outdim dim smaller 0; Define output dim in DerivativesCppad constructor");
218 assert(model_->isSparseHessianAvailable() ==
true);
219 std::vector<double> input(x.data(), x.data() + x.rows() * x.cols());
220 std::vector<double> inputLambda(lambda.data(), lambda.data() + lambda.rows() * lambda.cols());
221 std::vector<double> output;
222 model_->SparseHessian(input, inputLambda, output, sparsityRowsHessian_, sparsityColsHessian_);
223 return Eigen::Map<Eigen::VectorXd>(output.data(), output.size(), 1);
226 throw std::runtime_error(
"Error: Compile the library first by calling compileJIT(..)");
229 template <
int IN_DIM,
int OUT_DIM>
230 Eigen::Matrix<bool, Eigen::Dynamic, Eigen::Dynamic> DerivativesCppadJIT<IN_DIM, OUT_DIM>::getSparsityPatternJacobian()
232 assert(model_->isJacobianSparsityAvailable() ==
true);
234 std::vector<bool> sparsityVec = model_->JacobianSparsityBool();
235 Eigen::Matrix<bool, Eigen::Dynamic, Eigen::Dynamic> sparsityMat(outputDim_, inputDim_);
237 assert((
int)(sparsityVec.size()) == outputDim_ * inputDim_);
238 for (
int row = 0; row < outputDim_; ++row)
239 for (
int col = 0; col < inputDim_; ++col)
240 sparsityMat(row, col) = sparsityVec[col + row * inputDim_];
245 template <
int IN_DIM,
int OUT_DIM>
246 Eigen::Matrix<bool, Eigen::Dynamic, Eigen::Dynamic> DerivativesCppadJIT<IN_DIM, OUT_DIM>::getSparsityPatternHessian()
248 assert(model_->isHessianSparsityAvailable() ==
true);
250 std::vector<bool> sparsityVec = model_->HessianSparsityBool();
251 Eigen::Matrix<bool, Eigen::Dynamic, Eigen::Dynamic> sparsityMat(inputDim_, inputDim_);
253 assert(sparsityVec.size() == inputDim_ * inputDim_);
254 for (
int row = 0; row < inputDim_; ++row)
255 for (
int col = 0; col < inputDim_; ++col)
257 sparsityMat(row, col) = sparsityVec[col + row * inputDim_];
263 template <
int IN_DIM,
int OUT_DIM>
264 void DerivativesCppadJIT<IN_DIM, OUT_DIM>::getSparsityPatternJacobian(Eigen::VectorXi& rows, Eigen::VectorXi& columns)
266 assert(model_->isJacobianSparsityAvailable() ==
true);
268 rows = sparsityRowsJacobianEigen_;
269 columns = sparsityColsJacobianEigen_;
272 template <
int IN_DIM,
int OUT_DIM>
273 size_t DerivativesCppadJIT<IN_DIM, OUT_DIM>::getNumNonZerosJacobian()
275 assert(model_->isJacobianSparsityAvailable() ==
true);
276 return sparsityRowsJacobian_.size();
279 template <
int IN_DIM,
int OUT_DIM>
280 size_t DerivativesCppadJIT<IN_DIM, OUT_DIM>::getNumNonZerosHessian()
282 assert(model_->isJacobianSparsityAvailable() ==
true);
283 return sparsityRowsHessian_.size();
286 template <
int IN_DIM,
int OUT_DIM>
287 void DerivativesCppadJIT<IN_DIM, OUT_DIM>::getSparsityPatternHessian(Eigen::VectorXi& rows, Eigen::VectorXi& columns)
289 assert(model_->isHessianSparsityAvailable() ==
true);
291 rows = sparsityRowsHessianEigen_;
292 columns = sparsityColsHessianEigen_;
295 template <
int IN_DIM,
int OUT_DIM>
296 void DerivativesCppadJIT<IN_DIM, OUT_DIM>::compileJIT(
const DerivativesCppadSettings& settings,
297 const std::string& libName,
304 clock_gettime(CLOCK_MONOTONIC, &ts);
307 std::string uniqueID =
308 std::to_string(std::hash<std::thread::id>()(std::this_thread::get_id())) +
"_" + std::to_string(ts.tv_nsec);
310 libName_ = libName + uniqueID;
312 CppAD::cg::ModelCSourceGen<double> cgen(cgCppadFun_, libName_);
314 cgen.setMultiThreading(settings.multiThreading_);
315 cgen.setCreateForwardZero(settings.createForwardZero_);
316 cgen.setCreateForwardOne(settings.createForwardOne_);
317 cgen.setCreateReverseOne(settings.createReverseOne_);
318 cgen.setCreateReverseTwo(settings.createReverseTwo_);
319 cgen.setCreateJacobian(settings.createJacobian_);
320 cgen.setCreateSparseJacobian(settings.createSparseJacobian_);
321 cgen.setCreateHessian(settings.createHessian_);
322 cgen.setCreateSparseHessian(settings.createSparseHessian_);
323 cgen.setMaxAssignmentsPerFunc(settings.maxAssignements_);
325 CppAD::cg::ModelLibraryCSourceGen<double> libcgen(cgen);
327 if (settings.useDynamicLibrary_)
329 std::string tempDir =
"cppad_temp" + uniqueID;
332 std::cout <<
"DerivativesCppadJIT: starting to compile dynamic library" << libName_ << std::endl;
333 std::cout <<
"DerivativesCppadJIT: in temporary directory " << tempDir << std::endl;
337 CppAD::cg::DynamicModelLibraryProcessor<double> p(libcgen, libName_);
339 if (settings.compiler_ == DerivativesCppadSettings::GCC)
341 CppAD::cg::GccCompiler<double> compiler;
342 compiler.setTemporaryFolder(tempDir);
343 dynamicLib_ = std::shared_ptr<CppAD::cg::DynamicLib<double>>(p.createDynamicLibrary(compiler));
345 else if (settings.compiler_ == DerivativesCppadSettings::CLANG)
347 CppAD::cg::ClangCompiler<double> compiler;
348 compiler.setTemporaryFolder(tempDir);
349 dynamicLib_ = std::shared_ptr<CppAD::cg::DynamicLib<double>>(p.createDynamicLibrary(compiler));
352 throw std::runtime_error(
"Unknown compiler type for dynamic library, support only gcc and clang.");
355 model_ = std::shared_ptr<CppAD::cg::GenericModel<double>>(dynamicLib_->model(libName_));
361 std::cout <<
"DerivativesCppadJIT: starting to compile with LLVM library " << libName_ << std::endl;
363 #ifdef LLVM_VERSION_MAJOR 365 CppAD::cg::LlvmModelLibraryProcessor<double> p(libcgen);
366 llvmModelLib_ = p.create();
369 model_ = std::shared_ptr<CppAD::cg::GenericModel<double>>(llvmModelLib_->model(libName_));
371 throw std::runtime_error(
"DerivativesCppadJIT: LLVM not installed.");
376 if (settings.generateSourceCode_)
380 std::cout <<
"DerivativesCppadJIT: generating source-code... " << libName_ << std::endl;
382 CppAD::cg::SaveFilesModelLibraryProcessor<double> p2(libcgen);
388 if (model_->isJacobianSparsityAvailable())
391 std::cout <<
"DerivativesCppadJIT: updating Jacobian sparsity pattern" << std::endl;
393 model_->JacobianSparsity(sparsityRowsJacobian_, sparsityColsJacobian_);
394 sparsityRowsJacobianEigen_.resize(sparsityRowsJacobian_.size());
395 sparsityColsJacobianEigen_.resize(sparsityColsJacobian_.size());
397 Eigen::Matrix<size_t, Eigen::Dynamic, 1> rowsSizeT;
398 rowsSizeT.resize(sparsityRowsJacobian_.size());
399 Eigen::Matrix<size_t, Eigen::Dynamic, 1> colsSizeT;
400 colsSizeT.resize(sparsityColsJacobian_.size());
402 rowsSizeT = Eigen::Map<Eigen::Matrix<size_t, Eigen::Dynamic, 1>>(
403 sparsityRowsJacobian_.data(), sparsityRowsJacobian_.size(), 1);
404 colsSizeT = Eigen::Map<Eigen::Matrix<size_t, Eigen::Dynamic, 1>>(
405 sparsityColsJacobian_.data(), sparsityColsJacobian_.size(), 1);
407 sparsityRowsJacobianEigen_ = rowsSizeT.cast<
int>();
408 sparsityColsJacobianEigen_ = colsSizeT.cast<
int>();
411 if (model_->isHessianSparsityAvailable())
414 std::cout <<
"DerivativesCppadJIT: updating Hessian sparsity pattern" << std::endl;
416 model_->HessianSparsity(sparsityRowsHessian_, sparsityColsHessian_);
417 sparsityRowsHessianEigen_.resize(sparsityRowsHessian_.size());
418 sparsityColsHessianEigen_.resize(sparsityColsHessian_.size());
420 Eigen::Matrix<size_t, Eigen::Dynamic, 1> rowsSizeT;
421 rowsSizeT.resize(sparsityRowsHessian_.size());
422 Eigen::Matrix<size_t, Eigen::Dynamic, 1> colsSizeT;
423 colsSizeT.resize(sparsityColsHessian_.size());
425 rowsSizeT = Eigen::Map<Eigen::Matrix<size_t, Eigen::Dynamic, 1>>(
426 sparsityRowsHessian_.data(), sparsityRowsHessian_.size(), 1);
427 colsSizeT = Eigen::Map<Eigen::Matrix<size_t, Eigen::Dynamic, 1>>(
428 sparsityColsHessian_.data(), sparsityColsHessian_.size(), 1);
430 sparsityRowsHessianEigen_ = rowsSizeT.cast<
int>();
431 sparsityColsHessianEigen_ = colsSizeT.cast<
int>();
435 std::cout <<
"DerivativesCppadJIT: compileJIT() completed." << std::endl;
438 template <
int IN_DIM,
int OUT_DIM>
439 auto DerivativesCppadJIT<IN_DIM, OUT_DIM>::getDynamicLib() ->
const std::shared_ptr<CppAD::cg::DynamicLib<double>>
444 throw std::runtime_error(
"DerivativesCppADJIT: dynamic lib not compiled.");
447 #ifdef LLVM_VERSION_MAJOR 448 template <
int IN_DIM,
int OUT_DIM>
449 auto DerivativesCppadJIT<IN_DIM, OUT_DIM>::getLlvmLib() ->
const std::shared_ptr<CppAD::cg::LlvmModelLibrary<double>>
452 return llvmModelLib_;
454 throw std::runtime_error(
"DerivativesCppADJIT: llvm library not available.");
458 template <
int IN_DIM,
int OUT_DIM>
459 void DerivativesCppadJIT<IN_DIM, OUT_DIM>::recordCg()
462 Eigen::Matrix<CG_SCALAR, Eigen::Dynamic, 1> x(inputDim_);
465 CppAD::Independent(x);
468 Eigen::Matrix<CG_SCALAR, Eigen::Dynamic, 1> y(outputDim_);
473 CppAD::ADFun<CG_VALUE_TYPE> fCodeGen(x, y);
477 cgCppadFun_ = fCodeGen;
ct::core::StateVector< state_dim > x
const bool verbose
Definition: JacobianCGTest.h:19