矩阵分解算法

1 LU分解

三角分解常用于数值分析中,是高斯消元法的一种表达形式,可以方便的求解线性方程组,求逆矩阵,计算行列式的值。

矩阵的三角分解体现了高斯消元的一个过程,将实矩阵拓展成A:E的形式,可以很方便的求解矩阵的逆,而如果我们将A变成一个下三角矩阵事,在A的所有顺序主子式不为0的情况下总是有E变为一上三角矩阵。不妨认为下三角矩阵与上三角矩阵分别为L,U,则有A=LU。可以认为U为A到L的线性变换的矩阵。

高斯消元法中,我们将右侧向量b与A写在一起作为一个增广矩阵进行同步的操作,这就默认了对A与b的操作数是相等的且每换一个b就要重复一遍对A的操作。然而,当其右侧向量b发生变化时,需要重新进行消元,而分解后的矩阵进行回代操作的过程会明显快于重新消元。所以对A进行一次完整的消元操作后再将b回代。而所谓的完整消元就是将A进行线性变换成一个三角矩阵的过程(这里不妨认为是下三角矩阵),而其变换所对应的矩阵又是可求的,这就为求解方程组提供了便利。

U分解的步骤如下:

1.求U留E:沿用高斯消元法,将A化为U,不同的是,变换过程中左边乘上的每一个E都要记录下来;

2.逆E为L:将用到的E各自求逆(取含变换操作的元素的相反数)再逆序相乘(将消元乘数按照原来的位置写到一起,再补齐左上-右下对角线上的1和对角线上方的0),乘积即为L:

E求逆的简便方法和乘积求逆的运算法则在#3中已经提到。

逆序相乘等价于归置消元乘数于下三角矩阵中是一个常用结论,记忆使用可以简化运算。

乘积为L的依据是:假设E为所有E的乘积,EA=U可变形为E(-1)EA=E(-1)U=IA=A=LU,其中L=E(-1)。

利用A的LU分解解线性方程组的过程为将Ax=b等价变形成(LU)x=b,根据结合律有L(Ux)=b,再解Ly=b中的y,最后解Ux=y得到线性方程组的解。

提供一种快速LU分解矩阵的方法,如下图。

基于这种求解方法,大佬(Doolittle)发明了一种算法进行分解。

#include<algorithm>
#include<iostream>
using namespace std;
/*这里以20*20矩阵为例*/
const int Size = 20;
double a[Size][Size];//A
double l[Size][Size];//L
double u[Size][Size];//U
double sumLrkUki(int r, int i) {
	double re = 0.0;
	for (int k = 0; k < r; k++) {
		re += l[r][k] * u[k][i];
	}
	return re;
}
double sumLikUkr(int r, int i) {
	double re = 0.0;
	for (int k = 0; k < r; k++) {
		re += l[i][k] * u[k][r];
	}
	return re;
}
void countLU() {
	for (int i = 0; i < Size; i++) {
		u[0][i] = a[0][i];
		l[i][0] = a[i][0] / u[0][0];
	}
	for (int r = 1; r < Size; r++) {
		for (int i = r; i < Size; i++) {
			u[r][i] = a[r][i] - sumLrkUki(r, i);
			if (i == r) l[r][r] = 1;
			else if
				(r == Size) l[Size][Size] = 1;
			else
				l[i][r] = (a[i][r] - sumLikUkr(r, i)) / u[r][r];
		}
	}
}
void setData() {
	for (int i = 0; i < Size; i++) {
		for (int j = 0; j < Size; j++) {
			cin >> a[i][j];
		}
	}
}


猜你喜欢

转载自blog.csdn.net/qq_41104612/article/details/80698118
今日推荐