source: trunk/example/general/compare_change.cpp @ 3928

Last change on this file since 3928 was 3928, checked in by bradbell, 2 years ago

merge to branch: trunk
from repository: https://github.com/coin-or/CppAD
start hash code: c326e13e2a7554ceb73e05e6af6b7c9fac4a2b4d
end hash code: 50e67821490174a876874dae9dbfa83365212e2d

commit 50e67821490174a876874dae9dbfa83365212e2d
Author: Brad Bell <bradbell@…>
Date: Wed May 17 09:52:27 2017 -0700

  1. Move example/*.cpp -> example/general/*.cpp.
  2. Make example/CMakeLists.txt control debug/release for all subdirectories.
  3. Advanmce to cppad-20170517.
File size: 4.7 KB
Line 
1/* --------------------------------------------------------------------------
2CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
3
4CppAD is distributed under multiple licenses. This distribution is under
5the terms of the
6                    Eclipse Public License Version 1.0.
7
8A copy of this license is included in the COPYING file of this distribution.
9Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
10-------------------------------------------------------------------------- */
11
12/*
13$begin compare_change.cpp$$
14$spell
15        Cpp
16$$
17
18$section CompareChange and Re-Tape: Example and Test$$
19$mindex compare change re-tape$$
20
21
22$code
23$srcfile%example/general/compare_change.cpp%0%// BEGIN C++%// END C++%1%$$
24$$
25
26$end
27*/
28// BEGIN C++
29
30# include <cppad/cppad.hpp>
31
32namespace { // put this function in the empty namespace
33        template <typename Type>
34        Type Minimum(const Type &x, const Type &y)
35        {       // Use a comparision to compute the min(x, y)
36                // (note that CondExp would never require retaping).
37                if( x < y )
38                        return x;
39                return y;
40        }
41        struct error_info {
42                bool known;
43                int  line;
44                std::string file;
45                std::string exp;
46                std::string msg;
47        };
48        void error_handler(
49                bool        known       ,
50                int         line        ,
51                const char *file        ,
52                const char *exp         ,
53                const char *msg         )
54        {       // error handler must not return, so throw an exception
55                error_info info;
56                info.known = known;
57                info.line  = line;
58                info.file  = file;
59                info.exp   = exp;
60                info.msg   = msg;
61                throw info;
62        }
63
64}
65
66bool compare_change(void)
67{       bool ok = true;
68        using CppAD::AD;
69
70        // domain space vector
71        size_t n = 2;
72        CPPAD_TESTVECTOR(AD<double>) ax(n);
73        ax[0] = 3.;
74        ax[1] = 4.;
75
76        // declare independent variables and start tape recording
77        CppAD::Independent(ax);
78
79        // range space vector
80        size_t m = 1;
81        CPPAD_TESTVECTOR(AD<double>) ay(m);
82        ay[0] = Minimum(ax[0], ax[1]);
83
84        // create f: x -> y and stop tape recording
85        CppAD::ADFun<double> f(ax, ay);
86
87        // set count to one (not necessry because is its default value)
88        f.compare_change_count(1);
89
90        // evaluate zero mode Forward where comparison has the same result
91        // as during taping; i.e., x[0] < x[1].
92        CPPAD_TESTVECTOR(double) x(n), y(m);
93        x[0] = 2.;
94        x[1] = 3.;
95        y    = f.Forward(0, x);
96        ok  &= (y[0] == x[0]);
97        ok  &= (y[0] == Minimum(x[0], x[1]));
98        ok  &= (f.compare_change_number() == 0);
99        ok  &= (f.compare_change_op_index() == 0);
100
101        // evaluate zero mode Forward where comparison has different result
102        // as during taping; i.e., x[0] >= x[1].
103        x[0] = 3.;
104        x[1] = 2.;
105        y    = f.Forward(0, x);
106        ok  &= (y[0] == x[0]);
107        ok  &= (y[0] != Minimum(x[0], x[1]));
108        ok  &= (f.compare_change_number() == 1);
109        ok  &= (f.compare_change_op_index() > 0 );
110        size_t op_index = f.compare_change_op_index();
111
112        // Local block during which default CppAD error handler is replaced.
113        // If you do not replace the default CppAD error handler,
114        // and you run in the debugger, you will be able to inspect the
115        // call stack and see that 'if( x < y )' is where the comparison is.
116        bool missed_error = true;
117        {       CppAD::ErrorHandler local_error_handler(error_handler);
118
119                std::string check_msg =
120                        "Operator index equals abort_op_index in Independent";
121                try {
122                        // determine the operation index where the change occurred
123                        CppAD::Independent(ax, op_index);
124                        ay[0] = Minimum(ax[0], ax[1]);
125# ifdef NDEBUG
126                        // CppAD does not spend time checking operator index when
127                        // NDEBUG is defined
128                        missed_error = false;
129                        AD<double>::abort_recording();
130# endif
131                }
132                catch( error_info info )
133                {       missed_error = false;
134                        ok          &= info.known;
135                        ok          &= info.msg == check_msg;
136                        // Must abort the recording so we can start a new one
137                        // (and to avoid a memory leak).
138                        AD<double>::abort_recording();
139                }
140        }
141        ok &= ! missed_error;
142
143
144        // set count to zero to demonstrate case where comparisons are not checked
145        f.compare_change_count(0);
146        y    = f.Forward(0, x);
147        ok  &= (y[0] == x[0]);
148        ok  &= (y[0] != Minimum(x[0], x[1]));
149        ok  &= (f.compare_change_number()   == 0);
150        ok  &= (f.compare_change_op_index() == 0);
151
152        // now demonstrate that compare_change_number works for an optimized
153        // tape (note that compare_change_op_index is always zero after optimize)
154        f.optimize();
155        f.compare_change_count(1);
156        y    = f.Forward(0, x);
157        ok  &= (y[0] == x[0]);
158        ok  &= (y[0] != Minimum(x[0], x[1]));
159        ok  &= (f.compare_change_number()   == 1);
160        ok  &= (f.compare_change_op_index() == 0);
161
162        // now retape to get the a tape that agrees with the algorithm
163        ax[0] = x[0];
164        ax[1] = x[1];
165        Independent(ax);
166        ay[0] = Minimum(ax[0], ax[1]);
167        f.Dependent(ax, ay);
168        y    = f.Forward(0, x);
169        ok  &= (y[0] == x[1]);
170        ok  &= (y[0] == Minimum(x[0], x[1]));
171        ok  &= (f.compare_change_number()   == 0);
172        ok  &= (f.compare_change_op_index() == 0);
173
174        return ok;
175}
176
177
178// END C++
Note: See TracBrowser for help on using the repository browser.