北航 数值分析报告第二次大作业(带双步位移地QR方法)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、算法设计方案:
按题目要求,本程序运用带双步位移的QR方法求解给定矩阵的特征值,并对每一实特征值,求解其相应的特征向量。
总体思路:
1)初始化矩阵
首先需要将需要求解的矩阵输入程序。为了防止矩阵在后面的计算中被破坏保存A[][]。
2)对给定的矩阵进行拟上三角化
为了尽量减少计算量,提高程序的运行效率,在对矩阵进行QR分解之前,先进行拟上三角化。由于矩阵的QR 分解不改变矩阵的结构,所以具有拟上三角形状的矩阵的QR分解可以减少大量的计算量。这里用函数
void QuasiTriangularization()来实现,函数形参为double型N维方阵double a[][N]。
3)对拟上三角化后的矩阵进行QR分解
对拟上三角化的矩阵进行QR分解会大大减小计算量。用子程序void QR_decomposition()来实现,将Q、R设为形参,然后将计算出来的结果传入Q和R,然后求出RQ乘积。
4)对拟上三角化后的矩阵进行带双步位移的QR分解
为了加速收敛,对QR分解引入双步位移,适当选取位移量,可以避免进行复数运算。为了进一步减少计算量,在每次进行QR分解之前,先判断是否可以直接得到矩阵的一个特征值或者通过简单的运算得到矩阵的一对特征值。若可以,则得到特征值,同时对矩阵进行降阶处理;若不可以,则进行QR分解。这里用函数intTwoStepDisplacement_QR()来实现。这是用来存储计算得到的特征值的二维数组。考虑到特征值可能为复数,因此将所有特征值均当成复数处理。此函数中,QR分解部分用子函数void QR_decompositionMk()实现。这里形参有三个,分别用来传递引入双步位移后的Mk阵,A矩阵,以及当前目标矩阵的维数m。
5)计算特征向量
得到特征值后,计算实特征值相应的特征向量。这里判断所得特征值的虚数部分是否为零。特征值的特征向量采用求解相应的方程组((A-λI)x=0)的方法。因此先初始化矩阵Array,计算(A-λI),再求解方程组。
方程组的求解采用列主元的高斯消去法,由函数intGauss_column(double a[][N],double b[],double X[])实现。由于此给定矩阵的特殊性,其没有重根,所有对应于每一特征值只有一个特征向量,因此可以用高斯消去法求解此奇异的线性方程组。首先用高斯消去将矩阵(A-λI)化为上三角阵,其最后一行必定全为零。因此在反代的过程中,只要令x[]的最后一个元素为“1”,即可得到方程组的一个基础解系,从而也就是一个特征向量。
6)输出有关结果
根据题目要求,需要输出拟上三角化后的矩阵、QR分解结束后的矩阵、矩阵全部特征值及对应实特征值的特征向量。由于输出结果要求都要保留12位有效数字,所以将结果输出到文件result.txt中更有利于数据的打印。程
序中构造了两个输出函数专门来解决不同输出结果的问题,void print_lambda(complex lambda[]);void print_matrix(double mat[][N])。
二、程序源代码:
#include "stdafx.h"
#include "stdlib.h"
#include "math.h"
#define L 100 //定义最大迭代次数
#define N 10 //定义矩阵大小
#define err 1e-12 //定义误差限
//定义一个结构体来表示复数
typedefstruct complex{
double rpart;
double ipart;
};
FILE * pReadFile;
//主函数
int _tmain(intargc, _TCHAR* argv[])
{
inti,j,t;
double y[N],X[N],a[N][N],A[N][N],B[N][N],Q[N][N],R[N][N],RQ[N][N];
struct complex lambda[N];
//声明要调用的函数
void QuasiTriangularization(double a[][N]);
void QR_decomposition(double A[][N],double Q[][N],double R[][N]);
void QR_decompositionMk(double mk[][N],int m, double a[][N]);
void print_lambda(complex lambda[]);
void print_matrix(double mat[][N]);
void multi_matrix(double a[][N],double b[][N],double c[][N]);
intTwoStepDisplacement_QR(double a[][N],complex lambda[]);
intGauss_column(double a[][N],double b[],double X[]);
//矩阵初始化
for (i = 0; i < N; i++){
for (j = 0; j < N; j++){
if (i == j){
a[i][j] = 1.5 * cos((i+1) + 1.2 * (j+1));
A[i][j] = a[i][j];
}
else{
a[i][j] = sin(0.5 * (i+1) + 0.2 * (j+1));
A[i][j] = a[i][j];
}
}