Galois Theory
Let K
be a finite (separable) field extension of k
. Then, in contrast to most of the literature we distinguish two concepts
- the automorphism group
- the Galois group
The automorphism group deals with the actual automorphism of K
fixing k
and thus is, in general trivial. Access is via two constructions:
- a list of all automorphisms (usually only the identity)
- the group of automorphisms, returned as an abstract group and a map linking group elements to actual automorphisms
On the other hand, the Galois group is isomorphic to the automorphism group of the normal closure and is explicitly given as a group of permutations of the roots of the defining polynomial. Thus even in the case of K
over k
being normal, elements of the Galois group do not immediately give automorphisms at all.
Currently, the computation of Galois groups is possible for
K
a simple extension of the rationals (AbsSimpleNumField
)K
a simple extension of anAbsSimpleNumField
K
a finite extension of the rational function field over the rationals. In this case the monodromy group can be computed as well, ie. the automorphism group over the complex numbers.f
a polynomial over the rationals, or anAbsSimpleNumField
Independently of the Galois group, subfields, that is intermediate fields between K
and k
can be computed as well.
Automorphism Group
The automorphisms are computed using various specialized factoring algorithms: lifting the roots of the defining polynomial in the given field modulo suitable prime ideal powers and recovering the true roots from this information.
The main information is included in the number field chapter, see for example
automorphism_list(::Hecke.NumFieldHom)
automorphism_group(::NumField)
automorphism_group(::NumField, ::NumField)
Subfields
The main information is included in the number field chapter, see
subfields(K::SimpleNumField; degree::Int = -1)
Hecke.principal_subfields(K::SimpleNumField)
subfields(FF::Generic.FunctionField{QQFieldElem})
By setting set_verbosity_level(:Subfields, n::Int)
to 1 or 2 information about the progress can be obtained.
Galois Group
The computation of Galois groups follows Stauduhars algorithm with many improvements, see ... for an overview.
The entrire computation can also be thought of finding a description of the splitting field of the polynomial. In fact, the information returned can be used to verify any algebraic identity between the roots, and find explicit subfields of the splitting field as well.
Information about the progress is available via
set_verbosity_level(:GaloisGroup, n::Int)
set_verbosity_level(:GaloisInvariants, n::Int)
galois_group
— Functiongalois_group
— MethodOver the rational function field, we can also compute the monodromy group:
julia> Qt, t = rational_function_field(QQ, "t");
julia> Qtx, x = Qt[:x];
julia> F, a = function_field(x^6 + 108*t^2 + 108*t + 27);
julia> subfields(F)
4-element Vector{Any}:
(Function Field over QQ with defining polynomial a^3 + 54*t + 27, (1//12*_a^4 + (3//2*t + 3//4)*_a)//(t + 1//2))
(Function Field over QQ with defining polynomial a^2 + 108*t^2 + 108*t + 27, _a^3)
(Function Field over QQ with defining polynomial a^3 - 108*t^2 - 108*t - 27, -_a^2)
(Function Field over QQ with defining polynomial a^3 - 54*t - 27, (-1//12*_a^4 + (3//2*t + 3//4)*_a)//(t + 1//2))
julia> galois_group(F)
(Permutation group of degree 6 and order 6, Galois context for s^6 + 108*t^2 + 540*t + 675)
julia> G, C, k = galois_group(F, overC = true)
(Permutation group of degree 6 and order 3, Galois context for s^6 + 108*t^2 + 540*t + 675, Number field of degree 2 over QQ)
So, while the splitting field over Q(t)
has degree 6
, the galois group there is isomorphic to the S(3)
or D(3)
(on 6 points), the splitting field over C(t)
is only of degree 3
. Here the group collapses to a cyclic group of degree 3
, the algebraic closure of Q
in the splitting field is the quadratic field returned last. It can be seen to be isomorphic to a cyclotomic field:
julia> is_isomorphic(k, cyclotomic_field(3)[1])
true
The information returned consists always at least of a group G
and a GaloisCtx
: C
. Jointly, they can be used to further work with the information:
roots
— Methodupper_bound
— Functionisinteger
— Functionresolvent
— FunctionTo illustrate:
julia> Qx, x = QQ[:x];
julia> f = (x^2-2)*(x^2-3);
julia> G, C = galois_group(f)
(Permutation group of degree 4 and order 4, Galois context for x^4 - 5*x^2 + 6 and prime 11)
julia> r = roots(C, 5)
4-element Vector{QadicFieldElem}:
5*11^0 + 2*11^1 + 6*11^2 + 8*11^3 + 11^4 + O(11^5)
6*11^0 + 8*11^1 + 4*11^2 + 2*11^3 + 9*11^4 + O(11^5)
(10*11^0 + 4*11^1 + 4*11^2 + 10*11^3 + 8*11^4 + O(11^5))*a + 2*11^0 + 6*11^1 + 4*11^2 + 3*11^3 + 9*11^4 + O(11^5)
(11^0 + 6*11^1 + 6*11^2 + 2*11^4 + O(11^5))*a + 9*11^0 + 4*11^1 + 6*11^2 + 7*11^3 + 11^4 + O(11^5)
julia> r[1]^2
3*11^0 + O(11^5)
julia> r[3]^2
2*11^0 + O(11^5)
To illustrate the use as a splitting field, we will prove that r[1]^2
is actually an integer - and that r[1]+r[3]
is not.
Any multivariate polynomial in four variables and with integer coefficients defines via evaluation at the roots an element in the splitting field. In case the evaluation is actually an integer, this can be proven with the tools provided.
julia> I, s = polynomial_ring(ZZ, 4);
julia> s[1]^2
x1^2
Next, we need a bound for the evaluation as a complex number, and compute the precision necessary:
julia> B = Oscar.GaloisGrp.upper_bound(C, s[1]^2)
(x <= 36)
julia> pr = Oscar.GaloisGrp.bound_to_precision(C, B)
7
Finally, we evaluate the polynomial at the roots and verify that the exact value is 3
:
julia> evaluate(s[1]^2, roots(C, 7))
3*11^0 + O(11^7)
julia> Oscar.GaloisGrp.isinteger(C, B, ans)
(true, 3)
Now, to show that r[1] + r[3]
is not an integer:
julia> B = Oscar.GaloisGrp.upper_bound(C, s[1] + s[3])
(x <= 12)
julia> Oscar.GaloisGrp.isinteger(C, B, evaluate(s[1] + s[3], roots(C, 7)))
(false, nothing)
More interestingly, we can use this to find the minimal polynomial of r[1] + r[3]
. Generically, the Galois-conjugates of r[1]+r[3]
should be the G
-orbit of s[1]+s[3]
evaluated at the roots.
Once the orbit is known, the coefficients of the minimal polynomial are just the elementary symmetric functions evaluated at the roots:
julia> o = collect(orbit(G, s[1]+s[3]))
4-element Vector{ZZMPolyRingElem}:
x1 + x3
x1 + x4
x2 + x4
x2 + x3
julia> for i=1:4
B = Oscar.GaloisGrp.upper_bound(C, elementary_symmetric, o, i)
pr = Oscar.GaloisGrp.bound_to_precision(C, B)
co = [evaluate(x, roots(C, pr)) for x = o]
println(i, ": ", Oscar.GaloisGrp.isinteger(C, B, elementary_symmetric(co, i)))
end
1: (true, 0)
2: (true, -10)
3: (true, 0)
4: (true, 1)
So, x^4-10x^2+1
should be the minimal polynomial to - which it is.
In the case of computations over the rational function field, both the precision and the bound are more complicated - but can be used in the same way: Here, the roots are power series with q
-adic coefficients, thus the precision has to cover both the precision of the coefficient as well as the number of terms in the series. Similarly, in this context, an isinteger
is now a polynomial with integer coefficients. Thus the bound needs to bound the degree as well as the coefficient size.
julia> Qt,t = rational_function_field(QQ, "t");
julia> Qtx, x = Qt[:x];
julia> F, a = function_field(x^3+t+2);
julia> G, C = galois_group(F);
julia> describe(G)
"S3"
julia> _, s = slpoly_ring(ZZ, 3);
julia> B = Oscar.GaloisGrp.upper_bound(C, prod(s))
(x <= (9261, 2, 1))
julia> pr = Oscar.GaloisGrp.bound_to_precision(C, B)
(2, 2)
julia> Oscar.GaloisGrp.isinteger(C, B, evaluate(prod(s), roots(C, pr)))
(true, -t - 2)
galois_quotient
— Methodgalois_quotient
— Methodgalois_quotient
— Methodgalois_quotient
— Methodfixed_field
— Functionminpoly
— Functioncauchy_ideal
— Methodgalois_ideal
— FunctionOver the integers, if the Galois group is solvable, the roots can be expressed as radicals:
solve
— Methodfixed_field
— Method