• 矩阵对角化


    numerical recipe 里一共讲了两种实数对称矩阵的对角化,

    jacobi法

    tred2生成上三角阵以后用tqli对角化

    前者稳定但慢易并行,后者较快但疑似不稳定,串行。

    花了一下午,一点点调试终于知道了第二种方法不稳定的原因在哪里

     1         SUBROUTINE tred2(a,d,e,novectors)
     2         USE nrtype; USE nrutil, ONLY : assert_eq,outerprod
     3         IMPLICIT NONE
     4         REAL(SP), DIMENSION(:,:), INTENT(INOUT) :: a
     5         REAL(SP), DIMENSION(:), INTENT(OUT) :: d,e
     6         LOGICAL(LGT), OPTIONAL, INTENT(IN) :: novectors
     7         INTEGER(I4B) :: i,j,l,n
     8         REAL(SP) :: f,g,h,hh,scale
     9         REAL(SP), DIMENSION(size(a,1)) :: gg
    10         LOGICAL(LGT) :: yesvec
    11         n=assert_eq(size(a,1),size(a,2),size(d),size(e),'tred2')
    12         if (present(novectors)) then
    13                 yesvec=.not. novectors
    14         else
    15                 yesvec=.true.
    16         end if
    17         do i=n,2,-1
    18                 l=i-1
    19                 h=0.0
    20                 if (l > 1) then
    21                         scale=sum(abs(a(i,1:l)))
    22                         if (scale == 0.0) then
    23                                 e(i)=a(i,l)
    24                         else
    25                                 a(i,1:l)=a(i,1:l)/scale
    26                                 h=sum(a(i,1:l)**2)
    27                                 f=a(i,l)
    28                                 g=-sign(sqrt(h),f)
    29                                 e(i)=scale*g
    30                                 h=h-f*g
    31                                 a(i,l)=f-g
    32                                 if (yesvec) a(1:l,i)=a(i,1:l)/h
    33                                 do j=1,l
    34                                         e(j)=(dot_product(a(j,1:j),a(i,1:j)) &
    35                                         +dot_product(a(j+1:l,j),a(i,j+1:l)))/h
    36                                 end do
    37                                 f=dot_product(e(1:l),a(i,1:l))
    38                                 hh=f/(h+h)
    39                                 e(1:l)=e(1:l)-hh*a(i,1:l)
    40                                 do j=1,l
    41                                         a(j,1:j)=a(j,1:j)-a(i,j)*e(1:j)-e(j)*a(i,1:j)
    42                                 end do
    43                         end if
    44                 else
    45                         e(i)=a(i,l)
    46                 end if
    47                 d(i)=h
    48         end do
    49         if (yesvec) d(1)=0.0
    50         e(1)=0.0
    51         do i=1,n
    52                 if (yesvec) then
    53                         l=i-1
    54                         if (d(i) /= 0.0) then
    55                                 gg(1:l)=matmul(a(i,1:l),a(1:l,1:l))
    56                                 a(1:l,1:l)=a(1:l,1:l)-outerprod(a(1:l,i),gg(1:l))
    57                         end if
    58                         d(i)=a(i,i)
    59                         a(i,i)=1.0
    60                         a(i,1:l)=0.0
    61                         a(1:l,i)=0.0
    62                 else
    63                         d(i)=a(i,i)
    64                 end if
    65         end do
    66         END SUBROUTINE tred2

    问题出在22行,scale==0.0的判断上。稍微有点常识的人都知道,计算机里做浮点数判断不能用==,必须用abs(scale-0.0)<episilon episilon为一个很小的数。没想到numerical recipe第三版的这本书里还有这样子的代码。

    鉴于scale>=0.0,所以改成scale<=episilon就行了,结果就很稳定了。

    吐槽一下,怪不得我总觉得结果怎么那么随机,原来是这里出的问题,这可是真随机啊!

  • 相关阅读:
    Python中的装饰器之@wraps(四)
    python中装饰器之有参装饰器(三)
    python中装饰器之叠加装饰器(二)
    python中装饰器之闭包函数(一)
    python中的命名空间
    函数的嵌套与迭代
    函数对象
    matlab学习checkbox使用
    matlab学习滚动条改变文本数值
    matlab学习GUI可调的界面窗口
  • 原文地址:https://www.cnblogs.com/sickboy/p/3804254.html
Copyright © 2020-2023  润新知