AD Vectors that Record Index Operations

Syntax
VecAD<Base> v(n)   v.size()   b = v[i]   r = v[x]

Purpose
If either v or x is a variable , the indexing operation       y = v[x]  is recorded in the corresponding AD of Base operation sequence and transferred to the corresponding ADFun object f . Such an index can change each time zero order f.Forward is used; i.e., f is evaluated with new value for the independent variables . Note that the value of y depends on the value of x in a discrete fashion and CppAD computes its partial derivative with respect to x as zero.

Alternatives
If only the values in the vector, and not the indices, depend on the independent variables, the class Vector< AD<Base> > is much more efficient for storing AD values where Vector is any SimpleVector template class, If only the indices, and not the values in the vector, depend on the independent variables, The Discrete functions are a much more efficient way to represent these vectors.

The result y has type       VecAD<Base>::reference  which is very much like the AD<Base> type with some notable exceptions:

Exceptions
1. The object y cannot be used with the Value function to compute the corresponding Base value. If v is not a variable       v[i]  can be used to compute the corresponding Base value.
2. The object y cannot be used with the computed assignments operators +=, -=, *=, or /=. For example, the following syntax is not valid:       v[x] += z;  no matter what the types of z .
3. Assignment to y returns a void. For example, the following syntax is not valid:       z = v[x] = u;  no matter what the types of z , and u .
4. The CondExp functions do not accept VecAD<Base>::reference arguments. For example, the following syntax is not valid:       CondExpGt(y, z, u, v)  no matter what the types of z , u , and v .
5. The Parameter and Variable functions cannot be used with VecAD<Base>::reference arguments (use the entire VecAD<Base> vector instead).
6. The vectors passed to Independent must have elements of type AD<Base> ; i.e., VecAD vectors cannot be passed to Independent.
7. If one uses this type in a AD of Base operation sequence , sparsity pattern calculations (Sparse ) are less efficient because the dependence of different elements of the vector cannot be separated.

Constructor

v
The syntax       VecAD<Base> v(n)  creates an VecAD object v with n elements. The initial value of the elements of v is unspecified.

n
The argument n has prototype       size_t n 
size
The syntax       v.size()  returns the number of elements in the vector v ; i.e., the value of n when it was constructed.

size_t Indexing
We refer to the syntax       b = v[i]  as size_t indexing of a VecAD object. This indexing is only valid if the vector v is a parameter ; i.e., it does not depend on the independent variables.

i
The operand i has prototype       size_t i  It must be greater than or equal zero and less than n ; i.e., less than the number of elements in v .

b
The result b has prototype       Base b  and is a reference to the i-th element in the vector v . It can be used to change the element value; for example,       v[i] = c  is valid where c is a Base object. The reference b is no longer valid once the destructor for v is called; for example, when v falls out of scope.

We refer to the syntax       r = v[x]  as AD indexing of a VecAD object.

x
The argument x has prototype       const AD<Base> &x  The value of x must be greater than or equal zero and less than n ; i.e., less than the number of elements in v .

r
The result y has prototype       VecAD<Base>::reference r  The object r has an AD type and its operations are recorded as part of the same AD of Base operation sequence as for AD<Base> objects. It acts as a reference to the element with index   {\rm floor} (x) in the vector v (  {\rm floor} (x) is the greatest integer less than or equal x ). Because it is a reference, it can be used to change the element value; for example,       v[x] = z  is valid where z is an VecAD<Base>::reference object. As a reference, r is no longer valid once the destructor for v is called; for example, when v falls out of scope.

Example
The file vec_ad.cpp contains an example and test using VecAD vectors. It returns true if it succeeds and false otherwise.

Speed and Memory
The VecAD vector type is inefficient because every time an element of a vector is accessed, a new CppAD variable is created on the tape using either the Ldp or Ldv operation (unless all of the elements of the vector are parameters ). The effect of this can be seen by executing the following steps:
1. In the file cppad/local/forward_sweep.h, change the definition of CPPAD_FORWARD_SWEEP_TRACE to  # define CPPAD_FORWARD_SWEEP_TRACE 1 
2. In the Example directory, execute the command  ./test_one.sh lu_vec_ad_ok.cpp lu_vec_ad.cpp -DNDEBUG > lu_vec_ad_ok.log  This will write a trace of all the forward tape operations, for the test case lu_vec_ad_ok.cpp , to the file lu_vec_ad_ok.log.
3. In the Example directory execute the commands  grep "op=" lu_vec_ad_ok.log | wc -l grep "op=Ld[vp]" lu_vec_ad_ok.log | wc -l grep "op=St[vp][vp]" lu_vec_ad_ok.log | wc -l  The first command counts the number of operators in the tracing, the second counts the number of VecAD load operations, and the third counts the number of VecAD store operations. (For CppAD version 05-11-20 these counts were 956, 348, and 118 respectively.)