Prev Next Index-> contents reference index search external Up-> CppAD AD ADValued atomic atomic_base atomic_forward ADValued-> Arithmetic unary_standard_math binary_math CondExp Discrete numeric_limits atomic atomic-> checkpoint atomic_base atomic_base-> atomic_ctor atomic_option atomic_afun atomic_forward atomic_reverse atomic_for_sparse_jac atomic_rev_sparse_jac atomic_for_sparse_hes atomic_rev_sparse_hes atomic_base_clear atomic_get_started.cpp atomic_norm_sq.cpp atomic_reciprocal.cpp atomic_set_sparsity.cpp atomic_tangent.cpp atomic_eigen_mat_mul.cpp atomic_eigen_mat_inv.cpp atomic_eigen_cholesky.cpp atomic_mat_mul.cpp atomic_forward-> atomic_forward.cpp Headings-> Syntax Purpose Implementation p q vx vy tx ty ok Discussion Examples

Atomic Forward Mode

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

Purpose
This virtual function is used by atomic_afun to evaluate function values. It is also used buy 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_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_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_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 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 (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 . For $j = 0 , \ldots , n-1$ and $k = 0 , \ldots , q$, we use the Taylor coefficient notation $$\begin{array}{rcl} 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{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)$$

ty
The argument ty has prototype       CppAD::vector<Base>& ty  and tx.size() == (q+1)*m . Upon return, For $i = 0 , \ldots , m-1$ and $k = 0 , \ldots , q$, $$\begin{array}{rcl} 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{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)$$ 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.

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{array}{rcl} 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{array}$$ For $i = 0 , \ldots , m-1$, and $k = 0 , 1 , 2$, $$ty [ i * (q + 1) + k ] = y_i^k$$

Examples
The file atomic_forward.cpp contains an example and test that uses this routine. It returns true if the test passes and false if it fails.