Álgebra Lineal - Sage Tutorial

Skip to content
Back to top
View this page
Edit this page

# Álgebra Lineal

Sage soporta construcciones estándar de álgebra lineal, como el polinomio característico, la forma escalonada, la traza, descomposición, etcétera de una matriz.

La creación de matrices y la multiplicación es sencilla y natural:

Sage

    sage: A = Matrix([[1,2,3],[3,2,1],[1,1,1]])
    sage: w = vector([1,1,-4])
    sage: w*A
    (0, 0, 0)
    sage: A*w
    (-9, 1, -2)
    sage: kernel(A)
    Free module of degree 3 and rank 1 over Integer Ring
    Echelon basis matrix:
    [ 1  1 -4]

Python

    >>> from sage.all import *
    >>> A = Matrix([[Integer(1),Integer(2),Integer(3)],[Integer(3),Integer(2),Integer(1)],[Integer(1),Integer(1),Integer(1)]])
    >>> w = vector([Integer(1),Integer(1),-Integer(4)])
    >>> w*A
    (0, 0, 0)
    >>> A*w
    (-9, 1, -2)
    >>> kernel(A)
    Free module of degree 3 and rank 1 over Integer Ring
    Echelon basis matrix:
    [ 1  1 -4]

La descripción de `kernel(A)` indica que se trata de un subespacio de dimensión 1 («rank 1») de un espacio de dimensión 3 («degree 3»). Por el momento, tanto `kernel(A)` como el espacio ambiente admiten coeficientes enteros («over Integer Ring»). Finalmente, Sage nos muestra una base escalonada («Echelon basis»).

Observa que en Sage, el núcleo de la matriz \(A\) es el «núcleo por la izquierda», e.g. el subespacio formado por los vectores \(w\) tales que \(wA=0\).

Resolver ecuaciones matriciales es sencillo, usando el método `solve_right` (resolver por la derecha). Al evaluar `A.solve_right(Y)` obtenemos una matriz (o un vector) \(X\) tal que \(AX=Y\):

Sage

    sage: Y = vector([0, -4, -1])
    sage: X = A.solve_right(Y)
    sage: X
    (-2, 1, 0)
    sage: A * X   # comprobando la solución...
    (0, -4, -1)

[Python]

    >>> from sage.all import *
    >>> Y = vector([Integer(0), -Integer(4), -Integer(1)])
    >>> X = A.solve_right(Y)
    >>> X
    (-2, 1, 0)
    >>> A * X   # comprobando la solución...
    (0, -4, -1)

Si no hay solución, Sage lanza un error:

Sage

    sage: A.solve_right(w)
    Traceback (most recent call last):
    ...
    ValueError: matrix equation has no solutions

Python

    >>> from sage.all import *
    >>> A.solve_right(w)
    Traceback (most recent call last):
    ...
    ValueError: matrix equation has no solutions

De forma similar, usamos `A.solve_left(Y)` para despejar \(X\) de la ecuación \(XA=Y\).

Sage también puede calcular autovalores («eigenvalues») y autovectores («eigenvectors»):

Sage

    sage: A = matrix([[0, 4], [-1, 0]])
    sage: A.eigenvalues ()
    [-2*I, 2*I]
    sage: B = matrix([[1, 3], [3, 1]])
    sage: B.eigenvectors_left()
    [(4, [(1, 1)], 1), (-2, [(1, -1)], 1)]

[Python]

    >>> from sage.all import *
    >>> A = matrix([[Integer(0), Integer(4)], [-Integer(1), Integer(0)]])
    >>> A.eigenvalues ()
    [-2*I, 2*I]
    >>> B = matrix([[Integer(1), Integer(3)], [Integer(3), Integer(1)]])
    >>> B.eigenvectors_left()
    [(4, [(1, 1)], 1), (-2, [(1, -1)], 1)]

(La sintaxis de la salida de `eigenvectors_left` es una lista de tuplas: (autovalor, autovector, multiplicidad).) Los autovalores y autovectores sobre `QQ` o `RR` también se pueden calcular usando Maxima.

Como ya indicamos en Anillos Elementales, el anillo sobre el que se define una matriz afecta algunas de sus propiedades. En las líneas que siguen, el primer argumento al comando `matrix` le dice a Sage que considere la matriz como una matriz de enteros (si el argumento es `ZZ`), de números racionales (si es `QQ`), o de números reales (si es `RR`):

