20. Métodos para calcular la matriz inversa

Calcular una inversa consiste en transformar una matriz invertible hasta encontrar la operación que deshace su efecto. Estudiaremos la fórmula 2 × 2, el método de la adjunta y Gauss-Jordan.

20.1 Introducción

En el tema anterior definimos A-1 mediante la igualdad AA-1 = I. Ahora veremos procedimientos concretos para obtenerla.

Todos los métodos parten de dos requisitos: A debe ser cuadrada y no singular. Si det(A) = 0, ninguna secuencia válida de cálculos puede producir su inversa.

Antes de calcular, conviene preguntar: ¿la matriz es cuadrada?, ¿es invertible? y ¿realmente necesitamos formar A-1?

20.2 Cómo elegir un método

MétodoUso recomendadoIdea central
Fórmula 2 × 2Matrices pequeñasAplicar una expresión directa
AdjuntaEjercicios teóricos de orden bajoUsar menores y cofactores
Gauss-JordanMétodo general y programableReducir [A | I] hasta [I | A-1]
FactorizacionesCálculo numérico y varios sistemasResolver columnas sin formar la inversa explícitamente

La adjunta ayuda a comprender la teoría, pero Gauss-Jordan resulta más sistemático. En aplicaciones grandes se prefieren algoritmos basados en factorizaciones.

20.3 Fórmula directa para orden 2

Para A = [[a, b], [c, d]], con ad − bc distinto de cero:

A-1 = 1/(ad − bc) · [[d, −b], [−c, a]]

El procedimiento intercambia los elementos de la diagonal principal, cambia el signo de los otros dos y divide todos los valores por el determinante.

const A = [[4, 7], [2, 6]];
const determinante = A[0][0] * A[1][1] - A[0][1] * A[1][0];

const inversa = [
  [ A[1][1] / determinante, -A[0][1] / determinante],
  [-A[1][0] / determinante,  A[0][0] / determinante]
];

console.log(inversa); // [[0.6, -0.7], [-0.2, 0.4]]

20.4 Ejemplo completo de orden 2

Sea A = [[3, 1], [5, 2]]. Su determinante es 3 · 2 − 1 · 5 = 1. Como no es cero, A es invertible.

A-1 = [[2, −1], [−5, 3]]

Al ser el determinante igual a 1, no cambia los elementos de la matriz obtenida después de intercambiar la diagonal y cambiar los signos.

function inversa2x2(matriz) {
  const [[a, b], [c, d]] = matriz;
  const det = a * d - b * c;
  if (Math.abs(det) < 1e-12) return null;
  return [[d / det, -b / det], [-c / det, a / det]];
}

console.log(inversa2x2([[3, 1], [5, 2]]));

20.5 Método de la matriz adjunta

Para una matriz cuadrada invertible de cualquier orden puede emplearse:

A-1 = adj(A) / det(A)

La matriz adjunta se obtiene en tres etapas: calcular los menores, asignar los signos de los cofactores y transponer la matriz de cofactores.

  1. Construir la matriz de menores.
  2. Convertir cada menor en un cofactor.
  3. Transponer la matriz de cofactores.
  4. Dividir la adjunta por det(A).

20.6 Matriz de menores

El menor Mij es el determinante que queda al eliminar la fila i y la columna j. Por ejemplo, para:

A = [[1, 2, 3], [0, 1, 4], [5, 6, 0]]

Al eliminar la primera fila y la primera columna queda [[1, 4], [6, 0]], por lo que M11 = 1 · 0 − 4 · 6 = −24.

function submatriz(matriz, fila, columna) {
  return matriz
    .filter((_, i) => i !== fila)
    .map(renglon => renglon.filter((_, j) => j !== columna));
}

const A = [[1, 2, 3], [0, 1, 4], [5, 6, 0]];
console.log(submatriz(A, 0, 0)); // [[1, 4], [6, 0]]

20.7 Matriz de cofactores

Cada cofactor incorpora un signo al menor:

Cij = (−1)i+jMij
Patrón de signos: [[+, −, +], [−, +, −], [+, −, +]]
function determinante2x2(m) {
  return m[0][0] * m[1][1] - m[0][1] * m[1][0];
}

function submatriz(m, fila, columna) {
  return m.filter((_, i) => i !== fila)
    .map(r => r.filter((_, j) => j !== columna));
}

const A = [[1, 2, 3], [0, 1, 4], [5, 6, 0]];
const cofactores = A.map((fila, i) =>
  fila.map((_, j) => (-1) ** (i + j) * determinante2x2(submatriz(A, i, j)))
);
console.log(cofactores);

