CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
dependent.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_CORE_DEPENDENT_HPP
2 # define CPPAD_CORE_DEPENDENT_HPP
3 
4 /* --------------------------------------------------------------------------
5 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
6 
7 CppAD is distributed under multiple licenses. This distribution is under
8 the terms of the
9  Eclipse Public License Version 1.0.
10 
11 A copy of this license is included in the COPYING file of this distribution.
12 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
13 -------------------------------------------------------------------------- */
14 /*
15 $begin Dependent$$
16 $spell
17  alloc
18  num
19  taylor_
20  ADvector
21  const
22 $$
23 
24 $spell
25 $$
26 
27 $section Stop Recording and Store Operation Sequence$$
28 $mindex ADFun tape Dependent$$
29 
30 
31 $head Syntax$$
32 $icode%f%.Dependent(%x%, %y%)%$$
33 
34 $head Purpose$$
35 Stop recording and the AD of $icode Base$$
36 $cref/operation sequence/glossary/Operation/Sequence/$$
37 that started with the call
38 $codei%
39  Independent(%x%)
40 %$$
41 and store the operation sequence in $icode f$$.
42 The operation sequence defines an
43 $cref/AD function/glossary/AD Function/$$
44 $latex \[
45  F : B^n \rightarrow B^m
46 \] $$
47 where $latex B$$ is the space corresponding to objects of type $icode Base$$.
48 The value $latex n$$ is the dimension of the
49 $cref/domain/seq_property/Domain/$$ space for the operation sequence.
50 The value $latex m$$ is the dimension of the
51 $cref/range/seq_property/Range/$$ space for the operation sequence
52 (which is determined by the size of $icode y$$).
53 
54 $head f$$
55 The object $icode f$$ has prototype
56 $codei%
57  ADFun<%Base%> %f%
58 %$$
59 The AD of $icode Base$$ operation sequence is stored in $icode f$$; i.e.,
60 it becomes the operation sequence corresponding to $icode f$$.
61 If a previous operation sequence was stored in $icode f$$,
62 it is deleted.
63 
64 $head x$$
65 The argument $icode x$$
66 must be the vector argument in a previous call to
67 $cref Independent$$.
68 Neither its size, or any of its values, are allowed to change
69 between calling
70 $codei%
71  Independent(%x%)
72 %$$
73 and
74 $codei%
75  %f%.Dependent(%x%, %y%)
76 %$$.
77 
78 $head y$$
79 The vector $icode y$$ has prototype
80 $codei%
81  const %ADvector% &%y%
82 %$$
83 (see $cref/ADvector/FunConstruct/$$ below).
84 The length of $icode y$$ must be greater than zero
85 and is the dimension of the range space for $icode f$$.
86 
87 $head ADvector$$
88 The type $icode ADvector$$ must be a $cref SimpleVector$$ class with
89 $cref/elements of type/SimpleVector/Elements of Specified Type/$$
90 $codei%AD<%Base%>%$$.
91 The routine $cref CheckSimpleVector$$ will generate an error message
92 if this is not the case.
93 
94 $head Taping$$
95 The tape,
96 that was created when $codei%Independent(%x%)%$$ was called,
97 will stop recording.
98 The AD operation sequence will be transferred from
99 the tape to the object $icode f$$ and the tape will then be deleted.
100 
101 $head Forward$$
102 No $cref Forward$$ calculation is preformed during this operation.
103 Thus, directly after this operation,
104 $codei%
105  %f%.size_order()
106 %$$
107 is zero (see $cref size_order$$).
108 
109 $head Parallel Mode$$
110 The call to $code Independent$$,
111 and the corresponding call to
112 $codei%
113  ADFun<%Base%> %f%( %x%, %y%)
114 %$$
115 or
116 $codei%
117  %f%.Dependent( %x%, %y%)
118 %$$
119 or $cref abort_recording$$,
120 must be preformed by the same thread; i.e.,
121 $cref/thread_alloc::thread_num/ta_thread_num/$$ must be the same.
122 
123 $head Example$$
124 The file
125 $cref fun_check.cpp$$
126 contains an example and test of this operation.
127 It returns true if it succeeds and false otherwise.
128 
129 $end
130 ----------------------------------------------------------------------------
131 */
132 
133 
134 // BEGIN CppAD namespace
135 namespace CppAD {
136 
137 /*!
138 \file dependent.hpp
139 Different versions of Dependent function.
140 */
141 
142 /*!
143 Determine the \c tape corresponding to this exeuction thread and then use
144 <code>Dependent(tape, y)</code> to store this tapes recording in a function.
145 
146 \param y [in]
147 The dependent variable vector for the corresponding function.
148 */
149 template <typename Base>
150 template <typename ADvector>
151 void ADFun<Base>::Dependent(const ADvector &y)
154  tape != CPPAD_NULL,
155  "Can't store current operation sequence in this ADFun object"
156  "\nbecause there is no active tape (for this thread)."
157  );
158 
159  // code above just determines the tape and checks for errors
160  Dependent(tape, y);
161 }
162 
163 
164 /*!
165 Determine the \c tape corresponding to this exeuction thread and then use
166 <code>Dependent(tape, y)</code> to store this tapes recording in a function.
167 
168 \param x [in]
169 The independent variable vector for this tape. This informaiton is
170 also stored in the tape so a check is done to make sure it is correct
171 (if NDEBUG is not defined).
172 
173 \param y [in]
174 The dependent variable vector for the corresponding function.
175 */
176 template <typename Base>
177 template <typename ADvector>
178 void ADFun<Base>::Dependent(const ADvector &x, const ADvector &y)
179 {
181  x.size() > 0,
182  "Dependent: independent variable vector has size zero."
183  );
185  Variable(x[0]),
186  "Dependent: independent variable vector has been changed."
187  );
188  local::ADTape<Base> *tape = AD<Base>::tape_ptr(x[0].tape_id_);
190  tape->size_independent_ == size_t( x.size() ),
191  "Dependent: independent variable vector has been changed."
192  );
193 # ifndef NDEBUG
194  size_t i, j;
195  for(j = 0; j < size_t(x.size()); j++)
197  size_t(x[j].taddr_) == (j+1),
198  "ADFun<Base>: independent variable vector has been changed."
199  );
201  x[j].tape_id_ == x[0].tape_id_,
202  "ADFun<Base>: independent variable vector has been changed."
203  );
204  }
205  for(i = 0; i < size_t(y.size()); i++)
207  CppAD::Parameter( y[i] ) | (y[i].tape_id_ == x[0].tape_id_) ,
208  "ADFun<Base>: dependent vector contains a variable for"
209  "\na different tape (thread) than the independent variables."
210  );
211  }
212 # endif
213 
214  // code above just determines the tape and checks for errors
215  Dependent(tape, y);
216 }
217 
218 /*!
219 Replace the floationg point operations sequence for this function object.
220 
221 \param tape
222 is a tape that contains the new floating point operation sequence
223 for this function.
224 After this operation, all memory allocated for this tape is deleted.
225 
226 \param y
227 The dependent variable vector for the function being stored in this object.
228 
229 \par
230 All of the private member data in ad_fun.hpp is set to correspond to the
231 new tape except for check_for_nan_.
232 */
233 
234 template <typename Base>
235 template <typename ADvector>
236 void ADFun<Base>::Dependent(local::ADTape<Base> *tape, const ADvector &y)
237 {
238  size_t m = y.size();
239  size_t n = tape->size_independent_;
240  size_t i, j;
241  size_t y_taddr;
242 
243  // check ADvector is Simple Vector class with AD<Base> elements
244  CheckSimpleVector< AD<Base>, ADvector>();
245 
247  y.size() > 0,
248  "ADFun operation sequence dependent variable size is zero size"
249  );
250  // ---------------------------------------------------------------------
251  // Begin setting ad_fun.hpp private member data
252  // ---------------------------------------------------------------------
253  // dep_parameter_, dep_taddr_
255  dep_parameter_.resize(m);
256  dep_taddr_.resize(m);
257  for(i = 0; i < m; i++)
258  { dep_parameter_[i] = CppAD::Parameter(y[i]);
259  if( dep_parameter_[i] )
260  { // make a tape copy of dependent variables that are parameters,
261  y_taddr = tape->RecordParOp( y[i].value_ );
262  }
263  else y_taddr = y[i].taddr_;
264 
265  CPPAD_ASSERT_UNKNOWN( y_taddr > 0 );
266  dep_taddr_[i] = y_taddr;
267  }
268 
269  // put an EndOp at the end of the tape
270  tape->Rec_.PutOp(local::EndOp);
271 
272  // some size_t values in ad_fun.hpp
273  has_been_optimized_ = false;
274  compare_change_count_ = 1;
275  compare_change_number_ = 0;
276  compare_change_op_index_ = 0;
277  num_order_taylor_ = 0;
278  num_direction_taylor_ = 0;
279  cap_order_taylor_ = 0;
280 
281  // num_var_tape_
282  // Now that all the variables are in the tape, we can set this value.
283  num_var_tape_ = tape->Rec_.num_var_rec();
284 
285  // taylor_
286  taylor_.resize(0);
287 
288  // cskip_op_
289  cskip_op_.resize( tape->Rec_.num_op_rec() );
290 
291  // load_op_
292  load_op_.resize( tape->Rec_.num_load_op_rec() );
293 
294  // play_
295  // Now that each dependent variable has a place in the tape,
296  // and there is a EndOp at the end of the tape, we can transfer the
297  // recording to the player and and erase the recording; i.e. ERASE Rec_.
298  play_.get(tape->Rec_, n);
299 
300  // ind_taddr_
301  // Note that play_ has been set, we can use it to check operators
302  ind_taddr_.resize(n);
303  CPPAD_ASSERT_UNKNOWN( n < num_var_tape_);
304  for(j = 0; j < n; j++)
305  { CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == local::InvOp );
306  ind_taddr_[j] = j+1;
307  }
308 
309  // for_jac_sparse_pack_, for_jac_sparse_set_
310  for_jac_sparse_pack_.resize(0, 0);
311  for_jac_sparse_set_.resize(0,0);
312 
313  // resize subgraph_info_
314  subgraph_info_.resize(
315  ind_taddr_.size(), // n_dep
316  dep_taddr_.size(), // n_ind
317  play_.num_op_rec(), // n_op
318  play_.num_var_rec() // n_var
319  );
320  // ---------------------------------------------------------------------
321  // End set ad_fun.hpp private member data
322  // ---------------------------------------------------------------------
323 
324  // now we can delete the tape
326 
327  // total number of varables in this recording
328  CPPAD_ASSERT_UNKNOWN( num_var_tape_ == play_.num_var_rec() );
329 
330  // used to determine if there is an operation sequence in *this
331  CPPAD_ASSERT_UNKNOWN( num_var_tape_ > 0 );
332 
333 }
334 
335 } // END CppAD namespace
336 
337 # endif
addr_t RecordParOp(const Base &x)
Place a parameter in the tape.
Definition: ad_tape.hpp:160
#define CPPAD_ASSERT_KNOWN(exp, msg)
Check that exp is true, if not print msg and terminate execution.
size_t size_independent_
Number of independent variables in this tapes reconding. Set by Independent and effectively const...
Definition: ad_tape.hpp:104
size_t NumRes(OpCode op)
Number of variables resulting from the specified operation.
Definition: op_code.hpp:281
static local::ADTape< Base > * tape_manage(tape_manage_job job)
Create and delete tapes that record AD&lt;Base&gt; operations for current thread.
Definition: tape_link.hpp:210
static local::ADTape< Base > * tape_ptr(void)
Pointer for the tape for this AD&lt;Base&gt; class and the current thread.
Definition: tape_link.hpp:130
void Dependent(local::ADTape< Base > *tape, const ADvector &y)
change the operation sequence corresponding to this object
Definition: dependent.hpp:236
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool Variable(const AD< Base > &x)
Definition: par_var.hpp:99
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.
local::recorder< Base > Rec_
This is where the information is recorded.
Definition: ad_tape.hpp:106
Class used to hold tape that records AD&lt;Base&gt; operations.
Definition: ad_tape.hpp:26
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool Parameter(const AD< Base > &x)
Definition: par_var.hpp:80