Sage

    sage: AZ = matrix(ZZ, [[2,0], [0,1]])
    sage: AQ = matrix(QQ, [[2,0], [0,1]])
    sage: AR = matrix(RR, [[2,0], [0,1]])
    sage: AZ.echelon_form()
    [2 0]
    [0 1]
    sage: AQ.echelon_form()
    [1 0]
    [0 1]
    sage: AR.echelon_form()
    [ 1.00000000000000 0.000000000000000]
    [0.000000000000000  1.00000000000000]

Python

    >>> from sage.all import *
    >>> AZ = matrix(ZZ, [[Integer(2),Integer(0)], [Integer(0),Integer(1)]])
    >>> AQ = matrix(QQ, [[Integer(2),Integer(0)], [Integer(0),Integer(1)]])
    >>> AR = matrix(RR, [[Integer(2),Integer(0)], [Integer(0),Integer(1)]])
    >>> AZ.echelon_form()
    [2 0]
    [0 1]
    >>> AQ.echelon_form()
    [1 0]
    [0 1]
    >>> AR.echelon_form()
    [ 1.00000000000000 0.000000000000000]
    [0.000000000000000  1.00000000000000]

(El comando `echelon_form` devuelve una forma escalonada de la matriz)

## Espacios de matrices

Creamos el espacio \(\text{Mat}_{3\times 3}(\QQ)\) matrices \(3 \times 3\) con coeficientes racionales:

Sage

    sage: M = MatrixSpace(QQ,3)
    sage: M
    Full MatrixSpace of 3 by 3 dense matrices over Rational Field

Python

    >>> from sage.all import *
    >>> M = MatrixSpace(QQ,Integer(3))
    >>> M
    Full MatrixSpace of 3 by 3 dense matrices over Rational Field

(Para especificar el espacio de matrices 3 por 4, usaríamos `MatrixSpace(QQ,3,4)`. Si se omite el número de columnas, se adopta por defecto el número de filas, de modo que `MatrixSpace(QQ,3)` es un sinónimo de `MatrixSpace(QQ,3,3)`.) El espacio de matrices está equipado con su base canónica:

Sage

    sage: B = M.basis()
    sage: len(B)
    9
    sage: B[0,1]
    [0 1 0]
    [0 0 0]
    [0 0 0]

[Python]

    >>> from sage.all import *
    >>> B = M.basis()
    >>> len(B)
    9
    >>> B[Integer(0),Integer(1)]
    [0 1 0]
    [0 0 0]
    [0 0 0]

Creamos una matriz como un elemento de `M`.

Sage

    sage: A = M(range(9)); A
    [0 1 2]
    [3 4 5]
    [6 7 8]

Python

    >>> from sage.all import *
    >>> A = M(range(Integer(9))); A
    [0 1 2]
    [3 4 5]
    [6 7 8]

Calculamos su forma escalonada por filas y su núcleo.

Sage

    sage: A.echelon_form()
    [ 1  0 -1]
    [ 0  1  2]
    [ 0  0  0]
    sage: A.kernel()
    Vector space of degree 3 and dimension 1 over Rational Field
    Basis matrix:
    [ 1 -2  1]

[Python]

    >>> from sage.all import *
    >>> A.echelon_form()
    [ 1  0 -1]
    [ 0  1  2]
    [ 0  0  0]
    >>> A.kernel()
    Vector space of degree 3 and dimension 1 over Rational Field
    Basis matrix:
    [ 1 -2  1]

Ilustramos un cálculo de matrices definidas sobre cuerpos finitos:

Sage

    sage: M = MatrixSpace(GF(2),4,8)
    sage: A = M([1,1,0,0, 1,1,1,1, 0,1,0,0, 1,0,1,1,
    ....:        0,0,1,0, 1,1,0,1, 0,0,1,1, 1,1,1,0])
    sage: A
    [1 1 0 0 1 1 1 1]
    [0 1 0 0 1 0 1 1]
    [0 0 1 0 1 1 0 1]
    [0 0 1 1 1 1 1 0]
    sage: rows = A.rows()
    sage: A.columns()
    [(1, 0, 0, 0), (1, 1, 0, 0), (0, 0, 1, 1), (0, 0, 0, 1),
     (1, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)]
    sage: rows
    [(1, 1, 0, 0, 1, 1, 1, 1), (0, 1, 0, 0, 1, 0, 1, 1),
     (0, 0, 1, 0, 1, 1, 0, 1), (0, 0, 1, 1, 1, 1, 1, 0)]