20.8 De los cofactores a la adjunta

La adjunta no es la matriz de cofactores sin modificar: es su transpuesta. Por tanto, las filas se convierten en columnas.

function transponer(matriz) {
  return matriz[0].map((_, columna) =>
    matriz.map(fila => fila[columna])
  );
}

const cofactores = [[-24, 20, -5], [18, -15, 4], [5, -4, 1]];
const adjunta = transponer(cofactores);
console.log(adjunta);

Finalmente, se divide cada elemento de la adjunta por el determinante de A.

20.9 Ejemplo 3 × 3 mediante la adjunta

Para A = [[1, 2, 3], [0, 1, 4], [5, 6, 0]], el determinante vale 1. Su adjunta es:

adj(A) = [[−24, 18, 5], [20, −15, −4], [−5, 4, 1]]

Como det(A) = 1, esa misma matriz es A-1.

const A = [[1, 2, 3], [0, 1, 4], [5, 6, 0]];
const inversa = [[-24, 18, 5], [20, -15, -4], [-5, 4, 1]];

const producto = A.map((fila, i) =>
  inversa[0].map((_, j) =>
    fila.reduce((suma, valor, k) => suma + valor * inversa[k][j], 0)
  )
);
console.log(producto); // matriz identidad

20.10 Método de Gauss-Jordan

Gauss-Jordan coloca la matriz A junto a la identidad del mismo orden y aplica operaciones elementales por fila:

[A | I] ⟶ [I | A-1]

Si la parte izquierda no puede reducirse a la identidad, A es singular. El método calcula la inversa completa sin construir explícitamente todos los menores y cofactores.

20.11 Operaciones elementales por fila

Las operaciones que conservan la equivalencia del sistema son:

  • Intercambiar dos filas.
  • Multiplicar una fila por un escalar distinto de cero.
  • Sumar a una fila un múltiplo de otra.

Cada operación debe aplicarse a toda la fila aumentada, tanto en el bloque A como en el bloque I.

const aumentada = [[2, 1, 1, 0], [5, 3, 0, 1]];

// F1 se divide por su pivote 2.
aumentada[0] = aumentada[0].map(valor => valor / 2);

// F2 recibe F2 - 5F1.
aumentada[1] = aumentada[1].map(
  (valor, j) => valor - 5 * aumentada[0][j]
);
console.log(aumentada);

20.12 Gauss-Jordan paso a paso para orden 2

Para A = [[2, 1], [5, 3]] se comienza con [[2, 1 | 1, 0], [5, 3 | 0, 1]]. Una secuencia posible es:

  1. Dividir F1 por 2.
  2. Reemplazar F2 por F2 − 5F1.
  3. Dividir F2 por su nuevo pivote.
  4. Eliminar el valor sobre el segundo pivote.
[A | I] ⟶ [[1, 0 | 3, −1], [0, 1 | −5, 2]]
A-1 = [[3, −1], [−5, 2]]

20.13 Implementación general de Gauss-Jordan

La siguiente función acepta una matriz cuadrada de cualquier orden. Copia sus datos para no modificar la matriz original y devuelve null cuando detecta singularidad.

function inversaGaussJordan(matriz, tolerancia = 1e-12) {
  const n = matriz.length;
  if (n === 0 || matriz.some(fila => fila.length !== n)) return null;

  const aumentada = matriz.map((fila, i) => [
    ...fila.map(Number),
    ...Array.from({ length: n }, (_, j) => Number(i === j))
  ]);

  for (let columna = 0; columna < n; columna++) {
    let filaPivote = columna;
    for (let fila = columna + 1; fila < n; fila++) {
      if (Math.abs(aumentada[fila][columna]) >
          Math.abs(aumentada[filaPivote][columna])) {
        filaPivote = fila;
      }
    }

    if (Math.abs(aumentada[filaPivote][columna]) < tolerancia) return null;
    [aumentada[columna], aumentada[filaPivote]] =
      [aumentada[filaPivote], aumentada[columna]];

    const pivote = aumentada[columna][columna];
    aumentada[columna] = aumentada[columna].map(valor => valor / pivote);

    for (let fila = 0; fila < n; fila++) {
      if (fila === columna) continue;
      const factor = aumentada[fila][columna];
      aumentada[fila] = aumentada[fila].map(
        (valor, j) => valor - factor * aumentada[columna][j]
      );
    }
  }

  return aumentada.map(fila => fila.slice(n));
}

console.log(inversaGaussJordan([[2, 1], [5, 3]]));

