C++学习日记#2——幂法求矩阵的主特征值

{​{v_{1}}}\left | \lambda _{n} \right |幂法的主要作用是求矩阵的主特征值,这种方法特别适用于求大型稀疏矩阵。

定理:

设A∈\mathbb{R}^{n\times n}有n个线性无关的特征向量,主特征值\left | \lambda _{1} \right |满足\left | \lambda _{1} \right |>\left |\lambda _{2}\right |\geq\left |\lambda ^{_{3}} \right |\geq·····\geq\left | \lambda _{n} \right |,则对任意非零初始向量v_{0}= u_{0}(a_{1}\neq0),按照下述方法构造的向量序列{u_{k}},{v_{k}}:

 (P.S)过程迭代讲解:

第一步:定义一个初始规范化向量u_{0}

第二步:初始规范化向量u_{0}与矩阵A相乘得到一个结果矩阵v_{1}

第三步:取结果矩阵v_{1}的最大值,即(max{v_{1}})

第四步:将初始规范化向量除以矩阵v_{1}的最大值得到下一次迭代所需的规范化向量。

第五步:用新得到的规范化向量重复以上四个步骤。

迭代结果:

 注释:

当迭代次数k趋于无穷时, 结果矩阵v_{k}的最大值,即(max{v_{k}})为主特征值。

当迭代次数k趋于无穷时,规范化向量即为主特征值对应的特征向量(这个特征向量是除以了最大值后所得的)

程序主要思路:

主要分为三个模块:赋值、求解函数、输出;

在这里主要讲解求解函数和输出模块。

求解函数模块:

主要有四个循环语句,和两个调用函数组成。

1.执行第一个循环,主要计算两个矩阵某行列相乘

2.执行第二个循环,主要用于计算两矩阵相乘后得到的新矩阵

3.执行第三个循环,主要用于上一次迭代后得到的规范化向量与矩阵相乘

4.一个插入循环,该循环位于第二个循环与第三个循环之间,主要担任桥梁角色,将每次相乘得到的矩阵赋值给一个临时数组,该数组主要是用于取最大值函数。

调用函数:

一个取最大值函数,一个求规范化向量函数

这两个调用函数紧接着上述的插入循环,主要是由于插入循环提供了一个可以求该次两矩阵相乘后得到临时数组,该数组可以求出最大值,之后可以为求规范化向量提供最大值。该最大值将被一个以迭代次数为坐标的一个定义变量(M_v[k])储存起来,这样就可以构建出迭代次数与最大值一一对应的关系,便于后续的结果输出。

输出模块:

该模块最关键点是将迭代次数、规范化向量以及最大值统一起来。

在该模块中,我通过以迭代次数为坐标,建立每次迭代规范化向量和最大值的存储数组,这样的好处是在以迭代次数递增的循环语句中,每执行一次循环就可以输出该次的迭代次数、规范化向量和最大值。

(p.s)以上都是自己的个人理解,讲解的不是很专业。

附上实现程序

#include <iostream>
#include <iomanip>//用于cout保留小数

double a[100][100];//定义A矩阵
double u[100][100];//定义规范化向量U
double v[100][100];//定义Au的结果结果矩阵
double max_v;//定义Au的结果矩阵的最大值
double M_v[100]; //定义Au的结果矩阵的最大值,为了之后在循环外输出
double X_x[100];//定义赋值每次迭代Au结果矩阵
int In;//定义该次的迭代次数(p.s便于在求解循环调用函数中赋值下次迭代所需的规范化向量U)
int I[100];//定义现已迭代的次数(P.S便于后续的输出,使迭代次数与迭代结果一一对应
double max(double X_x[],int n);//定义取最大值函数
void dev_u(double X_x[], int n);//定义Au结果矩阵每个元素除以元素最大值的函数
using namespace std;

