克劳特算法计算行列式(Kraut)

使用克劳特算法以 O ( N 3 ) O(N^3) O(N3) 的复杂度计算行列式(Calculating the determinant using Kraut method in O ( N 3 ) O(N^3) O(N3)

在本文中,我们将描述如何使用 Kraut 方法找到矩阵的行列式,该方法的时间复杂度为 O ( N 3 ) O(N^3) O(N3)

克劳特算法发现矩阵 A A A 的分解为 A = L U A=LU A=LU ,其中 L L L 是下三角矩阵, U U U 是上三角矩阵。在不丧失一般性的情况下,我们可以假设 L L L 的所有对角线元素都等于 1 1 1 。一旦我们知道这些矩阵,就很容易计算出 A A A 的行列式:它等于矩阵 U U U 的主对角线上所有元素的乘积。

有一个定理表明,任何可逆矩阵都有 L U LU LU 分解,并且它是唯一的,当且仅当它的所有主余子式都是非零的。我们只考虑这样的分解,其中矩阵 L L L 的对角线是由矩阵的对角线构成的。

A A A 为矩阵, N N N 为矩阵的大小。我们将使用以下步骤找到矩阵的 L L L U U U 元素:

  1. L i i = 1 L_{i i} = 1 Lii=1 for i = 1 , 2 , . . . , N i = 1, 2, ..., N i=1,2,...,N
  2. 对于每个 j = 1 , 2 , . . . , N j = 1, 2, ..., N j=1,2,...,N ,执行:
    • for i = 1 , 2 , . . . , j i = 1, 2, ..., j i=1,2,...,j 寻找值
      U i j = A i j − ∑ k = 1 i − 1 L i k ⋅ U k j U_{ij} = A_{ij} - \sum_{k=1}^{i-1} L_{ik} \cdot U_{kj} Uij=Aijk=1i1LikUkj
    • 接下来,for i = j + 1 , j + 2 , . . . , N i = j+1, j+2, ..., N i=j+1,j+2,...,N 寻找值
      L i j = 1 U j j ( A i j − ∑ k = 1 j − 1 L i k ⋅ U k j ) L_{ij} = \frac{1}{U_{jj}} \left(A_{ij} - \sum_{k=1}^{j-1} L_{ik} \cdot U_{kj} \right) Lij=Ujj1(Aijk=1j1LikUkj)

实现

static BigInteger det (BigDecimal a [][], int n) {
	try {

	for (int i=0; i<n; i++) {
		boolean nonzero = false;
		for (int j=0; j<n; j++)
			if (a[i][j].compareTo (new BigDecimal (BigInteger.ZERO)) > 0)
				nonzero = true;
		if (!nonzero)
			return BigInteger.ZERO;
	}

	BigDecimal scaling [] = new BigDecimal [n];
	for (int i=0; i<n; i++) {
		BigDecimal big = new BigDecimal (BigInteger.ZERO);
		for (int j=0; j<n; j++)
			if (a[i][j].abs().compareTo (big) > 0)
				big = a[i][j].abs();
		scaling[i] = (new BigDecimal (BigInteger.ONE)) .divide
			(big, 100, BigDecimal.ROUND_HALF_EVEN);
	}

	int sign = 1;

	for (int j=0; j<n; j++) {
		for (int i=0; i<j; i++) {
			BigDecimal sum = a[i][j];
			for (int k=0; k<i; k++)
				sum = sum.subtract (a[i][k].multiply (a[k][j]));
			a[i][j] = sum;
		}

		BigDecimal big = new BigDecimal (BigInteger.ZERO);
		int imax = -1;
		for (int i=j; i<n; i++) {
			BigDecimal sum = a[i][j];
			for (int k=0; k<j; k++)
				sum = sum.subtract (a[i][k].multiply (a[k][j]));
			a[i][j] = sum;
			BigDecimal cur = sum.abs();
			cur = cur.multiply (scaling[i]);
			if (cur.compareTo (big) >= 0) {
				big = cur;
				imax = i;
			}
		}

		if (j != imax) {
			for (int k=0; k<n; k++) {
				BigDecimal t = a[j][k];
				a[j][k] = a[imax][k];
				a[imax][k] = t;
			}

			BigDecimal t = scaling[imax];
			scaling[imax] = scaling[j];
			scaling[j] = t;

			sign = -sign;
		}

		if (j != n-1)
			for (int i=j+1; i<n; i++)
				a[i][j] = a[i][j].divide
					(a[j][j], 100, BigDecimal.ROUND_HALF_EVEN);

	}

	BigDecimal result = new BigDecimal (1);
	if (sign == -1)
		result = result.negate();
	for (int i=0; i<n; i++)
		result = result.multiply (a[i][i]);

	return result.divide
		(BigDecimal.valueOf(1), 0, BigDecimal.ROUND_HALF_EVEN).toBigInteger();
	}
	catch (Exception e) {
		return BigInteger.ZERO;
	}
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我真的不是cjc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值