雅可比迭代法与矩阵的特征值
- 格式:doc
- 大小:407.00 KB
- 文档页数:23
准备工作➢算法设计矩阵特征值的求法有幂法、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<stdio.h>#include<math.h>#include<time.h>#define N 501#define V (N+1)*N/2+1#define e 2.6630353#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 39int p;int q;double cosz;double sinz;double MAX;int kk;//#define PTS pts#ifdef PTSvoid 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);}#elsevoid PTS(double *m){}#endifvoid 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;}}m[(p-1)*p/2+q] = 0;PTS(m);}//void calCosSin(double *m){double app = m[(p+1)*p/2];double aqq = m[(q+1)*q/2];double apq = m[(p-1)*p/2+q];cosz = cos(atan(2 * apq / (app - aqq))/2);sinz = sin(atan(2 * apq / (app - aqq))/2); }//void find_pq(double *m){double max = 0.0;int pp = 0;int qq = 0;for(int i = 1 ; i <= V ; i++){if(fabs(m[i]) > max){recounti(i,&pp,&qq);if(pp != qq){max = fabs(m[i]);p = pp;q = qq;}}}MAX = max;}void init(double *m){for(int i = 1 ; i <= N ;i++)m[(i+1)*i/2] = a(i);for(int i = 2 ; i <= N ; i++)m[(i-1)*i/2+i-1] = b;for(int i = 3 ; i <= N ; i++)m[(i-1)*i/2+i-2] = c;PTS(m);}void calFinal(double *m){printf("---------------------------------------------------------------------------------------------------\n");printf("结果输出:\n\n");double conda;double deta = 1.0;double minlumda = pow((double)10.0,12);double maxlumda = pow((double)10.0,-12);double absminlumda = pow((double)10.0,12);for(int i = 1 ; i <=N ;i++){if(m[(i+1)*i/2] > maxlumda)maxlumda = m[(i+1)*i/2];if(m[(i+1)*i/2] < minlumda)minlumda = m[(i+1)*i/2];if(fabs(m[(i+1)*i/2]) < absminlumda)absminlumda = fabs(m[(i+1)*i/2]);deta *= m[(i+1)*i/2];}if(fabs(minlumda) < fabs(maxlumda))conda = fabs(maxlumda) / absminlumda;elseconda = fabs(minlumda) / absminlumda;printf(" Lumda(1)=%.11e Lumda(%d)=%.11e Lumda(s)=%.11e\n",minlumda,N,maxlumda,absminlumda);printf(" Cond(A)=%.11e\n",conda);printf(" Det(A)=%.11e\n\n",deta);for(int i = 1 ; i <= FK ; i++){double muk = minlumda + i * (maxlumda - minlumda) / 40;double lumdak = 0.0;double tempabsmin = pow((double)10.0,12);for(int j = 1 ; j <= N ;j++){if(fabs(muk - m[(j+1)*j/2]) < tempabsmin){lumdak = m[(j+1)*j/2];tempabsmin = fabs(muk - m[(j+1)*j/2]);}}printf(" Lumda(i%d)=%.11e ",i,lumdak);if(i%3==0)putchar(10);}putchar(10);printf("------------------------------------------------------------------------------------------------------\n");putchar(10);putchar(10);}int _tmain(int argc, _TCHAR* argv[]){double m[(N+1)*N/2+1] = {0.0};kk=0;MAX=1.0;time_t t0,t1;t0 = time( &t0);init(m);#ifndef PTSprintf("正在计算...\n\n");#endifwhile(true){kk++;find_pq(m);if(MAX<eps)break;#ifdef PTSprintf(" p=%d q=%d |max|=%e\n",p,q,MAX);printf("-----------------------------------------------------------------------\n\n"); #endifcalCosSin(m);refreshMetrix(m);}#ifdef PTSprintf(" p=%d q=%d |max|=%e\n",p,q,MAX);printf("-----------------------------------------------------------------------\n\n");#endifprintf("矩阵最终形态...\n");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);t1 = time(&t1);#ifdef PTSprintf("计算并输出用时%.2f秒\n\n",difftime(t1,t0));#elseprintf("迭代次数%d,计算用时%.2f秒\n\n",kk,difftime(t1,t0)); #endifcalFinal(m);return 0;}运行结果如下:中间运行状态如下:结果分析➢有效性分析1.由输出结果可见矩阵经过21840次迭代后,非对角元全部为零或接近于零;2.代码中有定义预编译宏//#define PTS控制程序运行过程是否输出中间迭代结果,如果输出中间迭代结果,可以发现对角元素在迭代的后期变化非常小,达到收敛的效果;3.算法在多次运行中基本可以在45秒左右完成计算(酷睿i5双核处理器,10G存,64位windows10操作系统)。
特征值和特征向量计算的数值方法在数学和计算机科学领域中,特征值和特征向量是非常重要的概念。
特征值和特征向量的计算有许多不同的数值方法,本文将介绍其中一些常见的数值方法,并分析它们的优劣和适用范围。
一、特征值和特征向量的定义在矩阵理论中,给定一个n×n的矩阵A,如果存在一个非零向量v和一个标量λ,使得Av=λv,那么称v为矩阵A的特征向量,λ为矩阵A的特征值。
特征值和特征向量的计算可以帮助我们理解矩阵的性质以及解决一些实际问题。
二、幂法幂法是计算特征值和特征向量的常用数值方法之一。
幂法的基本思想是通过多次迭代,逐渐逼近矩阵的特征值和特征向量。
具体操作如下:1. 初始化一个非零向量b0;2. 进行迭代计算:bi+1 = A * bi / ||A * bi||;3. 取出近似特征向量的最后一列:v = bn;4. 进行迭代计算特征值:λ = (Av)T * v / (vT * v)。
幂法的主要优点是简单易懂,且只需要进行矩阵向量乘法和内积计算。
然而,幂法仅能求取具有最大特征值的特征向量,而且对于存在多个特征值相等的情况并不适用。
三、反幂法反幂法是幂法的一种改进方法,用于求取矩阵A的最小特征值和对应的特征向量。
反幂法的基本步骤如下:1. 初始化一个非零向量b0;2. 进行迭代计算:bi+1 = (A - μI)^-1 * bi / ||(A - μI)^-1 * bi||;3. 取出近似特征向量的最后一列:v = bn;4. 进行迭代计算特征值:λ = (Av)T * v / (vT * v)。
反幂法的改进之处在于引入了矩阵的逆运算,通过使用矩阵A减去一个合适的常数μ乘以单位矩阵来实现。
反幂法适用于矩阵A的特征值接近于μ的情况。
四、QR方法QR方法也是一种常用的特征值计算方法,它适用于求解所有特征值以及对应的特征向量。
QR方法的基本思想是将一个矩阵分解为正交矩阵Q和上三角矩阵R的乘积,然后迭代地将矩阵A转化为更接近上三角形的形式。
雅可⽐算法求矩阵的特征值和特征向量⽬的求⼀个实对称矩阵的所有特征值和特征向量。
前置知识对于⼀个实对称矩阵A ,必存在对⾓阵D 和正交阵U 满⾜D =U T AUD 的对⾓线元素为A 的特征值,U 的列向量为A 的特征向量。
定义n 阶旋转矩阵G (p ,q ,θ)=1⋯0 ⋱ 1 cos θ−sin θ 10 ⋱ 0即在单位矩阵的基础上,修改a pp =a qq =cos θ,a qp =−a pq =sin θ对于n 阶向量α,α⋅G (p ,q ,θ)的⼏何意义是把α在与第p 维坐标轴和第q 维坐标轴平⾏的平⾯内旋转⾓度θ,并且旋转后的模长保持不变。
算法原理⼤概思路使通过旋转变换使⾮对⾓线上的元素不断变⼩,最后得到与原矩阵相似的对⾓矩阵。
每次找到矩阵A 绝对值最⼤的的⾮对⾓线元素,设为a pq ,令U =G (p ,q ,θ),将A 变换为U T AU变换后的值为通过令b p ,q =0解得θ=12arctan 2a pq a qq−a pp 特别地当a qq =a pp 时θ=π4注意到旋转操作并不会改变每个⾏向量或列向量的模长,即矩阵A 的F-范数||A ||F =∑i ∑j a 2ij 是不变的,并且通过计算可以得出$$b_{ip}2+b_{iq}2=a_{ip}2+a_{iq}2$$从⽽可以得知⾮对⾓线元素的平⽅和变⼩,对⾓线上元素的平⽅和增⼤,故⾮主对⾓线上元素的平⽅和收敛。
算法流程(1)令矩阵T =E ,即初始化单位矩阵(2)找到A 中绝对值最⼤的⾮对⾓选元素a pq(3)找到对应的⾓度θ,构造矩阵U =G (p ,q ,θ)(4)令A =U T AU ,T =TU(5)不停地重复(2)到(4),直到a pq <ϵ或迭代次数超过某个限定值,则A 的对⾓线元素近似等于A 的特征值,T 的列向量为A 的特征向量代码#include<bits/stdc++.h>using namespace std;const int N=1005;const double eps=1e-5;const int lim=100;int n,id[N];[√double key[N],mat[N][N],EigVal[N],EigVec[N][N],tmpEigVec[N][N];bool cmpEigVal(int x,int y){return key[x]>key[y];}void Find_Eigen(int n,double (*a)[N],double *EigVal,double (*EigVec)[N]){for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)EigVec[i][j]=0;for (int i=1;i<=n;i++) EigVec[i][i]=1.0;int count=0;while (1){//统计迭代次数count++;//找绝对值最⼤的元素double mx_val=0;int row_id,col_id;for (int i=1;i<n;i++)for (int j=i+1;j<=n;j++)if (fabs(a[i][j])>mx_val) mx_val=fabs(a[i][j]),row_id=i,col_id=j;if (mx_val<eps||count>lim) break;//进⾏旋转变换int p=row_id,q=col_id;double Apq=a[p][q],App=a[p][p],Aqq=a[q][q];double theta=0.5*atan2(-2.0*Apq,Aqq-App);double sint=sin(theta),cost=cos(theta);double sin2t=sin(2.0*theta),cos2t=cos(2.0*theta);a[p][p]=App*cost*cost+Aqq*sint*sint+2.0*Apq*cost*sint;a[q][q]=App*sint*sint+Aqq*cost*cost-2.0*Apq*cost*sint;a[p][q]=a[q][p]=0.5*(Aqq-App)*sin2t+Apq*cos2t;for (int i=1;i<=n;i++)if (i!=p&&i!=q){double u=a[p][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 (int i=1;i<=n;i++){double u=EigVec[i][p],v=EigVec[i][q];EigVec[i][p]=u*cost+v*sint;EigVec[i][q]=v*cost-u*sint;}}//对特征值排序for (int i=1;i<=n;i++) id[i]=i,key[i]=a[i][i];std::sort(id+1,id+n+1,cmpEigVal);for (int i=1;i<=n;i++){EigVal[i]=a[id[i]][id[i]];for (int j=1;j<=n;j++)tmpEigVec[j][i]=EigVec[j][id[i]];}for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)EigVec[i][j]=tmpEigVec[i][j];//特征向量为列向量}int main(){scanf("%d",&n);for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)scanf("%lf",&mat[i][j]);Find_Eigen(n,mat,EigVal,EigVec);printf("EigenValues = ");for (int i=1;i<=n;i++) printf("%lf ",EigVal[i]);printf("\nEigenVector =\n");for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)printf("%lf%c",EigVec[i][j],j==n?'\n':' ');return 0;}Processing math: 100%。
求矩阵特征向量的三种方法特征向量是线性代数中一个重要的概念,用于描述矩阵变换作用后不改变方向的向量。
在本文中,将介绍矩阵特征向量的三种求解方法:特征值分解法、幂迭代法和雅可比方法。
一、特征值分解法特征值分解法是求解矩阵特征向量最常用的方法之一,其基本思想是将矩阵分解为特征向量和特征值的乘积形式。
特征值分解法的步骤如下:1.对于一个n×n的矩阵A,首先求解其特征方程:,A-λI,=0,其中λ为特征值,I为单位矩阵。
2.解特征方程得到所有的特征值λ1,λ2,...,λn。
3.将每个特征值代入特征方程,得到对应的特征向量。
特征向量满足(A-λI)X=0,其中X为特征向量。
特征值分解法的优点是求解过程简单、直观,但在实际运算中,特征值分解法可能由于求解特征方程而导致计算量大、耗时长。
二、幂迭代法幂迭代法是一种迭代算法,用于求解矩阵特征向量。
幂迭代法的基本思想是通过不断迭代,逐渐逼近矩阵的特征向量。
幂迭代法的步骤如下:1.随机选择一个向量作为初始向量X(0),并进行归一化处理。
2.根据迭代公式X(k+1)=AX(k)求解下一次迭代的特征向量。
3.重复步骤2直到特征向量收敛。
一般通过判断向量的变化是否小于设定的阈值来确定是否收敛。
幂迭代法的优点是收敛速度快,但受到初始向量的选择的影响,可能不能找到所有的特征向量。
三、雅可比方法雅可比方法是一种基于矩阵相似变换的求解特征向量的方法。
雅可比方法的基本思想是通过一系列的正交相似变化,逐渐将矩阵变换为对角线形式,从而得到特征向量。
雅可比方法的步骤如下:1.初始化D为单位矩阵,将矩阵A进行复制得到副本B。
2. 在矩阵B中寻找绝对值最大的非对角元素(b_ij),将其所在行列的元素,使其变为0。
3.利用一系列的旋转变换R(i,j)乘以矩阵D和B,得到新的矩阵D和B',使得B'中新的非对角元素b_i'j'为0。
4.重复步骤2和步骤3直到矩阵B变为对角线形式。
矩阵特征问题的计算方法首先,我们来定义特征值和特征向量。
对于一个n阶方阵A,如果存在一个非零向量X,使得下式成立:AX=λX其中,λ是一个实数常数,称为特征值;X是一个非零向量,称为特征向量。
也可以将上面的等式写成(A-λI)X=0,其中I是n阶单位矩阵。
接下来,我们介绍一些常用的计算特征值和特征向量的方法。
一、特征方程法特征方程法是最常用的求解特征值和特征向量的方法。
对于n阶方阵A,我们可以将特征方程写成:A-λI,=0其中,A-λI,表示A-λI的行列式。
解特征方程即可得到n个特征值λ1,λ2,...,λn。
对于每个特征值λi,我们可以代入(A-λiI)X=0,求解出对应的特征向量Xi。
二、幂法幂法是一种迭代计算特征值和特征向量的方法。
它的基本思想是,假设一个向量X0,然后通过迭代的方式不断计算Xk+1=AXk,直到收敛为止。
此时,Xk就是所求的特征向量,而特征值可以通过计算向量Xk与Xk+1的比值得到。
三、雅可比迭代法雅可比迭代法是一种用于计算对称矩阵特征值和特征向量的方法。
它的基本思想是,通过矩阵的相似变换将对称矩阵转化为对角矩阵。
雅可比迭代法的具体步骤如下:1.初始化一个对称矩阵A,令Q为单位矩阵。
2.找到A的非对角元素中绝对值最大的元素(a,b)。
3.计算旋转矩阵R,使得AR=RD,其中D为对角矩阵,D的对角线元素与A的特征值相等。
4.更新矩阵A=R^TAR,更新矩阵Q=Q×R,重复步骤2和3,直到达到收敛条件。
四、QR分解法QR分解法是一种计算特征值和特征向量的常用方法。
它的基本思想是,将矩阵A分解为QR,其中Q是正交矩阵,R是上三角矩阵。
然后,通过对R进行迭代得到对角矩阵D,D的对角线元素与A的特征值相等。
具体步骤如下:1.初始化一个矩阵A。
2.对A进行QR分解,得到矩阵Q和R。
3.计算新矩阵A=RQ,重复步骤2和3,直到达到收敛条件。
特征值和特征向量在实际应用中具有重要的意义。
雅克⽐(Jacobi)⽅法可以⽤来求解协⽅差矩阵的特征值和特征向量。
雅可⽐⽅法(Jacobian method)求全积分的⼀种⽅法,把拉格朗阶查⽪特⽅法推⼴到求n个⾃变量⼀阶⾮线性⽅程的全积分的⽅法称为雅可⽐⽅法。
雅克⽐迭代法的计算公式简单,每迭代⼀次只需计算⼀次矩阵和向量的乘法,且计算过程中原始矩阵A始终不变,⽐较容易并⾏计算。
考虑线性⽅程组Ax=b时,⼀般当A为低阶稠密矩阵时,⽤主元消去法解此⽅程组是有效⽅法。
但是,对于由⼯程技术中产⽣的⼤型稀疏矩阵⽅程组(A的阶数很⾼,但零元素较多,例如求某些偏微分⽅程数值解所产⽣的线性⽅程组),利⽤迭代法求解此⽅程组就是合适的,在计算机内存和运算两⽅⾯,迭代法通常都可利⽤A中有⼤量零元素的特点。
雅克⽐迭代法就是众多迭代法中⽐较早且较简单的⼀种,其命名也是为纪念普鲁⼠著名数学家雅可⽐。
原理【收敛性】设Ax=b,其中A=D+L+U为⾮奇异矩阵,且对⾓阵D也⾮奇异,则当迭代矩阵J的谱半径ρ(J)<1时,雅克⽐迭代法收敛。
⾸先将⽅程组中的系数矩阵A分解成三部分,即:A = L+D+U,其中D为对⾓阵,L为下三⾓矩阵,U为上三⾓矩阵。
之后确定迭代格式,X^(k+1) = B*X^(k) +f ,(这⾥^表⽰的是上标,括号内数字即迭代次数),其中B称为迭代矩阵,雅克⽐迭代法中⼀般记为J。
(k = 0,1,......)再选取初始迭代向量X^(0),开始逐次迭代。
【优缺点】雅克⽐迭代法的优点明显,计算公式简单,每迭代⼀次只需计算⼀次矩阵和向量的乘法,且计算过程中原始矩阵A始终不变,⽐较容易并⾏计算。
然⽽这种迭代⽅式收敛速度较慢,⽽且占据的存储空间较⼤,所以⼯程中⼀般不直接⽤雅克⽐迭代法,⽽⽤其改进⽅法。
实现通过雅克⽐(Jacobi)⽅法求实对称矩阵的特征值和特征向量操作步骤:S′=G T SG,其中G是旋转矩阵,S′和S均为实对称矩阵,S′和S有相同的Frobenius norm,可以⽤⼀个最简单的3维实对称矩阵为例,根据公式进⾏详细推导(参考 ):通过旋转矩阵将对称矩阵转换为近似对⾓矩阵,进⽽求出特征值和特征向量,对⾓矩阵中主对⾓元素即为S近似的实特征值。
一、引言Jacobi方法是一种用于计算矩阵特征值和特征向量的迭代数值方法。
它是数值线性代数中的重要算法之一,广泛应用于科学计算、工程技术和金融领域。
本文将通过一个例题来介绍Jacobi方法的原理和求解过程,并分析其在实际问题中的应用。
二、Jacobi方法的原理Jacobi方法是一种通过迭代对矩阵进行相似变换,使得原矩阵逐步转化为对角矩阵的方法。
通过数值迭代,可以逐步逼近矩阵的特征值和对应的特征向量。
其基本原理如下:1. 对称矩阵特征值问题:对于对称矩阵A,存在一个正交矩阵P,使得P^T * A * P = D,其中D为对角矩阵,其对角线上的元素为A的特征值。
所以我们可以通过迭代找到P,使得P逼近正交矩阵,从而逼近A的特征值和特征向量。
2. Jacobi迭代:Jacobi方法的基本思想是通过正交相似变换,逐步将矩阵对角化。
具体来说,对于矩阵A,找到一个旋转矩阵G,使得A' = G^T * A * G为对角矩阵,然后递归地对A'进行相似变换,直到达到精度要求。
三、Jacobi方法求解特征值和特征向量的例题考虑以下矩阵A:A = [[4, -2, 2],[-2, 5, -1],[2, -1, 3]]我们将通过Jacobi方法来计算矩阵A的特征值和特征向量。
1. 对称化矩阵我们需要对矩阵A进行对称化处理。
对称化的思路是找到正交矩阵P,使得P^T * A * P = D,其中D为对角矩阵。
我们可以通过迭代找到逼近P的矩阵序列,直到达到一定的精度。
2. Jacobi迭代在Jacobi迭代的过程中,我们需要找到一个旋转矩阵G,使得A' =G^T * A * G为对角矩阵。
具体的迭代过程是:找到矩阵A中绝对值最大的非对角元素a[i][j],然后构造一个旋转矩阵G,将a[i][j]置零。
通过迭代地对A'进行相似变换,最终使得A'的非对角元素逼近零,即达到对角化的目的。
3. 计算特征值和特征向量经过一定次数的Jacobi迭代后,得到了对称矩阵A的对角化矩阵D和正交矩阵P。
#ifnde f ksf loat#defin e ksf loat doub le#e ndif#ifn def i nt16#defin e int16 i nt#e ndif#ifn def u int16#defi ne ui nt16unsig ned i nt#e ndif#ifn def k snew#defi ne ks new(s,t) ((t*)m alloc((s)*sizeo f(t)))#en dif#ifnd ef ks free#defin e ksf ree(p) if(p!=0){free(p);p=0;}#endi f/*ksJac obiGe tReal SymMa trixF eatur eValu e用jac obi方法求取*实对称*矩阵的特征值和特征向量 aMa trix[in]: n 阶实对称阵 sid e[in]: 矩阵阶大小 eps[in]:控制精度 ma xTime s[in]: 最大迭代次数返回值:前sid e*sid e个单元存储特征向量,一列为一特征向量;后side个存储单元为特征值,也就是总大小为 siz e = s ide*(side+1) 存储单元*/ksfl oat *ksJac obiGe tReal SymMa trixF eatur eValu e( ks float aMat rix[] , ui nt16side,ksf loateps , uint16 ma xTime s ){ ksfl oat *t, *s, *s1, *ve ctor, *q1; floa t a1, c , s2 , t1 , maxE ps =0 , d1 , d2, r= 1;u int16 i ,j , p , q, m , time s = 0 , le n = 0; uin t16 s tartI ndex= 0 , endI ndex; endI ndex= sid e + s tartI ndex;side+= st artIn dex;len = side*side; t = ksne w(len , ks float); s = ksn ew(le n , k sfloa t); s1 = ks new(l en ,ksflo at);q1 = k snew(len , ksfl oat);vecto r = k snew(len + side , ks float); mem set ( vect or ,0 , (len+s ide)*sizeo f(ksf loat)); for( i = star tInde x ; i < en dInde x ; i++) { ve ctor[i*sid e+i]= 1;//将初始Q[i][j]置为单位矩阵 }w hile(r >=eps && tim es <maxTi mes){p = q= sta rtInd ex; m axEps = 0;f or(i= sta rtInd ex; i < en dInde x; i++) {for(j = st artIn dex;j < e ndInd ex; j++) {i f( (j != i) &&fabs(aMatr ix[i*side+j]) > maxE ps) { ma xEps= (fl oat)f abs(a Matri x[i*s ide+j]);//找非对角元素绝对值最大的元p = i; q =j;} } }r = ma xEps;//重置当前误差 a1= (fl oat)((aMat rix[q*side+q]-a Matri x[p*s ide+p])/(2*aMat rix[p*side+q]));if(a1 >= 0){t1 = (float)(1/(fabs(a1)+s qrt(1+a1*a1)));}e lse { t1 = (flo at)(-1/(fa bs(a1)+sqr t(1+a1*a1))); } c = (flo at)(1/sqrt(1+t1*t1));s2 =t1*c;memse t ( s , 0, len*size of(ks float)); for( i = star tInde x ; i < en dInde x ; i++) { s[i*side+i] =1;//将初始Q[i][j]置为单位矩阵}s[p*s ide+p] = c ;s[p*sid e+q]=s2; s[q*side+p] = -s2;s[q*s ide+q]=c; fo r(i = star tInde x; i< end Index; i++){f or(j= sta rtInd ex; j < en dInde x; j++){ s1[i*si de+j] = s[j*sid e+i];//将矩阵s1[i][j]化为s[i][j]的转置 } }f or(i= sta rtInd ex; i < en dInde x; i++) {for(j = st artIn dex;j < e ndInd ex; j++) {d1 = 0; fo r(m = star tInde x; m< end Index; m++) {d1 += (flo at)(s1[i*s ide+m]*aMa trix[m*sid e+j]);//计算s1[i][j]*a Matri x[i][j] } t[i*side+j] = d1; } } fo r(i = star tInde x; i< end Index; i++){f or(j= sta rtInd ex; j < en dInde x; j++){ d1 = d2 = 0; for(m =start Index; m < endI ndex; m++) {d1 +=(floa t)(t[i*sid e+m]*s[m*s ide+j]);//计算t[i][j]*s[i][j] d2 += (float)(vec tor[i*side+m]*s[m*si de+j]);//计算Q[i][j]*s[i][j] } aMat rix[i*side+j] = d1; q1[i*side+j] = d2; } } me mcpy( vec tor , q1 , len*sizeo f(ksf loat)); time s +=1; }// 对特征值与特征向量进行整合for(i = st artIn dex;i < e ndInd ex; i++) { ve ctor[len+i] = a Matri x[i*s ide+i]; }k sfree ( t); ksf ree ( s );ksfre e ( s1 );k sfree ( q1 );i f(tim es >maxTi mes){k sfree ( ve ctor); retu rn NU LL; }retur n vec tor;}。
实验五矩阵的lu分解法,雅可比迭代法班级:学号::实验五 矩阵的LU 分解法,雅可比迭代一、目的与要求:➢ 熟悉求解线性方程组的有关理论和方法;➢ 会编制列主元消去法、LU 分解法、雅可比及高斯—塞德尔迭代法德程序;➢ 通过实际计算,进一步了解各种方法的优缺点,选择合适的数值方法。
二、实验内容:➢ 会编制列主元消去法、LU 分解法、雅可比及高斯—塞德尔迭代法德程序,进一步了解各种方法的优缺点。
三、程序与实例➢ 列主元高斯消去法算法:将方程用增广矩阵[A ∣b ]=(ij a )1n (n )+⨯表示1) 消元过程对k=1,2,…,n-1①选主元,找{}n ,,1k ,k i k +∈使得k ,i k a =ik a ni k max ≤≤ ②如果0a k ,i k =,则矩阵A 奇异,程序结束;否则执行③。
③如果k i k ≠,则交换第k 行与第k i 行对应元素位置,j i k j k a a ↔ j=k,┅,n+1④消元,对i=k+1, ┅,n 计算kk ik ik a a l /=对j=l+1, ┅,n+1计算kj ik ij ij a l a a -=2) 回代过程①若0=nn a ,则矩阵A 奇异,程序结束;否则执行②。
②nn n n n a a x /1,+=;对i=n-1, ┅,2,1,计算ii ni j j ij n i i a x a a x /11,⎪⎪⎭⎫ ⎝⎛-=∑+=+程序与实例程序设计如下:#include <iostream>#include <cmath>using namespace std;void disp(double** p,int row,int col){for(int i=0;i<row;i++){for(int j=0;j<col;j++)cout<<p[i][j]<<' ';cout<<endl;}}void disp(double* q,int n){cout<<"====================================="<<endl; for(int i=0;i<n;i++)cout<<"X["<<i+1<<"]="<<q[i]<<endl;cout<<"====================================="<<endl; }void input(double** p,int row,int col){for(int i=0;i<row;i++){cout<<"输入第"<<i+1<<"行:";for(int j=0;j<col;j++)cin>>p[i][j];}}int findMax(double** p,int start,int end){int max=start;for(int i=start;i<end;i++){if(abs(p[i][start])>abs(p[max][start]))max=i;}return max;}void swapRow(double** p,int one,int other,int col){double temp=0;for(int i=0;i<col;i++){temp=p[one][i];p[one][i]=p[other][i];p[other][i]=temp;}}bool dispel(double** p,int row,int col){for(int i=0;i<row;i++){int flag=findMax(p,i,row); //找列主元行号if(p[flag][i]==0) return false;swapRow(p,i,flag,col); //交换行for(int j=i+1;j<row;j++){double elem=p[j][i]/p[i][i]; //消元因子 p[j][i]=0;for(int k=i+1;k<col;k++){p[j][k]-=(elem*p[i][k]);}}}return true;}double sumRow(double** p,double* q,int row,int col){ double sum=0;for(int i=0;i<col-1;i++){if(i==row)continue;sum+=(q[i]*p[row][i]);}return sum;}void back(double** p,int row,int col,double* q){for(int i=row-1;i>=0;i--){q[i]=(p[i][col-1]-sumRow(p,q,i,col))/p[i][i]; }}int main(){cout<<"Input n:";int n; //方阵的大小cin>>n;double **p=new double* [n];for(int i=0;i<n;i++){p[i]=new double [n+1];}input(p,n,n+1);if(!dispel(p,n,n+1)){cout<<"奇异"<<endl;return 0;}double* q=new double[n];for(int i=0;i<n;i++)q[i]=0;back(p,n,n+1,q);disp(q,n);delete[] q;for(int i=0;i<n;i++)delete[] p[i];delete[] p;}1. 用列主元消去法解方程⎪⎩⎪⎨⎧=++-=++-=++035.3643x .5072x .1835x .2137.2623x .43712x 347x .1 1.1833.555x 2.304x 0.101x 321321321例2 解方程组⎪⎪⎪⎩⎪⎪⎪⎨⎧=++++=++++=++++=++++=++++-12.041.0F 1.02E 3.47D 1.04C 3.54B -6.301.0F2.01E 2.51D 4.04C 5.05B -8.531.0F 1.21E2.92D 1.46C3.53B -20.071.0F 1.10E4.48D 1.21C 4.93B -32.041.0F 1.55E5.66D 2.40C 8.77B 计算结果如下B=-1.461954C= 1.458125D=-6.004824E=-2.209018F= 14.719421➢矩阵直接三角分解法算法:将方程组A x=b 中的A分解为A=LU,其中L为单位下三角矩阵,U为上三角矩阵,则方程组A x=b化为解2个方程组Ly=b,Ux=y,具体算法如下:①对j=1,2,3,…,n计算jjau11=对i=2,3,…,n计算1111/aalii=②对k=1,2,3,…,n:a. 对j=k,k+1,…,n计算∑-=-=11kqqjkqkjkjulaub. 对i=k+1,k+2,…,n计算kkkqqkiqikikuulal/)(11∑-=-=③11by=,对k=2,3,…,n计算∑-=-=11kqqkqkkylby④nnnnuyx/=,对k=n-1,n-2,…,2,1计算kknkqqkqkkuxuyx/)(1∑+=-=注:由于计算u 的公式于计算y 的公式形式上一样,故可直接对增广矩阵[A ∣b ]=⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡+++1,211,2222211,111211n n nn n n n n n n a a a a a a a a a a a a 施行算法②,③,此时U 的第n+1列元素即为y 。
程序与实例例3 求解方程组A x=bA=⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡-----381265973274581221, b=⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡4911427 结果为X[0]= 3.000001X[1]=-2.000001X[2]= 1.000000X[3]= 5.000000#include <iostream>using namespace std;double** newMatrix(int row,int col){double **p=new double* [row]; //行for(int i=0;i<row;i++) //列p[i]=new double [col];return p;}void delMatrix(double** p,int row){for(int i=0;i<row;i++)delete[] p[i];delete[] p;}void inputMatrix(double** p,int row,int col){for(int i=0;i<row;i++){cout<<"输入第"<<i+1<<"行:";for(int j=0;j<col;j++)cin>>p[i][j];}}void dispMatrix(double** p,int row,int col){for(int i=0;i<row;i++){for(int j=0;j<col;j++)cout<<p[i][j]<<' ';cout<<endl;}}void dispVector(double* q,int n){cout<<"====================================="<<endl;for(int i=0;i<n;i++)cout<<"X["<<i+1<<"]="<<q[i]<<endl;cout<<"====================================="<<endl;}void initMatrix(double** p,int row,int col){for(int i=0;i<row;i++)for(int j=0;j<col;j++)p[i][j]=0;}double sum(double** L,double** U,int row,int col){int min=(row>=col?col:row);double sum=0;for(int i=0;i<min;i++)sum+=(U[i][col]*L[row][i]);return sum;}void resolve(double** A,double** L,double** U,int row,int col){ for(int i=0;i<col;i++)U[0][i]=A[0][i]; //把A的第一行给U的第一行L[0][0]=A[0][0];for(int i=1;i<row;i++) //填充L的第一列L[i][0]=A[i][0]/A[0][0];for(int i=1;i<row;i++)for(int j=1;j<col;j++){if(i<=j)U[i][j]=A[i][j]-sum(L,U,i,j);elseL[i][j]=(A[i][j]-sum(L,U,i,j))/U[j][j];}for(int i=0;i<row;i++)L[i][i]=1;}double sumRowY(double** L,double* y,int row){double sum=0;for(int i=0;i<row;i++)sum+=(L[row][i]*y[i]);return sum;}void backY(double** L,double* b,double* y,int row){for(int i=0;i<row;i++)y[i]=0; //初始化y向量全为零for(int i=0;i<row;i++)y[i]=b[i]-sumRowY(L,y,i);}double sumRowX(double** U,double* x,int row,int col){double sum=0;for(int i=row+1;i<col;i++)sum+=(U[row][i]*x[i]);return sum;}void backX(double** U,double* y,double* x,int row){for(int i=0;i<row;i++)x[i]=0; //初始化x向量全为零for(int i=row-1;i>=0;i--)x[i]=(y[i]-sumRowX(U,x,i,row))/U[i][i];}int main(){cout<<"输入方阵大小 n :";int n=0;cin>>n;cout<<"====================================="<<endl;cout<<"开始录入方阵数据....."<<endl;double** A=newMatrix(n,n); //开辟矩阵AinputMatrix(A,n,n); //录入数据到A中cout<<"录入方阵数据完毕......"<<endl;cout<<"====================================="<<endl<<endl;cout<<"开始录入列阵....."<<endl;cout<<"输入列阵:";double* b=new double[n]; //开辟向量bfor(int i=0;i<n;i++)cin>>b[i]; //录入数据到b中 cout<<"录入列阵数据完毕....."<<endl;double** L=newMatrix(n,n); //开辟方阵LinitMatrix(L,n,n); //初始化L全为零double** U=newMatrix(n,n); //开辟方阵UinitMatrix(U,n,n); //初始化Uresolve(A,L,U,n,n); //分解A为L与Udouble* y=new double[n]; //开辟向量ybackY(L,b,y,n); //回代求出ydouble* x=new double[n]; //开辟向量XbackX(U,y,x,n); //回代求出XdispVector(x,n);//释放空间delMatrix(A,n);delMatrix(L,n);delMatrix(U,n);delete[] b;delete[] y;delete[] x;}➢ 迭代法雅可比迭代法算法:设方程组Ax=b 系数矩阵的对角线元素)n ,,2,1i (0a ii =≠,M 为迭代次数容许的最大值,ε为容许误差。