1 #ifndef CPPAD_CG_FUNCTOR_GENERIC_MODEL_INCLUDED
2 #define CPPAD_CG_FUNCTOR_GENERIC_MODEL_INCLUDED
34 class FunctorGenericModel :
public GenericModel<Base> {
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++) {
106 const std::string& getName()
const override {
110 const std::vector<std::string>& getAtomicFunctionNames()
override {
114 bool addAtomicFunction(atomic_base<Base>& atomic)
override {
115 return addExternalFunction<atomic_base<Base>, AtomicExternalFunctionWrapper<Base> >
116 (atomic, atomic.atomic_name());
119 bool addExternalModel(GenericModel<Base>& atomic)
override {
120 return addExternalFunction<GenericModel<Base>, GenericModelExternalFunctionWrapper<Base> >
121 (atomic, atomic.getName());
125 bool isJacobianSparsityAvailable()
override {
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());
178 bool isHessianSparsityAvailable()
override {
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);
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")
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());
230 bool isEquationHessianSparsityAvailable()
override {
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);
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")
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());
294 bool isForwardZeroAvailable()
override {
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);
315 void ForwardZero(
const std::vector<const Base*> &x,
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]) {
360 bool isJacobianAvailable()
override {
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);
382 bool isHessianAvailable()
override {
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);
406 bool isForwardOneAvailable()
override {
407 return _forwardOne !=
nullptr;
410 void ForwardOne(ArrayView<const Base> tx,
411 ArrayView<Base> ty)
override {
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.")
425 bool isSparseForwardOneAvailable()
override {
426 return _forwardOneSparsity !=
nullptr && _sparseForwardOne !=
nullptr;
429 void ForwardOne(ArrayView<const Base> x,
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")
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];
467 bool isReverseOneAvailable()
override {
468 return _reverseOne !=
nullptr;
471 void ReverseOne(ArrayView<const Base> tx,
472 ArrayView<const Base> ty,
474 ArrayView<const Base> py)
override {
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.")
491 bool isSparseReverseOneAvailable()
override {
492 return _reverseOneSparsity !=
nullptr && _sparseReverseOne !=
nullptr;
495 void ReverseOne(ArrayView<const Base> x,
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];
533 bool isReverseTwoAvailable()
override {
534 return _reverseTwo !=
nullptr;
537 void ReverseTwo(ArrayView<const Base> tx,
538 ArrayView<const Base> ty,
540 ArrayView<const Base> py)
override {
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.")
559 bool isSparseReverseTwoAvailable()
override {
560 return _sparseReverseTwo !=
nullptr;
563 void ReverseTwo(ArrayView<const Base> x,
564 size_t tx1Nnz,
const size_t idx[],
const Base tx1[],
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")
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];
605 bool isSparseJacobianAvailable()
override {
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);
722 bool isSparseHessianAvailable()
override {
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);
823 ArrayView<const Base> w,
824 ArrayView<Base> hess,
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>;