Skip to content

Hom spaces between Drinfeld modules #40440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
af1c2e9
Added basis computation over Fq[tau^n]
DocTrivial Nov 18, 2023
6b3e2a7
Merge branch 'develop' into isogeny
ymusleh Nov 18, 2023
3a14482
Morphism casting and citation
DocTrivial Nov 18, 2023
96f38e9
Merge branch 'isogeny' of https://github.com/ymusleh/sage into isogeny
DocTrivial Nov 18, 2023
25999df
Fixing linting
DocTrivial Nov 25, 2023
b48d29d
Merge branch 'sagemath:develop' into isogeny
ymusleh Jan 25, 2024
ca42dde
Merge branch 'isogeny' of https://github.com/ymusleh/sage into isogeny
DocTrivial Jan 25, 2024
a908f8a
adding fqx basis
ymusleh Jan 29, 2024
c302d79
added motive basis expansion
ymusleh May 29, 2024
b9ceb78
updates to basis decomposition for elements of the motive
ymusleh May 29, 2024
6a070ff
Merge branch 'isogeny' of https://github.com/ymusleh/sage into isogeny
ymusleh May 30, 2024
3cf4644
updates to Fq_basis and basis methods
ymusleh May 31, 2024
78f461f
Merge branch 'develop' of https://github.com/sagemath/sage into develop
Apr 5, 2025
c2cfa25
computation of a A-basis of Hom(phi, psi)
Apr 6, 2025
6f52dc1
conftest (grr)
Apr 6, 2025
bef913d
use cache
Apr 7, 2025
636d97e
Merge branch 'develop' into morphisms_drinfeld_modules
May 22, 2025
843a581
Merge branch 'ore_not_extension' into drinfeld_tau
Jul 17, 2025
7c1a26b
t -> τ
Jul 17, 2025
27e890b
declare encoding
Jul 17, 2025
227e9f5
remove the condition: nonzero constant coefficient
Jul 17, 2025
4123efd
Merge branch 'ore_not_extension' into useless_limitations
Jul 17, 2025
bf7b318
Merge branch 'develop' into morphisms_drinfeld_modules
Jul 18, 2025
2d2fa67
Merge branch 'develop' into isogeny
Jul 18, 2025
19223e0
Merge branch 'isogeny' into morphisms_drinfeld_modules
Jul 18, 2025
50808c0
Merge branch 'morphisms_drinfeld_modules' of /tmp/sage into morphisms…
Jul 18, 2025
281d9a6
reorganize methods
Jul 18, 2025
e036a21
Merge branch 'drinfeld_tau' into morphisms_drinfeld_modules
Jul 18, 2025
96c4726
t -> τ
Jul 18, 2025
dcd2553
Merge branch 'useless_limitations' into morphisms_drinfeld_modules
Jul 18, 2025
81c37bc
small fixes and doctests
Jul 18, 2025
bffd26e
reference to Musleh's thesis
Jul 18, 2025
f8c02a0
small fixes
Jul 19, 2025
bb7c336
Merge branch 'develop' into morphisms_drinfeld_modules
xcaruso Aug 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/doc/en/reference/references/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5240,6 +5240,9 @@ REFERENCES:
.. [Mur1983] \G. E. Murphy. *The idempotents of the symmetric group
and Nakayama's conjecture*. J. Algebra **81** (1983). 258-265.

.. [Mus2023] Yossef Musleh. *Algorithms for Drinfeld Modules*.
PhD thesis, University of Waterloo, 2023.

.. [Muth2019] Robert Muth. *Super RSK correspondence with symmetry*.
Electron. J. Combin. **26** (2019), no. 2, Paper 2.27, 29 pp.
https://www.combinatorics.org/ojs/index.php/eljc/article/view/v26i2p27,
Expand Down Expand Up @@ -6914,6 +6917,9 @@ REFERENCES:
*A new keystream generator MUGI*; in
FSE, (2002), pp. 179-194.

