Anillos Elementales

Cuando definimos matrices, vectores o polinomios, a veces es útil, incluso necesario, especificar el «anillo» sobre el que están definidos. Un anillo es una construcción matemática consistente en un conjunto de elementos sobre los que está bien definidas las operaciones de suma y producto; si la noción de anillo no te resulta familiar, probablemente sólo necesitas conocer estos cuatro anillos:

  • los enteros \(\{..., -1, 0, 1, 2, ...\}\), a los que nos referimos en Sage por ZZ.

  • los números racionales – e.g., fracciones, o cocientes de números enteros –, QQ en Sage.

  • los números reales, RR en Sage.

  • los números complejos, CC en Sage.

Es importante conocer estas distinciones porque el mismo polinomio, por ejemplo, puede ser tratado de forma diferente dependiendo del anillo sobre el que se ha definido. Por ejemplo, el polinomio \(x^2-2\) tiene dos raíces, \(\pm \sqrt{2}\). Estas raíces no son racionales, así que si trabajamos con polinomios con coeficientes racionales, el polinomio es irreducible. Sin embargo, si los coeficientes son números reales, el polinomio factoriza como producto de dos factores lineales. En el siguiente ejemplo, los conjuntos de polinomios se llaman «ratpoly» y «realpoly», aunque no usaremos estos nombres; observa sin embargo que las cadenas «.<t>» y «.<z>» sirven para dar nombre a las variables usadas en cada caso.

sage: ratpoly.<t> = PolynomialRing(QQ)
sage: realpoly.<z> = PolynomialRing(RR)
>>> from sage.all import *
>>> ratpoly = PolynomialRing(QQ, names=('t',)); (t,) = ratpoly._first_ngens(1)
>>> realpoly = PolynomialRing(RR, names=('z',)); (z,) = realpoly._first_ngens(1)
ratpoly.<t> = PolynomialRing(QQ)
realpoly.<z> = PolynomialRing(RR)

Veamos el punto que hicimos antes sobre factorizar \(x^2-2\):

sage: factor(t^2-2)
t^2 - 2
sage: factor(z^2-2)
(z - 1.41421356237310) * (z + 1.41421356237310)
>>> from sage.all import *
>>> factor(t**Integer(2)-Integer(2))
t^2 - 2
>>> factor(z**Integer(2)-Integer(2))
(z - 1.41421356237310) * (z + 1.41421356237310)
factor(t^2-2)
factor(z^2-2)

Comentarios similares se aplican a las matrices: la forma reducida por filas de una matriz puede depender del anillo en que está definida, al igual que sus autovalores y autofunciones. Hay más construcciones con polinomios en la sección Polinomios, y más construcciones con matrices en Álgebra Lineal.

El símbolo I representa la raíz cuadrada de \(-1\); i es un sinónimo de I. Por supuesto, no es un número racional:

sage: i  # raíz cuadrada de -1
I
sage: i in QQ
False
>>> from sage.all import *
>>> i  # raíz cuadrada de -1
I
>>> i in QQ
False
i  # raíz cuadrada de -1
i in QQ

Nota: El código siguiente puede no funcionar como esperas si hemos asignado otro valor a la variable i, por ejemplo si la hemos usado como variable interna de un bucle. En este caso, podemos devolver i a su valor original:

sage: reset('i')
>>> from sage.all import *
>>> reset('i')
reset('i')

Hay una sutileza al definir números complejos: el símbolo i representa una raíz cuadrada de \(-1\), pero es una raíz formal como elemento de un cuerpo de números algebráicos. Ejecutando CC(i) o CC.0 o CC.gen(0) obtenemos el número complejo de coma flotante que es la raíz cuadrada de \(-1\).

