Skip to Content

Calcular el determinante usando el método de Kraut en O(N3)O(N^3)

En este artículo describiremos cómo hallar el determinante de la matriz usando el método de Kraut, que funciona en O(N3)O(N^3).

El algoritmo de Kraut halla una descomposición de la matriz AA como A=LUA = L U donde LL es triangular inferior y UU es una matriz triangular superior. Sin pérdida de generalidad, podemos asumir que todos los elementos diagonales de LL son iguales a 1. Una vez que conocemos estas matrices, es fácil calcular el determinante de AA: es igual al producto de todos los elementos de la diagonal principal de la matriz UU.

Hay un teorema que afirma que cualquier matriz invertible tiene una descomposición LU, y es única, si y solo si todos sus menores principales son no nulos. Consideramos solo aquella descomposición en la que la diagonal de la matriz LL consiste en unos.

Sea AA la matriz y NN su tamaño. Hallaremos los elementos de las matrices LL y UU usando los siguientes pasos:

  1. Sea Lii=1L_{i i} = 1 para i=1,2,...,Ni = 1, 2, …, N.
  2. Para cada j=1,2,...,Nj = 1, 2, …, N realizar:
    • Para i=1,2,...,ji = 1, 2, …, j hallar los valores

      Uij=Aijk=1i1LikUkjU_{ij} = A_{ij} - \sum_{k=1}^{i-1} L_{ik} \cdot U_{kj}

    • Luego, para i=j+1,j+2,...,Ni = j+1, j+2, …, N hallar los valores

      Lij=1Ujj(Aijk=1j1LikUkj).L_{ij} = \frac{1}{U_{jj}} \left(A_{ij} - \sum_{k=1}^{j-1} L_{ik} \cdot U_{kj} \right).

Implementación

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; } }