Prev Next

@(@\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 Function Reverse Mode

Base
This syntax is used by f.Reverse where f has prototype
    ADFun<
Basef
and afun is used in f ; see Base .

Syntax
ok = afun.reverse(
    
parameter_xtype_x,
    
order_uptaylor_xtaylor_ypartial_xpartial_y
)

Prototype

template <class Base>
bool atomic_three<Base>::reverse(
    const vector<Base>&         parameter_x ,
    const vector<ad_type_enum>& type_x      ,
    size_t                      order_up    ,
    const vector<Base>&         taylor_x    ,
    const vector<Base>&         taylor_y    ,
    vector<Base>&               partial_x   ,
    const vector<Base>&         partial_y   )

AD<Base>
This syntax is used by af.Reverse where af has prototype
    ADFun< AD<
Base> , Base > af
and afun is used in af (see base2ad ).

Syntax
ok = afun.reverse(
    
aparameter_xtype_x,
    
order_upataylor_xataylor_yapartial_xapartial_y
)

Prototype

template <class Base>
bool atomic_three<Base>::reverse(
    const vector< AD<Base> >&       aparameter_x ,
    const vector<ad_type_enum>&     type_x       ,
    size_t                          order_up     ,
    const vector< AD<Base> >&       ataylor_x    ,
    const vector< AD<Base> >&       ataylor_y    ,
    vector< AD<Base> >&             apartial_x   ,
    const vector< AD<Base> >&       apartial_y   )

Implementation
This function must be defined if afun is used to define an ADFun object f , and reverse mode derivatives are computed for f . It can return ok == false (and not compute anything) for values of order_up that are greater than those used by your reverse mode calculations.

parameter_x
See parameter_x .

aparameter_x
The specifications for aparameter_x is the same as for parameter_x (only the type of ataylor_x is different).

type_x
See type_x .

order_up
This argument specifies the highest order Taylor coefficient that computing the derivative of.

taylor_x
The size of taylor_x is (q+1)*n . For @(@ j = 0 , \ldots , n-1 @)@ and @(@ k = 0 , \ldots , q @)@, we use the Taylor coefficient notation @[@ \begin{array}{rcl} x_j^k & = & \R{taylor\_x} [ j * ( q + 1 ) + k ] \\ X_j (t) & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^q t^q \end{array} @]@ Note that superscripts represent an index for @(@ x_j^k @)@ and an exponent for @(@ t^k @)@. Also note that the Taylor coefficients for @(@ X(t) @)@ correspond to the derivatives of @(@ X(t) @)@ at @(@ t = 0 @)@ in the following way: @[@ x_j^k = \frac{1}{ k ! } X_j^{(k)} (0) @]@

parameters
If the j-th component of x corresponds to a parameter,
    
type_x[j] < CppAD::variable_enum
In this case, the j-th component of parameter_x is equal to @(@ x_j^0 @)@; i.e.,
    
parameter_x[j] == taylor_xj * ( q + 1 ) + 0 ]
Furthermore, for k > 0 ,
    
taylor_xj * ( q + 1 ) + k ] == 0

ataylor_x
The specifications for ataylor_x is the same as for taylor_x (only the type of ataylor_x is different).

taylor_y
The size of taylor_y is (q+1)*m . For @(@ i = 0 , \ldots , m-1 @)@ and @(@ k = 0 , \ldots , q @)@, we use the Taylor coefficient notation @[@ \begin{array}{rcl} Y_i (t) & = & g_i [ X(t) ] \\ Y_i (t) & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^q t^q + o ( t^q ) \\ y_i^k & = & \R{taylor\_y} [ i * ( q + 1 ) + k ] \end{array} @]@ where @(@ o( t^q ) / t^q \rightarrow 0 @)@ as @(@ t \rightarrow 0 @)@. Note that superscripts represent an index for @(@ y_j^k @)@ and an exponent for @(@ t^k @)@. Also note that the Taylor coefficients for @(@ Y(t) @)@ correspond to the derivatives of @(@ Y(t) @)@ at @(@ t = 0 @)@ in the following way: @[@ y_j^k = \frac{1}{ k ! } Y_j^{(k)} (0) @]@

