CppAD: A C++ Algorithmic Differentiation Package  20130918
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-14 Bradley M. Bell
00007 
00008 CppAD is distributed under multiple licenses. This distribution is under
00009 the terms of the 
00010                     Eclipse 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      alloc
00019      num
00020      taylor_
00021      ADvector
00022      const
00023 $$
00024 
00025 $spell
00026 $$
00027 
00028 $section Stop Recording and Store Operation Sequence$$
00029 
00030 $index ADFun, operation sequence$$
00031 $index operation, sequence store$$
00032 $index sequence, operation store$$
00033 $index recording, stop$$
00034 $index tape, stop recording$$
00035 $index Dependent$$
00036 
00037 $head Syntax$$
00038 $icode%f%.Dependent(%x%, %y%)%$$
00039 
00040 $head Purpose$$
00041 Stop recording and the AD of $icode Base$$
00042 $cref/operation sequence/glossary/Operation/Sequence/$$
00043 that started with the call
00044 $codei%
00045      Independent(%x%)
00046 %$$
00047 and store the operation sequence in $icode f$$.
00048 The operation sequence defines an 
00049 $cref/AD function/glossary/AD Function/$$
00050 $latex \[
00051      F : B^n \rightarrow B^m
00052 \] $$
00053 where $latex B$$ is the space corresponding to objects of type $icode Base$$.
00054 The value $latex n$$ is the dimension of the 
00055 $cref/domain/seq_property/Domain/$$ space for the operation sequence.
00056 The value $latex m$$ is the dimension of the 
00057 $cref/range/seq_property/Range/$$ space for the operation sequence
00058 (which is determined by the size of $icode y$$).
00059 
00060 $head f$$
00061 The object $icode f$$ has prototype
00062 $codei%
00063      ADFun<%Base%> %f%
00064 %$$
00065 The AD of $icode Base$$ operation sequence is stored in $icode f$$; i.e.,
00066 it becomes the operation sequence corresponding to $icode f$$.
00067 If a previous operation sequence was stored in $icode f$$,
00068 it is deleted. 
00069 
00070 $head x$$
00071 The argument $icode x$$ 
00072 must be the vector argument in a previous call to
00073 $cref Independent$$.
00074 Neither its size, or any of its values, are allowed to change
00075 between calling
00076 $codei%
00077      Independent(%x%)
00078 %$$
00079 and 
00080 $codei%
00081      %f%.Dependent(%x%, %y%)
00082 %$$.
00083 
00084 $head y$$
00085 The vector $icode y$$ has prototype
00086 $codei%
00087      const %ADvector% &%y%
00088 %$$
00089 (see $cref/ADvector/FunConstruct/$$ below).
00090 The length of $icode y$$ must be greater than zero
00091 and is the dimension of the range space for $icode f$$.
00092 
00093 $head ADvector$$
00094 The type $icode ADvector$$ must be a $cref SimpleVector$$ class with
00095 $cref/elements of type/SimpleVector/Elements of Specified Type/$$
00096 $codei%AD<%Base%>%$$.
00097 The routine $cref CheckSimpleVector$$ will generate an error message
00098 if this is not the case.
00099 
00100 $head Taping$$
00101 The tape,
00102 that was created when $codei%Independent(%x%)%$$ was called, 
00103 will stop recording.
00104 The AD operation sequence will be transferred from
00105 the tape to the object $icode f$$ and the tape will then be deleted.
00106 
00107 $head Forward$$
00108 No $cref Forward$$ calculation is preformed during this operation.
00109 Thus, directly after this operation,
00110 $codei%
00111      %f%.size_order()
00112 %$$ 
00113 is zero (see $cref size_order$$).
00114 
00115 $head Parallel Mode$$
00116 $index parallel, Dependent$$
00117 $index Dependent, parallel$$
00118 The call to $code Independent$$,
00119 and the corresponding call to
00120 $codei%
00121      ADFun<%Base%> %f%( %x%, %y%)
00122 %$$
00123 or 
00124 $codei%
00125      %f%.Dependent( %x%, %y%)
00126 %$$
00127 or $cref abort_recording$$,
00128 must be preformed by the same thread; i.e.,
00129 $cref/thread_alloc::thread_num/ta_thread_num/$$ must be the same.
00130 
00131 $head Example$$
00132 The file
00133 $cref fun_check.cpp$$ 
00134 contains an example and test of this operation.
00135 It returns true if it succeeds and false otherwise.
00136 
00137 $end
00138 ----------------------------------------------------------------------------
00139 */
00140 
00141 
00142 // BEGIN CppAD namespace
00143 namespace CppAD {
00144 
00145 /*!
00146 Determine the \c tape corresponding to this exeuction thread and then use
00147 <code>Dependent(tape, y)</code> to store this tapes recording in a function.
00148 
00149 \param y [in]
00150 The dependent variable vector for the corresponding function.
00151 */
00152 template <typename Base>
00153 template <typename ADvector>
00154 void ADFun<Base>::Dependent(const ADvector &y)
00155 {    ADTape<Base>* tape = AD<Base>::tape_ptr();
00156      CPPAD_ASSERT_KNOWN(
00157           tape != CPPAD_NULL,
00158           "Can't store current operation sequence in this ADFun object"
00159           "\nbecause there is no active tape (for this thread)."
00160      );
00161 
00162      // code above just determines the tape and checks for errors
00163      Dependent(tape, y);
00164 }
00165 
00166 
00167 /*!
00168 Determine the \c tape corresponding to this exeuction thread and then use
00169 <code>Dependent(tape, y)</code> to store this tapes recording in a function.
00170 
00171 \param x [in]
00172 The independent variable vector for this tape. This informaiton is
00173 also stored in the tape so a check is done to make sure it is correct
00174 (if NDEBUG is not defined).
00175 
00176 \param y [in]
00177 The dependent variable vector for the corresponding function.
00178 */
00179 template <typename Base>
00180 template <typename ADvector>
00181 void ADFun<Base>::Dependent(const ADvector &x, const ADvector &y)
00182 {
00183      CPPAD_ASSERT_KNOWN(
00184           x.size() > 0,
00185           "Dependent: independent variable vector has size zero."
00186      );
00187      CPPAD_ASSERT_KNOWN(
00188           Variable(x[0]),
00189           "Dependent: independent variable vector has been changed."
00190      );
00191      ADTape<Base> *tape = AD<Base>::tape_ptr(x[0].tape_id_);
00192      CPPAD_ASSERT_KNOWN(
00193           tape->size_independent_ == size_t( x.size() ),
00194           "Dependent: independent variable vector has been changed."
00195      );
00196 # ifndef NDEBUG
00197      size_t i, j;
00198      for(j = 0; j < size_t(x.size()); j++)
00199      {    CPPAD_ASSERT_KNOWN(
00200           size_t(x[j].taddr_) == (j+1),
00201           "ADFun<Base>: independent variable vector has been changed."
00202           );
00203           CPPAD_ASSERT_KNOWN(
00204           x[j].tape_id_ == x[0].tape_id_,
00205           "ADFun<Base>: independent variable vector has been changed."
00206           );
00207      }
00208      for(i = 0; i < size_t(y.size()); i++)
00209      {    CPPAD_ASSERT_KNOWN(
00210           CppAD::Parameter( y[i] ) | (y[i].tape_id_ == x[0].tape_id_) ,
00211           "ADFun<Base>: dependent vector contains a variable for"
00212           "\na different tape (thread) than the independent variables."
00213           );
00214      }
00215 # endif
00216 
00217      // code above just determines the tape and checks for errors
00218      Dependent(tape, y);
00219 }
00220 
00221 /*!
00222 Replace the floationg point operations sequence for this function object.
00223 
00224 \param tape
00225 is a tape that contains the new floating point operation sequence
00226 for this function.
00227 After this operation, all memory allocated for this tape is deleted.
00228 
00229 \param y
00230 The dependent variable vector for the function being stored in this object.
00231 
00232 \par
00233 All of the private member data in ad_fun.hpp is set to correspond to the 
00234 new tape except for check_for_nan_.
00235 */
00236 
00237 template <typename Base>
00238 template <typename ADvector>
00239 void ADFun<Base>::Dependent(ADTape<Base> *tape, const ADvector &y)
00240 {
00241      size_t   m = y.size();
00242      size_t   n = tape->size_independent_;
00243      size_t   i, j;
00244      size_t   y_taddr;
00245 
00246      // check ADvector is Simple Vector class with AD<Base> elements
00247      CheckSimpleVector< AD<Base>, ADvector>();
00248 
00249      CPPAD_ASSERT_KNOWN(
00250           y.size() > 0,
00251           "ADFun operation sequence dependent variable size is zero size"
00252      ); 
00253      // ---------------------------------------------------------------------
00254      // Begin setting ad_fun.hpp private member data
00255      // ---------------------------------------------------------------------
00256      // dep_parameter_, dep_taddr_
00257      CPPAD_ASSERT_UNKNOWN( NumRes(ParOp) == 1 );
00258      dep_parameter_.resize(m);
00259      dep_taddr_.resize(m);
00260      for(i = 0; i < m; i++)
00261      {    dep_parameter_[i] = CppAD::Parameter(y[i]);
00262           if( dep_parameter_[i] )
00263           {    // make a tape copy of dependent variables that are parameters, 
00264                y_taddr = tape->RecordParOp( y[i].value_ );
00265           }
00266           else y_taddr = y[i].taddr_;
00267 
00268           CPPAD_ASSERT_UNKNOWN( y_taddr > 0 );
00269           dep_taddr_[i] = y_taddr;
00270      }
00271 
00272      // put an EndOp at the end of the tape
00273      tape->Rec_.PutOp(EndOp);
00274 
00275      // some size_t values in ad_fun.hpp
00276      compare_change_       = 0;
00277      num_order_taylor_     = 0;
00278      cap_order_taylor_     = 0;
00279 
00280      // num_var_tape_
00281      // Now that all the variables are in the tape, we can set this value.
00282      num_var_tape_       = tape->Rec_.num_var_rec();
00283 
00284      // taylor_
00285      taylor_.erase();
00286 
00287      // cskip_op_
00288      cskip_op_.erase();
00289      cskip_op_.extend( tape->Rec_.num_op_rec() );
00290 
00291      // load_op_
00292      load_op_.erase();
00293      load_op_.extend( tape->Rec_.num_load_op_rec() );
00294 
00295      // play_
00296      // Now that each dependent variable has a place in the tape,
00297      // and there is a EndOp at the end of the tape, we can transfer the 
00298      // recording to the player and and erase the tape.
00299      play_.get(tape->Rec_);
00300 
00301      // ind_taddr_
00302      // Note that play_ has been set, we can use it to check operators
00303      ind_taddr_.resize(n);
00304      CPPAD_ASSERT_UNKNOWN( n < num_var_tape_);
00305      for(j = 0; j < n; j++)
00306      {    CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == InvOp );
00307           ind_taddr_[j] = j+1;
00308      }
00309 
00310      // for_jac_sparse_pack_, for_jac_sparse_set_
00311      for_jac_sparse_pack_.resize(0, 0);
00312      for_jac_sparse_set_.resize(0,0);
00313      // ---------------------------------------------------------------------
00314      // End set ad_fun.hpp private member data
00315      // ---------------------------------------------------------------------
00316 
00317      // now we can delete the tape
00318      AD<Base>::tape_manage(tape_manage_delete);
00319 
00320      // total number of varables in this recording 
00321      CPPAD_ASSERT_UNKNOWN( num_var_tape_  == play_.num_var_rec() );
00322 
00323      // used to determine if there is an operation sequence in *this
00324      CPPAD_ASSERT_UNKNOWN( num_var_tape_  > 0 );
00325 
00326 }
00327 
00328 } // END CppAD namespace
00329 
00330 # endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines