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

📄 szfx1.cpp

📁 求矩阵的最大特征值
💻 CPP
字号:
// SZFX1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <memory.h>
#include <stdio.h>
#include <afx.h>
#include <math.h>
#include <iostream.h>

//对三角矩阵下半宽带
const int g_nrLow = 3;
//对三角矩阵上半宽带
const int g_nsUpp = 3;
//对三角矩阵维数
const int g_nMatrixDimension = 1000;
//对三角矩阵压缩矩阵
double g_cMatrix[7][1000];
//double size
const int g_ndoublesize = sizeof(double);
//记录当前矩阵参数K值
int g_nkVar = 0;
//存储条件数数组
double g_vCondition[81];
//存储模最大特征值数组
double g_vMaxFeature[81];
//存储模最小特征值数组
double g_vMinFeature[81];
//存储最大特征值数组
double g_vMaxFeat[81];

//初始化对三角矩阵的压缩矩阵
void InitMatrix(int tk);
//用幂法求条件数
double ComputeCondition();
//用第一种迭代格式的幂法求模最大的特征值
double ComputeMaxFeature1();
//用第二种迭代格式的幂法求模最大的特征值
double ComputeMaxFeature2();
//用反幂法求模最小的特征值
double ComputeMinFeatrue();
//求向量的2-范数
double ComputeTFanShu(double *p);
//求向量的无穷范数
double ComputeNFanShu(double *p, int *r);
//A--对三角矩阵 r--下半带宽 s--上半带宽
//幂法迭代公式 u = Ay,计算u的第i个分量
double ComputeVector(int i, double *pyVector);
//用doolittle分解法求解对三角矩阵: Au = y中的u向量, 参考Page40
bool ComputeUVectorUseDoolittle(double *pyVector, double *puVector);
//用带平移的反幂法计算最大特征值
double ComputeMax(double dbuOffside);
//初始化带平移反幂法矩阵的压缩矩阵
void InitMatrixEx(int tk, double dbuOffside);

int main(int argc, char* argv[])
{
	try
	{
		//初始化
		memset((void *)g_vCondition, 0, 81*g_ndoublesize);  
		memset((void *)g_vMaxFeature, 0, 81*g_ndoublesize);  
		memset((void *)g_vMinFeature, 0, 81*g_ndoublesize);  
		memset((void *)g_vMaxFeat, 0, 81*g_ndoublesize);  
		for(int i=0; i<=80; i++)
		{
			g_nkVar = i;
			//初始化三角矩阵的压缩矩阵
			InitMatrix(i);
			//计算条件式中 k = i 时的条件数
			g_vCondition[i] = ComputeCondition();
			//求最大特征值
			g_vMaxFeat[i] = ComputeMax(fabs(g_vMaxFeature[i]));
			printf(" k = %d : \n", g_nkVar);
			printf("     |Min|=%.6e  |Max|=%.6e  Cond(A)=%.6e  Max=%.6e\n\n", g_vMinFeature[g_nkVar], g_vMaxFeature[g_nkVar],
				g_vCondition[g_nkVar], g_vMaxFeat[i]);

		}
		double dbMin = 0, dbMax = 0, dbMaxFeat = 0;
		int nMin = 0, nMax = 0, nMaxFeat = 0;
		dbMin = dbMax = g_vCondition[0];
		dbMaxFeat = g_vMaxFeat[0];
		//获取最大和最小条件数以及相应输入值
		for(i=1; i<=80; i++)
		{
			if (g_vCondition[i]>dbMax)
			{
				dbMax = g_vCondition[i];
				nMax = i;
			}
			if (g_vCondition[i]<dbMin)
			{
				dbMin = g_vCondition[i];
				nMin = i;
			}
			if (g_vMaxFeat[i]>dbMaxFeat)
			{
				dbMaxFeat = g_vMaxFeat[i];
				nMaxFeat = i;
			}
		}
		//输出计算结果
		printf("Max(k)=%d  Max[Cond(A)]=%.6e\n", nMax, dbMax);
		printf("Min(k)=%d  Min[Cond(A)]=%.6e\n", nMin, dbMin);
		printf("Max(k)=%d  Max[Feat(A)]=%.6e\n", nMaxFeat, dbMaxFeat);
	}
	catch(...)
	{
	}
	return 0;
}
	
