1 # ifndef CPPAD_CORE_FUN_CHECK_HPP
2 # define CPPAD_CORE_FUN_CHECK_HPP
3 /* --------------------------------------------------------------------------
4 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
5 
6 CppAD is distributed under the terms of the
7              Eclipse Public License Version 2.0.
8 
9 This Source Code may also be made available under the following
10 Secondary License when the conditions for such availability set forth
11 in the Eclipse Public License, Version 2.0 are satisfied:
12       GNU General Public License, Version 2.0 or later.
13 ---------------------------------------------------------------------------- */
14 
15 /*
16 $begin FunCheck$$
17 $spell
18     exp
19     bool
20     const
21     Taylor
22 $$
23 
24 
25 $section Check an ADFun Sequence of Operations$$
26 
27 $head Syntax$$
28 $icode%ok% = FunCheck(%f%, %g%, %x%, %r%, %a%)%$$
29 $pre
30 $$
31 $bold See Also$$
32 $cref CompareChange$$
33 
34 
35 $head Purpose$$
36 We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ to denote the
37 $cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$.
38 We use $latex G : \B{R}^n \rightarrow \B{R}^m$$ to denote the
39 function corresponding to the C++ function object $icode g$$.
40 This routine check if
41 $latex \[
42     F(x) = G(x)
43 \]$$
44 If $latex F(x) \neq G(x)$$, the
45 $cref/operation sequence/glossary/Operation/Sequence/$$
46 corresponding to $icode f$$ does not represents the algorithm used
47 by $icode g$$ to calculate values for $latex G$$
48 (see $cref/Discussion/FunCheck/Discussion/$$ below).
49 
50 $head f$$
51 The $code FunCheck$$ argument $icode f$$ has prototype
52 $codei%
53     ADFun<%Base%> %f%
54 %$$
55 Note that the $cref ADFun$$ object $icode f$$ is not $code const$$
56 (see $cref/Forward/FunCheck/FunCheck Uses Forward/$$ below).
57 
58 $head g$$
59 The $code FunCheck$$ argument $icode g$$ has prototype
60 $codei%
61     %Fun% &%g%
62 %$$
63 ($icode Fun$$ is defined the properties of $icode g$$).
64 The C++ function object $icode g$$ supports the syntax
65 $codei%
66     %y% = %g%(%x%)
67 %$$
68 which computes $latex y = G(x)$$.
69 
70 $subhead x$$
71 The $icode g$$ argument $icode x$$ has prototype
72 $codei%
73     const %Vector% &%x%
74 %$$
75 (see $cref/Vector/FunCheck/Vector/$$ below)
76 and its size
77 must be equal to $icode n$$, the dimension of the
78 $cref/domain/seq_property/Domain/$$ space for $icode f$$.
79 
80 $head y$$
81 The $icode g$$ result $icode y$$ has prototype
82 $codei%
83     %Vector% %y%
84 %$$
85 and its value is $latex G(x)$$.
86 The size of $icode y$$
87 is equal to $icode m$$, the dimension of the
88 $cref/range/seq_property/Range/$$ space for $icode f$$.
89 
90 $head x$$
91 The $code FunCheck$$ argument $icode x$$ has prototype
92 $codei%
93     const %Vector% &%x%
94 %$$
95 and its size
96 must be equal to $icode n$$, the dimension of the
97 $cref/domain/seq_property/Domain/$$ space for $icode f$$.
98 This specifies that point at which to compare the values
99 calculated by $icode f$$ and $icode G$$.
100 
101 $head r$$
102 The $code FunCheck$$ argument $icode r$$ has prototype
103 $codei%
104     const %Base% &%r%
105 %$$
106 It specifies the relative error the element by element
107 comparison of the value of $latex F(x)$$ and $latex G(x)$$.
108 
109 $head a$$
110 The $code FunCheck$$ argument $icode a$$ has prototype
111 $codei%
112     const %Base% &%a%
113 %$$
114 It specifies the absolute error the element by element
115 comparison of the value of $latex F(x)$$ and $latex G(x)$$.
116 
117 $head ok$$
118 The $code FunCheck$$ result $icode ok$$ has prototype
119 $codei%
120     bool %ok%
121 %$$
122 It is true, if for $latex i = 0 , \ldots , m-1$$
123 either the relative error bound is satisfied
124 $latex \[
125 | F_i (x) - G_i (x) |
126 \leq
127 r ( | F_i (x) | + | G_i (x) | )
128 \] $$
129 or the absolute error bound is satisfied
130 $latex \[
131     | F_i (x) - G_i (x) | \leq a
132 \] $$
133 It is false if for some $latex (i, j)$$ neither
134 of these bounds is satisfied.
135 
136 $head Vector$$
137 The type $icode Vector$$ must be a $cref SimpleVector$$ class with
138 $cref/elements of type/SimpleVector/Elements of Specified Type/$$
139 $icode Base$$.
140 The routine $cref CheckSimpleVector$$ will generate an error message
141 if this is not the case.
142 
143 $head FunCheck Uses Forward$$
144 After each call to $cref Forward$$,
145 the object $icode f$$ contains the corresponding
146 $cref/Taylor coefficients/glossary/Taylor Coefficient/$$.
147 After $code FunCheck$$,
148 the previous calls to $cref Forward$$ are undefined.
149 
150 $head Discussion$$
151 Suppose that the algorithm corresponding to $icode g$$ contains
152 $codei%
153     if( %x% >= 0 )
154         %y% = exp(%x%)
155     else
156         %y% = exp(-%x%)
157 %$$
158 where $icode x$$ and $icode y$$ are $codei%AD<double>%$$ objects.
159 It follows that the
160 AD of $code double$$ $cref/operation sequence/glossary/Operation/Sequence/$$
161 depends on the value of $icode x$$.
162 If the sequence of operations stored in $icode f$$ corresponds to
163 $icode g$$ with $latex x \geq 0$$,
164 the function values computed using $icode f$$ when $latex x < 0$$
165 will not agree with the function values computed by $latex g$$.
166 This is because the operation sequence corresponding to $icode g$$ changed
167 (and hence the object $icode f$$ does not represent the function
168 $latex G$$ for this value of $icode x$$).
169 In this case, you probably want to re-tape the calculations
170 performed by $icode g$$ with the
171 $cref/independent variables/glossary/Tape/Independent Variable/$$
172 equal to the values in $icode x$$
173 (so AD operation sequence properly represents the algorithm
174 for this value of independent variables).
175 
176 
177 $head Example$$
178 $children%
179     example/general/fun_check.cpp
180 %$$
181 The file
182 $cref fun_check.cpp$$
183 contains an example and test of this function.
184 
185 $end
186 ---------------------------------------------------------------------------
187 */
188 
189 namespace CppAD {
190     template <class Base, class RecBase, class Fun, class Vector>
FunCheck(ADFun<Base,RecBase> & f,Fun & g,const Vector & x,const Base & r,const Base & a)191     bool FunCheck(
192         ADFun<Base, RecBase>  &f ,
193         Fun                   &g ,
194         const Vector          &x ,
195         const Base            &r ,
196         const Base            &a )
197     {   bool ok = true;
198 
199         size_t m   = f.Range();
200         Vector yf  = f.Forward(0, x);
201         Vector yg  = g(x);
202 
203         size_t i;
204         for(i = 0; i < m; i++)
205             ok  &= NearEqual(yf[i], yg[i], r, a);
206         return ok;
207     }
208 }
209 
210 # endif
211