Sagebrush · Examples · Notebooks

Algebraic number theory (Sage)

Number fields: discriminants, maximal orders, units, regulators and how primes split.

notebook · Sage · research · by Sagebrush · MIT license

number theoryalgebra

Download (ZIP)Source on GitHub

Preview

Algebraic number theory

Number fields on Sagebrush's Rust engine, in your browser: maximal orders, prime decomposition, class groups, units and regulators, quadratic fields with 40-digit discriminants, integer factorization (ECM) and lattices. Class groups and regulators assume the Generalized Riemann Hypothesis, as Sage's and PARI's do, with a generator bound computed for each field; the results are checked against PARI. Everything is written from the literature (Cohen's books and papers) and is MIT OR Apache-2.0.

# A cubic field: discriminant, signature (r1, r2), integral basis
K.<a> = NumberField(x^3 - 11)
K, K.discriminant(), K.signature(), K.integral_basis()
(Number Field in a with defining polynomial x^3 - 11, -3267, (1, 1), [1, a, a^2])
K.maximal_order(), K.unit_group(), K.regulator()
(Maximal Order generated by a in Number Field in a with defining polynomial x^3 - 11, Unit group with structure C2 x Z of Number Field in a with defining polynomial x^3 - 11, 5.58720662606091)
# How each prime splits: (residue degree f, ramification index e) for each P^e in p O_K
for p in prime_range(2, 30):
    print(p, [(P.residue_class_degree(), e) for P, e in K.factor(p)])
2 [(2, 1), (1, 1)]
3 [(1, 3)]
5 [(2, 1), (1, 1)]
7 [(3, 1)]
11 [(1, 3)]
13 [(3, 1)]
17 [(2, 1), (1, 1)]
19 [(1, 1), (1, 1), (1, 1)]
23 [(2, 1), (1, 1)]
29 [(2, 1), (1, 1)]
# Class groups and regulators. On this field, the PARI in Sage 10.8.beta0 stops with
# "bug in small_norm (precision too low)"; Sagebrush answers in a fraction of a second.
K.<a> = NumberField(x^3 + 838398*x - 5077)
K.class_group(), K.regulator()
(Class group of order 32 with structure C8 x C2 x C2 of Number Field in a with defining polynomial x^3 + 838398*x - 5077, 1.05459712939614e7)
# Gauss's class number one problem (Heegner, Baker, Stark): the imaginary quadratic fields with h = 1.
# h(D) counts the reduced forms a*x^2 + b*x*y + c*y^2 of discriminant D = b^2 - 4*a*c < 0:
# primitive, |b| <= a <= c, and b >= 0 when |b| = a or a = c (Gauss's reduction)
def h(D):
    n = 0
    for a in range(1, isqrt(-D // 3) + 1):
        for b in range(-a + 1, a + 1):
            c, r = divmod(b^2 - D, 4*a)
            if r == 0 and c >= a and not (c == a and b < 0) and gcd([a, b, c]) == 1:
                n += 1
    return n
[d for d in range(1, 200) if is_squarefree(d) and h(-d if d % 4 == 3 else -4*d) == 1], QuadraticField(-163).class_number()
([1, 2, 3, 7, 11, 19, 43, 67, 163], 1)
# A 40-digit discriminant, by a subexponential sieve
K = QuadraticField(-(10^40 + 3))
K.class_group()
Class group of order 11536936302246622592 with structure C2884234075561655648 x C2 x C2 of Number Field in a with defining polynomial x^2 + 10000000000000000000000000000000000000003 with a = 1.0000000000000001?e20*I
# Real quadratic: a huge class number and a tiny regulator, since 10^20 + 1 = (10^10)^2 + 1
K.<s> = QuadraticField(10^20 + 1)
K.class_number(), K.regulator()
(352006328, 23.7000000000000)
# Units of a cyclotomic field: the roots of unity and r1 + r2 - 1 = 2 fundamental units
K = CyclotomicField(7)
K.unit_group(), K.regulator()
(Unit group with structure C14 x Z x Z of Cyclotomic Field of order 7 and degree 6, 2.10181872849029)
# Integer factorization by the elliptic curve method
factor(2^128 + 1)
59649589127497217 * 5704689200685129054721
# Lattices: Hermite form, elementary divisors (Smith form), LLL
M = matrix(ZZ, [[1, 1, 1], [-1, 0, 2], [3, 5, 6]])
M.hermite_form(), M.elementary_divisors(), M.LLL()
(
[1 0 1]             [ 0  1  0]
[0 1 0]             [ 1  0  1]
[0 0 3], [1, 1, 3], [-1  0  2]
)
# The complex roots of a defining polynomial (the field's embeddings)
R.<y> = QQ[]
(y^5 - y - 1).roots(CC)
[(1.16730397826142, 1), (-0.764884433600585 - 0.352471546031726*I, 1), (-0.764884433600585 + 0.352471546031726*I, 1), (0.181232444469875 - 1.08395410131771*I, 1), (0.181232444469875 + 1.08395410131771*I, 1)]
# The engines directly: the same API as `pip install sagebrush` in CPython
from sagebrush import nf
nf.bnf([-11, 0, 0, 1])
{'assumes': ['GRH'], 'certified': True, 'cyc': [2], 'degree': 3, 'disc': -3267, 'h': 2, 'r1': 1, 'r2': 1, 'regulator': '5.5872066260609077619', 'w': 2, 'w_proven': True}

Files

Open the ZIP's notebook in Sagebrush (File, Open) to run and change it.