Skip to content

Commit 93b5cf4

Browse files
committed
Merge branch 'drinfeld-module' of github:kryzar/sage into drinfeld-module
2 parents 24ad78a + 4c5666a commit 93b5cf4

File tree

6 files changed

+174
-137
lines changed

6 files changed

+174
-137
lines changed

src/sage/categories/drinfeld_modules.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# http://www.gnu.org/licenses/
1919
# ******************************************************************************
2020

21+
from sage.categories.objects import Objects
2122
from sage.categories.category_types import Category_over_base_ring
2223
from sage.categories.homsets import Homsets
2324
from sage.misc.functional import log
@@ -472,7 +473,7 @@ def object(self, gen):
472473
INPUT:
473474
474475
- ``gen`` -- the generator of the Drinfeld module, given as an Ore
475-
polynomial or a list of coefficients
476+
polynomial or a list of coefficients
476477
477478
EXAMPLES::
478479
@@ -565,9 +566,9 @@ def super_categories(self):
565566
sage: phi = DrinfeldModule(A, [p_root, 0, 0, 1])
566567
sage: C = phi.category()
567568
sage: C.super_categories()
568-
[]
569+
[Category of objects]
569570
"""
570-
return []
571+
return [Objects()]
571572

572573
class ParentMethods:
573574

src/sage/rings/function_field/drinfeld_modules/action.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def _latex_(self):
150150
sage: phi = DrinfeldModule(A, [z, 0, 0, 1])
151151
sage: action = phi.action()
152152
sage: latex(action)
153-
\text{Action{ }on{ }}\Bold{F}_{11^{2}}\text{{ }induced{ }by{ }}\text{Drinfeld{ }module{ }defined{ }by{ }} T \mapsto t^{3} + z\text{{ }over{ }base{ }}\Bold{F}_{11^{2}}
153+
\text{Action{ }on{ }}\Bold{F}_{11^{2}}\text{{ }induced{ }by{ }}\phi: T \mapsto t^{3} + z
154154
"""
155155
return f'\\text{{Action{{ }}on{{ }}}}' \
156156
f'{latex(self._base)}\\text{{{{ }}' \

src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py

Lines changed: 80 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@
2727
from sage.categories.drinfeld_modules import DrinfeldModules
2828
from sage.categories.homset import Hom
2929
from sage.misc.latex import latex
30+
from sage.misc.latex import latex_variable_name
31+
from sage.misc.lazy_string import _LazyString
3032
from sage.rings.integer import Integer
3133
from sage.rings.polynomial.ore_polynomial_element import OrePolynomial
3234
from sage.rings.polynomial.polynomial_ring import PolynomialRing_general
3335
from sage.rings.ring_extension import RingExtension_generic
3436
from sage.structure.parent import Parent
37+
from sage.structure.sage_object import SageObject
3538
from sage.structure.sequence import Sequence
3639
from sage.structure.unique_representation import UniqueRepresentation
3740