//初始化对三角矩阵的压缩矩阵
void InitMatrix(int tk)
{
	//矩阵初始化
	int r = 3,  s = 3;
	int n = 1000;
	memset(g_cMatrix, 0, (r+s+1)*n*g_ndoublesize);
	for(int ic=1; ic<=7; ic++)
	{
		for(int jc=1; jc<=1000; jc++)
		{
			int ja = jc;
			int ia = ic + jc - g_nsUpp - 1;
			if (((max(ja-3,1)<=ia && ia<ja) || (ja<ia && ia<=min(ja+3,1000))) && (ia>0 && ja>0))
			{
				g_cMatrix[ic-1][jc-1] = -1 * (ia + ja) / (1 + tk*0.05);
			}
			else if(ia == ja)
				g_cMatrix[ic-1][jc-1] = 100 * (ia + 0.1) / (ia + tk*0.05);
		}
	}
	//对三角矩阵A = LU分解的第一步,参看P40
	for(int k=1; k<=n; k++)
	{
		int jMax = min(k+s, n);
		double dbTemp = 0;
		for(int j=k; j<=jMax; j++)
		{
			int tMin = max(1, k-r);
			tMin = max(tMin, j-s);
			dbTemp = 0;
			for(int t=tMin; t<=k-1; t++)
				dbTemp += (g_cMatrix[k-t+s][t-1] * g_cMatrix[t-j+s][j-1]);
			g_cMatrix[k-j+s][j-1] -= dbTemp;
		}
		int iMax = min(k+r, n);
		for(int i=k+1; i<=iMax; i++)
		{
			int tMin = max(1, i-r);
			tMin = max(tMin, k-s);
			dbTemp = 0;
			for(int t=tMin; t<=k-1; t++)
				dbTemp += (g_cMatrix[i-t+s][t-1] * g_cMatrix[t-k+s][k-1]);
			dbTemp = g_cMatrix[i-k+s][k-1] - dbTemp;
			g_cMatrix[i-k+s][k-1] = dbTemp / g_cMatrix[s][k-1];
		}
	}
}

//求条件数
double ComputeCondition()
{
	//to compute max feature
	g_vMaxFeature[g_nkVar] = ComputeMaxFeature1();
	//to compute min feature
	g_vMinFeature[g_nkVar] = ComputeMinFeatrue();
	//to compute cond(A)
	return fabs(g_vMaxFeature[g_nkVar]/g_vMinFeature[g_nkVar]);
}

//用第一种迭代格式的幂法求模最大的特征值
double ComputeMaxFeature1()
{
	//to define two vectors : u, y
	double uVector[1000], yVector[1000];
	//to define one doulbe variant : beta;
	double dbPrevBeta = 0, dbBeta = 0;
	//to initialize uVector and yVector
	memset(uVector, 0, g_ndoublesize * 1000);
	memset(yVector, 0, g_ndoublesize * 1000);
	for(int j=0; j<1000; j++)
		uVector[j] = 1.00;
	bool bEnd = true;        //不懂bool
	double dbTemp = 0;
	do
	{
		double dbFanShu = ComputeTFanShu(uVector);
		for(int i=0; i<1000; i++)
			yVector[i] = uVector[i]/dbFanShu;
		for(i=1; i<=1000; i++)
			uVector[i-1] = ComputeVector(i, yVector);              //不懂i-1
		dbBeta = 0;  //初始化
		for(i=0; i<1000; i++)
			dbBeta += (yVector[i] * uVector[i]);
		bEnd = (fabs((dbBeta - dbPrevBeta) / dbBeta) <= 1e-7);
		dbPrevBeta = dbBeta;
	}while( !bEnd );         
	return dbBeta;
}

