File: subgraph_jac_rev.cpp

package info (click to toggle)
cppad 2025.00.00.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 11,552 kB
  • sloc: cpp: 112,594; sh: 5,972; ansic: 179; python: 71; sed: 12; makefile: 10
file content (134 lines) | stat: -rw-r--r-- 4,005 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
// SPDX-FileContributor: 2003-22 Bradley M. Bell
// ----------------------------------------------------------------------------

/*
{xrst_begin subgraph_jac_rev.cpp}

Computing Sparse Jacobian Using Reverse Mode: Example and Test
##############################################################

{xrst_literal
   // BEGIN C++
   // END C++
}

{xrst_end subgraph_jac_rev.cpp}
*/
// BEGIN C++
# include <cppad/cppad.hpp>
bool subgraph_jac_rev(void)
{  bool ok = true;
   //
   using CppAD::AD;
   using CppAD::NearEqual;
   using CppAD::sparse_rc;
   using CppAD::sparse_rcv;
   //
   typedef CPPAD_TESTVECTOR(AD<double>) a_vector;
   typedef CPPAD_TESTVECTOR(double)     d_vector;
   typedef CPPAD_TESTVECTOR(size_t)     s_vector;
   typedef CPPAD_TESTVECTOR(bool)       b_vector;
   //
   // domain space vector
   size_t n = 4;
   a_vector  a_x(n);
   for(size_t j = 0; j < n; j++)
      a_x[j] = AD<double> (0);
   //
   // declare independent variables and starting recording
   CppAD::Independent(a_x);
   //
   size_t m = 3;
   a_vector  a_y(m);
   a_y[0] = a_x[0] + a_x[1];
   a_y[1] = a_x[2] + a_x[3];
   a_y[2] = a_x[0] + a_x[1] + a_x[2] + a_x[3] * a_x[3] / 2.;
   //
   // create f: x -> y and stop tape recording
   CppAD::ADFun<double> f(a_x, a_y);
   ok &= f.size_random() == 0;
   //
   // new value for the independent variable vector
   d_vector x(n);
   for(size_t j = 0; j < n; j++)
      x[j] = double(j);
   /*
           [ 1 1 0 0  ]
   J(x) = [ 0 0 1 1  ]
           [ 1 1 1 x_3]
   */
   //
   // row-major order values of J(x)
   size_t nnz = 8;
   s_vector check_row(nnz), check_col(nnz);
   d_vector check_val(nnz);
   for(size_t k = 0; k < nnz; k++)
   {  // check_val
      if( k < 7 )
         check_val[k] = 1.0;
      else
         check_val[k] = x[3];
      //
      // check_row and check_col
      check_col[k] = k;
      if( k < 2 )
         check_row[k] = 0;
      else if( k < 4 )
         check_row[k] = 1;
      else
      {  check_row[k] = 2;
         check_col[k] = k - 4;
      }
   }
   //
   // select all range components of domain and range
   b_vector select_domain(n), select_range(m);
   for(size_t j = 0; j < n; ++j)
      select_domain[j] = true;
   for(size_t i = 0; i < m; ++i)
      select_range[i] = true;
   // -----------------------------------------------------------------------
   // Compute Jacobian using f.subgraph_jac_rev(x, subset)
   // -----------------------------------------------------------------------
   //
   // get sparsity pattern
   bool transpose     = false;
   sparse_rc<s_vector> pattern_jac;
   f.subgraph_sparsity(
      select_domain, select_range, transpose, pattern_jac
   );
   // f.subgraph_jac_rev(x, subset)
   sparse_rcv<s_vector, d_vector> subset( pattern_jac );
   f.subgraph_jac_rev(x, subset);
   //
   // check result
   ok  &= subset.nnz() == nnz;
   s_vector row_major = subset.row_major();
   for(size_t k = 0; k < nnz; k++)
   {  ok &= subset.row()[ row_major[k] ] == check_row[k];
      ok &= subset.col()[ row_major[k] ] == check_col[k];
      ok &= subset.val()[ row_major[k] ] == check_val[k];
   }
   // -----------------------------------------------------------------------
   // f.subgraph_jac_rev(select_domain, select_range, x, matrix_out)
   // -----------------------------------------------------------------------
   sparse_rcv<s_vector, d_vector>  matrix_out;
   f.subgraph_jac_rev(select_domain, select_range, x, matrix_out);
   //
   // check result
   ok  &= matrix_out.nnz() == nnz;
   row_major = matrix_out.row_major();
   for(size_t k = 0; k < nnz; k++)
   {  ok &= matrix_out.row()[ row_major[k] ] == check_row[k];
      ok &= matrix_out.col()[ row_major[k] ] == check_col[k];
      ok &= matrix_out.val()[ row_major[k] ] == check_val[k];
   }
   //
   ok &= f.size_random() > 0;
   f.clear_subgraph();
   ok &= f.size_random() == 0;
   return ok;
}
// END C++