1 #ifndef CPPAD_CG_SPARSE_FORJAC_HESSIAN_INCLUDED 2 #define CPPAD_CG_SPARSE_FORJAC_HESSIAN_INCLUDED 43 template<
class Base,
class VectorSize>
45 const VectorSize& row,
46 const VectorSize& col) {
51 size_t n = fun.Domain();
52 size_t m = fun.Range();
54 if (user_row.empty()) {
56 user_col.resize(K + 1);
57 user_row.resize(K + 1);
58 sort_col.resize(K + 1);
61 for (
size_t k = 0; k <
K; k++) {
69 index_sort(user_col, sort_col);
73 CPPAD_ASSERT_KNOWN(
size_t(row.size()) == K &&
size_t(col.size()) == K,
74 "sparseForJacHessian: either r or c does not have " 75 "the same size as jac.")
76 CPPAD_ASSERT_KNOWN(user_row.size() == K + 1 &&
77 user_col.size() == K + 1 &&
78 sort_col.size() == K + 1,
79 "sparseForJacHessian: invalid value in work.")
80 for (
size_t k = 0; k <
K; k++) {
81 CPPAD_ASSERT_KNOWN(row[k] < m,
82 "sparseForJacHessian: invalid value in r.")
83 CPPAD_ASSERT_KNOWN(col[k] < n,
84 "sparseForJacHessian: invalid value in c.")
85 CPPAD_ASSERT_KNOWN(sort_col[k] < K,
86 "sparseForJacHessian: invalid value in work.")
87 CPPAD_ASSERT_KNOWN(user_row[k] == row[k],
88 "sparseForJacHessian: invalid value in work.")
89 CPPAD_ASSERT_KNOWN(user_col[k] == col[k],
90 "sparseForJacHessian: invalid value in work.")
119 template<
class Base,
class VectorSize>
121 const VectorSize& row,
122 const VectorSize& col) {
126 size_t n = fun.Domain();
129 if (r_sort.empty()) {
132 r_sort.resize(K + 1);
136 index_sort(row, k_sort);
138 for (
size_t k = 0; k <
K; k++) {
139 r_sort[k] = row[ k_sort[k] ];
140 c_sort[k] = col[ k_sort[k] ];
145 CPPAD_ASSERT_KNOWN(
size_t(row.size()) == K &&
size_t(col.size()) == K,
146 "sparseForJacHessian: either r or c does not have the same size as ehs.")
147 CPPAD_ASSERT_KNOWN(r_sort.size() == K + 1 &&
148 c_sort.size() == K &&
150 "sparseForJacHessian: invalid value in work.")
151 for (
size_t k = 0; k <
K; k++) {
152 CPPAD_ASSERT_KNOWN(row[k] < n,
153 "sparseForJacHessian: invalid value in r.")
154 CPPAD_ASSERT_KNOWN(col[k] < n,
155 "sparseForJacHessian: invalid value in c.")
156 CPPAD_ASSERT_KNOWN(k_sort[k] < K,
157 "sparseForJacHessian: invalid value in work.")
158 CPPAD_ASSERT_KNOWN(r_sort[k] == row[ k_sort[k] ],
159 "sparseForJacHessian: invalid value in work.")
160 CPPAD_ASSERT_KNOWN(c_sort[k] == col[ k_sort[k] ],
161 "sparseForJacHessian: invalid value in work.")
185 template<
class Base,
class VectorSize>
187 const VectorSize& jacRow,
188 const VectorSize& jacCol,
189 const VectorSize& hesRow,
190 const VectorSize& hesCol) {
191 size_t n = fun.Domain();
193 CPPAD_ASSERT_KNOWN(color.empty() || color.size() == n,
194 "sparseForJacHessian: invalid value in work.")
195 if (!color.empty()) {
196 for (
size_t j = 0; j < n; j++) {
197 CPPAD_ASSERT_KNOWN(color[j] < n,
198 "sparseForJacHessian: invalid value in work.")
202 jac.
prepare(fun, jacRow, jacCol);
203 hes.
prepare(fun, hesRow, hesCol);
214 template<
class SparsityPattern>
215 inline void computeNotUsed(SparsityPattern& not_used,
216 const SparsityPattern& sparsity,
217 const SparsityPattern& r_used,
220 using SparIter =
typename SparsityPattern::const_iterator;
222 assert(not_used.n_set() == 0);
223 not_used.resize(m, n);
225 for (
size_t i = 0; i < n; i++) {
226 SparIter j_itr(sparsity, i);
228 while (j != sparsity.end()) {
229 if (!r_used.is_element(j, i))
230 not_used.add_element(j, i);
236 template<
class Base,
class VectorSet>
237 inline size_t colorForwardJacobianHessian(
const ADFun<Base>& fun,
238 const VectorSet& jac_p,
239 const VectorSet& hes_p,
245 size_t i, j1, j11, j2, c, k;
247 using Set_type =
typename VectorSet::value_type;
248 using SparsityPattern =
typename local::sparse::internal_pattern<Set_type>::pattern_type;
249 using SparIter =
typename SparsityPattern::const_iterator;
251 size_t n = fun.Domain();
252 size_t m = fun.Range();
254 std::vector<size_t>& color = work.
color;
260 CPPAD_ASSERT_KNOWN(jac_p.size() == m,
261 "sparseForJacHessian: invalid jacobian sparsity pattern dimension.")
262 CPPAD_ASSERT_KNOWN(hes_p.size() == n,
263 "sparseForJacHessian: invalid hessian sparsity pattern dimension.")
269 SparsityPattern p_transpose;
270 bool transpose =
true;
271 sparsity_user2internal(p_transpose, jac_p, n, m, transpose,
"Invalid sparsity pattern");
274 size_t jac_K = work.jac.
K;
275 std::vector<size_t>& jac_row = work.jac.
user_row;
276 std::vector<size_t>& jac_col = work.jac.
user_col;
279 CPPAD_ASSERT_UNKNOWN(p_transpose.n_set() == n)
280 CPPAD_ASSERT_UNKNOWN(p_transpose.end() == m)
283 SparsityPattern jac_r_used, jac_c_used;
284 jac_r_used.resize(n, m);
285 jac_c_used.resize(m, n);
287 for (k = 0; k < jac_K; k++) {
288 CPPAD_ASSERT_UNKNOWN(jac_row[sort_col[k]] < m && jac_col[sort_col[k]] < n)
289 CPPAD_ASSERT_UNKNOWN(k == 0 || jac_col[sort_col[k - 1]] <= jac_col[sort_col[k]])
290 CPPAD_ASSERT_KNOWN(p_transpose.is_element(jac_col[sort_col[k]], jac_row[sort_col[k]]),
291 "sparseForJacHessian: " 292 "a (row, col) pair is not in sparsity pattern.")
293 jac_r_used.add_element(jac_col[sort_col[k]], jac_row[sort_col[k]]);
294 jac_c_used.add_element(jac_row[sort_col[k]], jac_col[sort_col[k]]);
298 SparsityPattern jac_not_used;
299 computeNotUsed(jac_not_used, p_transpose, jac_c_used, m, n);
304 SparsityPattern hes_sparsity;
306 sparsity_user2internal(hes_sparsity, hes_p, n, n, transpose,
"Invalid sparsity pattern");
308 size_t hes_K = work.hes.
K;
309 std::vector<size_t>& hes_row(work.hes.
r_sort);
310 std::vector<size_t>& hes_col(work.hes.
c_sort);
312 CPPAD_ASSERT_UNKNOWN(hes_sparsity.n_set() == n)
313 CPPAD_ASSERT_UNKNOWN(hes_sparsity.end() == n)
316 SparsityPattern hes_r_used, hes_c_used;
317 hes_r_used.resize(n, n);
318 hes_c_used.resize(n, n);
320 for (k = 0; k < hes_K; k++) {
321 CPPAD_ASSERT_UNKNOWN(hes_row[k] < n && hes_col[k] < n)
322 CPPAD_ASSERT_UNKNOWN(k == 0 || hes_row[k - 1] <= hes_row[k])
323 CPPAD_ASSERT_KNOWN(hes_sparsity.is_element(hes_row[k], hes_col[k]),
324 "sparseForJacHessian: a (row, col) pair is not in sparsity pattern.")
325 hes_r_used.add_element(hes_col[k], hes_row[k]);
326 hes_c_used.add_element(hes_row[k], hes_col[k]);
330 SparsityPattern hes_not_used;
331 computeNotUsed(hes_not_used, hes_sparsity, hes_r_used, n, n);
334 for (j1 = 0; j1 < n; j1++) {
341 vectorBool forbidden(n);
342 for (j1 = 1; j1 < n; j1++) {
345 for (c = 0; c <= j1; c++)
346 forbidden[c] =
false;
352 SparIter p_itr(p_transpose, j1);
354 while (i != p_transpose.end()) {
356 SparIter jac_c_used_itr(jac_c_used, i);
357 j11 = *jac_c_used_itr;
358 while (j11 != jac_c_used.end()) {
361 forbidden[ color[j11] ] =
true;
362 j11 = *(++jac_c_used_itr);
368 SparIter jac_r_used_itr(jac_r_used, j1);
371 while (i != jac_r_used.end()) {
374 SparIter jac_not_used_itr(jac_not_used, i);
375 j11 = *jac_not_used_itr;
376 while (j11 != jac_not_used.end()) {
379 forbidden[ color[j11] ] =
true;
380 j11 = *(++jac_not_used_itr);
382 i = *(++jac_r_used_itr);
391 SparIter hes_itr(hes_sparsity, j1);
393 while (j2 != hes_sparsity.end()) {
395 SparIter hes_r_used_itr(hes_r_used, j2);
396 j11 = *hes_r_used_itr;
397 while (j11 != hes_r_used.end()) {
400 forbidden[ color[j11] ] =
true;
401 j11 = *(++hes_r_used_itr);
409 SparIter hes_c_used_itr(hes_c_used, j1);
410 j2 = *hes_c_used_itr;
411 while (j2 != hes_c_used.end()) {
414 SparIter hes_not_used_itr(hes_not_used, j2);
415 j11 = *hes_not_used_itr;
416 while (j11 != hes_not_used.end()) {
419 forbidden[ color[j11] ] =
true;
420 j11 = *(++hes_not_used_itr);
422 j2 = *(++hes_c_used_itr);
428 while (forbidden[c]) {
430 CPPAD_ASSERT_UNKNOWN(c <= j1)
438 for (j1 = 0; j1 < n; j1++)
439 n_color = std::max<size_t>(n_color, color[j1] + 1);
490 template<
class Base,
class VectorBase,
class VectorSet,
class VectorSize>
495 const VectorSet& jac_p,
496 const VectorSize& jac_row,
497 const VectorSize& jac_col,
499 const VectorSet& hes_p,
500 const VectorSize& hes_row,
501 const VectorSize& hes_col,
504 std::vector<VectorBase> vw(1);
505 std::vector<VectorBase> vhes(1);
509 size_t n_sweep = sparseForJacHessian(fun,
512 jac_p, jac_row, jac_col, jac,
513 hes_p, hes_row, hes_col, vhes,
521 template<
class Base,
class VectorBase,
class VectorVectorBase,
class VectorSet,
class VectorSize>
524 const VectorVectorBase& w,
526 const VectorSet& jac_p,
527 const VectorSize& jac_row,
528 const VectorSize& jac_col,
530 const VectorSet& hes_p,
531 const VectorSize& hes_row,
532 const VectorSize& hes_col,
533 VectorVectorBase& hes,
535 using CppAD::vectorBool;
538 size_t n = fun.Domain();
539 size_t m = fun.Range();
541 size_t nH = size_t(hes.size());
542 size_t jac_K = size_t(jac_row.size());
543 size_t hes_K = size_t(hes_row.size());
545 CPPADCG_ASSERT_KNOWN(
size_t(x.size()) == n,
546 "sparseForJacHessian: size of x not equal domain dimension for f.")
548 CPPADCG_ASSERT_KNOWN(
size_t(w.size()) == nH,
549 "sparseForJacHessian: size of w not equal to the size of hes.")
551 const std::vector<size_t>& jac_scol = work.jac.
sort_col;
552 const std::vector<size_t>& hes_srow = work.hes.
r_sort;
553 const std::vector<size_t>& hes_scol = work.hes.
c_sort;
554 const std::vector<size_t>& hes_user_k = work.hes.
k_sort;
555 const std::vector<size_t>& color = work.
color;
562 CheckSimpleVector<Base, VectorBase>();
564 CPPAD_ASSERT_UNKNOWN(
size_t(x.size()) == n)
566 work.prepare(fun, jac_row, jac_col, hes_row, hes_col);
571 size_t n_color = colorForwardJacobianHessian(fun, jac_p, hes_p, work);
575 y = fun.Forward(0, x);
584 VectorBase ddw(2 * n);
587 for (k = 0; k < jac_K; k++)
589 for (
size_t h = 0; h < nH; h++) {
590 VectorBase& hesh = hes[h];
591 for (k = 0; k < hes_K; k++)
597 for (c = 0; c < n_color; c++) {
601 for (j1 = 0; j1 < n; j1++) {
602 if (color[j1] == c) {
604 while (work.jac.
user_col[jac_scol[kJac]] < j1)
606 anyJac = work.jac.
user_col[jac_scol[kJac]] == j1;
613 size_t kHessStart = 0;
614 for (j1 = 0; j1 < n; j1++) {
615 if (color[j1] == c) {
617 while (hes_srow[kHessStart] < j1)
619 anyHes = hes_srow[kHessStart] == j1;
625 if (anyJac || anyHes) {
628 for (j1 = 0; j1 < n; j1++) {
634 dy = fun.Forward(1, u);
638 for (j1 = 0; j1 < n; j1++) {
639 if (color[j1] == c) {
641 while (work.jac.
user_col[jac_scol[kJac]] < j1)
644 while (work.jac.
user_col[jac_scol[kJac]] == j1) {
645 jac[ jac_scol[kJac] ] = dy[ work.jac.
user_row[jac_scol[kJac]] ];
655 for (
size_t h = 0; h < nH; h++) {
657 ddw = fun.Reverse(2, w[h]);
659 VectorBase& hesh = hes[h];
662 size_t kHess = kHessStart;
663 for (j1 = 0; j1 < n; j1++) {
664 if (color[j1] == c) {
666 while (hes_srow[kHess] < j1)
669 while (hes_srow[kHess] == j1) {
670 size_t j2 = hes_scol[kHess];
671 hesh[ hes_user_k[kHess] ] = ddw[ j2 * 2 + 1 ];
std::vector< size_t > user_col
version of user col array with the extra value n at end
void clear()
inform CppAD that this information needs to be recomputed
std::vector< size_t > color
results of the coloring algorithm
std::vector< size_t > user_row
version of user row array with the extra value m at end
void clear()
inform CppAD that this information needs to be recomputed
std::vector< size_t > sort_row
indices that sort the user arrays by row with the extra value K at the end
std::vector< size_t > sort_col
indices that sort the user arrays by column with the extra value K at the end
std::vector< size_t > r_sort
version of user r array sorted by row or column
size_t K
number elements in the user sparse Jacobian
void prepare(const ADFun< Base > &fun, const VectorSize &row, const VectorSize &col)
size_t K
number elements in the user sparse Hessian
void clear()
inform CppAD that this information needs to be recomputed
void prepare(const ADFun< Base > &fun, const VectorSize &row, const VectorSize &col)
std::vector< size_t > k_sort
mapping from sorted array indices to user array indices
std::vector< size_t > c_sort
version of user c array sorted by row or column