CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
functor_generic_model.hpp
1#ifndef CPPAD_CG_FUNCTOR_GENERIC_MODEL_INCLUDED
2#define CPPAD_CG_FUNCTOR_GENERIC_MODEL_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2012 Ciengis
6 * Copyright (C) 2018 Joao Leal
7 *
8 * CppADCodeGen is distributed under multiple licenses:
9 *
10 * - Eclipse Public License Version 1.0 (EPL1), and
11 * - GNU General Public License Version 3 (GPL3).
12 *
13 * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
14 * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
15 * ----------------------------------------------------------------------------
16 * Author: Joao Leal
17 */
18
19#include <typeinfo>
20
21namespace CppAD {
22namespace cg {
23
33template<class Base>
34class FunctorGenericModel : public GenericModel<Base> {
35protected:
36 static constexpr const char* ERROR_LIBRARY_NOT_READY = "The model library is not ready. The model library that"
37 " provided this model might have been closed or deleted.";
38protected:
39 bool _isLibraryReady;
41 const std::string _name;
42 size_t _m;
43 size_t _n;
44 std::vector<const Base*> _in;
45 std::vector<const Base*> _inHess;
46 std::vector<Base*> _out;
47 LangCAtomicFun _atomicFuncArg;
48 std::vector<std::string> _atomicNames; // names of the atomic/external functions required by this model
49 std::vector<ExternalFunctionWrapper<Base>* > _atomic;
50 size_t _missingAtomicFunctions;
51 CppAD::vector<Base> _tx, _ty, _px, _py;
52 // original model function
53 void (*_zero)(Base const*const*, Base * const*, LangCAtomicFun);
54 // first order forward mode
55 int (*_forwardOne)(Base const tx[], Base ty[], LangCAtomicFun);
56 // first order reverse mode
57 int (*_reverseOne)(Base const tx[], Base const ty[], Base px[], Base const py[], LangCAtomicFun);
58 // second order reverse mode
59 int (*_reverseTwo)(Base const tx[], Base const ty[], Base px[], Base const py[], LangCAtomicFun);
60 // jacobian function in the dynamic library
61 void (*_jacobian)(Base const*const*, Base * const*, LangCAtomicFun);
62 // hessian function in the dynamic library
63 void (*_hessian)(Base const*const*, Base * const*, LangCAtomicFun);
64 //
65 int (*_sparseForwardOne)(unsigned long, Base const *const *, Base * const *, LangCAtomicFun);
66 //
67 int (*_sparseReverseOne)(unsigned long, Base const *const *, Base * const *, LangCAtomicFun);
68 //
69 int (*_sparseReverseTwo)(unsigned long, Base const *const *, Base * const *, LangCAtomicFun);
70 // sparse jacobian function in the dynamic library
71 void (*_sparseJacobian)(Base const*const*, Base * const*, LangCAtomicFun);
72 // sparse hessian function in the dynamic library
73 void (*_sparseHessian)(Base const*const*, Base * const*, LangCAtomicFun);
74 //
75 void (*_forwardOneSparsity)(unsigned long, unsigned long const**, unsigned long*);
76 //
77 void (*_reverseOneSparsity)(unsigned long, unsigned long const**, unsigned long*);
78 //
79 void (*_reverseTwoSparsity)(unsigned long, unsigned long const**, unsigned long*);
80 // jacobian sparsity function in the dynamic library
81 void (*_jacobianSparsity)(unsigned long const** row,
82 unsigned long const** col,
83 unsigned long * nnz);
84 // hessian sparsity function in the dynamic library
85 void (*_hessianSparsity)(unsigned long const** row,
86 unsigned long const** col,
87 unsigned long * nnz);
88 void (*_hessianSparsity2)(unsigned long i,
89 unsigned long const** row,
90 unsigned long const** col,
91 unsigned long * nnz);
92 void (*_atomicFunctions)(const char*** names,
93 unsigned long * n);
94
95public:
96
98 FunctorGenericModel& operator=(const FunctorGenericModel&) = delete;
99
100 virtual ~FunctorGenericModel() {
101 for (size_t i = 0; i < _atomic.size(); i++) {
102 delete _atomic[i];
103 }
104 }
105
106 const std::string& getName() const override {
107 return _name;
108 }
109
110 const std::vector<std::string>& getAtomicFunctionNames() override {
111 return _atomicNames;
112 }
113
114 bool addAtomicFunction(atomic_base<Base>& atomic) override {
115 return addExternalFunction<atomic_base<Base>, AtomicExternalFunctionWrapper<Base> >
116 (atomic, atomic.atomic_name());
117 }
118
119 bool addExternalModel(GenericModel<Base>& atomic) override {
120 return addExternalFunction<GenericModel<Base>, GenericModelExternalFunctionWrapper<Base> >
121 (atomic, atomic.getName());
122 }
123
124 // Jacobian sparsity
126 return _jacobianSparsity != nullptr;
127 }
128
129 std::vector<bool> JacobianSparsityBool() override {
130 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
131 CPPADCG_ASSERT_KNOWN(_jacobianSparsity != nullptr, "No Jacobian sparsity function defined in the dynamic library")
132
133 unsigned long const* row, *col;
134 unsigned long nnz;
135 (*_jacobianSparsity)(&row, &col, &nnz);
136
137 bool set_type = true;
138 std::vector<bool> s;
139
140 loadSparsity(set_type, s, _m, _n, row, col, nnz);
141
142 return s;
143 }
144
145 std::vector<std::set<size_t> > JacobianSparsitySet() override {
146 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
147 CPPADCG_ASSERT_KNOWN(_jacobianSparsity != nullptr, "No Jacobian sparsity function defined in the dynamic library")
148
149 unsigned long const* row, *col;
150 unsigned long nnz;
151 (*_jacobianSparsity)(&row, &col, &nnz);
152
153 std::set<size_t> set_type;
154 std::vector<std::set<size_t> > s;
155
156 loadSparsity(set_type, s, _m, _n, row, col, nnz);
157
158 return s;
159 }
160
161 void JacobianSparsity(std::vector<size_t>& equations,
162 std::vector<size_t>& variables) override {
163 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
164 CPPADCG_ASSERT_KNOWN(_jacobianSparsity != nullptr, "No Jacobian sparsity function defined in the dynamic library")
165
166 unsigned long const* row, *col;
167 unsigned long nnz;
168 (*_jacobianSparsity)(&row, &col, &nnz);
169
170 equations.resize(nnz);
171 variables.resize(nnz);
172
173 std::copy(row, row + nnz, equations.begin());
174 std::copy(col, col + nnz, variables.begin());
175 }
176
177 // Hessian sparsity
179 return _hessianSparsity != nullptr;
180 }
181
182 std::vector<bool> HessianSparsityBool() override {
183 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
184 CPPADCG_ASSERT_KNOWN(_hessianSparsity != nullptr, "No Hessian sparsity function defined in the dynamic library")
185
186 unsigned long const* row, *col;
187 unsigned long nnz;
188 (*_hessianSparsity)(&row, &col, &nnz);
189
190 bool set_type = true;
191 std::vector<bool> s;
192
193 loadSparsity(set_type, s, _n, _n, row, col, nnz);
194
195 return s;
196 }
197
198 std::vector<std::set<size_t> > HessianSparsitySet() override {
199 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
200 CPPADCG_ASSERT_KNOWN(_hessianSparsity != nullptr, "No Hessian sparsity function defined in the dynamic library")
201
202 unsigned long const* row, *col;
203 unsigned long nnz;
204 (*_hessianSparsity)(&row, &col, &nnz);
205
206 std::set<size_t> set_type;
207 std::vector<std::set<size_t> > s;
208
209 loadSparsity(set_type, s, _n, _n, row, col, nnz);
210
211 return s;
212 }
213
214 void HessianSparsity(std::vector<size_t>& rows,
215 std::vector<size_t>& cols) override {
216 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
217 CPPADCG_ASSERT_KNOWN(_hessianSparsity != nullptr, "No Hessian sparsity function defined in the dynamic library")
218
219 unsigned long const* row, *col;
220 unsigned long nnz;
221 (*_hessianSparsity)(&row, &col, &nnz);
222
223 rows.resize(nnz);
224 cols.resize(nnz);
225
226 std::copy(row, row + nnz, rows.begin());
227 std::copy(col, col + nnz, cols.begin());
228 }
229
231 return _hessianSparsity2 != nullptr;
232 }
233
234 std::vector<bool> HessianSparsityBool(size_t i) override {
235 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
236 CPPADCG_ASSERT_KNOWN(_hessianSparsity2 != nullptr, "No Hessian sparsity function defined in the dynamic library")
237
238 unsigned long const* row, *col;
239 unsigned long nnz;
240 (*_hessianSparsity2)(i, &row, &col, &nnz);
241
242 bool set_type = true;
243 std::vector<bool> s;
244
245 loadSparsity(set_type, s, _n, _n, row, col, nnz);
246
247 return s;
248 }
249
250 std::vector<std::set<size_t> > HessianSparsitySet(size_t i) override {
251 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
252 CPPADCG_ASSERT_KNOWN(_hessianSparsity2 != nullptr, "No Hessian sparsity function defined in the dynamic library")
253
254 unsigned long const* row, *col;
255 unsigned long nnz;
256 (*_hessianSparsity2)(i, &row, &col, &nnz);
257
258 std::set<size_t> set_type;
259 std::vector<std::set<size_t> > s;
260
261 loadSparsity(set_type, s, _n, _n, row, col, nnz);
262
263 return s;
264 }
265
266 void HessianSparsity(size_t i, std::vector<size_t>& rows,
267 std::vector<size_t>& cols) override {
268 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
269 CPPADCG_ASSERT_KNOWN(_hessianSparsity2 != nullptr, "No Hessian sparsity function defined in the dynamic library")
270
271 unsigned long const* row, *col;
272 unsigned long nnz;
273 (*_hessianSparsity2)(i, &row, &col, &nnz);
274
275 rows.resize(nnz);
276 cols.resize(nnz);
277
278 std::copy(row, row + nnz, rows.begin());
279 std::copy(col, col + nnz, cols.begin());
280 }
281
283
284 size_t Domain() const override {
285 return _n;
286 }
287
289
290 size_t Range() const override {
291 return _m;
292 }
293
294 bool isForwardZeroAvailable() override {
295 return _zero != nullptr;
296 }
297
300 ArrayView<Base> dep) override {
301 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
302 CPPADCG_ASSERT_KNOWN(_zero != nullptr, "No zero order forward function defined in the dynamic library")
303 CPPADCG_ASSERT_KNOWN(_in.size() == 1, "The number of independent variable arrays is higher than 1,"
304 " please use the variable size methods")
305 CPPADCG_ASSERT_KNOWN(dep.size() == _m, "Invalid dependent array size")
306 CPPADCG_ASSERT_KNOWN(x.size() == _n, "Invalid independent array size")
307 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
308
309 _in[0] = x.data();
310 _out[0] = dep.data();
311
312 (*_zero)(&_in[0], &_out[0], _atomicFuncArg);
313 }
314
315 void ForwardZero(const std::vector<const Base*> &x,
316 ArrayView<Base> dep) override {
317 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
318 CPPADCG_ASSERT_KNOWN(_zero != nullptr, "No zero order forward function defined in the dynamic library")
319 CPPADCG_ASSERT_KNOWN(_in.size() == x.size(), "The number of independent variable arrays is invalid")
320 CPPADCG_ASSERT_KNOWN(dep.size() == _m, "Invalid dependent array size")
321 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
322
323 _out[0] = dep.data();
324
325 (*_zero)(&x[0], &_out[0], _atomicFuncArg);
326 }
327
328 void ForwardZero(const CppAD::vector<bool>& vx,
331 ArrayView<Base> ty) override {
332 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
333 CPPADCG_ASSERT_KNOWN(_zero != nullptr, "No zero order forward function defined in the dynamic library")
334 CPPADCG_ASSERT_KNOWN(_in.size() == 1, "The number of independent variable arrays is higher than 1,"
335 " please use the variable size methods")
336 CPPADCG_ASSERT_KNOWN(tx.size() == _n, "Invalid independent array size")
337 CPPADCG_ASSERT_KNOWN(ty.size() == _m, "Invalid dependent array size")
338 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
339
340 _in[0] = tx.data();
341 _out[0] = ty.data();
342
343 (*_zero)(&_in[0], &_out[0], _atomicFuncArg);
344
345 if (vx.size() > 0) {
346 CPPADCG_ASSERT_KNOWN(vx.size() >= _n, "Invalid vx size")
347 CPPADCG_ASSERT_KNOWN(vy.size() >= _m, "Invalid vy size")
348 const std::vector<std::set<size_t> > jacSparsity = JacobianSparsitySet();
349 for (size_t i = 0; i < _m; i++) {
350 for (size_t j : jacSparsity[i]) {
351 if (vx[j]) {
352 vy[i] = true;
353 break;
354 }
355 }
356 }
357 }
358 }
359
360 bool isJacobianAvailable() override {
361 return _jacobian != nullptr;
362 }
363
366 ArrayView<Base> jac) override {
367 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
368 CPPADCG_ASSERT_KNOWN(_jacobian != nullptr, "No Jacobian function defined in the dynamic library")
369 CPPADCG_ASSERT_KNOWN(_in.size() == 1, "The number of independent variable arrays is higher than 1,"
370 " please use the variable size methods")
371 CPPADCG_ASSERT_KNOWN(x.size() == _n, "Invalid independent array size")
372 CPPADCG_ASSERT_KNOWN(jac.size() == _m * _n, "Invalid Jacobian array size")
373 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
374
375
376 _in[0] = x.data();
377 _out[0] = jac.data();
378
379 (*_jacobian)(&_in[0], &_out[0], _atomicFuncArg);
380 }
381
382 bool isHessianAvailable() override {
383 return _hessian != nullptr;
384 }
385
389 ArrayView<Base> hess) override {
390 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
391 CPPADCG_ASSERT_KNOWN(_hessian != nullptr, "No Hessian function defined in the dynamic library")
392 CPPADCG_ASSERT_KNOWN(_in.size() == 1, "The number of independent variable arrays is higher than 1,"
393 " please use the variable size methods")
394 CPPADCG_ASSERT_KNOWN(x.size() == _n, "Invalid independent array size")
395 CPPADCG_ASSERT_KNOWN(w.size() == _m, "Invalid multiplier array size")
396 CPPADCG_ASSERT_KNOWN(hess.size() == _n * _n, "Invalid Hessian size")
397 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
398
399 _inHess[0] = x.data();
400 _inHess[1] = w.data();
401 _out[0] = hess.data();
402
403 (*_hessian)(&_inHess[0], &_out[0], _atomicFuncArg);
404 }
405
406 bool isForwardOneAvailable() override {
407 return _forwardOne != nullptr;
408 }
409
411 ArrayView<Base> ty) override {
412 const size_t k = 1;
413
414 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
415 CPPADCG_ASSERT_KNOWN(_forwardOne != nullptr, "No forward one function defined in the dynamic library")
416 CPPADCG_ASSERT_KNOWN(tx.size() >= (k + 1) * _n, "Invalid tx size")
417 CPPADCG_ASSERT_KNOWN(ty.size() >= (k + 1) * _m, "Invalid ty size")
418 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
419
420 int ret = (*_forwardOne)(tx.data(), ty.data(), _atomicFuncArg);
421
422 CPPADCG_ASSERT_KNOWN(ret == 0, "First-order forward mode failed.") // generic failure
423 }
424
426 return _forwardOneSparsity != nullptr && _sparseForwardOne != nullptr;
427 }
428
430 size_t tx1Nnz, const size_t idx[], const Base tx1[],
431 ArrayView<Base> ty1) override {
432 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
433 CPPADCG_ASSERT_KNOWN(_sparseForwardOne != nullptr, "No sparse forward one function defined in the dynamic library")
434 CPPADCG_ASSERT_KNOWN(_forwardOneSparsity != nullptr, "No forward one sparsity function defined in the dynamic library")
435 CPPADCG_ASSERT_KNOWN(x.size() >= _n, "Invalid x size")
436 CPPADCG_ASSERT_KNOWN(ty1.size() >= _m, "Invalid ty1 size")
437 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
438
439 std::fill(ty1.data(), ty1.data() + _m, Base(0));
440 if (tx1Nnz == 0)
441 return; //nothing to do
442
443 unsigned long const* pos;
444 size_t nnz = 0;
445
446 _ty.resize(_m);
447 Base* compressed = &_ty[0];
448
449 _inHess[0] = x.data();
450 _out[0] = compressed;
451
452 for (size_t ej = 0; ej < tx1Nnz; ej++) {
453 size_t j = idx[ej];
454 (*_forwardOneSparsity)(j, &pos, &nnz);
455
456 _inHess[1] = &tx1[ej];
457 int ret = (*_sparseForwardOne)(j, &_inHess[0], &_out[0], _atomicFuncArg);
458
459 CPPADCG_ASSERT_KNOWN(ret == 0, "First-order forward mode failed.") // generic failure
460
461 for (size_t ePos = 0; ePos < nnz; ePos++) {
462 ty1[pos[ePos]] += compressed[ePos];
463 }
464 }
465 }
466
467 bool isReverseOneAvailable() override {
468 return _reverseOne != nullptr;
469 }
470
474 ArrayView<const Base> py) override {
475 const size_t k = 0;
476 const size_t k1 = k + 1;
477
478 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
479 CPPADCG_ASSERT_KNOWN(_reverseOne != nullptr, "No reverse one function defined in the dynamic library")
480 CPPADCG_ASSERT_KNOWN(tx.size() >= k1 * _n, "Invalid tx size")
481 CPPADCG_ASSERT_KNOWN(ty.size() >= k1 * _m, "Invalid ty size")
482 CPPADCG_ASSERT_KNOWN(px.size() >= k1 * _n, "Invalid px size")
483 CPPADCG_ASSERT_KNOWN(py.size() >= k1 * _m, "Invalid py size")
484 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
485
486 int ret = (*_reverseOne)(tx.data(), ty.data(), px.data(), py.data(), _atomicFuncArg);
487
488 CPPADCG_ASSERT_KNOWN(ret == 0, "First-order reverse mode failed.")
489 }
490
492 return _reverseOneSparsity != nullptr && _sparseReverseOne != nullptr;
493 }
494
497 size_t pyNnz, const size_t idx[], const Base py[]) override {
498 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
499 CPPADCG_ASSERT_KNOWN(_sparseReverseOne != nullptr, "No sparse reverse one function defined in the dynamic library")
500 CPPADCG_ASSERT_KNOWN(_reverseOneSparsity != nullptr, "No reverse one sparsity function defined in the dynamic library")
501 CPPADCG_ASSERT_KNOWN(x.size() >= _n, "Invalid x size")
502 CPPADCG_ASSERT_KNOWN(px.size() >= _n, "Invalid px size")
503 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
504
505 std::fill(px.data(), px.data() + _n, Base(0));
506 if (pyNnz == 0)
507 return; //nothing to do
508
509 unsigned long const* pos;
510 size_t nnz = 0;
511
512 _px.resize(_n);
513 Base* compressed = &_px[0];
514
515 _inHess[0] = x.data();
516 _out[0] = compressed;
517
518 for (size_t ei = 0; ei < pyNnz; ei++) {
519 size_t i = idx[ei];
520 (*_reverseOneSparsity)(i, &pos, &nnz);
521
522 _inHess[1] = &py[ei];
523 int ret = (*_sparseReverseOne)(i, &_inHess[0], &_out[0], _atomicFuncArg);
524
525 CPPADCG_ASSERT_KNOWN(ret == 0, "First-order reverse mode failed.")
526
527 for (size_t ePos = 0; ePos < nnz; ePos++) {
528 px[pos[ePos]] += compressed[ePos];
529 }
530 }
531 }
532
533 bool isReverseTwoAvailable() override {
534 return _reverseTwo != nullptr;
535 }
536
540 ArrayView<const Base> py) override {
541 const size_t k = 1;
542 const size_t k1 = k + 1;
543
544 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
545 CPPADCG_ASSERT_KNOWN(_reverseTwo != nullptr, "No sparse reverse two function defined in the dynamic library")
546 CPPADCG_ASSERT_KNOWN(_in.size() == 1, "The number of independent variable arrays is higher than 1")
547 CPPADCG_ASSERT_KNOWN(tx.size() >= k1 * _n, "Invalid tx size")
548 CPPADCG_ASSERT_KNOWN(ty.size() >= k1 * _m, "Invalid ty size")
549 CPPADCG_ASSERT_KNOWN(px.size() >= k1 * _n, "Invalid px size")
550 CPPADCG_ASSERT_KNOWN(py.size() >= k1 * _m, "Invalid py size")
551 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
552
553 int ret = (*_reverseTwo)(tx.data(), ty.data(), px.data(), py.data(), _atomicFuncArg);
554
555 CPPADCG_ASSERT_KNOWN(ret != 1, "Second-order reverse mode failed: py[2*i] (i=0...m) must be zero.")
556 CPPADCG_ASSERT_KNOWN(ret == 0, "Second-order reverse mode failed.")
557 }
558
560 return _sparseReverseTwo != nullptr;
561 }
562
564 size_t tx1Nnz, const size_t idx[], const Base tx1[],
565 ArrayView<Base> px2,
566 ArrayView<const Base> py2) override {
567 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
568 CPPADCG_ASSERT_KNOWN(_sparseReverseTwo != nullptr, "No sparse reverse two function defined in the dynamic library")
569 CPPADCG_ASSERT_KNOWN(_reverseTwoSparsity != nullptr, "No reverse two sparsity function defined in the dynamic library")
570 CPPADCG_ASSERT_KNOWN(x.size() >= _n, "Invalid x size")
571 CPPADCG_ASSERT_KNOWN(px2.size() >= _n, "Invalid px2 size")
572 CPPADCG_ASSERT_KNOWN(py2.size() >= _m, "Invalid py2 size")
573 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
574
575 std::fill(px2.data(), px2.data() + _n, Base(0));
576 if (tx1Nnz == 0)
577 return; //nothing to do
578
579 unsigned long const* pos;
580 size_t nnz = 0;
581
582 _px.resize(_n);
583 Base* compressed = &_px[0];
584
585 const Base * in[3];
586 in[0] = x.data();
587 in[2] = py2.data();
588 _out[0] = compressed;
589
590 for (size_t ej = 0; ej < tx1Nnz; ej++) {
591 size_t j = idx[ej];
592 (*_reverseTwoSparsity)(j, &pos, &nnz);
593
594 in[1] = &tx1[ej];
595 int ret = (*_sparseReverseTwo)(j, &in[0], &_out[0], _atomicFuncArg);
596
597 CPPADCG_ASSERT_KNOWN(ret == 0, "Second-order reverse mode failed.") // generic failure
598
599 for (size_t ePos = 0; ePos < nnz; ePos++) {
600 px2[pos[ePos]] += compressed[ePos];
601 }
602 }
603 }
604
606 return _jacobianSparsity != nullptr && _sparseJacobian != nullptr;
607 }
608
610
612 ArrayView<Base> jac) override {
613 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
614 CPPADCG_ASSERT_KNOWN(_sparseJacobian != nullptr, "No sparse jacobian function defined in the dynamic library")
615 CPPADCG_ASSERT_KNOWN(_in.size() == 1, "The number of independent variable arrays is higher than 1,"
616 " please use the variable size methods")
617 CPPADCG_ASSERT_KNOWN(x.size() == _n, "Invalid independent array size")
618 CPPADCG_ASSERT_KNOWN(jac.size() == _m * _n, "Invalid Jacobian size")
619 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
620
621 unsigned long const* row;
622 unsigned long const* col;
623 unsigned long nnz;
624 (*_jacobianSparsity)(&row, &col, &nnz);
625
626 CppAD::vector<Base> compressed(nnz);
627
628 if (nnz > 0) {
629 _in[0] = x.data();
630 _out[0] = &compressed[0];
631
632 (*_sparseJacobian)(&_in[0], &_out[0], _atomicFuncArg);
633 }
634
635 createDenseFromSparse(compressed,
636 _m, _n,
637 row, col,
638 nnz,
639 jac);
640 }
641
642 void SparseJacobian(const std::vector<Base> &x,
643 std::vector<Base>& jac,
644 std::vector<size_t>& row,
645 std::vector<size_t>& col) override {
646 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
647 CPPADCG_ASSERT_KNOWN(_sparseJacobian != nullptr, "No sparse Jacobian function defined in the dynamic library")
648 CPPADCG_ASSERT_KNOWN(_in.size() == 1, "The number of independent variable arrays is higher than 1,"
649 " please use the variable size methods")
650 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
651
652 unsigned long const* drow;
653 unsigned long const* dcol;
654 unsigned long nnz;
655 (*_jacobianSparsity)(&drow, &dcol, &nnz);
656
657 jac.resize(nnz);
658 row.resize(nnz);
659 col.resize(nnz);
660
661 if (nnz > 0) {
662 _in[0] = &x[0];
663 _out[0] = &jac[0];
664
665 (*_sparseJacobian)(&_in[0], &_out[0], _atomicFuncArg);
666 std::copy(drow, drow + nnz, row.begin());
667 std::copy(dcol, dcol + nnz, col.begin());
668 }
669 }
670
671 void SparseJacobian(ArrayView<const Base> x,
672 ArrayView<Base> jac,
673 size_t const** row,
674 size_t const** col) override {
675 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
676 CPPADCG_ASSERT_KNOWN(_sparseJacobian != nullptr, "No sparse Jacobian function defined in the dynamic library")
677 CPPADCG_ASSERT_KNOWN(_in.size() == 1, "The number of independent variable arrays is higher than 1,"
678 " please use the variable size methods")
679 CPPADCG_ASSERT_KNOWN(x.size() == _n, "Invalid independent array size")
680 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
681
682 unsigned long const* drow;
683 unsigned long const* dcol;
684 unsigned long nnz;
685 (*_jacobianSparsity)(&drow, &dcol, &nnz);
686 CPPADCG_ASSERT_KNOWN(nnz == jac.size(), "Invalid number of non-zero elements in Jacobian")
687 *row = drow;
688 *col = dcol;
689
690 if (nnz > 0) {
691 _in[0] = x.data();
692 _out[0] = jac.data();
693
694 (*_sparseJacobian)(&_in[0], &_out[0], _atomicFuncArg);
695 }
696 }
697
698 void SparseJacobian(const std::vector<const Base*>& x,
699 ArrayView<Base> jac,
700 size_t const** row,
701 size_t const** col) override {
702 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
703 CPPADCG_ASSERT_KNOWN(_sparseJacobian != nullptr, "No sparse Jacobian function defined in the dynamic library")
704 CPPADCG_ASSERT_KNOWN(_in.size() == x.size(), "The number of independent variable arrays is invalid")
705 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
706
707 unsigned long const* drow;
708 unsigned long const* dcol;
709 unsigned long nnz;
710 (*_jacobianSparsity)(&drow, &dcol, &nnz);
711 CPPADCG_ASSERT_KNOWN(nnz == jac.size(), "Invalid number of non-zero elements in Jacobian")
712 *row = drow;
713 *col = dcol;
714
715 if (nnz > 0) {
716 _out[0] = jac.data();
717
718 (*_sparseJacobian)(&x[0], &_out[0], _atomicFuncArg);
719 }
720 }
721
722 bool isSparseHessianAvailable() override {
723 return _hessianSparsity != nullptr && _sparseHessian != nullptr;
724 }
725
727
730 ArrayView<Base> hess) override {
731 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
732 CPPADCG_ASSERT_KNOWN(_sparseHessian != nullptr, "No sparse Hessian function defined in the dynamic library")
733 CPPADCG_ASSERT_KNOWN(x.size() == _n, "Invalid independent array size")
734 CPPADCG_ASSERT_KNOWN(w.size() == _m, "Invalid multiplier array size")
735 // CPPADCG_ASSERT_KNOWN(hess.size() == _n * _n, "Invalid Hessian size")
736 CPPADCG_ASSERT_KNOWN(_in.size() == 1, "The number of independent variable arrays is higher than 1,"
737 " please use the variable size methods")
738 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
739
740 unsigned long const* row, *col;
741 unsigned long nnz;
742 (*_hessianSparsity)(&row, &col, &nnz);
743
744 CppAD::vector<Base> compressed(nnz);
745 if (nnz > 0) {
746 _inHess[0] = x.data();
747 _inHess[1] = w.data();
748 _out[0] = &compressed[0];
749
750 (*_sparseHessian)(&_inHess[0], &_out[0], _atomicFuncArg);
751 }
752
753 createDenseFromSparse(compressed,
754 _n, _n,
755 row, col,
756 nnz,
757 hess);
758 }
759
760 void SparseHessian(const std::vector<Base> &x,
761 const std::vector<Base> &w,
762 std::vector<Base>& hess,
763 std::vector<size_t>& row,
764 std::vector<size_t>& col) override {
765 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
766 CPPADCG_ASSERT_KNOWN(_sparseHessian != nullptr, "No sparse Hessian function defined in the dynamic library")
767 CPPADCG_ASSERT_KNOWN(x.size() == _n, "Invalid independent array size")
768 CPPADCG_ASSERT_KNOWN(w.size() == _m, "Invalid multiplier array size")
769 CPPADCG_ASSERT_KNOWN(_in.size() == 1, "The number of independent variable arrays is higher than 1,"
770 " please use the variable size methods")
771 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
772
773 unsigned long const* drow, *dcol;
774 unsigned long nnz;
775 (*_hessianSparsity)(&drow, &dcol, &nnz);
776
777 hess.resize(nnz);
778 row.resize(nnz);
779 col.resize(nnz);
780
781 if (nnz > 0) {
782 std::copy(drow, drow + nnz, row.begin());
783 std::copy(dcol, dcol + nnz, col.begin());
784
785 _inHess[0] = &x[0];
786 _inHess[1] = &w[0];
787 _out[0] = &hess[0];
788
789 (*_sparseHessian)(&_inHess[0], &_out[0], _atomicFuncArg);
790 }
791 }
792
793 void SparseHessian(ArrayView<const Base> x,
794 ArrayView<const Base> w,
795 ArrayView<Base> hess,
796 size_t const** row,
797 size_t const** col) override {
798 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
799 CPPADCG_ASSERT_KNOWN(_sparseHessian != nullptr, "No sparse Hessian function defined in the dynamic library")
800 CPPADCG_ASSERT_KNOWN(_in.size() == 1, "The number of independent variable arrays is higher than 1,"
801 " please use the variable size methods")
802 CPPADCG_ASSERT_KNOWN(x.size() == _n, "Invalid independent array size")
803 CPPADCG_ASSERT_KNOWN(w.size() == _m, "Invalid multiplier array size")
804 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
805
806 unsigned long const* drow, *dcol;
807 unsigned long nnz;
808 (*_hessianSparsity)(&drow, &dcol, &nnz);
809 CPPADCG_ASSERT_KNOWN(nnz == hess.size(), "Invalid number of non-zero elements in Hessian")
810 *row = drow;
811 *col = dcol;
812
813 if (nnz > 0) {
814 _inHess[0] = x.data();
815 _inHess[1] = w.data();
816 _out[0] = hess.data();
817
818 (*_sparseHessian)(&_inHess[0], &_out[0], _atomicFuncArg);
819 }
820 }
821
822 void SparseHessian(const std::vector<const Base*>& x,
824 ArrayView<Base> hess,
825 size_t const** row,
826 size_t const** col) override {
827 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
828 CPPADCG_ASSERT_KNOWN(_sparseHessian != nullptr, "No sparse Hessian function defined in the dynamic library")
829 CPPADCG_ASSERT_KNOWN(_in.size() == x.size(), "The number of independent variable arrays is invalid")
830 CPPADCG_ASSERT_KNOWN(w.size() == _m, "Invalid multiplier array size")
831 CPPADCG_ASSERT_KNOWN(_missingAtomicFunctions == 0, "Some atomic functions used by the compiled model have not been specified yet")
832
833 unsigned long const* drow, *dcol;
834 unsigned long nnz;
835 (*_hessianSparsity)(&drow, &dcol, &nnz);
836 CPPADCG_ASSERT_KNOWN(nnz == hess.size(), "Invalid number of non-zero elements in Hessian")
837 *row = drow;
838 *col = dcol;
839
840 if (nnz > 0) {
841 std::copy(x.begin(), x.end(), _inHess.begin());
842 _inHess.back() = w.data(); // the index might not be 1
843 _out[0] = hess.data();
844
845 (*_sparseHessian)(&_inHess[0], &_out[0], _atomicFuncArg);
846 }
847 }
848
849protected:
850
856 explicit FunctorGenericModel(std::string name) :
857 _isLibraryReady(false),
858 _name(std::move(name)),
859 _m(0),
860 _n(0),
861 _atomicFuncArg{nullptr}, // not really required
862 _missingAtomicFunctions(0),
863 _zero(nullptr),
864 _forwardOne(nullptr),
865 _reverseOne(nullptr),
866 _reverseTwo(nullptr),
867 _jacobian(nullptr),
868 _hessian(nullptr),
869 _sparseForwardOne(nullptr),
870 _sparseReverseOne(nullptr),
871 _sparseReverseTwo(nullptr),
872 _sparseJacobian(nullptr),
873 _sparseHessian(nullptr),
874 _forwardOneSparsity(nullptr),
875 _reverseOneSparsity(nullptr),
876 _reverseTwoSparsity(nullptr),
877 _jacobianSparsity(nullptr),
878 _hessianSparsity(nullptr),
879 _hessianSparsity2(nullptr),
880 _atomicFunctions(nullptr) {
881
882 }
883
884 virtual void init() {
885 // validate the dynamic library
886 validate();
887
888 // load functions from the dynamic library
890 }
891
892 virtual void* loadFunction(const std::string& functionName,
893 bool required = true) = 0;
894
895 virtual void validate() {
899 void (*infoFunc)(const char** baseName, unsigned long*, unsigned long*, unsigned int*, unsigned int*);
900 infoFunc = reinterpret_cast<decltype(infoFunc)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_INFO));
901
902 // local
903 const char* localBaseName = typeid (Base).name();
904 std::string local = ModelCSourceGen<Base>::baseTypeName() + " " + localBaseName;
905
906 // from dynamic library
907 const char* dynamicLibBaseName = nullptr;
908 unsigned int inSize = 0;
909 unsigned int outSize = 0;
910 (*infoFunc)(&dynamicLibBaseName, &_m, &_n, &inSize, &outSize);
911
912 _in.resize(inSize);
913 _inHess.resize(inSize + 1);
914 _out.resize(outSize);
915
916 CPPADCG_ASSERT_KNOWN(local == std::string(dynamicLibBaseName),
917 (std::string("Invalid data type in dynamic library. Expected '") + local
918 + "' but the library provided '" + dynamicLibBaseName + "'.").c_str())
919 CPPADCG_ASSERT_KNOWN(inSize > 0,
920 "Invalid dimension received from the dynamic library.")
921 CPPADCG_ASSERT_KNOWN(outSize > 0,
922 "Invalid dimension received from the dynamic library.")
923
924 _isLibraryReady = true;
925 }
926
927 virtual void loadFunctions() {
928 _zero = reinterpret_cast<decltype(_zero)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_FORWAD_ZERO, false));
929 _forwardOne = reinterpret_cast<decltype(_forwardOne)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_FORWARD_ONE, false));
930 _reverseOne = reinterpret_cast<decltype(_reverseOne)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_REVERSE_ONE, false));
931 _reverseTwo = reinterpret_cast<decltype(_reverseTwo)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_REVERSE_TWO, false));
932 _jacobian = reinterpret_cast<decltype(_jacobian)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_JACOBIAN, false));
933 _hessian = reinterpret_cast<decltype(_hessian)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_HESSIAN, false));
934 _sparseForwardOne = reinterpret_cast<decltype(_sparseForwardOne)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_SPARSE_FORWARD_ONE, false));
935 _sparseReverseOne = reinterpret_cast<decltype(_sparseReverseOne)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_SPARSE_REVERSE_ONE, false));
936 _sparseReverseTwo = reinterpret_cast<decltype(_sparseReverseTwo)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_SPARSE_REVERSE_TWO, false));
937 _sparseJacobian = reinterpret_cast<decltype(_sparseJacobian)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_SPARSE_JACOBIAN, false));
938 _sparseHessian = reinterpret_cast<decltype(_sparseHessian)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_SPARSE_HESSIAN, false));
939 _forwardOneSparsity = reinterpret_cast<decltype(_forwardOneSparsity)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_FORWARD_ONE_SPARSITY, false));
940 _reverseOneSparsity = reinterpret_cast<decltype(_reverseOneSparsity)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_REVERSE_ONE_SPARSITY, false));
941 _reverseTwoSparsity = reinterpret_cast<decltype(_reverseTwoSparsity)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_REVERSE_TWO_SPARSITY, false));
942 _jacobianSparsity = reinterpret_cast<decltype(_jacobianSparsity)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_JACOBIAN_SPARSITY, false));
943 _hessianSparsity = reinterpret_cast<decltype(_hessianSparsity)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_HESSIAN_SPARSITY, false));
944 _hessianSparsity2 = reinterpret_cast<decltype(_hessianSparsity2)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_HESSIAN_SPARSITY2, false));
945 _atomicFunctions = reinterpret_cast<decltype(_atomicFunctions)>(loadFunction(_name + "_" + ModelCSourceGen<Base>::FUNCTION_ATOMIC_FUNC_NAMES, true));
946
947 CPPADCG_ASSERT_KNOWN((_sparseForwardOne == nullptr) == (_forwardOneSparsity == nullptr), "Missing functions in the dynamic library")
948 CPPADCG_ASSERT_KNOWN((_sparseForwardOne == nullptr) == (_forwardOne == nullptr), "Missing functions in the dynamic library")
949 CPPADCG_ASSERT_KNOWN((_sparseReverseOne == nullptr) == (_reverseOneSparsity == nullptr), "Missing functions in the dynamic library")
950 CPPADCG_ASSERT_KNOWN((_sparseReverseOne == nullptr) == (_reverseOne == nullptr), "Missing functions in the dynamic library")
951 CPPADCG_ASSERT_KNOWN((_sparseReverseTwo == nullptr) == (_reverseTwoSparsity == nullptr), "Missing functions in the dynamic library")
952 CPPADCG_ASSERT_KNOWN((_sparseReverseTwo == nullptr) == (_reverseTwo == nullptr), "Missing functions in the dynamic library")
953 CPPADCG_ASSERT_KNOWN((_sparseJacobian == nullptr) || (_jacobianSparsity != nullptr), "Missing functions in the dynamic library")
954 CPPADCG_ASSERT_KNOWN((_sparseHessian == nullptr) || (_hessianSparsity != nullptr), "Missing functions in the dynamic library")
955
956
959 const char** names;
960 unsigned long n;
961 (*_atomicFunctions)(&names, &n);
962 _atomic.resize(n);
963 _atomicNames.resize(n);
964 for (unsigned long i = 0; i < n; ++i) {
965 _atomicNames[i] = std::string(names[i]);
966 }
967
968 _atomicFuncArg.libModel = this;
969 _atomicFuncArg.forward = &atomicForward;
970 _atomicFuncArg.reverse = &atomicReverse;
971
972 _missingAtomicFunctions = n;
973 }
974
975 template <class VectorSet>
976 inline void loadSparsity(bool set_type,
977 VectorSet& s,
978 unsigned long nrows, unsigned long ncols,
979 unsigned long const* rows, unsigned long const* cols,
980 unsigned long nnz) {
981 s.resize(nrows * ncols, false);
982
983 for (unsigned long i = 0; i < nnz; i++) {
984 s[rows[i] * ncols + cols[i]] = true;
985 }
986 }
987
988 template <class VectorSet>
989 inline void loadSparsity(const std::set<size_t>& set_type,
990 VectorSet& s,
991 unsigned long nrows, unsigned long ncols,
992 unsigned long const* rows, unsigned long const* cols,
993 unsigned long nnz) {
994
995 // dimension size of result vector
996 s.resize(nrows);
997
998 for (unsigned long i = 0; i < nnz; i++) {
999 s[rows[i]].insert(cols[i]);
1000 }
1001 }
1002
1003 inline void createDenseFromSparse(const CppAD::vector<Base>& compressed,
1004 unsigned long nrows, unsigned long ncols,
1005 unsigned long const* rows, unsigned long const* cols,
1006 unsigned long nnz,
1007 ArrayView<Base> mat) const {
1008 CPPADCG_ASSERT_KNOWN(mat.size() == nrows * ncols, "Invalid matrix size")
1009 mat.fill(Base(0));
1010
1011 for (size_t i = 0; i < nnz; i++) {
1012 mat[rows[i] * ncols + cols[i]] = compressed[i];
1013 }
1014 }
1015
1016 virtual void modelLibraryClosed() {
1017 _isLibraryReady = false;
1018 _zero = nullptr;
1019 _forwardOne = nullptr;
1020 _reverseOne = nullptr;
1021 _reverseTwo = nullptr;
1022 _jacobian = nullptr;
1023 _hessian = nullptr;
1024 _sparseForwardOne = nullptr;
1025 _sparseReverseOne = nullptr;
1026 _sparseReverseTwo = nullptr;
1027 _sparseJacobian = nullptr;
1028 _sparseHessian = nullptr;
1029 _forwardOneSparsity = nullptr;
1030 _reverseOneSparsity = nullptr;
1031 _reverseTwoSparsity = nullptr;
1032 _jacobianSparsity = nullptr;
1033 _hessianSparsity = nullptr;
1034 _hessianSparsity2 = nullptr;
1035 }
1036
1037private:
1038
1039 template<class ExtFunc, class Wrapper>
1040 inline bool addExternalFunction(ExtFunc& atomic,
1041 const std::string& name) {
1042 size_t n = _atomicNames.size();
1043 for (size_t i = 0; i < n; i++) {
1044 if (name == _atomicNames[i]) {
1045 if (_atomic[i] == nullptr) {
1046 _missingAtomicFunctions--;
1047 } else {
1048 delete _atomic[i];
1049 }
1050 _atomic[i] = new Wrapper(atomic);
1051 return true;
1052 }
1053 }
1054 return false;
1055 }
1056
1057 static int atomicForward(void* libModelIn,
1058 int atomicIndex,
1059 int q,
1060 int p,
1061 const Array tx[],
1062 Array* ty) {
1063 auto* libModel = static_cast<FunctorGenericModel<Base>*> (libModelIn);
1064 ExternalFunctionWrapper<Base>* externalFunc = libModel->_atomic[atomicIndex];
1065
1066 return externalFunc->forward(*libModel, q, p, tx, *ty);
1067 }
1068
1069 static int atomicReverse(void* libModelIn,
1070 int atomicIndex,
1071 int p,
1072 const Array tx[],
1073 Array* px,
1074 const Array py[]) {
1075 auto* libModel = static_cast<FunctorGenericModel<Base>*> (libModelIn);
1076 ExternalFunctionWrapper<Base>* externalFunc = libModel->_atomic[atomicIndex];
1077
1078 return externalFunc->reverse(*libModel, p, tx, *px, py);
1079 }
1080#ifdef CPPAD_CG_SYSTEM_LINUX
1081 friend class LinuxDynamicLib<Base>;
1082#endif
1083 friend class AtomicExternalFunctionWrapper<Base>;
1084};
1085
1086} // END cg namespace
1087} // END CppAD namespace
1088
1089#endif
size_t size() const noexcept
pointer data() noexcept
void ReverseOne(ArrayView< const Base > x, ArrayView< Base > px, size_t pyNnz, const size_t idx[], const Base py[]) override
std::vector< std::set< size_t > > HessianSparsitySet() override
size_t Domain() const override
number of independent variables
void ForwardOne(ArrayView< const Base > x, size_t tx1Nnz, const size_t idx[], const Base tx1[], ArrayView< Base > ty1) override
void SparseJacobian(const std::vector< const Base * > &x, ArrayView< Base > jac, size_t const **row, size_t const **col) override
void ReverseTwo(ArrayView< const Base > x, size_t tx1Nnz, const size_t idx[], const Base tx1[], ArrayView< Base > px2, ArrayView< const Base > py2) override
const std::string _name
the model name
void Hessian(ArrayView< const Base > x, ArrayView< const Base > w, ArrayView< Base > hess) override
calculate Hessian for one component of f
const std::vector< std::string > & getAtomicFunctionNames() override
void ForwardZero(ArrayView< const Base > x, ArrayView< Base > dep) override
calculate the dependent values (zero order)
void SparseHessian(const std::vector< const Base * > &x, ArrayView< const Base > w, ArrayView< Base > hess, size_t const **row, size_t const **col) override
void ReverseTwo(ArrayView< const Base > tx, ArrayView< const Base > ty, ArrayView< Base > px, ArrayView< const Base > py) override
void SparseJacobian(ArrayView< const Base > x, ArrayView< Base > jac) override
calculate sparse Jacobians
const std::string & getName() const override
void ForwardZero(const std::vector< const Base * > &x, ArrayView< Base > dep) override
void Jacobian(ArrayView< const Base > x, ArrayView< Base > jac) override
calculate entire Jacobian
bool addExternalModel(GenericModel< Base > &atomic) override
void SparseHessian(ArrayView< const Base > x, ArrayView< const Base > w, ArrayView< Base > hess) override
calculate sparse Hessians
void ReverseOne(ArrayView< const Base > tx, ArrayView< const Base > ty, ArrayView< Base > px, ArrayView< const Base > py) override
void ForwardOne(ArrayView< const Base > tx, ArrayView< Base > ty) override
size_t Range() const override
number of dependent variables
bool addAtomicFunction(atomic_base< Base > &atomic) override
virtual const std::string & getName() const =0