Saltar al contenido
Guía de Varlig
Inicio de Varlig

Vectores y matrices

Un vector es una lista plana de números, como una dirección en el espacio o un conjunto de cantidades. Una matriz es una lista de filas. Esta página trata el producto escalar y el vectorial, la multiplicación de matrices, determinantes e inversas, la resolución de varias ecuaciones lineales a la vez y las herramientas numéricas del álgebra lineal: valores propios y las descomposiciones QR, LU y en valores singulares.

Te servirá para ejercicios de álgebra lineal, geometría y transformaciones, o cualquier problema con varias incógnitas relacionadas mediante ecuaciones lineales. Los vectores y las matrices son listas normales, así que todo lo que se explica en Listas y estadística, como los índices, también se aplica.

Vectores

calc
dot([1, 2, 3], [4, 5, 6]) da 32
dot([3, 4], [4, -3]) da 0
cross([1, 0, 0], [0, 1, 0]) da [0, 0, 1]
cross([1, 2, 3], [4, 5, 6]) da [-3, 6, -3]
v = [3, 4]
sqrt(dot(v, v)) da 5

dot multiplica los elementos correspondientes y suma los resultados. Un producto escalar igual a cero significa que los dos vectores son perpendiculares, como [3, 4] y [4, -3]. cross da un vector perpendicular a los dos vectores de entrada: la dirección x por la dirección y da la dirección z. La longitud de un vector es la raíz cuadrada de su producto escalar consigo mismo.

dot necesita dos vectores de la misma longitud, y cross, dos vectores de tres elementos. Para sumar vectores o multiplicarlos por un escalar, usa la aritmética normal de listas: [1, 2] + [3, 4] es [4, 6] y 2 * [3, 4] es [6, 8].

Escribir y multiplicar matrices

Escribe una matriz como una lista de filas, cada una entre sus propios corchetes:

calc
shape([[1, 2, 3], [4, 5, 6]]) da [2, 3]
transpose([[1, 2, 3], [4, 5, 6]]) da [[1, 4], [2, 5], [3, 6]]
identity(3) da [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
[[1, 2], [3, 4]] * [[5, 6], [7, 8]] da [[19, 22], [43, 50]]

shape da [filas, columnas]. transpose intercambia filas y columnas. identity(n) es la matriz de n por n que deja otra matriz sin cambios al multiplicarla por ella.

* entre dos matrices es la multiplicación de matrices, que requiere que la matriz de la izquierda tenga tantas columnas como filas tiene la de la derecha. Para multiplicar una matriz por un vector, escribe el vector como columna, con un elemento por fila:

calc
# Gira el punto (3, 1) 90° en sentido antihorario
girar = [[0, -1], [1, 0]]
girar * [[3], [1]] da [[-1], [3]]
girar * girar da [[-1, 0], [0, -1]]

Girar dos veces 90° da media vuelta, y por eso girar * girar cambia ambos signos. Una lista plana como [3, 1] no se acepta a la derecha de una matriz. Si tienes una lista plana en un nombre, transpose([v]) la convierte en columna.

Las matrices de la misma forma se pueden sumar y restar, y multiplicar o dividir por un número, como las demás listas.

Algunas reglas se aplican a todas las operaciones con matrices:

  • Todas las filas deben tener el mismo número de elementos.
  • Los elementos deben ser números sin unidades. No se aceptan unidades ni dinero.
  • Una matriz puede tener como máximo 32 filas y 32 columnas.
  • No existe la forma abreviada con punto y coma. Escribe [[1, 2], [3, 4]], no [1, 2; 3, 4].

Determinante, inversa, traza y rango

calc
M = [[2, 1], [5, 3]]
det(M) da 1
inverse(M) da [[3, -1], [-5, 2]]
M * inverse(M) da [[1, 0], [0, 1]]
trace(M) da 5
inverse([[2, 1], [1, 3]]) da [[0.6, -0.2], [-0.2, 0.4]]
det([[1, 2], [2, 4]]) da 0
rank([[1, 2, 3], [2, 4, 6]]) da 1

det, inverse y trace (la suma de la diagonal) necesitan una matriz cuadrada. Un determinante igual a cero significa que la matriz es singular: sus filas no son independientes, así que no tiene inversa, e inverse([[1, 2], [2, 4]]) da un error. rank cuenta cuántas filas son independientes, y también acepta matrices que no son cuadradas. En la última línea, la segunda fila es el doble de la primera, así que el rango es 1.

Estas cuatro funciones usan fracciones exactas en lugar de decimales, y por eso M * inverse(M) da exactamente la matriz identidad.

Resolver un sistema lineal

Supón que tres cafés y dos tés cuestan 13.50 €, y un café y cuatro tés, 11.50 €. Escribe el número de cada bebida en una fila por ecuación, con las columnas en un orden fijo (café, té), y los totales en una lista con el mismo orden:

calc
solve_system([[3, 2], [1, 4]], [13.5, 11.5]) da [3.1, 2.1]

El resultado sigue el mismo orden que las columnas: un café cuesta 3.10 € y un té, 2.10 €. No pongas los símbolos de moneda, porque los elementos de una matriz deben ser números sin unidades.

solve_system(A, b) resuelve A * x = b para x. Necesita una matriz cuadrada, con una fila por incógnita, y una lista plana de términos independientes de la misma longitud. Usa fracciones exactas, así que el resultado no tiene errores de redondeo.

Si las ecuaciones no determinan una única solución, aparece un error que indica que el sistema no tiene solución única. Por ejemplo, solve_system([[1, 2], [2, 4]], [3, 6]) falla porque la segunda ecuación es la primera multiplicada por dos. solve_system solo resuelve ecuaciones lineales; para una ecuación como x^2 = 2, usa solve de Sumatorios, resolución de ecuaciones y cálculo.

Valores propios

calc
eigenvalues([[2, 1], [1, 2]]) da [1, 3]
eigenvalues([[4, 1], [2, 3]]) da [5, 2]
eigenvalues([[0, -1], [1, 0]]) da [i, -i]

eigenvalues recibe una matriz cuadrada y devuelve una lista plana. Un giro de 90° no deja ninguna dirección sin cambiar, así que sus valores propios son el par complejo i y -i; consulta Números complejos. No confíes en el orden de la lista.

Descomposiciones: QR, LU y SVD

Cada descomposición devuelve una lista de matrices. Usa índices para extraer las partes:

calc
A = [[3, 0], [4, 5]]
partes = qr(A)
q = partes[0] da [[0.6, -0.8], [0.8, 0.6]]
r = partes[1] da [[5, 4], [0, 3]]
q * r da [[3, 0], [4, 5]]

Al volver a multiplicar los factores se obtiene de nuevo A, así que puedes comprobar una descomposición de un vistazo. Trabajar en coma flotante binaria deja pequeños restos de redondeo, de alrededor de 10⁻¹⁵, que Varlig muestra como 0 en listas y matrices. Los valores guardados conservan todas las cifras, así que compara los resultados de una descomposición a simple vista o mirando la diferencia, no con ==.

calc
lu([[2, 1], [4, 3]]) da [[[0, 1], [1, 0]], [[1, 0], [0.5, 1]], [[4, 3], [0, -0.5]]]

lu devuelve [P, L, U], donde P registra los intercambios de filas y P * A es igual a L * U. Aquí se intercambiaron las filas para usar primero el número mayor, 4.

calc
B = [[3, 1], [4, 7]]
f = svd(B)
u = f[0]
s = f[1]
vt = f[2]
u * [[s[0], 0], [0, s[1]]] * vt da [[3, 1], [4, 7]]
svd([[3, 4]]) da [[[1]], [5], [[0.6, 0.8]]]

svd devuelve [U, s, Vt], donde s es una lista plana de valores singulares, de mayor a menor. En los libros de texto, B es igual a U * diag(s) * Vt. No hay función diag, así que construye tú la matriz diagonal, como en [[s[0], 0], [0, s[1]]].

Función Qué necesita y qué devuelve
identity(n) La matriz identidad de n por n
shape(A) [filas, columnas]
transpose(A) Filas y columnas intercambiadas
det(A) Determinante de una matriz cuadrada
inverse(A) Inversa de una matriz cuadrada con determinante distinto de cero
trace(A) Suma de la diagonal de una matriz cuadrada
rank(A) Número de filas independientes; cualquier matriz rectangular
solve_system(A,b) Solución de A * x = b para una matriz cuadrada con una única solución
eigenvalues(A) Valores propios de una matriz cuadrada, quizá complejos, sin un orden concreto
qr(A) [Q, R] con Q * R aproximadamente igual a A; cualquier matriz rectangular
lu(A) [P, L, U] con P * A aproximadamente igual a L * U; matriz cuadrada
svd(A) [U, s, Vt], donde s es una lista plana; cualquier matriz rectangular

Para una matriz que no es cuadrada, qr y svd devuelven factores reducidos: para una matriz de 3 por 2, Q también es de 3 por 2 en lugar de 3 por 3.

Algoritmos y límites

det, inverse, rank y solve_system trabajan con fracciones exactas, dentro de los límites de la calculadora en cuanto al tamaño de un número. eigenvalues, qr, lu y svd trabajan en coma flotante binaria, así que sus resultados son aproximaciones muy cercanas. Sus iteraciones se detienen tras 10,000 pasos.

Las matrices cuyas filas son casi dependientes, como [[1, 1], [1, 1.0000001]], se llaman mal condicionadas. Los pequeños errores de redondeo crecen mucho al trabajar con ellas, así que sus descomposiciones y valores propios pueden perder precisión, y los casos muy extremos pueden superar los límites numéricos y dar un error.

Las reglas completas están en Matemáticas avanzadas: posibilidades y límites.

Todo junto

Tres tiques de un puesto del mercado indican cuántas manzanas, peras y naranjas se compraron y el total pagado, pero no el precio de cada fruta:

calc
# Cada fila: manzanas, peras, naranjas
cestas = [[2, 3, 1], [1, 2, 3], [4, 1, 2]]
pagado = [2.15, 2.70, 3.05]
det(cestas) da 25
precios = solve_system(cestas, pagado) da [0.4, 0.25, 0.6]
# Comprueba los precios con cada tique
cestas * transpose([precios]) da [[2.15], [2.7], [3.05]]
# ¿Cuánto costarían 5 manzanas, 2 peras y 4 naranjas?
dot([5, 2, 4], precios) da 4.9

El determinante distinto de cero confirma que los tiques bastan para hallar un único conjunto de precios: las manzanas a 0.40 €, las peras a 0.25 € y las naranjas a 0.60 €. Multiplicar las cestas por los precios en forma de columna reproduce los totales, y dot calcula que una cesta nueva cuesta 4.90 €.