Python

    >>> from sage.all import *
    >>> M = MatrixSpace(GF(Integer(2)),Integer(4),Integer(8))
    >>> A = M([Integer(1),Integer(1),Integer(0),Integer(0), Integer(1),Integer(1),Integer(1),Integer(1), Integer(0),Integer(1),Integer(0),Integer(0), Integer(1),Integer(0),Integer(1),Integer(1),
    ...        Integer(0),Integer(0),Integer(1),Integer(0), Integer(1),Integer(1),Integer(0),Integer(1), Integer(0),Integer(0),Integer(1),Integer(1), Integer(1),Integer(1),Integer(1),Integer(0)])
    >>> A
    [1 1 0 0 1 1 1 1]
    [0 1 0 0 1 0 1 1]
    [0 0 1 0 1 1 0 1]
    [0 0 1 1 1 1 1 0]
    >>> rows = A.rows()
    >>> A.columns()
    [(1, 0, 0, 0), (1, 1, 0, 0), (0, 0, 1, 1), (0, 0, 0, 1),
     (1, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)]
    >>> rows
    [(1, 1, 0, 0, 1, 1, 1, 1), (0, 1, 0, 0, 1, 0, 1, 1),
     (0, 0, 1, 0, 1, 1, 0, 1), (0, 0, 1, 1, 1, 1, 1, 0)]

Construimos el subespacio sobre \(\GF{2}\) engendrado por las filas de arriba.

Sage

    sage: V = VectorSpace(GF(2),8)
    sage: S = V.subspace(rows)
    sage: S
    Vector space of degree 8 and dimension 4 over Finite Field of size 2
    Basis matrix:
    [1 0 0 0 0 1 0 0]
    [0 1 0 0 1 0 1 1]
    [0 0 1 0 1 1 0 1]
    [0 0 0 1 0 0 1 1]
    sage: A.echelon_form()
    [1 0 0 0 0 1 0 0]
    [0 1 0 0 1 0 1 1]
    [0 0 1 0 1 1 0 1]
    [0 0 0 1 0 0 1 1]

[Python]

    >>> from sage.all import *
    >>> V = VectorSpace(GF(Integer(2)),Integer(8))
    >>> S = V.subspace(rows)
    >>> S
    Vector space of degree 8 and dimension 4 over Finite Field of size 2
    Basis matrix:
    [1 0 0 0 0 1 0 0]
    [0 1 0 0 1 0 1 1]
    [0 0 1 0 1 1 0 1]
    [0 0 0 1 0 0 1 1]
    >>> A.echelon_form()
    [1 0 0 0 0 1 0 0]
    [0 1 0 0 1 0 1 1]
    [0 0 1 0 1 1 0 1]
    [0 0 0 1 0 0 1 1]

La base de \(S\) usada por Sage se obtiene de las filas no nulas de la forma escalonada reducida de la matriz compuesta por los generadores de \(S\).

## Álgebra Lineal Dispersa

Sage soporta espacios de matrices sobre DIPs almacenados de forma dispersa.

[Sage]

    sage: M = MatrixSpace(QQ, 100, sparse=True)
    sage: A = M.random_element(density = 0.05)
    sage: E = A.echelon_form()

[Python]

    >>> from sage.all import *
    >>> M = MatrixSpace(QQ, Integer(100), sparse=True)
    >>> A = M.random_element(density = RealNumber('0.05'))
    >>> E = A.echelon_form()

El algoritmo multi-modular de Sage es bueno para matrices cuadradas (pero no tan bueno para matrices no cuadradas):

[Sage]

    sage: M = MatrixSpace(QQ, 50, 100, sparse=True)
    sage: A = M.random_element(density = 0.05)
    sage: E = A.echelon_form()
    sage: M = MatrixSpace(GF(2), 20, 40, sparse=True)
    sage: A = M.random_element()
    sage: E = A.echelon_form()

[Python]

    >>> from sage.all import *
    >>> M = MatrixSpace(QQ, Integer(50), Integer(100), sparse=True)
    >>> A = M.random_element(density = RealNumber('0.05'))
    >>> E = A.echelon_form()
    >>> M = MatrixSpace(GF(Integer(2)), Integer(20), Integer(40), sparse=True)
    >>> A = M.random_element()
    >>> E = A.echelon_form()