CppADCodeGen  HEAD
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 
103  // S(x) = f'(x) * R
104  CppAD::cg::multMatrixMatrixSparsity(jacSparsity, r, s, m, n, q);
105 
106  return true;
107  }
108 
109  bool rev_sparse_jac(size_t q,
110  const CppAD::vector<std::set<size_t> >& rT,
111  CppAD::vector<std::set<size_t> >& sT,
112  const CppAD::vector<Base>& x) override {
113  return rev_sparse_jac(q, rT, sT);
114  }
115 
116  bool rev_sparse_jac(size_t q,
117  const CppAD::vector<std::set<size_t> >& rT,
118  CppAD::vector<std::set<size_t> >& sT) override {
119  size_t n = model_.Domain();
120  size_t m = model_.Range();
121  for (size_t i = 0; i < n; i++) {
122  sT[i].clear();
123  }
124 
125  const std::vector<std::set<size_t> > jacSparsity = model_.JacobianSparsitySet();
126 
127  // S(x)^T = ( R * f'(x) )^T = f'(x)^T * R^T
128  CppAD::cg::multMatrixTransMatrixSparsity(jacSparsity, rT, sT, m, n, q);
129 
130  return true;
131  }
132 
133  bool rev_sparse_hes(const CppAD::vector<bool>& vx,
134  const CppAD::vector<bool>& s,
136  size_t q,
137  const CppAD::vector<std::set<size_t> >& r,
138  const CppAD::vector<std::set<size_t> >& u,
139  CppAD::vector<std::set<size_t> >& v,
140  const CppAD::vector<Base>& x) override {
141  return rev_sparse_hes(vx, s, t, q, r, u, v);
142  }
143 
145  const CppAD::vector<bool>& s,
147  size_t q,
148  const CppAD::vector<std::set<size_t> >& r,
149  const CppAD::vector<std::set<size_t> >& u,
150  CppAD::vector<std::set<size_t> >& v) override {
151  size_t n = model_.Domain();
152  size_t m = model_.Range();
153 
154  for (size_t i = 0; i < n; i++) {
155  v[i].clear();
156  }
157 
158  const std::vector<std::set<size_t> > jacSparsity = model_.JacobianSparsitySet();
159 
163  // f'^T(x) U(x)
164  CppAD::cg::multMatrixTransMatrixSparsity(jacSparsity, u, v, m, n, q);
165 
166  // Sum( s(x)i f''(x) R )
167  bool allSelected = true;
168  for (size_t i = 0; i < m; i++) {
169  if (!s[i]) {
170  allSelected = false;
171  break;
172  }
173  }
174 
175  if (allSelected) {
176  // TODO: use reverseTwo sparsity instead of the HessianSparsity (they can be different!!!)
177  std::vector<std::set<size_t> > sparsitySF2R = model_.HessianSparsitySet(); // f''(x)
178  sparsitySF2R.resize(n);
179  CppAD::cg::multMatrixMatrixSparsity(sparsitySF2R, r, v, n, n, q); // f''(x) * R
180  } else {
181  std::vector<std::set<size_t> > sparsitySF2R(n);
182  for (size_t i = 0; i < m; i++) {
183  if (s[i]) {
184  CppAD::cg::addMatrixSparsity(model_.HessianSparsitySet(i), sparsitySF2R); // f''_i(x)
185  }
186  }
187  CppAD::cg::multMatrixMatrixSparsity(sparsitySF2R, r, v, n, n, q); // f''(x) * R
188  }
189 
193  for (size_t i = 0; i < m; i++) {
194  if (s[i]) {
195  for (size_t j : jacSparsity[i]) {
196  t[j] = true;
197  }
198  }
199  }
200 
201  return true;
202  }
203 
204 };
205 
206 } // END cg namespace
207 } // END CppAD namespace
208 
209 #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