目的
求一个实对称矩阵的所有特征值和特征向量。
先行知识
在实对称矩阵$A$的情况下,一定存在对角矩阵$D$和正交矩阵$U$满足$$D=U^TAU$$$D$的对角线元素为$A$的特征值,$U$的列向量为$A$的特征向量。
定义$n$步进旋转矩阵$$g(p,q,theta ) (begin ) b矩阵)1) cdots0(ddots(1(cos ) theta-sin )theta )
$n$阶向量$alpha$,$alphacdotg(p,q,theta ) $的几何含义是在平行于$p$维坐标轴和$q$维坐标轴的平面内旋转$theta$
算法原理
可能是考虑通过旋转变换来缩小非对角线的要素,最终得到与原始矩阵相似的对角矩阵。
每当找到矩阵$A$的绝对值最大的非对角线元素时,将其设置为$a_{pq}$,$u=g(p,q,theta ) $,并将$A$转换为$U^TAU$
转换后的值为
用$b_{p,q}=0$求解$ $theta=frac {1} {2}arctanfrac { 2a _ { pq } { a _ { QQ }-a _ { PP }
旋转操作不会改变每个行向量或列向量的大小。 也就是说,矩阵$A$的F-范数$|| a|| f=sqrt {sum _ I _ sum _ ja { ij } ^2} $保持不变。 通过计算得到$$b_{ii}
算法流程
(1)矩阵$T=E$,即初始化单位矩阵
)2)找到$A$中绝对值最大的非对角选择元素($a_{pq}$
(3)找到相应的角度(theta )、结构矩阵) u=g ) p,q,)theta ) $
(4)令$A=U^TAU,T=TU$
(5) )到) ),一直重复到$a_{pq}
代码
#包含
用户命名空间STD;
常数int n=1005;
常数双精度EPS=1e-5;
常数上限=100;
int n,id[N];
双键[ n ],mat[n],EigVal[N],EigVal[N],tmpeigvec[n];
Boolcmpeigval(intx,int y ) ) ) )。
{
返回密钥[ x ]密钥[ y ];
}
voidfind_eigen(intn,double(a ) [N],double *EigVal,double ) Eigvec ) [N] )
{
for(intI=1; i=n; I )
for(intj=1; j=n; j )
EigVec[i][j]=0;
for(intI=1; i=n; I ) EigVec[i][i]=1.0;
int count=0;
while(1)。
{
//计数反复次数
出局;
//寻找绝对值最大的元素
double mx_val=0;
int row_id,col_id;
for(intI=1; I
for(intj=I1; j=n; j )
if(Fabs ) a[I][j] ) mx_val ) MX_val=Fabs ) a[I][j],row_id=i,col_id=j;
if(MX_Vallim ) break;
//进行旋转变换
int p=row_id,q=col_id;
double Apq=a[p][q],App=a[p][p],Aqq=a[q][q];
doubletheta=0.5*Atan2(-2.0*apq,Aqq-App );
双精度int=sin (Theta )、cost=cos ) ) theta;
doublesin2t=sin(2.0*Theta )、cos2t=cos (2.0 * theta );
a [ p ] [ p ]=app * cost * Costa QQ * Sint * Sint 2.0 * apq * cost * Sint;
a [ q ] [ q ]=app * Sint * sinta QQ * cost * cost-2.0 * apq * cost * Sint;
a[p][q]=a[q][p]=0.5*(aqq-app ) *sin2t Apq*cos2t;
for(intI=1; i=n; I )
if(I!=pi!=q )
{
双精度v=a[q][i],v=a[q][i];
a[p][i]=u*cost v*sint; a[q][i]=v*cost-u*sint;
u=a[i][p],v=a[i][q];
a[i][p]=u*cost v*sint; a[i][q]=v*cost-u*sint;
}
//计算特征向量
for(intI=1; i=n; I )
{
双精度v=EigVec[i][q],v=EigVec[i][q];
EigVec[i][p]=u*cost v*sint; EigVec[i][q]=v*cost-u*sint;
}
}
//对特征值进行排序
for(intI=1; i=n; I ) id(I )、key (I )=a (I );
STD:3360sort(id1,id n 1,cmpEigVal );
for(intI=1; i=n; I )
{
EigVal[i]=a[id[i]][id[i]];
for(intj=1; j=n; j )
tmpeigvec [ j ] [ I ]=EIG vec [ j ] [ id [ I ];
}
for(intI=1; i=n; I )
for(intj=1; j=n; j )
EigVec[i][j]=tmpEigVec[i][j];
//特征向量是列向量
}
int main () )
{
scanf('%d ',n );
for(intI=1; i=n; I )
for(intj=1; j=n; j )
scanf('%lf ',mat[i][j];
find_eigen(n,mat,EigVal,EigVec );
printf(eigenvalues=);
for(intI=1; i=n; I ) printf('%lf ',EigVal[i];
printf((neigenvector=n );
for(intI=1; i=n; I )
for(intj=1; j=n; j )
printf('%lf%c ),EigVec[i][j],j==n?' n': ' );
返回0;
}