int main()
{
	int n;
	cout << "请输入A矩阵的阶数n" << endl;
	cin >> n;
	int N;
	cout << "请输入迭代次数N" << endl;
	cin >> N;
	cout << "************请输入A矩阵的各个元素************" << endl;
	cout << endl;
	for (int i = 1; i <= n; i++)
	{
		cout << "请输入第" << i << "行的元素" << endl;
		for (int j = 1; j <= n; j++)
		{
			cin >> a[i][j];
		}
	}
	cout << "请输初始规范化向量" << endl;
	for (int i = 1; i <= n; i++)
	{
		cin >> u[1][i];
	}//赋值模块
	for (int k = 1; k <= N; k++)//执行第三个循环,主要用于上一次迭代后得到的规范化向量与矩阵相乘
	{
		I[k] = k;
		In = k;
		for (int i = 1; i <= n; i++)//执行第二个循环,主要用于计算两矩阵相乘后得到的新矩阵
		{
			for (int j = 1; j <= n; j++)//执行第一个循环,主要计算两个矩阵某行列相乘
			{
				v[k][i] += a[i][j] * u[k][j];
			}
		}
		for (int p = 1; p <= n; p++)//该循环赋值主要担任桥梁角色,将每次相乘得到的矩阵赋值给临时数组,该数组主要是用于取最大值函数中;
		{
			X_x[p] = v[k][p];
		}//
		max(X_x, n);//调用取最大值函数
		dev_u(X_x, n);//调用求规范化向量函数
		M_v[k] = max_v;//将每次得出的最大值储存起来,便于后续的输出
	}//特征值函数求解模块
	cout << "****************输出计算结果****************" << endl;
	cout << endl;
	cout << setiosflags(ios::fixed) << setprecision(8);//输出结果保留8位小数
	cout << "迭代次数" << "   max{vk}  " << "      规范化向量uk^(T)   " << endl;
	for (int i = 1; i <= N; i++)
	{
		cout <<" 第" << I[i] <<"次" << "     " << M_v[i] << "     ";
		for (int p = 1; p <= n - 1; p++)
		{
			cout << u[i + 1][p] << " , ";
		}
		cout << u[i + 1][n] << endl;
	}//求解结果输出模块
	cout << endl;
	cout <<"输出最大迭代次数后得到的主特征值以及相应的特征向量" << endl;
	cout << "主特征值: " << M_v[N] << "  相应的特征向量: ";
	for (int p = 1; p <= n - 1; p++)
	{
		cout << u[N + 1][p] << " , ";
	}
	cout << u[N + 1][n] << endl;

	return 0;
}

double max(double X_x[], int n)
{
	max_v = X_x[1];

	for (int p = 2; p <= n; p++)
	{
		if (X_x[p] > max_v)
		{
			max_v = X_x[p];
		}
	}
	return max_v;
}

void dev_u(double X_x[], int n)
{
	for (int p = 1; p <= n; p++)
	{
		u[In+1][p]= X_x[p] / max_v;
	}
}

例题

用幂法求解A矩阵的主特征值以及相应的特征向量,该例题出现在数值分析第5版,由李庆杨等人编著:

 输出结果截图

后话

现在主要在阅读学习《C++ primer Plus》,这是我接触C++的第一本书。由于课程学习要接触《数值分析》这门课,就把书上的迭代方式给程序化,就可以把学到的知识很好的结合在一起。该程序是到目前为止使用过for循环最多的。但是当弄清楚了循环关系之间的先后关系之后,就会对其由清晰的认识吧,至少我是这样的。程序化之后,能带来简便就足够了。到目前为止所做的程序都没有考虑过资源占用问题以及优化问题,只是单纯的实现罢了,写的文章都是以我这接触程序语言不久的小白的角度叙述,专业性不是很高,不过对于小白来说还是挺友好的。

 

 

  • 5
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
颜庆津 幂法是一种求解矩阵最大特征值的迭代方法,它可以通过计算矩阵的特征向量来获取最大特征值。 在Fortran中,我们可以按照以下步骤来实现颜庆津 幂法求矩阵最大特征值: 1. 首先,定义一个n维矩阵A,并初始化特征向量x(长度为n)以及最大特征值的估计值λ。 2. 进行迭代计算,直到达到所需的精度或次数限制。在每次迭代中,进行以下操作: a. 将特征向量x乘以矩阵A,得到新的向量y。 b. 根据y的最大分量,更新最大特征值的估计值λ。 c. 将y的每个分量除以最大分量,以归一化y,得到新的特征向量x。 3. 返回最终的最大特征值λ作为结果。 Fortran代码示例: ``` program power_method implicit none integer, parameter :: n = 3 ! 矩阵维度 integer :: i, j, k real :: tolerance = 1e-6 ! 精度 integer :: max_iterations = 100 ! 最大迭代次数 real :: A(n,n), x(n), y(n), lambda, prev_lambda ! 初始化矩阵A和特征向量x A = reshape([2.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0], [n,n]) x = [1.0, 1.0, 1.0] ! 迭代计算 k = 0 do while (k < max_iterations) y = matmul(A, x) prev_lambda = lambda lambda = maxval(y) x = y / lambda ! 检查是否达到所需的精度 if (abs(lambda - prev_lambda) < tolerance) exit k = k + 1 end do ! 输出结果 write(*, '(A, F6.4)') "最大特征值为:", lambda end program power_method ``` 以上就是使用Fortran实现颜庆津 幂法求矩阵最大特征值的简单示例。在实际应用中,可能需要进一步处理特殊情况,比如矩阵A为奇异矩阵或无界矩阵时的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值