Galois groups (Sage)
Galois groups of polynomials over the rationals, and how the descent found them.
group theorypolynomialsnumber theoryDownload (ZIP)Source on GitHub
Preview
Galois groups
The Galois group of an irreducible polynomial permutes its roots, so, up to the numbering of the roots, it is one of the transitive groups T of degree . Sagebrush computes it for degrees to , , and (PARI stops at ), entirely in this page:
- Frobenius cycle types. For a prime not dividing the discriminant, the degrees of the factors of mod are the cycle lengths of an element of the Galois group (Dedekind). With the parity of the group (is the discriminant a square?) this leaves a few candidate groups, often just one.
- Stauduhar's descent. Otherwise, starting from or : for each maximal subgroup that is still a candidate, an invariant of is evaluated at the roots, computed -adically, permuted by coset representatives. The group lies in a conjugate of exactly when a value is a rational integer of known size, and only cosets fixed by the Frobenius at can work.
The 508 transitive groups of these degrees, and the maximal subgroups of each, were computed by Sagebrush itself; only their standard numbering and names were matched against GAP's library.
R.<x> = QQ[]
for f in [x^2 + 1, x^3 - 2, x^4 - 2, x^5 - 2, x^5 - x - 1, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1]:
G = f.galois_group()
print(f, ' ', G.transitive_label(), G.order(), G.name())x^2 + 1 2T1 2 S2
x^3 - 2 3T2 6 S3 x^4 - 2 4T3 8 D(4) x^5 - 2 5T3 20 F(5) = 5:4 x^5 - x - 1 5T5 120 S5 x^6 + x^5 + x^4 + x^3 + x^2 + x + 1 6T1 6 C(6) = 6 = 3[x]2
K.<a> = NumberField(x^6 - 2)
K.galois_group(), K.is_galois()(Galois group 6T3 (D(6) = S(3)[x]2) with order 12 of x^6 - 2, False)
How it was found
The log lists each descent step: the maximal subgroup, its index, how many cosets fixed by the Frobenius gave an integer, and the invariant used (a sum over an orbit of monomials, or a product of differences of roots or of block sums). Repeated values are separated by a Tschirnhausen transformation of the roots.
G = (x^8 - 2).galois_group()
G.galois_log()discriminant is not a square 5 Frobenius cycle types from 120 primes leave 12 candidates: 8T6, 8T8, 8T15, 8T23, 8T26, 8T27, 8T35, 8T40, 8T43, 8T44, 8T47, 8T50 p-adic roots: p = 7, unramified degree 2, Frobenius cycle type [2, 2, 2, 1, 1] 8T47 in 8T50: repeated values, Tschirnhausen transformation -2x^2 - x 8T50 -> 8T47 (index 35, 1 of 3 Frobenius-fixed cosets integral, invariant of degree 4 with 2 terms, value 64), proven 8T47 -> 8T35 (index 9, 1 of 3 Frobenius-fixed cosets integral, invariant of degree 2 with 4 terms, value 0), proven 8T35 -> 8T26 (index 2, 2 of 2 Frobenius-fixed cosets integral, invariant of degree 6 with 0 terms, value 2048), proven 8T15 in 8T26: repeated values, Tschirnhausen transformation -x^2 8T15 in 8T26: repeated values, Tschirnhausen transformation x^5 - 2x^4 - x^3 + 2x 8T26 -> 8T15 (index 2, 2 of 2 Frobenius-fixed cosets integral, invariant of degree 4 with 8 terms, value 576), proven 8T15 -> 8T8 (index 2, 2 of 2 Frobenius-fixed cosets integral, invariant of degree 3 with 8 terms, value -128), proven 8T8: no maximal subgroup is a candidate
Degrees 12 and 13
Here PARI gives up. The 13th cyclotomic polynomial has the cyclic group , has a group of order , and compositions have imprimitive groups, whose block systems correspond to the subfields. In prime degree every transitive group is primitive: has the Frobenius group .
for f in [sum(x^i for i in range(13)), x^12 - 2, x^12 + 3, (x^4 - 2)(x^3 - 3*x + 1), (x^6 - 2)(x^2 + x), x^12 - x - 1, x^13 - 2]:
G = f.galois_group()
print(G.transitive_label(), G.order(), G.name())12T1 12 C(4)[x]C(3)
12T28 48 D(4)[x]S(3)
12T15 24 1/2[3:2]dD(4)
12T274 10368 [S(3)^4]D(4)=S(3)wrD(4)
12T193 768 [2^6]D(6)=2wrD(6)
12T301 479001600 S12 13T6 156 F_156(13)=13:12
The Mathieu group
In August 2026, Huang, Jackson, Lee, Poonen, Pries and Zhang proved that , the last of the 26 sporadic simple groups not yet known to occur, is a Galois group over (arXiv:2608.08538), with this polynomial of degree . Here the cycle types of Frobenius elements rule out every group but and (rigorously), and one resolvent, the sum over the blocks of the Steiner system preserved by of the products of the roots in a block, picks : of the cosets only the few fixed by a Frobenius element need to be tried. That last step is a high-confidence computation, not a proof (the paper's proof is geometric).
f = x^23 - 184*x^21 - 1150*x^20 + 26151*x^19 + 18400*x^18 - 1808490*x^17 + 1545462*x^16 + 67672923*x^15 - 42732528*x^14 - 1333395744*x^13 + 290615166*x^12 + 10550424369*x^11 + 3700476348*x^10 + 35123826654*x^9 - 194398310718*x^8 - 1023887308293*x^7 + 3961650395556*x^6 + 1949980486716*x^5 - 28142323927002*x^4 + 53599151839311*x^3 - 46185312415788*x^2 + 19169943578802*x - 3150159884154
G = f.galois_group()
G, G.order(), G.name()(Transitive group number 5 of degree 23, 10200960, 'M(23)')
G.galois_log()discriminant is a square 9 Frobenius cycle types from 120 primes leave 2 candidates: 23T5, 23T6 p-adic roots: p = 29, unramified degree 23, Frobenius cycle type [23] 23T6 -> 23T5 (index 1267136462592000, 1 of 1 Frobenius-fixed cosets integral, invariant of degree 7 with 253 terms, value -2281968) 23T5: no maximal subgroup is a candidate
The transitive groups
There are transitive groups of degrees to up to conjugacy (OEIS A002106). Number of degree is the Mathieu group , which is -transitive.
[TransitiveGroups(n).cardinality() for n in range(1, 13)][1, 1, 2, 5, 5, 16, 7, 50, 34, 45, 8, 301]
M = TransitiveGroup(12, 295)
M, M.name(), M.order(), M.transitivity()(Transitive group number 295 of degree 12, 'M(12)', 95040, 5)
Proofs
A step is proven when its value is shown to be an integer (by a norm bound, which needs high -adic precision) and to differ from the values at all other cosets. By default the steps that are cheap to prove are proven. With proof=True, all of them are, however long that takes. Either way, the answers agree with Magma on thousands of test polynomials.
G = (x^12 - 2).galois_group(proof=True)
G, G.proven(Transitive group number 28 of degree 12, True)
Files
main.ipynb(9563 bytes)