20.14 Pivoteo parcial

Dividir por un pivote cero detendría el algoritmo. Un pivote muy pequeño, además, puede amplificar los errores de redondeo.

El pivoteo parcial busca en la columna el elemento disponible con mayor valor absoluto e intercambia las filas. Así se evita una división problemática siempre que exista un pivote adecuado.

const matriz = [[0, 2], [3, 4]];
const columna = 0;
let filaPivote = columna;

for (let fila = columna + 1; fila < matriz.length; fila++) {
  if (Math.abs(matriz[fila][columna]) > Math.abs(matriz[filaPivote][columna])) {
    filaPivote = fila;
  }
}

[matriz[columna], matriz[filaPivote]] = [matriz[filaPivote], matriz[columna]];
console.log(matriz); // [[3, 4], [0, 2]]

20.15 Detectar matrices singulares

Si, después de buscar en las filas disponibles, el mejor pivote es cero, la columna no puede producir el 1 correspondiente de la identidad. La matriz es singular.

function esCasiCero(valor, tolerancia = 1e-12) {
  return Math.abs(valor) < tolerancia;
}

const mejorPivote = 0;
if (esCasiCero(mejorPivote)) {
  console.log("No existe una inversa numéricamente segura");
}

En aritmética de punto flotante se usa una tolerancia en vez de exigir una igualdad exacta con cero. En programas más avanzados, la tolerancia debe adaptarse a la escala de la matriz.

20.16 Verificar la inversa calculada

Después de calcular B, se comprueba que AB y BA sean aproximadamente la identidad. La comparación aproximada es necesaria por los errores de representación decimal.

function multiplicar(A, B) {
  return A.map(fila => B[0].map((_, j) =>
    fila.reduce((suma, valor, k) => suma + valor * B[k][j], 0)
  ));
}

function esIdentidad(matriz, tolerancia = 1e-10) {
  return matriz.every((fila, i) => fila.every((valor, j) =>
    Math.abs(valor - Number(i === j)) < tolerancia
  ));
}

const A = [[4, 7], [2, 6]];
const B = [[0.6, -0.7], [-0.2, 0.4]];
console.log(esIdentidad(multiplicar(A, B))); // true

20.17 Comparación práctica de los métodos

CriterioFórmula 2 × 2AdjuntaGauss-Jordan
Orden admitidoSolo 2Cualquier ordenCualquier orden
Cálculo manualMuy breveCrece rápidamenteSistemático
ImplementaciónSimpleCostosa si se expande por cofactoresDirecta
Valor didácticoAlto para iniciarRelaciona determinante e inversaPrepara para sistemas lineales

La expansión recursiva por cofactores resulta ineficiente para matrices grandes. Gauss-Jordan evita esa explosión combinatoria, aunque las bibliotecas numéricas suelen utilizar factorizaciones más estables.

20.18 Resolver sin formar la inversa

Aunque x = A-1b es correcto, calcular toda la inversa para resolver un solo sistema Ax = b realiza trabajo innecesario y puede acumular más error.

Si el objetivo es encontrar x, conviene aplicar eliminación o una factorización directamente al sistema Ax = b.

La inversa explícita sí es útil cuando el resultado completo se necesita como objeto matemático, para enseñar el concepto o para reutilizar una transformación inversa pequeña y bien condicionada.

Las matrices rectangulares no poseen inversa ordinaria. En ciertos problemas se utiliza una pseudoinversa, que es un concepto diferente.

20.19 Qué debes recordar de este tema

  • La fórmula directa 2 × 2 divide una matriz modificada por ad − bc.
  • El método de la adjunta usa menores, cofactores, transposición y determinante.
  • Gauss-Jordan transforma [A | I] en [I | A-1].
  • Toda operación por fila se aplica a los dos bloques de la matriz aumentada.
  • El pivoteo parcial mejora la seguridad del cálculo.
  • Un pivote nulo indica que no puede continuarse hacia la identidad.
  • Los resultados numéricos se comparan mediante una tolerancia.
  • La inversa debe verificarse comprobando AB ≈ BA ≈ I.
  • Para resolver Ax = b normalmente es mejor resolver el sistema directamente.

20.20 Conclusión

Los distintos métodos conducen al mismo objeto, pero sirven para contextos diferentes. La fórmula 2 × 2 es inmediata, la adjunta muestra la relación con los determinantes y Gauss-Jordan ofrece un procedimiento general basado en operaciones por fila.

En el próximo tema estudiaremos el rango de una matriz, que mide la cantidad de información linealmente independiente contenida en sus filas o columnas.