File: get_started.cpp

package info (click to toggle)
cppad 2025.00.00.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 11,552 kB
  • sloc: cpp: 112,594; sh: 5,972; ansic: 179; python: 71; sed: 12; makefile: 10
file content (141 lines) | stat: -rw-r--r-- 3,859 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
// SPDX-FileContributor: 2003-24 Bradley M. Bell
// ----------------------------------------------------------------------------

/*
{xrst_begin abs_get_started.cpp}
{xrst_spell
  rclrcl
}

abs_normal Getting Started: Example and Test
############################################

Purpose
*******
Creates an :ref:`abs_normal<abs_normal_fun-name>`
representation :math:`g` for the function
:math:`f : \B{R}^3 \rightarrow \B{R}` defined by

.. math::

   f( x_0, x_1, x_2  ) = | x_0 + x_1 | + | x_1 + x_2 |

The corresponding
:ref:`abs_normal_fun@g` :math:`: \B{R}^5 \rightarrow \B{R}^3` is
given by

.. math::

   \begin{array}{rclrcl}
      g_0 ( x_0, x_1, x_2, u_0, u_1 ) & = & u_0 + u_1 & = & y_0 (x, u)
      \\
      g_1 ( x_0, x_1, x_2, u_0, u_1 ) & = & x_0 + x_1 & = & z_0 (x, u)
      \\
      g_1 ( x_0, x_1, x_2, u_0, u_1 ) & = & x_1 + x_2 & = & z_1 (x, u)
   \end{array}

Source
******
{xrst_literal
   // BEGIN C++
   // END C++
}

{xrst_end abs_get_started.cpp}
-------------------------------------------------------------------------------
*/
// BEGIN C++
# include <cppad/cppad.hpp>
namespace {
   CPPAD_TESTVECTOR(double) join(
      const CPPAD_TESTVECTOR(double)& x ,
      const CPPAD_TESTVECTOR(double)& u )
   {  size_t n = x.size();
      size_t s = u.size();
      CPPAD_TESTVECTOR(double) xu(n + s);
      for(size_t j = 0; j < n; j++)
         xu[j] = x[j];
      for(size_t j = 0; j < s; j++)
         xu[n + j] = u[j];
      return xu;
   }
}
bool get_started(void)
{  bool ok = true;
   //
   using CppAD::AD;
   using CppAD::ADFun;
   //
   size_t n = 3; // size of x
   size_t m = 1; // size of y
   size_t s = 2; // size of u and z
   //
   // record the function f(x)
   CPPAD_TESTVECTOR( AD<double> ) ax(n), ay(m);
   for(size_t j = 0; j < n; j++)
      ax[j] = double(j + 1);
   Independent( ax );
   // for this example, we ensure first absolute value is | x_0 + x_1 |
   AD<double> a0 = abs( ax[0] + ax[1] );
   // and second absolute value is | x_1 + x_2 |
   AD<double> a1 = abs( ax[1] + ax[2] );
   ay[0]         = a0 + a1;
   ADFun<double> f(ax, ay);

   // create its abs_normal representation in g, a
   ADFun<double> g, a;
   f.abs_normal_fun(g, a);

   // check dimension of domain and range space for g
   ok &= g.Domain() == n + s;
   ok &= g.Range() == m + s;

   // check dimension of domain and range space for a
   ok &= a.Domain() == n;
   ok &= a.Range() == s;

   // --------------------------------------------------------------------
   // a(x) has all the operations used to compute f(x), but the sum of the
   // absolute values is not needed for a(x), so optimize it out.
   size_t n_op = f.size_op();
   ok         &= a.size_op() == n_op;
   a.optimize();
   ok         &= a.size_op() < n_op;

   // --------------------------------------------------------------------
   // zero order forward mode calculation using g(x, u)
   CPPAD_TESTVECTOR(double) x(n), u(s), xu(n+s), yz(m+s);
   for(size_t j = 0; j < n; j++)
      x[j] = double(j + 2);
   for(size_t j = 0; j < s; j++)
      u[j] = double(j + n + 2);
   xu = join(x, u);
   yz = g.Forward(0, xu);

   // check y_0(x, u)
   double y0 = u[0] + u[1];
   ok       &= y0 == yz[0];

   // check z_0 (x, u)
   double z0 = x[0] + x[1];
   ok       &= z0 == yz[1];

   // check z_1 (x, u)
   double z1 = x[1] + x[2];
   ok       &= z1 == yz[2];


   // --------------------------------------------------------------------
   // check that y(x, a(x) ) == f(x)
   CPPAD_TESTVECTOR(double) y(m);
   y  = f.Forward(0, x);  // y  = f(x)
   u  = a.Forward(0, x);  // u  = a(x)
   xu = join(x, u);       // xu = ( x, a(x) )
   yz = g.Forward(0, xu); // yz = ( y(x, a(x)), z(x, a(x)) )
   ok &= yz[0] == y[0];

   return ok;
}
// END C++