|
Prev
| Next
|
|
|
|
|
|
atomic_four_mat_mul_identical_zero.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
.
Atomic Matrix Multiply Identical Zero: Example and Test
Purpose
This example demonstrates how the
atomic_four_mat_mul_for_type.hpp
routine uses the
identical_zero_enum
type to reduce the number
of variables.
Zero
The first case computes the following matrix product
@[@
\left( \begin{array}{ccc}
u_0 & 0 & 0 \\
0 & u_1 & 0 \\
0 & 0 & u_2
\end{array} \right)
\left( \begin{array}{ccc}
u_3 & 0 & 0 \\
0 & u_4 & 0 \\
0 & 0 & u_5
\end{array} \right)
=
\left( \begin{array}{ccc}
u_0 u_3 & 0 & 0 \\
0 & u_1 u_4 & 0 \\
0 & 0 & u_2 u_5
\end{array} \right)
@]@
The result matrix for this case has three variables,
one for each product on the diagonal.
One
The second case computes the following matrix product
@[@
\left( \begin{array}{ccc}
u_0 & 1 & 1 \\
1 & u_1 & 1 \\
1 & 1 & u_2
\end{array} \right)
\left( \begin{array}{ccc}
u_3 & 1 & 1 \\
1 & u_4 & 1 \\
1 & 1 & u_5
\end{array} \right)
=
\left( \begin{array}{ccc}
u_0 u_3 + 2 & u_0 + u_3 + 1 & u_0 + u_5 + 1 \\
u_1 + u_3 + 1 & u_1 u_4 + 2 & u_1 + u_5 + 1 \\
u_2 + u_3 + 1 & u_2 + u_4 + 1 & u_2 u_5 + 2
\end{array} \right)
@]@
The result matrix for this case has nine variables,
one for each of its elements.
Source
# include <cppad/cppad.hpp>
# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>
bool identical_zero(void)
{ // ok, eps
bool ok = true;
//
// AD, NearEqual
using CppAD::AD;
using CppAD::NearEqual;
// -----------------------------------------------------------------------
// Record f
// -----------------------------------------------------------------------
//
// afun
CppAD::atomic_mat_mul<double> afun("atomic_mat_mul");
//
// nleft
size_t size = 3;
//
// size_var
size_t size_var[2];
//
// zero_one
for(size_t zero_one = 0; zero_one < 2; ++zero_one)
{ //
// n_right, n_middle
size_t n_left = size, n_middle = size, n_right = size;
//
// nu, au
size_t nu = 2 * size;
CPPAD_TESTVECTOR( AD<double> ) au(nu);
for(size_t j = 0; j < nu; ++j)
au[j] = AD<double>(j + 2);
CppAD::Independent(au);
//
// offset
size_t offset = size * size;
//
// nx, ax
size_t nx = size * (size + size);
CPPAD_TESTVECTOR( AD<double> ) ax(nx);
for(size_t i = 0; i < size; ++i)
{ for(size_t j = 0; j < size; ++j)
{ // left
size_t ij = i * size + j;
if( i == j )
ax[ij] = au[j];
else
ax[ij] = AD<double>(zero_one);
// right
ij = offset + i * n_right + j;
if( i == j )
ax[ij] = au[i];
else
ax[ij] = AD<double>(zero_one);
}
}
//
// ay
size_t ny = size * size;
CPPAD_TESTVECTOR( AD<double> ) ay(ny);
size_t call_id = afun.set(n_left, n_middle, n_right);
afun(call_id, ax, ay);
//
// av
size_t nv = size;
CPPAD_TESTVECTOR( AD<double> ) av(nv);
for(size_t i = 0; i < nv; ++i)
av[i] += ay[i * size + i];
//
// f
CppAD::ADFun<double> f(au, av);
//
// size_var
size_var[zero_one] = f.size_var();
}
// ok
ok = size_var[1] - size_var[0] == size * size - size;
//
return ok;
}
Input File: example/atomic_four/mat_mul/identical_zero.cpp