算法:矩阵 LUP 分解

本文着笔于矩阵 LUP 分解算法,以及利用矩阵的 LUP 分解来解线性方程组、求矩阵对应行列式的值、求逆矩阵。

对于矩阵的定义代码如下:

struct Matrix
{double dat[MAX_N][MAX_N],det,LUdat[MAX_N][MAX_N],rev[MAX_N][MAX_N];int dgr,pi[MAX_N];bool LUP_Decomposition();VectorColumn LUP_Solve(VectorColumn);void GetDeterminant();void GetReverse();
};

矩阵的 LUP 分解

矩阵 A 的 LUP 分解即为找到下三角矩阵 L、上三角矩阵 U、行置换矩阵 P 使得 PA = LU ,实现方法为高斯消元。

E=I=(10⋯001⋯0⋮⋮⋱⋮00⋯1),eij={1i=j0i≠j\begin{matrix} E \end{matrix} = \begin{matrix} I \end{matrix} = \begin{pmatrix} 1 & 0 & \cdots & 0 \\ 0 & 1 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & 1 \end{pmatrix}, e_{ij} = \begin{cases} 1 & i = j \\0 & i \neq j \end{cases} E​=I​=⎝⎜⎜⎜⎛​10⋮0​01⋮0​⋯⋯⋱⋯​00⋮1​⎠⎟⎟⎟⎞​,eij​={10​i=ji̸​=j​

初始矩阵 P = E。对于矩阵 A,我们可以将它分解成这样两个矩阵的乘积(这里直接借用了 Introduction to Algorithms 里的描述)
A=(a11ωTνA′)=(10ν/a11In−1)(a11ωT0A′−νωT/a11)\begin{matrix} A \end{matrix} = \begin{pmatrix} a_{11} & \omega^T \\ \nu & A' \end{pmatrix} = \begin{pmatrix} 1 & 0 \\ \nu / a_{11} & I_{n-1} \end{pmatrix} \begin{pmatrix} a_{11} & \omega^T \\ 0 & A' - \nu \omega^T / a_{11} \end{pmatrix} A​=(a11​ν​ωTA′​)=(1ν/a11​​0In−1​​)(a11​0​ωTA′−νωT/a11​​)

这样,将这个规模为 n 的问题分解为一个规模为 n - 1 的子问题,迭代之即可求得矩阵 PA 的 LU 分解。最后得到的矩阵 U 相当于高斯消元后的结果,因为求矩阵 U 的实质是用当前规模矩阵的第一行的相应倍数减其它行,将其它行首列元素消为 0。

为了避免除数为零或过小引起精度问题,在迭代到矩阵第 i 行时,我们可以找到 j 使得 ∣Aj,i∣\vert A_{j, i} \vert∣Aj,i​∣ 尽可能大,其中 i≤j≤ni \leq j \leq ni≤j≤n。当 i 不等于 j 时,交换矩阵 PA 的第 i 行与第 j 行,相当于矩阵 A 不变,矩阵 P 的第 i 行与第 j 行交换。

对于矩阵的 LUP 分解代码如下:

#define ABS(x) \
({ \typeof(x) __tmp_x=(x); \__tmp_x<0?-__tmp_x:__tmp_x; \
})#define EXCHANGE(a,b) \
{ \typeof(a) __tmp_a=(a); \a=b,b=__tmp_a; \
}bool Matrix::LUP_Decomposition()
{int p;for(int i=1;i<=dgr;i++){pi[i]=i;for(int j=1;j<=dgr;j++)LUdat[i][j]=dat[i][j];}det=1;for(int i=1;i<=dgr;i++){p=i;for(int j=i+1;j<=dgr;j++)if(ABS(LUdat[j][i])>ABS(LUdat[p][i]))p=j;if(LUdat[p][i]==0)return false;if(p!=i){det=-det;EXCHANGE(pi[i],pi[p]);}for(int j=1;j<=dgr;j++)EXCHANGE(LUdat[i][j],LUdat[p][j]);for(int j=i+1;j<=dgr;j++){LUdat[j][i]/=LUdat[i][i];for(int k=i+1;k<=dgr;k++)LUdat[j][k]-=LUdat[j][i]*LUdat[i][k];}}return true;
}

时间复杂度 O(n3)O(n^3)O(n3)。

矩阵求解线性方程组

对于线性方程组
{a11x1+a12x2+⋯+a1nxn=b1a21x1+a22x2+⋯+a2nxn=b2⋮⋮⋮⋮an1x1+an2x2+⋯+annxn=bn\begin{cases} a_{11} x_1 + &amp; a_{12} x_2 + \cdots + &amp; a_{1n} x_n = &amp; b_1 \\ a_{21} x_1 + &amp; a_{22} x_2 + \cdots + &amp; a_{2n} x_n = &amp; b_2 \\ \vdots &amp; \vdots &amp; \vdots &amp; \vdots \\ a_{n1} x_1 + &amp; a_{n2} x_2 + \cdots + &amp; a_{nn} x_n = &amp; b_n \end{cases} ⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧​a11​x1​+a21​x1​+⋮an1​x1​+​a12​x2​+⋯+a22​x2​+⋯+⋮an2​x2​+⋯+​a1n​xn​=a2n​xn​=⋮ann​xn​=​b1​b2​⋮bn​​

构建矩阵 A 和列向量 B,使得
A=(a11a12⋯a1na21a22⋯a2n⋮⋮⋱⋮an1an2⋯ann),B=(b1b2⋮bn)\begin{matrix} A \end{matrix} = \begin{pmatrix} a_{11} &amp; a_{12} &amp; \cdots &amp; a_{1n} \\ a_{21} &amp; a_{22} &amp; \cdots &amp; a_{2n} \\ \vdots &amp; \vdots &amp; \ddots &amp; \vdots \\ a_{n1} &amp; a_{n2} &amp; \cdots &amp; a_{nn} \end{pmatrix}, \begin{matrix} B \end{matrix} = \begin{pmatrix} b_1 \\ b_2 \\ \vdots \\ b_n \end{pmatrix} A​=⎝⎜⎜⎜⎛​a11​a21​⋮an1​​a12​a22​⋮an2​​⋯⋯⋱⋯​a1n​a2n​⋮ann​​⎠⎟⎟⎟⎞​,B​=⎝⎜⎜⎜⎛​b1​b2​⋮bn​​⎠⎟⎟⎟⎞​

矩阵求解线性方程组即对于矩阵 A 和列向量 B,找到列向量 X,使得
AX=B\begin{matrix} A \end{matrix} \begin{matrix} X \end{matrix} = \begin{matrix} B \end{matrix} A​X​=B​

两边同乘 P,得
LUX=PAX=PB\begin{matrix} L \end{matrix} \begin{matrix} U \end{matrix} \begin{matrix} X \end{matrix} = \begin{matrix} P \end{matrix} \begin{matrix} A \end{matrix} \begin{matrix} X \end{matrix} = \begin{matrix} P \end{matrix} \begin{matrix} B \end{matrix} L​U​X​=P​A​X​=P​B​

设列向量 Y = UX,得
LY=PB\begin{matrix} L \end{matrix} \begin{matrix} Y \end{matrix} = \begin{matrix} P \end{matrix} \begin{matrix} B \end{matrix} L​Y​=P​B​

设数组 π1..n\pi_{1 .. n}π1..n​,其中 πi\pi_iπi​ 表示矩阵 P 中第 i 行第 πi\pi_iπi​ 列元素为 1,第 i 行其余元素均为 0,则 LY = PB 对应的方程组为
{l11y1=bπ1l21y1+l22y2=bπ2⋮⋮⋮ln1y1+ln2y2+⋯+lnnyn=bπn\begin{cases} l_{11} y_1 &amp; &amp; &amp; = &amp; b_{\pi_1} \\ l_{21} y_1 + &amp; l_{22} y_2 &amp; &amp; = &amp; b_{\pi_2} \\ \vdots &amp; \vdots &amp; &amp; &amp; \vdots \\ l_{n1} y_1 + &amp; l_{n2} y_2 + \cdots + &amp; l_{nn} y_n &amp; = &amp; b_{\pi_n} \end{cases} ⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧​l11​y1​l21​y1​+⋮ln1​y1​+​l22​y2​⋮ln2​y2​+⋯+​lnn​yn​​===​bπ1​​bπ2​​⋮bπn​​​

由定义,矩阵 L 中对角线元素均为 1。从上往下依次解出 y1..ny_{1 .. n}y1..n​,这样解出 Y 后,利用方程 UX = Y,解出 X 即可。对应方程组为
{u11x1+u12x2+⋯+u1nxn=y1u22x2+⋯+u2nxn=y2⋮⋮unnxn=yn\begin{cases} u_{11} x_1 + &amp; u_{12} x_2 + \cdots + &amp; u_{1n} x_n &amp; = &amp; y_1 \\ &amp; u_{22} x_2 + \cdots + &amp; u_{2n} x_n &amp; = &amp; y_2 \\ &amp; &amp; \vdots &amp; &amp; \vdots \\ &amp; &amp; u_{nn} x_n &amp; = &amp; y_n \end{cases} ⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧​u11​x1​+​u12​x2​+⋯+u22​x2​+⋯+​u1n​xn​u2n​xn​⋮unn​xn​​===​y1​y2​⋮yn​​

从下往上依次解出 xn..1x_{n .. 1}xn..1​。在具体实现过程中,由于结果中 Y 无需保留,列向量 X 和 Y 可共用存储空间。

对于求解线性方程组的代码如下:

struct VectorColumn
{double dat[MAX_N];int raw;
};VectorColumn Matrix::LUP_Solve(VectorColumn b)
{VectorColumn x;x.raw=dgr;for(int i=1;i<=dgr;i++){x.dat[i]=b.dat[pi[i]];for(int j=1;j<i;j++)x.dat[i]-=LUdat[i][j]*x.dat[j];}for(int i=dgr;i>=1;i--){for(int j=dgr;j>i;j--)x.dat[i]-=LUdat[i][j]*x.dat[j];x.dat[i]/=LUdat[i][i];}return x;
}

时间复杂度 O(n2)O(n^2)O(n2)。(若算上矩阵 LUP 分解,总时间复杂度 O(n3)O(n^3)O(n3))

矩阵的行列式值求解

由行列式性质可知
∣P∣∣A∣=∣L∣∣U∣\begin{vmatrix} P \end{vmatrix} \begin{vmatrix} A \end{vmatrix} = \begin{vmatrix} L \end{vmatrix} \begin{vmatrix} U \end{vmatrix} ∣∣​P​∣∣​∣∣​A​∣∣​=∣∣​L​∣∣​∣∣​U​∣∣​

其中,L 为对角线元素均为 1 的下三角矩阵,故其行列式值为 1;U 为上三角矩阵,其行列式值为对角线元素之积;P 初始行列式值为 1,每对 P 进行一次行交换,相当于行列式值取其相反数。

在具体实现过程中,行列式值的初值为 1 或 -1 在 LUP 分解过程中决定,此部分代码见上文。

对于矩阵的行列式值求解代码如下:

void Matrix::GetDeterminant()
{for(int i=1;i<=dgr;i++)det*=LUdat[i][i];
}

时间复杂度 O(n)O(n)O(n)。(若算上矩阵 LUP 分解,总时间复杂度 O(n3)O(n^3)O(n3))

矩阵求逆

求矩阵 AAA 的逆矩阵,即对于矩阵 AAA 和单位矩阵 EEE,找到矩阵 A−1A^{-1}A−1,使得 AA−1=EA A^{-1} = EAA−1=E。

对于矩阵 A−1A^{-1}A−1 和矩阵 EEE 的任一列,设列数为 iii,构建列向量
Acol(i)−1=(a1ia2i⋮ani),Ecol(i)=(e1ie2i⋮eni)\begin{matrix} A_{col(i)}^{-1} \end{matrix} = \begin{pmatrix} a_{1i} \\ a_{2i} \\ \vdots \\ a_{ni} \end{pmatrix}, \begin{matrix} E_{col(i)} \end{matrix} = \begin{pmatrix} e_{1i} \\ e_{2i} \\ \vdots \\ e_{ni} \end{pmatrix} Acol(i)−1​​=⎝⎜⎜⎜⎛​a1i​a2i​⋮ani​​⎠⎟⎟⎟⎞​,Ecol(i)​​=⎝⎜⎜⎜⎛​e1i​e2i​⋮eni​​⎠⎟⎟⎟⎞​

则有
AAcol(i)−1=Ecol(i)\begin{matrix} A \end{matrix} \begin{matrix} A_{col(i)}^{-1} \end{matrix} = \begin{matrix} E_{col(i)} \end{matrix}A​Acol(i)−1​​=Ecol(i)​​

套用矩阵求解线性方程组的方法即可。

对于矩阵求逆的代码如下:

void Matrix::GetReverse()
{VectorColumn curcol,revcol;curcol.raw=dgr;for(int i=1;i<=dgr;i++)curcol.dat[i]=0;for(int i=1;i<=dgr;i++){curcol.dat[i-1]=0,curcol.dat[i]=1;revcol=LUP_Solve(curcol);for(int j=1;j<=dgr;j++)rev[j][i]=revcol.dat[j];}
}

时间复杂度 O(n3)O(n^3)O(n3)。

矩阵 LUP 分解 解线性方程组 求行列式值 矩阵求逆 算法说解相关推荐

  1. MATLAB常见矩阵运算函数,矩阵的转置transpose()、求行列式值det()、求矩阵的秩rank()、求矩阵的特征值eig()、求逆矩阵inv()

    MATLAB常见矩阵运算函数 1.转置 如矩阵A 转置后 2.求行列式的值det(A) 使用此函数必须保证A为方阵 3.求矩阵的秩 4.求方阵的特征值 5.求方阵的逆矩阵

  2. 给MTL库添加求行列式值

    在使用MTL库的时候,发现mtl库没有求行列式的值的函数,google了一把,找到下面的网页 How to Find Determinant of nxn matrix? 参考里面的说明,给mtl加上 ...

  3. 矩阵库eigen的用法(三)————求行列式值和三角分解求线性方程组的解

    在经过前面2篇对 eigen库的基础知识了解之后,下面就可以用eigen库进行一些实际的操作了. 1.计算矩阵行列式的值 在Eigen里你不能混合两种不同类型的矩阵,像这样是错的 v_3d <& ...

  4. 选主元的高斯-约旦(Gauss-Jordan)消元法解线性方程组/求逆矩阵

    选主元的高斯-约当(Gauss-Jordan)消元法在很多地方都会用到,例如求一个矩阵的逆矩阵.解线性方程组(插一句:LM算法求解的一个步骤),等等.它的速度不是最快的,但是它非常稳定(来自网上的定义 ...

  5. C++高斯消去法求行列式值

    </pre><p><pre name="code" class="cpp">////Created By Kevin Fen ...

  6. 粒子群(pso)算法详解matlab代码,粒子群(pso)算法详解matlab代码

    粒子群(pso)算法详解matlab代码 (1)---- 一.粒子群算法的历史 粒子群算法源于复杂适应系统(Complex Adaptive System,CAS).CAS理论于1994年正式提出,C ...

  7. 解构给默认值_5个 JS 解构有趣的用途

    1. 交换变量 通常交换两个变量的方法需要一个额外的临时变量,来看看例子: let a = 1; let b = 2; let temp; temp = a; a = b; b = temp; a; ...

  8. c语言,通过计算行最简的方式来求行列式的值

    之前写过一个通过定义求行列式值的程序.但是新手写的,懂得都懂.昨天又看了看,我都不知道我咋写出来的了.颇有公司换人接前辈代码的感觉(虽然差了好几个量级).顺带着为了能以后考一考后辈,所以我又用行最简的 ...

  9. matlab解方程实验,MATLAB实验一解线性方程组的直接法

    MATLAB实验一解线性方程组的直接法 实 验 报 告 课程名称 数值分析 实验项目 解线性方程组的直接法 专业班级 姓 名 学 号 指导教师 成 绩 日 期 月 日 一. 实验目的 1. 掌握程序的 ...

  10. js求两圆交点_详解js实现线段交点的三种算法

    本文讲的内容都很初级, 主要是面向和我一样的初学者, 所以请各位算法帝们轻拍啊 引用 已知线段1(a,b) 和线段2(c,d) ,其中a b c d为端点, 求线段交点p .(平行或共线视作不相交) ...

最新文章

  1. linux中setfacl命令,setfacl命令
  2. linux下永久添加静态路由
  3. 计算机快捷键 还原默认值,CAD默认快捷键如何恢复?教你还原CAD默认配置的方法...
  4. 用c语言编程减法计算,求用C编个大数加减法运算程序
  5. php中如何配置环境变量,如何配置phpstorm环境变量如何配置phpstorm环境变量
  6. 《revolution in the valley》读后随笔--Steve jobs与Macintosh
  7. OpenGL在MFC下编程原理
  8. 转载:建设工程中常见的项目建设管理模式有哪些(DBB模式、EPC模式)
  9. MATLAB实现冒泡排序-M文件
  10. 关于短信猫死机的问题程序要如何解决
  11. 将图片转换为Base64编码字符串、解析Base64编码字符串后生成图片
  12. 最小二乘法节点定位(1)——小知识:非线性方程线性化
  13. 更改MyEclipse匹配颜色
  14. Error while Launching activity 解决方案:
  15. HP笔记本电源灯亮不能开机 - 静电问题
  16. java枚举类型季节实例_Java之枚举类
  17. P4735 最大异或和 可持久化trie树
  18. 2020-05-10
  19. php unix时间戳 秒,UNIX时间戳怎么在php项目中使用
  20. QPainter 保存自绘制为图片

热门文章

  1. php收藏影视,十个值得收藏的影视资源网站
  2. 什么是PLC?可编程控制器的结构和工作原理介绍
  3. django -数据库操作
  4. 《幸福的勇气》笔记四——自立就是摆脱“自我”
  5. 反馈抑制器设计的技术要点
  6. 陈强教授《机器学习及R应用》课程 第十章作业
  7. 多功能科学计算机在线使用,多功能科学计算器
  8. 论语十二章原文及翻译
  9. windows10如何让图片打开方式为照片查看器
  10. 图像补全(image inpainting)