ataylor_y
The specifications for ataylor_y is the same as for taylor_y (only the type of ataylor_y is different).

F
We use the notation @(@ \{ x_j^k \} \in \B{R}^{n \times (q+1)} @)@ for @[@ \{ x_j^k \W{:} j = 0 , \ldots , n-1, k = 0 , \ldots , q \} @]@ We use the notation @(@ \{ y_i^k \} \in \B{R}^{m \times (q+1)} @)@ for @[@ \{ y_i^k \W{:} i = 0 , \ldots , m-1, k = 0 , \ldots , q \} @]@ We define the function @(@ F : \B{R}^{n \times (q+1)} \rightarrow \B{R}^{m \times (q+1)} @)@ by @[@ y_i^k = F_i^k [ \{ x_j^k \} ] @]@ Note that @[@ F_i^0 ( \{ x_j^k \} ) = g_i ( X(0) ) = g_i ( x^0 ) @]@ We also note that @(@ F_i^\ell ( \{ x_j^k \} ) @)@ is a function of @(@ x^0 , \ldots , x^\ell @)@ and is determined by the derivatives of @(@ g_i (x) @)@ up to order @(@ \ell @)@.

G, H
We use @(@ G : \B{R}^{m \times (q+1)} \rightarrow \B{R} @)@ to denote an arbitrary scalar valued function of @(@ \{ y_i^k \} @)@. We use @(@ H : \B{R}^{n \times (q+1)} \rightarrow \B{R} @)@ defined by @[@ H ( \{ x_j^k \} ) = G[ F( \{ x_j^k \} ) ] @]@

partial_y
The size of partial_y is (q+1)*m . For @(@ i = 0 , \ldots , m-1 @)@, @(@ k = 0 , \ldots , q @)@, @[@ \R{partial\_y} [ i * (q + 1 ) + k ] = \partial G / \partial y_i^k @]@

apartial_y
The specifications for apartial_y is the same as for partial_y (only the type of apartial_y is different).

partial_x
The size of partial_x is (q+1)*n . The input values of the elements of partial_x are not specified (must not matter). Upon return, for @(@ j = 0 , \ldots , n-1 @)@ and @(@ \ell = 0 , \ldots , q @)@, @[@ \begin{array}{rcl} \R{partial\_x} [ j * (q + 1) + \ell ] & = & \partial H / \partial x_j^\ell \\ & = & ( \partial G / \partial \{ y_i^k \} ) \cdot ( \partial \{ y_i^k \} / \partial x_j^\ell ) \\ & = & \sum_{k=0}^q \sum_{i=0}^{m-1} ( \partial G / \partial y_i^k ) ( \partial y_i^k / \partial x_j^\ell ) \\ & = & \sum_{k=\ell}^q \sum_{i=0}^{m-1} \R{partial\_y}[ i * (q + 1 ) + k ] ( \partial F_i^k / \partial x_j^\ell ) \end{array} @]@ Note that we have used the fact that for @(@ k < \ell @)@, @(@ \partial F_i^k / \partial x_j^\ell = 0 @)@.

Short Circuit Operations
For the Base prototype, if IdenticalZero(partial_y[i*(q+1)+k]) is true, one does not need to compute @(@ ( \partial F_i^k / \partial x_j^\ell ) @)@; see base_identical . This can be used, in a similar way to need_y , to avoid unnecessary operations.

azmul
An optimized function will use zero for values in taylor_x and taylor_y that are not necessary in the current context. If you divide by these values when computing @(@ ( \partial F_i^k / \partial x_j^\ell ) @)@ you could get an nan if the corresponding value in partial_y is zero. To be careful, if you do divide by taylor_x or taylor_y , use azmul for to avoid zero over zero calculations.

apartial_x
The specifications for apartial_x is the same as for partial_x (only the type of apartial_x is different).

ok
If this calculation succeeded, ok is true. Otherwise it is false.

Examples
The file atomic_three_reverse.cpp contains an example and test that uses this routine.
Input File: include/cppad/core/atomic/three/reverse.hpp