1 #ifndef CPPAD_CG_FUNCTOR_GENERIC_MODEL_INCLUDED
2 #define CPPAD_CG_FUNCTOR_GENERIC_MODEL_INCLUDED
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.";
44 std::vector<const Base*> _in;
45 std::vector<const Base*> _inHess;
46 std::vector<Base*> _out;
48 std::vector<std::string> _atomicNames;
49 std::vector<ExternalFunctionWrapper<Base>* > _atomic;
50 size_t _missingAtomicFunctions;
57 int (*_reverseOne)(Base
const tx[], Base
const ty[], Base px[], Base
const py[],
LangCAtomicFun);
59 int (*_reverseTwo)(Base
const tx[], Base
const ty[], Base px[], Base
const py[],
LangCAtomicFun);
61 void (*_jacobian)(Base
const*
const*, Base *
const*,
LangCAtomicFun);
63 void (*_hessian)(Base
const*
const*, Base *
const*,
LangCAtomicFun);
65 int (*_sparseForwardOne)(
unsigned long, Base
const *
const *, Base *
const *,
LangCAtomicFun);
67 int (*_sparseReverseOne)(
unsigned long, Base
const *
const *, Base *
const *,
LangCAtomicFun);
69 int (*_sparseReverseTwo)(
unsigned long, Base
const *
const *, Base *
const *,
LangCAtomicFun);
71 void (*_sparseJacobian)(Base
const*
const*, Base *
const*,
LangCAtomicFun);
73 void (*_sparseHessian)(Base
const*
const*, Base *
const*,
LangCAtomicFun);
75 void (*_forwardOneSparsity)(
unsigned long,
unsigned long const**,
unsigned long*);
77 void (*_reverseOneSparsity)(
unsigned long,
unsigned long const**,
unsigned long*);
79 void (*_reverseTwoSparsity)(
unsigned long,
unsigned long const**,
unsigned long*);
81 void (*_jacobianSparsity)(
unsigned long const** row,
82 unsigned long const** col,
85 void (*_hessianSparsity)(
unsigned long const** row,
86 unsigned long const** col,
88 void (*_hessianSparsity2)(
unsigned long i,
89 unsigned long const** row,
90 unsigned long const** col,
92 void (*_atomicFunctions)(
const char*** names,
101 for (
size_t i = 0; i < _atomic.size(); i++) {
116 (atomic, atomic.atomic_name());
126 return _jacobianSparsity !=
nullptr;
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")
133 unsigned
long const* row, *col;
135 (*_jacobianSparsity)(&row, &col, &nnz);
137 bool set_type = true;
140 loadSparsity(set_type, s, _m, _n, row, col, nnz);
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")
149 unsigned
long const* row, *col;
151 (*_jacobianSparsity)(&row, &col, &nnz);
153 std::set<
size_t> set_type;
154 std::
vector<std::set<
size_t> > s;
156 loadSparsity(set_type, s, _m, _n, row, col, nnz);
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")
166 unsigned
long const* row, *col;
168 (*_jacobianSparsity)(&row, &col, &nnz);
170 equations.resize(nnz);
171 variables.resize(nnz);
173 std::copy(row, row + nnz, equations.begin());
174 std::copy(col, col + nnz, variables.begin());
179 return _hessianSparsity !=
nullptr;
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")
186 unsigned
long const* row, *col;
188 (*_hessianSparsity)(&row, &col, &nnz);
190 bool set_type = true;
193 loadSparsity(set_type, s, _n, _n, row, col, nnz);
199 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
200 CPPADCG_ASSERT_KNOWN(_hessianSparsity !=
nullptr,
"No Hessian sparsity function defined in the dynamic library")
202 unsigned long const* row, *col;
204 (*_hessianSparsity)(&row, &col, &nnz);
206 std::set<size_t> set_type;
207 std::vector<std::set<size_t> > s;
209 loadSparsity(set_type, s, _n, _n, row, col, nnz);
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")
219 unsigned
long const* row, *col;
221 (*_hessianSparsity)(&row, &col, &nnz);
226 std::copy(row, row + nnz, rows.begin());
227 std::copy(col, col + nnz, cols.begin());
231 return _hessianSparsity2 !=
nullptr;
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")
238 unsigned
long const* row, *col;
240 (*_hessianSparsity2)(i, &row, &col, &nnz);
242 bool set_type = true;
245 loadSparsity(set_type, s, _n, _n, row, col, nnz);
251 CPPADCG_ASSERT_KNOWN(_isLibraryReady, ERROR_LIBRARY_NOT_READY)
252 CPPADCG_ASSERT_KNOWN(_hessianSparsity2 !=
nullptr,
"No Hessian sparsity function defined in the dynamic library")
254 unsigned long const* row, *col;
256 (*_hessianSparsity2)(i, &row, &col, &nnz);
258 std::set<size_t> set_type;
259 std::vector<std::set<size_t> > s;
261 loadSparsity(set_type, s, _n, _n, row, col, nnz);
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")
271 unsigned
long const* row, *col;
273 (*_hessianSparsity2)(i, &row, &col, &nnz);
278 std::copy(row, row + nnz, rows.begin());
279 std::copy(col, col + nnz, cols.begin());
295 return _zero !=
nullptr;
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")
310 _out[0] = dep.
data();
312 (*_zero)(&_in[0], &_out[0], _atomicFuncArg);
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")
323 _out[0] = dep.
data();
325 (*_zero)(&x[0], &_out[0], _atomicFuncArg);
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")
343 (*_zero)(&_in[0], &_out[0], _atomicFuncArg);
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]) {
361 return _jacobian !=
nullptr;
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")
377 _out[0] = jac.
data();
379 (*_jacobian)(&_in[0], &_out[0], _atomicFuncArg);
383 return _hessian !=
nullptr;
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")
399 _inHess[0] = x.
data();
400 _inHess[1] = w.
data();
401 _out[0] = hess.
data();
403 (*_hessian)(&_inHess[0], &_out[0], _atomicFuncArg);
407 return _forwardOne !=
nullptr;
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")
420 int ret = (*_forwardOne)(tx.
data(), ty.
data(), _atomicFuncArg);
422 CPPADCG_ASSERT_KNOWN(ret == 0,
"First-order forward mode failed.")
426 return _forwardOneSparsity !=
nullptr && _sparseForwardOne !=
nullptr;
430 size_t tx1Nnz,
const size_t idx[],
const Base tx1[],
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")
439 std::fill(ty1.
data(), ty1.
data() + _m, Base(0));
443 unsigned long const* pos;
447 Base* compressed = &_ty[0];
449 _inHess[0] = x.
data();
450 _out[0] = compressed;
452 for (
size_t ej = 0; ej < tx1Nnz; ej++) {
454 (*_forwardOneSparsity)(j, &pos, &nnz);
456 _inHess[1] = &tx1[ej];
457 int ret = (*_sparseForwardOne)(j, &_inHess[0], &_out[0], _atomicFuncArg);
459 CPPADCG_ASSERT_KNOWN(ret == 0,
"First-order forward mode failed.")
461 for (
size_t ePos = 0; ePos < nnz; ePos++) {
462 ty1[pos[ePos]] += compressed[ePos];
468 return _reverseOne !=
nullptr;
476 const size_t k1 = k + 1;
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")
486 int ret = (*_reverseOne)(tx.
data(), ty.
data(), px.
data(), py.
data(), _atomicFuncArg);
488 CPPADCG_ASSERT_KNOWN(ret == 0,
"First-order reverse mode failed.")
492 return _reverseOneSparsity !=
nullptr && _sparseReverseOne !=
nullptr;
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")
505 std::fill(px.
data(), px.
data() + _n, Base(0));
509 unsigned long const* pos;
513 Base* compressed = &_px[0];
515 _inHess[0] = x.
data();
516 _out[0] = compressed;
518 for (
size_t ei = 0; ei < pyNnz; ei++) {
520 (*_reverseOneSparsity)(i, &pos, &nnz);
522 _inHess[1] = &py[ei];
523 int ret = (*_sparseReverseOne)(i, &_inHess[0], &_out[0], _atomicFuncArg);
525 CPPADCG_ASSERT_KNOWN(ret == 0,
"First-order reverse mode failed.")
527 for (
size_t ePos = 0; ePos < nnz; ePos++) {
528 px[pos[ePos]] += compressed[ePos];
534 return _reverseTwo !=
nullptr;
542 const size_t k1 = k + 1;
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")
553 int ret = (*_reverseTwo)(tx.
data(), ty.
data(), px.
data(), py.
data(), _atomicFuncArg);
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.")
560 return _sparseReverseTwo !=
nullptr;
564 size_t tx1Nnz,
const size_t idx[],
const Base tx1[],
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")
575 std::fill(px2.
data(), px2.
data() + _n, Base(0));
579 unsigned long const* pos;
583 Base* compressed = &_px[0];
588 _out[0] = compressed;
590 for (
size_t ej = 0; ej < tx1Nnz; ej++) {
592 (*_reverseTwoSparsity)(j, &pos, &nnz);
595 int ret = (*_sparseReverseTwo)(j, &in[0], &_out[0], _atomicFuncArg);
597 CPPADCG_ASSERT_KNOWN(ret == 0,
"Second-order reverse mode failed.")
599 for (
size_t ePos = 0; ePos < nnz; ePos++) {
600 px2[pos[ePos]] += compressed[ePos];
606 return _jacobianSparsity !=
nullptr && _sparseJacobian !=
nullptr;
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")
621 unsigned long const* row;
622 unsigned long const* col;
624 (*_jacobianSparsity)(&row, &col, &nnz);
630 _out[0] = &compressed[0];
632 (*_sparseJacobian)(&_in[0], &_out[0], _atomicFuncArg);
635 createDenseFromSparse(compressed,
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")
652 unsigned long const* drow;
653 unsigned long const* dcol;
655 (*_jacobianSparsity)(&drow, &dcol, &nnz);
665 (*_sparseJacobian)(&_in[0], &_out[0], _atomicFuncArg);
666 std::copy(drow, drow + nnz, row.begin());
667 std::copy(dcol, dcol + nnz, col.begin());
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")
682 unsigned long const* drow;
683 unsigned long const* dcol;
685 (*_jacobianSparsity)(&drow, &dcol, &nnz);
686 CPPADCG_ASSERT_KNOWN(nnz == jac.size(), "Invalid number of non-zero elements in
Jacobian")
692 _out[0] = jac.data();
694 (*_sparseJacobian)(&_in[0], &_out[0], _atomicFuncArg);
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")
707 unsigned long const* drow;
708 unsigned long const* dcol;
710 (*_jacobianSparsity)(&drow, &dcol, &nnz);
711 CPPADCG_ASSERT_KNOWN(nnz == jac.
size(),
"Invalid number of non-zero elements in Jacobian")
716 _out[0] = jac.
data();
718 (*_sparseJacobian)(&x[0], &_out[0], _atomicFuncArg);
723 return _hessianSparsity !=
nullptr && _sparseHessian !=
nullptr;
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")
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")
740 unsigned long const* row, *col;
742 (*_hessianSparsity)(&row, &col, &nnz);
746 _inHess[0] = x.
data();
747 _inHess[1] = w.
data();
748 _out[0] = &compressed[0];
750 (*_sparseHessian)(&_inHess[0], &_out[0], _atomicFuncArg);
753 createDenseFromSparse(compressed,
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")
773 unsigned long const* drow, *dcol;
775 (*_hessianSparsity)(&drow, &dcol, &nnz);
782 std::copy(drow, drow + nnz, row.begin());
783 std::copy(dcol, dcol + nnz, col.begin());
789 (*_sparseHessian)(&_inHess[0], &_out[0], _atomicFuncArg);
794 ArrayView<const Base> w,
795 ArrayView<Base> hess,
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")
806 unsigned long const* drow, *dcol;
808 (*_hessianSparsity)(&drow, &dcol, &nnz);
809 CPPADCG_ASSERT_KNOWN(nnz == hess.size(), "Invalid number of non-zero elements in
Hessian")
814 _inHess[0] = x.data();
815 _inHess[1] = w.data();
816 _out[0] = hess.data();
818 (*_sparseHessian)(&_inHess[0], &_out[0], _atomicFuncArg);
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")
833 unsigned long const* drow, *dcol;
835 (*_hessianSparsity)(&drow, &dcol, &nnz);
836 CPPADCG_ASSERT_KNOWN(nnz == hess.
size(),
"Invalid number of non-zero elements in Hessian")
841 std::copy(x.begin(), x.end(), _inHess.begin());
842 _inHess.back() = w.
data();
843 _out[0] = hess.
data();
845 (*_sparseHessian)(&_inHess[0], &_out[0], _atomicFuncArg);
857 _isLibraryReady(false),
858 _name(std::move(name)),
861 _atomicFuncArg{nullptr},
862 _missingAtomicFunctions(0),
864 _forwardOne(nullptr),
865 _reverseOne(nullptr),
866 _reverseTwo(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) {
884 virtual void init() {
892 virtual void* loadFunction(
const std::string& functionName,
893 bool required =
true) = 0;
899 void (*infoFunc)(
const char** baseName,
unsigned long*,
unsigned long*,
unsigned int*,
unsigned int*);
903 const char* localBaseName =
typeid (Base).name();
907 const char* dynamicLibBaseName =
nullptr;
908 unsigned int inSize = 0;
909 unsigned int outSize = 0;
910 (*infoFunc)(&dynamicLibBaseName, &_m, &_n, &inSize, &outSize);
913 _inHess.resize(inSize + 1);
914 _out.resize(outSize);
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.")
924 _isLibraryReady =
true;
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")
961 (*_atomicFunctions)(&names, &n);
963 _atomicNames.resize(n);
964 for (
unsigned long i = 0; i < n; ++i) {
965 _atomicNames[i] = std::string(names[i]);
968 _atomicFuncArg.libModel =
this;
969 _atomicFuncArg.forward = &atomicForward;
970 _atomicFuncArg.reverse = &atomicReverse;
972 _missingAtomicFunctions = n;
975 template <
class VectorSet>
976 inline void loadSparsity(
bool set_type,
978 unsigned long nrows,
unsigned long ncols,
979 unsigned long const* rows,
unsigned long const* cols,
981 s.resize(nrows * ncols,
false);
983 for (
unsigned long i = 0; i < nnz; i++) {
984 s[rows[i] * ncols + cols[i]] =
true;
988 template <
class VectorSet>
989 inline void loadSparsity(
const std::set<size_t>& set_type,
991 unsigned long nrows,
unsigned long ncols,
992 unsigned long const* rows,
unsigned long const* cols,
998 for (
unsigned long i = 0; i < nnz; i++) {
999 s[rows[i]].insert(cols[i]);
1004 unsigned long nrows,
unsigned long ncols,
1005 unsigned long const* rows,
unsigned long const* cols,
1007 ArrayView<Base> mat)
const {
1008 CPPADCG_ASSERT_KNOWN(mat.size() == nrows * ncols,
"Invalid matrix size")
1011 for (
size_t i = 0; i < nnz; i++) {
1012 mat[rows[i] * ncols + cols[i]] = compressed[i];
1016 virtual void modelLibraryClosed() {
1017 _isLibraryReady =
false;
1019 _forwardOne =
nullptr;
1020 _reverseOne =
nullptr;
1021 _reverseTwo =
nullptr;
1022 _jacobian =
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;
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--;
1050 _atomic[i] =
new Wrapper(atomic);
1057 static int atomicForward(
void* libModelIn,
1063 auto* libModel =
static_cast<FunctorGenericModel<Base>*
> (libModelIn);
1064 ExternalFunctionWrapper<Base>* externalFunc = libModel->_atomic[atomicIndex];
1066 return externalFunc->forward(*libModel, q, p, tx, *ty);
1069 static int atomicReverse(
void* libModelIn,
1075 auto* libModel =
static_cast<FunctorGenericModel<Base>*
> (libModelIn);
1076 ExternalFunctionWrapper<Base>* externalFunc = libModel->_atomic[atomicIndex];
1078 return externalFunc->reverse(*libModel, p, tx, *px, py);
1080 #ifdef CPPAD_CG_SYSTEM_LINUX
1081 friend class LinuxDynamicLib<Base>;
1083 friend class AtomicExternalFunctionWrapper<Base>;
size_t size() const noexcept
void ReverseOne(ArrayView< const Base > x, ArrayView< Base > px, size_t pyNnz, const size_t idx[], const Base py[]) override
size_t Domain() const override
number of independent variables
bool isReverseOneAvailable() override
void ForwardOne(ArrayView< const Base > x, size_t tx1Nnz, const size_t idx[], const Base tx1[], ArrayView< Base > ty1) override
bool isHessianAvailable() override
FunctorGenericModel(std::string name)
bool isSparseForwardOneAvailable() override
void SparseJacobian(const std::vector< const Base * > &x, ArrayView< Base > jac, size_t const **row, size_t const **col) override
const std::vector< std::string > & getAtomicFunctionNames() override
bool isJacobianSparsityAvailable() override
bool isSparseJacobianAvailable() 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
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
bool isHessianSparsityAvailable() override
void SparseJacobian(ArrayView< const Base > x, ArrayView< Base > jac) override
calculate sparse Jacobians
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 isSparseReverseOneAvailable() override
bool addExternalModel(GenericModel< Base > &atomic) override
void SparseHessian(ArrayView< const Base > x, ArrayView< const Base > w, ArrayView< Base > hess) override
calculate sparse Hessians
virtual void loadFunctions()
bool isForwardZeroAvailable() override
void ReverseOne(ArrayView< const Base > tx, ArrayView< const Base > ty, ArrayView< Base > px, ArrayView< const Base > py) override
const std::string & getName() const override
bool isJacobianAvailable() override
bool isEquationHessianSparsityAvailable() override
bool isReverseTwoAvailable() override
std::vector< std::set< size_t > > HessianSparsitySet() override
void ForwardOne(ArrayView< const Base > tx, ArrayView< Base > ty) override
bool isSparseHessianAvailable() override
bool isForwardOneAvailable() override
bool isSparseReverseTwoAvailable() override
size_t Range() const override
number of dependent variables
bool addAtomicFunction(atomic_base< Base > &atomic) override
virtual const std::string & getName() const =0