CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
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
19namespace CppAD {
20namespace cg {
21
27template <class Base>
28class CGAtomicGenericModel : public atomic_base<Base> {
29protected:
30 GenericModel<Base>& model_;
31public:
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
CGAtomicGenericModel(GenericModel< Base > &model)
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
virtual size_t Range() const =0
VectorBase ForwardZero(const VectorBase &x)
VectorBase ReverseTwo(const VectorBase &tx, const VectorBase &ty, const VectorBase &py)
VectorBase ReverseOne(const VectorBase &tx, const VectorBase &ty, const VectorBase &py)
virtual size_t Domain() const =0
virtual std::vector< std::set< size_t > > HessianSparsitySet()=0
VectorBase ForwardOne(const VectorBase &tx)