Álgebra lineal numérica · Tema 15

Sistemas lineales y eliminación de Gauss

Cómo transformar un sistema de ecuaciones en una matriz triangular y recuperar sus incógnitas mediante un algoritmo sistemático, verificable y programable.

01 · El problema

Varias ecuaciones, una solución común

Un sistema lineal reúne ecuaciones cuyas incógnitas aparecen elevadas a la primera potencia. Por ejemplo:

2x + y − z = 8
−3x − y + 2z = −11
−2x + y + 2z = −3

Resolverlo significa encontrar valores de x, y y z que satisfagan simultáneamente las tres ecuaciones. Estos sistemas aparecen en circuitos, estructuras, gráficos, ajuste de datos, simulaciones, optimización y discretización de ecuaciones diferenciales.

02 · Representación

De las ecuaciones a Ax=b

Los coeficientes se organizan en una matriz A, las incógnitas en un vector x y los términos independientes en un vector b:

A x = b
A = [ 2   1   −1 ;   −3   −1   2 ;   −2   1   2 ]
x = [ x   y   z ]ᵀ    b = [ 8   −11   −3 ]ᵀ

La matriz aumentada coloca b como una columna adicional:

[ A | b ] = [ 2   1   −1 | 8 ;   −3   −1   2 | −11 ;   −2   1   2 | −3 ]

Guardar únicamente números evita repetir los nombres de las variables y facilita aplicar el mismo algoritmo a sistemas de cualquier tamaño.

03 · Equivalencia

Operaciones elementales por filas

Podemos transformar la matriz aumentada sin cambiar su conjunto de soluciones mediante tres operaciones:

Intercambiar filas
Fᵢ ↔ Fⱼ. Cambia el orden de las ecuaciones.
Multiplicar una fila
Fᵢ ← cFᵢ, con c≠0. Escala una ecuación.
Sumar un múltiplo
Fᵢ ← Fᵢ+cFⱼ. Combina dos ecuaciones.
Conservar equivalencia
Cada operación es reversible, por lo que no crea ni elimina soluciones.

Gauss utiliza principalmente la tercera operación para crear ceros debajo de la diagonal principal.

04 · Primera fase

Eliminación hacia adelante

En la columna k, el elemento diagonal a[k][k] actúa como pivote. Para anular el elemento a[i][k] de una fila inferior calculamos:

mik = aik / akk
Fi ← Fi − mikFk

Al repetir el proceso columna por columna obtenemos un sistema triangular superior:

[ u₁₁   u₁₂   u₁₃ | c₁ ;   0   u₂₂   u₂₃ | c₂ ;   0   0   u₃₃ | c₃ ]
  1. 1
    Seleccionar el pivote.

    Comenzar en la primera posición diagonal disponible.

  2. 2
    Calcular multiplicadores.

    Uno por cada fila situada debajo del pivote.

  3. 3
    Actualizar filas.

    Restar el múltiplo apropiado desde la columna actual hasta el término independiente.

  4. 4
    Avanzar.

    Repetir sobre la submatriz inferior derecha.

05 · Ejemplo manual

Triangularizar un sistema de 3×3

Partimos de:

[ 2   1   −1 | 8 ;   −3   −1   2 | −11 ;   −2   1   2 | −3 ]

Usamos el primer pivote, 2. Para la segunda fila, m₂₁=−3/2; para la tercera, m₃₁=−1:

F₂ ← F₂ + (3/2)F₁
F₃ ← F₃ + F₁
[ 2   1   −1 | 8 ;   0   1/2   1/2 | 1 ;   0   2   1 | 5 ]

Ahora 1/2 es el segundo pivote. Como m₃₂=2/(1/2)=4:

F₃ ← F₃ − 4F₂
[ 2   1   −1 | 8 ;   0   1/2   1/2 | 1 ;   0   0   −1 | 1 ]

La matriz ya es triangular superior. Todavía no terminamos: falta recuperar las incógnitas.

06 · Segunda fase

Sustitución regresiva

La última ecuación contiene una sola incógnita. Después de resolverla, sustituimos su valor en la fila anterior y continuamos hacia arriba:

xi = (ci − Σj=i+1n−1 uijxj) / uii

En el ejemplo:

  1. −z=1, por lo tanto z=−1.
  2. (1/2)y+(1/2)(−1)=1, por lo tanto y=3.
  3. 2x+3−(−1)=8, por lo tanto x=2.
solución: (x,y,z) = (2,3,−1)

07 · Implementación

Eliminación de Gauss en JavaScript

La siguiente versión educativa copia sus entradas, comprueba dimensiones y rechaza un pivote nulo o demasiado pequeño. El intercambio automático de filas se estudiará en el próximo tema.

