⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qr.txt

📁 Java实现QR分解法求矩阵的所有特征值及特征向量
💻 TXT
字号:
/**
 * @(#)work.java数值分析课计算实习作业第二题 QR分解法求矩阵的所有特征值及特征向量
 *编程语言:JAVA
 * work application
 *
 * @author 503所 马灵霞
 * @version 1.00 2008/11/16
 */
import java.text.*;
import java.math.*;
import java.util.*;
class date{
	static double[][] upTriangle(double matrixA[][]){
//子程序:对matrixA进行拟上三角化,并将拟上三角化后的矩阵存入到matrixA中
		for(int r=0;r<=matrixA.length-3;r++){
    			int allzero=0;
    			for(int i=r+2;i<=matrixA.length-1;i++){
    				if(matrixA[i][r]!=0) {
    					allzero=1;
    					break;
    				}		
    			}
    			if(allzero==0) continue;
    			else{
    				double d=0;
    				double c=0;
    				double h=0;
    				double p[]=new double[matrixA.length];
    				double q[]=new double[matrixA.length];
    				double t=0;
    				double w[]=new double[matrixA.length];
    				double sum1=0;//part variable 
    				for(int i=r+1;i<=matrixA.length-1;i++){
    					sum1=sum1+matrixA[i][r]*matrixA[i][r];
    				}
    				d=Math.sqrt(sum1);
    				c=-Math.signum(matrixA[r+1][r])*d;
    				h=c*c-c*matrixA[r+1][r];
    				double u[]=new double[matrixA.length];
    				for(int i=0;i<=r;i++){
    					u[i]=0;
    				}
    				u[r+1]=matrixA[r+1][r]-c;
    				for(int i=r+2;i<=matrixA.length-1;i++){
    					u[i]=matrixA[i][r];
    				}
    				for(int j=0;j<=matrixA.length-1;j++){
    					double sum2=0;
    					for(int i=0;i<=matrixA.length-1;i++){
    						sum2=sum2+matrixA[i][j]*u[i];
    					}
    					p[j]=sum2/h;
    				}
    				for(int i=0;i<=matrixA.length-1;i++){
    					double sum3=0;
    					for(int j=0;j<=matrixA.length-1;j++){
    						sum3=sum3+matrixA[i][j]*u[j];
    					}
    					q[i]=sum3/h;
    				}
    				double sum4=0;
    				for(int i=0;i<=matrixA.length-1;i++){
    					sum4=sum4+p[i]*u[i];
    				}
    				t=sum4/h;
    				for(int i=0;i<=matrixA.length-1;i++){
    					w[i]=q[i]-t*u[i];
    				}
    				for(int i=0;i<=matrixA.length-1;i++){
    					for(int j=0;j<=matrixA.length-1;j++){
    						matrixA[i][j]=matrixA[i][j]-w[i]*u[j]-u[i]*p[j];
    					}
    				}
    			}
		}
		return matrixA;
	}
	static void QR(double matrixA0[][]){//QR分解子程序
		DecimalFormat myformat = new DecimalFormat();
    	myformat.applyPattern("0.00000000000E00");
		double matrixQ[][]=new double[matrixA0.length][matrixA0.length];
		for(int i=0;i<=matrixA0.length-1;i++){
			for(int j=0;j<=matrixA0.length-1;j++){
				if(i==j){
					matrixQ[i][j]=1;
				}
				else
					matrixQ[i][j]=0;
			}
		}
		double matrixA1[][]=new double[matrixA0.length][matrixA0.length];
		for(int r=0;r<=matrixA0.length-2;r++){
			//判断矩阵A主对角线下元素是否全为0
			int allzero=0;
			for(int i=r+1;i<=matrixA0.length-1;i++){
				if(matrixA0[i][r]!=0){
					allzero=1;
					break;
				}
			}
			if(allzero==0) break;
			else{
				//计算dr,cr,hr	
				double sum1=0;
				for(int i=r;i<=matrixA0.length-1;i++){
					sum1=sum1+matrixA0[i][r]*matrixA0[i][r];
				}
				double dr=Math.sqrt(sum1);
				double cr=0;
				if(matrixA0[r][r]==0){
					cr=dr;
				}
				else{
					cr=-Math.signum(matrixA0[r][r])*dr;
				}	
				double hr=cr*cr-cr*matrixA0[r][r];
				double vectorU[]=new double[matrixA0.length];
				for(int i=0;i<r;i++){
					vectorU[i]=0;
				}
				vectorU[r]=matrixA0[r][r]-cr;
				for(int i=r+1;i<=matrixA0.length-1;i++){
					vectorU[i]=matrixA0[i][r];
				}//evaluate vectorU
				//计算Q与R(An)
				double vectorW[]=new double[matrixA0.length];
				for(int i=0;i<=matrixA0.length-1;i++){
					double sum2=0;
					for(int j=0;j<=matrixA0.length-1;j++){
						sum2=sum2+matrixQ[i][j]*vectorU[j];
					}
					vectorW[i]=sum2;
				}
				for(int i=0;i<=matrixA0.length-1;i++){
					for(int j=0;j<=matrixA0.length-1;j++){
						matrixQ[i][j]=matrixQ[i][j]-vectorW[i]*vectorU[j]/hr;
					}
				}
				double vectorP[]=new double[matrixA0.length];
				for(int i=0;i<=matrixA0.length-1;i++){
					double sum3=0;
					for(int j=0;j<=matrixA0.length-1;j++){
						sum3=sum3+matrixA0[j][i]*vectorU[j];
					}
					vectorP[i]=sum3/hr;
				}
				for(int i=0;i<=matrixA0.length-1;i++){
					for(int j=0;j<=matrixA0.length-1;j++){
						matrixA0[i][j]=matrixA0[i][j]-vectorU[i]*vectorP[j];
					}
				}
			}
		}
		for(int i=0;i<=matrixA0.length-1;i++){
			for(int j=0;j<=matrixA0.length-1;j++){
				double sum4=0;
				for(int k=0;k<=matrixA0.length-1;k++){
					sum4=sum4+matrixA0[i][k]*matrixQ[k][j];
				}
				matrixA1[i][j]=sum4;
			}	
		}
		System.out.println("对拟上三角化以后的矩阵A进行QR分解后的矩阵Q为:");
		for(int i=0;i<=matrixA0.length-1;i++){
			for(int j=0;j<=matrixA0.length-1;j++){
				if(matrixQ[i][j]==0){
					System.out.print(matrixQ[i][j]+"	");
				}
				else{
					System.out.print(myformat.format(matrixQ[i][j])+"	");
				}
			}
			System.out.println("\n");
		}
		System.out.println("对拟上三角化以后的矩阵A进行QR分解后的矩阵R为:");
		double e=0.000000000001;
		for(int i=0;i<=matrixA0.length-1;i++){
			for(int j=0;j<=matrixA0.length-1;j++){
				if(Math.abs(matrixA0[i][j])<=e){
					matrixA0[i][j]=0;
				System.out.print(matrixA0[i][j]+"	");
				}
				else{
					System.out.print(myformat.format(matrixA0[i][j])+"	");
				}
				
			}
			System.out.println("\n");
		}
		System.out.println("QR分解后的RQ=:");
		for(int i=0;i<=matrixA0.length-1;i++){
			for(int j=0;j<=matrixA0.length-1;j++){
				if(Math.abs(matrixA1[i][j])<=e){
					matrixA1[i][j]=0;
					System.out.print(matrixA1[i][j]+"	");
				}
				else{
					System.out.print(myformat.format(matrixA1[i][j])+"	");
				}
			}
			System.out.println("\n");
		}
	}

