\(\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}} }\)
atomic_four_mat_mul_rev_depend.cpp¶
View page sourceAtomic Matrix Multiply Reverse Dependency: Example and Test¶
Purpose¶
This example uses the atomic matrix multiply
rev_depend
function to reduce the number of variables in
the recording of \(g(u)\).
f(u)¶
Forward Analysis¶
Forward dependency analysis determines that there is a new variable for each of the 8 multiplications by 2.0. It also determines, using for_type that each of the 4 elements in the matrix product result is a new variable.
Reverse Analysis¶
Reverse analysis detect that only 1 of the 4 elements in the matrix product is used. In addition it determines, using rev_depend , that only 4 of the 8 multiplications by 2.0 are used.
size_var¶
The difference in size_var is the difference between only using forward dependency and using both; i.e., (8 - 4) + (4 - 1) = 7.
Source¶
# include <cppad/cppad.hpp>
# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>
bool rev_depend(void)
{ // ok, eps
bool ok = true;
//
// AD
using CppAD::AD;
using CppAD::sparse_rc;
// -----------------------------------------------------------------------
// Record g
// -----------------------------------------------------------------------
//
// afun
CppAD::atomic_mat_mul<double> afun("atomic_mat_mul");
//
// nleft, n_middle, n_right
size_t n_left = 2, n_middle = 2, n_right = 2;
//
// nu, au
size_t nu = n_middle * (n_left + n_right);
CPPAD_TESTVECTOR( AD<double> ) au(nu);
for(size_t j = 0; j < nu; ++j)
au[j] = AD<double>(j + 2);
CppAD::Independent(au);
//
// nx, ax
CPPAD_TESTVECTOR( AD<double> ) ax(nu);
for(size_t j = 0; j < nu; ++j)
ax[j] = 2.0 * au[j];
//
// ny, ay
size_t ny = n_left * n_right;
CPPAD_TESTVECTOR( AD<double> ) ay(ny);
size_t call_id = afun.set(n_left, n_middle, n_right);
afun(call_id, ax, ay);
//
// az = f_{0,0} (x)
CPPAD_TESTVECTOR( AD<double> ) az(1);
az[0] = ay[ 0 * n_right + 0 ];
//
// g
CppAD::ADFun<double> g(au, az);
//
// size_var_before
size_t size_var_before = g.size_var();
//
//
// optimize
g.optimize("val_graph no_conditional_skip");
//
// size_var_after
size_t size_var_after = g.size_var();
//
// ok
ok &= size_var_before - size_var_after == 7;
//
return ok;
}