function gauss(A, b, toleranciaPivote = 1e-12) {
  const n = A.length;
  if (n === 0 || b.length !== n || A.some(fila => fila.length !== n)) {
    throw new Error("Dimensiones incompatibles");
  }
  if (A.some(fila => fila.some(valor => !Number.isFinite(valor)))
      || b.some(valor => !Number.isFinite(valor))) {
    throw new Error("Todos los coeficientes deben ser finitos");
  }

  // Copiar para no modificar los datos recibidos.
  const M = A.map((fila, i) => [...fila, b[i]]);

  // Eliminación hacia adelante.
  for (let k = 0; k < n - 1; k++) {
    const pivote = M[k][k];
    if (!Number.isFinite(pivote) || Math.abs(pivote) <= toleranciaPivote) {
      throw new Error(`Pivote inadecuado en la columna ${k}`);
    }

    for (let i = k + 1; i < n; i++) {
      const multiplicador = M[i][k] / pivote;
      M[i][k] = 0;
      for (let j = k + 1; j <= n; j++) {
        M[i][j] -= multiplicador * M[k][j];
      }
    }
  }

  // Sustitución regresiva.
  const x = Array(n).fill(0);
  for (let i = n - 1; i >= 0; i--) {
    if (!Number.isFinite(M[i][i]) || Math.abs(M[i][i]) <= toleranciaPivote) {
      throw new Error(`No hay pivote válido en la fila ${i}`);
    }
    let suma = 0;
    for (let j = i + 1; j < n; j++) suma += M[i][j] * x[j];
    x[i] = (M[i][n] - suma) / M[i][i];
  }
  return { solucion: x, triangular: M };
}

const A = [[2, 1, -1], [-3, -1, 2], [-2, 1, 2]];
const b = [8, -11, -3];
console.log(gauss(A, b).solucion); // [2, 3, -1]

08 · Lectura del código

Qué representan k, i y j

Índices de la fase de eliminación.
ÍndiceRecorreFunción
kColumnas pivoteDetermina la etapa de eliminación.
iFilas inferioresSelecciona la fila donde se creará un cero.
jColumnas restantesActualiza coeficientes y término independiente.

La asignación M[i][k]=0 impone el valor que matemáticamente debería resultar de la resta. Esto evita conservar un pequeño residuo de redondeo, como 2.22e−16, en una posición estructuralmente nula.

09 · Escalabilidad

Costo computacional y memoria

La eliminación contiene tres recorridos anidados cuyo tamaño disminuye en cada etapa. Su operación dominante requiere aproximadamente:

(2/3)n³ operaciones aritméticas

La sustitución regresiva utiliza aproximadamente n² operaciones. Para valores grandes de n, domina el término cúbico de la eliminación:

T(n) = O(n³)     memoria = O(n²)
Efecto aproximado de duplicar el tamaño.
TamañoTrabajo relativoMemoria relativa
n11
2naprox. 8aprox. 4
4naprox. 64aprox. 16

Las matrices dispersas, con gran cantidad de ceros, suelen requerir estructuras y algoritmos especializados para evitar almacenar y operar sobre todos los elementos.

10 · Existencia y unicidad

Una, ninguna o infinitas soluciones

Durante la eliminación pueden aparecer filas que revelan la naturaleza del sistema:

Solución única
Hay un pivote válido para cada incógnita y la sustitución regresiva determina todos los valores.
Sistema incompatible
Una fila [0 0 … 0 | c] con c≠0 representa la contradicción 0=c.
Infinitas soluciones
Una fila completamente nula y menos pivotes que incógnitas deja una o más variables libres.
Caso numérico
En coma flotante, «cero» significa una magnitud pequeña respecto de una escala elegida.

11 · Límite del método básico

Un pivote cero no siempre significa que no hay solución

Consideremos:

0x + 2y = 4
x + y = 3

La primera posición diagonal es cero, pero el sistema tiene la solución (1,2). Basta intercambiar las ecuaciones antes de eliminar:

F₁ ↔ F₂

También conviene evitar pivotes extremadamente pequeños, porque producen multiplicadores grandes y amplifican errores de redondeo. El pivoteo parcial elige, en cada columna, una fila con coeficiente de mayor magnitud.

En el tema siguiente estudiaremos esta estrategia y la factorización PA=LU de forma detallada.

12 · Verificación numérica

Calcular el vector residuo

Después de obtener una aproximación x̃, calculamos:

r = b − Ax̃

Una norma del residuo resume la discrepancia. La norma infinito toma el mayor valor absoluto:

||r||∞ = max |rᵢ|
function residuoInfinito(A, x, b) {
  let maximo = 0;
  for (let i = 0; i < A.length; i++) {
    let producto = 0;
    for (let j = 0; j < x.length; j++) producto += A[i][j] * x[j];
    maximo = Math.max(maximo, Math.abs(b[i] - producto));
  }
  return maximo;
}

const A = [[2, 1, -1], [-3, -1, 2], [-2, 1, 2]];
const b = [8, -11, -3];
console.log(residuoInfinito(A, [2, 3, -1], b)); // 0

Un residuo pequeño es necesario, pero no siempre garantiza un error pequeño en x. En sistemas mal condicionados, pequeñas perturbaciones pueden cambiar mucho la solución.

13 · Coma flotante