	static double[][] method(double matrixA[][],int m){
//子程序:对matrixA进行双步位移QR分解,计算A=Q'AQ
		double s=matrixA[m-1][m-1]+matrixA[m][m];
    	double t=matrixA[m-1][m-1]*matrixA[m][m]-matrixA[m][m-1]*matrixA[m-1][m];
    	double matrixM[][]=new double[m+1][m+1];
    	double squareA[][]=new double[m+1][m+1];
    	for(int i=0;i<=m;i++){			
    		for(int j=0;j<=m;j++){
    			double sum5=0;
				for(int t1=0;t1<=m;t1++){
    				sum5=sum5+matrixA[i][t1]*matrixA[t1][j];
    			}
    			squareA[i][j]=sum5;
    		}
    	}//A的平方
    							
    	for(int i=0;i<=m;i++){
    		for(int j=0;j<=m;j++){
    			if(i==j){
    				matrixM[i][j]=squareA[i][j]-s*matrixA[i][j]+t;
    			}
    			else{
    				matrixM[i][j]=squareA[i][j]-s*matrixA[i][j];	
    			}
    		}
    	}//M
    							
    	label2://对M进行双步QR分解,并求下一次迭代所需要的A
    	for(int r=0;r<=m-1;r++){
    		int allzero1=0;
    		label3:
    		for(int i=r+1;i<=m;i++){
    			if(matrixM[i][r]!=0){
    				allzero1=1;
    				break label3;
    			}
    		}
    		if(allzero1==0) continue label2;
    		else{
    			double dr=0,cr=0;
    			double sum6=0;
    			for(int i=r;i<=m;i++){
    			sum6=sum6+matrixM[i][r]*matrixM[i][r];
    			}
    			dr=Math.sqrt(sum6);
    			if(matrixM[r][r]==0){
    				cr=dr;
    			}
    			else{
    			    	cr=-Math.signum(matrixM[r][r])*dr;
    			}			
    			double hr=cr*cr-cr*matrixM[r][r];
    			double vectorU[]=new double[m+1];
    			for(int i=0;i<=r-1;i++){
    				vectorU[i]=0;
    			}
    			vectorU[r]=matrixM[r][r]-cr;
    			for(int i=r+1;i<=m;i++){
    				vectorU[i]=matrixM[i][r];
    			}//vectorU赋值
    			double vectorV[]=new double[m+1];
    			for(int j=0;j<=m;j++){
    				double sum7=0;
    				for(int i=0;i<=m;i++){
    					sum7=sum7+matrixM[i][j]*vectorU[i];
    				}
    				vectorV[j]=sum7/hr;
    			}//vectorV				
    			for(int i=0;i<=m;i++){
    				for(int j=0;j<=m;j++){
    					matrixM[i][j]=matrixM[i][j]-vectorU[i]*vectorV[j];
    				}
    			}//matrixM
    			double vectorP[]=new double[m+1];
    			for(int i=0;i<=m;i++){
    				double sum8=0;
    				for(int j=0;j<=m;j++){
    					sum8=sum8+matrixA[j][i]*vectorU[j];
    				}
    				vectorP[i]=sum8/hr;
    			}//Pr
    			double vectorQ[]=new double[m+1];
    			for(int i=0;i<=m;i++){
    				double sum8=0;
    				for(int j=0;j<=m;j++){
    					sum8=sum8+matrixA[i][j]*vectorU[j];
    				}
    				vectorQ[i]=sum8/hr;
    			}//Qr
    			double tr=0;
    			double sum9=0;
    			for(int i=0;i<=m;i++){
    				sum9=sum9+vectorP[i]*vectorU[i];
    			}
    			tr=sum9/hr;//tr
    			double vectorW[]=new double[m+1];
    			for(int i=0;i<=m;i++){
    				vectorW[i]=vectorQ[i]-tr*vectorU[i];
    			}//Wr
    			for(int i=0;i<=m;i++){
    				for(int j=0;j<=m;j++){
    			matrixA[i][j]=matrixA[i][j]-vectorW[i]*vectorU[j]-vectorU[i]*vectorP[j];
    				}
    			}//下一次的matrixA
    		}
    	}//Mk的QR分解,得出下一次的A
	return matrixA;
	}
}

