CppADCodeGen  HEAD
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:
30  CGAtomicGenericModel<Base>* _atomic;
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 GenericModel(GenericModel&& other) noexcept :
41  _atomic(other._atomic),
42  _evalAtomicForwardOne4CppAD(other._evalAtomicForwardOne4CppAD) {
43  other._atomic = nullptr;
44  }
45 
46  inline virtual ~GenericModel() {
47  delete _atomic;
48  }
49 
55  virtual const std::string& getName() const = 0;
56 
57 
63  virtual bool isJacobianSparsityAvailable() = 0;
64 
65  // Jacobian sparsity
66  virtual std::vector<std::set<size_t> > JacobianSparsitySet() = 0;
67  virtual std::vector<bool> JacobianSparsityBool() = 0;
68  virtual void JacobianSparsity(std::vector<size_t>& equations,
69  std::vector<size_t>& variables) = 0;
70 
78  virtual bool isHessianSparsityAvailable() = 0;
79 
86  virtual std::vector<std::set<size_t> > HessianSparsitySet() = 0;
87  virtual std::vector<bool> HessianSparsityBool() = 0;
88  virtual void HessianSparsity(std::vector<size_t>& rows,
89  std::vector<size_t>& cols) = 0;
90 
98  virtual bool isEquationHessianSparsityAvailable() = 0;
99 
106  virtual std::vector<std::set<size_t> > HessianSparsitySet(size_t i) = 0;
107 
111  virtual std::vector<bool> HessianSparsityBool(size_t i) = 0;
112 
120  virtual void HessianSparsity(size_t i,
121  std::vector<size_t>& rows,
122  std::vector<size_t>& cols) = 0;
123 
129  virtual size_t Domain() const = 0;
130 
136  virtual size_t Range() const = 0;
137 
145  virtual const std::vector<std::string>& getAtomicFunctionNames() = 0;
146 
158  virtual bool addAtomicFunction(atomic_base<Base>& atomic) = 0;
159 
172  virtual bool addExternalModel(GenericModel<Base>& atomic) = 0;
173 
182  inline void setAtomicEvalForwardOne4CppAD(bool evalForwardOne4CppAD) {
183  _evalAtomicForwardOne4CppAD = evalForwardOne4CppAD;
184  }
185 
186  inline bool isAtomicEvalForwardOne4CppAD() const {
187  return _evalAtomicForwardOne4CppAD;
188  }
189 
190  /***********************************************************************
191  * Forward zero
192  **********************************************************************/
193 
200  virtual bool isForwardZeroAvailable() = 0;
201 
211  template<typename VectorBase>
212  inline VectorBase ForwardZero(const VectorBase& x) {
213  VectorBase dep(Range());
214  this->ForwardZero(ArrayView<const Base>(&x[0], x.size()),
215  ArrayView<Base>(&dep[0], dep.size()));
216  return dep;
217  }
218 
230  virtual void ForwardZero(const CppAD::vector<bool>& vx,
233  ArrayView<Base> ty) = 0;
234 
244  template<typename VectorBase>
245  inline void ForwardZero(const VectorBase& x,
246  VectorBase& dep) {
247  dep.resize(Range());
248  this->ForwardZero(ArrayView<const Base>(&x[0], x.size()),
249  ArrayView<Base>(&dep[0], dep.size()));
250  }
251 
255  virtual void ForwardZero(ArrayView<const Base> x,
256  ArrayView<Base> dep) = 0;
257 
268  virtual void ForwardZero(const std::vector<const Base*> &x,
269  ArrayView<Base> dep) = 0;
270 
271  /***********************************************************************
272  * Dense Jacobian
273  **********************************************************************/
274 
281  virtual bool isJacobianAvailable() = 0;
282 
292  template<typename VectorBase>
293  inline VectorBase Jacobian(const VectorBase& x) {
294  VectorBase jac(Range() * Domain());
295  Jacobian(ArrayView<const Base>(&x[0], x.size()),
296  ArrayView<Base>(&jac[0], jac.size()));
297  return jac;
298  }
299 
309  template<typename VectorBase>
310  inline void Jacobian(const VectorBase& x,
311  VectorBase& jac) {
312  jac.resize(Range() * Domain());
313  Jacobian(ArrayView<const Base>(&x[0], x.size()),
314  ArrayView<Base>(&jac[0], jac.size()));
315  }
316 
320  virtual void Jacobian(ArrayView<const Base> x,
321  ArrayView<Base> jac) = 0;
322 
323  /***********************************************************************
324  * Dense Hessian
325  **********************************************************************/
326 
334  virtual bool isHessianAvailable() = 0;
335 
336 
346  template<typename VectorBase>
347  inline VectorBase Hessian(const VectorBase& x,
348  const VectorBase& w) {
349  VectorBase hess(Domain() * Domain());
350  this->Hessian(ArrayView<const Base>(&x[0], x.size()),
351  ArrayView<const Base>(&w[0], w.size()),
352  ArrayView<Base>(&hess[0], hess.size()));
353  return hess;
354  }
355 
365  template<typename VectorBase>
366  inline void Hessian(const VectorBase& x,
367  const VectorBase& w,
368  VectorBase& hess) {
369  hess.resize(Domain() * Domain());
370  this->Hessian(ArrayView<const Base>(&x[0], x.size()),
371  ArrayView<const Base>(&w[0], w.size()),
372  ArrayView<Base>(&hess[0], hess.size()));
373  }
374 
383  template<typename VectorBase>
384  inline VectorBase Hessian(const VectorBase& x,
385  size_t i) {
386  CPPADCG_ASSERT_KNOWN(i < Range(), "Invalid equation index")
387 
388  VectorBase w(Range());
389  w[i] = 1.0;
390  VectorBase hess(Domain() * Domain());
391  this->Hessian(ArrayView<const Base>(&x[0], x.size()),
392  ArrayView<const Base>(&w[0], w.size()),
393  ArrayView<Base>(&hess[0], hess.size()));
394  return hess;
395  }
396 
400  virtual void Hessian(ArrayView<const Base> x,
402  ArrayView<Base> hess) = 0;
403 
404  /***********************************************************************
405  * Forward one
406  **********************************************************************/
407 
415  virtual bool isForwardOneAvailable() = 0;
416 
428  template<typename VectorBase>
429  inline VectorBase ForwardOne(const VectorBase& tx) {
430  size_t m = Range();
431  const size_t k = 1;
432  VectorBase ty((k + 1) * m);
433 
434  this->ForwardOne(ArrayView<const Base>(&tx[0], tx.size()),
435  ArrayView<Base>(&ty[0], ty.size()));
436 
437  VectorBase dy(m);
438  for (size_t i = 0; i < m; i++) {
439  dy[i] = ty[i * (k + 1) + k];
440  }
441 
442  return dy;
443  }
444 
456  virtual void ForwardOne(ArrayView<const Base> tx,
457  ArrayView<Base> ty) = 0;
458 
466  virtual bool isSparseForwardOneAvailable() = 0;
467 
486  virtual void ForwardOne(ArrayView<const Base> x,
487  size_t tx1Nnz, const size_t idx[], const Base tx1[],
488  ArrayView<Base> ty1) = 0;
489 
490  /***********************************************************************
491  * Reverse one
492  **********************************************************************/
493 
501  virtual bool isReverseOneAvailable() = 0;
502 
510  template<typename VectorBase>
511  inline VectorBase ReverseOne(const VectorBase& tx,
512  const VectorBase& ty,
513  const VectorBase& py) {
514  const size_t k = 0;
515  VectorBase px((k + 1) * Domain());
516  this->ReverseOne(tx, ty, px, py);
517  return px;
518  }
519 
527  template<typename VectorBase>
528  inline void ReverseOne(const VectorBase& tx,
529  const VectorBase& ty,
530  VectorBase& px,
531  const VectorBase& py) {
532  this->ReverseOne(ArrayView<const Base>(&tx[0], tx.size()),
533  ArrayView<const Base>(&ty[0], ty.size()),
534  ArrayView<Base>(&px[0], px.size()),
535  ArrayView<const Base>(&py[0], py.size()));
536  }
537 
545  virtual bool isSparseReverseOneAvailable() = 0;
546 
554  virtual void ReverseOne(ArrayView<const Base> tx,
556  ArrayView<Base> px,
557  ArrayView<const Base> py) = 0;
558 
576  virtual void ReverseOne(ArrayView<const Base> x,
577  ArrayView<Base> px,
578  size_t pyNnz, const size_t idx[], const Base py[]) = 0;
579 
580  /***********************************************************************
581  * Reverse two
582  **********************************************************************/
583 
591  virtual bool isReverseTwoAvailable() = 0;
592 
601  template<typename VectorBase>
602  inline VectorBase ReverseTwo(const VectorBase& tx,
603  const VectorBase& ty,
604  const VectorBase& py) {
605  const size_t k = 1;
606  VectorBase px((k + 1) * Domain());
607  this->ReverseTwo(tx, ty, px, py);
608  return px;
609  }
610 
619  template<typename VectorBase>
620  inline void ReverseTwo(const VectorBase& tx,
621  const VectorBase& ty,
622  VectorBase& px,
623  const VectorBase& py) {
624  this->ReverseTwo(ArrayView<const Base>(&tx[0], tx.size()),
625  ArrayView<const Base>(&ty[0], ty.size()),
626  ArrayView<Base>(&px[0], px.size()),
627  ArrayView<const Base>(&py[0], py.size()));
628  }
629 
637  virtual bool isSparseReverseTwoAvailable() = 0;
638 
647  virtual void ReverseTwo(ArrayView<const Base> tx,
649  ArrayView<Base> px,
650  ArrayView<const Base> py) = 0;
670  virtual void ReverseTwo(ArrayView<const Base> x,
671  size_t tx1Nnz, const size_t idx[], const Base tx1[],
672  ArrayView<Base> px2,
673  ArrayView<const Base> py2) = 0;
674 
675  /***********************************************************************
676  * Sparse Jacobians
677  **********************************************************************/
678 
685  virtual bool isSparseJacobianAvailable() = 0;
686 
696  template<typename VectorBase>
697  inline VectorBase SparseJacobian(const VectorBase& x) {
698  VectorBase jac(Range() * Domain());
699  SparseJacobian(ArrayView<const Base>(&x[0], x.size()),
700  ArrayView<Base>(&jac[0], jac.size()));
701  return jac;
702  }
703 
713  template<typename VectorBase>
714  inline void SparseJacobian(const VectorBase& x,
715  VectorBase& jac) {
716  jac.resize(Range() * Domain());
717  SparseJacobian(ArrayView<const Base>(&x[0], x.size()),
718  ArrayView<Base>(&jac[0], jac.size()));
719  }
720 
730  virtual void SparseJacobian(ArrayView<const Base> x,
731  ArrayView<Base> jac) = 0;
732 
742  virtual void SparseJacobian(const std::vector<Base> &x,
743  std::vector<Base>& jac,
744  std::vector<size_t>& row,
745  std::vector<size_t>& col) = 0;
746 
750  virtual void SparseJacobian(ArrayView<const Base> x,
751  ArrayView<Base> jac,
752  size_t const** row,
753  size_t const** col) = 0;
754 
767  virtual void SparseJacobian(const std::vector<const Base*>& x,
768  ArrayView<Base> jac,
769  size_t const** row,
770  size_t const** col) = 0;
771 
772  /***********************************************************************
773  * Sparse Hessians
774  **********************************************************************/
775 
783  virtual bool isSparseHessianAvailable() = 0;
784 
794  template<typename VectorBase>
795  inline VectorBase SparseHessian(const VectorBase& x,
796  const VectorBase& w) {
797  VectorBase hess(Domain() * Domain());
798  SparseHessian(ArrayView<const Base>(&x[0], x.size()),
799  ArrayView<const Base>(&w[0], w.size()),
800  ArrayView<Base>(&hess[0], hess.size()));
801  return hess;
802  }
803 
813  template<typename VectorBase>
814  inline void SparseHessian(const VectorBase& x,
815  const VectorBase& w,
816  VectorBase& hess) {
817  hess.resize(Domain() * Domain());
818  SparseHessian(ArrayView<const Base>(&x[0], x.size()),
819  ArrayView<const Base>(&w[0], w.size()),
820  ArrayView<Base>(&hess[0], hess.size()));
821  }
822 
826  virtual void SparseHessian(ArrayView<const Base> x,
828  ArrayView<Base> hess) = 0;
829 
843  virtual void SparseHessian(const std::vector<Base>& x,
844  const std::vector<Base>& w,
845  std::vector<Base>& hess,
846  std::vector<size_t>& row,
847  std::vector<size_t>& col) = 0;
848 
852  virtual void SparseHessian(ArrayView<const Base> x,
854  ArrayView<Base> hess,
855  size_t const** row,
856  size_t const** col) = 0;
857 
876  virtual void SparseHessian(const std::vector<const Base*>& x,
878  ArrayView<Base> hess,
879  size_t const** row,
880  size_t const** col) = 0;
881 
890  if (_atomic == nullptr) {
891  _atomic = new CGAtomicGenericModel<Base>(*this);
892  }
893  return *_atomic;
894  }
895 };
896 
897 } // END cg namespace
898 } // END CppAD namespace
899 
900 #endif
VectorBase Hessian(const VectorBase &x, size_t i)
VectorBase ForwardZero(const VectorBase &x)
virtual bool addAtomicFunction(atomic_base< Base > &atomic)=0
virtual bool isReverseTwoAvailable()=0
virtual const std::vector< std::string > & getAtomicFunctionNames()=0
virtual bool addExternalModel(GenericModel< Base > &atomic)=0
void SparseHessian(const VectorBase &x, const VectorBase &w, VectorBase &hess)
VectorBase ReverseTwo(const VectorBase &tx, const VectorBase &ty, const VectorBase &py)
virtual bool isForwardOneAvailable()=0
virtual bool isSparseHessianAvailable()=0
VectorBase Hessian(const VectorBase &x, const VectorBase &w)
VectorBase SparseHessian(const VectorBase &x, const VectorBase &w)
virtual bool isJacobianSparsityAvailable()=0
void Jacobian(const VectorBase &x, VectorBase &jac)
virtual bool isSparseReverseTwoAvailable()=0
virtual bool isJacobianAvailable()=0
virtual bool isForwardZeroAvailable()=0
VectorBase SparseJacobian(const VectorBase &x)
VectorBase ForwardOne(const VectorBase &tx)
virtual bool isHessianSparsityAvailable()=0
void SparseJacobian(const VectorBase &x, VectorBase &jac)
void Hessian(const VectorBase &x, const VectorBase &w, VectorBase &hess)
VectorBase ReverseOne(const VectorBase &tx, const VectorBase &ty, const VectorBase &py)
virtual std::vector< std::set< size_t > > HessianSparsitySet()=0
void ReverseOne(const VectorBase &tx, const VectorBase &ty, VectorBase &px, const VectorBase &py)
virtual bool isHessianAvailable()=0
virtual bool isReverseOneAvailable()=0
virtual bool isSparseJacobianAvailable()=0
virtual bool isSparseReverseOneAvailable()=0
virtual size_t Range() const =0
virtual const std::string & getName() const =0
void ReverseTwo(const VectorBase &tx, const VectorBase &ty, VectorBase &px, const VectorBase &py)
virtual CGAtomicGenericModel< Base > & asAtomic()
virtual size_t Domain() const =0
void ForwardZero(const VectorBase &x, VectorBase &dep)
VectorBase Jacobian(const VectorBase &x)
virtual bool isEquationHessianSparsityAvailable()=0
virtual bool isSparseForwardOneAvailable()=0
void setAtomicEvalForwardOne4CppAD(bool evalForwardOne4CppAD)