Fortran и Matlab возвращают разные собственные значения для одной и той же матрицы

Я пытаюсь научиться использовать LaPACK, диагонализируя эту простую матрицу:

0.8147    0.9058    0.1270    0.9134
0.6324    0.0975    0.2785    0.5469
0.9575    0.9649    0.1576    0.9706
0.9572    0.4854    0.8003    0.1419

В Matlab я просто использую команду eig (mat) и получаю результат:

ans =

    2.4021
   -0.0346
   -0.7158
   -0.4400

Однако когда я пытаюсь написать простую программу fortran для диагонализации той же матрицы, я получаю разные собственные значения:

      implicit none

  real*8, allocatable::dataMat(:,:),dataMatP(:,:),corMat(:,:),
 $   tempMat(:,:),corMat2(:,:)
  real*8, allocatable::matList(:),rawData(:)
  real*8, allocatable ::eig(:),diag(:),offdiag(:),tau(:),work(:)
  real*8 avg1,avg2,SD1,SD2,geneCorSum,genei,genej,temp
  integer i,j,k,numElements,info,lwork,numGenes,n,
 $   numExperiments,readsize,numAbsent,count,geneTolerance

  real*8 mean,std

  n=4

  allocate(corMat(4,4))

corMat(1,1)=0.8147
corMat(1,2)=0.9058
corMat(1,3)=0.1270
corMat(1,4)=0.9134
corMat(2,1)=0.6234
corMat(2,2)=0.0975
corMat(2,3)=0.2785
corMat(2,4)=0.5469
corMat(3,1)=0.9575
corMat(3,2)=0.9649
corMat(3,3)=0.1576
corMat(3,4)=0.9706
corMat(4,1)=0.9572
corMat(4,2)=0.4854
corMat(4,3)=0.8003
corMat(4,4)=0.1419



  allocate(diag(n))
  allocate(offdiag(n-1))
  allocate(tau(n-1))
  allocate(work(1))

  call dsytrd('U',n,corMat,n,diag,offdiag,tau,
 $ work,-1,info)
  print*,"Returning from Blocksize calculation"
  if(info.eq.0) then
  print*,"Work value successfully calculated:",work(1)
  endif
  lwork=work(1)
  deallocate(work)
  allocate(work(max(1,lwork)))

  call dsytrd('U',n,corMat,n,diag,offdiag,tau,
 $ work,lwork,info)
  print*,"Returning from full SSYTRD"
  if(info.EQ.0) then
  print*,"Tridiagonal matrix calculated"
  endif



  call dsterf(n,diag,offdiag,info)
  if(info.EQ.0) then
    print*,"Matrix Diagonalized"
  endif


  do i=1,n
  print*,"lam=",i,diag(i)
  enddo

  deallocate(offdiag)
  deallocate(work)
  deallocate(tau)

  end

Это дает мне:

 lam= 1,  -1.0228376083545221
 lam= 2,  -0.48858533844019592
 lam= 3,  0.43828991894506536
 lam= 4,  2.2848330351691031

Я сделал что-то не так, чтобы получить разные собственные значения?


person user1042343    schedule 11.12.2013    source источник


Ответы (3)


Используемые вами процедуры LAPACK предполагают симметричную матрицу, тогда как исходная матрица не.

Чтобы доказать это, создайте симметричную матрицу из исходной матрицы, используя верхнюю правую треугольную часть и запустите функцию MATLAB eig:

for i=1:4
  for j=i:4; 
    xx(i,j) = x(i,j); 
    xx(j,i)=x(i,j);
  end
end

Результирующая матрица (x была исходной матрицей, которая у вас была):

xx =

0.8147    0.9058    0.1270    0.9134
0.9058    0.0975    0.2785    0.5469
0.1270    0.2785    0.1576    0.9706
0.9134    0.5469    0.9706    0.1419

И собственные значения исходной x и симметричной xx матриц:

>> eig(x)
  ans =    2.4022    -0.0346   -0.7158   -0.4400

>> eig(xx)
  ans =   -1.0228    -0.4886     0.4383     2.2848
person nimrodm    schedule 11.12.2013

Для начала, я надеюсь, что вы не просто копируете / вставляете четыре десятичных разряда, которые Matlab по умолчанию выводит в командное окно. Во-вторых, corMat(2,1)=0.6234 отличается от соответствующего значения в вашей первой матрице. В-третьих, в документации для dsytrd говорится:

DSYTRD приводит реальную симметричную матрицу A к действительной симметричной трехдиагональной форме T с помощью преобразования ортогонального подобия ...

Ваша матрица определенно не симметрична (isequal(A,A')). Существует множество процедур, которые обрабатывают несимметричные матрицы. Вы можете, например, попробовать dgeev.

person horchler    schedule 11.12.2013

SSYTRD/DSYTRD работает только для симметричной матрицы.

person user3092403    schedule 11.12.2013