Redondeo, escala y condicionamiento

En aritmética exacta, las operaciones por filas preservan perfectamente la solución. En una computadora, cada suma, multiplicación y división puede redondearse.

  • Un pivote pequeño genera un multiplicador potencialmente grande.
  • Restar números cercanos puede causar cancelación.
  • Coeficientes con escalas muy diferentes dificultan elegir una tolerancia absoluta.
  • Un sistema mal condicionado amplifica perturbaciones en datos y cálculos.

No debemos decidir si un valor es cero mediante valor === 0. Una prueba escalada compara su magnitud con una tolerancia y con los coeficientes relevantes.

|pivote| ≤ ε · escala    ⇒    pivote numéricamente pequeño

14 · Exploración interactiva

Laboratorio: observar la matriz durante la eliminación

Elegí un sistema, una política de pivote y una etapa. El gráfico muestra la matriz aumentada; la celda dorada es el pivote y la fila resaltada es la que se modifica.

EXPERIMENTO 15

Operaciones por filas paso a paso

Sistema clásico 3×3

Los resultados numéricos aparecen debajo.
OperaciónMatriz inicial
EstadoEliminando
SoluciónPendiente
Residuo ∞—

Mové el control de etapa para seguir las operaciones por filas.

Preguntas para explorar

  1. En el sistema clásico, identificá los multiplicadores de cada operación.
  2. En «Requiere intercambio», compará ambas políticas de pivote.
  3. Observá la última fila de los sistemas sin solución y con infinitas soluciones.
  4. En «Pivotes pequeños», compará el tamaño de los números intermedios.

15 · Comprensión

Confusiones frecuentes

«Gauss calcula la inversa de A»

No es necesario calcular A⁻¹. El método transforma directamente el sistema y suele ser más eficiente y preciso que formar la inversa para luego multiplicarla por b.

«Un pivote cero demuestra que el sistema no tiene solución»

Puede bastar con intercambiar filas. La clasificación depende de la estructura resultante, no de una única posición diagonal.

«La matriz de entrada puede modificarse sin avisar»

Modificarla reduce memoria, pero es un efecto lateral. Una función reutilizable debe documentarlo o trabajar sobre una copia.

«Un residuo pequeño garantiza una solución muy exacta»

En un sistema mal condicionado puede coexistir un residuo pequeño con un error apreciable en las incógnitas.

«O(n³) significa que siempre será lento»

Describe el crecimiento asintótico. El tiempo real depende del tamaño, hardware, implementación, estructura de la matriz y cantidad de sistemas a resolver.

16 · Práctica guiada

Ejercicios

Ejercicio 1: una eliminación

Para [2 1 | 5; 4 3 | 11], anulá el primer elemento de la segunda fila.

Ver solución

El multiplicador es m₂₁=4/2=2. Aplicando F₂←F₂−2F₁ se obtiene [0 1 | 1].

Ejercicio 2: sustitución regresiva

Resolvé el sistema triangular 3x−y+2z=7, 2y+z=5, 4z=8.

Ver solución razonada

z=2; luego 2y+2=5, así que y=1.5; finalmente 3x−1.5+4=7, de donde x=1.5.

Ejercicio 3: clasificar una fila

¿Qué indica la fila aumentada [0 0 0 | 4]?

Ver solución

Representa 0=4, una contradicción. El sistema es incompatible y no tiene solución.

Ejercicio 4: costo

Si el tamaño del sistema se duplica, ¿cómo cambian aproximadamente el trabajo y la memoria de una matriz densa?

Ver solución

El trabajo cúbico se multiplica aproximadamente por 2³=8; la memoria cuadrática se multiplica por 2²=4.

Ejercicio 5: multiplicación matriz-vector

Implementá una función que calcule Ax y valide las dimensiones.

Ver una posible solución
function matrizPorVector(A, x) {
  if (!Array.isArray(A) || A.some(fila => fila.length !== x.length)) {
    throw new Error("Dimensiones incompatibles");
  }
  return A.map(fila =>
    fila.reduce((suma, valor, j) => suma + valor * x[j], 0)
  );
}

console.log(matrizPorVector([[2, 1], [4, 3]], [2, 1])); // [5, 11]

17 · Síntesis

Ideas para recordar

  • Un sistema lineal se representa de forma compacta como Ax=b.
  • Las operaciones elementales por filas conservan el conjunto de soluciones.
  • La eliminación hacia adelante crea una matriz triangular superior.
  • La sustitución regresiva recupera las incógnitas desde la última fila.
  • La eliminación densa requiere tiempo O(n³) y memoria O(n²).
  • Las filas finales permiten distinguir solución única, incompatibilidad e infinitas soluciones.
  • Un pivote cero puede resolverse mediante intercambio de filas.
  • El residuo b−Ax̃ sirve para comprobar la solución calculada.
  • El redondeo y el condicionamiento forman parte del problema numérico.

En el próximo tema reforzaremos la eliminación mediante pivoteo y separaremos el proceso en una factorización LU reutilizable.