.. [Wes2022] \B. Wesolowski. 2022. *Computing isogenies between finite Drinfeld modules*.
Cryptology ePrint Archive, Paper 2022/438. https://eprint.iacr.org/2022/438

.. [Whi1932] \H. Whitney, *Congruent graphs and the connectivity of graphs*,
American Journal of Mathematics,
pages 150--168, 1932,
Expand Down
32 changes: 16 additions & 16 deletions src/sage/categories/drinfeld_modules.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# sage_setup: distribution = sagemath-categories
# sage.doctest: needs sage.rings.finite_rings
r"""
Expand Down Expand Up @@ -123,7 +124,7 @@ class DrinfeldModules(Category_over_base_ring):
True

sage: C.ore_polring()
Ore Polynomial Ring in t over Finite Field in z of size 11^4 twisted by z |--> z^11
Ore Polynomial Ring in τ over Finite Field in z of size 11^4 twisted by z |--> z^11
sage: C.ore_polring() is phi.ore_polring()
True

Expand All @@ -135,7 +136,7 @@ class DrinfeldModules(Category_over_base_ring):

sage: psi = C.object([p_root, 1])
sage: psi
Drinfeld module defined by T |--> t + z^3 + 7*z^2 + 6*z + 10
Drinfeld module defined by T |--> τ + z^3 + 7*z^2 + 6*z + 10
sage: psi.category() is C
True

Expand Down Expand Up @@ -207,7 +208,7 @@ class DrinfeldModules(Category_over_base_ring):
TypeError: function ring base must be a finite field
"""

def __init__(self, base_morphism, name='t'):
def __init__(self, base_morphism, name='τ'):
r"""
Initialize ``self``.

Expand All @@ -216,7 +217,7 @@ def __init__(self, base_morphism, name='t'):
- ``base_field`` -- the base field, which is a ring extension
over a base

- ``name`` -- (default: ``'t'``) the name of the Ore polynomial
- ``name`` -- (default: ``'τ'``) the name of the Ore polynomial
variable

TESTS::
Expand All @@ -227,7 +228,7 @@ def __init__(self, base_morphism, name='t'):
sage: p_root = z^3 + 7*z^2 + 6*z + 10
sage: phi = DrinfeldModule(A, [p_root, 0, 0, 1])
sage: C = phi.category()
sage: ore_polring.<t> = OrePolynomialRing(K, K.frobenius_endomorphism())
sage: ore_polring.<τ> = OrePolynomialRing(K, K.frobenius_endomorphism())
sage: C._ore_polring is ore_polring
True
sage: C._function_ring is A
Expand Down Expand Up @@ -438,7 +439,7 @@ def characteristic(self):

::

sage: psi = DrinfeldModule(A, [Frac(A).gen(), 1])
sage: psi = DrinfeldModule(A, [T, 1])
sage: C = psi.category()
sage: C.characteristic()
0
Expand Down Expand Up @@ -507,7 +508,7 @@ def object(self, gen):

sage: phi = C.object([p_root, 0, 1])
sage: phi
Drinfeld module defined by T |--> t^2 + z^3 + 7*z^2 + 6*z + 10
Drinfeld module defined by T |--> τ^2 + z^3 + 7*z^2 + 6*z + 10
sage: t = phi.ore_polring().gen()
sage: C.object(t^2 + z^3 + 7*z^2 + 6*z + 10) is phi
True
Expand All @@ -534,7 +535,7 @@ def ore_polring(self):
sage: phi = DrinfeldModule(A, [p_root, 0, 0, 1])
sage: C = phi.category()
sage: C.ore_polring()
Ore Polynomial Ring in t over Finite Field in z of size 11^4 twisted by z |--> z^11
Ore Polynomial Ring in τ over Finite Field in z of size 11^4 twisted by z |--> z^11
"""
return self._ore_polring

Expand Down Expand Up @@ -639,7 +640,7 @@ def base(self):

The base can be infinite::