//用第二种迭代格式的幂法求模最大的特征值
double ComputeMaxFeature2()
{
	//to define two vectors : u, y
	double uVector[1000], yVector[1000];
	//to define one doulbe variant : beta;
	double dbPrevBeta = 0, dbBeta = 0;
	//to init uVector and yVector
	memset(uVector, 0, g_ndoublesize * 1000);
	memset(yVector, 0, g_ndoublesize * 1000);
	for(int j=0; j<1000; j++)
		uVector[j] = 1;
	bool bEnd = true;
	double dbTemp = 0;
	do
	{
		int r;
		double dbFanShu = ComputeNFanShu(uVector, &r);
		for(int i=0; i<1000; i++)
			yVector[i] = uVector[i]/dbFanShu;
		for(i=1; i<=1000; i++)
			uVector[i-1] = ComputeVector(i, yVector);
		double dbBeta = yVector[r] * uVector[r];
		bEnd = (fabs((dbBeta - dbPrevBeta) / dbBeta) <= 1e-7);
		dbPrevBeta = dbBeta;
	}while( !bEnd );
	return dbBeta;
}

//用反幂法求最小特征值
double ComputeMinFeatrue()
{
	//to define two vectors : u, y
	double uVector[1000], yVector[1000];
	//to define one doulbe variant : beta;
	double dbPrevBeta = 0, dbBeta = 0;
	//to init uVector and yVector
	memset(uVector, 0, g_ndoublesize * 1000);
	memset(yVector, 0, g_ndoublesize * 1000);
	for(int i=0; i<1000; i++)
		uVector[i] = 1.00;
	bool bEnd = true;                    //不懂1
	do
	{
		double dbFanShu = ComputeTFanShu(uVector);
		for(i=0; i<1000; i++)
			yVector[i] = uVector[i]/dbFanShu;
		//to compute Au = y : using doolittle method
		ComputeUVectorUseDoolittle(yVector, uVector);	
		dbBeta = 0;
		for(i=0; i<1000; i++)
			dbBeta += (yVector[i] * uVector[i]);
		double dbTemp = fabs((dbBeta - dbPrevBeta) / dbBeta );
		bEnd = fabs((dbBeta - dbPrevBeta) / dbBeta) <= 1e-7;
		dbPrevBeta = dbBeta;
	}while( !bEnd );
	dbBeta = 1 / dbBeta;
	return dbBeta;
}

//求向量的2-范数
double ComputeTFanShu(double *p)          //不懂2
{
	double dbTemp = 0;
	ASSERT(p!=NULL);                 //不懂3
	for(int i=0; i<1000; i++)
		dbTemp += (p[i]*p[i]);
	dbTemp = sqrt(dbTemp);
	return dbTemp;
}

//求向量的无穷范数
double ComputeNFanShu(double *p, int *r)
{
	ASSERT(p!=NULL);
	double dbRes = 0;
	for(int i=0; i<1000; i++)
	{
		if ((fabs(dbRes) - fabs(p[i])) < 0)
		{
			dbRes = fabs(p[i]);
			*r = i;
		}
	}
	return dbRes;
}

//A--对三角矩阵 r--下半带宽 s--上半带宽
//幂法迭代公式 u = Ay,计算u的第i个分量
double ComputeVector(int i, double *pyVector)
{
	ASSERT(i > 0);             //不懂assert
	double dbRes = 0;
	double dbTemp = 0;
	int jMin = 0, jMax = 0;
	if (i>=1 && i<=g_nrLow+1)
	{
		jMin = 1;
		jMax = g_nsUpp + i; 
	}
	else
	{
		jMin = min(i - 3, 1000);
		jMax = min(jMin + 6, 1000);
	}
	for(int j=jMin; j<=jMax; j++)
	{
		if (i==j)
			dbTemp = 100 * (i + 0.1) / (i + g_nkVar*0.05);
		else
			dbTemp = -1 * (i + j) / (1 + g_nkVar*0.05);
		dbRes += (dbTemp * pyVector[j-1]);
	}
	return dbRes;
}

//用doolittle分解法求解对三角矩阵: Au = y中的u向量, 参考Page40
bool ComputeUVectorUseDoolittle(double *pyVector, double *puVector)
{
	ASSERT(pyVector!=NULL && puVector!=NULL);
	int n = 1000, r = g_nrLow,  s = g_nsUpp;
	bool bRes = true;
	double dbTemp = 0;
	double yNewVector[1000];
	memcpy(yNewVector, pyVector, g_ndoublesize * n);
	for(int i=2; i<=n; i++)
	{
		dbTemp = 0;
		int tMin = max(1, i-r);
		for(int t=tMin; t<=i-1; t++)
			dbTemp += (g_cMatrix[i-t+s][t-1] * yNewVector[t-1]);
		yNewVector[i-1] -= dbTemp;
	}
	puVector[n-1] = yNewVector[n-1] / g_cMatrix[s+1-1][n-1];
	for(i=n-1; i>=1; i--)
	{
		dbTemp = 0;
		int tMax = min(i+s, n);
		for(int t=i+1; t<=tMax; t++)
			dbTemp += (g_cMatrix[i-t+s][t-1] * puVector[t-1]);
		dbTemp = yNewVector[i-1] - dbTemp;
		puVector[i-1] = dbTemp / g_cMatrix[s][i-1];
	}
	return bRes;
}

