CppAD: A C++ Algorithmic Differentiation Package 20110419
|
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