Toda transformación lineal entre espacios de dimensión finita puede representarse mediante una matriz. Multiplicar esa matriz por las coordenadas de un vector produce las coordenadas de su imagen.
Una transformación lineal queda determinada por su acción sobre una base. Una matriz organiza esas imágenes en columnas y convierte la aplicación de la transformación en una multiplicación.
Esta equivalencia permite utilizar algoritmos matriciales para componer, invertir y analizar transformaciones.
Sea T : ℝn → ℝm. Si e1, ..., en es la base canónica del dominio, la matriz estándar de T es:
Cada T(ej) se coloca como la columna j, no como una fila.
Si la entrada tiene n coordenadas y la salida m, A posee m filas y n columnas:
| Transformación | Tamaño de A |
|---|---|
| ℝ2 → ℝ2 | 2 × 2 |
| ℝ3 → ℝ2 | 2 × 3 |
| ℝ2 → ℝ4 | 4 × 2 |
Sea T(x, y) = (2x − y, x + 3y). Calculamos:
const T = ([x, y]) => [2 * x - y, x + 3 * y];
const e1 = [1, 0];
const e2 = [0, 1];
const columnas = [T(e1), T(e2)];
const A = columnas[0].map((_, fila) => columnas.map(columna => columna[fila]));
console.log(A); // [[2, -1], [1, 3]]
Para v = (4, 2):
function matrizPorVector(A, v) {
if (A.some(fila => fila.length !== v.length)) {
throw new Error("Dimensiones incompatibles");
}
return A.map(fila =>
fila.reduce((suma, valor, i) => suma + valor * v[i], 0)
);
}
const A = [[2, -1], [1, 3]];
console.log(matrizPorVector(A, [4, 2])); // [6, 10]
El resultado coincide con T(4, 2) = (8 − 2, 4 + 6).
Sea T(x, y, z) = (x + 2y − z, 3x + z). Las imágenes canónicas son:
const A = [[1, 2, -1], [3, 0, 1]];
const v = [2, 1, 4];
const imagen = A.map(fila =>
fila.reduce((suma, valor, i) => suma + valor * v[i], 0)
);
console.log(imagen); // [0, 10]
Multiplicar A por ej selecciona su columna j. Esta observación explica por qué la matriz se construye con las imágenes como columnas.
const A = [[2, -1], [1, 3]];
const e1 = [1, 0];
const e2 = [0, 1];
const aplicar = v => A.map(fila => fila.reduce((s, x, i) => s + x * v[i], 0));
console.log(aplicar(e1)); // [2, 1]: primera columna
console.log(aplicar(e2)); // [-1, 3]: segunda columna
function matrizRotacion(grados) {
const theta = grados * Math.PI / 180;
const c = Math.cos(theta);
const s = Math.sin(theta);
return [[c, -s], [s, c]];
}
const R = matrizRotacion(90);
const resultado = R.map(fila => fila[0] * 1 + fila[1] * 0);
console.log(resultado); // aproximadamente [0, 1]
| Transformación | Matriz |
|---|---|
| Reflexión respecto del eje x | [[1, 0], [0, −1]] |
| Proyección sobre el eje x | [[1, 0], [0, 0]] |
| Cizallamiento horizontal | [[1, k], [0, 1]] |
| Cizallamiento vertical | [[1, 0], [k, 1]] |
Las matrices permiten almacenar y aplicar estas transformaciones con el mismo algoritmo.
Podemos generar la base canónica, evaluar T en cada vector y transponer la lista de imágenes para obtener filas.
function matrizDeTransformacion(T, dimensionDominio) {
const base = Array.from({ length: dimensionDominio }, (_, i) =>
Array.from({ length: dimensionDominio }, (_, j) => Number(i === j))
);
const columnas = base.map(T);
const dimensionSalida = columnas[0]?.length ?? 0;
if (!columnas.every(columna => columna.length === dimensionSalida)) {
throw new Error("Las imágenes deben tener igual dimensión");
}
return Array.from({ length: dimensionSalida }, (_, fila) =>
columnas.map(columna => columna[fila])
);
}
const T = ([x, y]) => [2 * x - y, x + 3 * y];
console.log(matrizDeTransformacion(T, 2)); // [[2,-1], [1,3]]
Este procedimiento supone que T es lineal; muestrear la base no demuestra esa propiedad.
Si S(v) = Bv y T(w) = Aw, entonces:
La matriz más cercana al vector se aplica primero. Por eso el orden del producto es importante.
function multiplicar(A, B) {
return A.map(fila => B[0].map((_, j) =>
fila.reduce((suma, valor, k) => suma + valor * B[k][j], 0)
));
}
const escala = [[2, 0], [0, 1]];
const rotacion90 = [[0, -1], [1, 0]];
console.log(multiplicar(rotacion90, escala)); // rotar después de escalar
La transformación identidad se representa con I. Si T es invertible y su matriz es A, la transformación inversa se representa con A-1.
const A = [[2, 0], [0, 4]];
const inversa = [[0.5, 0], [0, 0.25]];
const aplicar = (M, v) => M.map(fila =>
fila.reduce((suma, valor, i) => suma + valor * v[i], 0)
);
const v = [3, 8];
console.log(aplicar(inversa, aplicar(A, v))); // [3, 8]
El núcleo de T es el conjunto de soluciones del sistema homogéneo:
Por tanto, se obtiene reduciendo A y describiendo sus variables libres.
const A = [[1, 2], [2, 4]];
const vectorNucleo = [-2, 1];
const imagen = A.map(fila =>
fila.reduce((suma, valor, i) => suma + valor * vectorNucleo[i], 0)
);
console.log(imagen); // [0, 0]
La imagen de T es el espacio generado por las columnas de A:
Las columnas pivote originales forman una base de la imagen.
const A = [[1, 2], [2, 4], [-1, -2]];
const columna1 = A.map(fila => fila[0]);
const columna2 = A.map(fila => fila[1]);
console.log(columna1); // [1, 2, -1]
console.log(columna2); // [2, 4, -2] = 2 * columna1
// La imagen tiene dimensión 1.
| Propiedad de T : ℝⁿ → ℝᵐ | Criterio matricial |
|---|---|
| Inyectiva | Un pivote en cada columna; rango(A) = n |
| Sobreyectiva | Un pivote en cada fila; rango(A) = m |
| Invertible, si m = n | rango(A) = n, equivalentemente det(A) ≠ 0 |
Una matriz rectangular puede ser inyectiva o sobreyectiva, pero no posee una inversa cuadrada ordinaria.
Sean B = (b1, ..., bn) una base del dominio y C una base del codominio. La columna j de [T]C←B es [T(bj)]C.
La transformación abstracta no cambia; cambia su descripción numérica al elegir otras bases.
Sea T(x, y) = (x, −y), reflexión respecto del eje x, y B = {(1, 1), (1, −1)}.
const matrizEnB = [[0, 1], [1, 0]];
const coordenadasV = [3, 1];
const coordenadasTv = matrizEnB.map(fila =>
fila.reduce((suma, valor, i) => suma + valor * coordenadasV[i], 0)
);
console.log(coordenadasTv); // [1, 3]
Si T : V → V y P convierte coordenadas de una base B a la base canónica, las representaciones se relacionan por:
Las matrices A y [T]B son semejantes: describen la misma transformación desde sistemas de coordenadas diferentes.
const A = [[1, 0], [0, -1]]; // reflexión en base canónica
const P = [[1, 1], [1, -1]]; // columnas de B
const inversaP = [[0.5, 0.5], [0.5, -0.5]];
const multiplicar = (X, Y) => X.map(fila => Y[0].map((_, j) =>
fila.reduce((suma, valor, k) => suma + valor * Y[k][j], 0)
));
console.log(multiplicar(multiplicar(inversaP, A), P));
// [[0, 1], [1, 0]]
La matriz de una transformación reúne en sus columnas el efecto sobre una base. Gracias a esta representación, aplicar y componer funciones lineales se reduce a multiplicar matrices y vectores.
En el próximo tema estudiaremos los valores propios, escalares que describen direcciones cuya orientación se conserva bajo una transformación.