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