atomic_two_forward

View page source

Atomic Forward Mode

Syntax

Base

ok = afun . forward ( p , q , vx , vy , tx , ty )

This syntax is used by f . Forward where f has prototype

ADFun < Base > f

and afun is used in f .

AD<Base>

ok = afun . forward ( p , q , vx , vy , atx , aty )

This syntax is used by af . Forward where af has prototype

ADFun< AD< Base > , Base > af

and afun is used in af (see base2ad ).

Purpose

This virtual function is used by atomic_two_afun to evaluate function values. It is also used buy f.Forward (and af . Forward ) to compute function vales and derivatives.

Implementation

This virtual function must be defined by the atomic_user class. It can just return ok == false (and not compute anything) for values of q > 0 that are greater than those used by your Forward mode calculations.

p

The argument p has prototype

size_t p

It specifies the lowest order Taylor coefficient that we are evaluating. During calls to atomic_two_afun , p == 0 .

q

The argument q has prototype

size_t q

It specifies the highest order Taylor coefficient that we are evaluating. During calls to atomic_two_afun , q == 0 .

vx

The forward argument vx has prototype

const CppAD::vector<bool>& vx

The case vx . size () > 0 only occurs while evaluating a call to atomic_two_afun . In this case, p == q == 0 , vx . size () == n , and for \(j = 0 , \ldots , n-1\), vx [ j ] is true if and only if ax [ j ] is a Variable or dynamic parameter in the corresponding call to

afun ( ax , ay )

If vx . size () == 0 , then vy . size () == 0 and neither of these vectors should be used.

vy

The forward argument vy has prototype

CppAD::vector<bool>& vy

If vy . size () == 0 , it should not be used. Otherwise, q == 0 and vy . size () == m . The input values of the elements of vy are not specified (must not matter). Upon return, for \(j = 0 , \ldots , m-1\), vy [ i ] is true if and only if ay [ i ] is a variable or dynamic parameter (CppAD uses vy to reduce the necessary computations).

tx

The argument tx has prototype

const CppAD::vector< Base >& tx

and tx . size () == ( q +1)* n . It is used by f . Forward where f has type ADFun < Base > f and afun is used in f . For \(j = 0 , \ldots , n-1\) and \(k = 0 , \ldots , q\), we use the Taylor coefficient notation

\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 \(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)\]

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

CppAD::vector< Base >& ty

and tx . size () == ( q +1)* m . It is set by f . Forward where f has type ADFun < Base > f and afun is used in f . Upon return, For \(i = 0 , \ldots , m-1\) and \(k = 0 , \ldots , q\),

\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 ) \\ ty [ i * ( q + 1 ) + k ] & = & y_i^k \end{eqnarray}

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)\]

If \(p > 0\), for \(i = 0 , \ldots , m-1\) and \(k = 0 , \ldots , p-1\), the input of ty satisfies

\[ty [ i * ( q + 1 ) + k ] = y_i^k\]

and hence the corresponding elements need not be recalculated.

aty

The argument aty has prototype

const CppAD::vector< AD< Base > >& aty

Otherwise, aty specifications are the same as for ty .

ok

If the required results are calculated, ok should be true. Otherwise, it should be false.

Discussion

For example, suppose that q == 2 , and you know how to compute the function \(f(x)\), its first derivative \(f^{(1)} (x)\), and it component wise Hessian \(f_i^{(2)} (x)\). Then you can compute ty using the following formulas:

\begin{eqnarray} y_i^0 & = & Y(0) = f_i ( x^0 ) \\ y_i^1 & = & Y^{(1)} ( 0 ) = f_i^{(1)} ( x^0 ) X^{(1)} ( 0 ) = f_i^{(1)} ( x^0 ) x^1 \\ y_i^2 & = & \frac{1}{2 !} Y^{(2)} (0) \\ & = & \frac{1}{2} X^{(1)} (0)^\R{T} f_i^{(2)} ( x^0 ) X^{(1)} ( 0 ) + \frac{1}{2} f_i^{(1)} ( x^0 ) X^{(2)} ( 0 ) \\ & = & \frac{1}{2} (x^1)^\R{T} f_i^{(2)} ( x^0 ) x^1 + f_i^{(1)} ( x^0 ) x^2 \end{eqnarray}

For \(i = 0 , \ldots , m-1\), and \(k = 0 , 1 , 2\),

\[ty [ i * (q + 1) + k ] = y_i^k\]