Gauss-Jordan lleva una matriz hasta su forma escalonada reducida: cada pivote vale 1 y es el único elemento no nulo de su columna. Así, las soluciones y las variables libres quedan visibles directamente.
La eliminación de Gauss anula los elementos situados debajo de cada pivote. Gauss-Jordan amplía ese proceso: normaliza los pivotes y elimina también los elementos que están encima.
El resultado se denomina forma escalonada reducida por filas, abreviada RREF por su nombre en inglés.
| Característica | Gauss | Gauss-Jordan |
|---|---|---|
| Elimina debajo del pivote | Sí | Sí |
| Elimina encima del pivote | No necesariamente | Sí |
| Normaliza cada pivote a 1 | No es obligatorio | Sí |
| Sustitución hacia atrás | Necesaria | No es necesaria |
| Trabajo aritmético | Menor | Mayor |
Ambos métodos emplean las mismas operaciones elementales por fila y conservan el conjunto de soluciones.
Una matriz está en forma escalonada reducida cuando cumple:
Esta forma es única para cada matriz, aunque distintas secuencias de operaciones pueden conducir a ella.
Gauss-Jordan utiliza las tres operaciones conocidas: intercambiar filas, multiplicar una fila por un escalar no nulo y sumar a una fila un múltiplo de otra.
Para convertir un pivote p en 1 se divide toda la fila por p:
const fila = [0, -3, -9];
const pivote = fila[1];
const normalizada = fila.map(valor => valor / pivote);
console.log(normalizada); // [0, 1, 3]
La operación debe incluir siempre la columna de términos independientes.
Resolvamos x + y = 5 y 2x − y = 1. Partimos de:
Aplicamos F2 ← F2 − 2F1:
const matriz = [[1, 1, 5], [2, -1, 1]];
matriz[1] = matriz[1].map(
(valor, j) => valor - 2 * matriz[0][j]
);
console.log(matriz); // [[1, 1, 5], [0, -3, -9]]
Dividimos F2 por −3 para crear el segundo pivote y después aplicamos F1 ← F1 − F2:
const matriz = [[1, 1, 5], [0, -3, -9]];
matriz[1] = matriz[1].map(valor => valor / -3);
matriz[0] = matriz[0].map((valor, j) => valor - matriz[1][j]);
console.log(matriz); // [[1, 0, 2], [0, 1, 3]]
La solución se lee directamente: x = 2, y = 3.
Para el sistema del tema anterior:
Gauss-Jordan produce:
La parte izquierda es la identidad; por lo tanto, x = 1, y = 2 y z = 3.
const reducida = [[1, 0, 0, 1], [0, 1, 0, 2], [0, 0, 1, 3]];
const solucion = reducida.map(fila => fila.at(-1));
console.log(solucion); // [1, 2, 3]
La siguiente implementación acepta cualquier matriz rectangular, trabaja sobre una copia y devuelve tanto la forma reducida como las columnas que contienen pivotes.
function gaussJordan(matriz, tolerancia = 1e-10) {
if (matriz.length === 0) return { matriz: [], pivotes: [] };
const columnas = matriz[0].length;
if (matriz.some(fila => fila.length !== columnas)) {
throw new Error("Todas las filas deben tener igual longitud");
}
const m = matriz.map(fila => fila.map(Number));
const pivotes = [];
let filaPivote = 0;
for (let columna = 0; columna < columnas && filaPivote < m.length; columna++) {
let mejor = filaPivote;
for (let fila = filaPivote + 1; fila < m.length; fila++) {
if (Math.abs(m[fila][columna]) > Math.abs(m[mejor][columna])) {
mejor = fila;
}
}
if (Math.abs(m[mejor][columna]) <= tolerancia) continue;
[m[filaPivote], m[mejor]] = [m[mejor], m[filaPivote]];
const pivote = m[filaPivote][columna];
m[filaPivote] = m[filaPivote].map(valor => valor / pivote);
for (let fila = 0; fila < m.length; fila++) {
if (fila === filaPivote) continue;
const factor = m[fila][columna];
m[fila] = m[fila].map(
(valor, j) => valor - factor * m[filaPivote][j]
);
}
pivotes.push(columna);
filaPivote++;
}
for (const fila of m) {
for (let j = 0; j < columnas; j++) {
if (Math.abs(fila[j]) <= tolerancia) fila[j] = 0;
}
}
return { matriz: m, pivotes };
}
const sistema = [[1, 1, 5], [2, -1, 1]];
console.log(gaussJordan(sistema));
Antes de normalizar una fila se busca el elemento de mayor magnitud en la parte disponible de la columna. Así se evita dividir por cero o por un número innecesariamente pequeño.
const matriz = [[0, 2, 4], [3, 1, 7], [-5, 2, 1]];
let mejor = 0;
for (let fila = 1; fila < matriz.length; fila++) {
if (Math.abs(matriz[fila][0]) > Math.abs(matriz[mejor][0])) mejor = fila;
}
[matriz[0], matriz[mejor]] = [matriz[mejor], matriz[0]];
console.log(matriz[0]); // comienza con -5
Si cada columna de incógnita contiene un pivote y no aparece ninguna contradicción, el sistema posee una única solución.
function leerSolucionUnica(reducida, incognitas) {
if (reducida.length !== incognitas) return null;
const izquierdaEsIdentidad = reducida.every((fila, i) =>
fila.slice(0, incognitas).every((v, j) => Math.abs(v - Number(i === j)) < 1e-10)
);
return izquierdaEsIdentidad ? reducida.map(fila => fila[incognitas]) : null;
}
console.log(leerSolucionUnica([[1, 0, 2], [0, 1, 3]], 2));
Si una columna de incógnita no tiene pivote, su variable es libre. Por ejemplo:
Podemos elegir y = s, z = t y expresar x = 3 − s − t. Cada pareja de parámetros produce una solución.
function solucionParametrica(s, t) {
const y = s;
const z = t;
const x = 3 - s - t;
return [x, y, z];
}
console.log(solucionParametrica(1, 1)); // [1, 1, 1]
console.log(solucionParametrica(4, -2)); // [1, 4, -2]
Una fila con coeficientes nulos y término independiente no nulo representa una contradicción:
function tieneContradiccion(reducida, tolerancia = 1e-10) {
return reducida.some(fila => {
const coeficientesNulos = fila.slice(0, -1)
.every(valor => Math.abs(valor) <= tolerancia);
return coeficientesNulos && Math.abs(fila.at(-1)) > tolerancia;
});
}
console.log(tieneContradiccion([[1, 1, 2], [0, 0, 1]])); // true
La forma reducida permite leer información estructural:
const incognitas = 4;
const columnasPivote = [0, 2];
const columnasLibres = Array.from({ length: incognitas }, (_, j) => j)
.filter(j => !columnasPivote.includes(j));
console.log(columnasLibres); // [1, 3]
Gauss-Jordan también calcula A-1. Se aumenta A con la identidad y se reduce el bloque izquierdo:
Si A no puede transformarse en I, la inversa no existe.
const A = [[2, 1], [5, 3]];
const aumentada = A.map((fila, i) => [
...fila,
...Array.from({ length: A.length }, (_, j) => Number(i === j))
]);
console.log(aumentada); // [[2, 1, 1, 0], [5, 3, 0, 1]]
Las soluciones obtenidas deben sustituirse en el sistema original. La comprobación se realiza con tolerancia para admitir pequeños errores de punto flotante.
function verificar(A, x, b, tolerancia = 1e-10) {
return A.every((fila, i) => {
const resultado = fila.reduce((suma, valor, j) => suma + valor * x[j], 0);
return Math.abs(resultado - b[i]) <= tolerancia;
});
}
const A = [[1, 1], [2, -1]];
console.log(verificar(A, [2, 3], [5, 1])); // true
Gauss y Gauss-Jordan tienen un crecimiento cúbico aproximado para matrices cuadradas, pero Gauss-Jordan realiza más operaciones porque elimina por encima y por debajo de cada pivote.
| Objetivo | Elección habitual |
|---|---|
| Resolver un sistema con solución única | Gauss o factorización |
| Obtener la forma reducida completa | Gauss-Jordan |
| Identificar variables libres didácticamente | Gauss-Jordan |
| Calcular una inversa pequeña | Gauss-Jordan |
El pivoteo parcial y una tolerancia adecuada reducen problemas numéricos. Las matrices casi singulares pueden seguir siendo muy sensibles a pequeñas variaciones.
Errores habituales:
Gauss-Jordan transforma una matriz en una representación canónica que muestra pivotes, variables libres y contradicciones. Aunque requiere más operaciones que Gauss, resulta especialmente claro para analizar todas las soluciones de un sistema.
En el próximo tema estudiaremos la regla de Cramer, que utiliza determinantes para resolver sistemas cuadrados con solución única.