double ComputeMax(double dbuOffside)
{
	//to define two vectors : u, y
	double uVector[1000], yVector[1000];
	//to define one doulbe variant : beta;
	double dbPrevBeta = 0, dbBeta = 0;
	//初始化用带平移的反幂法求最大特征值的压缩矩阵
	InitMatrixEx(g_nkVar, fabs(g_vMaxFeature[g_nkVar]));
	//to init uVector and yVector
	memset(uVector, 0, g_ndoublesize * 1000);
	memset(yVector, 0, g_ndoublesize * 1000);
	for(int i=0; i<1000; i++)
		uVector[i] = 1.00;
	bool bEnd = true;
	do
	{
		double dbFanShu = ComputeTFanShu(uVector);
		for(i=0; i<1000; i++)
			yVector[i] = uVector[i]/dbFanShu;
		//to compute Au = y : using doolittle method
		ComputeUVectorUseDoolittle(yVector, uVector);	
		dbBeta = 0;
		for(i=0; i<1000; i++)
			dbBeta += (yVector[i] * uVector[i]);
		double dbTemp = fabs((dbBeta - dbPrevBeta) / dbBeta );
		bEnd = fabs((dbBeta - dbPrevBeta) / dbBeta) <= 1e-7;
		dbPrevBeta = dbBeta;
	}while( !bEnd );
	return 1/dbBeta + dbuOffside;
}

//初始化带平移反幂法矩阵的压缩矩阵,迭代公式中(A-uI)u = y,其中u=dbuOffside
void InitMatrixEx(int tk, double dbuOffside)
{
	//矩阵初始化
	int r = 3,  s = 3;
	int n = 1000;
	memset(g_cMatrix, 0, (r+s+1)*n*g_ndoublesize);
	for(int ic=1; ic<=7; ic++)
	{
		for(int jc=1; jc<=1000; jc++)
		{
			int ja = jc;
			int ia = ic + jc - g_nsUpp - 1;
			if (((max(ja-3,1)<=ia && ia<ja) || (ja<ia && ia<=min(ja+3,1000))) && (ia>0 && ja>0))
			{
				g_cMatrix[ic-1][jc-1] = -1 * (ia + ja) / (1 + tk*0.05);
			}
			else if(ia == ja)
				g_cMatrix[ic-1][jc-1] = 100 * (ia + 0.1) / (ia + tk*0.05) - dbuOffside;
		}
	}
	//对三角矩阵A = LU分解的第一步,参看P40
	for(int k=1; k<=n; k++)
	{
		int jMax = min(k+s, n);
		double dbTemp = 0;
		for(int j=k; j<=jMax; j++)
		{
			int tMin = max(1, k-r);
			tMin = max(tMin, j-s);
			dbTemp = 0;
			for(int t=tMin; t<=k-1; t++)
				dbTemp += (g_cMatrix[k-t+s][t-1] * g_cMatrix[t-j+s][j-1]);
			g_cMatrix[k-j+s][j-1] -= dbTemp;
		}
		int iMax = min(k+r, n);
		for(int i=k+1; i<=iMax; i++)
		{
			int tMin = max(1, i-r);
			tMin = max(tMin, k-s);
			dbTemp = 0;
			for(int t=tMin; t<=k-1; t++)
				dbTemp += (g_cMatrix[i-t+s][t-1] * g_cMatrix[t-k+s][k-1]);
			dbTemp = g_cMatrix[i-k+s][k-1] - dbTemp;
			g_cMatrix[i-k+s][k-1] = dbTemp / g_cMatrix[s][k-1];
		}
	}
}

⌨️ 快捷键说明

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