Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/modular/modform/constructor.py
8820 views
1
# -*- coding: utf-8 -*-
2
"""
3
Creating Spaces of Modular Forms
4
5
EXAMPLES::
6
7
sage: m = ModularForms(Gamma1(4),11)
8
sage: m
9
Modular Forms space of dimension 6 for Congruence Subgroup Gamma1(4) of weight 11 over Rational Field
10
sage: m.basis()
11
[
12
q - 134*q^5 + O(q^6),
13
q^2 + 80*q^5 + O(q^6),
14
q^3 + 16*q^5 + O(q^6),
15
q^4 - 4*q^5 + O(q^6),
16
1 + 4092/50521*q^2 + 472384/50521*q^3 + 4194300/50521*q^4 + O(q^6),
17
q + 1024*q^2 + 59048*q^3 + 1048576*q^4 + 9765626*q^5 + O(q^6)
18
]
19
20
"""
21
22
#########################################################################
23
# Copyright (C) 2004--2006 William Stein <[email protected]>
24
#
25
# Distributed under the terms of the GNU General Public License (GPL)
26
#
27
# http://www.gnu.org/licenses/
28
#########################################################################
29
30
import weakref
31
import re
32
33
import sage.modular.arithgroup.all as arithgroup
34
import sage.modular.dirichlet as dirichlet
35
import sage.rings.all as rings
36
37
from sage.rings.commutative_ring import is_CommutativeRing
38
39
import ambient_eps
40
import ambient_g0
41
import ambient_g1
42
import ambient_R
43
import defaults
44
45
46
def canonical_parameters(group, level, weight, base_ring):
47
"""
48
Given a group, level, weight, and base_ring as input by the user,
49
return a canonicalized version of them, where level is a Sage
50
integer, group really is a group, weight is a Sage integer, and
51
base_ring a Sage ring. Note that we can't just get the level from
52
the group, because we have the convention that the character for
53
Gamma1(N) is None (which makes good sense).
54
55
INPUT:
56
57
58
- ``group`` - int, long, Sage integer, group,
59
dirichlet character, or
60
61
- ``level`` - int, long, Sage integer, or group
62
63
- ``weight`` - coercible to Sage integer
64
65
- ``base_ring`` - commutative Sage ring
66
67
68
OUTPUT:
69
70
71
- ``level`` - Sage integer
72
73
- ``group`` - congruence subgroup
74
75
- ``weight`` - Sage integer
76
77
- ``ring`` - commutative Sage ring
78
79
80
EXAMPLES::
81
82
sage: from sage.modular.modform.constructor import canonical_parameters
83
sage: v = canonical_parameters(5, 5, int(7), ZZ); v
84
(5, Congruence Subgroup Gamma0(5), 7, Integer Ring)
85
sage: type(v[0]), type(v[1]), type(v[2]), type(v[3])
86
(<type 'sage.rings.integer.Integer'>,
87
<class 'sage.modular.arithgroup.congroup_gamma0.Gamma0_class_with_category'>,
88
<type 'sage.rings.integer.Integer'>,
89
<type 'sage.rings.integer_ring.IntegerRing_class'>)
90
sage: canonical_parameters( 5, 7, 7, ZZ )
91
Traceback (most recent call last):
92
...
93
ValueError: group and level do not match.
94
"""
95
weight = rings.Integer(weight)
96
if weight <= 0:
97
raise NotImplementedError, "weight must be at least 1"
98
99
if isinstance(group, dirichlet.DirichletCharacter):
100
if ( group.level() != rings.Integer(level) ):
101
raise ValueError, "group.level() and level do not match."
102
group = group.minimize_base_ring()
103
level = rings.Integer(level)
104
105
elif arithgroup.is_CongruenceSubgroup(group):
106
if ( rings.Integer(level) != group.level() ):
107
raise ValueError, "group.level() and level do not match."
108
# normalize the case of SL2Z
109
if arithgroup.is_SL2Z(group) or \
110
arithgroup.is_Gamma1(group) and group.level() == rings.Integer(1):
111
group = arithgroup.Gamma0(rings.Integer(1))
112
113
elif group is None:
114
pass
115
116
else:
117
try:
118
m = rings.Integer(group)
119
except TypeError:
120
raise TypeError, "group of unknown type."
121
level = rings.Integer(level)
122
if ( m != level ):
123
raise ValueError, "group and level do not match."
124
group = arithgroup.Gamma0(m)
125
126
if not is_CommutativeRing(base_ring):
127
raise TypeError, "base_ring (=%s) must be a commutative ring"%base_ring
128
129
# it is *very* important to include the level as part of the data
130
# that defines the key, since dirichlet characters of different
131
# levels can compare equal, but define much different modular
132
# forms spaces.
133
return level, group, weight, base_ring
134
135
_cache = {}
136
137
def ModularForms_clear_cache():
138
"""
139
Clear the cache of modular forms.
140
141
EXAMPLES::
142
143
sage: M = ModularForms(37,2)
144
sage: sage.modular.modform.constructor._cache == {}
145
False
146
147
::
148
149
sage: sage.modular.modform.constructor.ModularForms_clear_cache()
150
sage: sage.modular.modform.constructor._cache
151
{}
152
"""
153
global _cache
154
_cache = {}
155
156
def ModularForms(group = 1,
157
weight = 2,
158
base_ring = None,
159
use_cache = True,
160
prec = defaults.DEFAULT_PRECISION):
161
r"""
162
Create an ambient space of modular forms.
163
164
INPUT:
165
166
167
- ``group`` - A congruence subgroup or a Dirichlet
168
character eps.
169
170
- ``weight`` - int, the weight, which must be an
171
integer = 1.
172
173
- ``base_ring`` - the base ring (ignored if group is
174
a Dirichlet character)
175
176
177
Create using the command ModularForms(group, weight, base_ring)
178
where group could be either a congruence subgroup or a Dirichlet
179
character.
180
181
EXAMPLES: First we create some spaces with trivial character::
182
183
sage: ModularForms(Gamma0(11),2).dimension()
184
2
185
sage: ModularForms(Gamma0(1),12).dimension()
186
2
187
188
If we give an integer N for the congruence subgroup, it defaults to
189
`\Gamma_0(N)`::
190
191
sage: ModularForms(1,12).dimension()
192
2
193
sage: ModularForms(11,4)
194
Modular Forms space of dimension 4 for Congruence Subgroup Gamma0(11) of weight 4 over Rational Field
195
196
We create some spaces for `\Gamma_1(N)`.
197
198
::
199
200
sage: ModularForms(Gamma1(13),2)
201
Modular Forms space of dimension 13 for Congruence Subgroup Gamma1(13) of weight 2 over Rational Field
202
sage: ModularForms(Gamma1(13),2).dimension()
203
13
204
sage: [ModularForms(Gamma1(7),k).dimension() for k in [2,3,4,5]]
205
[5, 7, 9, 11]
206
sage: ModularForms(Gamma1(5),11).dimension()
207
12
208
209
We create a space with character::
210
211
sage: e = (DirichletGroup(13).0)^2
212
sage: e.order()
213
6
214
sage: M = ModularForms(e, 2); M
215
Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 6 and degree 2
216
sage: f = M.T(2).charpoly('x'); f
217
x^3 + (-2*zeta6 - 2)*x^2 - 2*zeta6*x + 14*zeta6 - 7
218
sage: f.factor()
219
(x - zeta6 - 2) * (x - 2*zeta6 - 1) * (x + zeta6 + 1)
220
221
We can also create spaces corresponding to the groups `\Gamma_H(N)` intermediate
222
between `\Gamma_0(N)` and `\Gamma_1(N)`::
223
224
sage: G = GammaH(30, [11])
225
sage: M = ModularForms(G, 2); M
226
Modular Forms space of dimension 20 for Congruence Subgroup Gamma_H(30) with H generated by [11] of weight 2 over Rational Field
227
sage: M.T(7).charpoly().factor() # long time (7s on sage.math, 2011)
228
(x + 4) * x^2 * (x - 6)^4 * (x + 6)^4 * (x - 8)^7 * (x^2 + 4)
229
230
More examples of spaces with character::
231
232
sage: e = DirichletGroup(5, RationalField()).gen(); e
233
Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1
234
235
sage: m = ModularForms(e, 2); m
236
Modular Forms space of dimension 2, character [-1] and weight 2 over Rational Field
237
sage: m == loads(dumps(m))
238
True
239
sage: m.T(2).charpoly('x')
240
x^2 - 1
241
sage: m = ModularForms(e, 6); m.dimension()
242
4
243
sage: m.T(2).charpoly('x')
244
x^4 - 917*x^2 - 42284
245
246
This came up in a subtle bug (trac #5923)::
247
248
sage: ModularForms(gp(1), gap(12))
249
Modular Forms space of dimension 2 for Modular Group SL(2,Z) of weight 12 over Rational Field
250
251
This came up in another bug (related to trac #8630)::
252
253
sage: chi = DirichletGroup(109, CyclotomicField(3)).0
254
sage: ModularForms(chi, 2, base_ring = CyclotomicField(15))
255
Modular Forms space of dimension 10, character [zeta3 + 1] and weight 2 over Cyclotomic Field of order 15 and degree 8
256
257
We create some weight 1 spaces. The first example works fine, since we can prove purely by Riemann surface theory that there are no weight 1 cusp forms::
258
259
sage: M = ModularForms(Gamma1(11), 1); M
260
Modular Forms space of dimension 5 for Congruence Subgroup Gamma1(11) of weight 1 over Rational Field
261
sage: M.basis()
262
[
263
1 + 22*q^5 + O(q^6),
264
q + 4*q^5 + O(q^6),
265
q^2 - 4*q^5 + O(q^6),
266
q^3 - 5*q^5 + O(q^6),
267
q^4 - 3*q^5 + O(q^6)
268
]
269
sage: M.cuspidal_subspace().basis()
270
[
271
]
272
sage: M == M.eisenstein_subspace()
273
True
274
275
This example doesn't work so well, because we can't calculate the cusp
276
forms; but we can still work with the Eisenstein series.
277
278
sage: M = ModularForms(Gamma1(57), 1); M
279
Modular Forms space of dimension (unknown) for Congruence Subgroup Gamma1(57) of weight 1 over Rational Field
280
sage: M.basis()
281
Traceback (most recent call last):
282
...
283
NotImplementedError: Computation of dimensions of weight 1 cusp forms spaces not implemented in general
284
sage: M.cuspidal_subspace().basis()
285
Traceback (most recent call last):
286
...
287
NotImplementedError: Computation of dimensions of weight 1 cusp forms spaces not implemented in general
288
289
sage: E = M.eisenstein_subspace(); E
290
Eisenstein subspace of dimension 36 of Modular Forms space of dimension (unknown) for Congruence Subgroup Gamma1(57) of weight 1 over Rational Field
291
sage: (E.0 + E.2).q_expansion(40)
292
1 + q^2 + 1473/2*q^36 - 1101/2*q^37 + q^38 - 373/2*q^39 + O(q^40)
293
294
"""
295
if isinstance(group, dirichlet.DirichletCharacter):
296
if base_ring is None:
297
base_ring = group.minimize_base_ring().base_ring()
298
if base_ring is None:
299
base_ring = rings.QQ
300
301
if isinstance(group, dirichlet.DirichletCharacter) \
302
or arithgroup.is_CongruenceSubgroup(group):
303
level = group.level()
304
else:
305
level = group
306
307
key = canonical_parameters(group, level, weight, base_ring)
308
309
if use_cache and _cache.has_key(key):
310
M = _cache[key]()
311
if not (M is None):
312
M.set_precision(prec)
313
return M
314
315
(level, group, weight, base_ring) = key
316
317
M = None
318
if arithgroup.is_Gamma0(group):
319
M = ambient_g0.ModularFormsAmbient_g0_Q(group.level(), weight)
320
if base_ring != rings.QQ:
321
M = ambient_R.ModularFormsAmbient_R(M, base_ring)
322
323
elif arithgroup.is_Gamma1(group):
324
M = ambient_g1.ModularFormsAmbient_g1_Q(group.level(), weight)
325
if base_ring != rings.QQ:
326
M = ambient_R.ModularFormsAmbient_R(M, base_ring)
327
328
elif arithgroup.is_GammaH(group):
329
M = ambient_g1.ModularFormsAmbient_gH_Q(group, weight)
330
if base_ring != rings.QQ:
331
M = ambient_R.ModularFormsAmbient_R(M, base_ring)
332
333
elif isinstance(group, dirichlet.DirichletCharacter):
334
eps = group
335
if eps.base_ring().characteristic() != 0:
336
# TODO -- implement this
337
# Need to add a lift_to_char_0 function for characters,
338
# and need to still remember eps.
339
raise NotImplementedError, "currently the character must be over a ring of characteristic 0."
340
eps = eps.minimize_base_ring()
341
if eps.is_trivial():
342
return ModularForms(eps.modulus(), weight, base_ring,
343
use_cache = use_cache,
344
prec = prec)
345
M = ambient_eps.ModularFormsAmbient_eps(eps, weight)
346
if base_ring != eps.base_ring():
347
M = M.base_extend(base_ring) # ambient_R.ModularFormsAmbient_R(M, base_ring)
348
349
if M is None:
350
raise NotImplementedError, \
351
"computation of requested space of modular forms not defined or implemented"
352
353
M.set_precision(prec)
354
_cache[key] = weakref.ref(M)
355
return M
356
357
358
def CuspForms(group = 1,
359
weight = 2,
360
base_ring = None,
361
use_cache = True,
362
prec = defaults.DEFAULT_PRECISION):
363
"""
364
Create a space of cuspidal modular forms.
365
366
See the documentation for the ModularForms command for a
367
description of the input parameters.
368
369
EXAMPLES::
370
371
sage: CuspForms(11,2)
372
Cuspidal subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field
373
"""
374
return ModularForms(group, weight, base_ring,
375
use_cache=use_cache, prec=prec).cuspidal_submodule()
376
377
378
def EisensteinForms(group = 1,
379
weight = 2,
380
base_ring = None,
381
use_cache = True,
382
prec = defaults.DEFAULT_PRECISION):
383
"""
384
Create a space of eisenstein modular forms.
385
386
See the documentation for the ModularForms command for a
387
description of the input parameters.
388
389
EXAMPLES::
390
391
sage: EisensteinForms(11,2)
392
Eisenstein subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field
393
"""
394
return ModularForms(group, weight, base_ring,
395
use_cache=use_cache, prec=prec).eisenstein_submodule()
396
397
398
399
def Newforms(group, weight=2, base_ring=None, names=None):
400
r"""
401
Returns a list of the newforms of the given weight and level (or weight,
402
level and character). These are calculated as
403
`\operatorname{Gal}(\overline{F} / F)`-orbits, where `F` is the given base
404
field.
405
406
INPUT:
407
408
409
- ``group`` - the congruence subgroup of the newform, or a Nebentypus
410
character
411
412
- ``weight`` - the weight of the newform (default 2)
413
414
- ``base_ring`` - the base ring (defaults to `\QQ` for spaces without
415
character, or the base ring of the character otherwise)
416
417
- ``names`` - if the newform has coefficients in a
418
number field, a generator name must be specified
419
420
421
EXAMPLES::
422
423
sage: Newforms(11, 2)
424
[q - 2*q^2 - q^3 + 2*q^4 + q^5 + O(q^6)]
425
sage: Newforms(65, names='a')
426
[q - q^2 - 2*q^3 - q^4 - q^5 + O(q^6),
427
q + a1*q^2 + (a1 + 1)*q^3 + (-2*a1 - 1)*q^4 + q^5 + O(q^6),
428
q + a2*q^2 + (-a2 + 1)*q^3 + q^4 - q^5 + O(q^6)]
429
430
A more complicated example involving both a nontrivial character, and a
431
base field that is not minimal for that character::
432
433
sage: K.<i> = QuadraticField(-1)
434
sage: chi = DirichletGroup(5, K)[3]
435
sage: len(Newforms(chi, 7, names='a'))
436
1
437
sage: x = polygen(K); L.<c> = K.extension(x^2 - 402*i)
438
sage: N = Newforms(chi, 7, base_ring = L); len(N)
439
2
440
sage: sorted([N[0][2], N[1][2]]) == sorted([1/2*c - 5/2*i - 5/2, -1/2*c - 5/2*i - 5/2])
441
True
442
443
We test that :trac:`8630` is fixed::
444
445
sage: chi = DirichletGroup(109, CyclotomicField(3)).0
446
sage: CuspForms(chi, 2, base_ring = CyclotomicField(9))
447
Cuspidal subspace of dimension 8 of Modular Forms space of dimension 10, character [zeta3 + 1] and weight 2 over Cyclotomic Field of order 9 and degree 6
448
"""
449
return CuspForms(group, weight, base_ring).newforms(names)
450
451
452
def Newform(identifier, group=None, weight=2, base_ring=rings.QQ, names=None):
453
"""
454
INPUT:
455
456
457
- ``identifier`` - a canonical label, or the index of
458
the specific newform desired
459
460
- ``group`` - the congruence subgroup of the newform
461
462
- ``weight`` - the weight of the newform (default 2)
463
464
- ``base_ring`` - the base ring
465
466
- ``names`` - if the newform has coefficients in a
467
number field, a generator name must be specified
468
469
470
EXAMPLES::
471
472
sage: Newform('67a', names='a')
473
q + 2*q^2 - 2*q^3 + 2*q^4 + 2*q^5 + O(q^6)
474
sage: Newform('67b', names='a')
475
q + a1*q^2 + (-a1 - 3)*q^3 + (-3*a1 - 3)*q^4 - 3*q^5 + O(q^6)
476
"""
477
if isinstance(group, str) and names is None:
478
names = group
479
if isinstance(identifier, str):
480
group, identifier = parse_label(identifier)
481
if weight != 2:
482
raise ValueError, "Canonical label not implemented for higher weight forms."
483
elif base_ring != rings.QQ:
484
raise ValueError, "Canonical label not implemented except for over Q."
485
elif group is None:
486
raise ValueError, "Must specify a group or a label."
487
return Newforms(group, weight, base_ring, names=names)[identifier]
488
489
490
def parse_label(s):
491
"""
492
Given a string s corresponding to a newform label, return the
493
corresponding group and index.
494
495
EXAMPLES::
496
497
sage: sage.modular.modform.constructor.parse_label('11a')
498
(Congruence Subgroup Gamma0(11), 0)
499
sage: sage.modular.modform.constructor.parse_label('11aG1')
500
(Congruence Subgroup Gamma1(11), 0)
501
sage: sage.modular.modform.constructor.parse_label('11wG1')
502
(Congruence Subgroup Gamma1(11), 22)
503
"""
504
m = re.match(r'(\d+)([a-z]+)((?:G.*)?)$', s)
505
if not m:
506
raise ValueError, "Invalid label: %s" % s
507
N, order, G = m.groups()
508
N = int(N)
509
index = 0
510
for c in reversed(order):
511
index = 26*index + ord(c)-ord('a')
512
if G == '' or G == 'G0':
513
G = arithgroup.Gamma0(N)
514
elif G == 'G1':
515
G = arithgroup.Gamma1(N)
516
elif G[:2] == 'GH':
517
if G[2] != '[' or G[-1] != ']':
518
raise ValueError, "Invalid congruence subgroup label: %s" % G
519
gens = [int(g.strip()) for g in G[3:-1].split(',')]
520
return arithgroup.GammaH(N, gens)
521
else:
522
raise ValueError, "Invalid congruence subgroup label: %s" % G
523
return G, index
524
525
526
527