CppAD: A C++ Algorithmic Differentiation Package 20110419
dependent.hpp
Go to the documentation of this file.
00001 /* $Id$ */
00002 # ifndef CPPAD_DEPENDENT_INCLUDED
00003 # define CPPAD_DEPENDENT_INCLUDED
00004 
00005 /* --------------------------------------------------------------------------
00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-09 Bradley M. Bell
00007 
00008 CppAD is distributed under multiple licenses. This distribution is under
00009 the terms of the 
00010                     Common Public License Version 1.0.
00011 
00012 A copy of this license is included in the COPYING file of this distribution.
00013 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
00014 -------------------------------------------------------------------------- */
00015 /*
00016 $begin Dependent$$
00017 $spell 
00018         taylor_
00019         ADvector
00020         const
00021 $$
00022 
00023 $spell
00024 $$
00025 
00026 $section Stop Recording and Store Operation Sequence$$
00027 
00028 $index ADFun, operation sequence$$
00029 $index operation, sequence store$$
00030 $index sequence, operation store$$
00031 $index recording, stop$$
00032 $index tape, stop recording$$
00033 $index Dependent$$
00034 
00035 $head Syntax$$
00036 $syntax%%f%.Dependent(%x%, %y%)%$$
00037 
00038 $head Purpose$$
00039 Stop recording and the AD of $italic Base$$
00040 $xref/glossary/Operation/Sequence/operation sequence/1/$$
00041 that started with the call
00042 $syntax%
00043         Independent(%x%)
00044 %$$
00045 and store the operation sequence in $italic f$$.
00046 The operation sequence defines an 
00047 $xref/glossary/AD Function/AD function/$$
00048 $latex \[
00049         F : B^n \rightarrow B^m
00050 \] $$
00051 where $latex B$$ is the space corresponding to objects of type $italic Base$$.
00052 The value $latex n$$ is the dimension of the 
00053 $xref/seq_property/Domain/domain/$$ space for the operation sequence.
00054 The value $latex m$$ is the dimension of the 
00055 $xref/seq_property/Range/range/$$ space for the operation sequence
00056 (which is determined by the size of $italic y$$).
00057 
00058 $head f$$
00059 The object $italic f$$ has prototype
00060 $syntax%
00061         ADFun<%Base%> %f%
00062 %$$
00063 The AD of $italic Base$$ operation sequence is stored in $italic f$$; i.e.,
00064 it becomes the operation sequence corresponding to $italic f$$.
00065 If a previous operation sequence was stored in $italic f$$,
00066 it is deleted. 
00067 
00068 $head x$$
00069 The argument $italic x$$ 
00070 must be the vector argument in a previous call to
00071 $cref/Independent/$$.
00072 Neither its size, or any of its values, are allowed to change
00073 between calling
00074 $syntax%
00075         Independent(%x%)
00076 %$$
00077 and 
00078 $syntax%
00079         %f%.Dependent(%x%, %y%)
00080 %$$.
00081 
00082 $head y$$
00083 The vector $italic y$$ has prototype
00084 $syntax%
00085         const %ADvector% &%y%
00086 %$$
00087 (see $xref/FunConstruct//ADvector/$$ below).
00088 The length of $italic y$$ must be greater than zero
00089 and is the dimension of the range space for $italic f$$.
00090 
00091 $head ADvector$$
00092 The type $italic ADvector$$ must be a $xref/SimpleVector/$$ class with
00093 $xref/SimpleVector/Elements of Specified Type/elements of type/$$
00094 $syntax%AD<%Base%>%$$.
00095 The routine $xref/CheckSimpleVector/$$ will generate an error message
00096 if this is not the case.
00097 
00098 $head Taping$$
00099 The tape,
00100 that was created when $syntax%Independent(%x%)%$$ was called, 
00101 will stop recording.
00102 The AD operation sequence will be transferred from
00103 the tape to the object $italic f$$ and the tape will then be deleted.
00104 
00105 $head Forward$$
00106 No $xref/Forward/$$ calculation is preformed during this operation.
00107 Thus, directly after this operation,
00108 $syntax%
00109         %f%.size_taylor()
00110 %$$ 
00111 is zero (see $xref/size_taylor/$$).
00112 
00113 $head Example$$
00114 The file
00115 $xref/FunCheck.cpp/$$ 
00116 contains an example and test of this operation.
00117 It returns true if it succeeds and false otherwise.
00118 
00119 $end
00120 ----------------------------------------------------------------------------
00121 */
00122 
00123 
00124 // BEGIN CppAD namespace
00125 namespace CppAD {
00126 
00127 template <typename Base>
00128 template <typename ADvector>
00129 void ADFun<Base>::Dependent(const ADvector &y)
00130 {       ADTape<Base> *tape = AD<Base>::tape_ptr();
00131         CPPAD_ASSERT_KNOWN(
00132                 tape != CPPAD_NULL,
00133                 "Can't store current operation sequence in this ADFun object"
00134                 "\nbecause there is no active tape (for this thread)."
00135         );
00136 
00137         // code above just determines the tape and checks for errors
00138         Dependent(tape, y);
00139 }
00140 
00141 template <typename Base>
00142 template <typename ADvector>
00143 void ADFun<Base>::Dependent(const ADvector &x, const ADvector &y)
00144 {
00145         CPPAD_ASSERT_KNOWN(
00146                 x.size() > 0,
00147                 "Dependent: independent variable vector has size zero."
00148         );
00149         CPPAD_ASSERT_KNOWN(
00150                 Variable(x[0]),
00151                 "Dependent: independent variable vector has been changed."
00152         );
00153         ADTape<Base> *tape = AD<Base>::tape_ptr(x[0].id_);
00154         CPPAD_ASSERT_KNOWN(
00155                 tape->size_independent_ == x.size(),
00156                 "Dependent: independent variable vector has been changed."
00157         );
00158 # ifndef NDEBUG
00159         size_t i, j;
00160         for(j = 0; j < x.size(); j++)
00161         {       CPPAD_ASSERT_KNOWN(
00162                 x[j].taddr_ == (j+1),
00163                 "ADFun<Base>: independent variable vector has been changed."
00164                 );
00165                 CPPAD_ASSERT_KNOWN(
00166                 x[j].id_ == x[0].id_,
00167                 "ADFun<Base>: independent variable vector has been changed."
00168                 );
00169         }
00170         for(i = 0; i < y.size(); i++)
00171         {       CPPAD_ASSERT_KNOWN(
00172                 CppAD::Parameter( y[i] ) | (y[i].id_ == x[0].id_) ,
00173                 "ADFun<Base>: dependent vector contains a variable for"
00174                 "\na different tape (thread) than the independent variables."
00175                 );
00176         }
00177 # endif
00178 
00179         // code above just determines the tape and checks for errors
00180         Dependent(tape, y);
00181 }
00182                 
00183 
00184 template <typename Base>
00185 template <typename ADvector>
00186 void ADFun<Base>::Dependent(ADTape<Base> *tape, const ADvector &y)
00187 {
00188         size_t   m = y.size();
00189         size_t   n = tape->size_independent_;
00190         size_t   i, j;
00191         size_t   y_taddr;
00192 
00193         // check ADvector is Simple Vector class with AD<Base> elements
00194         CheckSimpleVector< AD<Base>, ADvector>();
00195 
00196         CPPAD_ASSERT_KNOWN(
00197                 y.size() > 0,
00198                 "ADFun operation sequence dependent variable size is zero size"
00199         ); 
00200 
00201         // set total number of variables in tape, parameter flag, 
00202         // make a tape copy of dependent variables that are parameters, 
00203         // and store tape address for each dependent variable
00204         CPPAD_ASSERT_UNKNOWN( NumRes(ParOp) == 1 );
00205         dep_parameter_.resize(m);
00206         dep_taddr_.resize(m);
00207         for(i = 0; i < m; i++)
00208         {       dep_parameter_[i] = CppAD::Parameter(y[i]);
00209                 if( dep_parameter_[i] )
00210                         y_taddr = tape->RecordParOp( y[i].value_ );
00211                 else    y_taddr = y[i].taddr_;
00212 
00213                 CPPAD_ASSERT_UNKNOWN( y_taddr > 0 );
00214                 dep_taddr_[i] = y_taddr;
00215         }
00216 
00217         // put an EndOp at the end of the tape
00218         tape->Rec_.PutOp(EndOp);
00219 
00220         // total number of variables on the tape
00221         total_num_var_ = tape->Rec_.num_rec_var();
00222 
00223         // now that each dependent variable has a place in the tape,
00224         // and there is a EndOp at the end of the tape,
00225         // we can make a copy for this function and erase the tape.
00226         play_ = tape->Rec_;
00227 
00228         // now we can delete the tape
00229         AD<Base>::tape_delete( tape->id_ );
00230 
00231         // total number of varables in this recording 
00232         CPPAD_ASSERT_UNKNOWN( total_num_var_ == play_.num_rec_var() );
00233 
00234         // used to determine if there is an operation sequence in *this
00235         CPPAD_ASSERT_UNKNOWN( total_num_var_ > 0 );
00236 
00237         // free old buffers
00238         if( taylor_ != CPPAD_NULL )
00239                 CPPAD_TRACK_DEL_VEC(taylor_);
00240         for_jac_sparse_pack_.resize(0, 0);
00241         for_jac_sparse_set_.resize(0,0);
00242 
00243         // initialize buffers
00244         taylor_  = CPPAD_NULL;
00245 
00246         // initial row and column dimensions
00247         // memoryMax  = 0;
00248         taylor_per_var_   = 0;
00249         taylor_col_dim_   = 0;
00250 
00251         // set tape address 
00252         ind_taddr_.resize(n);
00253         CPPAD_ASSERT_UNKNOWN(
00254                 n < total_num_var_
00255         );
00256         for(j = 0; j < n; j++)
00257         {       CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == InvOp );
00258                 ind_taddr_[j] = j+1;
00259         }
00260 
00261 }
00262 
00263 } // END CppAD namespace
00264 
00265 # endif