1 | /* $Id: fun_construct.hpp 3607 2015-01-20 16:20:41Z bradbell $ */ |
---|
2 | # ifndef CPPAD_FUN_CONSTRUCT_INCLUDED |
---|
3 | # define CPPAD_FUN_CONSTRUCT_INCLUDED |
---|
4 | |
---|
5 | /* -------------------------------------------------------------------------- |
---|
6 | CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-15 Bradley M. Bell |
---|
7 | |
---|
8 | CppAD is distributed under multiple licenses. This distribution is under |
---|
9 | the terms of the |
---|
10 | Eclipse Public License Version 1.0. |
---|
11 | |
---|
12 | A copy of this license is included in the COPYING file of this distribution. |
---|
13 | Please visit http://www.coin-or.org/CppAD/ for information on other licenses. |
---|
14 | -------------------------------------------------------------------------- */ |
---|
15 | /* |
---|
16 | $begin FunConstruct$$ |
---|
17 | $spell |
---|
18 | alloc |
---|
19 | num |
---|
20 | Jac |
---|
21 | bool |
---|
22 | taylor |
---|
23 | var |
---|
24 | ADvector |
---|
25 | const |
---|
26 | Jacobian |
---|
27 | $$ |
---|
28 | |
---|
29 | $spell |
---|
30 | $$ |
---|
31 | |
---|
32 | $section Construct an ADFun Object and Stop Recording$$ |
---|
33 | |
---|
34 | $index ADFun, construct$$ |
---|
35 | $index construct, ADFun$$ |
---|
36 | $index tape, stop recording$$ |
---|
37 | $index recording, stop tape$$ |
---|
38 | |
---|
39 | $head Syntax$$ |
---|
40 | $codei%ADFun<%Base%> %f%, %g% |
---|
41 | %$$ |
---|
42 | $codei%ADFun<%Base%> %f%(%x%, %y%) |
---|
43 | %$$ |
---|
44 | $icode%g% = %f% |
---|
45 | %$$ |
---|
46 | |
---|
47 | |
---|
48 | $head Purpose$$ |
---|
49 | The $codei%AD<%Base%>%$$ object $icode f$$ can |
---|
50 | store an AD of $icode Base$$ |
---|
51 | $cref/operation sequence/glossary/Operation/Sequence/$$. |
---|
52 | It can then be used to calculate derivatives of the corresponding |
---|
53 | $cref/AD function/glossary/AD Function/$$ |
---|
54 | $latex \[ |
---|
55 | F : B^n \rightarrow B^m |
---|
56 | \] $$ |
---|
57 | where $latex B$$ is the space corresponding to objects of type $icode Base$$. |
---|
58 | |
---|
59 | $head x$$ |
---|
60 | If the argument $icode x$$ is present, it has prototype |
---|
61 | $codei% |
---|
62 | const %VectorAD% &%x% |
---|
63 | %$$ |
---|
64 | It must be the vector argument in the previous call to |
---|
65 | $cref Independent$$. |
---|
66 | Neither its size, or any of its values, are allowed to change |
---|
67 | between calling |
---|
68 | $codei% |
---|
69 | Independent(%x%) |
---|
70 | %$$ |
---|
71 | and |
---|
72 | $codei% |
---|
73 | ADFun<%Base%> %f%(%x%, %y%) |
---|
74 | %$$ |
---|
75 | |
---|
76 | $head y$$ |
---|
77 | If the argument $icode y$$ is present, it has prototype |
---|
78 | $codei% |
---|
79 | const %VectorAD% &%y% |
---|
80 | %$$ |
---|
81 | The sequence of operations that map $icode x$$ |
---|
82 | to $icode y$$ are stored in the ADFun object $icode f$$. |
---|
83 | |
---|
84 | $head VectorAD$$ |
---|
85 | The type $icode VectorAD$$ must be a $cref SimpleVector$$ class with |
---|
86 | $cref/elements of type/SimpleVector/Elements of Specified Type/$$ |
---|
87 | $codei%AD<%Base%>%$$. |
---|
88 | The routine $cref CheckSimpleVector$$ will generate an error message |
---|
89 | if this is not the case. |
---|
90 | |
---|
91 | $head Default Constructor$$ |
---|
92 | $index default, ADFun constructor$$ |
---|
93 | $index ADFun, default constructor$$ |
---|
94 | $index constructor, ADFun constructor$$ |
---|
95 | The default constructor |
---|
96 | $codei% |
---|
97 | ADFun<%Base%> %f% |
---|
98 | %$$ |
---|
99 | creates an |
---|
100 | $codei%AD<%Base%>%$$ object with no corresponding operation sequence; i.e., |
---|
101 | $codei% |
---|
102 | %f%.size_var() |
---|
103 | %$$ |
---|
104 | returns the value zero (see $cref/size_var/seq_property/size_var/$$). |
---|
105 | |
---|
106 | $head Sequence Constructor$$ |
---|
107 | $index sequence, ADFun constructor$$ |
---|
108 | $index ADFun, sequence constructor$$ |
---|
109 | $index constructor, ADFun sequence$$ |
---|
110 | The sequence constructor |
---|
111 | $codei% |
---|
112 | ADFun<%Base%> %f%(%x%, %y%) |
---|
113 | %$$ |
---|
114 | creates the $codei%AD<%Base%>%$$ object $icode f$$, |
---|
115 | stops the recording of AD of $icode Base$$ operations |
---|
116 | corresponding to the call |
---|
117 | $codei% |
---|
118 | Independent(%x%) |
---|
119 | %$$ |
---|
120 | and stores the corresponding operation sequence in the object $icode f$$. |
---|
121 | It then stores the zero order Taylor coefficients |
---|
122 | (corresponding to the value of $icode x$$) in $icode f$$. |
---|
123 | This is equivalent to the following steps using the default constructor: |
---|
124 | |
---|
125 | $list number$$ |
---|
126 | Create $icode f$$ with the default constructor |
---|
127 | $codei% |
---|
128 | ADFun<%Base%> %f%; |
---|
129 | %$$ |
---|
130 | $lnext |
---|
131 | Stop the tape and storing the operation sequence using |
---|
132 | $codei% |
---|
133 | %f%.Dependent(%x%, %y%); |
---|
134 | %$$ |
---|
135 | (see $cref Dependent$$). |
---|
136 | $lnext |
---|
137 | Calculate the zero order Taylor coefficients for all |
---|
138 | the variables in the operation sequence using |
---|
139 | $codei% |
---|
140 | %f%.Forward(%p%, %x_p%) |
---|
141 | %$$ |
---|
142 | with $icode p$$ equal to zero and the elements of $icode x_p$$ |
---|
143 | equal to the corresponding elements of $icode x$$ |
---|
144 | (see $cref Forward$$). |
---|
145 | $lend |
---|
146 | |
---|
147 | $head Copy Constructor$$ |
---|
148 | $index copy, ADFun constructor$$ |
---|
149 | $index ADFun, copy constructor$$ |
---|
150 | $index constructor, ADFun copy$$ |
---|
151 | It is an error to attempt to use the $codei%ADFun<%Base%>%$$ copy constructor; |
---|
152 | i.e., the following syntax is not allowed: |
---|
153 | $codei% |
---|
154 | ADFun<%Base%> %g%(%f%) |
---|
155 | %$$ |
---|
156 | where $icode f$$ is an $codei%ADFun<%Base%>%$$ object. |
---|
157 | Use its $cref/default constructor/FunConstruct/Default Constructor/$$ instead |
---|
158 | and its assignment operator. |
---|
159 | |
---|
160 | $head Assignment Operator$$ |
---|
161 | $index ADFun, assignment operator$$ |
---|
162 | $index assignment, ADFun operator$$ |
---|
163 | $index operator, ADFun assignment$$ |
---|
164 | The $codei%ADFun<%Base%>%$$ assignment operation |
---|
165 | $codei% |
---|
166 | %g% = %f% |
---|
167 | %$$ |
---|
168 | makes a copy of the operation sequence currently stored in $icode f$$ |
---|
169 | in the object $icode g$$. |
---|
170 | The object $icode f$$ is not affected by this operation and |
---|
171 | can be $code const$$. |
---|
172 | All of information (state) stored in $icode f$$ is copied to $icode g$$ |
---|
173 | and any information originally in $icode g$$ is lost. |
---|
174 | |
---|
175 | $subhead Taylor Coefficients$$ |
---|
176 | The Taylor coefficient information currently stored in $icode f$$ |
---|
177 | (computed by $cref/f.Forward/Forward/$$) is |
---|
178 | copied to $icode g$$. |
---|
179 | Hence, directly after this operation |
---|
180 | $codei% |
---|
181 | %g%.size_order() == %f%.size_order() |
---|
182 | %$$ |
---|
183 | |
---|
184 | $subhead Sparsity Patterns$$ |
---|
185 | The forward Jacobian sparsity pattern currently stored in $icode f$$ |
---|
186 | (computed by $cref/f.ForSparseJac/ForSparseJac/$$) is |
---|
187 | copied to $icode g$$. |
---|
188 | Hence, directly after this operation |
---|
189 | $codei% |
---|
190 | %g%.size_forward_bool() == %f%.size_forward_bool() |
---|
191 | %g%.size_forward_set() == %f%.size_forward_set() |
---|
192 | %$$ |
---|
193 | |
---|
194 | $head Parallel Mode$$ |
---|
195 | $index parallel, ADFun$$ |
---|
196 | $index ADFun, parallel$$ |
---|
197 | The call to $code Independent$$, |
---|
198 | and the corresponding call to |
---|
199 | $codei% |
---|
200 | ADFun<%Base%> %f%( %x%, %y%) |
---|
201 | %$$ |
---|
202 | or |
---|
203 | $codei% |
---|
204 | %f%.Dependent( %x%, %y%) |
---|
205 | %$$ |
---|
206 | or $cref abort_recording$$, |
---|
207 | must be preformed by the same thread; i.e., |
---|
208 | $cref/thread_alloc::thread_num/ta_thread_num/$$ must be the same. |
---|
209 | |
---|
210 | $head Example$$ |
---|
211 | |
---|
212 | $subhead Sequence Constructor$$ |
---|
213 | The file |
---|
214 | $cref independent.cpp$$ |
---|
215 | contains an example and test of the sequence constructor. |
---|
216 | It returns true if it succeeds and false otherwise. |
---|
217 | |
---|
218 | $subhead Default Constructor$$ |
---|
219 | The files |
---|
220 | $cref fun_check.cpp$$ |
---|
221 | and |
---|
222 | $cref hes_lagrangian.cpp$$ |
---|
223 | contain an examples and tests using the default constructor. |
---|
224 | They return true if they succeed and false otherwise. |
---|
225 | |
---|
226 | $children% |
---|
227 | example/fun_assign.cpp |
---|
228 | %$$ |
---|
229 | $subhead Assignment Operator$$ |
---|
230 | The file |
---|
231 | $cref fun_assign.cpp$$ |
---|
232 | contains an example and test of the $codei%ADFun<%Base%>%$$ |
---|
233 | assignment operator. |
---|
234 | It returns true if it succeeds and false otherwise. |
---|
235 | |
---|
236 | $end |
---|
237 | ---------------------------------------------------------------------------- |
---|
238 | */ |
---|
239 | |
---|
240 | namespace CppAD { // BEGIN_CPPAD_NAMESPACE |
---|
241 | /*! |
---|
242 | \file fun_construct.hpp |
---|
243 | ADFun function constructors and assignment operator. |
---|
244 | */ |
---|
245 | |
---|
246 | /*! |
---|
247 | ADFun default constructor |
---|
248 | |
---|
249 | The C++ syntax for this operation is |
---|
250 | \verbatim |
---|
251 | ADFun<Base> f |
---|
252 | \endverbatim |
---|
253 | An empty ADFun object is created. |
---|
254 | The Dependent member function, |
---|
255 | or the ADFun<Base> assingment operator, |
---|
256 | can then be used to put an operation sequence in this ADFun object. |
---|
257 | |
---|
258 | \tparam Base |
---|
259 | is the base for the recording that can be stored in this ADFun object; |
---|
260 | i.e., operation sequences that were recorded using the type \c AD<Base>. |
---|
261 | */ |
---|
262 | template <typename Base> |
---|
263 | ADFun<Base>::ADFun(void) : |
---|
264 | has_been_optimized_(false), |
---|
265 | check_for_nan_(true) , |
---|
266 | compare_change_count_(1), |
---|
267 | compare_change_number_(0), |
---|
268 | compare_change_op_index_(0), |
---|
269 | num_var_tape_(0) |
---|
270 | { } |
---|
271 | |
---|
272 | /*! |
---|
273 | ADFun assignment operator |
---|
274 | |
---|
275 | The C++ syntax for this operation is |
---|
276 | \verbatim |
---|
277 | g = f |
---|
278 | \endverbatim |
---|
279 | where \c g and \c f are ADFun<Base> ADFun objects. |
---|
280 | A copy of the the operation sequence currently stored in \c f |
---|
281 | is placed in this ADFun object (called \c g above). |
---|
282 | Any information currently stored in this ADFun object is lost. |
---|
283 | |
---|
284 | \tparam Base |
---|
285 | is the base for the recording that can be stored in this ADFun object; |
---|
286 | i.e., operation sequences that were recorded using the type \c AD<Base>. |
---|
287 | |
---|
288 | \param f |
---|
289 | ADFun object containing the operation sequence to be copied. |
---|
290 | */ |
---|
291 | template <typename Base> |
---|
292 | void ADFun<Base>::operator=(const ADFun<Base>& f) |
---|
293 | { size_t m = f.Range(); |
---|
294 | size_t n = f.Domain(); |
---|
295 | size_t i; |
---|
296 | |
---|
297 | // go through member variables in ad_fun.hpp order |
---|
298 | // |
---|
299 | // size_t objects |
---|
300 | has_been_optimized_ = f.has_been_optimized_; |
---|
301 | check_for_nan_ = f.check_for_nan_; |
---|
302 | compare_change_count_ = f.compare_change_count_; |
---|
303 | compare_change_number_ = f.compare_change_number_; |
---|
304 | compare_change_op_index_ = f.compare_change_op_index_; |
---|
305 | num_order_taylor_ = f.num_order_taylor_; |
---|
306 | cap_order_taylor_ = f.cap_order_taylor_; |
---|
307 | num_direction_taylor_ = f.num_direction_taylor_; |
---|
308 | num_var_tape_ = f.num_var_tape_; |
---|
309 | // |
---|
310 | // CppAD::vector objects |
---|
311 | ind_taddr_.resize(n); |
---|
312 | ind_taddr_ = f.ind_taddr_; |
---|
313 | dep_taddr_.resize(m); |
---|
314 | dep_taddr_ = f.dep_taddr_; |
---|
315 | dep_parameter_.resize(m); |
---|
316 | dep_parameter_ = f.dep_parameter_; |
---|
317 | // |
---|
318 | // pod_vector objects |
---|
319 | taylor_ = f.taylor_; |
---|
320 | cskip_op_ = f.cskip_op_; |
---|
321 | load_op_ = f.load_op_; |
---|
322 | // |
---|
323 | // player |
---|
324 | play_ = f.play_; |
---|
325 | // |
---|
326 | // sparse_pack |
---|
327 | for_jac_sparse_pack_.resize(0, 0); |
---|
328 | size_t n_set = f.for_jac_sparse_pack_.n_set(); |
---|
329 | size_t end = f.for_jac_sparse_pack_.end(); |
---|
330 | if( n_set > 0 ) |
---|
331 | { CPPAD_ASSERT_UNKNOWN( n_set == num_var_tape_ ); |
---|
332 | CPPAD_ASSERT_UNKNOWN( f.for_jac_sparse_set_.n_set() == 0 ); |
---|
333 | for_jac_sparse_pack_.resize(n_set, end); |
---|
334 | for(i = 0; i < num_var_tape_ ; i++) |
---|
335 | { for_jac_sparse_pack_.assignment( |
---|
336 | i , |
---|
337 | i , |
---|
338 | f.for_jac_sparse_pack_ |
---|
339 | ); |
---|
340 | } |
---|
341 | } |
---|
342 | // |
---|
343 | // sparse_set |
---|
344 | for_jac_sparse_set_.resize(0, 0); |
---|
345 | n_set = f.for_jac_sparse_set_.n_set(); |
---|
346 | end = f.for_jac_sparse_set_.end(); |
---|
347 | if( n_set > 0 ) |
---|
348 | { CPPAD_ASSERT_UNKNOWN( n_set == num_var_tape_ ); |
---|
349 | CPPAD_ASSERT_UNKNOWN( f.for_jac_sparse_pack_.n_set() == 0 ); |
---|
350 | for_jac_sparse_set_.resize(n_set, end); |
---|
351 | for(i = 0; i < num_var_tape_; i++) |
---|
352 | { for_jac_sparse_set_.assignment( |
---|
353 | i , |
---|
354 | i , |
---|
355 | f.for_jac_sparse_set_ |
---|
356 | ); |
---|
357 | } |
---|
358 | } |
---|
359 | } |
---|
360 | |
---|
361 | /*! |
---|
362 | ADFun constructor from an operation sequence. |
---|
363 | |
---|
364 | The C++ syntax for this operation is |
---|
365 | \verbatim |
---|
366 | ADFun<Base> f(x, y) |
---|
367 | \endverbatim |
---|
368 | The operation sequence that started with the previous call |
---|
369 | \c Independent(x), and that ends with this operation, is stored |
---|
370 | in this \c ADFun<Base> object \c f. |
---|
371 | |
---|
372 | \tparam Base |
---|
373 | is the base for the recording that will be stored in the object \c f; |
---|
374 | i.e., the operations were recorded using the type \c AD<Base>. |
---|
375 | |
---|
376 | \tparam VectorAD |
---|
377 | is a simple vector class with elements of typea \c AD<Base>. |
---|
378 | |
---|
379 | \param x |
---|
380 | is the independent variable vector for this ADFun object. |
---|
381 | The domain dimension of this object will be the size of \a x. |
---|
382 | |
---|
383 | \param y |
---|
384 | is the dependent variable vector for this ADFun object. |
---|
385 | The range dimension of this object will be the size of \a y. |
---|
386 | |
---|
387 | \par Taylor Coefficients |
---|
388 | A zero order forward mode sweep is done, |
---|
389 | and if NDEBUG is not defined the resulting values for the |
---|
390 | depenedent variables are checked against the values in \a y. |
---|
391 | Thus, the zero order Taylor coefficients |
---|
392 | corresponding to the value of the \a x vector |
---|
393 | are stored in this ADFun object. |
---|
394 | */ |
---|
395 | template <typename Base> |
---|
396 | template <typename VectorAD> |
---|
397 | ADFun<Base>::ADFun(const VectorAD &x, const VectorAD &y) |
---|
398 | { |
---|
399 | CPPAD_ASSERT_KNOWN( |
---|
400 | x.size() > 0, |
---|
401 | "ADFun<Base>: independent variable vector has size zero." |
---|
402 | ); |
---|
403 | CPPAD_ASSERT_KNOWN( |
---|
404 | Variable(x[0]), |
---|
405 | "ADFun<Base>: independent variable vector has been changed." |
---|
406 | ); |
---|
407 | ADTape<Base>* tape = AD<Base>::tape_ptr(x[0].tape_id_); |
---|
408 | CPPAD_ASSERT_KNOWN( |
---|
409 | tape->size_independent_ == size_t ( x.size() ), |
---|
410 | "ADFun<Base>: independent variable vector has been changed." |
---|
411 | ); |
---|
412 | size_t j, n = x.size(); |
---|
413 | # ifndef NDEBUG |
---|
414 | size_t i, m = y.size(); |
---|
415 | for(j = 0; j < n; j++) |
---|
416 | { CPPAD_ASSERT_KNOWN( |
---|
417 | size_t(x[j].taddr_) == (j+1), |
---|
418 | "ADFun<Base>: independent variable vector has been changed." |
---|
419 | ); |
---|
420 | CPPAD_ASSERT_KNOWN( |
---|
421 | x[j].tape_id_ == x[0].tape_id_, |
---|
422 | "ADFun<Base>: independent variable vector has been changed." |
---|
423 | ); |
---|
424 | } |
---|
425 | for(i = 0; i < m; i++) |
---|
426 | { CPPAD_ASSERT_KNOWN( |
---|
427 | CppAD::Parameter( y[i] ) | (y[i].tape_id_ == x[0].tape_id_) , |
---|
428 | "ADFun<Base>: dependent vector contains variables for" |
---|
429 | "\na different tape than the independent variables." |
---|
430 | ); |
---|
431 | } |
---|
432 | # endif |
---|
433 | |
---|
434 | // stop the tape and store the operation sequence |
---|
435 | Dependent(tape, y); |
---|
436 | |
---|
437 | |
---|
438 | // ad_fun.hpp member values not set by dependent |
---|
439 | check_for_nan_ = true; |
---|
440 | |
---|
441 | // allocate memory for one zero order taylor_ coefficient |
---|
442 | CPPAD_ASSERT_UNKNOWN( num_order_taylor_ == 0 ); |
---|
443 | CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == 0 ); |
---|
444 | size_t c = 1; |
---|
445 | size_t r = 1; |
---|
446 | capacity_order(c, r); |
---|
447 | CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ == c ); |
---|
448 | CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == r ); |
---|
449 | |
---|
450 | // set zero order coefficients corresponding to indpendent variables |
---|
451 | CPPAD_ASSERT_UNKNOWN( n == ind_taddr_.size() ); |
---|
452 | for(j = 0; j < n; j++) |
---|
453 | { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) ); |
---|
454 | CPPAD_ASSERT_UNKNOWN( size_t(x[j].taddr_) == (j+1) ); |
---|
455 | taylor_[ ind_taddr_[j] ] = x[j].value_; |
---|
456 | } |
---|
457 | |
---|
458 | // use independent variable values to fill in values for others |
---|
459 | CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_op_rec() ); |
---|
460 | CPPAD_ASSERT_UNKNOWN( load_op_.size() == play_.num_load_op_rec() ); |
---|
461 | forward0sweep(std::cout, false, |
---|
462 | n, num_var_tape_, &play_, cap_order_taylor_, taylor_.data(), |
---|
463 | cskip_op_.data(), load_op_, |
---|
464 | compare_change_count_, |
---|
465 | compare_change_number_, |
---|
466 | compare_change_op_index_ |
---|
467 | ); |
---|
468 | CPPAD_ASSERT_UNKNOWN( compare_change_count_ == 1 ); |
---|
469 | CPPAD_ASSERT_UNKNOWN( compare_change_number_ == 0 ); |
---|
470 | CPPAD_ASSERT_UNKNOWN( compare_change_op_index_ == 0 ); |
---|
471 | |
---|
472 | // now set the number of orders stored |
---|
473 | num_order_taylor_ = 1; |
---|
474 | |
---|
475 | # ifndef NDEBUG |
---|
476 | // on MS Visual Studio 2012, CppAD required in front of isnan ? |
---|
477 | for(i = 0; i < m; i++) |
---|
478 | if( taylor_[dep_taddr_[i]] != y[i].value_ || CppAD::isnan( y[i].value_ ) ) |
---|
479 | { using std::endl; |
---|
480 | std::ostringstream buf; |
---|
481 | buf << "A dependent variable value is not equal to " |
---|
482 | << "its tape evaluation value," << endl |
---|
483 | << "perhaps it is nan." << endl |
---|
484 | << "Dependent variable value = " |
---|
485 | << y[i].value_ << endl |
---|
486 | << "Tape evaluation value = " |
---|
487 | << taylor_[dep_taddr_[i]] << endl |
---|
488 | << "Difference = " |
---|
489 | << y[i].value_ - taylor_[dep_taddr_[i]] << endl |
---|
490 | ; |
---|
491 | CPPAD_ASSERT_KNOWN( |
---|
492 | 0, |
---|
493 | buf.str().c_str() |
---|
494 | ); |
---|
495 | } |
---|
496 | # endif |
---|
497 | } |
---|
498 | |
---|
499 | } // END_CPPAD_NAMESPACE |
---|
500 | # endif |
---|