chemometrics.f
1 ! @section Synopsis
2 !
3 ! Machine Learning subprograms for VIF. Needs LAPACK.
4 !
5 ! @author J. Marcel van der Veer
6 !
7 ! @section copyright
8 !
9 ! This file is part of VIF - vintage fortran compiler.
10 ! Copyright 2020-2025 J. Marcel van der Veer <algol68g@xs4all.nl>.
11 !
12 ! @section license
13 !
14 ! This program is free software; you can redistribute it and/or modify it
15 ! under the terms of the gnu general public license as published by the
16 ! free software foundation; either version 3 of the license, or
17 ! (at your option) any later version.
18 !
19 ! This program is distributed in the hope that it will be useful, but
20 ! without any warranty; without even the implied warranty of merchantability
21 ! or fitness for a particular purpose. See the GNU general public license for
22 ! more details. You should have received a copy of the GNU general public
23 ! license along with this program. If not, see <http://www.gnu.org/licenses/>.
24 !
25 SUBROUTINE ml colmean(a, m, n)
26 IMPLICIT none
27 INTEGER i, j, m, n
28 REAL*8 a(m, n), mean
29 REAL*16 sum
30 DO i = 1, n
31 sum = 0.0q0
32 DO j = 1, m
33 sum = sum + a(j, i)
34 END DO
35 mean = dble (sum / m)
36 DO j = 1, m
37 a(j, i) = a(j, i) - mean
38 END DO
39 END DO
40 END
41 !
42 SUBROUTINE ml ols(a, m, n, x, y, a inv, u, vt, s, tol)
43 ! Solve 'A' 'x' = 'y' by computing the pseudo-inverse of 'A'.
44 ! 'A' is a 'm'x'n' matrix which is overwritten.
45 ! 'Ainv' will contain the 'n'x'm' pseudo-inverse.
46 ! 'U' will contain U, and 'VT' will contain V^T.
47 ! 'S' will contain reciprocal singular values.
48 ! 'Tol' is the threshold ratio relative to the largest singular value.
49 ! 'Info' is a status indicator. Zero on exit is good.
50 IMPLICIT none
51 INTEGER i, info, j, k, lmax, lwork, m, n
52 ! Work dimension should be at least 8 * min(m, n)
53 REAL*8 a(m, n), x(m), y(m), u(m, m), vt(n, n), s(n), a inv(n, m), tol
54 ! Solve A x = b.
55 CALL ml pinv (a, m, n, a inv, u, vt, s, tol)
56 CALL dgemv ('n', n, m, 1.0d0, a inv, n, y, 1, 0.0d0, x, 1)
57 RETURN
58 END
59 !
60 SUBROUTINE ml pinv(a, m, n, a inv, u, vt, s, tol)
61 ! Compute pseudo-inverse of 'A'.
62 ! 'A' is a 'm'x'n' matrix which is overwritten.
63 ! 'Ainv' will contain the 'n'x'm' pseudo-inverse.
64 ! 'U' will contain U, and 'VT' will contain V^T.
65 ! 'S' will contain reciprocal singular values.
66 ! 'Tol' is the threshold ratio relative to the largest singular value.
67 ! 'Info' is a status indicator. Zero on exit is good.
68 IMPLICIT none
69 REAL*8 work
70 INTEGER iwork, lwmax
71 parameter (lwmax = 100000)
72 common /work/ work(lwmax), iwork(lwmax)
73 INTEGER i, info, j, k, lmax, lwork, m, n
74 ! Work dimension should be at least 8 * min(m, n)
75 REAL*8 a(m, n), u(m, m), vt(n, n), s(n), a inv(n, m)
76 REAL*8 s1, tol
77 REAL*16 sum
78 ! find optimal workspace.
79 lwork = -1
80 CALL dgesdd('a', m, n, a, m, s, u, m, vt, n, work, lwork, iwork, info)
81 lwork = min(lwmax, int(work(1)))
82 ! compute svd.
83 CALL dgesdd('a', m, n, a, m, s, u, m, vt, n, work, lwork, iwork, info)
84 IF (info > 0) THEN
85 write (*, *) 'failed to converge'
86 END IF
87 ! compute pseudo inverse V * S^+ * U^T
88 ! blas has no routines for multiplying diagonal matrices.
89 s1 = s(1)
90 DO i = 1, n
91 IF (s(i) > tol * s1) THEN
92 s(i) = 1.0d0 / s(i)
93 ELSE
94 s(i) = 0.0d0
95 END IF
96 END DO
97 DO i = 1, n
98 DO j = 1, m
99 sum = 0
100 DO k = 1, m
101 sum = sum + vt(k, i) * s(k) * u (j, k)
102 END DO
103 a inv(i, j) = dble (sum)
104 END DO
105 END DO
106 END
107
108 SUBROUTINE ml testsignal(a, m, n, y)
109 ! make a dummy test signal.
110 IMPLICIT none
111 INTEGER j, k, l, m, n
112 REAL*8 a(m, n), y(n), x, pi
113 CALL pi8(pi)
114 DO j = 1, m
115 y(j) = j
116 DO k = 1, n
117 a(j, k) = j * sin ((k - 0.5) / n * pi)
118 END DO
119 END DO
120 RETURN
121 END
122
123 SUBROUTINE ml svddd(a, m, n, u, vt, s, iwork)
124 !
125 ! compute the SVD of rectangular matrix using a divide and conquer algorithm.
126 ! the svd reads
127 !
128 ! a = u * sigma * vt
129 !
130 ! where sigma is an m x n matrix which is zero except for its min(m, n)
131 ! diagonal elements, u is an m x m orthogonal matrix and vt (v transposed)
132 ! is an n x n orthogonal matrix.
133 !
134 ! the diagonal elements of sigma are the real non - negative singular values
135 ! of a- negative, in descending order.
136 ! the first min(m, n) columns of u and v are the left and right singular vectors of a.
137 !
138 ! left singular vectors are stored columnwise, right singular vectors are stored rowwise.
139 ! note that the routine returns vt, not v.
140 !
141 ! iwork dimension should be at least 8 * min(m, n)
142 !
143 IMPLICIT none
144 REAL*8 work
145 INTEGER iwork, lwmax
146 parameter (lwmax = 100000)
147 common /work/ work(lwmax), iwork(lwmax)
148 INTEGER info, lda, ldu, ldvt, lwork, m, n
149 ! work dimension should be at least 8 * min(m, n)
150 REAL*8 a(m, n), u(m, m), vt(n, n), s(n)
151 lda = m
152 ldu = m
153 ldvt = n
154 ! find optimal workspace.
155 lwork = -1
156 CALL dgesdd('a', m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork, iwork, info)
157 lwork = min(lwmax, int(work(1)))
158 ! compute svd.
159 CALL dgesdd('a', m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork, iwork, info)
160 IF (info > 0) THEN
161 write (*, *) 'failed to converge'
162 END IF
163 END
164
165 SUBROUTINE ml wmatrow(a, l, n, m)
166 IMPLICIT none
167 INTEGER k, l, m, n
168 REAL*8 a(n, m)
169 ! Print row n of a having width m.
170 IF (m <= 6) THEN
171 write (*, *) (sngl(a(l, k))i, ' ', k = 1, m)
172 ELSE
173 write (*, *) (sngl(a(l, k)), k = 1, 3) , ' ... ', (sngl(a(l, k)), k = m - 2, m)
174 END IF
175 END
176
177 SUBROUTINE ml wmatrix(caption, a, n, m)
178 IMPLICIT none
179 INTEGER k, m, n
180 ! ML Write MATRIX.
181 REAL*8 a(n, m)
182 character*(*) caption
183 write (*, *) caption, ': ', n, 'x', m, ' matrix'
184 IF (n <= 20) THEN
185 DO k = 1, n
186 CALL ml wmatrow(a, k, n, m)
187 END DO
188 ELSE
189 DO k = 1, 10
190 CALL ml wmatrow(a, k, n, m)
191 END DO
192 write (*, *) ' ... '
193 DO k = n - 10, n
194 CALL ml wmatrow(a, k, n, m)
195 END DO
196 END IF
197 END
198
199 SUBROUTINE ml wcolvec(caption, v, n)
200 ! ML Write COLumn VECtor.
201 CALL ml wmatrix(caption, v, 1, n)
202 END
203
204 SUBROUTINE mlwrowvec(caption, v, m)
205 ! ML Write ROW VECtor.
206 CALL ml wmatrix(caption, v, m, 1)
207 END
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|