CppADCodeGen  2.3.0
A C++ Algorithmic Differentiation Package with Source Code Generation
atomic_generic_model.hpp
1 #ifndef CPPAD_CG_ATOMIC_GENERIC_MODEL_INCLUDED
2 #define CPPAD_CG_ATOMIC_GENERIC_MODEL_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2013 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 namespace CppAD {
20 namespace cg {
21 
27 template <class Base>
28 class CGAtomicGenericModel : public atomic_base<Base> {
29 protected:
30  GenericModel<Base>& model_;
31 public:
32 
40  atomic_base<Base>(model.getName()),
41  model_(model) {
42  this->option(CppAD::atomic_base<Base>::set_sparsity_enum);
43  }
44 
45  virtual ~CGAtomicGenericModel() = default;
46 
47  template <class ADVector>
48  void operator()(const ADVector& ax, ADVector& ay, size_t id = 0) {
49  this->atomic_base<Base>::operator()(ax, ay, id);
50  }
51 
52  bool forward(size_t q,
53  size_t p,
54  const CppAD::vector<bool>& vx,
56  const CppAD::vector<Base>& tx,
57  CppAD::vector<Base>& ty) override {
58  if (p == 0) {
59  model_.ForwardZero(vx, vy, tx, ty);
60  return true;
61  } else if (p == 1) {
62  model_.ForwardOne(tx, ty);
63  return true;
64  }
65 
66  return false;
67  }
68 
69  bool reverse(size_t p,
70  const CppAD::vector<Base>& tx,
71  const CppAD::vector<Base>& ty,
73  const CppAD::vector<Base>& py) override {
74  if (p == 0) {
75  model_.ReverseOne(tx, ty, px, py);
76  return true;
77  } else if (p == 1) {
78  model_.ReverseTwo(tx, ty, px, py);
79  return true;
80  }
81 
82  return false;
83  }
84 
85  bool for_sparse_jac(size_t q,
86  const CppAD::vector<std::set<size_t> >& r,
87  CppAD::vector<std::set<size_t> >& s,
88  const CppAD::vector<Base>& x) override {
89  return for_sparse_jac(q, r, s);
90  }
91 
92  bool for_sparse_jac(size_t q,
93  const CppAD::vector<std::set<size_t> >& r,
94  CppAD::vector<std::set<size_t> >& s) override {
95  size_t n = model_.Domain();
96  size_t m = model_.Range();
97  for (size_t i = 0; i < m; i++) {
98  s[i].clear();
99  }
100 
101  const std::vector<std::set<size_t> > jacSparsity = model_.JacobianSparsitySet();
102  CppAD::cg::multMatrixMatrixSparsity(jacSparsity, r, s, m, n, q);
103 
104  return true;
105  }
106 
107  bool rev_sparse_jac(size_t q,
108  const CppAD::vector<std::set<size_t> >& rT,
109  CppAD::vector<std::set<size_t> >& sT,
110  const CppAD::vector<Base>& x) override {
111  return rev_sparse_jac(q, rT, sT);
112  }
113 
114  bool rev_sparse_jac(size_t q,
115  const CppAD::vector<std::set<size_t> >& rT,
116  CppAD::vector<std::set<size_t> >& sT) override {
117  size_t n = model_.Domain();
118  size_t m = model_.Range();
119  for (size_t i = 0; i < n; i++) {
120  sT[i].clear();
121  }
122 
123  const std::vector<std::set<size_t> > jacSparsity = model_.JacobianSparsitySet();
124 
125  CppAD::cg::multMatrixMatrixSparsityTrans(rT, jacSparsity, sT, m, n, q);
126 
127  return true;
128  }
129 
130  bool rev_sparse_hes(const CppAD::vector<bool>& vx,
131  const CppAD::vector<bool>& s,
133  size_t q,
134  const CppAD::vector<std::set<size_t> >& r,
135  const CppAD::vector<std::set<size_t> >& u,
136  CppAD::vector<std::set<size_t> >& v,
137  const CppAD::vector<Base>& x) override {
138  return rev_sparse_hes(vx, s, t, q, r, u, v);
139  }
140 
142  const CppAD::vector<bool>& s,
144  size_t q,
145  const CppAD::vector<std::set<size_t> >& r,
146  const CppAD::vector<std::set<size_t> >& u,
147  CppAD::vector<std::set<size_t> >& v) override {
148  size_t n = model_.Domain();
149  size_t m = model_.Range();
150 
151  for (size_t i = 0; i < n; i++) {
152  v[i].clear();
153  }
154 
155  const std::vector<std::set<size_t> > jacSparsity = model_.JacobianSparsitySet();
156 
160  // f'^T(x) U(x)
161  CppAD::cg::multMatrixTransMatrixSparsity(jacSparsity, u, v, m, n, q);
162 
163  // Sum( s(x)i f''(x) R(x) )
164  bool allSelected = true;
165  for (size_t i = 0; i < m; i++) {
166  if (!s[i]) {
167  allSelected = false;
168  break;
169  }
170  }
171 
172  if (allSelected) {
173  // TODO: use reverseTwo sparsity instead of the HessianSparsity (they can be different!!!)
174  std::vector<std::set<size_t> > sparsitySF2R = model_.HessianSparsitySet(); // f''(x)
175  sparsitySF2R.resize(n);
176  CppAD::cg::multMatrixTransMatrixSparsity(sparsitySF2R, r, v, n, n, q); // f''^T * R
177  } else {
178  std::vector<std::set<size_t> > sparsitySF2R(n);
179  for (size_t i = 0; i < m; i++) {
180  if (s[i]) {
181  CppAD::cg::addMatrixSparsity(model_.HessianSparsitySet(i), sparsitySF2R); // f''_i(x)
182  }
183  }
184  CppAD::cg::multMatrixTransMatrixSparsity(sparsitySF2R, r, v, n, n, q); // f''^T * R
185  }
186 
190  for (size_t i = 0; i < m; i++) {
191  if (s[i]) {
192  for (size_t j : jacSparsity[i]) {
193  t[j] = true;
194  }
195  }
196  }
197 
198  return true;
199  }
200 
201 };
202 
203 } // END cg namespace
204 } // END CppAD namespace
205 
206 #endif
VectorBase ForwardZero(const VectorBase &x)
bool rev_sparse_hes(const CppAD::vector< bool > &vx, const CppAD::vector< bool > &s, CppAD::vector< bool > &t, size_t q, const CppAD::vector< std::set< size_t > > &r, const CppAD::vector< std::set< size_t > > &u, CppAD::vector< std::set< size_t > > &v) override
CGAtomicGenericModel(GenericModel< Base > &model)
VectorBase ReverseTwo(const VectorBase &tx, const VectorBase &ty, const VectorBase &py)
VectorBase ForwardOne(const VectorBase &tx)
VectorBase ReverseOne(const VectorBase &tx, const VectorBase &ty, const VectorBase &py)
virtual std::vector< std::set< size_t > > HessianSparsitySet()=0
virtual size_t Range() const =0
virtual size_t Domain() const =0