Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Add various getters for FiniteDrinfeldModule
Browse files Browse the repository at this point in the history
This commit is a bit dirty, apologies. There are new getters (see
below), and the commit includes some refactoring of the doctests.

The added getters are:
    - characteristic,
    - constant_term,
    - delta (rank two specific),
    - g (rank two specific),
    - height,
    - j (rank two specific).
  • Loading branch information
kryzar committed May 12, 2022
1 parent f0a9f63 commit 86348ff
Showing 1 changed file with 88 additions and 47 deletions.
135 changes: 88 additions & 47 deletions src/sage/modules/finite_drinfeld_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from sage.categories.action import Action
from sage.categories.homset import Hom
from sage.misc.latex import latex
from sage.rings.integer import Integer
from sage.rings.morphism import RingHomomorphism_im_gens
from sage.rings.polynomial.ore_polynomial_element import OrePolynomial
from sage.rings.polynomial.ore_polynomial_ring import OrePolynomialRing
Expand All @@ -57,68 +58,75 @@ class FiniteDrinfeldModule(RingHomomorphism_im_gens):
First, create base objects::
sage: Fq = GF(7^2)
sage: Fq.<z2> = GF(3^2)
sage: FqX.<X> = Fq[]
sage: L = Fq.extension(3)
sage: frobenius = L.frobenius_endomorphism(2)
sage: Ltau.<t> = OrePolynomialRing(L, frobenius)
sage: p = X^3 + (z2 + 2)*X^2 + (6*z2 + 1)*X + 3*z2 + 5
sage: L = Fq.extension(6)
sage: Ltau.<t> = OrePolynomialRing(L, L.frobenius_endomorphism(2))
sage: omega = p.roots(L, multiplicities=False)[0]
sage: phi_X = omega + t + t^2
Then we instanciate the Drinfeld module::
sage: phi_X = 1 + t^2
sage: phi = FiniteDrinfeldModule(FqX, phi_X)
sage: phi = FiniteDrinfeldModule(FqX, phi_X, p)
sage: phi
Finite Drinfeld module from Univariate Polynomial Ring in X over Finite Field in z2 of size 7^2 over Finite Field in z6 of size 7^6 generated by t^2 + 1.
Finite Drinfeld module:
Polring: Univariate Polynomial Ring in X over Finite Field in z2 of size 3^2
Ore polring: Ore Polynomial Ring in t over Finite Field in z12 of size 3^12 twisted by z12 |--> z12^(3^2)
Generator: t^2 + t + z12^11 + z12^10 + z12^9 + 2*z12^5 + 2*z12^4 + z12^3 + 2*z12
Characteristic: X^3 + (z2 + 2)*X^2 + X + 2
There are getters for the base objects::
sage: phi.polring()
Univariate Polynomial Ring in X over Finite Field in z2 of size 7^2
Univariate Polynomial Ring in X over Finite Field in z2 of size 3^2
sage: phi.ore_polring()
Ore Polynomial Ring in t over Finite Field in z6 of size 7^6 twisted by z6 |--> z6^(7^2)
Ore Polynomial Ring in t over Finite Field in z12 of size 3^12 twisted by z12 |--> z12^(3^2)
sage: phi.gen()
t^2 + 1
t^2 + t + z12^11 + z12^10 + z12^9 + 2*z12^5 + 2*z12^4 + z12^3 + 2*z12
And the class inherits `RingHomomorphism_im_gens`, so that one can
use::
sage: phi.domain()
Univariate Polynomial Ring in X over Finite Field in z2 of size 7^2
Univariate Polynomial Ring in X over Finite Field in z2 of size 3^2
sage: phi.codomain()
Ore Polynomial Ring in t over Finite Field in z6 of size 7^6 twisted by z6 |--> z6^(7^2)
Ore Polynomial Ring in t over Finite Field in z12 of size 3^12 twisted by z12 |--> z12^(3^2)
sage: phi.im_gens()
[t^2 + 1]
[t^2 + t + z12^11 + z12^10 + z12^9 + 2*z12^5 + 2*z12^4 + z12^3 + 2*z12]
The rank of the Drinfeld module is retrieved with::
We can retrieve basic quantities:
sage: phi.rank()
2
sage: phi.j()
1
.. RUBRIC:: The module law induced by a Drinfeld module
The most important feature of Drinfeld modules is that they induce
an `\Fq[X]`-module law on the algebraic closure `\Fqbar` of `\Fq`.
We implement this action for any finite field extension `M` of `L`.
The `_get_action_` method returns an `Action` object::
an `\Fq[X]`-module law on any subextension of the algebraic closure
`\Fqbar` of `\Fq`. For this, we created the class
`FiniteDrinfeldModuleAction`, which inherits `Action`. For the sake
of simplicity, `phi` will only act on the base field (`L`) of its
Ore polynomial ring. If you want to act on a bigger field, you can
use the method `change_ring`.
sage: M = L.extension(2)
sage: action = phi._get_action_(M)
sage: action
sage: phi_M = phi.change_ring(M) # todo: not tested
sage: action = phi._get_action_() # todo: not tested
sage: action # todo: not tested
Action on Finite Field in z12 of size 7^12 induced by the Finite Drinfeld module from Univariate Polynomial Ring in X over Finite Field in z2 of size 7^2 over Finite Field in z6 of size 7^6
generated by t^2 + 1.
sage: x = M.gen()
sage: g = X^3 + X + 5
sage: action(g, x)
The calculation of the action is simple:
sage: x = M.gen() # todo: not tested
sage: g = X^3 + X + 5 # todo: not tested
sage: action(g, x) # todo: not tested
...
6*z12^11 + 5*z12^9 + 5*z12^8 + 2*z12^7 + 6*z12^6 + z12^5 + 6*z12^4 + 2*z12^3 + 3*z12^2 + 5*z12 + 4
Furthermore, it can be useful to embed a Drinfeld module into a
larger Ore polynomial ring::
sage: M = L.extension(2)
sage: psi = phi.change_ring(M); psi
Finite Drinfeld module from Univariate Polynomial Ring in X over Finite Field in z2 of size 7^2 over Finite Field in z12 of size 7^12 generated by t^2 + 1.
.. NOTE::
The general definition of a Drinfeld module is out of the scope
Expand All @@ -136,35 +144,37 @@ class FiniteDrinfeldModule(RingHomomorphism_im_gens):
:mod:`sage.rings.polynomial.ore_polynomial_ring`
"""

def __init__(self, polring, gen):
# VERIFICATIONS
# Check `polring` is an Fq[X]:
# See docstrings of `PolynomialRing_dense_finite_field` and
# `is_PolynomialRing`.
isinstance(polring, PolynomialRing_dense_finite_field)
# Check `gen` is an Ore polynomial:
def __init__(self, polring, gen, characteristic):
# Verifications
if not isinstance(polring, PolynomialRing_dense_finite_field):
raise TypeError('First argument must be a polynomial ring')
if not characteristic in polring:
raise TypeError('The characteristic must be in the polynomial ' \
'ring')
if not characteristic.is_prime():
raise ValueError('The characteristic must be irreducible')
if not isinstance(gen, OrePolynomial):
raise TypeError('The generator must be an Ore polynomial')
# Now we can define those for convenience:
# We define those for convenience before continuing
FqX = polring
Ltau = gen.parent()
Fq = FqX.base_ring()
L = Ltau.base_ring()
# Check the Ore polynomial ring is an L{tau} with L a finite
# field extension of Fq:
_check_base_fields(Fq, L)
if not Ltau.twisting_derivation() is None:
raise ValueError('The Ore polynomial ring should have no ' \
'derivation')
# Check the frobenius is x -> x^q:
if Ltau.twisting_morphism().power() != Fq.degree():
raise ValueError('The twisting morphism of the Ore polynomial ' \
'ring must be the Frobenius endomorphism of the base ' \
'field of the polynomial ring')
# The generator is not constant:
if characteristic(gen[0]) != 0:
raise ValueError('The constant coefficient of the generator ' \
'must be a root of the characteristic')
if gen.is_constant():
raise ValueError('The generator must not be constant')
# ACTUAL WORK
# Finally
self.__characteristic = characteristic
super().__init__(Hom(FqX, Ltau), gen)

###########
Expand All @@ -183,7 +193,30 @@ def change_ring(self, R):
new_frobenius = R.frobenius_endomorphism(self.frobenius().power())
new_ore_polring = OrePolynomialRing(R, new_frobenius,
names=self.ore_polring().variable_names())
return FiniteDrinfeldModule(self.polring(), new_ore_polring(self.gen()))
return FiniteDrinfeldModule(self.polring(),
new_ore_polring(self.gen()), self.characteristic())

def delta(self):
if self.rank() != 2:
raise ValueError('The rank must equal 2')
return self.gen()[2]

def g(self):
if self.rank() != 2:
raise ValueError('The rank must equal 2')
return self.gen()[1]

def height(self):
return Integer(1)

def j(self):
if self.rank() != 2:
raise ValueError('The j-invariant is only defined for rank 2 ' \
'Drinfeld modules')
g = self.gen()[1]
delta = self.gen()[2]
q = self.polring().base_ring().order()
return (g**(q+1)) / delta

def rank(self):
return self.gen().degree()
Expand All @@ -196,8 +229,7 @@ def _get_action_(self):
return FiniteDrinfeldModuleAction(self)

def _latex_(self):
return f'\\text{{Finite{{ }}{latex(self.polring())}-Drinfeld{{ }}' \
f'module{{ }}defined{{ }}by{{ }}}}\n' \
return f'\\text{{Finite{{ }}Drinfeld{{ }}module{{ }}defined{{ }}by{{ }}}}\n' \
f'\\begin{{align}}\n' \
f' {latex(self.polring())}\n' \
f' &\\to {latex(self.ore_polring())} \\\\\n' \
Expand All @@ -208,13 +240,22 @@ def _latex_(self):
f'{latex(self.characteristic())}'

def _repr_(self):
return f'Finite Drinfeld module from {self.polring()} over ' \
f'{self.ore_polring().base_ring()} generated by {self.gen()}.'
return f'Finite Drinfeld module:\n' \
f' Polring: {self.polring()}\n' \
f' Ore polring: {self.ore_polring()}\n' \
f' Generator: {self.gen()}\n' \
f' Characteristic: {self.characteristic()}'

###########
# Getters #
###########

def characteristic(self):
return self.__characteristic

def constant_term(self):
return self.gen()[0]

def frobenius(self):
return self.ore_polring().twisting_morphism()

Expand Down

0 comments on commit 86348ff

Please sign in to comment.