24. Método de Gauss-Jordan

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.

24.1 Introducción

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.

[A | b] ⟶ forma escalonada reducida ⟶ lectura directa de las soluciones

24.2 Diferencias entre Gauss y Gauss-Jordan

CaracterísticaGaussGauss-Jordan
Elimina debajo del pivote
Elimina encima del pivoteNo necesariamente
Normaliza cada pivote a 1No es obligatorio
Sustitución hacia atrásNecesariaNo es necesaria
Trabajo aritméticoMenorMayor

Ambos métodos emplean las mismas operaciones elementales por fila y conservan el conjunto de soluciones.

24.3 Forma escalonada reducida

Una matriz está en forma escalonada reducida cuando cumple:

  • Las filas nulas aparecen al final.
  • El pivote de cada fila no nula es 1.
  • Cada pivote está a la derecha del pivote de la fila anterior.
  • Cada pivote es el único elemento no nulo de su columna.
[[1, 0, 2 | 4], [0, 1, −3 | 1], [0, 0, 0 | 0]]

Esta forma es única para cada matriz, aunque distintas secuencias de operaciones pueden conducir a ella.

24.4 Operaciones elementales

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.

24.5 Pasos del método

  1. Construir la matriz aumentada [A | b].
  2. Buscar un pivote no nulo en la primera columna disponible.
  3. Intercambiar filas si resulta necesario.
  4. Dividir la fila para convertir el pivote en 1.
  5. Anular todos los demás elementos de la columna del pivote.
  6. Avanzar a la siguiente fila y columna.
  7. Interpretar la matriz reducida.
A diferencia de Gauss, la eliminación se aplica sobre y debajo de cada pivote.

24.6 Ejemplo 2 × 2: eliminación inicial

Resolvamos x + y = 5 y 2x − y = 1. Partimos de:

[[1, 1 | 5], [2, −1 | 1]]

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]]

24.7 Ejemplo 2 × 2: reducción completa

Dividimos F2 por −3 para crear el segundo pivote y después aplicamos F1 ← F1 − F2:

[[1, 1 | 5], [0, 1 | 3]] ⟶ [[1, 0 | 2], [0, 1 | 3]]
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.

24.8 Ejemplo de orden 3

Para el sistema del tema anterior:

x + y + z = 6
2x − y + z = 3
x + 2y − z = 2

Gauss-Jordan produce:

[[1, 0, 0 | 1], [0, 1, 0 | 2], [0, 0, 1 | 3]]

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]

24.9 Algoritmo general en JavaScript

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

24.10 Pivoteo parcial

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

24.11 Sistema con solución única

Si cada columna de incógnita contiene un pivote y no aparece ninguna contradicción, el sistema posee una única solución.

[[1, 0 | a], [0, 1 | b]] ⇒ x = a, y = b
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));

24.12 Sistema con infinitas soluciones

Si una columna de incógnita no tiene pivote, su variable es libre. Por ejemplo:

[[1, 1, 1 | 3], [0, 0, 0 | 0]]
x + y + z = 3

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]

24.13 Sistema sin solución

Una fila con coeficientes nulos y término independiente no nulo representa una contradicción:

[0, 0, ..., 0 | c], con c ≠ 0 ⇒ 0 = c
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

24.14 Pivotes, rango y variables libres

La forma reducida permite leer información estructural:

  • La cantidad de pivotes en A es rango(A).
  • Las columnas con pivote corresponden a variables básicas.
  • Las columnas sin pivote corresponden a variables libres.
  • El número de variables libres es n − rango(A).
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]

24.15 Cálculo de la matriz inversa

Gauss-Jordan también calcula A-1. Se aumenta A con la identidad y se reduce el bloque izquierdo:

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

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]]

24.16 Verificación del resultado

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

24.17 Costo y comparación práctica

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.

ObjetivoElección habitual
Resolver un sistema con solución únicaGauss o factorización
Obtener la forma reducida completaGauss-Jordan
Identificar variables libres didácticamenteGauss-Jordan
Calcular una inversa pequeñaGauss-Jordan

24.18 Estabilidad y errores frecuentes

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:

  • Normalizar solo parte de la fila.
  • Eliminar debajo del pivote, pero olvidar los valores superiores.
  • Usar como pivote un valor cero sin intercambiar filas.
  • Incluir la columna aumentada entre las variables.
  • Confundir una fila nula con una contradicción.
  • No expresar mediante parámetros las variables libres.

24.19 Qué debes recordar de este tema

  • Gauss-Jordan obtiene la forma escalonada reducida.
  • Cada pivote debe valer 1 y ser el único valor no nulo de su columna.
  • El método elimina elementos tanto debajo como encima del pivote.
  • La solución única se lee directamente cuando el bloque izquierdo es la identidad.
  • Una columna sin pivote identifica una variable libre.
  • Una fila [0 ... 0 | c], con c distinto de cero, indica incompatibilidad.
  • La cantidad de pivotes coincide con el rango.
  • El método también permite calcular matrices inversas.

24.20 Conclusión

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.