Fortran計算大型對稱稀疏矩陣的二範數

在fortran中,有時候需要對一個大型的稀疏矩陣求取2範數。
由於大型稀疏矩陣一般使用CSR存儲格式,MKL函數庫中的gesvd的參數是稠密矩陣<matlab可以直接計算稀疏矩陣的2範數>
所以本文根據相關知識,給出求解CSR存儲的對稱方陣2範數的代碼。

由矩陣分析可以知道:
特徵值分解和奇異值分解的區別所有的矩陣都可以進行奇異值分解,而只有方陣纔可以進行特徵值分解。
當所給的矩陣是對稱的方陣,A'=A,二者的結果是相同的。
也就是說對稱矩陣的特徵值分解是所有奇異值分解的一個特例。
但是二者還是存在一些小的差異,奇異值分解需要對奇異值從大到小的排序,而且全部是大於等於零。

代碼運行環境:
win10 + vs2019 + ivf2020
代碼如下:
program SparseMatrix2norm
    implicit none
    integer, parameter        :: n = 3  !// depend on your equation
    integer                   :: i, j, mm, tmp, fileid, first, num
    real(kind=8)              :: matrix(n,n)
    real(kind=8), allocatable :: aa(:)
    integer, allocatable      :: ia(:), ja(:)
  
    type                      :: node
        real(kind=8)          :: s
        integer               :: k1, k2
        type (node), pointer  :: next
    end type node 
    type (node), pointer      :: head, tail, p, q  
    
    
    !//=====================
    character(len=1)  :: uplo = 'u'
    integer           :: fpm(128), m0, loop, m, info
    real*8, parameter :: emin = 1d-5, emax = 1d5
    real*8            :: x(n,n), tempx(n,n), epsout, e(n), res
    
    !// input data
    open( newunit = fileid, file = 'SparseMatrix.txt' )  !// The sparse matrix data needs to be given by itself
    read( fileid,* ) matrix
    close( fileid )
 
    !// =========================store data by CSR format=======================
    first = 1
    if ( .not.associated(p) ) then
        allocate( p )
        q    => p
        nullify( p%next )
        q%k2 = first
        tmp  = q%k2
    end if
  
    num = 0  !// calculate the number of no-zero
    do i =  1, n
        mm = 0  !// calculate the position of no-zero in every row
        do j = i, n
            if ( matrix(i,j) /= 0.0 ) then
                if ( .not.associated(head) ) then
                    allocate( head )
                    tail    => head
                    nullify( tail%next )
                    tail%s  = matrix(i,j)
                    tail%k1 = j
                    num     = num + 1
                    mm      = mm + 1
                else
                    allocate( tail%next )
                    tail    => tail%next
                    tail%s  = matrix(i,j)
                    tail%k1 = j
                    num     = num + 1  
                    mm      = mm + 1  
                    nullify( tail%next )
                end if
            end if
        end do
        if ( associated(p) ) then
            allocate( q%next )
            q    => q%next
            q%k2 = tmp + mm
            tmp  = q%k2
            nullify( q%next )
        end if
    end do
  
    allocate( aa(num), ja(num), ia(n+1) )  !// store the no-zero element
    !// output a and ja
    tail => head
    j = 1
    do 
        if ( .not.associated(tail) ) exit
        aa(j) = tail%s
        ja(j) = tail%k1
        j     = j + 1
        tail  => tail%next
    end do
  
    !// output ia
    q => p
    j = 1
    do 
        if ( .not.associated(q) ) exit
        ia(j) = q%k2
        j     = j + 1
        q     => q%next
    end do
  
    nullify( head, tail, p, q )
    !// =========================store data by CSR format=======================
    write ( *,'(a)' ) '>> Original data'
    write ( *,'(<n>f7.2)' ) matrix
    write ( *,'(a)' ) '>> CSR data'
    write ( *,'(*(f7.2))' ) aa
    write ( *,'(a)' ) '>> B data'
    write ( *,'(a)' ) '>> Colnum of CSR data'
    write ( *,'(*(i4))' ) ja
    write ( *,'(a)' ) '>> The position of CSR data'
    write ( *,'(*(i4))' ) ia
  
    !// eig
    m0 = n
    call feastinit(fpm)
    call dfeast_scsrev(uplo, n, aa, ia, ja, fpm, epsout, loop, emin, emax, m0, e, x, m, res, info)
    tempx = x
    
    if ( info == 0 ) then
            write(*,'(a)') "計算正確..."
    else
            write(*,'(a)') "計算錯誤..."
    end if
    
    write ( *,'(a)' ) '>> The 2-norm of Sparse Matrix is...'
    write(*,'(*(1x,f7.4,2x))') maxval(abs(e))
    
    
    deallocate( aa, ja, ia )
  
end program SparseMatrix2norm


運行結果如下:
>> Original data
   2.00   0.00  -1.00
   0.00   3.00   0.00
  -1.00   0.00   4.00
>> CSR data
   2.00  -1.00   3.00   4.00
>> B data
>> Colnum of CSR data
   1   3   2   3
>> The position of CSR data
   1   3   4   5
計算正確...
>> The 2-norm of Sparse Matrix is...
  4.4142

上述計算結果與matlab的計算結果相同。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章