\(\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}} }\)
atomic_four_forward¶
View page sourceAtomic Function Forward Mode¶
Syntax¶
Base¶
forward
(AD<Base>¶
forward
(Prototype¶
Base¶
template <class Base>
bool atomic_four<Base>::forward(
size_t call_id ,
const vector<bool>& select_y ,
size_t order_low ,
size_t order_up ,
const vector<Base>& taylor_x ,
vector<Base>& taylor_y )
AD<Base>¶
template <class Base>
bool atomic_four<Base>::forward(
size_t call_id ,
const vector<bool>& select_y ,
size_t order_low ,
size_t order_up ,
const vector< AD<Base> >& ataylor_x ,
vector< AD<Base> >& ataylor_y )
Base¶
see Base .
vector¶
is the CppAD_vector template class.
Usage¶
Base¶
The Base syntax and prototype are used by a
call to the atomic function afun .
They are also used by
f . Forward
and f . new_dynamic
where f has prototype
ADFun
< Base > f
and afun is used during the recording of f .
AD<Base>¶
The AD
< Base > syntax and prototype are used by
af . Forward
and af . new_dynamic
where af has prototype
ADFun< AD<
Base > , Base > af
and afun is used in a function af , created from f using base2ad .
Implementation¶
The taylor_x , taylor_y version of this function
must be defined by the
atomic_user class.
It can return ok == false
(and not compute anything) for values
of order_up that are greater than those used by your
Forward mode calculations.
Order zero must be implemented.
call_id¶
See call_id .
select_y¶
This argument has size equal to the number of results to this atomic function; i.e. the size of ay . It specifies which components of y the corresponding Taylor coefficients must be computed.
order_low¶
This argument specifies the lowest order Taylor coefficient that we are computing.
p¶
We sometimes use the notation p = order_low below.
order_up¶
This argument is the highest order Taylor coefficient that we are computing ( order_low <= order_up ).
q¶
We use the notation q = order_up + 1 below. This is the number of Taylor coefficients for each component of x and y .
taylor_x¶
The size of taylor_x is q * n . For \(j = 0 , \ldots , n-1\) and \(k = 0 , \ldots , q-1\), we use the Taylor coefficient notation
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:
parameters¶
If the j-th component of x is a parameter,
type_x [ j ] <
CppAD::variable_enum
In this case, for k > 0 ,
taylor_x [ j * q + 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 * m . Upon return, For \(i = 0 , \ldots , m-1\) and \(k = 0 , \ldots , q-1\), if select_y [ i ] is true,
where \(o( t^{q-1} ) / t^{q-1} \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:
If \(p > 0\), for \(i = 0 , \ldots , m-1\) and \(k = 0 , \ldots , p-1\), the input of taylor_y satisfies
These values do not need to be recalculated and can be used during the computation of the higher order coefficients.
ataylor_y¶
The specifications for ataylor_y is the same as for taylor_y (only the type of ataylor_y is different).
ok¶
If this calculation succeeded, ok is true. Otherwise, it is false.
Discussion¶
For example, suppose that order_up == 2 , and you know how to compute the function \(g(x)\), its first derivative \(g^{(1)} (x)\), and it component wise Hessian \(g_i^{(2)} (x)\). Then you can compute taylor_x using the following formulas:
For \(i = 0 , \ldots , m-1\), and \(k = 0 , 1 , 2\),
Example¶
The following is an example forward
definition taken from
atomic_four_norm_sq.cpp :
bool forward(
size_t call_id ,
const CppAD::vector<bool>& select_y ,
size_t order_low ,
size_t order_up ,
const CppAD::vector<double>& tx ,
CppAD::vector<double>& ty ) override
{
size_t q = order_up + 1;
size_t n = tx.size() / q;
# ifndef NDEBUG
size_t m = ty.size() / q;
assert( call_id == 0 );
assert( m == 1 );
assert( m == select_y.size() );
# endif
// ok
bool ok = order_up <= 1 && order_low <= order_up;
if ( ! ok )
return ok;
//
// sum = x_0^0 * x_0^0 + x_1^0 * x_1^0 + ...
double sum = 0.0;
for(size_t j = 0; j < n; ++j)
{ double xj0 = tx[ j * q + 0];
sum += xj0 * xj0;
}
//
// ty[0] = sum
if( order_low <= 0 )
ty[0] = sum;
if( order_up < 1 )
return ok;
// sum = x_0^0 * x_0^1 + x_1^0 ^ x_1^1 + ...
sum = 0.0;
for(size_t j = 0; j < n; ++j)
{ double xj0 = tx[ j * q + 0];
double xj1 = tx[ j * q + 1];
sum += xj0 * xj1;
}
// ty[1] = 2.0 * sum
assert( order_up == 1 );
ty[1] = 2.0 * sum;
return ok;
}