CppADCodeGen  2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
generic_model.hpp
1 #ifndef CPPAD_CG_GENERIC_MODEL_INCLUDED
2 #define CPPAD_CG_GENERIC_MODEL_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2012 Ciengis
6  * Copyright (C) 2020 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 namespace CppAD {
20 namespace cg {
21 
27 template<class Base>
28 class GenericModel {
29 protected:
31  // whether or not to evaluate forward mode of atomics during a reverse sweep
32  bool _evalAtomicForwardOne4CppAD;
33 public:
34 
35  GenericModel() :
36  _atomic(nullptr),
37  _evalAtomicForwardOne4CppAD(true) {
38  }
39 
40  inline virtual ~GenericModel() {
41  delete _atomic;
42  }
43 
49  virtual const std::string& getName() const = 0;
50 
51 
57  virtual bool isJacobianSparsityAvailable() = 0;
58 
59  // Jacobian sparsity
60  virtual std::vector<std::set<size_t> > JacobianSparsitySet() = 0;
61  virtual std::vector<bool> JacobianSparsityBool() = 0;
62  virtual void JacobianSparsity(std::vector<size_t>& equations,
63  std::vector<size_t>& variables) = 0;
64 
72  virtual bool isHessianSparsityAvailable() = 0;
73 
80  virtual std::vector<std::set<size_t> > HessianSparsitySet() = 0;
81  virtual std::vector<bool> HessianSparsityBool() = 0;
82  virtual void HessianSparsity(std::vector<size_t>& rows,
83  std::vector<size_t>& cols) = 0;
84 
93 
100  virtual std::vector<std::set<size_t> > HessianSparsitySet(size_t i) = 0;
101  virtual std::vector<bool> HessianSparsityBool(size_t i) = 0;
102  virtual void HessianSparsity(size_t i,
103  std::vector<size_t>& rows,
104  std::vector<size_t>& cols) = 0;
105 
111  virtual size_t Domain() const = 0;
112 
118  virtual size_t Range() const = 0;
119 
127  virtual const std::vector<std::string>& getAtomicFunctionNames() = 0;
128 
140  virtual bool addAtomicFunction(atomic_base<Base>& atomic) = 0;
141 
154  virtual bool addExternalModel(GenericModel<Base>& atomic) = 0;
155 
164  inline void setAtomicEvalForwardOne4CppAD(bool evalForwardOne4CppAD) {
165  _evalAtomicForwardOne4CppAD = evalForwardOne4CppAD;
166  }
167 
168  inline bool isAtomicEvalForwardOne4CppAD() const {
169  return _evalAtomicForwardOne4CppAD;
170  }
171 
172  /***********************************************************************
173  * Forward zero
174  **********************************************************************/
175 
182  virtual bool isForwardZeroAvailable() = 0;
183 
193  template<typename VectorBase>
194  inline VectorBase ForwardZero(const VectorBase& x) {
195  VectorBase dep(Range());
196  this->ForwardZero(ArrayView<const Base>(&x[0], x.size()),
197  ArrayView<Base>(&dep[0], dep.size()));
198  return dep;
199  }
200 
201  virtual void ForwardZero(const CppAD::vector<bool>& vx,
204  ArrayView<Base> ty) = 0;
205 
215  template<typename VectorBase>
216  inline void ForwardZero(const VectorBase& x,
217  VectorBase& dep) {
218  dep.resize(Range());
219  this->ForwardZero(ArrayView<const Base>(&x[0], x.size()),
220  ArrayView<Base>(&dep[0], dep.size()));
221  }
222 
223  virtual void ForwardZero(ArrayView<const Base> x,
224  ArrayView<Base> dep) = 0;
225 
236  virtual void ForwardZero(const std::vector<const Base*> &x,
237  ArrayView<Base> dep) = 0;
238 
239  /***********************************************************************
240  * Dense Jacobian
241  **********************************************************************/
242 
249  virtual bool isJacobianAvailable() = 0;
250 
251  template<typename VectorBase>
252  inline VectorBase Jacobian(const VectorBase& x) {
253  VectorBase jac(Range() * Domain());
254  Jacobian(ArrayView<const Base>(&x[0], x.size()),
255  ArrayView<Base>(&jac[0], jac.size()));
256  return jac;
257  }
258 
259  template<typename VectorBase>
260  inline void Jacobian(const VectorBase& x,
261  VectorBase& jac) {
262  jac.resize(Range() * Domain());
263  Jacobian(ArrayView<const Base>(&x[0], x.size()),
264  ArrayView<Base>(&jac[0], jac.size()));
265  }
266 
267  virtual void Jacobian(ArrayView<const Base> x,
268  ArrayView<Base> jac) = 0;
269 
270  /***********************************************************************
271  * Dense Hessian
272  **********************************************************************/
273 
281  virtual bool isHessianAvailable() = 0;
282 
283  template<typename VectorBase>
284  inline VectorBase Hessian(const VectorBase& x,
285  const VectorBase& w) {
286  VectorBase hess(Domain() * Domain());
287  this->Hessian(ArrayView<const Base>(&x[0], x.size()),
288  ArrayView<const Base>(&w[0], w.size()),
289  ArrayView<Base>(&hess[0], hess.size()));
290  return hess;
291  }
292 
293  template<typename VectorBase>
294  inline void Hessian(const VectorBase& x,
295  const VectorBase& w,
296  VectorBase& hess) {
297  hess.resize(Domain() * Domain());
298  this->Hessian(ArrayView<const Base>(&x[0], x.size()),
299  ArrayView<const Base>(&w[0], w.size()),
300  ArrayView<Base>(&hess[0], hess.size()));
301  }
302 
304 
305  template<typename VectorBase>
306  inline VectorBase Hessian(const VectorBase& x,
307  size_t i) {
308  CPPADCG_ASSERT_KNOWN(i < Range(), "Invalid equation index")
309 
310  VectorBase w(Range());
311  w[i] = 1.0;
312  VectorBase hess(Domain() * Domain());
313  this->Hessian(ArrayView<const Base>(&x[0], x.size()),
314  ArrayView<const Base>(&w[0], w.size()),
315  ArrayView<Base>(&hess[0], hess.size()));
316  return hess;
317  }
318 
319  virtual void Hessian(ArrayView<const Base> x,
321  ArrayView<Base> hess) = 0;
322 
323  /***********************************************************************
324  * Forward one
325  **********************************************************************/
326 
334  virtual bool isForwardOneAvailable() = 0;
335 
347  template<typename VectorBase>
348  inline VectorBase ForwardOne(const VectorBase& tx) {
349  size_t m = Range();
350  const size_t k = 1;
351  VectorBase ty((k + 1) * m);
352 
353  this->ForwardOne(ArrayView<const Base>(&tx[0], tx.size()),
354  ArrayView<Base>(&ty[0], ty.size()));
355 
356  VectorBase dy(m);
357  for (size_t i = 0; i < m; i++) {
358  dy[i] = ty[i * (k + 1) + k];
359  }
360 
361  return dy;
362  }
363 
376  ArrayView<Base> ty) = 0;
377 
385  virtual bool isSparseForwardOneAvailable() = 0;
386 
406  size_t tx1Nnz, const size_t idx[], const Base tx1[],
407  ArrayView<Base> ty1) = 0;
408 
409  /***********************************************************************
410  * Reverse one
411  **********************************************************************/
412 
420  virtual bool isReverseOneAvailable() = 0;
421 
429  template<typename VectorBase>
430  inline VectorBase ReverseOne(const VectorBase& tx,
431  const VectorBase& ty,
432  const VectorBase& py) {
433  const size_t k = 0;
434  VectorBase px((k + 1) * Domain());
435  this->ReverseOne(tx, ty, px, py);
436  return px;
437  }
438 
446  template<typename VectorBase>
447  inline void ReverseOne(const VectorBase& tx,
448  const VectorBase& ty,
449  VectorBase& px,
450  const VectorBase& py) {
451  this->ReverseOne(ArrayView<const Base>(&tx[0], tx.size()),
452  ArrayView<const Base>(&ty[0], ty.size()),
453  ArrayView<Base>(&px[0], px.size()),
454  ArrayView<const Base>(&py[0], py.size()));
455  }
456 
464  virtual bool isSparseReverseOneAvailable() = 0;
465 
475  ArrayView<Base> px,
476  ArrayView<const Base> py) = 0;
477 
496  ArrayView<Base> px,
497  size_t pyNnz, const size_t idx[], const Base py[]) = 0;
498 
499  /***********************************************************************
500  * Reverse two
501  **********************************************************************/
502 
510  virtual bool isReverseTwoAvailable() = 0;
511 
520  template<typename VectorBase>
521  inline VectorBase ReverseTwo(const VectorBase& tx,
522  const VectorBase& ty,
523  const VectorBase& py) {
524  const size_t k = 1;
525  VectorBase px((k + 1) * Domain());
526  this->ReverseTwo(tx, ty, px, py);
527  return px;
528  }
529 
538  template<typename VectorBase>
539  inline void ReverseTwo(const VectorBase& tx,
540  const VectorBase& ty,
541  VectorBase& px,
542  const VectorBase& py) {
543  this->ReverseTwo(ArrayView<const Base>(&tx[0], tx.size()),
544  ArrayView<const Base>(&ty[0], ty.size()),
545  ArrayView<Base>(&px[0], px.size()),
546  ArrayView<const Base>(&py[0], py.size()));
547  }
548 
556  virtual bool isSparseReverseTwoAvailable() = 0;
557 
568  ArrayView<Base> px,
569  ArrayView<const Base> py) = 0;
590  size_t tx1Nnz, const size_t idx[], const Base tx1[],
591  ArrayView<Base> px2,
592  ArrayView<const Base> py2) = 0;
593 
594  /***********************************************************************
595  * Sparse Jacobians
596  **********************************************************************/
597 
604  virtual bool isSparseJacobianAvailable() = 0;
605 
615  template<typename VectorBase>
616  inline VectorBase SparseJacobian(const VectorBase& x) {
617  VectorBase jac(Range() * Domain());
618  SparseJacobian(ArrayView<const Base>(&x[0], x.size()),
619  ArrayView<Base>(&jac[0], jac.size()));
620  return jac;
621  }
622 
632  template<typename VectorBase>
633  inline void SparseJacobian(const VectorBase& x,
634  VectorBase& jac) {
635  jac.resize(Range() * Domain());
636  SparseJacobian(ArrayView<const Base>(&x[0], x.size()),
637  ArrayView<Base>(&jac[0], jac.size()));
638  }
639 
650  ArrayView<Base> jac) = 0;
651 
652  virtual void SparseJacobian(const std::vector<Base> &x,
653  std::vector<Base>& jac,
654  std::vector<size_t>& row,
655  std::vector<size_t>& col) = 0;
656 
657  virtual void SparseJacobian(ArrayView<const Base> x,
658  ArrayView<Base> jac,
659  size_t const** row,
660  size_t const** col) = 0;
661 
674  virtual void SparseJacobian(const std::vector<const Base*>& x,
675  ArrayView<Base> jac,
676  size_t const** row,
677  size_t const** col) = 0;
678 
679  /***********************************************************************
680  * Sparse Hessians
681  **********************************************************************/
682 
690  virtual bool isSparseHessianAvailable() = 0;
691 
692  template<typename VectorBase>
693  inline VectorBase SparseHessian(const VectorBase& x,
694  const VectorBase& w) {
695  VectorBase hess(Domain() * Domain());
696  SparseHessian(ArrayView<const Base>(&x[0], x.size()),
697  ArrayView<const Base>(&w[0], w.size()),
698  ArrayView<Base>(&hess[0], hess.size()));
699  return hess;
700  }
701 
702  template<typename VectorBase>
703  inline void SparseHessian(const VectorBase& x,
704  const VectorBase& w,
705  VectorBase& hess) {
706  hess.resize(Domain() * Domain());
707  SparseHessian(ArrayView<const Base>(&x[0], x.size()),
708  ArrayView<const Base>(&w[0], w.size()),
709  ArrayView<Base>(&hess[0], hess.size()));
710  }
711 
712  virtual void SparseHessian(ArrayView<const Base> x,
713  ArrayView<const Base> w,
714  ArrayView<Base> hess) = 0;
715 
716  virtual void SparseHessian(const std::vector<Base> &x,
717  const std::vector<Base> &w,
718  std::vector<Base>& hess,
719  std::vector<size_t>& row,
720  std::vector<size_t>& col) = 0;
721 
722  virtual void SparseHessian(ArrayView<const Base> x,
723  ArrayView<const Base> w,
724  ArrayView<Base> hess,
725  size_t const** row,
726  size_t const** col) = 0;
727 
742  virtual void SparseHessian(const std::vector<const Base*>& x,
744  ArrayView<Base> hess,
745  size_t const** row,
746  size_t const** col) = 0;
747 
756  if (_atomic == nullptr) {
757  _atomic = new CGAtomicGenericModel<Base>(*this);
758  }
759  return *_atomic;
760  }
761 };
762 
763 } // END cg namespace
764 } // END CppAD namespace
765 
766 #endif
virtual size_t Range() const =0
virtual std::vector< std::set< size_t > > HessianSparsitySet()=0
VectorBase ForwardZero(const VectorBase &x)
virtual void SparseHessian(const std::vector< const Base * > &x, ArrayView< const Base > w, ArrayView< Base > hess, size_t const **row, size_t const **col)=0
VectorBase Hessian(const VectorBase &x, size_t i)
calculate Hessian for one component of f
void setAtomicEvalForwardOne4CppAD(bool evalForwardOne4CppAD)
virtual bool isReverseOneAvailable()=0
virtual bool isJacobianSparsityAvailable()=0
virtual void ReverseTwo(ArrayView< const Base > x, size_t tx1Nnz, const size_t idx[], const Base tx1[], ArrayView< Base > px2, ArrayView< const Base > py2)=0
virtual const std::vector< std::string > & getAtomicFunctionNames()=0
virtual CGAtomicGenericModel< Base > & asAtomic()
VectorBase ReverseTwo(const VectorBase &tx, const VectorBase &ty, const VectorBase &py)
void ReverseTwo(const VectorBase &tx, const VectorBase &ty, VectorBase &px, const VectorBase &py)
VectorBase ReverseOne(const VectorBase &tx, const VectorBase &ty, const VectorBase &py)
virtual void SparseJacobian(const std::vector< const Base * > &x, ArrayView< Base > jac, size_t const **row, size_t const **col)=0
virtual bool isSparseReverseOneAvailable()=0
virtual std::vector< std::set< size_t > > HessianSparsitySet(size_t i)=0
virtual bool isForwardZeroAvailable()=0
virtual bool isSparseJacobianAvailable()=0
virtual void ReverseOne(ArrayView< const Base > tx, ArrayView< const Base > ty, ArrayView< Base > px, ArrayView< const Base > py)=0
virtual size_t Domain() const =0
virtual void ForwardOne(ArrayView< const Base > x, size_t tx1Nnz, const size_t idx[], const Base tx1[], ArrayView< Base > ty1)=0
virtual bool isJacobianAvailable()=0
virtual bool addExternalModel(GenericModel< Base > &atomic)=0
virtual bool isSparseForwardOneAvailable()=0
virtual void ReverseOne(ArrayView< const Base > x, ArrayView< Base > px, size_t pyNnz, const size_t idx[], const Base py[])=0
virtual bool isEquationHessianSparsityAvailable()=0
virtual const std::string & getName() const =0
VectorBase SparseJacobian(const VectorBase &x)
virtual bool isHessianSparsityAvailable()=0
virtual void SparseJacobian(ArrayView< const Base > x, ArrayView< Base > jac)=0
virtual bool isSparseReverseTwoAvailable()=0
virtual bool isReverseTwoAvailable()=0
virtual bool addAtomicFunction(atomic_base< Base > &atomic)=0
void ReverseOne(const VectorBase &tx, const VectorBase &ty, VectorBase &px, const VectorBase &py)
void ForwardZero(const VectorBase &x, VectorBase &dep)
virtual bool isSparseHessianAvailable()=0
virtual bool isHessianAvailable()=0
virtual void ForwardOne(ArrayView< const Base > tx, ArrayView< Base > ty)=0
virtual void ReverseTwo(ArrayView< const Base > tx, ArrayView< const Base > ty, ArrayView< Base > px, ArrayView< const Base > py)=0
virtual void ForwardZero(const std::vector< const Base * > &x, ArrayView< Base > dep)=0
void SparseJacobian(const VectorBase &x, VectorBase &jac)
virtual bool isForwardOneAvailable()=0
VectorBase ForwardOne(const VectorBase &tx)