sage: sigma = DrinfeldModule(A, [Frac(A).gen(), 1])
sage: sigma = DrinfeldModule(A, [T, 1])
sage: sigma.base()
Fraction Field of Univariate Polynomial Ring in T over Finite Field in z2 of size 5^2 over its base
"""
Expand All @@ -664,7 +665,7 @@ def base_morphism(self):

The base field can be infinite::

sage: sigma = DrinfeldModule(A, [Frac(A).gen(), 1])
sage: sigma = DrinfeldModule(A, [T, 1])
sage: sigma.base_morphism()
Coercion map:
From: Univariate Polynomial Ring in T over Finite Field in z2 of size 5^2
Expand Down Expand Up @@ -711,8 +712,7 @@ def characteristic(self):
::

sage: B.<Y> = Fq[]
sage: L = Frac(B)
sage: psi = DrinfeldModule(A, [L(1), 0, 0, L(1)])
sage: psi = DrinfeldModule(A, [B(1), 0, 0, 1])
sage: psi.characteristic()
Traceback (most recent call last):
...
Expand Down Expand Up @@ -770,7 +770,7 @@ def constant_coefficient(self):
sage: t = phi.ore_polring().gen()
sage: psi = C.object(phi.constant_coefficient() + t^3)
sage: psi
Drinfeld module defined by T |--> t^3 + 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
Drinfeld module defined by T |--> τ^3 + 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

Reciprocally, it is impossible to create two Drinfeld modules in
this category if they do not share the same constant
Expand All @@ -796,7 +796,7 @@ def ore_polring(self):
sage: phi = DrinfeldModule(A, [p_root, z12^3, z12^5])
sage: S = phi.ore_polring()
sage: S
Ore Polynomial Ring in t over Finite Field in z12 of size 5^12 twisted by z12 |--> z12^(5^2)
Ore Polynomial Ring in τ over Finite Field in z12 of size 5^12 twisted by z12 |--> z12^(5^2)

The Ore polynomial ring can also be retrieved from the category
of the Drinfeld module::
Expand Down Expand Up @@ -825,8 +825,8 @@ def ore_variable(self):
sage: phi = DrinfeldModule(A, [p_root, z12^3, z12^5])

sage: phi.ore_polring()
Ore Polynomial Ring in t over Finite Field in z12 of size 5^12 twisted by z12 |--> z12^(5^2)
Ore Polynomial Ring in τ over Finite Field in z12 of size 5^12 twisted by z12 |--> z12^(5^2)
sage: phi.ore_variable()
t
τ
"""
return self.category().ore_polring().gen()
7 changes: 4 additions & 3 deletions src/sage/rings/function_field/drinfeld_modules/action.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# sage.doctest: needs sage.rings.finite_rings
r"""
The module action induced by a Drinfeld module
Expand Down Expand Up @@ -60,7 +61,7 @@ class DrinfeldModuleAction(Action):
sage: action = phi.action()
sage: action
Action on Finite Field in z of size 11^2 over its base
induced by Drinfeld module defined by T |--> t^3 + z
induced by Drinfeld module defined by T |--> τ^3 + z

The action on elements is computed as follows::

Expand Down Expand Up @@ -154,7 +155,7 @@ def _latex_(self):
sage: phi = DrinfeldModule(A, [z, 0, 0, 1])
sage: action = phi.action()
sage: latex(action)
\text{Action{ }on{ }}\Bold{F}_{11^{2}}\text{{ }induced{ }by{ }}\phi: T \mapsto t^{3} + z
\text{Action{ }on{ }}\Bold{F}_{11^{2}}\text{{ }induced{ }by{ }}\phi: T \mapsto τ^{3} + z
"""
return f'\\text{{Action{{ }}on{{ }}}}' \
f'{latex(self._base)}\\text{{{{ }}' \
Expand All @@ -174,7 +175,7 @@ def _repr_(self):
sage: phi = DrinfeldModule(A, [z, 0, 0, 1])
sage: action = phi.action()
sage: action
Action on Finite Field in z of size 11^2 over its base induced by Drinfeld module defined by T |--> t^3 + z
Action on Finite Field in z of size 11^2 over its base induced by Drinfeld module defined by T |--> τ^3 + z
"""
return f'Action on {self._base} induced by ' \
f'{self._drinfeld_module}'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# sage.doctest: optional - sage.rings.finite_rings
r"""
Drinfeld modules over rings of characteristic zero
Expand Down Expand Up @@ -56,11 +57,10 @@ class DrinfeldModule_charzero(DrinfeldModule):
responsible for instantiating the right class depending on the
input::

