CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
sparsity.hpp
1#ifndef CPPAD_CG_SPARSITY_INCLUDED
2#define CPPAD_CG_SPARSITY_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2012 Ciengis
6 *
7 * CppADCodeGen is distributed under multiple licenses:
8 *
9 * - Eclipse Public License Version 1.0 (EPL1), and
10 * - GNU General Public License Version 3 (GPL3).
11 *
12 * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
13 * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
14 * ----------------------------------------------------------------------------
15 * Author: Joao Leal
16 */
17
18namespace CppAD {
19namespace cg {
20
21template<class VectorBool, class Base>
22inline VectorBool jacobianForwardSparsity(ADFun<Base>& fun) {
23 size_t n = fun.Domain();
24
25 VectorBool r(n * n);
26 for (size_t j = 0; j < n; j++) {
27 for (size_t k = 0; k < n; k++)
28 r[j * n + k] = false;
29 r[j * n + j] = true;
30 }
31 return fun.ForSparseJac(n, r);
32
33}
34
35template<class VectorBool, class Base>
36inline VectorBool jacobianReverseSparsity(ADFun<Base>& fun) {
37 size_t m = fun.Range();
38
39 VectorBool s(m * m);
40 for (size_t i = 0; i < m; i++) {
41 for (size_t k = 0; k < m; k++)
42 s[i * m + k] = false;
43 s[i * m + i] = true;
44 }
45 return fun.RevSparseJac(m, s);
46}
47
48template<class VectorSet, class Base>
49inline VectorSet jacobianForwardSparsitySet(ADFun<Base>& fun) {
50 size_t n = fun.Domain();
51
52 VectorSet r(n);
53 for (size_t i = 0; i < n; i++)
54 r[i].insert(i);
55
56 return fun.ForSparseJac(n, r);
57}
58
59template<class VectorSet, class Base>
60inline VectorSet jacobianReverseSparsitySet(ADFun<Base>& fun) {
61 size_t m = fun.Range();
62
63 VectorSet s_s(m);
64 for (size_t i = 0; i < m; i++)
65 s_s[i].insert(i);
66
67 return fun.RevSparseJac(m, s_s);
68}
69
76template<class VectorBool, class Base>
77inline VectorBool jacobianSparsity(ADFun<Base>& fun) {
78 size_t m = fun.Range();
79 size_t n = fun.Domain();
80
81 if (n <= m) {
82 // use forward mode
83 return jacobianForwardSparsity<VectorBool, Base> (fun);
84 } else {
85 // use reverse mode
86 return jacobianReverseSparsity<VectorBool, Base> (fun);
87 }
88}
89
96template<class VectorSet, class Base>
97inline VectorSet jacobianSparsitySet(ADFun<Base>& fun) {
98 size_t m = fun.Range();
99 size_t n = fun.Domain();
100
101 if (n <= m) {
102 // use forward mode
103 return jacobianForwardSparsitySet<VectorSet, Base> (fun);
104 } else {
105 // use reverse mode
106 return jacobianReverseSparsitySet<VectorSet, Base> (fun);
107 }
108}
109
116inline bool estimateBestJacobianADMode(const std::vector<size_t>& jacRows,
117 const std::vector<size_t>& jacCols) {
118 std::set<size_t> rows, cols;
119 rows.insert(jacRows.begin(), jacRows.end());
120 size_t workReverse = rows.size();
121 cols.insert(jacCols.begin(), jacCols.end());
122 size_t workForward = cols.size();
123
124 return workForward <= workReverse;
125}
126
134template<class VectorBool, class Base>
135inline VectorBool hessianSparsity(ADFun<Base>& fun,
136 bool transpose = false) {
137 size_t m = fun.Range();
138 size_t n = fun.Domain();
139
143 VectorBool r(n * n); // identity matrix
144 for (size_t j = 0; j < n; j++) {
145 for (size_t k = 0; k < n; k++)
146 r[j * n + k] = false;
147 r[j * n + j] = true;
148 }
149 fun.ForSparseJac(n, r);
150
151 VectorBool s(m);
152 for (size_t i = 0; i < m; i++)
153 s[i] = true;
154 return fun.RevSparseHes(n, s, transpose);
155}
156
157template<class VectorSet, class Base>
158inline VectorSet hessianSparsitySet(ADFun<Base>& fun,
159 const std::set<size_t>& w,
160 bool transpose = false) {
161 size_t n = fun.Domain();
162
166 VectorSet r(n); // identity matrix
167 for (size_t j = 0; j < n; j++)
168 r[j].insert(j);
169 fun.ForSparseJac(n, r);
170
171 VectorSet s(1);
172 s[0] = w;
173
174 return fun.RevSparseHes(n, s, transpose);
175}
176
177template<class VectorSet, class Base>
178inline VectorSet hessianSparsitySet(ADFun<Base>& fun, bool transpose = false) {
179 size_t m = fun.Range();
180
181 std::set<size_t> w;
182 for (size_t i = 0; i < m; i++) {
183 w.insert(i);
184 }
185 return hessianSparsitySet<VectorSet, Base>(fun, w, transpose);
186}
187
196template<class VectorBool, class Base>
197inline VectorBool hessianSparsity(ADFun<Base>& fun,
198 size_t i,
199 bool transpose = false) {
200 size_t m = fun.Range();
201 size_t n = fun.Domain();
202
206 VectorBool r(n * n); // identity matrix
207 for (size_t j = 0; j < n; j++) {
208 for (size_t k = 0; k < n; k++)
209 r[j * n + k] = false;
210 r[j * n + j] = true;
211 }
212 fun.ForSparseJac(n, r);
213
214 VectorBool s(m);
215 for (size_t ii = 0; ii < m; ii++)
216 s[ii] = false;
217 s[i] = true;
218 return fun.RevSparseHes(n, s, transpose);
219}
220
221template<class VectorSet, class Base>
222inline VectorSet hessianSparsitySet(ADFun<Base>& fun,
223 size_t i,
224 bool transpose = false) {
225 size_t n = fun.Domain();
226
227 VectorSet r(n); // identity matrix
228 for (size_t j = 0; j < n; j++)
229 r[j].insert(j);
230 fun.ForSparseJac(n, r);
231
232 VectorSet s(1);
233 s[0].insert(i);
234
235 return fun.RevSparseHes(n, s, transpose);
236}
237
238template<class VectorBool, class VectorSize>
239inline void generateSparsityIndexes(const VectorBool& sparsity,
240 size_t m,
241 size_t n,
242 VectorSize& row,
243 VectorSize& col) {
244 assert(sparsity.size() == m * n);
245
246 // determine total number of non zeros
247 size_t nnz = 0;
248 for (size_t i = 0; i < sparsity.size(); i++) {
249 if (sparsity[i])
250 nnz++;
251 }
252
253 row.resize(nnz);
254 col.resize(nnz);
255
256 // save the indexes
257 nnz = 0;
258 for (size_t i = 0; i < m; i++) {
259 for (size_t j = 0; j < n; j++) {
260 if (sparsity[i * n + j]) {
261 row[nnz] = i;
262 col[nnz] = j;
263 nnz++;
264 }
265 }
266 }
267
268 assert(nnz == row.size());
269}
270
271template<class VectorSet, class VectorSize>
272inline void generateSparsityIndexes(const VectorSet& sparsity,
273 VectorSize& row,
274 VectorSize& col) {
275 size_t m = sparsity.size();
276
277 // determine total number of non zeros
278 size_t nnz = 0;
279 for (size_t i = 0; i < m; i++) {
280 nnz += sparsity[i].size();
281 }
282
283 row.resize(nnz);
284 col.resize(nnz);
285 if (nnz == 0)
286 return;
287
288 // save the indexes
289 nnz = 0;
290 for (size_t i = 0; i < m; i++) {
291 const std::set<size_t>& rowSparsity = sparsity[i];
292 size_t rowNnz = rowSparsity.size();
293 std::fill(&row[0] + nnz, &row[0] + nnz + rowNnz, i);
294 std::copy(rowSparsity.begin(), rowSparsity.end(), &col[0] + nnz);
295 nnz += rowNnz;
296 }
297}
298
299template<class VectorSet, class VectorSize>
300inline void generateSparsitySet(const VectorSize& row,
301 const VectorSize& col,
302 VectorSet& sparsity) {
303 assert(row.size() == col.size());
304
305 size_t nnz = row.size();
306 for (size_t e = 0; e < nnz; e++) {
307 sparsity[row[e]].insert(col[e]);
308 }
309}
310
311} // END cg namespace
312} // END CppAD namespace
313
314#endif
315