Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/abvar/cuspidal_subgroup.py
4057 views
1
"""
2
Cuspidal subgroups of modular abelian varieties
3
4
AUTHORS:
5
6
- William Stein (2007-03, 2008-02)
7
8
EXAMPLES: We compute the cuspidal subgroup of `J_1(13)`::
9
10
sage: A = J1(13)
11
sage: C = A.cuspidal_subgroup(); C
12
Finite subgroup with invariants [19, 19] over QQ of Abelian variety J1(13) of dimension 2
13
sage: C.gens()
14
[[(1/19, 0, 0, 9/19)], [(0, 1/19, 1/19, 18/19)]]
15
sage: C.order()
16
361
17
sage: C.invariants()
18
[19, 19]
19
20
We compute the cuspidal subgroup of `J_0(54)`::
21
22
sage: A = J0(54)
23
sage: C = A.cuspidal_subgroup(); C
24
Finite subgroup with invariants [3, 3, 3, 3, 3, 9] over QQ of Abelian variety J0(54) of dimension 4
25
sage: C.gens()
26
[[(1/3, 0, 0, 0, 0, 1/3, 0, 2/3)], [(0, 1/3, 0, 0, 0, 2/3, 0, 1/3)], [(0, 0, 1/9, 1/9, 1/9, 1/9, 1/9, 2/9)], [(0, 0, 0, 1/3, 0, 1/3, 0, 0)], [(0, 0, 0, 0, 1/3, 1/3, 0, 1/3)], [(0, 0, 0, 0, 0, 0, 1/3, 2/3)]]
27
sage: C.order()
28
2187
29
sage: C.invariants()
30
[3, 3, 3, 3, 3, 9]
31
32
We compute the subgroup of the cuspidal subgroup generated by
33
rational cusps.
34
35
::
36
37
sage: C = J0(54).rational_cusp_subgroup(); C
38
Finite subgroup with invariants [3, 3, 9] over QQ of Abelian variety J0(54) of dimension 4
39
sage: C.gens()
40
[[(1/3, 0, 0, 1/3, 2/3, 1/3, 0, 1/3)], [(0, 0, 1/9, 1/9, 7/9, 7/9, 1/9, 8/9)], [(0, 0, 0, 0, 0, 0, 1/3, 2/3)]]
41
sage: C.order()
42
81
43
sage: C.invariants()
44
[3, 3, 9]
45
46
This might not give us the exact rational torsion subgroup, since
47
it might be bigger than order `81`::
48
49
sage: J0(54).rational_torsion_subgroup().multiple_of_order()
50
243
51
52
TESTS::
53
54
sage: C = J0(54).cuspidal_subgroup()
55
sage: loads(dumps(C)) == C
56
True
57
sage: D = J0(54).rational_cusp_subgroup()
58
sage: loads(dumps(D)) == D
59
True
60
"""
61
62
###########################################################################
63
# Copyright (C) 2007 William Stein <[email protected]> #
64
# Distributed under the terms of the GNU General Public License (GPL) #
65
# http://www.gnu.org/licenses/ #
66
###########################################################################
67
68
from finite_subgroup import FiniteSubgroup
69
from sage.rings.all import infinity, QQ, gcd, ZZ
70
from sage.matrix.all import matrix
71
from sage.modular.arithgroup.all import is_Gamma0
72
from sage.modular.cusps import Cusp
73
74
class CuspidalSubgroup_generic(FiniteSubgroup):
75
def _compute_lattice(self, rational_only=False, rational_subgroup=False):
76
r"""
77
Return a list of vectors that define elements of the rational
78
homology that generate this finite subgroup.
79
80
INPUT:
81
82
83
- ``rational_only`` - bool (default: False); if
84
``True``, only use rational cusps.
85
86
87
OUTPUT:
88
89
90
- ``list`` - list of vectors
91
92
93
EXAMPLES::
94
95
sage: J = J0(37)
96
sage: C = sage.modular.abvar.cuspidal_subgroup.CuspidalSubgroup(J)
97
sage: C._compute_lattice()
98
Free module of degree 4 and rank 4 over Integer Ring
99
Echelon basis matrix:
100
[ 1 0 0 0]
101
[ 0 1 0 0]
102
[ 0 0 1 0]
103
[ 0 0 0 1/3]
104
sage: J = J0(43)
105
sage: C = sage.modular.abvar.cuspidal_subgroup.CuspidalSubgroup(J)
106
sage: C._compute_lattice()
107
Free module of degree 6 and rank 6 over Integer Ring
108
Echelon basis matrix:
109
[ 1 0 0 0 0 0]
110
[ 0 1/7 0 6/7 0 5/7]
111
[ 0 0 1 0 0 0]
112
[ 0 0 0 1 0 0]
113
[ 0 0 0 0 1 0]
114
[ 0 0 0 0 0 1]
115
sage: J = J0(22)
116
sage: C = sage.modular.abvar.cuspidal_subgroup.CuspidalSubgroup(J)
117
sage: C._compute_lattice()
118
Free module of degree 4 and rank 4 over Integer Ring
119
Echelon basis matrix:
120
[1/5 1/5 4/5 0]
121
[ 0 1 0 0]
122
[ 0 0 1 0]
123
[ 0 0 0 1/5]
124
sage: J = J1(13)
125
sage: C = sage.modular.abvar.cuspidal_subgroup.CuspidalSubgroup(J)
126
sage: C._compute_lattice()
127
Free module of degree 4 and rank 4 over Integer Ring
128
Echelon basis matrix:
129
[ 1/19 0 0 9/19]
130
[ 0 1/19 1/19 18/19]
131
[ 0 0 1 0]
132
[ 0 0 0 1]
133
134
We compute with and without the optional
135
``rational_only`` option.
136
137
::
138
139
sage: J = J0(27); G = sage.modular.abvar.cuspidal_subgroup.CuspidalSubgroup(J)
140
sage: G._compute_lattice()
141
Free module of degree 2 and rank 2 over Integer Ring
142
Echelon basis matrix:
143
[1/3 0]
144
[ 0 1/3]
145
sage: G._compute_lattice(rational_only=True)
146
Free module of degree 2 and rank 2 over Integer Ring
147
Echelon basis matrix:
148
[1/3 0]
149
[ 0 1]
150
"""
151
A = self.abelian_variety()
152
Cusp = A.modular_symbols()
153
Amb = Cusp.ambient_module()
154
Eis = Amb.eisenstein_submodule()
155
156
C = Amb.cusps()
157
N = Amb.level()
158
159
if rational_subgroup:
160
# QQ-rational subgroup of cuspidal subgroup
161
assert A.is_ambient()
162
Q = Cusp.abvarquo_rational_cuspidal_subgroup()
163
return Q.V()
164
165
if rational_only:
166
# subgroup generated by differences of rational cusps
167
if not is_Gamma0(A.group()):
168
raise NotImplementedError, 'computation of rational cusps only implemented in Gamma0 case.'
169
if not N.is_squarefree():
170
data = [n for n in range(2,N) if gcd(n,N) == 1]
171
C = [c for c in C if is_rational_cusp_gamma0(c, N, data)]
172
173
v = [Amb([infinity, alpha]).element() for alpha in C]
174
cusp_matrix = matrix(QQ, len(v), Amb.dimension(), v)
175
176
# TODO -- refactor something out here
177
# Now we project onto the cuspidal part.
178
B = Cusp.free_module().basis_matrix().stack(Eis.free_module().basis_matrix())
179
X = B.solve_left(cusp_matrix)
180
X = X.matrix_from_columns(range(Cusp.dimension()))
181
lattice = X.row_module(ZZ) + A.lattice()
182
return lattice
183
184
class CuspidalSubgroup(CuspidalSubgroup_generic):
185
"""
186
EXAMPLES::
187
188
sage: a = J0(65)[2]
189
sage: t = a.cuspidal_subgroup()
190
sage: t.order()
191
6
192
"""
193
def _repr_(self):
194
"""
195
String representation of the cuspidal subgroup.
196
197
EXAMPLES::
198
199
sage: G = J0(27).cuspidal_subgroup()
200
sage: G._repr_()
201
'Finite subgroup with invariants [3, 3] over QQ of Abelian variety J0(27) of dimension 1'
202
"""
203
return "Cuspidal subgroup %sover QQ of %s"%(self._invariants_repr(), self.abelian_variety())
204
205
206
def lattice(self):
207
"""
208
Returned cached tuple of vectors that define elements of the
209
rational homology that generate this finite subgroup.
210
211
OUTPUT:
212
213
214
- ``tuple`` - cached
215
216
217
EXAMPLES::
218
219
sage: J = J0(27)
220
sage: G = J.cuspidal_subgroup()
221
sage: G.lattice()
222
Free module of degree 2 and rank 2 over Integer Ring
223
Echelon basis matrix:
224
[1/3 0]
225
[ 0 1/3]
226
227
Test that the result is cached::
228
229
sage: G.lattice() is G.lattice()
230
True
231
"""
232
try:
233
return self.__lattice
234
except AttributeError:
235
lattice = self._compute_lattice(rational_only = False)
236
self.__lattice = lattice
237
return lattice
238
239
class RationalCuspSubgroup(CuspidalSubgroup_generic):
240
"""
241
EXAMPLES::
242
243
sage: a = J0(65)[2]
244
sage: t = a.rational_cusp_subgroup()
245
sage: t.order()
246
6
247
"""
248
def _repr_(self):
249
"""
250
String representation of the cuspidal subgroup.
251
252
EXAMPLES::
253
254
sage: G = J0(27).rational_cusp_subgroup()
255
sage: G._repr_()
256
'Finite subgroup with invariants [3] over QQ of Abelian variety J0(27) of dimension 1'
257
"""
258
return "Subgroup generated by differences of rational cusps %sover QQ of %s"%(self._invariants_repr(), self.abelian_variety())
259
260
261
def lattice(self):
262
"""
263
Return lattice that defines this group.
264
265
OUTPUT: lattice
266
267
EXAMPLES::
268
269
sage: G = J0(27).rational_cusp_subgroup()
270
sage: G.lattice()
271
Free module of degree 2 and rank 2 over Integer Ring
272
Echelon basis matrix:
273
[1/3 0]
274
[ 0 1]
275
276
Test that the result is cached.
277
278
::
279
280
sage: G.lattice() is G.lattice()
281
True
282
"""
283
try:
284
return self.__lattice
285
except AttributeError:
286
lattice = self._compute_lattice(rational_only = True)
287
self.__lattice = lattice
288
return lattice
289
290
class RationalCuspidalSubgroup(CuspidalSubgroup_generic):
291
"""
292
EXAMPLES::
293
294
sage: a = J0(65)[2]
295
sage: t = a.rational_cuspidal_subgroup()
296
sage: t.order()
297
6
298
"""
299
def _repr_(self):
300
"""
301
String representation of the cuspidal subgroup.
302
303
EXAMPLES::
304
305
sage: G = J0(27).rational_cuspidal_subgroup()
306
sage: G._repr_()
307
'Finite subgroup with invariants [3] over QQ of Abelian variety J0(27) of dimension 1'
308
"""
309
return "Rational cuspidal subgroup %sover QQ of %s"%(self._invariants_repr(), self.abelian_variety())
310
311
def lattice(self):
312
"""
313
Return lattice that defines this group.
314
315
OUTPUT: lattice
316
317
EXAMPLES::
318
319
sage: G = J0(27).rational_cuspidal_subgroup()
320
sage: G.lattice()
321
Free module of degree 2 and rank 2 over Integer Ring
322
Echelon basis matrix:
323
[1/3 0]
324
[ 0 1]
325
326
Test that the result is cached.
327
328
::
329
330
sage: G.lattice() is G.lattice()
331
True
332
"""
333
try:
334
return self.__lattice
335
except AttributeError:
336
lattice = self._compute_lattice(rational_subgroup = True)
337
self.__lattice = lattice
338
return lattice
339
340
def is_rational_cusp_gamma0(c, N, data):
341
"""
342
Return True if the rational number c is a rational cusp of level N.
343
This uses remarks in Glenn Steven's Ph.D. thesis.
344
345
INPUT:
346
347
348
- ``c`` - a cusp
349
350
- ``N`` - a positive integer
351
352
- ``data`` - the list [n for n in range(2,N) if
353
gcd(n,N) == 1], which is passed in as a parameter purely for
354
efficiency reasons.
355
356
357
EXAMPLES::
358
359
sage: from sage.modular.abvar.cuspidal_subgroup import is_rational_cusp_gamma0
360
sage: N = 27
361
sage: data = [n for n in range(2,N) if gcd(n,N) == 1]
362
sage: is_rational_cusp_gamma0(Cusp(1/3), N, data)
363
False
364
sage: is_rational_cusp_gamma0(Cusp(1), N, data)
365
True
366
sage: is_rational_cusp_gamma0(Cusp(oo), N, data)
367
True
368
sage: is_rational_cusp_gamma0(Cusp(2/9), N, data)
369
False
370
"""
371
num = c.numerator()
372
den = c.denominator()
373
for d in data:
374
if not c.is_gamma0_equiv(Cusp(num,d*den), N):
375
return False
376
return True
377
378