sage: i = CC(i)       # número complejo de coma flotante
sage: i == CC.0
True
sage: a, b = 4/3, 2/3
sage: z = a + b*i
sage: z
1.33333333333333 + 0.666666666666667*I
sage: z.imag()        # parte imaginaria
0.666666666666667
sage: z.real() == a   # conversión automática antes de la comparación
True
sage: a + b
2
sage: 2*b == a
True
sage: parent(2/3)
Rational Field
sage: parent(4/2)
Rational Field
sage: 2/3 + 0.1       # conversión automática antes de la suma
0.766666666666667
sage: 0.1 + 2/3       # las reglas de conversión son simétricas en Sage
0.766666666666667
>>> from sage.all import *
>>> i = CC(i)       # número complejo de coma flotante
>>> i == CC.gen(0)
True
>>> a, b = Integer(4)/Integer(3), Integer(2)/Integer(3)
>>> z = a + b*i
>>> z
1.33333333333333 + 0.666666666666667*I
>>> z.imag()        # parte imaginaria
0.666666666666667
>>> z.real() == a   # conversión automática antes de la comparación
True
>>> a + b
2
>>> Integer(2)*b == a
True
>>> parent(Integer(2)/Integer(3))
Rational Field
>>> parent(Integer(4)/Integer(2))
Rational Field
>>> Integer(2)/Integer(3) + RealNumber('0.1')       # conversión automática antes de la suma
0.766666666666667
>>> RealNumber('0.1') + Integer(2)/Integer(3)       # las reglas de conversión son simétricas en Sage
0.766666666666667
i = CC(i)       # número complejo de coma flotante
i == CC.0
a, b = 4/3, 2/3
z = a + b*i
z
z.imag()        # parte imaginaria
z.real() == a   # conversión automática antes de la comparación
a + b
2*b == a
parent(2/3)
parent(4/2)
2/3 + 0.1       # conversión automática antes de la suma
0.1 + 2/3       # las reglas de conversión son simétricas en Sage

Veamos más ejemplos de anillos elementales en Sage. Como mencionamos antes, nos podemos referir al anillo de números racionales usando QQ, o también RationalField() (field, o cuerpo, se refiere a un anillo en el que el producto es conmutativo y todo elemento excepto el cero tiene un inverso para la multiplicación. De este modo, los racionales son un cuerpo, pero los enteros no:

sage: RationalField()
Rational Field
sage: QQ
Rational Field
sage: 1/2 in QQ
True
>>> from sage.all import *
>>> RationalField()
Rational Field
>>> QQ
Rational Field
>>> Integer(1)/Integer(2) in QQ
True
RationalField()
QQ
1/2 in QQ

El número decimal 1.2 se considera que está en QQ: los números decimales, que también son racionales, se pueden convertir a racionales de forma automática. Sin embargo, los números \(\pi\) y \(\sqrt{2}\) no son racionales:

sage: 1.2 in QQ
True
sage: pi in QQ
False
sage: pi in RR
True
sage: sqrt(2) in QQ
False
sage: sqrt(2) in CC
True
>>> from sage.all import *
>>> RealNumber('1.2') in QQ
True
>>> pi in QQ
False
>>> pi in RR
True
>>> sqrt(Integer(2)) in QQ
False
>>> sqrt(Integer(2)) in CC
True
1.2 in QQ
pi in QQ
pi in RR
sqrt(2) in QQ
sqrt(2) in CC

En Sage también podemos trabajar con otros anillos, como cuerpos finitos, enteros \(p\)-ádicos, el anillo de los números algebraicos, anillos de polinomios y anillos de matrices. Veamos algunos de estos anillos:

sage: GF(3)
Finite Field of size 3
sage:                 # es necesario dar un nombre al generador si el número
sage: GF(27, 'a')     # de elementos no es primo
Finite Field in a of size 3^3
sage: Zp(5)
5-adic Ring with capped relative precision 20
sage: sqrt(3) in QQbar # clausura algebraica de QQ
True
>>> from sage.all import *
>>> GF(Integer(3))
Finite Field of size 3
>>>                 # es necesario dar un nombre al generador si el número
>>> GF(Integer(27), 'a')     # de elementos no es primo
Finite Field in a of size 3^3
>>> Zp(Integer(5))
5-adic Ring with capped relative precision 20
>>> sqrt(Integer(3)) in QQbar # clausura algebraica de QQ
True
GF(3)
                # es necesario dar un nombre al generador si el número
GF(27, 'a')     # de elementos no es primo
Zp(5)
sqrt(3) in QQbar # clausura algebraica de QQ