CppADCodeGen  2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
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 
18 namespace CppAD {
19 namespace cg {
20 
21 template<class VectorBool, class Base>
22 inline 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 
35 template<class VectorBool, class Base>
36 inline 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 
48 template<class VectorSet, class Base>
49 inline 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 
59 template<class VectorSet, class Base>
60 inline 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 
76 template<class VectorBool, class Base>
77 inline 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 
96 template<class VectorSet, class Base>
97 inline 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 
116 inline 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 
134 template<class VectorBool, class Base>
135 inline 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 
157 template<class VectorSet, class Base>
158 inline 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 
177 template<class VectorSet, class Base>
178 inline 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 
196 template<class VectorBool, class Base>
197 inline 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 
221 template<class VectorSet, class Base>
222 inline 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 
238 template<class VectorBool, class VectorSize>
239 inline 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 
271 template<class VectorSet, class VectorSize>
272 inline 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 
299 template<class VectorSet, class VectorSize>
300 inline 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