LU分解的实现

LU分解是将矩阵分解为一个下三角矩阵和一个上三角矩阵的乘积。矩阵可以不是NxN的矩阵

一个可逆矩阵可以进行LU分解当且仅当它的所有子式都非零。如果要求其中的L矩阵(或U矩阵)为单位三角矩阵,那么分解是唯一的。同理可知,矩阵的LDU可分解条件也相同,并且总是唯一的。
即使矩阵不可逆,LU仍然可能存在。实际上,如果一个秩为k的矩阵的前k个顺序主子式不为零,那么它就可以进行LU分解,但反之则不然。
目前,在任意域上一个方块矩阵可进行LU分解的充要条件已经被发现,这些充要条件可以用某些特定子矩阵的秩表示。用高斯消元法来得到LU分解的算法也可以扩张到任意域上。
任意矩阵A(不仅仅是方块矩阵)都可以进行LUP分解。其中的L和U矩阵是方阵,P矩阵则与A形状一样。

这里给出高斯消元法的思想

Matrix A (M x N) 
for(column index i from 1 to N){
	select max(A[i][i...M]), swap to row i //第i列中从第i行到第N行绝对值最大值元素的行作为第i行
	if(A[i][i] is not zero){
		for(row index j from i + 1 to M){
			A[j][i] /= A[i][i]
			for(column index k from i + 1 to N){
				A[j][k] -= A[j][i] * A[i][k]
			}
		}
	}
}


L如下

1, 	0, 	0, ... 	, 	0
A[21], 	1,	0, ...	,	0
A[31],	A[32],	1, ...	,	0
A[41],	A[42],	A[43], ...,	0
...	...
A[m1],	A[m2],	A[m3], ...,	1

U如下

A[11], 	A[12], 	A[13], ..., 	A[1n]
0, 	A[22],	A[23], ...,	A[2n]
0,	0,	A[33], ...,	A[3n]
0,	0,	0, ...	,	A[4n]
...	...
0,	0,	0, ...	,	A[mn]


下面给出实现,摘自JAMA

// Initialize.
      LU = A.getArrayCopy();
      m = A.getRowDimension();
      n = A.getColumnDimension();
      piv = new int[m];
      for (int i = 0; i < m; i++) {
         piv[i] = i;
      }
      pivsign = 1;
      // Main loop.
      for (int k = 0; k < n; k++) {
         // Find pivot.
         int p = k;
         for (int i = k+1; i < m; i++) {
            if (Math.abs(LU[i][k]) > Math.abs(LU[p][k])) {
               p = i;
            }
         }
         // Exchange if necessary.
         if (p != k) {
            for (int j = 0; j < n; j++) {
               double t = LU[p][j]; LU[p][j] = LU[k][j]; LU[k][j] = t;
            }
            int t = piv[p]; piv[p] = piv[k]; piv[k] = t;
            pivsign = -pivsign;
         }
         // Compute multipliers and eliminate k-th column.
         if (LU[k][k] != 0.0) {
            for (int i = k+1; i < m; i++) {
               LU[i][k] /= LU[k][k];
               for (int j = k+1; j < n; j++) {
                  LU[i][j] -= LU[i][k]*LU[k][j];
               }
            }
         }
      }

由于Java对点乘支持的问题,上述方法在JAMA中并没有使用,而是使用了Crout/Doolittle算法,描述如下:




根据上述写的代码如下


for(int a = 0; a < length; a++){
			for(int b = 0; b < length; b++){
				double sum = 0.0;
				if(a <= b){
					for(int i = 0; i < a; i++){
						sum += l[a][i] * u[i][b];
					}
					u[a][b] = matrix[a][b] - sum;
				}else{
					for(int i = 0; i < b; i++){
						sum += l[a][i] * u[i][b];
					}
					l[a][b] = (matrix[a][b] - sum) / u[b][b];
				}
			}
		}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LU 分解LU decomposition)是一种矩阵分解的方法,也被称为 LU 分解法或 LU 分解算法。它将一个矩阵分解为一个下三角矩阵 L 和一个上三角矩阵 U 的乘积,即 A = LU,其中 A 是原始矩阵LU 分解的主要目的是将线性方程组的求解问题转化为两个简化的步骤:首先,通过前代法(forward substitution)求解 Lc = b,其中 c 是一个中间向量;然后,通过回代法(backward substitution)求解 Ux = c,其中 x 是方程组的解向量。 LAPACK(Linear Algebra PACKage)是一个开源的数值线性代数库,包含了许多高效的算法和函数,用于解决线性代数问题。其中包括了进行 LU 分解的函数。 Eigen 是另一个开源的线性代数库,提供了高级的矩阵和向量操作接口。它本身并不包含 LAPACK 的实现,但提供了对 LAPACK 接口的封装,以便更方便地使用 LAPACK 的功能。 因此,在 Eigen 中,你可以使用 `Eigen::FullPivLU` 类来进行 LU 分解。这个类使用 LAPACK 库中的 LU 分解函数来实现 LU 分解操作。实际上,Eigen 将 LAPACK 的功能封装在自己的类中,并提供了更简单和高级的接口,使得使用 LU 分解更加方便。 所以,虽然 Eigen 本身不能执行 LU 分解,但通过使用 Eigen 提供的相关类和函数,你可以间接地调用 LAPACK 库中的 LU 分解功能。 希望这个解释能够清楚回答你的问题。如果还有任何疑问,欢迎继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值