@@ -172,20 +175,13 @@ class DrinfeldModule(Parent, UniqueRepresentation):
172175
sage: phi(1) # phi_1
173176
1
174177
175-
One can give a LaTeX name to be used for LaTeX representation::
176-
177-
sage: sigma = DrinfeldModule(A, [z, 1, 1], latexname='\sigma')
178-
...
179-
sage: latex(sigma)
180-
\sigma
181-
182178
.. RUBRIC:: The category of Drinfeld modules
183179
184180
Drinfeld modules have their own category (see class
185181
:class:`sage.categories.drinfeld_modules.DrinfeldModules`)::
186182
187183
sage: phi.category()
188-
Category of Drinfeld modules defined over Finite Field in z of size 3^12 over its base
184+
Category of Drinfeld modules over Finite Field in z of size 3^12 over its base
189185
sage: phi.category() is psi.category()
190186
False
191187
sage: phi.category() is rho.category()
@@ -271,10 +267,10 @@ class DrinfeldModule(Parent, UniqueRepresentation):
271267
sage: phi.j_invariant() # j-invariant
272268
1
273269
274-
A Drinfeld `\mathbb{F}_q[T]`-module can be seen as an Ore
275-
polynomial with positive degree and constant coefficient
276-
`\gamma(T)`, where `\gamma` is the base morphism. This analogy is
277-
the motivation for the following methods::
270+
A Drinfeld `\mathbb{F}_q[T]`-module can be seen as an Ore polynomial
271+
with positive degree and constant coefficient `\gamma(T)`, where
272+
`\gamma` is the base morphism. This analogy is the motivation for
273+
the following methods::
278274
279275
sage: phi.coefficients()
280276
[z, 1, 1]
@@ -316,20 +312,13 @@ class DrinfeldModule(Parent, UniqueRepresentation):
316312
sage: identity_morphism = hom(1)
317313
sage: zero_morphism = hom(0)
318314
sage: frobenius_endomorphism
319-
Drinfeld Module morphism:
320-
From (gen): t^2 + t + z
321-
To (gen): t^2 + t + z
322-
Defn: t^6
315+
Endomorphism of Drinfeld module defined by T |--> t^2 + t + z
316+
Defn: t^6
323317
sage: identity_morphism
324-
Drinfeld Module morphism:
325-
From (gen): t^2 + t + z
326-
To (gen): t^2 + t + z
327-
Defn: 1
318+
Identity morphism of Drinfeld module defined by T |--> t^2 + t + z
328319
sage: zero_morphism
329-
Drinfeld Module morphism:
330-
From (gen): t^2 + t + z
331-
To (gen): t^2 + t + z
332-
Defn: 0
320+
Endomorphism of Drinfeld module defined by T |--> t^2 + t + z
321+
Defn: 0
333322
334323
The underlying Ore polynomial is retrieved with the method
335324
:meth:`ore_polynomial`::
@@ -512,7 +501,7 @@ class DrinfeldModule(Parent, UniqueRepresentation):
512501
"""
513502

514503
@staticmethod
515-
def __classcall_private__(cls, function_ring, gen, name='t', latexname=None):
504+
def __classcall_private__(cls, function_ring, gen, name='t'):
516505
"""
517506
Check input validity and return a ``DrinfeldModule`` or
518507
``FiniteDrinfeldModule`` object accordingly.
@@ -528,9 +517,6 @@ def __classcall_private__(cls, function_ring, gen, name='t', latexname=None):
528517
- ``name`` (default: ``'t'``) -- the name of the Ore polynomial
529518
ring gen
530519
531-
- ``latexname`` (default: ``None``) -- the LaTeX name of the Drinfeld
532-
module
533-
534520
OUTPUT:
535521
536522
A DrinfeldModule or FiniteDrinfeldModule.
@@ -591,10 +577,6 @@ def __classcall_private__(cls, function_ring, gen, name='t', latexname=None):
591577
base_field_noext.has_coerce_map_from(function_ring.base_ring())):
592578
raise ValueError('function ring base must coerce into base field')
593579

594-
# Check LaTeX name
595-
if latexname is not None and type(latexname) is not str:
596-
raise ValueError('LaTeX name should be a string')
597-
598580
# Build the category
599581
T = function_ring.gen()
600582
if isinstance(base_field_noext, RingExtension_generic):
@@ -607,6 +589,11 @@ def __classcall_private__(cls, function_ring, gen, name='t', latexname=None):
607589
base_morphism = Hom(function_ring, base_field_noext)(gen[0])
608590
base_field = base_field_noext.over(base_morphism)
609591

592+
# This test is also done in the category. We put it here also
593+
# to have a friendlier error message
594+
if not base_field.is_field():
595+
raise ValueError('generator coefficients must live in a field')
596+
610597
category = DrinfeldModules(base_field, name=name)
611598

612599
# Check gen as Ore polynomial
@@ -618,10 +605,10 @@ def __classcall_private__(cls, function_ring, gen, name='t', latexname=None):
618605
# Instantiate the appropriate class
619606
if base_field.is_finite():
620607
from sage.rings.function_field.drinfeld_modules.finite_drinfeld_module import FiniteDrinfeldModule
621-
return FiniteDrinfeldModule(gen, category, latexname)
622-
return cls.__classcall__(cls, gen, category, latexname)
608+
return FiniteDrinfeldModule(gen, category)
609+
return cls.__classcall__(cls, gen, category)
623610

