Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/modular/modsym/modsym.py
8820 views
1
# -*- coding: utf-8 -*-
2
r"""
3
Creation of modular symbols spaces
4
5
EXAMPLES: We create a space and output its category.
6
7
::
8
9
sage: C = HeckeModules(RationalField()); C
10
Category of Hecke modules over Rational Field
11
sage: M = ModularSymbols(11)
12
sage: M.category()
13
Category of Hecke modules over Rational Field
14
sage: M in C
15
True
16
17
We create a space compute the charpoly, then compute the same but
18
over a bigger field. In each case we also decompose the space using
19
`T_2`.
20
21
::
22
23
sage: M = ModularSymbols(23,2,base_ring=QQ)
24
sage: print M.T(2).charpoly('x').factor()
25
(x - 3) * (x^2 + x - 1)^2
26
sage: print M.decomposition(2)
27
[
28
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 5 for Gamma_0(23) of weight 2 with sign 0 over Rational Field,
29
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 5 for Gamma_0(23) of weight 2 with sign 0 over Rational Field
30
]
31
32
::
33
34
sage: M = ModularSymbols(23,2,base_ring=QuadraticField(5, 'sqrt5'))
35
sage: print M.T(2).charpoly('x').factor()
36
(x - 3) * (x - 1/2*sqrt5 + 1/2)^2 * (x + 1/2*sqrt5 + 1/2)^2
37
sage: print M.decomposition(2)
38
[
39
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 5 for Gamma_0(23) of weight 2 with sign 0 over Number Field in sqrt5 with defining polynomial x^2 - 5,
40
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 5 for Gamma_0(23) of weight 2 with sign 0 over Number Field in sqrt5 with defining polynomial x^2 - 5,
41
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 5 for Gamma_0(23) of weight 2 with sign 0 over Number Field in sqrt5 with defining polynomial x^2 - 5
42
]
43
44
We compute some Hecke operators and do a consistency check::
45
46
sage: m = ModularSymbols(39, 2)
47
sage: t2 = m.T(2); t5 = m.T(5)
48
sage: t2*t5 - t5*t2 == 0
49
True
50
51
This tests the bug reported in trac #1220::
52
53
sage: G = GammaH(36, [13, 19])
54
sage: G.modular_symbols()
55
Modular Symbols space of dimension 13 for Congruence Subgroup Gamma_H(36) with H generated by [13, 19] of weight 2 with sign 0 and over Rational Field
56
sage: G.modular_symbols().cuspidal_subspace()
57
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 13 for Congruence Subgroup Gamma_H(36) with H generated by [13, 19] of weight 2 with sign 0 and over Rational Field
58
59
This test catches a tricky corner case for spaces with character::
60
61
sage: ModularSymbols(DirichletGroup(20).1**3, weight=3, sign=1).cuspidal_subspace()
62
Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 6 and level 20, weight 3, character [1, -zeta4], sign 1, over Cyclotomic Field of order 4 and degree 2
63
"""
64
65
#*****************************************************************************
66
# Sage: System for Algebra and Geometry Experimentation
67
#
68
# Copyright (C) 2005 William Stein <[email protected]>
69
#
70
# Distributed under the terms of the GNU General Public License (GPL)
71
#
72
# This code is distributed in the hope that it will be useful,
73
# but WITHOUT ANY WARRANTY; without even the implied warranty of
74
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
75
# General Public License for more details.
76
#
77
# The full text of the GPL is available at:
78
#
79
# http://www.gnu.org/licenses/
80
#*****************************************************************************
81
82
import weakref
83
84
import ambient
85
import sage.modular.arithgroup.all as arithgroup
86
import sage.modular.dirichlet as dirichlet
87
import sage.rings.rational_field as rational_field
88
import sage.rings.all as rings
89
from sage.rings.commutative_ring import is_CommutativeRing
90
91
92
def canonical_parameters(group, weight, sign, base_ring):
93
"""
94
Return the canonically normalized parameters associated to a choice
95
of group, weight, sign, and base_ring. That is, normalize each of
96
these to be of the correct type, perform all appropriate type
97
checking, etc.
98
99
EXAMPLES::
100
101
sage: p1 = sage.modular.modsym.modsym.canonical_parameters(5,int(2),1,QQ) ; p1
102
(Congruence Subgroup Gamma0(5), 2, 1, Rational Field)
103
sage: p2 = sage.modular.modsym.modsym.canonical_parameters(Gamma0(5),2,1,QQ) ; p2
104
(Congruence Subgroup Gamma0(5), 2, 1, Rational Field)
105
sage: p1 == p2
106
True
107
sage: type(p1[1])
108
<type 'sage.rings.integer.Integer'>
109
"""
110
sign = rings.Integer(sign)
111
if not (sign in [-1,0,1]):
112
raise ValueError, "sign must be -1, 0, or 1"
113
114
weight = rings.Integer(weight)
115
if weight <= 1:
116
raise ValueError, "the weight must be at least 2"
117
118
if isinstance(group, (int, rings.Integer)):
119
group = arithgroup.Gamma0(group)
120
121
elif isinstance(group, dirichlet.DirichletCharacter):
122
try:
123
eps = group.minimize_base_ring()
124
except NotImplementedError:
125
# TODO -- implement minimize_base_ring over finite fields
126
eps = group
127
G = eps.parent()
128
if eps.is_trivial():
129
group = arithgroup.Gamma0(eps.modulus())
130
else:
131
group = (eps, G)
132
if base_ring is None: base_ring = eps.base_ring()
133
134
if base_ring is None: base_ring = rational_field.RationalField()
135
136
if not is_CommutativeRing(base_ring):
137
raise TypeError, "base_ring (=%s) must be a commutative ring"%base_ring
138
139
if not base_ring.is_field():
140
raise TypeError, "(currently) base_ring (=%s) must be a field"%base_ring
141
142
return group, weight, sign, base_ring
143
144
_cache = {}
145
146
def ModularSymbols_clear_cache():
147
"""
148
Clear the global cache of modular symbols spaces.
149
150
EXAMPLES::
151
152
sage: sage.modular.modsym.modsym.ModularSymbols_clear_cache()
153
sage: sage.modular.modsym.modsym._cache.keys()
154
[]
155
sage: M = ModularSymbols(6,2)
156
sage: sage.modular.modsym.modsym._cache.keys()
157
[(Congruence Subgroup Gamma0(6), 2, 0, Rational Field)]
158
sage: sage.modular.modsym.modsym.ModularSymbols_clear_cache()
159
sage: sage.modular.modsym.modsym._cache.keys()
160
[]
161
162
TESTS:
163
164
Make sure #10548 is fixed
165
sage: import gc
166
sage: m=ModularSymbols(Gamma1(29))
167
sage: m=[]
168
sage: ModularSymbols_clear_cache()
169
sage: gc.collect() # random
170
3422
171
sage: a=[x for x in gc.get_objects() if isinstance(x,sage.modular.modsym.ambient.ModularSymbolsAmbient_wtk_g1)]
172
sage: a
173
[]
174
175
"""
176
global _cache
177
_cache = {}
178
179
def ModularSymbols(group = 1,
180
weight = 2,
181
sign = 0,
182
base_ring = None,
183
use_cache = True,
184
custom_init=None):
185
r"""
186
Create an ambient space of modular symbols.
187
188
INPUT:
189
190
- ``group`` - A congruence subgroup or a Dirichlet character eps.
191
- ``weight`` - int, the weight, which must be = 2.
192
- ``sign`` - int, The sign of the involution on modular symbols
193
induced by complex conjugation. The default is 0, which means
194
"no sign", i.e., take the whole space.
195
- ``base_ring`` - the base ring. Defaults to `\QQ` if no character
196
is given, or to the minimal extension of `\QQ` containing the
197
values of the character.
198
- ``custom_init`` - a function that is called with self as input
199
before any computations are done using self; this could be used
200
to set a custom modular symbols presentation. If self is
201
already in the cache and use_cache=True, then this function is
202
not called.
203
204
EXAMPLES: First we create some spaces with trivial character::
205
206
sage: ModularSymbols(Gamma0(11),2).dimension()
207
3
208
sage: ModularSymbols(Gamma0(1),12).dimension()
209
3
210
211
If we give an integer N for the congruence subgroup, it defaults to
212
`\Gamma_0(N)`::
213
214
sage: ModularSymbols(1,12,-1).dimension()
215
1
216
sage: ModularSymbols(11,4, sign=1)
217
Modular Symbols space of dimension 4 for Gamma_0(11) of weight 4 with sign 1 over Rational Field
218
219
We create some spaces for `\Gamma_1(N)`.
220
221
::
222
223
sage: ModularSymbols(Gamma1(13),2)
224
Modular Symbols space of dimension 15 for Gamma_1(13) of weight 2 with sign 0 and over Rational Field
225
sage: ModularSymbols(Gamma1(13),2, sign=1).dimension()
226
13
227
sage: ModularSymbols(Gamma1(13),2, sign=-1).dimension()
228
2
229
sage: [ModularSymbols(Gamma1(7),k).dimension() for k in [2,3,4,5]]
230
[5, 8, 12, 16]
231
sage: ModularSymbols(Gamma1(5),11).dimension()
232
20
233
234
We create a space for `\Gamma_H(N)`::
235
236
sage: G = GammaH(15,[4,13])
237
sage: M = ModularSymbols(G,2)
238
sage: M.decomposition()
239
[
240
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 5 for Congruence Subgroup Gamma_H(15) with H generated by [4, 13] of weight 2 with sign 0 and over Rational Field,
241
Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 5 for Congruence Subgroup Gamma_H(15) with H generated by [4, 13] of weight 2 with sign 0 and over Rational Field
242
]
243
244
We create a space with character::
245
246
sage: e = (DirichletGroup(13).0)^2
247
sage: e.order()
248
6
249
sage: M = ModularSymbols(e, 2); M
250
Modular Symbols space of dimension 4 and level 13, weight 2, character [zeta6], sign 0, over Cyclotomic Field of order 6 and degree 2
251
sage: f = M.T(2).charpoly('x'); f
252
x^4 + (-zeta6 - 1)*x^3 - 8*zeta6*x^2 + (10*zeta6 - 5)*x + 21*zeta6 - 21
253
sage: f.factor()
254
(x - zeta6 - 2) * (x - 2*zeta6 - 1) * (x + zeta6 + 1)^2
255
256
We create a space with character over a larger base ring than the values of the character::
257
258
sage: ModularSymbols(e, 2, base_ring = CyclotomicField(24))
259
Modular Symbols space of dimension 4 and level 13, weight 2, character [zeta24^4], sign 0, over Cyclotomic Field of order 24 and degree 8
260
261
More examples of spaces with character::
262
263
sage: e = DirichletGroup(5, RationalField()).gen(); e
264
Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1
265
266
sage: m = ModularSymbols(e, 2); m
267
Modular Symbols space of dimension 2 and level 5, weight 2, character [-1], sign 0, over Rational Field
268
269
::
270
271
sage: m.T(2).charpoly('x')
272
x^2 - 1
273
sage: m = ModularSymbols(e, 6); m.dimension()
274
6
275
sage: m.T(2).charpoly('x')
276
x^6 - 873*x^4 - 82632*x^2 - 1860496
277
278
We create a space of modular symbols with nontrivial character in
279
characteristic 2.
280
281
::
282
283
sage: G = DirichletGroup(13,GF(4,'a')); G
284
Group of Dirichlet characters of modulus 13 over Finite Field in a of size 2^2
285
sage: e = G.list()[2]; e
286
Dirichlet character modulo 13 of conductor 13 mapping 2 |--> a + 1
287
sage: M = ModularSymbols(e,4); M
288
Modular Symbols space of dimension 8 and level 13, weight 4, character [a + 1], sign 0, over Finite Field in a of size 2^2
289
sage: M.basis()
290
([X*Y,(1,0)], [X*Y,(1,5)], [X*Y,(1,10)], [X*Y,(1,11)], [X^2,(0,1)], [X^2,(1,10)], [X^2,(1,11)], [X^2,(1,12)])
291
sage: M.T(2).matrix()
292
[ 0 0 0 0 0 0 1 1]
293
[ 0 0 0 0 0 0 0 0]
294
[ 0 0 0 0 0 a + 1 1 a]
295
[ 0 0 0 0 0 1 a + 1 a]
296
[ 0 0 0 0 a + 1 0 1 1]
297
[ 0 0 0 0 0 a 1 a]
298
[ 0 0 0 0 0 0 a + 1 a]
299
[ 0 0 0 0 0 0 1 0]
300
301
We illustrate the custom_init function, which can be used to make
302
arbitrary changes to the modular symbols object before its
303
presentation is computed::
304
305
sage: ModularSymbols_clear_cache()
306
sage: def custom_init(M):
307
... M.customize='hi'
308
sage: M = ModularSymbols(1,12, custom_init=custom_init)
309
sage: M.customize
310
'hi'
311
312
We illustrate the relation between custom_init and use_cache::
313
314
sage: def custom_init(M):
315
... M.customize='hi2'
316
sage: M = ModularSymbols(1,12, custom_init=custom_init)
317
sage: M.customize
318
'hi'
319
sage: M = ModularSymbols(1,12, custom_init=custom_init, use_cache=False)
320
sage: M.customize
321
'hi2'
322
323
TESTS: We test use_cache::
324
325
sage: ModularSymbols_clear_cache()
326
sage: M = ModularSymbols(11,use_cache=False)
327
sage: sage.modular.modsym.modsym._cache
328
{}
329
sage: M = ModularSymbols(11,use_cache=True)
330
sage: sage.modular.modsym.modsym._cache
331
{(Congruence Subgroup Gamma0(11), 2, 0, Rational Field): <weakref at ...; to 'ModularSymbolsAmbient_wt2_g0_with_category' at ...>}
332
sage: M is ModularSymbols(11,use_cache=True)
333
True
334
sage: M is ModularSymbols(11,use_cache=False)
335
False
336
"""
337
key = canonical_parameters(group, weight, sign, base_ring)
338
339
if use_cache and _cache.has_key(key):
340
M = _cache[key]()
341
if not (M is None): return M
342
343
(group, weight, sign, base_ring) = key
344
345
M = None
346
if arithgroup.is_Gamma0(group):
347
if weight == 2:
348
M = ambient.ModularSymbolsAmbient_wt2_g0(
349
group.level(),sign, base_ring, custom_init=custom_init)
350
else:
351
M = ambient.ModularSymbolsAmbient_wtk_g0(
352
group.level(), weight, sign, base_ring, custom_init=custom_init)
353
354
elif arithgroup.is_Gamma1(group):
355
356
M = ambient.ModularSymbolsAmbient_wtk_g1(group.level(),
357
weight, sign, base_ring, custom_init=custom_init)
358
359
elif arithgroup.is_GammaH(group):
360
361
M = ambient.ModularSymbolsAmbient_wtk_gamma_h(group,
362
weight, sign, base_ring, custom_init=custom_init)
363
364
elif isinstance(group, tuple):
365
eps = group[0]
366
M = ambient.ModularSymbolsAmbient_wtk_eps(eps,
367
weight, sign, base_ring, custom_init=custom_init)
368
369
if M is None:
370
raise NotImplementedError, "computation of requested space of modular symbols not defined or implemented"
371
372
if use_cache:
373
_cache[key] = weakref.ref(M)
374
return M
375
376
377