lines 7-120 of file: example/general/rev_checkpoint.cpp

{xrst_begin rev_checkpoint.cpp}

Reverse Mode General Case (Checkpointing): Example and Test
###########################################################

See Also
********
:ref:`checkpoint<chkpoint_one-name>`

Purpose
*******
Break a large computation into pieces and only store values at the
interface of the pieces (this is much easier to do using :ref:`checkpoint<chkpoint_one-name>` ).
In actual applications, there may be many functions, but
for this example there are only two.
The functions
:math:`F : \B{R}^2 \rightarrow \B{R}^2`
and
:math:`G : \B{R}^2 \rightarrow \B{R}^2`
defined by

.. math::

   F(x) = \left( \begin{array}{c} x_0 x_1   \\ x_1 - x_0 \end{array} \right)
   \; , \;
   G(y) = \left( \begin{array}{c} y_0 - y_1 \\ y_1  y_0   \end{array} \right)

Processing Steps
****************
We apply reverse mode to compute the derivative of
:math:`H : \B{R}^2 \rightarrow \B{R}`
is defined by

.. math::
   :nowrap:

   \begin{eqnarray}
      H(x)
      & = & G_0 [ F(x) ] + G_1 [ F(x)  ]
      \\
      & = & x_0 x_1 - ( x_1 - x_0 ) + x_0 x_1 ( x_1 - x_0 )
      \\
      & = & x_0 x_1 ( 1 - x_0 + x_1 ) - x_1 + x_0
   \end{eqnarray}

Given the zero and first order Taylor coefficients
:math:`x^{(0)}` and :math:`x^{(1)}`,
we use :math:`X(t)`, :math:`Y(t)` and :math:`Z(t)`
for the corresponding functions; i.e.,

.. math::
   :nowrap:

   \begin{eqnarray}
      X(t) & = & x^{(0)} + x^{(1)} t
      \\
      Y(t) & = & F[X(t)] = y^{(0)} + y^{(1)} t  + O(t^2)
      \\
      Z(t) & = & G \{ F [ X(t) ] \} = z^{(0)} + z^{(1)} t  + O(t^2)
      \\
      h^{(0)} & = & z^{(0)}_0 + z^{(0)}_1
      \\
      h^{(1)} & = & z^{(1)}_0 + z^{(1)}_1
   \end{eqnarray}

Here are the processing steps:

#. Use forward mode on :math:`F(x)` to compute
   :math:`y^{(0)}` and :math:`y^{(1)}`.
#. Free some, or all, of the memory corresponding to :math:`F(x)`.
#. Use forward mode on :math:`G(y)` to compute
   :math:`z^{(0)}` and :math:`z^{(1)}`
#. Use reverse mode on :math:`G(y)` to compute the derivative of
   :math:`h^{(1)}` with respect to
   :math:`y^{(0)}` and :math:`y^{(1)}`.
#. Free all the memory corresponding to :math:`G(y)`.
#. Use reverse mode on :math:`F(x)` to compute the derivative of
   :math:`h^{(1)}` with respect to
   :math:`x^{(0)}` and :math:`x^{(1)}`.

This uses the following relations:

.. math::
   :nowrap:

   \begin{eqnarray}
      \partial_{x(0)} h^{(1)} [ x^{(0)} , x^{(1)} ]
      & = &
      \partial_{y(0)} h^{(1)} [ y^{(0)} , y^{(1)} ]
      \partial_{x(0)} y^{(0)} [ x^{(0)} , x^{(1)} ]
      \\
      & + &
      \partial_{y(1)} h^{(1)} [ y^{(0)} , y^{(1)} ]
      \partial_{x(0)} y^{(1)} [ x^{(0)} , x^{(1)} ]
      \\
      \partial_{x(1)} h^{(1)} [ x^{(0)} , x^{(1)} ]
      & = &
      \partial_{y(0)} h^{(1)} [ y^{(0)} , y^{(1)} ]
      \partial_{x(1)} y^{(0)} [ x^{(0)} , x^{(1)} ]
      \\
      & + &
      \partial_{y(1)} h^{(1)} [ y^{(0)} , y^{(1)} ]
      \partial_{x(1)} y^{(1)} [ x^{(0)} , x^{(1)} ]
   \end{eqnarray}

where :math:`\partial_{x(0)}` denotes the partial with respect
to :math:`x^{(0)}`.

{xrst_literal
   // BEGIN C++
   // END C++
}

{xrst_end rev_checkpoint.cpp}
