|
Prev
| Next
|
|
|
|
|
|
json_sparse.cpp |
|
@(@\newcommand{\W}[1]{ \; #1 \; }
\newcommand{\R}[1]{ {\rm #1} }
\newcommand{\B}[1]{ {\bf #1} }
\newcommand{\D}[2]{ \frac{\partial #1}{\partial #2} }
\newcommand{\DD}[3]{ \frac{\partial^2 #1}{\partial #2 \partial #3} }
\newcommand{\Dpow}[2]{ \frac{\partial^{#1}}{\partial {#2}^{#1}} }
\newcommand{\dpow}[2]{ \frac{ {\rm d}^{#1}}{{\rm d}\, {#2}^{#1}} }@)@This is cppad-20221105 documentation. Here is a link to its
current documentation
.
Json Representation of a Sparse Matrix: Example and Test
Discussion
The example using a CppAD Json to represent the sparse matrix
@[@
\partial_x f(x, p) = \left( \begin{array}{ccc}
p_0 & 0 & 0 \\
0 & p_1 & 0 \\
0 & 0 & c_0
\end{array} \right)
@]@
where @(@
c_0
@)@ is the constant 3.
Source Code
# include <cppad/cppad.hpp>
bool sparse(void)
{ bool ok = true;
using CppAD::vector;
typedef vector<size_t> s_vector;
typedef vector<double> d_vector;
//
// An AD graph example
// node_1 : p[0]
// node_2 : p[1]
// node_3 : x[0]
// node_4 : x[1]
// node_5 : x[2]
// node_6 : c[0]
// node_7 : p[0] * x[0]
// node_8 : p[1] * x[1]
// node_9 : c[0] * x[2]
// y[0] = p[0] * x[0]
// y[1] = p[1] * x[1]
// y[2] = c[0] * x[0]
// use single quote to avoid having to escape double quote
std::string json =
"{\n"
" 'function_name' : 'sparse example',\n"
" 'op_define_vec' : [ 1, [\n"
" { 'op_code':1, 'name':'mul', 'n_arg':2 } ]\n"
" ],\n"
" 'n_dynamic_ind' : 2,\n"
" 'n_variable_ind' : 3,\n"
" 'constant_vec' : [ 1, [ 3.0 ] ],\n"
" 'op_usage_vec' : [ 3, [\n"
" [ 1, 1, 3 ] , \n"
" [ 1, 2, 4 ] , \n"
" [ 1, 6, 5 ] ] \n"
" ],\n"
" 'dependent_vec' : [ 3, [7, 8, 9] ] \n"
"}\n";
// Convert the single quote to double quote
for(size_t i = 0; i < json.size(); ++i)
if( json[i] == '\'' ) json[i] = '"';
//
CppAD::ADFun<double> fun;
fun.from_json(json);
ok &= fun.Domain() == 3;
ok &= fun.Range() == 3;
ok &= fun.size_dyn_ind() == 2;
//
// Point at which we are going to evaluate the Jacobian of f(x, p).
// The Jacobian is constant w.r.t. x, so the value of x does not matter.
vector<double> p(2), x(3);
p[0] = 1.0;
p[1] = 2.0;
for(size_t j = 0; j < x.size(); ++j)
x[j] = 0.0;
//
// set the dynamic parameters
fun.new_dynamic(p);
//
// compute the sparsity pattern for f_x(x, p)
vector<bool> select_domain(3);
vector<bool> select_range(3);
for(size_t i = 0; i < 3; ++i)
{ select_domain[i] = true;
select_range[i] = true;
}
bool transpose = false;
CppAD::sparse_rc<s_vector> pattern;
fun.subgraph_sparsity(select_domain, select_range, transpose, pattern);
//
// compute the entire Jacobian
CppAD::sparse_rcv<s_vector, d_vector> subset(pattern);
fun.subgraph_jac_rev(x, subset);
//
// information in the sparse Jacobian
const s_vector& row( subset.row() );
const s_vector& col( subset.col() );
const d_vector& val( subset.val() );
size_t nnz = subset.nnz();
s_vector row_major = subset.row_major();
//
// check number of non-zero elements in sparse matrix
ok &= nnz == 3;
//
// check first element of matrix (in row major order)
size_t k = row_major[0];
ok &= row[k] == 0;
ok &= col[k] == 0;
ok &= val[k] == p[0];
//
// check second element of matrix
k = row_major[1];
ok &= row[k] == 1;
ok &= col[k] == 1;
ok &= val[k] == p[1];
//
// check third element of matrix
k = row_major[2];
ok &= row[k] == 2;
ok &= col[k] == 2;
ok &= val[k] == 3.0;
//
return ok;
}
Input File: example/json/sparse.cpp