\(\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}} }\)
valvector_ad_join.cpp¶
View page sourceExample and Test of Joining a valvector¶
# include <cppad/example/valvector/split_join.hpp>
# include <cppad/cppad.hpp>
bool ad_join(void)
{ // ok
bool ok = true;
//
// sparsity_type
typedef CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > sparsity_type;
//
// scalar_type
typedef valvector::scalar_type scalar_type;
//
// ad_valvector
typedef CppAD::AD<valvector> ad_valvector;
//
// ajoin
valvector_ad_join ajoin;
//
// n, m
size_t n = 10;
size_t m = 1;
//
// ax
CPPAD_TESTVECTOR( ad_valvector ) ax(n);
for(size_t j = 0; j < n; ++j)
ax[j] = valvector(j);
CppAD::Independent(ax);
//
// ay
ad_valvector ay;
ajoin(ax, ay);
//
ad_valvector ay_sq = ay * ay;
//
// f
CPPAD_TESTVECTOR( ad_valvector ) az(m);
az[0] = ay_sq;
CppAD::ADFun<valvector> f(ax, az);
//
// x
CPPAD_TESTVECTOR( valvector ) x(n);
for(size_t j = 0; j < n; ++j)
x[j][0] = scalar_type(j + 1);
//
// a
CPPAD_TESTVECTOR( valvector ) z(m);
z = f.Forward(0, x);
//
// ok
for(size_t j = 0; j < n; ++j)
ok &= z[0][j] == x[j][0] * x[j][0];
//
// dw
CPPAD_TESTVECTOR( valvector ) w(m), dw(n);
w[0][0] = 1.0;
dw = f.Reverse(1, w);
//
// ok
for(size_t j = 0; j < n; ++j)
ok &= dw[0][j] == scalar_type(2) * x[0][j];
//
// jac_pattern
sparsity_type identity_pattern(n, n, n);
for(size_t k = 0; k < n; ++k)
identity_pattern.set(k, k, k);
bool transpose = false;
bool dependency = false;
bool internal_bool = false;
sparsity_type jac_pattern;
f.for_jac_sparsity(
identity_pattern, transpose, dependency, internal_bool, jac_pattern
);
//
// ok
ok &= jac_pattern.nnz() == n;
ok &= jac_pattern.nr() == m;
ok &= jac_pattern.nc() == n;
{ CPPAD_TESTVECTOR(size_t) col_major = jac_pattern.col_major();
const CPPAD_TESTVECTOR(size_t)& row = jac_pattern.row();
const CPPAD_TESTVECTOR(size_t)& col = jac_pattern.col();
for(size_t k = 0; k < n; ++k)
{ ok &= row[ col_major[k] ] == 0;
ok &= col[ col_major[k] ] == k;
}
}
//
// hes_pattern
internal_bool = false;
CPPAD_TESTVECTOR(bool) select_domain(n);
CPPAD_TESTVECTOR(bool) select_range(m);
select_range[0] = true;
for(size_t j = 0; j < n; ++j)
select_domain[j] = true;
sparsity_type hes_pattern;
f.for_hes_sparsity (
select_domain , select_range , internal_bool , hes_pattern
);
//
// ok
// The sparsity calculation does not distinguish between different elements
// of a valvector so the sparsity pattern fills in (this is not efficient).
ok &= hes_pattern.nnz() == n * n;
ok &= hes_pattern.nr() == n;
ok &= hes_pattern.nc() == n;
{ CPPAD_TESTVECTOR(size_t) col_major = hes_pattern.col_major();
const CPPAD_TESTVECTOR(size_t)& row = hes_pattern.row();
const CPPAD_TESTVECTOR(size_t)& col = hes_pattern.col();
size_t k = 0;
for(size_t j = 0; j < n; ++j)
{ for(size_t i = 0; i < n; ++i)
{ ok &= row[ col_major[k] ] == i;
ok &= col[ col_major[k] ] == j;
++k;
}
}
}
//
// af
typedef CppAD::ADFun<ad_valvector, valvector> ad_fun_type;
ad_fun_type af = ad_fun_type( f.base2ad() );
//
// g
CPPAD_TESTVECTOR( ad_valvector ) adx(n), adz(m);
for(size_t j = 0; j < n; ++j)
adx[j] = valvector( 1.0 );
CppAD::Independent(ax);
af.Forward(0, ax);
adz = af.Forward(1, adx);
CppAD::ADFun<valvector> g(ax, adz);
//
// ok
CPPAD_TESTVECTOR( valvector ) dz(m);
dz = g.Forward(0, x);
for(size_t j = 0; j < n; ++j)
ok &= dz[0][j] == 2.0 * x[j][0];
//
// h
CPPAD_TESTVECTOR( ad_valvector ) aw(m), adw(n);
aw[0] = valvector( 1.0 );
CppAD::Independent(ax);
af.Forward(0, ax);
adw = af.Reverse(1, aw);
CppAD::ADFun<valvector> h(ax, adw);
//
// ok
dw = h.Forward(0, x);
for(size_t j = 0; j < n; ++j)
ok &= dw[j][0] == 2.0 * x[j][0];
//
// ok
f.optimize();
z = f.Forward(0, x);
for(size_t j = 0; j < n; ++j)
ok &= z[0][j] == x[j][0] * x[j][0];
//
return ok;
}