1 #ifndef CPPAD_CG_SPARSE_FORJAC_HESSIAN_INCLUDED 2 #define CPPAD_CG_SPARSE_FORJAC_HESSIAN_INCLUDED 42 template<
class Base,
class VectorSize>
44 const VectorSize& row,
45 const VectorSize& col) {
50 size_t n = fun.Domain();
51 size_t m = fun.Range();
53 if (user_row.size() == 0) {
55 user_col.resize(K + 1);
56 user_row.resize(K + 1);
57 sort_col.resize(K + 1);
60 for (
size_t k = 0; k <
K; k++) {
68 index_sort(user_col, sort_col);
72 CPPAD_ASSERT_KNOWN(
size_t(row.size()) == K &&
size_t(col.size()) == K,
73 "sparseForJacHessian: either r or c does not have " 74 "the same size as jac.");
75 CPPAD_ASSERT_KNOWN(user_row.size() == K + 1 &&
76 user_col.size() == K + 1 &&
77 sort_col.size() == K + 1,
78 "sparseForJacHessian: invalid value in work.");
79 for (
size_t k = 0; k <
K; k++) {
80 CPPAD_ASSERT_KNOWN(row[k] < m,
81 "sparseForJacHessian: invalid value in r.");
82 CPPAD_ASSERT_KNOWN(col[k] < n,
83 "sparseForJacHessian: invalid value in c.");
84 CPPAD_ASSERT_KNOWN(sort_col[k] < K,
85 "sparseForJacHessian: invalid value in work.");
86 CPPAD_ASSERT_KNOWN(user_row[k] == row[k],
87 "sparseForJacHessian: invalid value in work.");
88 CPPAD_ASSERT_KNOWN(user_col[k] == col[k],
89 "sparseForJacHessian: invalid value in work.");
118 template<
class Base,
class VectorSize>
120 const VectorSize& row,
121 const VectorSize& col) {
125 size_t n = fun.Domain();
128 if (r_sort.size() == 0) {
131 r_sort.resize(K + 1);
135 index_sort(row, k_sort);
137 for (
size_t k = 0; k <
K; k++) {
138 r_sort[k] = row[ k_sort[k] ];
139 c_sort[k] = col[ k_sort[k] ];
144 CPPAD_ASSERT_KNOWN(
size_t(row.size()) == K &&
size_t(col.size()) == K,
145 "sparseForJacHessian: either r or c does not have the same size as ehs.");
146 CPPAD_ASSERT_KNOWN(r_sort.size() == K + 1 &&
147 c_sort.size() == K &&
149 "sparseForJacHessian: invalid value in work.");
150 for (
size_t k = 0; k <
K; k++) {
151 CPPAD_ASSERT_KNOWN(row[k] < n,
152 "sparseForJacHessian: invalid value in r.");
153 CPPAD_ASSERT_KNOWN(col[k] < n,
154 "sparseForJacHessian: invalid value in c.");
155 CPPAD_ASSERT_KNOWN(k_sort[k] < K,
156 "sparseForJacHessian: invalid value in work.");
157 CPPAD_ASSERT_KNOWN(r_sort[k] == row[ k_sort[k] ],
158 "sparseForJacHessian: invalid value in work.");
159 CPPAD_ASSERT_KNOWN(c_sort[k] == col[ k_sort[k] ],
160 "sparseForJacHessian: invalid value in work.");
184 template<
class Base,
class VectorSize>
186 const VectorSize& jacRow,
187 const VectorSize& jacCol,
188 const VectorSize& hesRow,
189 const VectorSize& hesCol) {
190 size_t n = fun.Domain();
192 CPPAD_ASSERT_KNOWN(color.size() == 0 || color.size() == n,
193 "sparseForJacHessian: invalid value in work.");
194 if (color.size() != 0) {
195 for (
size_t j = 0; j < n; j++) {
196 CPPAD_ASSERT_KNOWN(color[j] < n,
197 "sparseForJacHessian: invalid value in work.");
201 jac.
prepare(fun, jacRow, jacCol);
202 hes.
prepare(fun, hesRow, hesCol);
213 template<
class SparsityPattern>
214 inline void computeNotUsed(SparsityPattern& not_used,
215 const SparsityPattern& sparsity,
216 const SparsityPattern& r_used,
219 using SparIter =
typename SparsityPattern::const_iterator;
221 assert(not_used.n_set() == 0);
222 not_used.resize(m, n);
224 for (
size_t i = 0; i < n; i++) {
225 SparIter j_itr(sparsity, i);
227 while (j != sparsity.end()) {
228 if (!r_used.is_element(j, i))
229 not_used.add_element(j, i);
235 template<
class Base,
class VectorSet>
236 inline size_t colorForwardJacobianHessian(
const ADFun<Base>& fun,
237 const VectorSet& jac_p,
238 const VectorSet& hes_p,
244 size_t i, j1, j11, j2, c, k;
246 using Set_type =
typename VectorSet::value_type;
247 using SparsityPattern =
typename local::internal_sparsity<Set_type>::pattern_type;
248 using SparIter =
typename SparsityPattern::const_iterator;
250 size_t n = fun.Domain();
251 size_t m = fun.Range();
253 std::vector<size_t>& color = work.
color;
255 if (color.size() == 0) {
259 CPPAD_ASSERT_KNOWN(jac_p.size() == m,
260 "sparseForJacHessian: invalid jacobian sparsity pattern dimension.");
261 CPPAD_ASSERT_KNOWN(hes_p.size() == n,
262 "sparseForJacHessian: invalid hessian sparsity pattern dimension.");
268 SparsityPattern p_transpose;
269 bool transpose =
true;
270 sparsity_user2internal(p_transpose, jac_p, n, m, transpose,
"Invalid sparsity pattern");
273 size_t jac_K = work.jac.
K;
274 std::vector<size_t>& jac_row = work.jac.
user_row;
275 std::vector<size_t>& jac_col = work.jac.
user_col;
278 CPPAD_ASSERT_UNKNOWN(p_transpose.n_set() == n);
279 CPPAD_ASSERT_UNKNOWN(p_transpose.end() == m);
282 SparsityPattern jac_r_used, jac_c_used;
283 jac_r_used.resize(n, m);
284 jac_c_used.resize(m, n);
286 for (k = 0; k < jac_K; k++) {
287 CPPAD_ASSERT_UNKNOWN(jac_row[sort_col[k]] < m && jac_col[sort_col[k]] < n);
288 CPPAD_ASSERT_UNKNOWN(k == 0 || jac_col[sort_col[k - 1]] <= jac_col[sort_col[k]]);
289 CPPAD_ASSERT_KNOWN(p_transpose.is_element(jac_col[sort_col[k]], jac_row[sort_col[k]]),
290 "sparseForJacHessian: " 291 "a (row, col) pair is not in sparsity pattern.");
292 jac_r_used.add_element(jac_col[sort_col[k]], jac_row[sort_col[k]]);
293 jac_c_used.add_element(jac_row[sort_col[k]], jac_col[sort_col[k]]);
297 SparsityPattern jac_not_used;
298 computeNotUsed(jac_not_used, p_transpose, jac_c_used, m, n);
303 SparsityPattern hes_sparsity;
305 sparsity_user2internal(hes_sparsity, hes_p, n, n, transpose,
"Invalid sparsity pattern");
307 size_t hes_K = work.hes.
K;
308 std::vector<size_t>& hes_row(work.hes.
r_sort);
309 std::vector<size_t>& hes_col(work.hes.
c_sort);
311 CPPAD_ASSERT_UNKNOWN(hes_sparsity.n_set() == n);
312 CPPAD_ASSERT_UNKNOWN(hes_sparsity.end() == n);
315 SparsityPattern hes_r_used, hes_c_used;
316 hes_r_used.resize(n, n);
317 hes_c_used.resize(n, n);
319 for (k = 0; k < hes_K; k++) {
320 CPPAD_ASSERT_UNKNOWN(hes_row[k] < n && hes_col[k] < n);
321 CPPAD_ASSERT_UNKNOWN(k == 0 || hes_row[k - 1] <= hes_row[k]);
322 CPPAD_ASSERT_KNOWN(hes_sparsity.is_element(hes_row[k], hes_col[k]),
323 "sparseForJacHessian: a (row, col) pair is not in sparsity pattern.");
324 hes_r_used.add_element(hes_col[k], hes_row[k]);
325 hes_c_used.add_element(hes_row[k], hes_col[k]);
329 SparsityPattern hes_not_used;
330 computeNotUsed(hes_not_used, hes_sparsity, hes_r_used, n, n);
333 for (j1 = 0; j1 < n; j1++) {
340 vectorBool forbidden(n);
341 for (j1 = 1; j1 < n; j1++) {
344 for (c = 0; c <= j1; c++)
345 forbidden[c] =
false;
351 SparIter p_itr(p_transpose, j1);
353 while (i != p_transpose.end()) {
355 SparIter jac_c_used_itr(jac_c_used, i);
356 j11 = *jac_c_used_itr;
357 while (j11 != jac_c_used.end()) {
360 forbidden[ color[j11] ] =
true;
361 j11 = *(++jac_c_used_itr);
367 SparIter jac_r_used_itr(jac_r_used, j1);
370 while (i != jac_r_used.end()) {
373 SparIter jac_not_used_itr(jac_not_used, i);
374 j11 = *jac_not_used_itr;
375 while (j11 != jac_not_used.end()) {
378 forbidden[ color[j11] ] =
true;
379 j11 = *(++jac_not_used_itr);
381 i = *(++jac_r_used_itr);
390 SparIter hes_itr(hes_sparsity, j1);
392 while (j2 != hes_sparsity.end()) {
394 SparIter hes_r_used_itr(hes_r_used, j2);
395 j11 = *hes_r_used_itr;
396 while (j11 != hes_r_used.end()) {
399 forbidden[ color[j11] ] =
true;
400 j11 = *(++hes_r_used_itr);
408 SparIter hes_c_used_itr(hes_c_used, j1);
409 j2 = *hes_c_used_itr;
410 while (j2 != hes_c_used.end()) {
413 SparIter hes_not_used_itr(hes_not_used, j2);
414 j11 = *hes_not_used_itr;
415 while (j11 != hes_not_used.end()) {
418 forbidden[ color[j11] ] =
true;
419 j11 = *(++hes_not_used_itr);
421 j2 = *(++hes_c_used_itr);
427 while (forbidden[c]) {
429 CPPAD_ASSERT_UNKNOWN(c <= j1);
437 for (j1 = 0; j1 < n; j1++)
438 n_color = std::max(n_color, color[j1] + 1);
489 template<
class Base,
class VectorBase,
class VectorSet,
class VectorSize>
494 const VectorSet& jac_p,
495 const VectorSize& jac_row,
496 const VectorSize& jac_col,
498 const VectorSet& hes_p,
499 const VectorSize& hes_row,
500 const VectorSize& hes_col,
503 std::vector<VectorBase> vw(1);
504 std::vector<VectorBase> vhes(1);
508 size_t n_sweep = sparseForJacHessian(fun,
511 jac_p, jac_row, jac_col, jac,
512 hes_p, hes_row, hes_col, vhes,
520 template<
class Base,
class VectorBase,
class VectorVectorBase,
class VectorSet,
class VectorSize>
523 const VectorVectorBase& w,
525 const VectorSet& jac_p,
526 const VectorSize& jac_row,
527 const VectorSize& jac_col,
529 const VectorSet& hes_p,
530 const VectorSize& hes_row,
531 const VectorSize& hes_col,
532 VectorVectorBase& hes,
534 using CppAD::vectorBool;
537 size_t n = fun.Domain();
538 size_t m = fun.Range();
540 size_t nH = size_t(hes.size());
541 size_t jac_K = size_t(jac_row.size());
542 size_t hes_K = size_t(hes_row.size());
544 CPPADCG_ASSERT_KNOWN(
size_t(x.size()) == n,
545 "sparseForJacHessian: size of x not equal domain dimension for f.");
547 CPPADCG_ASSERT_KNOWN(
size_t(w.size()) == nH,
548 "sparseForJacHessian: size of w not equal to the size of hes.");
550 const std::vector<size_t>& jac_scol = work.jac.
sort_col;
551 const std::vector<size_t>& hes_srow = work.hes.
r_sort;
552 const std::vector<size_t>& hes_scol = work.hes.
c_sort;
553 const std::vector<size_t>& hes_user_k = work.hes.
k_sort;
554 const std::vector<size_t>& color = work.
color;
561 CheckSimpleVector<Base, VectorBase>();
563 CPPAD_ASSERT_UNKNOWN(
size_t(x.size()) == n);
565 work.prepare(fun, jac_row, jac_col, hes_row, hes_col);
570 size_t n_color = colorForwardJacobianHessian(fun, jac_p, hes_p, work);
574 y = fun.Forward(0, x);
583 VectorBase ddw(2 * n);
586 for (k = 0; k < jac_K; k++)
588 for (
size_t h = 0; h < nH; h++) {
589 VectorBase& hesh = hes[h];
590 for (k = 0; k < hes_K; k++)
596 for (c = 0; c < n_color; c++) {
600 for (j1 = 0; j1 < n; j1++) {
601 if (color[j1] == c) {
603 while (work.jac.
user_col[jac_scol[kJac]] < j1)
605 anyJac = work.jac.
user_col[jac_scol[kJac]] == j1;
612 size_t kHessStart = 0;
613 for (j1 = 0; j1 < n; j1++) {
614 if (color[j1] == c) {
616 while (hes_srow[kHessStart] < j1)
618 anyHes = hes_srow[kHessStart] == j1;
624 if (anyJac || anyHes) {
627 for (j1 = 0; j1 < n; j1++) {
633 dy = fun.Forward(1, u);
637 for (j1 = 0; j1 < n; j1++) {
638 if (color[j1] == c) {
640 while (work.jac.
user_col[jac_scol[kJac]] < j1)
643 while (work.jac.
user_col[jac_scol[kJac]] == j1) {
644 jac[ jac_scol[kJac] ] = dy[ work.jac.
user_row[jac_scol[kJac]] ];
654 for (
size_t h = 0; h < nH; h++) {
656 ddw = fun.Reverse(2, w[h]);
658 VectorBase& hesh = hes[h];
661 size_t kHess = kHessStart;
662 for (j1 = 0; j1 < n; j1++) {
663 if (color[j1] == c) {
665 while (hes_srow[kHess] < j1)
668 while (hes_srow[kHess] == j1) {
669 size_t j2 = hes_scol[kHess];
670 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
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(void)
inform CppAD that this information needs to be recomputed
void clear(void)
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(void)
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