624-
def __init__(self, gen, category, latexname=None):
611+
def __init__(self, gen, category):
625612
"""
626613
Initialize ``self``.
627614
@@ -639,9 +626,6 @@ def __init__(self, gen, category, latexname=None):
639626
- ``name`` (default: ``'t'``) -- the name of the Ore polynomial
640627
ring gen
641628
642-
- ``latexname`` (default: ``None``) -- the LaTeX name of the Drinfeld
643-
module
644-
645629
TESTS::
646630
647631
sage: Fq = GF(25)
@@ -661,13 +645,14 @@ def __init__(self, gen, category, latexname=None):
661645
True
662646
sage: phi._morphism == Hom(A, ore_polring)(phi._gen)
663647
True
664-
sage: phi._latexname is None
665-
True
648+
649+
::
650+
651+
sage: TestSuite(phi).run()
666652
"""
667653
self._base = category.base()
668654
self._function_ring = category.function_ring()
669655
self._gen = gen
670-
self._latexname = latexname
671656
self._morphism = category._function_ring.hom([gen])
672657
self._ore_polring = gen.parent()
673658
self._Fq = self._function_ring.base_ring() # Must be last
@@ -777,8 +762,8 @@ def _latex_(self):
777762
r"""
778763
Return a LaTeX representation of the Drinfeld module.
779764
780-
If a LaTeX name was given at initialization, we use it.
781-
Otherwise, we create a representation.
765+
If a representation name is given with meth:`rename`, it is
766+
taken into account for LaTeX representation.
782767
783768
EXAMPLES::
784769
@@ -788,29 +773,20 @@ def _latex_(self):
788773
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
789774
sage: phi = DrinfeldModule(A, [p_root, z12^3, z12^5])
790775
sage: latex(phi)
791-
\text{Drinfeld{ }module{ }defined{ }by{ }} T \mapsto z_{12}^{5} t^{2} + z_{12}^{3} t + 2 z_{12}^{11} + 2 z_{12}^{10} + z_{12}^{9} + 3 z_{12}^{8} + z_{12}^{7} + 2 z_{12}^{5} + 2 z_{12}^{4} + 3 z_{12}^{3} + z_{12}^{2} + 2 z_{12}\text{{ }over{ }base{ }}\Bold{F}_{5^{12}}
776+
\phi: T \mapsto z_{12}^{5} t^{2} + z_{12}^{3} t + 2 z_{12}^{11} + 2 z_{12}^{10} + z_{12}^{9} + 3 z_{12}^{8} + z_{12}^{7} + 2 z_{12}^{5} + 2 z_{12}^{4} + 3 z_{12}^{3} + z_{12}^{2} + 2 z_{12}
792777
793778
::
794779
795-
sage: psi = DrinfeldModule(A, [p_root, z12^3, z12^5], latexname='\psi')
796-
...
797-
sage: latex(psi)
798-
\psi
799-
800-
::
801-
802-
sage: psi = DrinfeldModule(A, [p_root, z12^3, z12^5], latexname=1729)
803-
Traceback (most recent call last):
804-
...
805-
ValueError: LaTeX name should be a string
780+
sage: phi.rename('phi')
781+
sage: latex(phi)
782+
\phi
783+
sage: phi.reset_name()
806784
"""
807-
if self._latexname is not None:
808-
return self._latexname
785+
if hasattr(self, '__custom_name'):
786+
return latex_variable_name(getattr(self, '__custom_name'))
809787
else:
810-
return f'\\text{{Drinfeld{{ }}module{{ }}defined{{ }}by{{ }}}} ' \
811-
f'{latex(self._function_ring.gen())} '\
812-
f'\\mapsto {latex(self._gen)}' \
813-
f'\\text{{{{ }}over{{ }}base{{ }}}}{latex(self._base)}'
788+
return f'\\phi: {latex(self._function_ring.gen())} \\mapsto ' \
789+
f'{latex(self._gen)}'
814790

