Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LAPACK giving me incorrect eigenvalues

I am using DSYEV and DSYEVD from the LAPACK library to find eigenvalues and eigenvectors (Compilation syntax: gfortran -llapack ). However, I find wrong eigenvalues (-0.44,0.35,0.88) for a particular matrix. What's going wrong?

One can easily see the matrix has zero determinant, so at least one eigenvalue must be zero.

Here is my code (hope it's not too big):

    Program Real_Eigenvec
    implicit none

    integer, parameter:: n=3
    integer:: i,j, flag
    real*8:: A(n,n),X(n,n) 
    real*8:: lambda(n)
    real*8, parameter:: p=0.5d0/dsqrt(2.d0), q=1.d0-1.d0/dsqrt(2.d0)


    Print*,'Enter flag: 0 for DSYEV, 1 for DSYEVD'
    Read*, flag


    A= transpose(reshape((/ 0.d0, 1.d0, 0.d0, p, q, p, 0.5d0, 0.0d0, 0.5d0 /), shape(A)))


    print*,'Dimension of the matrix, n=',int(sqrt(float(size(A))))

    Print*,'A matrix in full form:'
    Do i=1,n
      print 100, (A(i,j),j=1,n)
    End Do

    call Eigen(A,lambda,X,n,flag)

    !    Print the eigenvalues and eigenvectors.

    PRINT 200
    DO i  = 1, n
      PRINT 201, lambda(i), (X(i,j), j=1,n)
    END DO

100 FORMAT (1X,10(:2X,F10.2))
200 FORMAT (/1X, 'Eigenvalue', 16X, 'Eigenvector^T')
201 FORMAT (1X, F10.2,4X,6(:f10.2))

    End Program Real_Eigenvec



!!!      SUBROUTINES -----------------------------------------


    Subroutine Eigen(A,lambda,X,n,flag)
    implicit none

    integer:: i,n,flag
    real*8:: A(n,n),Ap(n,n),X(n,n)
    real*8:: lambda(n)
    real*8, allocatable  :: work(:)
        integer, allocatable :: iwork(:)
    integer:: lwork,liwork,info

    print*,'n in Eiegen routine=',n

    lwork=3*n-1      ! DSYEV for flag=0
    if (flag==1) then ! DSYEVD for flag=1
      lwork=1+6*n+2*n**2
    end if 

    liwork=3+5*n


    allocate(work(lwork))
    allocate(iwork(liwork))

    Ap=A

    if (flag==0) then
      CALL DSYEV ('v', 'l', n, Ap, n, lambda, work, lwork, info)
    else
      CALL  DSYEVD ('V', 'U', n, Ap, n, lambda, work, &
                &   lwork, iwork, liwork, info)
      ! For doumentation visit: http://www.netlib.org/lapack/explore-html/d1/da2/dsyevd_8f.html
    end if

    X=Ap

    print*,'info=',info

    deallocate(work)
    deallocate(iwork)

    End Subroutine Eigen
like image 514
hbaromega Avatar asked Apr 17 '15 12:04

hbaromega


1 Answers

As stated in lapack documentation the DSYEV can be used for symmetric matrices.

DSYEV computes all eigenvalues and, optionally, eigenvectors of a real symmetric matrix A.

In the example the matrix A is not symmetric

Dimension of the matrix, n=           3
A matrix in full form:
     0.00        1.00        0.00
     0.35        0.29        0.35
     0.50        0.00        0.50

In this case you should use DGEEV which is used for unsymmetric matrices

DGEEV computes for an N-by-N real nonsymmetric matrix A, the eigenvalues and, optionally, the left and/or right eigenvectors.

In general use the eigenvalues are complex numbers so you have to provide WR and WL. Also, you need to define whether you want left VL or right VR eigenvectors.

A * v(j) = lambda(j) * v(j)
u(j)**H * A = lambda(j) * u(j)**H

The definition of the function is:

DGEEV(JOBVL, JOBVR, N, A, LDA, WR, WI, VL, LDVL, VR, LDVR, WORK, LWORK, INFO)

I suggest to use it like

LWORK = 4*N
CALL DGEEV( 'N', 'V', n, A, n, wr, wl, Ap, n, Ap, n, work, lwork, info )

In order to get both left and right eigen vectors use

real*8:: A(n,n),VL(n,n),VR(n,n)
real*8:: wr(n),wl(n)
lwork = 4*N
allocate(work(lwork))
CALL DGEEV( 'V', 'V', n, A, n, wr, wl, VL, n, VR, n, work, lwork, info )

For your matrix the imaginary part of all eigenvalues is zero. So the eigenvalues are (1.00, -0.21, 0.00).

like image 189
ztik Avatar answered Oct 28 '22 21:10

ztik