sage: A = GF(3)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(3)[]
sage: phi = DrinfeldModule(A, [T, 1])
sage: phi
Drinfeld module defined by T |--> t + T
Drinfeld module defined by T |--> τ + T

::

Expand All @@ -75,8 +75,7 @@ class DrinfeldModule_charzero(DrinfeldModule):
It is possible to calculate the logarithm and the exponential of
any Drinfeld modules of characteristic zero::

sage: A = GF(2)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(2)[]
sage: phi = DrinfeldModule(A, [T, 1])
sage: phi.exponential()
z + ((1/(T^2+T))*z^2) + ((1/(T^8+T^6+T^5+T^3))*z^4) + O(z^8)
Expand All @@ -89,8 +88,7 @@ class DrinfeldModule_charzero(DrinfeldModule):
analytic theory of Drinfeld module. They provide a function field
analogue of certain classical trigonometric functions::

sage: A = GF(2)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(2)[]
sage: phi = DrinfeldModule(A, [T, 1])
sage: phi.goss_polynomial(1)
X
Expand All @@ -110,7 +108,7 @@ class DrinfeldModule_charzero(DrinfeldModule):
sage: L.<s> = LaurentSeriesRing(GF(2)) # s = 1/T
sage: phi = DrinfeldModule(A, [1/s, s + s^2 + s^5 + O(s^6), 1+1/s])
sage: phi(T)
(s^-1 + 1)*t^2 + (s + s^2 + s^5 + O(s^6))*t + s^-1
(s^-1 + 1)*τ^2 + (s + s^2 + s^5 + O(s^6))*τ + s^-1