815791
def _repr_(self):
816792
r"""
@@ -829,6 +805,49 @@ def _repr_(self):
829805
return f'Drinfeld module defined by {self._function_ring.gen()} ' \
830806
f'|--> {self._gen}'
831807

808+
def _test_category(self, **options):
809+
"""
810+
Run generic tests on the method :meth:`.category`.
811+
812+
EXAMPLES::
813+
814+
sage: Fq = GF(25)
815+
sage: A.<T> = Fq[]
816+
sage: K.<z12> = Fq.extension(6)
817+
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
818+
sage: phi = DrinfeldModule(A, [p_root, z12^3, z12^5])
819+
sage: phi._test_category()
820+
821+
.. NOTE::
822+
823+
We reimplemented this method because Drinfeld modules are
824+
parents, and
825+
meth:`sage.structure.parent.Parent._test_category` requires
826+
parents' categories to be subcategories of ``Sets()``.
827+
"""
828+
tester = self._tester(**options)
829+
SageObject._test_category(self, tester=tester)
830+
category = self.category()
831+
# Tests that self inherits methods from the categories
832+
tester.assertTrue(isinstance(self, category.parent_class),
833+
_LazyString("category of %s improperly initialized", (self,), {}))
834+
835+
def __hash__(self):
836+
r"""
837+
Return a hash of ``self``.
838+
839+
EXAMPLES::
840+
841+
sage: Fq = GF(25)
842+
sage: A.<T> = Fq[]
843+
sage: K.<z12> = Fq.extension(6)
844+
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
845+
sage: phi = DrinfeldModule(A, [p_root, z12^3, z12^5])
846+
sage: hash(phi) # random
847+
-6894299335185957188
848+
"""
849+
return hash((self.base(), self._gen))
850+
832851
def action(self):
833852
r"""
834853
Return the action object

src/sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,8 @@ class FiniteDrinfeldModule(DrinfeldModule):
7777
7878
sage: frobenius_endomorphism = phi.frobenius_endomorphism()
7979
sage: frobenius_endomorphism
80-
Drinfeld Module morphism:
81-
From (gen): 5*t^2 + z6
82-
To (gen): 5*t^2 + z6
83-
Defn: t^2
80+
Endomorphism of Drinfeld module defined by T |--> 5*t^2 + z6
81+
Defn: t^2
8482
8583
Its characteristic polynomial can be computed::
8684
@@ -118,7 +116,7 @@ class FiniteDrinfeldModule(DrinfeldModule):
118116
True
119117
"""
120118

121-
def __init__(self, gen, category, latexname=None):
119+
def __init__(self, gen, category):
122120
"""
123121
Initialize `self`.
124122
@@ -136,9 +134,6 @@ def __init__(self, gen, category, latexname=None):
136134
- ``name`` (default: `'t'`) -- the name of the Ore polynomial
137135
ring gen
138136
139-
- ``latexname`` (default: ``None``) -- the LaTeX name of the Drinfeld
140-
module
141-
142137
TESTS::
143138
144139
sage: Fq = GF(25)
@@ -154,7 +149,7 @@ def __init__(self, gen, category, latexname=None):
154149
# NOTE: There used to be no __init__ here (which was fine). I
155150
# added one to ensure that FiniteDrinfeldModule would always
156151
# have _frobenius_norm and _frobenius_trace attributes.
157-
super().__init__(gen, category, latexname)
152+
super().__init__(gen, category)
158153
self._frobenius_norm = None
159154
self._frobenius_trace = None
160155

@@ -174,10 +169,8 @@ def frobenius_endomorphism(self):
174169
sage: K.<z6> = Fq.extension(2)
175170
sage: phi = DrinfeldModule(A, [1, 0, z6])
176171
sage: phi.frobenius_endomorphism()
177-
Drinfeld Module morphism:
178-
From (gen): z6*t^2 + 1
179-
To (gen): z6*t^2 + 1
180-
Defn: t^2
172+
Endomorphism of Drinfeld module defined by T |--> z6*t^2 + 1
173+
Defn: t^2
181174
182175
TESTS::
183176

0 commit comments

Comments
 (0)