Matrices
Si los vectores son los átomos del álgebra lineal, las matrices son las moléculas. Son la herramienta fundamental para representar transformaciones, resolver sistemas de ecuaciones y manipular datos estructurados.
Concepto
Al igual que con los vectores, el concepto de "matriz" puede referirse a distintas ideas según el contexto.
Nota histórica
El término "matriz" fue introducido por James Joseph Sylvester en 1850. Sin embargo, el desarrollo sistemático de la teoría de matrices se atribuye a Arthur Cayley, quien en 1858 publicó "A Memoir on the Theory of Matrices", estableciendo las reglas de la aritmética matricial que usamos hoy.
Matriz en programación
Para un programador, una matriz es simplemente un array bidimensional (un array de arrays). Es una tabla de datos organizada en filas y columnas.
public class MatrixExample { public static void main(String[] args) { // Una matriz de 2x3 (2 filas, 3 columnas) double[][] matrix = { {1.0, 2.0, 3.0}, {4.0, 5.0, 6.0} }; // Acceder al elemento en fila 1, columna 2 System.out.println(matrix[1][2]); // 6.0 // Imprimir la matriz completa for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { System.out.print(matrix[i][j] + " "); } System.out.println(); } }}Matriz en geometría: Transformaciones del espacio
Aquí es donde las matrices revelan su verdadero poder. Geométricamente, una matriz representa una transformación del espacio.
Mientras que un vector es un punto (o flecha) en el espacio, una matriz es una instrucción de cómo mover, rotar o deformar ese punto.
- Una matriz puede rotar vectores
- Una matriz puede escalar (estirar o encoger) vectores
- Una matriz puede reflejar vectores (como un espejo)
- Una matriz puede proyectar vectores (reducir dimensiones)
Intuición clave
Piensa en una matriz como una "función" que toma un vector como entrada y produce otro vector transformado como salida.
Cada entrada produce una salida diferente, pero la "regla de transformación" (la matriz) permanece igual.
Representación matemática de una matriz
Una matriz de dimensión tiene filas y columnas:
Cada elemento representa el valor en la fila y columna .
Ejemplos de dimensiones:
| Dimensión | Nombre | Uso común |
|---|---|---|
| Cuadrada pequeña | Transformaciones 2D | |
| Cuadrada | Transformaciones 3D, rotaciones | |
| Rectangular | Datos tabulares, sistemas de ecuaciones | |
| Vector fila | Una observación con características | |
| Vector columna | observaciones de una variable |
Representando imágenes como matrices
Una aplicación natural de las matrices es la representación de imágenes digitales. Una imagen en escala de grises puede verse como una matriz donde cada elemento representa la intensidad de un píxel (0 = negro, 255 = blanco).
Por ejemplo, una imagen simple de píxeles:
Esta matriz representa una imagen dividida en cuadrantes: negro arriba-izquierda, blanco arriba-derecha, blanco abajo-izquierda, y negro abajo-derecha.
Para imágenes a color, se utilizan tres matrices (una por cada canal: Rojo, Verde, Azul), formando lo que se conoce como un tensor de dimensión .
Operaciones con Matrices
Para que las matrices sean útiles, necesitamos operar con ellas. Empecemos por las más sencillas.
1. Suma de matrices
Solo podemos sumar matrices si tienen las mismas dimensiones. Sumamos elemento a elemento.
Ejemplo en Minerva:
import com.minerva.core.primitives.Matrix; public class Main { public static void main(String[] args) { Matrix A = new Matrix(new double[][]{ {1, 2}, {3, 4} }); Matrix B = new Matrix(new double[][]{ {5, 6}, {7, 8} }); Matrix C = A.add(B); System.out.println("A + B = \n" + C); }}A + B =[6, 8][10, 12]
2. Multiplicación por escalar
Multiplicamos cada elemento de la matriz por un número.
Esto "escala" toda la matriz uniformemente.
En Minerva, esta operación se puede realizar elemento a elemento multiplicando cada entrada de la matriz.
3. Transpuesta
La transpuesta de una matriz (denotada ) consiste en intercambiar filas por columnas. Lo que era la fila 1 se convierte en la columna 1.
Si (dimensión ), entonces:
Nota que tiene dimensión .
Propiedades importantes:
- — transponer dos veces devuelve la original
- — la transpuesta distribuye sobre la suma
- — ¡el orden se invierte!
Matrix A = new Matrix(new double[][]{ {1, 2, 3}, {4, 5, 6} });Matrix At = A.transpose();System.out.println("Original: " + A.rows() + "x" + A.cols());System.out.println("Transpuesta: " + At.rows() + "x" + At.cols());Original: 2x3Transpuesta: 3x2
4. Multiplicación de matrices
Esta es la operación más importante del álgebra lineal. A diferencia de la suma, no multiplicamos elemento a elemento.
Para multiplicar :
- Tomamos una fila de
- Tomamos una columna de
- Calculamos su producto punto (como vimos en la sección de vectores)
- Ese resultado va en la posición correspondiente
Requisito de dimensión: Para multiplicar una matriz por una , necesitamos que . El resultado tendrá dimensión .
Veamos un ejemplo paso a paso:
Para calcular el elemento (fila 1, columna 1):
Repitiendo para todos los elementos:
Matrix A = new Matrix(new double[][]{ {1, 2}, {3, 4} });Matrix B = new Matrix(new double[][]{ {5, 6}, {7, 8} });Matrix C = A.multiply(B);System.out.println("A × B = \n" + C);A × B =[19, 22][43, 50]
¡El orden importa!
En matrices, el orden de multiplicación importa.
De hecho, a veces ni siquiera se puede calcular si las dimensiones no coinciden. Esto es muy diferente a los números, donde .
Transformaciones geométricas
Las matrices nos permiten describir matemáticamente cómo transformar puntos en el espacio. Cada tipo de transformación tiene una matriz característica.
Rotación
La matriz de rotación para un ángulo (en sentido antihorario) es:
Ejemplo: Rotar el vector un ángulo de 90° ():
El vector que apuntaba a la derecha ahora apunta hacia arriba .
Algunas rotaciones comunes:
| Ángulo | Matriz | ||
|---|---|---|---|
| 0° | 1 | 0 | |
| 90° | 0 | 1 | |
| 180° | -1 | 0 | |
| 270° | 0 | -1 |
Escalado
La matriz de escalado multiplica cada componente por un factor:
- Si : escalado uniforme (agranda o encoge proporcionalmente)
- Si : escalado no uniforme (estira en una dirección)
- Si : encoge
- Si : agranda
- Si : refleja además de escalar
Ejemplo: Duplicar el tamaño de un vector:
Reflexión
Las matrices de reflexión "voltean" los vectores respecto a un eje.
Reflexión respecto al eje X (voltea verticalmente):
Reflexión respecto al eje Y (voltea horizontalmente):
Reflexión respecto al origen (voltea en ambos ejes):
Reflexión respecto a la diagonal :
Ejemplo: Reflejar respecto al eje X:
Cizallamiento (Shear)
El cizallamiento "inclina" las figuras manteniendo el área constante.
Cizallamiento horizontal (inclina a lo largo de X):
Cizallamiento vertical (inclina a lo largo de Y):
Ejemplo: Aplicar cizallamiento horizontal con a :
Composición de transformaciones
Lo poderoso de las matrices es que podemos combinar transformaciones multiplicándolas:
Orden de aplicación
Las transformaciones se aplican de derecha a izquierda. Si queremos primero rotar y luego escalar:
Se lee: "aplica primero, luego ".
Ejemplo: Rotar 45° y luego escalar 2x:
Implementación en Java utilizando Minerva
package com.minerva; import com.minerva.core.primitives.Matrix;import com.minerva.core.primitives.Vector; /*** Biblioteca de transformaciones geométricas 2D.*/public class Transformer { /** * Crea una matriz de rotación. * @param angleDegrees Ángulo en grados (antihorario) */ public static Matrix rotation(double angleDegrees) { double rad = Math.toRadians(angleDegrees); return new Matrix(new double[][]{ {Math.cos(rad), -Math.sin(rad)}, {Math.sin(rad), Math.cos(rad)} }); } /** * Crea una matriz de escalado. * @param sx Factor de escala en X * @param sy Factor de escala en Y */ public static Matrix scale(double sx, double sy) { return new Matrix(new double[][]{ {sx, 0}, {0, sy} }); } /** * Crea una matriz de reflexión respecto al eje X. */ public static Matrix reflectX() { return new Matrix(new double[][]{ {1, 0}, {0, -1} }); } /** * Crea una matriz de reflexión respecto al eje Y. */ public static Matrix reflectY() { return new Matrix(new double[][]{ {-1, 0}, {0, 1} }); } /** * Crea una matriz de cizallamiento horizontal. * @param k Factor de cizallamiento */ public static Matrix shearX(double k) { return new Matrix(new double[][]{ {1, k}, {0, 1} }); } /** * Aplica una transformación a un vector. */ public static Vector apply(Matrix transform, Vector v) { return transform.multiply(v); }}Vector original: [1.0, 0.0]Rotado 90°: [0.0, 1.0]Escalado 2x: [2.0, 0.0]Rotar 45° + Escalar 2x: [1.41, 1.41]Reflexión de (3,4) en eje X: [3.0, -4.0]
Matrices especiales
Hay algunas matrices con propiedades únicas que aparecen constantemente en matemáticas y aplicaciones.
Matriz identidad
La matriz identidad es como el "1" de las matrices: no cambia nada cuando multiplicas.
Es una matriz cuadrada con 1s en la diagonal y 0s en el resto:
Geométricamente, la matriz identidad es la transformación "no hacer nada".
Matrix I = Matrix.identity(3);Matrix A = new Matrix(new double[][]{{1,2,3},{4,5,6},{7,8,9}});Matrix result = I.multiply(A);// result es igual a AMatriz inversa
La inversa de (denotada ) es la matriz que "deshace" lo que hace:
Es como la división para matrices. Si rota 30°, entonces rota -30°.
No todas las matrices tienen inversa
Solo las matrices cuadradas pueden tener inversa, y no todas la tienen. Una matriz sin inversa se llama singular o no invertible. Esto ocurre cuando la matriz "colapsa" el espacio (por ejemplo, proyecta 3D a una línea).
Para una matriz :
El valor se llama determinante, y si es cero, la matriz no tiene inversa.
Nota computacional
La fórmula anterior es útil para entender el concepto, pero no es como se calcula en la práctica. Para matrices grandes, calcular el determinante con la fórmula de Leibniz o por cofactores tiene complejidad , lo cual es prohibitivo.
En implementaciones reales (incluyendo Minerva), se utilizan métodos como la descomposición LU, que tienen complejidad y son numéricamente más estables.
Matrix A = new Matrix(new double[][]{{4, 7}, {2, 6}});Matrix Ainv = A.inv();Matrix identity = A.multiply(Ainv);// identity es aproximadamente IMatriz diagonal
Una matriz donde solo la diagonal tiene valores distintos de cero:
Las matrices diagonales son muy eficientes: multiplicar por ellas solo escala cada componente del vector.
Matriz simétrica
Una matriz es simétrica si (es igual a su transpuesta):
Las matrices simétricas aparecen naturalmente en problemas de optimización y tienen propiedades especiales (todos sus autovalores son reales).
Ejemplo práctico: Sistemas de ecuaciones lineales
Una de las aplicaciones más importantes de las matrices es resolver sistemas de ecuaciones lineales.
El problema
Considera este sistema:
Podemos escribirlo en forma matricial:
O sea:
La solución
Si tiene inversa, la solución es:
package com.minerva; import com.minerva.core.primitives.Matrix;import com.minerva.core.primitives.Vector; public class LinearSystem { public static void main(String[] args) { // Sistema: // 2x + 3y = 8 // 4x + y = 6 Matrix A = new Matrix(new double[][]{ {2, 3}, {4, 1} }); Vector b = new Vector(new double[]{8, 6}); System.out.println("Sistema Ax = b"); System.out.println("A ="); System.out.println(A); System.out.println("b = " + b); // Resolver: x = A^(-1) * b // Forma recomendada: usar solve() directamente Vector solution = A.solve(b); System.out.println("Solución:"); System.out.printf("x = %.2f%n", solution.get(0)); System.out.printf("y = %.2f%n", solution.get(1)); // Verificar System.out.println("Verificación:"); System.out.printf("2(%.0f) + 3(%.0f) = %.0f (esperado: 8)%n", solution.get(0), solution.get(1), 2*solution.get(0) + 3*solution.get(1)); System.out.printf("4(%.0f) + 1(%.0f) = %.0f (esperado: 6)%n", solution.get(0), solution.get(1), 4*solution.get(0) + solution.get(1)); }}Sistema Ax = bA =[2, 3][4, 1]b = [8, 6]Solución:x = 1.00y = 2.00Verificación:2(1) + 3(2) = 8 (esperado: 8)4(1) + 1(2) = 6 (esperado: 6)
Problema aplicado: Optimización de producción
Los sistemas de ecuaciones lineales aparecen naturalmente en problemas de optimización. Veamos un problema clásico estilo los libros de álgebra lineal de Grossman.
El problema
Una fábrica produce dos tipos de productos: mesas y sillas. Cada producto requiere tiempo en dos máquinas:
| Producto | Máquina A (horas) | Máquina B (horas) | Ganancia ($) |
|---|---|---|---|
| Mesa | 2 | 1 | 40 |
| Silla | 1 | 2 | 30 |
| Disponible | 100 horas | 80 horas | — |
Pregunta: ¿Cuántas mesas () y sillas () debe producir para maximizar la ganancia?
Formulación matemática
Función objetivo (lo que queremos maximizar):
Restricciones (lo que debemos cumplir):
Representación matricial
Las restricciones se pueden escribir como :
Solución: Encontrar los vértices
En programación lineal, el óptimo siempre está en un vértice de la región factible. Los vértices se encuentran resolviendo sistemas de ecuaciones.
Vértice 1: Intersección de y
Usando la inversa:
Otros vértices de la región factible:
- : origen
- : solo mesas, máquina A al límite
- : solo sillas, máquina B al límite
- : la intersección que calculamos
Evaluando la función objetivo en cada vértice:
| Vértice | |
|---|---|
Solución óptima: Producir 40 mesas y 20 sillas para una ganancia máxima de $2,200.
package com.minerva; import com.minerva.core.primitives.Matrix;import com.minerva.core.primitives.Vector; /*** Resuelve el problema de optimización de producción* encontrando la intersección de las restricciones.*/public class ProductionOptimizer { public static void main(String[] args) { // Matriz de restricciones (cuando son igualdades) // 2x + y = 100 (Máquina A al límite) // x + 2y = 80 (Máquina B al límite) Matrix A = new Matrix(new double[][]{ {2, 1}, {1, 2} }); Vector b = new Vector(new double[]{100, 80}); System.out.println("=== Problema de Optimización ==="); System.out.println("Maximizar: Z = 40x + 30y"); System.out.println("Sujeto a: 2x + y ≤ 100"); System.out.println(" x + 2y ≤ 80"); System.out.println(); // Encontrar punto de intersección Vector intersection = A.solve(b); double x = intersection.get(0); double y = intersection.get(1); System.out.println("Intersección de restricciones:"); System.out.printf("x = %.0f mesas%n", x); System.out.printf("y = %.0f sillas%n", y); // Evaluar función objetivo en todos los vértices double[][] vertices = {{0, 0}, {50, 0}, {0, 40}, {x, y}}; String[] names = {"(0,0)", "(50,0)", "(0,40)", String.format("(%.0f,%.0f)", x, y)}; System.out.println("\nEvaluación de vértices:"); double maxZ = Double.NEGATIVE_INFINITY; String bestVertex = ""; for (int i = 0; i < vertices.length; i++) { double xi = vertices[i][0]; double yi = vertices[i][1]; double Z = 40 * xi + 30 * yi; System.out.printf("%s: Z = $%.0f%n", names[i], Z); if (Z > maxZ) { maxZ = Z; bestVertex = names[i]; } } System.out.printf("\n>>> Solución óptima: %s con ganancia $%.0f%n", bestVertex, maxZ); }}=== Problema de Optimización ===Maximizar: Z = 40x + 30ySujeto a: 2x + y ≤ 100x + 2y ≤ 80Intersección de restricciones:x = 40 mesasy = 20 sillasEvaluación de vértices:(0,0): Z = 0(50,0): Z = 2000(0,40): Z = 1200(40,20): Z = 2200Solución óptima: (40,20) con ganancia 2200
Conexión con álgebra lineal
En este problema, las matrices nos permiten:
- Representar restricciones de forma compacta:
- Encontrar intersecciones resolviendo con la inversa
- Escalar a problemas grandes: con variables y restricciones, las técnicas matriciales son esenciales
Aplicaciones de los sistemas lineales
| Aplicación | Descripción |
|---|---|
| Regresión lineal | Encontrar la mejor línea/plano que ajusta datos |
| Balanceo de ecuaciones químicas | Encontrar coeficientes estequiométricos |
| Análisis de circuitos | Ley de Kirchhoff produce sistemas lineales |
| Economía | Modelos de entrada-salida de Leontief |
| Gráficos 3D | Transformaciones y proyecciones de cámara |
Bonus: Definición formal de matriz
Advertencia
Esta sección es para lectores con interés en matemáticas puras. Puedes saltarla sin perder continuidad.
Matrices como funciones lineales
Formalmente, una matriz representa una transformación lineal .
Una transformación es lineal si cumple:
- Aditividad:
- Homogeneidad:
Toda matriz define una transformación lineal, y toda transformación lineal puede representarse con una matriz (una vez elegida una base).
Espacio de matrices
El conjunto de todas las matrices de con entradas reales, denotado , forma un espacio vectorial (como mencionamos en la documentación sobre vectores, donde vimos que las matrices también pueden ser "vectores" en un sentido abstracto).
- Dimensión: (una matriz tiene 12 "componentes")
- Suma: elemento a elemento
- Escalar: multiplicar cada elemento
Propiedades algebraicas
Para matrices y escalares :
| Propiedad | Expresión |
|---|---|
| Asociatividad de suma | |
| Conmutatividad de suma | |
| Elemento neutro | |
| Asociatividad de producto | |
| Distributividad izquierda | |
| Distributividad derecha | |
| Compatibilidad escalar |
Nota importante: el producto no es conmutativo ( en general).
El rango de una matriz
El rango de una matriz es el número de filas (o columnas) linealmente independientes. Indica cuánta "información" contiene la matriz.
- Si : la matriz tiene rango completo
- Si : la matriz es deficiente en rango
El rango determina si un sistema de ecuaciones tiene solución única, infinitas soluciones, o ninguna solución.
Resumen
| Concepto | Descripción | Notación |
|---|---|---|
| Matriz | Arreglo rectangular de números | |
| Suma | Elemento a elemento (mismas dimensiones) | |
| Producto escalar | Multiplicar cada elemento | |
| Transpuesta | Intercambiar filas y columnas | |
| Multiplicación | Filas × columnas (producto punto) | |
| Identidad | No cambia al multiplicar | |
| Inversa | Deshace la transformación |
Las matrices son el lenguaje fundamental para describir transformaciones lineales, resolver sistemas de ecuaciones y estructurar datos multidimensionales.