北航数值分析1-Jacobi法计算矩阵特征值
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
准备工作
➢算法设计
矩阵特征值的求法有幂法、Jacobi法、QR法等,其中幂法可求得矩阵按模最大的特征值(反幂法可求得按模最小特征值),Jacobi法则可以求得对称阵的所有特征值。
分析一:由题目中所给条件λ1≤λ2≤…≤λn,可得出λ1、λn按模并不一定严格小于或大于其他特征值,且即使按模严格小于或大于其他特征值,也极有可能出现|λs|<λ1|<|λn |或|λs|<λn|<|λ1 |的情况,导致按幂法和反幂法无法求解λ1或λn二者中的一者;
分析二:题目要求求解与数μk =λ1+k(λn-λ1)/40最接近的特征值λik(k=1,2,3…39),这个问题其实可以转换为求A-μk 按模最小的特征值的问题,但因为在第一个问题中无法确定能肯定的求得λ1和λn,所以第二个问题暂先搁浅;
分析三:cond(A) 2 = ||A|| * ||A-1|| =|λ|max * |λ|min,这可以用幂法和反幂法求得,det(A) =λ1 *λ2 * … *λn,这需要求得矩阵A的所有特征值。
由以上分析可知,用幂法和反幂法无法完成所有问题的求解,而用Jacobi法求得矩阵所有特征值后可以求解题目中所给的各个问题。所以该题可以用Jacobi法求解。
➢模块设计
由
➢数据结构设计
由于矩阵是对称阵,上下带宽均为2,所以可以考虑用二维数组压缩存储矩阵上半带或下半带。但由于Jacobi法在迭代过程中会破坏矩阵的形态,所以原来为零的元素可能会变为非零,这就导致原来的二维数组无法存储迭代后的矩阵。基于此的考虑,决定采用一维数组存储整个下三角阵,以此保证迭代的正确进行。
完整代码如下(编译环境windows10 + visual studio2010):
完整代码
// math.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
#include
#define N 501
#define V (N+1)*N/2+1
#define e 2.718281828459045235360287471352662497757247093699959574966967627724076630353 #define a(i) (1.64 - 0.024 * (i)) * sin(0.2 * (i)) - 0.64 * pow(e , 0.1 / (i))
#define b 0.16
#define c -0.064
#define eps pow((double)10.0,-12)
#define PFbits "%10.5f "
#define PFrols 5
#define PFe %.11e
#define FK 39
int p;
int q;
double cosz;
double sinz;
double MAX;
int kk;
//#define PTS pts
#ifdef PTS
void PTS(double *m)
{
printf("-----------------------------------------------------------------------\n");
printf(" 迭代第%d次\n",kk);
for(int i = 1 ; i <= PFrols ; i++)
{
for( int j = (i-1)*i/2+1 ; j <= (i+1)*i/2 ; j++)
{
printf(PFbits,m[j]);
}
putchar(10);
}
for(int i = 1 ; i <= PFrols+1 ; i++)
{
printf(" ... ");
}
putchar(10);
printf(" . .\n");
printf(" . .\n");
printf(" . .\n");
for(int i = 1 ; i <= PFrols+2 ; i++)
{
printf(" ... ");
}
putchar(10);
}
#else
void PTS(double *m)
{
}
#endif
void recounti(int i , int *pp, int *qq)
{
for(int j = 0 ; j <= N-1 ; j++)
{
if( (i - (j+1)*j/2) <= j+1)
{
*pp = j+1;
*qq = i - (j+1)*j/2;
break;
}
}
}
void refreshMetrix(double *m)
{
int ipr,ipc,iqr,iqc;
m[(p+1)*p/2] = m[(p+1)*p/2] * pow(cosz,2) + m[(q+1)*q/2] * pow(sinz,2) + 2 * m[(p-1)*p/2+q] * cosz * sinz;
m[(q+1)*q/2] = m[(p+1)*p/2] * pow(sinz,2) + m[(q+1)*q/2] * pow(cosz,2) - 2 * m[(p-1)*p/2+q] * cosz * sinz;
for(int i = 1; i <= N ;i++)
{
if(i != p && i != q)
{
if(i > p)
{
ipr = i;
ipc = p;
}
else
{
ipr = p;
ipc = i;
}
if(i > q)
{
iqr = i;
iqc = q;
}
else
{
iqr = q;
iqc = i;
}
m[(ipr-1)*ipr/2+ipc] = m[(ipr-1)*ipr/2+ipc] * cosz + m[(iqr-1)*iqr/2+iqc] * sinz;
m[(iqr-1)*iqr/2+iqc] = -m[(ipr-1)*ipr/2+ipc] * sinz + m[(iqr-1)*iqr/2+iqc] * cosz;
}