ml.f

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


© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)