source: trunk/cppad/local/fun_construct.hpp @ 3301

Last change on this file since 3301 was 3301, checked in by bradbell, 6 years ago

merge in multiple forward direcitons from branches/forward_dir

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