Finite Drinfeld modules#
This module provides the class
sage.rings.function_fields.drinfeld_module.finite_drinfeld_module.FiniteDrinfeldModule
,
which inherits
sage.rings.function_fields.drinfeld_module.drinfeld_module.DrinfeldModule
.
AUTHORS:
Antoine Leudière (2022-04)
- class sage.rings.function_field.drinfeld_modules.finite_drinfeld_module.FiniteDrinfeldModule(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
FiniteDrinfeldModule
— the metaclassDrinfeldModule
is responsible for instantiatingDrinfeldModule
orFiniteDrinfeldModule
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 FiniteDrinfeldModule sage: isinstance(phi, FiniteDrinfeldModule) True
The user should never use
FiniteDrinfeldModule
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')#
Return the characteristic polynomial of the Frobenius endomorphism if the rank is two. Raise a NotImplementedError otherwise.
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 a monic univariate polynomial with 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^2 - A(T)X + B(T)\) 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 over of the base field over \(\mathbb{F}_q\). We have \(\chi(t^n)(\phi(T)) = t^{2n} - \phi_A t^n + \phi_B = 0\), with \(\deg(A) \leq \frac{n}{2}\) and \(\deg(B) = n\).
Note that the Frobenius trace is defined as \(A(T)\) and the Frobenius norm is defined as \(B(T)\).
INPUT:
var
(default:'X'
) – the name of the second variable
EXAMPLES:
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: trace = phi.frobenius_trace() sage: trace (4*z3^2 + 6*z3 + 3)*T + 3*z3^2 + z3 + 4 sage: norm = phi.frobenius_norm() sage: norm (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: trace.degree() <= n/2 True sage: norm.degree() == n True
ALGORITHM:
We compute the Frobenius norm, and with it the Frobenius trace. This gives the Frobenius characteristic polynomial. See [MS2019], Section 4.
See docstrings of methods
frobenius_norm()
andfrobenius_trace()
for further details on the computation of the norm and of the trace.
- 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 Frobenius norm of the Drinfeld module, if the rank is two, raise a NotImplementedError otherwise.
Let \(\mathbb{F}_q[T]\) be the function ring, write \(\chi = X^2 - A(T)X + B(T) \in \mathbb{F}_q[T][X]\) for the characteristic polynomial of the Frobenius endomorphism. The Frobenius norm is defined as the polynomial \(B(T) \in \mathbb{F}_q[T]\).
Let \(n\) be 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 Frobenius norm of the Drinfeld module, if the rank is two; raise a NotImplementedError otherwise.
Let \(\mathbb{F}_q[T]\) be the function ring, write \(\chi = T^2 - A(X)T + B(X) \in \mathbb{F}_q[T][X]\) for the characteristic polynomial of the Frobenius endomorphism. The Frobenius trace is defined as the polynomial \(A(T) \in \mathbb{F}_q[T]\).
Let \(n\) be the degree over \(\mathbb{F}_q\) of the base codomain. Then the Frobenius trace has degree at most \(\frac{n}{2}\).
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:
Let \(A(T)\) denote the Frobenius trace and \(B(T)\) denote the Frobenius norm. We begin by computing \(B(T)\), see docstring of method
frobenius_norm()
for details. The characteristic polynomial of the Frobenius yields \(t^{2n} - \phi_A t^n + \phi_B = 0\), where \(t^n\) is the Frobenius endomorphism. As \(\phi_B\) is now known, we can compute \(\phi_A = (t^{2n} + \phi_B) / t^n\). We get \(A(T)\) by inverting this quantity, using the methodsage.rings.function_fields.drinfeld_module.drinfeld_module.DrinfeldModule.invert()
, see its docstring for details.
- 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_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