lines 8-266 of file: include/cppad/core/atomic/two/reverse.hpp {xrst_begin atomic_two_reverse app} {xrst_spell apx apy atx aty px py superscripts tx } Atomic Reverse Mode ################### Syntax ****** Base ==== *ok* = *afun* . ``reverse`` ( *q* , *tx* , *ty* , *px* , *py* ) This syntax is used by *f* . ``Forward`` where *f* has prototype ``ADFun`` < *Base* > *f* and *afun* is used in *f* . AD ======== *ok* = *afun* . ``reverse`` ( *q* , *atx* , *aty* , *apx* , *apy* ) This syntax is used by *af* . ``Forward`` where *af* has prototype ``ADFun< AD<`` *Base* > , *Base* > *af* and *afun* is used in *af* (see :ref:`base2ad-name` ). Purpose ******* This function is used by :ref:`Reverse-name` to compute derivatives. Implementation ************** If you are using :ref:`Reverse-name` mode, this virtual function must be defined by the :ref:`atomic_two_ctor@atomic_user` class. It can just return *ok* == ``false`` (and not compute anything) for values of *q* that are greater than those used by your :ref:`Reverse-name` mode calculations. q * The argument *q* has prototype ``size_t`` *q* It specifies the highest order Taylor coefficient that computing the derivative of. tx ** The argument *tx* has prototype ``const CppAD::vector<`` *Base* >& *tx* and *tx* . ``size`` () == ( *q* +1)* *n* . For :math:`j = 0 , \ldots , n-1` and :math:`k = 0 , \ldots , q`, we use the Taylor coefficient notation .. math:: :nowrap: \begin{eqnarray} x_j^k & = & tx [ j * ( q + 1 ) + k ] \\ X_j (t) & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^q t^q \end{eqnarray} Note that superscripts represent an index for :math:`x_j^k` and an exponent for :math:`t^k`. Also note that the Taylor coefficients for :math:`X(t)` correspond to the derivatives of :math:`X(t)` at :math:`t = 0` in the following way: .. math:: x_j^k = \frac{1}{ k ! } X_j^{(k)} (0) atx *** The argument *atx* has prototype ``const CppAD::vector< AD<`` *Base* > >& *atx* Otherwise, *atx* specifications are the same as for *tx* . ty ** The argument *ty* has prototype ``const CppAD::vector<`` *Base* >& *ty* and *tx* . ``size`` () == ( *q* +1)* *m* . For :math:`i = 0 , \ldots , m-1` and :math:`k = 0 , \ldots , q`, we use the Taylor coefficient notation .. math:: :nowrap: \begin{eqnarray} Y_i (t) & = & f_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 & = & ty [ i * ( q + 1 ) + k ] \end{eqnarray} where :math:`o( t^q ) / t^q \rightarrow 0` as :math:`t \rightarrow 0`. Note that superscripts represent an index for :math:`y_j^k` and an exponent for :math:`t^k`. Also note that the Taylor coefficients for :math:`Y(t)` correspond to the derivatives of :math:`Y(t)` at :math:`t = 0` in the following way: .. math:: y_j^k = \frac{1}{ k ! } Y_j^{(k)} (0) aty *** The argument *aty* has prototype ``const CppAD::vector< AD<`` *Base* > >& *aty* Otherwise, *aty* specifications are the same as for *ty* . F * We use the notation :math:`\{ x_j^k \} \in \B{R}^{n \times (q+1)}` for .. math:: \{ x_j^k \W{:} j = 0 , \ldots , n-1, k = 0 , \ldots , q \} We use the notation :math:`\{ y_i^k \} \in \B{R}^{m \times (q+1)}` for .. math:: \{ y_i^k \W{:} i = 0 , \ldots , m-1, k = 0 , \ldots , q \} We define the function :math:`F : \B{R}^{n \times (q+1)} \rightarrow \B{R}^{m \times (q+1)}` by .. math:: y_i^k = F_i^k [ \{ x_j^k \} ] Note that .. math:: F_i^0 ( \{ x_j^k \} ) = f_i ( X(0) ) = f_i ( x^0 ) We also note that :math:`F_i^\ell ( \{ x_j^k \} )` is a function of :math:`x^0 , \ldots , x^\ell` and is determined by the derivatives of :math:`f_i (x)` up to order :math:`\ell`. G, H **** We use :math:`G : \B{R}^{m \times (q+1)} \rightarrow \B{R}` to denote an arbitrary scalar valued function of :math:`\{ y_i^k \}`. We use :math:`H : \B{R}^{n \times (q+1)} \rightarrow \B{R}` defined by .. math:: H ( \{ x_j^k \} ) = G[ F( \{ x_j^k \} ) ] py ** The argument *py* has prototype ``const CppAD::vector<`` *Base* >& *py* and *py* . ``size`` () == ``m`` * ( *q* +1) . For :math:`i = 0 , \ldots , m-1`, :math:`k = 0 , \ldots , q`, .. math:: py[ i * (q + 1 ) + k ] = \partial G / \partial y_i^k apy *** The argument *apy* has prototype ``const CppAD::vector< AD<`` *Base* > >& *apy* Otherwise, *apy* specifications are the same as for *py* . px == The *px* has prototype ``CppAD::vector<`` *Base* >& *px* and *px* . ``size`` () == ``n`` * ( *q* +1) . The input values of the elements of *px* are not specified (must not matter). Upon return, for :math:`j = 0 , \ldots , n-1` and :math:`\ell = 0 , \ldots , q`, .. math:: :nowrap: \begin{eqnarray} px [ 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} py[ i * (q + 1 ) + k ] ( \partial F_i^k / \partial x_j^\ell ) \end{eqnarray} Note that we have used the fact that for :math:`k < \ell`, :math:`\partial F_i^k / \partial x_j^\ell = 0`. apx *** The argument *apx* has prototype ``CppAD::vector< AD<`` *Base* > >& *apx* Otherwise, *apx* specifications are the same as for *px* . ok ** The return value *ok* has prototype ``bool`` *ok* If it is ``true`` , the corresponding evaluation succeeded, otherwise it failed. {xrst_end atomic_two_reverse}