Finite Drinfeld modules#
This module provides the class
sage.rings.function_fields.drinfeld_module.finite_drinfeld_module.DrinfeldModule_finite
,
which inherits
sage.rings.function_fields.drinfeld_module.drinfeld_module.DrinfeldModule
.
AUTHORS:
Antoine Leudière (2022-04)
Yossef Musleh (2023-02): added characteristic polynomial methods
- class sage.rings.function_field.drinfeld_modules.finite_drinfeld_module.DrinfeldModule_finite(gen, category)#
Bases:
DrinfeldModule
This class implements finite Drinfeld \(\mathbb{F}_q[T]\)-modules.
A finite Drinfeld module is a Drinfeld module whose base field is finite. In this case, the function field characteristic is a prime ideal.
For general definitions and help on Drinfeld modules, see class
sage.rings.function_fields.drinfeld_module.drinfeld_module.DrinfeldModule
.Construction:
The user does not ever need to directly call
DrinfeldModule_finite
— the metaclassDrinfeldModule
is responsible for instantiatingDrinfeldModule
orDrinfeldModule_finite
depending on the input:sage: Fq = GF(343) sage: A.<T> = Fq[] sage: K.<z6> = Fq.extension(2) sage: phi = DrinfeldModule(A, [z6, 0, 5]) sage: phi Drinfeld module defined by T |--> 5*t^2 + z6
sage: isinstance(phi, DrinfeldModule) True sage: from sage.rings.function_field.drinfeld_modules.finite_drinfeld_module import DrinfeldModule_finite sage: isinstance(phi, DrinfeldModule_finite) True
The user should never use
DrinfeldModule_finite
to test if a Drinfeld module is finite, but rather theis_finite
method:sage: phi.is_finite() True
Complex multiplication of rank two finite Drinfeld modules
We can handle some aspects of the theory of complex multiplication of finite Drinfeld modules. Apart from the method
frobenius_endomorphism
, we only handle rank two Drinfeld modules.First of all, it is easy to create the Frobenius endomorphism:
sage: frobenius_endomorphism = phi.frobenius_endomorphism() sage: frobenius_endomorphism Endomorphism of Drinfeld module defined by T |--> 5*t^2 + z6 Defn: t^2
Its characteristic polynomial can be computed:
sage: chi = phi.frobenius_charpoly() sage: chi X^2 + (T + 2*z3^2 + 2*z3 + 1)*X + 2*T^2 + (z3^2 + z3 + 4)*T + 2*z3 sage: frob_pol = frobenius_endomorphism.ore_polynomial() sage: chi(frob_pol, phi(T)) 0
as well as its trace and norm:
sage: phi.frobenius_trace() 6*T + 5*z3^2 + 5*z3 + 6 sage: phi.frobenius_trace() == -chi[1] True sage: phi.frobenius_norm() 2*T^2 + (z3^2 + z3 + 4)*T + 2*z3
We can decide if a Drinfeld module is ordinary or supersingular:
sage: phi.is_ordinary() True sage: phi.is_supersingular() False
Inverting the Drinfeld module
The morphism that defines a Drinfeld module is injective (see [Gos1998], cor. 4.5.2). If the Drinfeld module is finite, one can retrieve preimages:
sage: a = A.random_element() sage: phi.invert(phi(a)) == a True
- frobenius_charpoly(var='X', algorithm='crystalline')#
Return the characteristic polynomial of the Frobenius endomorphism.
Let \(\mathbb{F}_q\) be the base field of the function ring. The characteristic polynomial \(\chi\) of the Frobenius endomorphism is defined in [Gek1991]. An important feature of this polynomial is that it is monic, univariate, and has coefficients in the function ring. As in our case the function ring is a univariate polynomial ring, it is customary to see the characteristic polynomial of the Frobenius endomorphism as a bivariate polynomial.
Let \(\chi = X^r + \sum_{i=0}^{r-1} A_{i}(T)X^{i}\) be the characteristic polynomial of the Frobenius endomorphism, and let \(t^n\) be the Ore polynomial that defines the Frobenius endomorphism of \(\phi\); by definition, \(n\) is the degree of \(K\) over the base field \(\mathbb{F}_q\). Then we have
\[\chi(t^n)(\phi(T)) = t^{nr} + \sum_{i=1}^{r} \phi_{A_{i}}t^{n(i)} = 0,\]with \(\deg(A_i) \leq \frac{n(r-i)}{r}\).
Note that the Frobenius trace is defined as \(A_{r-1}(T)\) and the Frobenius norm is defined as \(A_0(T)\).
INPUT:
var
(default:'X'
) – the name of the second variablealgorithm
(default:'crystalline'
) – the algorithm used to compute the characteristic polynomial
EXAMPLES:
sage: Fq = GF(25) sage: A.<T> = Fq[] sage: K.<z12> = Fq.extension(6) sage: p_root = 2*z12^11 + 2*z12^10 + z12^9 + 3*z12^8 + z12^7 + 2*z12^5 + 2*z12^4 + 3*z12^3 + z12^2 + 2*z12 sage: phi = DrinfeldModule(A, [p_root, z12^3, z12^5]) sage: phi.frobenius_charpoly() X^2 + ((4*z2 + 4)*T^3 + (z2 + 3)*T^2 + 3*T + 2*z2 + 3)*X + 3*z2*T^6 + (4*z2 + 3)*T^5 + (4*z2 + 4)*T^4 + 2*T^3 + (3*z2 + 3)*T^2 + (z2 + 2)*T + 4*z2
sage: Fq = GF(343) sage: A.<T> = Fq[] sage: K.<z6> = Fq.extension(2) sage: phi = DrinfeldModule(A, [1, 0, z6]) sage: chi = phi.frobenius_charpoly() sage: chi X^2 + ((3*z3^2 + z3 + 4)*T + 4*z3^2 + 6*z3 + 3)*X + (5*z3^2 + 2*z3)*T^2 + (4*z3^2 + 3*z3)*T + 5*z3^2 + 2*z3
sage: frob_pol = phi.frobenius_endomorphism().ore_polynomial() sage: chi(frob_pol, phi(T)) 0
sage: phi.frobenius_charpoly(algorithm="NotImplemented") Traceback (most recent call last): ... NotImplementedError: algorithm "NotImplemented" not implemented
ALGORITHM:
By default, this method uses the so-called crystalline algorithm which computes the characteristic polynomial of the Frobenius acting on the crystalline cohomology of the Drinfeld module. For further details, see [Ang1997].
The available options for ‘algorithm’ are:
'crystalline'
– Computes the characteristic polynomial of the Frobenius endomorphism on the crystalline cohomology of a Drinfeld module.'motive'
– Based on computing the characteristic polynomial of the Frobenius endomorphism on the motive of a Drinfeld module. This instantiates the Frobenius as a morphism object and calls its'characteristic_polynomial'
method.
- frobenius_endomorphism()#
Return the Frobenius endomorphism of the Drinfeld module as a morphism object.
Let \(q\) be the order of the base field of the function ring. The Frobenius endomorphism is defined as the endomorphism whose defining Ore polynomial is \(t^q\).
EXAMPLES:
sage: Fq = GF(343) sage: A.<T> = Fq[] sage: K.<z6> = Fq.extension(2) sage: phi = DrinfeldModule(A, [1, 0, z6]) sage: phi.frobenius_endomorphism() Endomorphism of Drinfeld module defined by T |--> z6*t^2 + 1 Defn: t^2
- frobenius_norm()#
Return the Frobenius norm of the Drinfeld module.
Let \(C(X) = \sum_{i=0}^r a_iX^{i}\) denote the characteristic polynomial of the Frobenius endomorphism. The Frobenius norm is \((-1)^r a_{0}\). This is an element of the regular function ring and if \(n\) is the degree of the base field over \(\mathbb{F}_q\), then the Frobenius norm has degree \(n\).
EXAMPLES:
sage: Fq = GF(343) sage: A.<T> = Fq[] sage: K.<z6> = Fq.extension(2) sage: phi = DrinfeldModule(A, [1, 0, z6]) sage: B = phi.frobenius_norm() sage: B (5*z3^2 + 2*z3)*T^2 + (4*z3^2 + 3*z3)*T + 5*z3^2 + 2*z3
sage: n = 2 # Degree of the base field over Fq sage: B.degree() == n True
sage: B == phi.frobenius_charpoly()[0] True
ALGORITHM:
The Frobenius norm is computed using the formula, by Gekeler, given in [MS2019], Section 4, Proposition 3.
- frobenius_trace()#
Return the Frobenius trace of the Drinfeld module.
Let \(C(X) = \sum_{i=0}^r a_iX^{i}\) denote the characteristic polynomial of the Frobenius endomorphism. The Frobenius trace is \(-a_{r-1}\). This is an element of the regular function ring and if \(n\) is the degree of the base field over \(\mathbb{F}_q\), then the Frobenius trace has degree at most \(\frac{n}{r}\).
EXAMPLES:
sage: Fq = GF(343) sage: A.<T> = Fq[] sage: K.<z6> = Fq.extension(2) sage: phi = DrinfeldModule(A, [1, 0, z6]) sage: A = phi.frobenius_trace() sage: A (4*z3^2 + 6*z3 + 3)*T + 3*z3^2 + z3 + 4
sage: n = 2 # Degree over Fq of the base codomain sage: A.degree() <= n/2 True
sage: A == -phi.frobenius_charpoly()[1] True
ALGORITHM:
We extract the coefficient of \(X^{r-1}\) from the characteristic polynomial if it has been previously computed, otherwise we compute the trace of the matrix of the Frobenius acting on the crystalline cohomology.
- invert(ore_pol)#
Return the preimage of the input under the Drinfeld module, if it exists.
INPUT:
ore_pol
– the Ore polynomial whose preimage we want to compute
EXAMPLES:
sage: Fq = GF(25) sage: A.<T> = Fq[] sage: K.<z12> = Fq.extension(6) sage: p_root = 2*z12^11 + 2*z12^10 + z12^9 + 3*z12^8 + z12^7 + 2*z12^5 + 2*z12^4 + 3*z12^3 + z12^2 + 2*z12 sage: phi = DrinfeldModule(A, [p_root, z12^3, z12^5]) sage: a = A.random_element() sage: phi.invert(phi(a)) == a True sage: phi.invert(phi(T)) == T True sage: phi.invert(phi(Fq.gen())) == Fq.gen() True
When the input is not in the image of the Drinfeld module, an exception is raised:
sage: t = phi.ore_polring().gen() sage: phi.invert(t + 1) Traceback (most recent call last): ... ValueError: input must be in the image of the Drinfeld module
sage: phi.invert(t^4 + t^2 + 1) Traceback (most recent call last): ... ValueError: input must be in the image of the Drinfeld module
ALGORITHM:
The algorithm relies on the inversion of a linear algebra system. See [MS2019], 3.2.5 for details.
- is_isogenous(psi)#
Return
True
whenself
is isogenous to the other Drinfeld module.If the Drinfeld modules do not belong to the same category, an exception is raised.
EXAMPLES:
sage: Fq = GF(2) sage: A.<T> = Fq[] sage: K.<z> = Fq.extension(3) sage: psi = DrinfeldModule(A, [z, z + 1, z^2 + z + 1]) sage: phi = DrinfeldModule(A, [z, z^2 + z + 1, z^2 + z]) sage: phi.is_isogenous(psi) True
sage: chi = DrinfeldModule(A, [z, z + 1, z^2 + z]) sage: phi.is_isogenous(chi) False
sage: mu = DrinfeldModule(A, [z + 1, z^2 + z + 1, z^2 + z]) sage: phi.is_isogenous(mu) Traceback (most recent call last): ... TypeError: Drinfeld modules are not in the same category
sage: mu = 1 sage: phi.is_isogenous(mu) Traceback (most recent call last): ... TypeError: input must be a Drinfeld module
ALGORITHM:
Two Drinfeld A-modules of equal characteristic are isogenous if and only if:
they have the same rank
the characteristic polynomial of the Frobenius endomorphism for both Drinfeld modules are equal.
- is_ordinary()#
Return
True
if this Drinfeld module is ordinary.A Drinfeld module is ordinary if and only if its height is one.
EXAMPLES:
sage: Fq = GF(343) sage: A.<T> = Fq[] sage: K.<z6> = Fq.extension(2) sage: phi = DrinfeldModule(A, [1, 0, z6]) sage: phi.is_ordinary() False
sage: phi = DrinfeldModule(A, [1, z6, 0, z6]) sage: phi.is_ordinary() True
- is_supersingular()#
Return
True
if this Drinfeld module is supersingular.A Drinfeld module is supersingular if and only if its height equals its rank.
EXAMPLES:
sage: Fq = GF(343) sage: A.<T> = Fq[] sage: K.<z6> = Fq.extension(2) sage: phi = DrinfeldModule(A, [1, 0, z6]) sage: phi.is_supersingular() True sage: phi(phi.characteristic()) # Purely inseparable z6*t^2
In rank two, a Drinfeld module is either ordinary or supersinguler. In higher ranks, it could be neither of the two:
sage: psi = DrinfeldModule(A, [1, 0, z6, z6]) sage: psi.is_ordinary() False sage: psi.is_supersingular() False