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.
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.
| Método | Uso recomendado | Idea central |
|---|---|---|
| Fórmula 2 × 2 | Matrices pequeñas | Aplicar una expresión directa |
| Adjunta | Ejercicios teóricos de orden bajo | Usar menores y cofactores |
| Gauss-Jordan | Método general y programable | Reducir [A | I] hasta [I | A-1] |
| Factorizaciones | Cálculo numérico y varios sistemas | Resolver 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.
Para A = [[a, b], [c, d]], con ad − bc distinto de cero:
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]]
Sea A = [[3, 1], [5, 2]]. Su determinante es 3 · 2 − 1 · 5 = 1. Como no es cero, A es invertible.
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]]));
Para una matriz cuadrada invertible de cualquier orden puede emplearse:
La matriz adjunta se obtiene en tres etapas: calcular los menores, asignar los signos de los cofactores y transponer la matriz de cofactores.
El menor Mij es el determinante que queda al eliminar la fila i y la columna j. Por ejemplo, para:
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]]
Cada cofactor incorpora un signo al menor:
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);
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.
Para A = [[1, 2, 3], [0, 1, 4], [5, 6, 0]], el determinante vale 1. Su adjunta es:
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
Gauss-Jordan coloca la matriz A junto a la identidad del mismo orden y aplica operaciones elementales por fila:
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.
Las operaciones que conservan la equivalencia del sistema son:
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);
Para A = [[2, 1], [5, 3]] se comienza con [[2, 1 | 1, 0], [5, 3 | 0, 1]]. Una secuencia posible es:
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]]));
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]]
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.
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
| Criterio | Fórmula 2 × 2 | Adjunta | Gauss-Jordan |
|---|---|---|---|
| Orden admitido | Solo 2 | Cualquier orden | Cualquier orden |
| Cálculo manual | Muy breve | Crece rápidamente | Sistemático |
| Implementación | Simple | Costosa si se expande por cofactores | Directa |
| Valor didáctico | Alto para iniciar | Relaciona determinante e inversa | Prepara 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.
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.
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.
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.