One can also construct Drinfeld modules over SageMath's global
function fields::
Expand All @@ -119,7 +117,7 @@ class DrinfeldModule_charzero(DrinfeldModule):
sage: K.<z> = FunctionField(GF(5)) # z = T
sage: phi = DrinfeldModule(A, [z, 1, z^2])
sage: phi(T)
z^2*t^2 + t + z
z^2*τ^2 + τ + z
"""
@cached_method
def _compute_coefficient_exp(self, k):
Expand All @@ -133,8 +131,7 @@ def _compute_coefficient_exp(self, k):

TESTS::

sage: A = GF(2)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(2)[]
sage: phi = DrinfeldModule(A, [T, 1])
sage: q = A.base_ring().cardinality()
sage: phi._compute_coefficient_exp(0)
Expand Down Expand Up @@ -175,8 +172,7 @@ def exponential(self, prec=Infinity, name='z'):

EXAMPLES::

sage: A = GF(2)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(2)[]
sage: phi = DrinfeldModule(A, [T, 1])
sage: q = A.base_ring().cardinality()

Expand All @@ -199,8 +195,7 @@ def exponential(self, prec=Infinity, name='z'):

Example in higher rank::

sage: A = GF(5)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(5)[]
sage: phi = DrinfeldModule(A, [T, T^2, T + T^2 + T^4, 1])
sage: exp = phi.exponential(); exp
z + ((T/(T^4+4))*z^5) + O(z^8)
Expand All @@ -217,8 +212,7 @@ def exponential(self, prec=Infinity, name='z'):

TESTS::

sage: A = GF(2)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(2)[]
sage: phi = DrinfeldModule(A, [T, 1])
sage: exp = phi.exponential()
sage: exp[2] == 1/(T**q - T) # expected value
Expand Down Expand Up @@ -259,8 +253,7 @@ def _compute_coefficient_log(self, k):

TESTS::

sage: A = GF(2)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(2)[]
sage: phi = DrinfeldModule(A, [T, 1])
sage: q = A.base_ring().cardinality()
sage: phi._compute_coefficient_log(0)
Expand Down Expand Up @@ -305,8 +298,7 @@ def logarithm(self, prec=Infinity, name='z'):

EXAMPLES::

sage: A = GF(2)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(2)[]
sage: phi = DrinfeldModule(A, [T, 1])

When ``prec`` is ``Infinity`` (which is the default),
Expand All @@ -328,16 +320,14 @@ def logarithm(self, prec=Infinity, name='z'):

Example in higher rank::

sage: A = GF(5)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(5)[]
sage: phi = DrinfeldModule(A, [T, T^2, T + T^2 + T^4, 1])
sage: phi.logarithm()
z + ((4*T/(T^4+4))*z^5) + O(z^8)

TESTS::

sage: A = GF(2)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(2)[]
sage: phi = DrinfeldModule(A, [T, 1])
sage: q = 2
sage: log[2] == -1/((T**q - T)) # expected value
Expand Down Expand Up @@ -374,8 +364,7 @@ def _compute_goss_polynomial(self, n, q, poly_ring, X):

TESTS::

sage: A = GF(2^2)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(2^2)[]
sage: phi = DrinfeldModule(A, [T, T+1, T^2, 1])
sage: poly_ring = phi.base()['X']
sage: X = poly_ring.gen()
Expand Down Expand Up @@ -423,8 +412,7 @@ def goss_polynomial(self, n, var='X'):

EXAMPLES::

sage: A = GF(3)['T']
sage: K.<T> = Frac(A)
sage: A.<T> = GF(3)[]
sage: phi = DrinfeldModule(A, [T, 1]) # Carlitz module
sage: phi.goss_polynomial(1)
X
Expand Down Expand Up @@ -459,10 +447,9 @@ class DrinfeldModule_rational(DrinfeldModule_charzero):

sage: q = 9
sage: Fq = GF(q)
sage: A = Fq['T']
sage: K.<T> = Frac(A)
sage: A.<T> = Fq[]
sage: C = DrinfeldModule(A, [T, 1]); C
Drinfeld module defined by T |--> t + T
Drinfeld module defined by T |--> τ + T
sage: type(C)
<class 'sage.rings.function_field.drinfeld_modules.charzero_drinfeld_module.DrinfeldModule_rational_with_category'>
"""
Expand All @@ -479,9 +466,8 @@ def coefficient_in_function_ring(self, n):

sage: q = 5
sage: Fq = GF(q)
sage: A = Fq['T']
sage: R = Fq['U']
sage: K.<U> = Frac(R)
sage: A.<T> = Fq[]
sage: R.<U> = Fq[]
sage: phi = DrinfeldModule(A, [U, 0, U^2, U^3])
sage: phi.coefficient_in_function_ring(2)
T^2
Expand Down Expand Up @@ -524,9 +510,8 @@ def coefficients_in_function_ring(self, sparse=True):

sage: q = 5
sage: Fq = GF(q)
sage: A = Fq['T']
sage: R = Fq['U']
sage: K.<U> = Frac(R)
sage: A.<T> = Fq[]
sage: R.<U> = Fq[]
sage: phi = DrinfeldModule(A, [U, 0, U^2, U^3])
sage: phi.coefficients_in_function_ring()
[T, T^2, T^3]
Expand Down Expand Up @@ -570,10 +555,9 @@ def class_polynomial(self):

sage: q = 5
sage: Fq = GF(q)
sage: A = Fq['T']
sage: K.<T> = Frac(A)
sage: A.<T> = Fq[]
sage: C = DrinfeldModule(A, [T, 1]); C
Drinfeld module defined by T |--> t + T
Drinfeld module defined by T |--> τ + T
sage: C.class_polynomial()
1

Expand Down
Loading
Loading