# ifndef CPPAD_DEPENDENT_INCLUDED # define CPPAD_DEPENDENT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-08 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the Common Public License Version 1.0. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin Dependent$$ $spell taylor_ ADvector const $$ $spell $$ $section Stop Recording and Store Operation Sequence$$ $index ADFun, operation sequence$$ $index operation, sequence store$$ $index sequence, operation store$$ $index recording, stop$$ $index tape, stop recording$$ $index Dependent$$ $head Syntax$$ $syntax%%f%.Dependent(%x%, %y%)%$$ $head Purpose$$ Stop recording and the AD of $italic Base$$ $xref/glossary/Operation/Sequence/operation sequence/1/$$ that started with the call $syntax% Independent(%x%) %$$ and store the operation sequence in $italic f$$. The operation sequence defines an $xref/glossary/AD Function/AD function/$$ $latex \[ F : B^n \rightarrow B^m \] $$ where $latex B$$ is the space corresponding to objects of type $italic Base$$. The value $latex n$$ is the dimension of the $xref/SeqProperty/Domain/domain/$$ space for the operation sequence. The value $latex m$$ is the dimension of the $xref/SeqProperty/Range/range/$$ space for the operation sequence (which is determined by the size of $italic y$$). $head f$$ The object $italic f$$ has prototype $syntax% ADFun<%Base%> %f% %$$ The AD of $italic Base$$ operation sequence is stored in $italic f$$; i.e., it becomes the operation sequence corresponding to $italic f$$. If a previous operation sequence was stored in $italic f$$, it is deleted. $head x$$ The argument $italic x$$ must be the vector argument in a previous call to $cref/Independent/$$. Neither its size, or any of its values, are allowed to change between calling $syntax% Independent(%x%) %$$ and $syntax% %f%.Dependent(%x%, %y%) %$$. $head y$$ The vector $italic y$$ has prototype $syntax% const %ADvector% &%y% %$$ (see $xref/FunConstruct//ADvector/$$ below). The length of $italic y$$ must be greater than zero and is the dimension of the range space for $italic f$$. $head ADvector$$ The type $italic ADvector$$ must be a $xref/SimpleVector/$$ class with $xref/SimpleVector/Elements of Specified Type/elements of type/$$ $syntax%AD<%Base%>%$$. The routine $xref/CheckSimpleVector/$$ will generate an error message if this is not the case. $head Taping$$ The tape, that was created when $syntax%Independent(%x%)%$$ was called, will stop recording. The AD operation sequence will be transferred from the tape to the object $italic f$$ and the tape will then be deleted. $head Forward$$ No $xref/Forward/$$ calculation is preformed during this operation. Thus, directly after this operation, $syntax% %f%.size_taylor() %$$ is zero (see $xref/size_taylor/$$). $head Example$$ The file $xref/FunCheck.cpp/$$ contains an example and test of this operation. It returns true if it succeeds and false otherwise. $end ---------------------------------------------------------------------------- */ // BEGIN CppAD namespace namespace CppAD { template template void ADFun::Dependent(const ADvector &y) { ADTape *tape = AD::tape_ptr(); CPPAD_ASSERT_KNOWN( tape != CPPAD_NULL, "Can't store current operation sequence in this ADFun object" "\nbecause there is no active tape (for this thread)." ); // code above just determines the tape and checks for errors Dependent(tape, y); } template template void ADFun::Dependent(const ADvector &x, const ADvector &y) { CPPAD_ASSERT_KNOWN( x.size() > 0, "Dependent: independent variable vector has size zero." ); CPPAD_ASSERT_KNOWN( Variable(x[0]), "Dependent: independent variable vector has been changed." ); ADTape *tape = AD::tape_ptr(x[0].id_); CPPAD_ASSERT_KNOWN( tape->size_independent_ == x.size(), "Dependent: independent variable vector has been changed." ); # ifndef NDEBUG size_t i, j; for(j = 0; j < x.size(); j++) { CPPAD_ASSERT_KNOWN( x[j].taddr_ == (j+1), "ADFun: independent variable vector has been changed." ); CPPAD_ASSERT_KNOWN( x[j].id_ == x[0].id_, "ADFun: independent variable vector has been changed." ); } for(i = 0; i < y.size(); i++) { CPPAD_ASSERT_KNOWN( CppAD::Parameter( y[i] ) | (y[i].id_ == x[0].id_) , "ADFun: dependent vector contains a variable for" "\na different tape (thread) than the independent variables." ); } # endif // code above just determines the tape and checks for errors Dependent(tape, y); } template template void ADFun::Dependent(ADTape *tape, const ADvector &y) { size_t m = y.size(); size_t n = tape->size_independent_; size_t i, j; size_t y_taddr; // check ADvector is Simple Vector class with AD elements CheckSimpleVector< AD, ADvector>(); CPPAD_ASSERT_KNOWN( y.size() > 0, "ADFun operation sequence dependent variable size is zero size" ); // set total number of variables in tape, parameter flag, // make a tape copy of dependent variables that are parameters, // and store tape address for each dependent variable CPPAD_ASSERT_UNKNOWN( NumVar(ParOp) == 1 ); dep_parameter_.resize(m); dep_taddr_.resize(m); total_num_var_ = tape->Rec_.TotNumVar(); for(i = 0; i < m; i++) { dep_parameter_[i] = CppAD::Parameter(y[i]); if( dep_parameter_[i] ) { y_taddr = tape->RecordParOp( y[i].value_ ); total_num_var_++; } else y_taddr = y[i].taddr_; CPPAD_ASSERT_UNKNOWN( y_taddr > 0 ); CPPAD_ASSERT_UNKNOWN( y_taddr < total_num_var_ ); dep_taddr_[i] = y_taddr; } // now that each dependent variable has a place in the tape, // we can make a copy for this function and erase the tape. play_ = tape->Rec_; // now we can delete the tape AD::tape_delete( tape->id_ ); // total number of varables in this recording CPPAD_ASSERT_UNKNOWN( total_num_var_ == play_.TotNumVar() ); // used to determine if there is an operation sequence in *this CPPAD_ASSERT_UNKNOWN( total_num_var_ > 0 ); // free old buffers if( taylor_ != CPPAD_NULL ) CPPAD_TRACK_DEL_VEC(taylor_); if( for_jac_ != CPPAD_NULL ) CPPAD_TRACK_DEL_VEC(for_jac_); // initialize buffers taylor_ = CPPAD_NULL; for_jac_ = CPPAD_NULL; // initial row and column dimensions // memoryMax = 0; taylor_per_var_ = 0; for_jac_col_dim_ = 0; for_jac_bit_dim_ = 0; taylor_col_dim_ = 0; // set tape address ind_taddr_.resize(n); CPPAD_ASSERT_UNKNOWN( n < total_num_var_ ); for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == InvOp ); ind_taddr_[j] = j+1; } } } // END CppAD namespace # endif