算法课外思考题十


问题一

问题描述

调研学习并给出矩阵的LU分解方法

矩阵的LU分解方法

Doolittle分解

概念

数值分析中得到:

A为$n*n$阶矩阵,如果A的顺序主子式$A_i$满足$det(A_i)\neq 0(i=1,2,…,n-1)$,则A可分解为一个单位下三角矩阵L与一个上三角矩阵U的乘积,即A=LU,且分解是唯一的


$$
\left(\begin{array}{cccc}
a_{11} & a_{12} & \cdots & a_{1 n} \
a_{21} & a_{22} & \cdots & a_{2 n} \
\vdots & \vdots & \ddots & \vdots \
a_{n 1} & a_{n 2} & \cdots & a_{n n}
\end{array}\right)=\left(\begin{array}{cccc}
1 & & & \
l_{21} & 1 & & \
\vdots & \vdots & \ddots & \
l_{n 1} & l_{n 2} & \cdots & 1
\end{array}\right)\left(\begin{array}{cccc}
u_{11} & u_{12} & \cdots & u_{1 n} \
& u_{22} & \cdots & u_{2 n} \
& & \ddots & \vdots \
& & & u_{n n}
\end{array}\right)
$$
由矩阵乘法可以得到u、l关系:
$$
\left{\begin{array}{l}
\boldsymbol{u}{i j}=\boldsymbol{a}{i j}-\sum_{k=1}^{i-1} \boldsymbol{l}{i k} \boldsymbol{u}{k j} \quad j=\boldsymbol{i}: \boldsymbol{n} \
\boldsymbol{l}{i j}=\left(\boldsymbol{a}{i j}-\sum_{k=1}^{j-1} \boldsymbol{l}{i k} \boldsymbol{u}{k j}\right) / \boldsymbol{u}{j j} \quad \boldsymbol{i}=\boldsymbol{j}+\mathbf{1}: \boldsymbol{n}
\end{array}\right.
$$
在计算机运算程序中,可以将两个三角矩阵按照紧凑格式存放在同一个矩阵中,节省存储空间(注意:主对角线上存储的是U矩阵上主对角线的元素,而L矩阵主对角线元素都为1,只要在运算中体现即可):
$$
\left(\begin{array}{cccc}
\boldsymbol{u}
{11} & \boldsymbol{u}{12} & \ldots & \boldsymbol{u}{1 n} \
\boldsymbol{l}{21} & \boldsymbol{u}{22} & \cdots & \boldsymbol{u}{2 n} \
\vdots & \vdots & \ddots & \vdots \
\boldsymbol{l}
{n 1} & \boldsymbol{l}{n 2} & \cdots & \boldsymbol{u}{n n}
\end{array}\right)
$$

Doolittle分解算法实现
void Doolittle(double** a,int n,double** res){
    for (int k = 1; k < n + 1; k++)
	{
		for (int j = k, i = k + 1; j < n + 1, i < n + 1; j++, i++)
		{
			double sum_1 = 0;
			for (int t = 1; t < k; t++)
			{
				sum_1 += res[k - 1][t - 1] * res[t - 1][j - 1];
			}
			res[k - 1][j - 1] = a[k - 1][j - 1] - sum_1;
			double sum_2 = 0;
			for (int t = 1; t < k; t++)
			{
				sum_2 += res[i - 1][t - 1] * res[t - 1][k - 1];
			}
			res[i - 1][k - 1] = (a[i - 1][k - 1] - sum_2) / res[k - 1][k - 1];
		}
		double sum_1 = 0;
		for (int t = 1; t < k; t++)
		{
			sum_1 += res[k - 1][t - 1] * res[t - 1][n - 1];
		}
		res[k - 1][n - 1] = a[k - 1][n - 1] - sum_1;
	}
}

Crout分解

概念

与Doolittle分解类似的,将单位下三角矩阵L与一个上三角矩阵U的乘积替换成下三角矩阵L与一个单位上三角矩阵U的乘积,其实质上,是将U进一步分解为:

image-20230422212257389

也被称为$LDL^T$分解

Crout分解算法实现
void Cout(double** a,int n,double** res){
    for(int k=0;k<n;k++)
      {
        //同时计算L的第1到K列元素
          for(int i=k;i<n;i++)
          {
             res[i][k]=a[i][k];
             for(int j=0;j<=k-1;j++)
             res[i][k]-=(res[i][j]*res[j][k]);
          }
          //同时计算U的第1到K行元素
            for(int j=k+1;j<n;j++)
          {
              res[k][j]=a[k][j];
              for(int i=0;i<=k-1;i++)
              res[k][j]-=(res[k][i]*res[i][j]);
              res[k][j]/=res[k][k];
          }
      }
}

问题二

问题描述

给出方案计算可逆矩阵的逆

问题解决

方法一:Gauss-Jordan消元法

构造一个n*2n的增广矩阵$(A,I_n)$

然后使用高斯消元法,将增广矩阵的左半部分化为单位矩阵,得到的增广矩阵右半部分即为$(I_n,A^{-1})$

高斯消元法:

  • 对于一个矩阵A,我们从第1行到第n行不断选取第i列不为0的行,然后做一个行变换(交换两行,使得当前的第i行的第i列不为0)
  • 然后将当前的第i行做一个初等变换,也就是都除以$A[i][i]$这样的话就能让第i行第i列变为1
  • 将第i行下面的所有行的第i列全部消掉,此时就构成了一个上三角矩阵
  • 此时已经构成了一个阶梯型矩阵,我们再从下往上不断将上半矩阵同理消掉即可

算法:

void gauss(){
	for(ll i = 1;i <= n; ++i) {//枚举当前处理到第几列
		for(ll j = i;j <= n; ++j) {//找到一个第i列不为空的行
			if(fabs(a[i][i]) > EPS) {
				for(ll k = i;k <= n; ++k) //交换i,j行
					swap(a[i][k],a[j][k]);
				break;
			}
		}
		if(fabs(a[i][i]) < EPS) {
			cout<<"不存在逆矩阵"<<endl;
			return ;
		}
		//这里就是将第i行下面所有行的第i列清空,变成一个阶梯型的矩阵
		double aii_inv = 1.0/a[i][i];
		//将第i行都乘上a[i][i]的逆
		a[i][i] = 1.0;
		for(ll j = i + 1;j <= n ; ++j) {
			a[i][j] = a[i][j] * aii_inv;
		}
		for(ll j = 1;j <= n; ++j) {
			b[i][j] = b[i][j] * aii_inv;
		}
		//将第i行下面的所有第i列的元素值清空
		for(ll j = i + 1;j <= n; ++j) {
			for(ll k = i + 1;k <= n; ++k) {
				a[j][k] = a[j][k] - a[i][k] * a[j][i];
			}
			for(ll k = 1;k <= n; ++k) {
				b[j][k] = b[j][k] - b[i][k] * a[j][i];
			}
			a[j][i] = 0.0;
		}
	}
}

演示:

image-20230422221117595

方法二:LU分解法

LU分解法是高斯消元法的一种变种算法,根据上述定义,将矩阵A分解成一个下三角矩阵与一个上三角矩阵:
$$
A=LU
\
A^{-1}=U^{-1}L^{-1}
$$

方法三:SVD分解法

奇异值分解,将矩阵A分解为三个矩阵的乘积分别为:正交矩阵U、对角矩阵W、另一正交矩阵V的转置**$V^T$**
$$
A=UWV^T
\
A^{-1}=VW^{-1}U^T
$$


文章作者: J&Ocean
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 J&Ocean !
评论
  目录