2016-06-15 5 views
1

나는 고유치와 고유 벡터를 광범위하게 사용하는 프로그램을 만들고있다. 프로그램을 테스트하는 동안 동일한 고유 값을 갖는 두 개의 고유 벡터가 직각이 아닌 경우가 발생했습니다. degenerate eigenvector의 경우, 솔루션은 유일하지 않으며 해결 루틴은 특정 벡터를 생성하는 것이 보장되지 않습니다. 왜냐하면 축퇴 된 고유 벡터의 선형 조합은 여전히 ​​동일한 고유 값을 갖는 고유 벡터이기 때문입니다. 그러나 나는 그들 중 두 명이 직각이 될 것으로 기대했다.Lapack dgeev는 비 직교 인 고유 벡터를 퇴화시킨다

이것은 버그입니까? dgeev에 의해 생성 된 모든 고유 벡터는 직교해야 하는가? 직교 벡터를 항상 출력하는 다른 루틴이 있습니까?

#include <stdio.h> 

void ctofortran(double *matrix,double *fortranMatrix,int numberOfRows,int numberOfColumns) 
{ 
/******************************************************************/ 
/* This function converts a row-major C matrix into a column-major*/ 
/* fortran "array".            */ 
/******************************************************************/ 
int columnNumber,rowNumber; 
for (columnNumber = 0;columnNumber<numberOfColumns ;columnNumber++) 
{ 
    for (rowNumber = 0;rowNumber<numberOfRows ;rowNumber++) 
    { 
     fortranMatrix[rowNumber+numberOfRows*columnNumber] = *(matrix + columnNumber+numberOfColumns*rowNumber); 
    } 
} 
} 


int main(int argc, char **argv) 
{ 
double matrix[] = {4, -1, 0, -1, 0, 0, 0, 0, 
        -1, 4, -1, 0, 0, 0, 0, 0, 
        0, -1, 4, 0, -1, 0, 0, 0, 
        -1, 0, 0, 4, 0, -1, 0, 0, 
        0, 0, -1, 0, 4, 0, 0, -1,  
        0, 0, 0, -1, 0, 4, -1, 0, 
        0, 0, 0, 0, 0, -1, 4, -1,  
        0, 0, 0, 0, -1, 0, -1, 4 }; 
int rows = 8, columns = 8; 
double *fortranmatrix = malloc(rows*columns*sizeof(double)); 
ctofortran(matrix,fortranmatrix,rows,columns); 



char jobvl ='v'; 
char jobvr = 'n'; 
//This symbolizes that the left eigenvectors will be found 
double *realEigenValues,*imaginaryEigenValues; 
realEigenValues = malloc(rows*sizeof(double)); 
imaginaryEigenValues = malloc(rows*sizeof(double)); 
double *leftEigenVectors = malloc(rows*columns*sizeof(double)); 
int lwork = rows * 4; 
double *work = malloc(lwork*sizeof(double)); 
//This allocates workspace to be used by dgeev. The recomended space is 4 times the dimension 
int info = 0;//After dgeev info = 0 if the calculation went correctly 


dgeev_(&jobvl,&jobvr,&rows,fortranmatrix,&rows,realEigenValues,imaginaryEigenValues,leftEigenVectors,&rows,NULL,&rows,work,&lwork,&info); 

int index; 
for(index = 0;index<rows;index++) 
printf("Eigenvalue %d %g + %g * i\n",index,*(realEigenValues+index), *(imaginaryEigenValues+index)); 

int v1 = 1, v6 = 6; 
double sum = 0; 
printf("\nv1\tv6\n"); 
for(index = 0;index<rows;index++) 
{ 
printf("%g\t%g\n",*(leftEigenVectors+v1*rows+index),*(leftEigenVectors+v6*rows+index)); 
sum += *(leftEigenVectors+v1*rows+index) * *(leftEigenVectors+v6*rows+index); 
} 
printf("\n Dot product between v1 and v6 %g\n",sum); 

return 0; 

} 

그리고 여기에 출력됩니다 : 여기

는 C에서 테스트 케이스입니다

Eigenvalue 0 2 + 0 * i 
Eigenvalue 1 2.58579 + 0 * i 
Eigenvalue 2 4 + 0 * i 
Eigenvalue 3 6 + 0 * i 
Eigenvalue 4 5.41421 + 0 * i 
Eigenvalue 5 5.41421 + 0 * i 
Eigenvalue 6 2.58579 + 0 * i 
Eigenvalue 7 4 + 0 * i 

v1   v6 
-0.499878 0 
-0.345657 0.353553 
0.0110458 0.5 
-0.361278 -0.353553 
0.361278 0.353553 
-0.0110458 -0.5 
0.345657 -0.353553 
0.499878 -9.88042e-16 

Dot product between v1 and v6 0.0220917 

V6 나에게 더 "정상"보인다.

*이 행렬은 대칭이지만 항상 그렇게되지는 않습니다. 이 같은 %lf

+0

나는 그냥 엉덩이에서 (나는 결코 lapack을 사용하지 않았다) 쏘고 있는데, 그것은 나에게 부동 소수점 반올림 문제처럼 보인다. 자세한 내용은 http://stackoverflow.com/questions/588004/is-floating-point-math-broken을 참조하십시오. – tonysdg

+0

관련 상품 http://icl.cs.utk.edu/lapack-forum/viewtopic.php?f=2&t=1769 같은 행렬에 대해 Julia에서 LAPACK.geev!()를 사용해 보았습니다. 축약을 위해 비 직교 고유 벡터를주었습니다 한 쌍. – roygvib

+0

@roygvib, 네, 확실히 도움이되었습니다. 나는 DSYEVD로 바꿨다. 그리고 그것은 직교 고유 벡터 (대칭 행렬을 필요로한다)를 출력한다. 비대칭 행렬이 가능하다고 생각했기 때문에 조사해 보겠다. 왜냐하면 나는 그것이 틀렸다는 것을 생각했기 때문이다. –

답변

0

인쇄 해보십시오 : 여기에 설명 된 같은

printf("\n Dot product between v1 and v6 %lf\n",sum); 

: Scanf/Printf double variable C


이 도움이되지 않는 경우, 나는이 이후 (부동 소수점 문제를 추측하고 있어요 그들의 내적은 작다).