File: lu_vec_ad_ok.cpp

package info (click to toggle)
cppad 2025.00.00.2-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 11,552 kB
  • sloc: cpp: 112,594; sh: 5,972; ansic: 179; python: 71; sed: 12; makefile: 10
file content (145 lines) | stat: -rw-r--r-- 3,487 bytes parent folder | download | duplicates (2)
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
142
143
144
145
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
// SPDX-FileContributor: 2003-22 Bradley M. Bell
// ----------------------------------------------------------------------------

/*
{xrst_begin lu_vec_ad_ok.cpp}

Lu Factor and Solve With Recorded Pivoting: Example and Test
############################################################

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

{xrst_end lu_vec_ad_ok.cpp}
*/

// BEGIN C++

# include <cppad/cppad.hpp>
# include "lu_vec_ad.hpp"
# include <cppad/speed/det_by_minor.hpp>

bool lu_vec_ad_ok(void)
{  bool  ok = true;

   using namespace CppAD;
   typedef AD<double> ADdouble;
   using CppAD::NearEqual;
   double eps99 = 99.0 * std::numeric_limits<double>::epsilon();

   size_t              n = 3;
   size_t              m = 2;
   double a1[] = {
      3., 0., 0., // (1,1) is first  pivot
      1., 2., 1., // (2,2) is second pivot
      1., 0., .5  // (3,3) is third  pivot
   };
   double a2[] = {
      1., 2., 1., // (1,2) is second pivot
      3., 0., 0., // (2,1) is first  pivot
      1., 0., .5  // (3,3) is third  pivot
   };
   double rhs[] = {
      1., 3.,
      2., 2.,
      3., 1.
   };

   VecAD<double>       Copy    (n * n);
   VecAD<double>       Rhs     (n * m);
   VecAD<double>       Result  (n * m);
   ADdouble            logdet;
   ADdouble            signdet;

   // routine for checking determinants using expansion by minors
   det_by_minor<ADdouble> Det(n);

   // matrix we are computing the determinant of
   CPPAD_TESTVECTOR(ADdouble) A(n * n);

   // dependent variable values
   CPPAD_TESTVECTOR(ADdouble) Y(1 + n * m);

   size_t  i;
   size_t  j;
   size_t  k;

   // Original matrix
   for(i = 0; i < n * n; i++)
      A[i] = a1[i];

   // right hand side
   for(j = 0; j < n; j++)
      for(k = 0; k < m; k++)
         Rhs[ j * m + k ] = rhs[ j * m + k ];

   // Declare independent variables
   Independent(A);

   // Copy the matrix
   ADdouble index(0);
   for(i = 0; i < n*n; i++)
   {  Copy[index] = A[i];
      index += 1.;
   }

   // Solve the equation
   signdet = lu_vec_ad(n, m, Copy, Rhs, Result, logdet);

   // Result is the first n * m dependent variables
   index = 0.;
   for(i = 0; i < n * m; i++)
   {  Y[i] = Result[index];
      index += 1.;
   }

   // Determinant is last component of the solution
   Y[ n * m ] = signdet * exp( logdet );

   // construct f: A -> Y
   ADFun<double> f(A, Y);

   // check determinant using minors routine
   ADdouble determinant = Det( A );
   ok &= NearEqual(Y[n * m], determinant, eps99, eps99);


   // Check solution of Rhs = A * Result
   double sum;
   for(k = 0; k < m; k++)
   {  for(i = 0; i < n; i++)
      {  sum = 0.;
         for(j = 0; j < n; j++)
            sum += a1[i * n + j] * Value( Y[j * m + k] );
         ok &= NearEqual( rhs[i * m + k], sum, eps99, eps99);
      }
   }

   CPPAD_TESTVECTOR(double) y2(1 + n * m);
   CPPAD_TESTVECTOR(double) A2(n * n);
   for(i = 0; i < n * n; i++)
      A[i] = A2[i] = a2[i];


   y2          = f.Forward(0, A2);
   determinant = Det(A);
   ok &= NearEqual(y2[ n * m], Value(determinant), eps99, eps99);

   // Check solution of Rhs = A2 * Result
   for(k = 0; k < m; k++)
   {  for(i = 0; i < n; i++)
      {  sum = 0.;
         for(j = 0; j < n; j++)
            sum += a2[i * n + j] * y2[j * m + k];
         ok &= NearEqual( rhs[i * m + k], sum, eps99, eps99);
      }
   }

   return ok;
}

// END C++