public class work {// 主程序
    public static void main(String[] args) {
    	DecimalFormat myformat = new DecimalFormat();
    	myformat.applyPattern("0.00000000000E00");
    	/*给定矩阵A,赋值,然后转化为拟上三角矩阵
    	 *Give  matrixA,  evaluate matrixA, then convert in to up the triangle matrix
    	 **/
    	int dimensionA=10;
    	double e=0.000000000001;
    	double matrixA[][]=new double[dimensionA][dimensionA];
    	for(int i=0;i<=dimensionA-1;i++){
    		for(int j=0;j<=dimensionA-1;j++){
    			if(i!=j) matrixA[i][j]=Math.sin(0.5*(i+1)+0.2*(j+1));
    			else{
    				matrixA[i][j]=1.5*Math.cos(i+1+1.2*(j+1));
    			}
    		}
    	}//evaluate matirxA
 		matrixA=date.upTriangle(matrixA);//调用方法,完成矩阵A的拟上三角化
    	System.out.println("将 A拟上三角化后的矩阵为:");
    	for(int i=0;i<=dimensionA-1;i++){
    		for(int j=0;j<=dimensionA-1;j++){
    			if(Math.abs(matrixA[i][j])<=e){
    				matrixA[i][j]=0;
    				System.out.print(matrixA[i][j]+"	");
    			}
    			else{
    				System.out.print(myformat.format(matrixA[i][j])+"     ");
    			}
    		}
    		System.out.println("\n");
    	}//println 拟上三角化后的 矩阵A
    	double matrixA0[][]=new double[dimensionA][dimensionA];
    	for(int i=0;i<=dimensionA-1;i++){
    		for(int j=0;j<=dimensionA-1;j++){
    			matrixA0[i][j]=matrixA[i][j];
    		}
    	}
    	date.QR(matrixA0);//调用QR子程序,观察A的拟上三角化后的矩阵进行QR分解的结果
    	
    	/*求矩阵A的所有特征值*/
    	
    	int L=2000;
    	int k=1,m=dimensionA-1;
    	double eigenvalueA[][]=new double[dimensionA][2];
    	double s1[]={0,0},s2[]={0,0};
    	label1:
			while(k<=L){
    			if(Math.abs(matrixA[m][m-1])<=e){
    				eigenvalueA[m][0]=matrixA[m][m];
    				m=m-1;
    				switch(m){
    					case(0):eigenvalueA[m][0]=matrixA[m][m];break label1;
    					case(-1):break label1;
    					default:continue label1;
    				}
    			}
    			else{
    				double detD=matrixA[m-1][m-1]*matrixA[m][m]-matrixA[m-1][m]*matrixA[m][m-1];
					double sum=(matrixA[m-1][m-1]+matrixA[m][m])*(matrixA[m-1][m-1]+matrixA[m][m])-4*detD;
    				s1[1]=0;s1[0]=0;
    				s2[1]=0;s2[0]=0;
    				if(sum>=0){
    					s1[0]=(matrixA[m-1][m-1]+matrixA[m][m]+Math.sqrt(sum))/2;
    					s2[0]=(matrixA[m-1][m-1]+matrixA[m][m]-Math.sqrt(sum))/2;
    				}
    				else{
    					s1[0]=(matrixA[m-1][m-1]+matrixA[m][m])/2;
    					s1[1]=Math.sqrt(Math.abs(sum))/2;
    					s2[0]=(matrixA[m-1][m-1]+matrixA[m][m])/2;
    					s2[1]=-Math.sqrt(Math.abs(sum))/2;
    				}
    				if(m==1){
    					eigenvalueA[m][0]=s1[0];
    					eigenvalueA[m][1]=s1[1];
    					eigenvalueA[m-1][0]=s2[0];
    					eigenvalueA[m-1][1]=s2[1];
    					break label1;
    				}
    				else{
    					if(Math.abs(matrixA[m-1][m-2])<=e){
    					eigenvalueA[m][0]=s1[0];
    					eigenvalueA[m][1]=s1[1];
    					eigenvalueA[m-1][0]=s2[0];
    					eigenvalueA[m-1][1]=s2[1];
    					m=m-2;
    					switch(m){
    					case(0):eigenvalueA[m][0]=matrixA[m][m];break label1;
    					case(-1):break label1;
    					default:continue label1;
    					}
    					}
    					else{
    						if(k==L){
    							System.out.println("未得到A的全部特征值,计算终止");
    							break label1;
    						}
    						else{
    							matrixA=date.method(matrixA,m);//调用方法,求QR分解后的矩阵A
    							k=k+1;
    							continue label1;
    							
    						}//(9)
    					}//判断 k==L
    				}//(7)	
    			}//(5) 计算s1,s2
			}//while
    		
		for(int i=0;i<=dimensionA-1;i++){
			System.out.println("矩阵A的第"+(i+1)+"个特征值为:"+myformat.format(eigenvalueA[i][0])+"+i"+myformat.format(eigenvalueA[i][1]));
		}//println eigenvalue

		/*找出 实特征值,然后 求其对应的特征向量 ,运用 Gauss法
		* 首先应 还原 matrixA,matrixA-eigenvalueA*I=0的解即为 对应 eigenvalueA的特征向量
		**/
		double eigenvectorA[]=new double[dimensionA];
		for(int n=0;n<=dimensionA-1;n++){
			if(eigenvalueA[n][1]!=0) continue;
				else{
				for(int i=0;i<=dimensionA-1;i++){
					for(int j=0;j<=dimensionA-1;j++){
						if(i!=j) matrixA[i][j]=Math.sin(0.5*(i+1)+0.2*(j+1));
						else{
							matrixA[i][j]=1.5*Math.cos(i+1+1.2*(j+1));
						}
					}
				}//revert matrixA
				for(int i=0;i<=dimensionA-1;i++){
					matrixA[i][i]=matrixA[i][i]-eigenvalueA[n][0];
				}//matrixA-eigenvalue*I
				double b[]={0,0,0,0,0,0,0,0,0,0};//置线性方程组的右端结果为0向量
				double mid[][]=new double[dimensionA][dimensionA];
				for(int k1=0;k1<=dimensionA-2;k1++){
					if(matrixA[k1][k1]==0) break;
					else{
						for(int i=k1+1;i<=dimensionA-1;i++){
							mid[i][k1]=matrixA[i][k1]/matrixA[k1][k1];
							b[i]=b[i]-mid[i][k1]*b[k1];
							for(int j=k1+1;j<=dimensionA-1;j++){
    							matrixA[i][j]=matrixA[i][j]-mid[i][k1]*matrixA[k1][j];
    						}
    					}
    				}
    			}//矩阵消元化为上三角阵
    			eigenvectorA[dimensionA-1]=1;
    			for(int k1=dimensionA-2;k1>=0;k1--){
    				double h=0;
    				for(int j=k1+1;j<=dimensionA-1;j++){
    					h=h+matrixA[k1][j]*eigenvectorA[j];
    				}
    				eigenvectorA[k1]=(b[k1]-h)/matrixA[k1][k1];
    			}//计算各个eigenvectorA[i]的值
    			System.out.println("矩阵A相对应于第"+(n+1)+"个特征值"+ myformat.format(eigenvalueA[n][0])+"的特征向量为:");
    			for(int i=0;i<=dimensionA-1;i++){
    				System.out.println(myformat.format(eigenvectorA[i]));
    			}
    		}
    	}		
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -