Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/modsym/subspace.py
4048 views
1
"""
2
Subspace of ambient spaces of modular symbols
3
"""
4
5
#*****************************************************************************
6
# Sage: System for Algebra and Geometry Experimentation
7
#
8
# Copyright (C) 2005 William Stein <[email protected]>
9
#
10
# Distributed under the terms of the GNU General Public License (GPL)
11
#
12
# This code is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
# General Public License for more details.
16
#
17
# The full text of the GPL is available at:
18
#
19
# http://www.gnu.org/licenses/
20
#*****************************************************************************
21
22
23
import sage.modular.hecke.all as hecke
24
25
import sage.structure.factorization
26
27
import sage.modular.modsym.space
28
29
30
31
class ModularSymbolsSubspace(sage.modular.modsym.space.ModularSymbolsSpace, hecke.HeckeSubmodule):
32
"""
33
Subspace of ambient space of modular symbols
34
"""
35
################################
36
# Special Methods
37
################################
38
def __init__(self, ambient_hecke_module, submodule,
39
dual_free_module=None, check=False):
40
"""
41
INPUT:
42
43
44
- ``ambient_hecke_module`` - the ambient space of
45
modular symbols in which we're constructing a submodule
46
47
- ``submodule`` - the underlying free module of the
48
submodule
49
50
- ``dual_free_module`` - underlying free module of
51
the dual of the submodule (optional)
52
53
- ``check`` - (default: False) whether to check that
54
the submodule is invariant under all Hecke operators T_p.
55
56
57
EXAMPLES::
58
59
sage: M = ModularSymbols(15,4) ; S = M.cuspidal_submodule() # indirect doctest
60
sage: S
61
Modular Symbols subspace of dimension 8 of Modular Symbols space of dimension 12 for Gamma_0(15) of weight 4 with sign 0 over Rational Field
62
sage: S == loads(dumps(S))
63
True
64
sage: M = ModularSymbols(1,24)
65
sage: A = M.ambient_hecke_module()
66
sage: B = A.submodule([ x.element() for x in M.cuspidal_submodule().gens() ])
67
sage: S = sage.modular.modsym.subspace.ModularSymbolsSubspace(A, B.free_module())
68
sage: S
69
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 5 for Gamma_0(1) of weight 24 with sign 0 over Rational Field
70
sage: S == loads(dumps(S))
71
True
72
"""
73
self.__ambient_hecke_module = ambient_hecke_module
74
A = ambient_hecke_module
75
sage.modular.modsym.space.ModularSymbolsSpace.__init__(self, A.group(), A.weight(), \
76
A.character(), A.sign(), A.base_ring())
77
hecke.HeckeSubmodule.__init__(self, A, submodule, dual_free_module = dual_free_module, check=check)
78
79
def _repr_(self):
80
"""
81
Return the string representation of self.
82
83
EXAMPLES::
84
85
sage: ModularSymbols(24,4).cuspidal_subspace()._repr_()
86
'Modular Symbols subspace of dimension 16 of Modular Symbols space of dimension 24 for Gamma_0(24) of weight 4 with sign 0 over Rational Field'
87
"""
88
return "Modular Symbols subspace of dimension %s of %s"%(
89
self.rank(), self.ambient_module())
90
91
################################
92
# Public functions
93
################################
94
def boundary_map(self):
95
"""
96
The boundary map to the corresponding space of boundary modular
97
symbols. (This is the restriction of the map on the ambient
98
space.)
99
100
EXAMPLES::
101
102
sage: M = ModularSymbols(1, 24, sign=1) ; M
103
Modular Symbols space of dimension 3 for Gamma_0(1) of weight 24 with sign 1 over Rational Field
104
sage: M.basis()
105
([X^18*Y^4,(0,0)], [X^20*Y^2,(0,0)], [X^22,(0,0)])
106
sage: M.cuspidal_submodule().basis()
107
([X^18*Y^4,(0,0)], [X^20*Y^2,(0,0)])
108
sage: M.eisenstein_submodule().basis()
109
([X^18*Y^4,(0,0)] + 166747/324330*[X^20*Y^2,(0,0)] + 236364091/6742820700*[X^22,(0,0)],)
110
sage: M.boundary_map()
111
Hecke module morphism boundary map defined by the matrix
112
[ 0]
113
[ 0]
114
[-1]
115
Domain: Modular Symbols space of dimension 3 for Gamma_0(1) of weight ...
116
Codomain: Space of Boundary Modular Symbols for Modular Group SL(2,Z) ...
117
sage: M.cuspidal_subspace().boundary_map()
118
Hecke module morphism defined by the matrix
119
[0]
120
[0]
121
Domain: Modular Symbols subspace of dimension 2 of Modular Symbols space ...
122
Codomain: Space of Boundary Modular Symbols for Modular Group SL(2,Z) ...
123
sage: M.eisenstein_submodule().boundary_map()
124
Hecke module morphism defined by the matrix
125
[-236364091/6742820700]
126
Domain: Modular Symbols subspace of dimension 1 of Modular Symbols space ...
127
Codomain: Space of Boundary Modular Symbols for Modular Group SL(2,Z) ...
128
"""
129
try:
130
return self.__boundary_map
131
except AttributeError:
132
# restrict from ambient space
133
b = self.ambient_hecke_module().boundary_map()
134
self.__boundary_map = b.restrict_domain(self)
135
return self.__boundary_map
136
137
def cuspidal_submodule(self):
138
"""
139
Return the cuspidal subspace of this subspace of modular symbols.
140
141
EXAMPLES::
142
143
sage: S = ModularSymbols(42,4).cuspidal_submodule() ; S
144
Modular Symbols subspace of dimension 40 of Modular Symbols space of dimension 48 for Gamma_0(42) of weight 4 with sign 0 over Rational Field
145
sage: S.is_cuspidal()
146
True
147
sage: S.cuspidal_submodule()
148
Modular Symbols subspace of dimension 40 of Modular Symbols space of dimension 48 for Gamma_0(42) of weight 4 with sign 0 over Rational Field
149
150
The cuspidal submodule of the cuspidal submodule is just itself::
151
152
sage: S.cuspidal_submodule() is S
153
True
154
sage: S.cuspidal_submodule() == S
155
True
156
157
An example where we abuse the _set_is_cuspidal function::
158
159
sage: M = ModularSymbols(389)
160
sage: S = M.eisenstein_submodule()
161
sage: S._set_is_cuspidal(True)
162
sage: S.cuspidal_submodule()
163
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 65 for Gamma_0(389) of weight 2 with sign 0 over Rational Field
164
"""
165
try:
166
return self.__cuspidal_submodule
167
except AttributeError:
168
try:
169
if self.__is_cuspidal:
170
return self
171
except AttributeError:
172
pass
173
S = self.ambient_hecke_module().cuspidal_submodule()
174
self.__cuspidal_submodule = S.intersection(self)
175
return self.__cuspidal_submodule
176
177
178
def dual_star_involution_matrix(self):
179
"""
180
Return the matrix of the dual star involution, which is induced by
181
complex conjugation on the linear dual of modular symbols.
182
183
EXAMPLES::
184
185
sage: S = ModularSymbols(6,4) ; S.dual_star_involution_matrix()
186
[ 1 0 0 0 0 0]
187
[ 0 1 0 0 0 0]
188
[ 0 -2 1 2 0 0]
189
[ 0 2 0 -1 0 0]
190
[ 0 -2 0 2 1 0]
191
[ 0 2 0 -2 0 1]
192
sage: S.star_involution().matrix().transpose() == S.dual_star_involution_matrix()
193
True
194
"""
195
try:
196
return self.__dual_star_involution
197
except AttributeError:
198
pass
199
S = self.ambient_hecke_module().dual_star_involution_matrix()
200
A = S.restrict(self.dual_free_module())
201
self.__dual_star_involution = A
202
return self.__dual_star_involution
203
204
def eisenstein_subspace(self):
205
"""
206
Return the Eisenstein subspace of this space of modular symbols.
207
208
EXAMPLES::
209
210
sage: ModularSymbols(24,4).eisenstein_subspace()
211
Modular Symbols subspace of dimension 8 of Modular Symbols space of dimension 24 for Gamma_0(24) of weight 4 with sign 0 over Rational Field
212
sage: ModularSymbols(20,2).cuspidal_subspace().eisenstein_subspace()
213
Modular Symbols subspace of dimension 0 of Modular Symbols space of dimension 7 for Gamma_0(20) of weight 2 with sign 0 over Rational Field
214
"""
215
try:
216
return self.__eisenstein_subspace
217
except AttributeError:
218
S = self.ambient_hecke_module().eisenstein_subspace()
219
self.__eisenstein_subspace = S.intersection(self)
220
return self.__eisenstein_subspace
221
222
def factorization(self):
223
"""
224
Returns a list of pairs `(S,e)` where `S` is simple
225
spaces of modular symbols and self is isomorphic to the direct sum
226
of the `S^e` as a module over the *anemic* Hecke algebra
227
adjoin the star involution.
228
229
The cuspidal `S` are all simple, but the Eisenstein factors
230
need not be simple.
231
232
The factors are sorted by dimension - don't depend on much more for
233
now.
234
235
ASSUMPTION: self is a module over the anemic Hecke algebra.
236
237
EXAMPLES: Note that if the sign is 1 then the cuspidal factors
238
occur twice, one with each star eigenvalue.
239
240
::
241
242
sage: M = ModularSymbols(11)
243
sage: D = M.factorization(); D
244
(Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field) *
245
(Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field) *
246
(Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field)
247
sage: [A.T(2).matrix() for A, _ in D]
248
[[-2], [3], [-2]]
249
sage: [A.star_eigenvalues() for A, _ in D]
250
[[-1], [1], [1]]
251
252
In this example there is one old factor squared.
253
254
::
255
256
sage: M = ModularSymbols(22,sign=1)
257
sage: S = M.cuspidal_submodule()
258
sage: S.factorization()
259
(Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 2 for Gamma_0(11) of weight 2 with sign 1 over Rational Field)^2
260
261
::
262
263
sage: M = ModularSymbols(Gamma0(22), 2, sign=1)
264
sage: M1 = M.decomposition()[1]
265
sage: M1.factorization()
266
Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 5 for Gamma_0(22) of weight 2 with sign 1 over Rational Field
267
"""
268
try:
269
return self._factorization
270
except AttributeError:
271
pass
272
try:
273
if self._is_simple:
274
return [(self, 1)]
275
except AttributeError:
276
pass
277
if self.is_new() and self.is_cuspidal():
278
D = []
279
N = self.decomposition()
280
if self.sign() == 0:
281
for A in N:
282
if A.is_cuspidal():
283
V = A.plus_submodule()
284
V._is_simple = True
285
D.append((V,1))
286
V = A.minus_submodule()
287
V._is_simple = True
288
D.append((V,1))
289
else:
290
A._is_simple = True
291
D.append((A, 1))
292
else:
293
for A in N:
294
A._is_simple = True
295
D.append((A,1))
296
else:
297
# Compute factorization of the ambient space, then compute multiplicity
298
# of each factor in this space.
299
D = []
300
for S in self.ambient_hecke_module().simple_factors():
301
n = self.multiplicity(S, check_simple=False)
302
if n > 0:
303
D.append((S,n))
304
# endif
305
306
# check that dimensions add up
307
r = self.dimension()
308
s = sum([A.rank()*mult for A, mult in D])
309
if r != s:
310
raise NotImplementedError, "modular symbols factorization not fully implemented yet -- self has dimension %s, but sum of dimensions of factors is %s"%(
311
r, s)
312
self._factorization = sage.structure.factorization.Factorization(D, cr=True)
313
return self._factorization
314
315
def hecke_bound(self):
316
"""
317
Compute the Hecke bound for self; that is, a number n such that the
318
T_m for m = n generate the Hecke algebra.
319
320
EXAMPLES::
321
322
sage: M = ModularSymbols(24,8)
323
sage: M.hecke_bound()
324
53
325
sage: M.cuspidal_submodule().hecke_bound()
326
32
327
sage: M.eisenstein_submodule().hecke_bound()
328
53
329
"""
330
if self.is_cuspidal():
331
return self.sturm_bound()
332
else:
333
return self.ambient_hecke_module().hecke_bound()
334
335
def is_cuspidal(self):
336
"""
337
Return True if self is cuspidal.
338
339
EXAMPLES::
340
341
sage: ModularSymbols(42,4).cuspidal_submodule().is_cuspidal()
342
True
343
sage: ModularSymbols(12,6).eisenstein_submodule().is_cuspidal()
344
False
345
"""
346
try:
347
return self.__is_cuspidal
348
except AttributeError:
349
C = self.ambient_hecke_module().cuspidal_submodule()
350
self.__is_cuspidal = self.is_submodule(C)
351
return self.__is_cuspidal
352
353
def _set_is_cuspidal(self, t):
354
"""
355
Used internally to declare that a given submodule is cuspidal.
356
357
EXAMPLES: We abuse this command::
358
359
sage: M = ModularSymbols(389)
360
sage: S = M.eisenstein_submodule()
361
sage: S._set_is_cuspidal(True)
362
sage: S.is_cuspidal()
363
True
364
"""
365
self.__is_cuspidal = t
366
367
def is_eisenstein(self):
368
"""
369
Return True if self is an Eisenstein subspace.
370
371
EXAMPLES::
372
373
sage: ModularSymbols(22,6).cuspidal_submodule().is_eisenstein()
374
False
375
sage: ModularSymbols(22,6).eisenstein_submodule().is_eisenstein()
376
True
377
"""
378
try:
379
return self.__is_eisenstien
380
except AttributeError:
381
C = self.ambient_hecke_module().eisenstein_subspace()
382
self.__is_eisenstein = self.is_submodule(C)
383
return self.__is_eisenstein
384
385
386
def _compute_sign_subspace(self, sign, compute_dual=True):
387
"""
388
Return the subspace of self that is fixed under the star
389
involution.
390
391
INPUT:
392
393
394
- ``sign`` - int (either -1 or +1)
395
396
- ``compute_dual`` - bool (default: True) also
397
compute dual subspace. This are useful for many algorithms.
398
399
400
OUTPUT: subspace of modular symbols
401
402
EXAMPLES::
403
404
sage: S = ModularSymbols(100,2).cuspidal_submodule() ; S
405
Modular Symbols subspace of dimension 14 of Modular Symbols space of dimension 31 for Gamma_0(100) of weight 2 with sign 0 over Rational Field
406
sage: S._compute_sign_subspace(1)
407
Modular Symbols subspace of dimension 7 of Modular Symbols space of dimension 31 for Gamma_0(100) of weight 2 with sign 0 over Rational Field
408
sage: S._compute_sign_subspace(-1)
409
Modular Symbols subspace of dimension 7 of Modular Symbols space of dimension 31 for Gamma_0(100) of weight 2 with sign 0 over Rational Field
410
sage: S._compute_sign_subspace(-1).sign()
411
-1
412
"""
413
S = self.star_involution().matrix() - sign
414
V = S.kernel()
415
if compute_dual:
416
Sdual = self.dual_star_involution_matrix() - sign
417
Vdual = Sdual.kernel()
418
else:
419
Vdual = None
420
res = self.submodule_from_nonembedded_module(V, Vdual)
421
res._set_sign(sign)
422
return res
423
424
def star_involution(self):
425
"""
426
Return the star involution on self, which is induced by complex
427
conjugation on modular symbols.
428
429
EXAMPLES::
430
431
sage: M = ModularSymbols(1,24)
432
sage: M.star_involution()
433
Hecke module morphism Star involution on Modular Symbols space of dimension 5 for Gamma_0(1) of weight 24 with sign 0 over Rational Field defined by the matrix
434
[ 1 0 0 0 0]
435
[ 0 -1 0 0 0]
436
[ 0 0 1 0 0]
437
[ 0 0 0 -1 0]
438
[ 0 0 0 0 1]
439
Domain: Modular Symbols space of dimension 5 for Gamma_0(1) of weight ...
440
Codomain: Modular Symbols space of dimension 5 for Gamma_0(1) of weight ...
441
sage: M.cuspidal_subspace().star_involution()
442
Hecke module morphism defined by the matrix
443
[ 1 0 0 0]
444
[ 0 -1 0 0]
445
[ 0 0 1 0]
446
[ 0 0 0 -1]
447
Domain: Modular Symbols subspace of dimension 4 of Modular Symbols space ...
448
Codomain: Modular Symbols subspace of dimension 4 of Modular Symbols space ...
449
sage: M.plus_submodule().star_involution()
450
Hecke module morphism defined by the matrix
451
[1 0 0]
452
[0 1 0]
453
[0 0 1]
454
Domain: Modular Symbols subspace of dimension 3 of Modular Symbols space ...
455
Codomain: Modular Symbols subspace of dimension 3 of Modular Symbols space ...
456
sage: M.minus_submodule().star_involution()
457
Hecke module morphism defined by the matrix
458
[-1 0]
459
[ 0 -1]
460
Domain: Modular Symbols subspace of dimension 2 of Modular Symbols space ...
461
Codomain: Modular Symbols subspace of dimension 2 of Modular Symbols space ...
462
"""
463
try:
464
return self.__star_involution
465
except AttributeError:
466
pass
467
S = self.ambient_hecke_module().star_involution()
468
self.__star_involution = S.restrict(self)
469
return self.__star_involution
470
471