Introduction to Number Fields¶
In Sage, we can create the number field
sage: K.<alpha> = NumberField(x^3 - 2)
>>> from sage.all import *
>>> K = NumberField(x**Integer(3) - Integer(2), names=('alpha',)); (alpha,) = K._first_ngens(1)
K.<alpha> = NumberField(x^3 - 2)
The above creates two Sage objects,
sage: K
Number Field in alpha with defining polynomial x^3 - 2
>>> from sage.all import *
>>> K
Number Field in alpha with defining polynomial x^3 - 2
K
and
sage: alpha^3
2
sage: (alpha+1)^3
3*alpha^2 + 3*alpha + 3
>>> from sage.all import *
>>> alpha**Integer(3)
2
>>> (alpha+Integer(1))**Integer(3)
3*alpha^2 + 3*alpha + 3
alpha^3 (alpha+1)^3
The variable ¶
Note that we did not define
sage: x = 1
sage: K.<alpha> = NumberField(x^3 - 2)
Traceback (most recent call last):
...
TypeError: polynomial (=-1) must be a polynomial.
>>> from sage.all import *
>>> x = Integer(1)
>>> K = NumberField(x**Integer(3) - Integer(2), names=('alpha',)); (alpha,) = K._first_ngens(1)
Traceback (most recent call last):
...
TypeError: polynomial (=-1) must be a polynomial.
x = 1 K.<alpha> = NumberField(x^3 - 2)
The Traceback above indicates that there was an error.
Potentially lots of detailed information about the error (a
“traceback”) may be given after the word Traceback
and before the last line, which contains the actual error
messages.
Note
Important: whenever you use Sage and get a big error, look at the
last line for the actual error, and only look at the rest if you are
feeling adventurous. In the notebook, the part indicated
by ...
above is not displayed; to see it, click just to the left of
the word Traceback and the traceback will appear.
If you redefine
sage: reset('x')
sage: x
x
sage: x = 1
sage: x = var('x')
sage: x
x
sage: x = 1
sage: x = polygen(QQ, 'x')
sage: x
x
sage: x = 1
sage: R.<x> = PolynomialRing(QQ)
sage: x
x
>>> from sage.all import *
>>> reset('x')
>>> x
x
>>> x = Integer(1)
>>> x = var('x')
>>> x
x
>>> x = Integer(1)
>>> x = polygen(QQ, 'x')
>>> x
x
>>> x = Integer(1)
>>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1)
>>> x
x
reset('x') x x = 1 x = var('x') x x = 1 x = polygen(QQ, 'x') x x = 1 R.<x> = PolynomialRing(QQ) x
Using tab completion to get the methods of an object¶
One you have created a number field K.[tab key]
to
see a list of functions. Type, e.g., K.minkowski_embedding?[tab
key]
to see help on the minkowski_embedding
command. To see
source code, type K.minkowski_embedding??[tab key]
.
sage: K.<alpha> = NumberField(x^3 - 2)
sage: K.[tab key]
>>> from sage.all import *
>>> K = NumberField(x**Integer(3) - Integer(2), names=('alpha',)); (alpha,) = K._first_ngens(1)
>>> K.[tab key]
K.<alpha> = NumberField(x^3 - 2) K.[tab key]
Symbolic Expressions¶
Another natural way for us to create certain number fields is to
create a symbolic expression and adjoin it to the rational
numbers. Unlike Pari and Magma (and like Mathematica and Maple), Sage
also supports manipulation of symbolic expressions and solving
equations, without defining abstract structures such as a number
fields. For example, we can define a variable a = sqrt(2)
. When we
type parent(a)
below, Sage tells us the mathematical object that
it views
sage: a = sqrt(2)
sage: parent(a)
Symbolic Ring
>>> from sage.all import *
>>> a = sqrt(Integer(2))
>>> parent(a)
Symbolic Ring
a = sqrt(2) parent(a)
sqrt(2) in Pari and Magma¶
In particular, typing sqrt(2)
does not numerically extract an
approximation to
sage: gp('sqrt(2)')
1.414213562373095048801688724...
sage: magma('Sqrt(2)') # optional - magma
1.414213562373095048801688724...
>>> from sage.all import *
>>> gp('sqrt(2)')
1.414213562373095048801688724...
>>> magma('Sqrt(2)') # optional - magma
1.414213562373095048801688724...
gp('sqrt(2)') magma('Sqrt(2)') # optional - magma
You probably noticed a pause when evaluated the second line as
Magma started up. Also, note the # optional
comment, which indicates that the line won’t work if you don’t have
Magma installed.
Numerically evaluating sqrt(2)¶
Incidentally, if you want to numerically evaluate prec
argument to the sqrt
function, which takes the required number of bits (binary digits)
of precision.
sage: sqrt(2, prec=100)
1.4142135623730950488016887242
>>> from sage.all import *
>>> sqrt(Integer(2), prec=Integer(100))
1.4142135623730950488016887242
sqrt(2, prec=100)
It’s important to note in computations like this that there is not an
a priori guarantee that prec
bits of the answer are all
correct. Instead, what happens is that Sage creates the number
Arithmetic with sqrt(2)¶
We return now to our symbolic expression
sage: a = sqrt(2)
sage: (a+1)^2
(sqrt(2) + 1)^2
sage: expand((a+1)^2)
2*sqrt(2) + 3
>>> from sage.all import *
>>> a = sqrt(Integer(2))
>>> (a+Integer(1))**Integer(2)
(sqrt(2) + 1)^2
>>> expand((a+Integer(1))**Integer(2))
2*sqrt(2) + 3
a = sqrt(2) (a+1)^2 expand((a+1)^2)
Adjoining a symbolic expression¶
Given any symbolic expression for which Sage can compute its
minimal polynomial, you can construct the number field obtained by
adjoining that expression to QQ[a]
where a
is the symbolic expression.
sage: a = sqrt(2)
sage: K.<b> = QQ[a]
sage: K
Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?
sage: b
sqrt2
sage: (b+1)^2
2*sqrt2 + 3
sage: QQ[a/3 + 5]
Number Field in a with defining polynomial x^2 - 10*x + 223/9 with a = 5.471404520791032?
>>> from sage.all import *
>>> a = sqrt(Integer(2))
>>> K = QQ[a]; (b,) = K._first_ngens(1)
>>> K
Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?
>>> b
sqrt2
>>> (b+Integer(1))**Integer(2)
2*sqrt2 + 3
>>> QQ[a/Integer(3) + Integer(5)]
Number Field in a with defining polynomial x^2 - 10*x + 223/9 with a = 5.471404520791032?
a = sqrt(2) K.<b> = QQ[a] K b (b+1)^2 QQ[a/3 + 5]
Coercion: QQ[a] versus QQ(a)¶
You can’t create the number field QQ(a)
, which has a very different meaning in Sage. It
means “try to create a rational number from QQ(a)
in Sage is the analogue of QQ!a
in Magma (Pari has no notion of
rings such as QQ
).
sage: a = sqrt(2)
sage: QQ(a)
Traceback (most recent call last):
...
TypeError: unable to convert sqrt(2) to a rational
>>> from sage.all import *
>>> a = sqrt(Integer(2))
>>> QQ(a)
Traceback (most recent call last):
...
TypeError: unable to convert sqrt(2) to a rational
a = sqrt(2) QQ(a)
In general, if X(a)
to
make an element of X(a)
is the finite field element
sage: X = GF(7); a = 2/5
sage: X(a)
6
>>> from sage.all import *
>>> X = GF(Integer(7)); a = Integer(2)/Integer(5)
>>> X(a)
6
X = GF(7); a = 2/5 X(a)
Solving a cubic equation¶
As a slightly less trivial illustration of symbolic manipulation, consider the cubic equation
In Sage, we can create this equation, and find an exact symbolic solution.
sage: x = var('x')
sage: eqn = x^3 + sqrt(2)*x + 5 == 0
sage: a = solve(eqn, x)[0].rhs()
>>> from sage.all import *
>>> x = var('x')
>>> eqn = x**Integer(3) + sqrt(Integer(2))*x + Integer(5) == Integer(0)
>>> a = solve(eqn, x)[Integer(0)].rhs()
x = var('x') eqn = x^3 + sqrt(2)*x + 5 == 0 a = solve(eqn, x)[0].rhs()
The first line above makes sure that the symbolic variable eqn
, and the third
line solves eqn
for a
.
Viewing complicated symbolic expressions¶
To see the solution nicely typeset, use the pretty_print
command
sage: pretty_print(a)
-1/2*(I*sqrt(3) + 1)*(1/6*sqrt(8/3*sqrt(2) + 225) - 5/2)^(1/3) + 1/6*sqrt(2)*(-I*sqrt(3) + 1)/(1/6*sqrt(8/3*sqrt(2) + 225) - 5/2)^(1/3)
>>> from sage.all import *
>>> pretty_print(a)
-1/2*(I*sqrt(3) + 1)*(1/6*sqrt(8/3*sqrt(2) + 225) - 5/2)^(1/3) + 1/6*sqrt(2)*(-I*sqrt(3) + 1)/(1/6*sqrt(8/3*sqrt(2) + 225) - 5/2)^(1/3)
pretty_print(a)
You can also see the latex needed to paste latex(a)
. The latex
command works on most Sage objects.
sage: latex(a)
-\frac{1}{2} \, {\left(i \, \sqrt{3} + 1\right)} ...
>>> from sage.all import *
>>> latex(a)
-\frac{1}{2} \, {\left(i \, \sqrt{3} + 1\right)} ...
latex(a)
Adjoining a root of the cubic¶
Next, we construct the number field obtained by adjoining the solution
a
to
Warning
The following tests are currently broken until Issue #5338 is fixed.
sage: K.<b> = QQ[a]
sage: K
Number Field in a with defining
polynomial x^6 + 10*x^3 - 2*x^2 + 25
sage: a.minpoly()
x^6 + 10*x^3 - 2*x^2 + 25
sage: b.minpoly()
x^6 + 10*x^3 - 2*x^2 + 25
>>> from sage.all import *
>>> K = QQ[a]; (b,) = K._first_ngens(1)
>>> K
Number Field in a with defining
polynomial x^6 + 10*x^3 - 2*x^2 + 25
>>> a.minpoly()
x^6 + 10*x^3 - 2*x^2 + 25
>>> b.minpoly()
x^6 + 10*x^3 - 2*x^2 + 25
K.<b> = QQ[a] K a.minpoly() b.minpoly()
We can now compute interesting invariants of the number field
sage: K.class_number()
5
sage: K.galois_group().order()
72
>>> from sage.all import *
>>> K.class_number()
5
>>> K.galois_group().order()
72
K.class_number() K.galois_group().order()