Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/abvar/abvar.py
4057 views
1
"""
2
Base class for modular abelian varieties
3
4
AUTHORS:
5
6
- William Stein (2007-03)
7
8
TESTS::
9
10
sage: A = J0(33)
11
sage: D = A.decomposition(); D
12
[
13
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33),
14
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33),
15
Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33)
16
]
17
sage: loads(dumps(D)) == D
18
True
19
sage: loads(dumps(A)) == A
20
True
21
"""
22
23
###########################################################################
24
# Copyright (C) 2007 William Stein <[email protected]> #
25
# Distributed under the terms of the GNU General Public License (GPL) #
26
# http://www.gnu.org/licenses/ #
27
###########################################################################
28
29
from sage.categories.all import ModularAbelianVarieties
30
from sage.structure.sequence import Sequence, Sequence_generic
31
from sage.structure.parent_base import ParentWithBase
32
from morphism import HeckeOperator, Morphism, DegeneracyMap
33
from torsion_subgroup import RationalTorsionSubgroup, QQbarTorsionSubgroup
34
from finite_subgroup import (FiniteSubgroup_lattice, FiniteSubgroup, TorsionPoint)
35
from cuspidal_subgroup import CuspidalSubgroup, RationalCuspidalSubgroup, RationalCuspSubgroup
36
from sage.rings.all import (ZZ, QQ, QQbar, is_Ring, LCM,
37
divisors, Integer, prime_range)
38
from sage.modules.all import is_FreeModule
39
from sage.modular.arithgroup.all import is_CongruenceSubgroup, is_Gamma0, is_Gamma1, is_GammaH
40
from sage.modular.modsym.all import ModularSymbols
41
from sage.modular.modsym.space import ModularSymbolsSpace
42
from sage.matrix.all import matrix, block_diagonal_matrix, identity_matrix
43
from sage.modules.all import vector
44
from sage.groups.all import AbelianGroup
45
from sage.databases.cremona import cremona_letter_code
46
from sage.misc.misc import prod
47
48
from copy import copy
49
50
import homology
51
import homspace
52
import lseries
53
54
def is_ModularAbelianVariety(x):
55
"""
56
Return True if x is a modular abelian variety.
57
58
INPUT:
59
60
61
- ``x`` - object
62
63
64
EXAMPLES::
65
66
sage: from sage.modular.abvar.abvar import is_ModularAbelianVariety
67
sage: is_ModularAbelianVariety(5)
68
False
69
sage: is_ModularAbelianVariety(J0(37))
70
True
71
72
Returning True is a statement about the data type not whether or
73
not some abelian variety is modular::
74
75
sage: is_ModularAbelianVariety(EllipticCurve('37a'))
76
False
77
"""
78
return isinstance(x, ModularAbelianVariety_abstract)
79
80
81
class ModularAbelianVariety_abstract(ParentWithBase):
82
def __init__(self, groups, base_field, is_simple=None, newform_level=None,
83
isogeny_number=None, number=None, check=True):
84
"""
85
Abstract base class for modular abelian varieties.
86
87
INPUT:
88
89
90
- ``groups`` - a tuple of congruence subgroups
91
92
- ``base_field`` - a field
93
94
- ``is_simple`` - bool; whether or not self is
95
simple
96
97
- ``newform_level`` - if self is isogenous to a
98
newform abelian variety, returns the level of that abelian variety
99
100
- ``isogeny_number`` - which isogeny class the
101
corresponding newform is in; this corresponds to the Cremona letter
102
code
103
104
- ``number`` - the t number of the degeneracy map that
105
this abelian variety is the image under
106
107
- ``check`` - whether to do some type checking on the
108
defining data
109
110
111
EXAMPLES: One should not create an instance of this class, but we
112
do so anyways here as an example::
113
114
sage: A = sage.modular.abvar.abvar.ModularAbelianVariety_abstract((Gamma0(37),), QQ)
115
sage: type(A)
116
<class 'sage.modular.abvar.abvar.ModularAbelianVariety_abstract_with_category'>
117
118
119
All hell breaks loose if you try to do anything with `A`::
120
121
sage: A
122
Traceback (most recent call last):
123
...
124
NotImplementedError: BUG -- lattice method must be defined in derived class
125
126
127
All instances of this class are in the category of modular
128
abelian varieties::
129
130
sage: A.category()
131
Category of modular abelian varieties over Rational Field
132
sage: J0(23).category()
133
Category of modular abelian varieties over Rational Field
134
"""
135
if check:
136
if not isinstance(groups, tuple):
137
raise TypeError, "groups must be a tuple"
138
for G in groups:
139
if not is_CongruenceSubgroup(G):
140
raise TypeError, "each element of groups must be a congruence subgroup"
141
self.__groups = groups
142
if is_simple is not None:
143
self.__is_simple = is_simple
144
if newform_level is not None:
145
self.__newform_level = newform_level
146
if number is not None:
147
self.__degen_t = number
148
if isogeny_number is not None:
149
self.__isogeny_number = isogeny_number
150
if check and not is_Ring(base_field) and base_field.is_field():
151
raise TypeError, "base_field must be a field"
152
ParentWithBase.__init__(self, base_field, category = ModularAbelianVarieties(base_field))
153
154
def groups(self):
155
r"""
156
Return an ordered tuple of the congruence subgroups that the
157
ambient product Jacobian is attached to.
158
159
Every modular abelian variety is a finite quotient of an abelian
160
subvariety of a product of modular Jacobians `J_\Gamma`.
161
This function returns a tuple containing the groups
162
`\Gamma`.
163
164
EXAMPLES::
165
166
sage: A = (J0(37) * J1(13))[0]; A
167
Simple abelian subvariety 13aG1(1,13) of dimension 2 of J0(37) x J1(13)
168
sage: A.groups()
169
(Congruence Subgroup Gamma0(37), Congruence Subgroup Gamma1(13))
170
"""
171
return self.__groups
172
173
#############################################################################
174
# lattice() *must* be defined by every derived class!!!!
175
def lattice(self):
176
"""
177
Return lattice in ambient cuspidal modular symbols product that
178
defines this modular abelian variety.
179
180
This must be defined in each derived class.
181
182
OUTPUT: a free module over `\ZZ`
183
184
EXAMPLES::
185
186
sage: A = sage.modular.abvar.abvar.ModularAbelianVariety_abstract((Gamma0(37),), QQ)
187
sage: A
188
Traceback (most recent call last):
189
...
190
NotImplementedError: BUG -- lattice method must be defined in derived class
191
"""
192
raise NotImplementedError, "BUG -- lattice method must be defined in derived class"
193
#############################################################################
194
195
def free_module(self):
196
r"""
197
Synonym for ``self.lattice()``.
198
199
OUTPUT: a free module over `\ZZ`
200
201
EXAMPLES::
202
203
sage: J0(37).free_module()
204
Ambient free module of rank 4 over the principal ideal domain Integer Ring
205
sage: J0(37)[0].free_module()
206
Free module of degree 4 and rank 2 over Integer Ring
207
Echelon basis matrix:
208
[ 1 -1 1 0]
209
[ 0 0 2 -1]
210
"""
211
return self.lattice()
212
213
def vector_space(self):
214
r"""
215
Return vector space corresponding to the modular abelian variety.
216
217
This is the lattice tensored with `\QQ`.
218
219
EXAMPLES::
220
221
sage: J0(37).vector_space()
222
Vector space of dimension 4 over Rational Field
223
sage: J0(37)[0].vector_space()
224
Vector space of degree 4 and dimension 2 over Rational Field
225
Basis matrix:
226
[ 1 -1 0 1/2]
227
[ 0 0 1 -1/2]
228
"""
229
try:
230
return self.__vector_space
231
except AttributeError:
232
self.__vector_space = self.lattice().change_ring(QQ)
233
return self.__vector_space
234
235
def base_field(self):
236
r"""
237
Synonym for ``self.base_ring()``.
238
239
EXAMPLES::
240
241
sage: J0(11).base_field()
242
Rational Field
243
"""
244
return self.base_ring()
245
246
def base_extend(self, K):
247
"""
248
EXAMPLES::
249
250
sage: A = J0(37); A
251
Abelian variety J0(37) of dimension 2
252
sage: A.base_extend(QQbar)
253
Abelian variety J0(37) over Algebraic Field of dimension 2
254
sage: A.base_extend(GF(7))
255
Abelian variety J0(37) over Finite Field of size 7 of dimension 2
256
"""
257
N = self.__newform_level if hasattr(self, '__newform_level') else None
258
return ModularAbelianVariety(self.groups(), self.lattice(), K, newform_level=N)
259
260
def __contains__(self, x):
261
"""
262
Determine whether or not self contains x.
263
264
EXAMPLES::
265
266
sage: J = J0(67); G = (J[0] + J[1]).intersection(J[1] + J[2])
267
sage: G[0]
268
Finite subgroup with invariants [5, 10] over QQbar of Abelian subvariety of dimension 3 of J0(67)
269
sage: a = G[0].0; a
270
[(1/10, 1/10, 3/10, 1/2, 1, -2, -3, 33/10, 0, -1/2)]
271
sage: a in J[0]
272
False
273
sage: a in (J[0]+J[1])
274
True
275
sage: a in (J[1]+J[2])
276
True
277
sage: C = G[1] # abelian variety in kernel
278
sage: G[0].0
279
[(1/10, 1/10, 3/10, 1/2, 1, -2, -3, 33/10, 0, -1/2)]
280
sage: 5*G[0].0
281
[(1/2, 1/2, 3/2, 5/2, 5, -10, -15, 33/2, 0, -5/2)]
282
sage: 5*G[0].0 in C
283
True
284
"""
285
if not isinstance(x, TorsionPoint):
286
return False
287
if x.parent().abelian_variety().groups() != self.groups():
288
return False
289
v = x.element()
290
n = v.denominator()
291
nLambda = self.ambient_variety().lattice().scale(n)
292
return n*v in self.lattice() + nLambda
293
294
def __cmp__(self, other):
295
"""
296
Compare two modular abelian varieties.
297
298
If other is not a modular abelian variety, compares the types of
299
self and other. If other is a modular abelian variety, compares the
300
groups, then if those are the same, compares the newform level and
301
isogeny class number and degeneracy map numbers. If those are not
302
defined or matched up, compare the underlying lattices.
303
304
EXAMPLES::
305
306
sage: cmp(J0(37)[0], J0(37)[1])
307
-1
308
sage: cmp(J0(33)[0], J0(33)[1])
309
-1
310
sage: cmp(J0(37), 5) #random
311
1
312
"""
313
if not isinstance(other, ModularAbelianVariety_abstract):
314
return cmp(type(self), type(other))
315
if self is other:
316
return 0
317
c = cmp(self.groups(), other.groups())
318
if c: return c
319
320
try:
321
c = cmp(self.__newform_level, other.__newform_level)
322
if c: return c
323
except AttributeError:
324
pass
325
try:
326
c = cmp(self.__isogeny_number, other.__isogeny_number)
327
if c: return c
328
except AttributeError:
329
pass
330
331
try:
332
c = cmp(self.__degen_t, other.__degen_t)
333
if c: return c
334
except AttributeError:
335
pass
336
337
# NOTE!! having the same newform level, isogeny class number,
338
# and degen_t does not imply two abelian varieties are equal.
339
# See the docstring for self.label.
340
341
return cmp(self.lattice(), other.lattice())
342
343
def __radd__(self,other):
344
"""
345
Return other + self when other is 0. Otherwise raise a TypeError.
346
347
EXAMPLES::
348
349
sage: int(0) + J0(37)
350
Abelian variety J0(37) of dimension 2
351
"""
352
if other == 0:
353
return self
354
raise TypeError
355
356
def _repr_(self):
357
"""
358
Return string representation of this modular abelian variety.
359
360
This is just the generic base class, so it's unlikely to be called
361
in practice.
362
363
EXAMPLES::
364
365
sage: A = J0(23)
366
sage: import sage.modular.abvar.abvar as abvar
367
sage: abvar.ModularAbelianVariety_abstract._repr_(A)
368
'Abelian variety J0(23) of dimension 2'
369
370
::
371
372
sage: (J0(11) * J0(33))._repr_()
373
'Abelian variety J0(11) x J0(33) of dimension 4'
374
"""
375
field = '' if self.base_field() == QQ else ' over %s'%self.base_field()
376
#if self.newform_level(none_if_not_known=True) is None:
377
simple = self.is_simple(none_if_not_known=True)
378
if simple and self.dimension() > 0:
379
label = self.label() + ' '
380
else:
381
label = ''
382
simple = 'Simple a' if simple else 'A'
383
if self.is_ambient():
384
return '%sbelian variety %s%s of dimension %s'%(simple, self._ambient_repr(), field, self.dimension())
385
386
if self.is_subvariety_of_ambient_jacobian():
387
sub = 'subvariety'
388
else:
389
sub = 'variety factor'
390
return "%sbelian %s %sof dimension %s of %s%s"%(
391
simple, sub, label, self.dimension(), self._ambient_repr(), field)
392
393
394
def label(self):
395
r"""
396
Return the label associated to this modular abelian variety.
397
398
The format of the label is [level][isogeny class][group](t, ambient
399
level)
400
401
If this abelian variety `B` has the above label, this
402
implies only that `B` is isogenous to the newform abelian
403
variety `A_f` associated to the newform with label
404
[level][isogeny class][group]. The [group] is empty for
405
`\Gamma_0(N)`, is G1 for `\Gamma_1(N)` and is
406
GH[...] for `\Gamma_H(N)`.
407
408
.. warning::
409
410
The sum of `\delta_s(A_f)` for all `s\mid t`
411
contains `A`, but no sum for a proper divisor of
412
`t` contains `A`. It need *not* be the case
413
that `B` is equal to `\delta_t(A_f)`!!!
414
415
OUTPUT: string
416
417
EXAMPLES::
418
419
sage: J0(11).label()
420
'11a(1,11)'
421
sage: J0(11)[0].label()
422
'11a(1,11)'
423
sage: J0(33)[2].label()
424
'33a(1,33)'
425
sage: J0(22).label()
426
Traceback (most recent call last):
427
...
428
ValueError: self must be simple
429
430
We illustrate that self need not equal `\delta_t(A_f)`::
431
432
sage: J = J0(11); phi = J.degeneracy_map(33, 1) + J.degeneracy_map(33,3)
433
sage: B = phi.image(); B
434
Abelian subvariety of dimension 1 of J0(33)
435
sage: B.decomposition()
436
[
437
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33)
438
]
439
sage: C = J.degeneracy_map(33,3).image(); C
440
Abelian subvariety of dimension 1 of J0(33)
441
sage: C == B
442
False
443
"""
444
degen = str(self.degen_t()).replace(' ','')
445
return '%s%s'%(self.newform_label(), degen)
446
447
def newform_label(self):
448
"""
449
Return the label [level][isogeny class][group] of the newform
450
`f` such that this abelian variety is isogenous to the
451
newform abelian variety `A_f`. If this abelian variety is
452
not simple, raise a ValueError.
453
454
OUTPUT: string
455
456
EXAMPLES::
457
458
sage: J0(11).newform_label()
459
'11a'
460
sage: J0(33)[2].newform_label()
461
'33a'
462
463
The following fails since `J_0(33)` is not simple::
464
465
sage: J0(33).newform_label()
466
Traceback (most recent call last):
467
...
468
ValueError: self must be simple
469
"""
470
N, G = self.newform_level()
471
if is_Gamma0(G):
472
group = ''
473
elif is_Gamma1(G):
474
group = 'G1'
475
elif is_GammaH(G):
476
group = 'GH%s'%(str(G._generators_for_H()).replace(' ',''))
477
return '%s%s%s'%(N, cremona_letter_code(self.isogeny_number()), group)
478
479
def _isogeny_to_newform_abelian_variety(self):
480
r"""
481
Return an isogeny from self to an abelian variety `A_f`
482
attached to a newform. If self is not simple (so that no such
483
isogeny exists), raise a ValueError.
484
485
EXAMPLES::
486
487
sage: J0(22)[0]._isogeny_to_newform_abelian_variety()
488
Abelian variety morphism:
489
From: Simple abelian subvariety 11a(1,22) of dimension 1 of J0(22)
490
To: Newform abelian subvariety 11a of dimension 1 of J0(11)
491
sage: J = J0(11); phi = J.degeneracy_map(33, 1) + J.degeneracy_map(33,3)
492
sage: A = phi.image()
493
sage: A._isogeny_to_newform_abelian_variety().matrix()
494
[-3 3]
495
[ 0 -3]
496
"""
497
try:
498
return self._newform_isogeny
499
except AttributeError:
500
pass
501
502
if not self.is_simple():
503
raise ValueError, "self is not simple"
504
505
ls = []
506
507
t, N = self.decomposition()[0].degen_t()
508
A = self.ambient_variety()
509
for i in range(len(self.groups())):
510
g = self.groups()[i]
511
if N == g.level():
512
J = g.modular_abelian_variety()
513
d = J.degeneracy_map(self.newform_level()[0], t)
514
p = A.project_to_factor(i)
515
mat = p.matrix() * d.matrix()
516
if not (self.lattice().matrix() * mat).is_zero():
517
break
518
519
from constructor import AbelianVariety
520
Af = AbelianVariety(self.newform_label())
521
H = A.Hom(Af.ambient_variety())
522
m = H(Morphism(H, mat))
523
self._newform_isogeny = m.restrict_domain(self).restrict_codomain(Af)
524
return self._newform_isogeny
525
526
def _simple_isogeny(self, other):
527
"""
528
Given self and other, if both are simple, and correspond to the
529
same newform with the same congruence subgroup, return an isogeny.
530
Otherwise, raise a ValueError.
531
532
INPUT:
533
534
535
- ``self, other`` - modular abelian varieties
536
537
538
OUTPUT: an isogeny
539
540
EXAMPLES::
541
542
sage: J = J0(33); J
543
Abelian variety J0(33) of dimension 3
544
sage: J[0]._simple_isogeny(J[1])
545
Abelian variety morphism:
546
From: Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
547
To: Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33)
548
549
The following illustrates how simple isogeny is only implemented
550
when the ambients are the same::
551
552
sage: J[0]._simple_isogeny(J1(11))
553
Traceback (most recent call last):
554
...
555
NotImplementedError: _simple_isogeny only implemented when both abelian variety have the same ambient product Jacobian
556
"""
557
if not is_ModularAbelianVariety(other):
558
raise TypeError, "other must be a modular abelian variety"
559
560
if not self.is_simple():
561
raise ValueError, "self is not simple"
562
563
if not other.is_simple():
564
raise ValueError, "other is not simple"
565
566
if self.groups() != other.groups():
567
# The issue here is that the stuff below probably won't make any sense at all if we don't know
568
# that the two newform abelian varieties $A_f$ are identical.
569
raise NotImplementedError, "_simple_isogeny only implemented when both abelian variety have the same ambient product Jacobian"
570
571
572
if (self.newform_level() != other.newform_level()) or \
573
(self.isogeny_number() != other.isogeny_number()):
574
raise ValueError, "self and other do not correspond to the same newform"
575
576
return other._isogeny_to_newform_abelian_variety().complementary_isogeny() * \
577
self._isogeny_to_newform_abelian_variety()
578
579
def _Hom_(self, B, cat=None):
580
"""
581
INPUT:
582
583
584
- ``B`` - modular abelian varieties
585
586
- ``cat`` - category
587
588
589
EXAMPLES::
590
591
sage: J0(37)._Hom_(J1(37))
592
Space of homomorphisms from Abelian variety J0(37) of dimension 2 to Abelian variety J1(37) of dimension 40
593
sage: J0(37)._Hom_(J1(37)).homset_category()
594
Category of modular abelian varieties over Rational Field
595
"""
596
if cat is None:
597
K = self.base_field(); L = B.base_field()
598
if K == L:
599
F = K
600
elif K == QQbar or L == QQbar:
601
F = QQbar
602
else:
603
# TODO -- improve this
604
raise ValueError, "please specify a category"
605
cat = ModularAbelianVarieties(F)
606
if self is B:
607
return self.endomorphism_ring()
608
else:
609
return homspace.Homspace(self, B, cat)
610
611
def in_same_ambient_variety(self, other):
612
"""
613
Return True if self and other are abelian subvarieties of the same
614
ambient product Jacobian.
615
616
EXAMPLES::
617
618
sage: A,B,C = J0(33)
619
sage: A.in_same_ambient_variety(B)
620
True
621
sage: A.in_same_ambient_variety(J0(11))
622
False
623
"""
624
if not is_ModularAbelianVariety(other):
625
return False
626
if self.groups() != other.groups():
627
return False
628
if not self.is_subvariety_of_ambient_jacobian() or not other.is_subvariety_of_ambient_jacobian():
629
return False
630
return True
631
632
def modular_kernel(self):
633
"""
634
Return the modular kernel of this abelian variety, which is the
635
kernel of the canonical polarization of self.
636
637
EXAMPLES::
638
639
sage: A = AbelianVariety('33a'); A
640
Newform abelian subvariety 33a of dimension 1 of J0(33)
641
sage: A.modular_kernel()
642
Finite subgroup with invariants [3, 3] over QQ of Newform abelian subvariety 33a of dimension 1 of J0(33)
643
"""
644
try:
645
return self.__modular_kernel
646
except AttributeError:
647
_, f, _ = self.dual()
648
G = f.kernel()[0]
649
self.__modular_kernel = G
650
return G
651
652
def modular_degree(self):
653
"""
654
Return the modular degree of this abelian variety, which is the
655
square root of the degree of the modular kernel.
656
657
EXAMPLES::
658
659
sage: A = AbelianVariety('37a')
660
sage: A.modular_degree()
661
2
662
"""
663
n = self.modular_kernel().order()
664
return ZZ(n.sqrt())
665
666
667
def intersection(self, other):
668
"""
669
Returns the intersection of self and other inside a common ambient
670
Jacobian product.
671
672
INPUT:
673
674
675
- ``other`` - a modular abelian variety or a finite
676
group
677
678
679
OUTPUT: If other is a modular abelian variety:
680
681
682
- ``G`` - finite subgroup of self
683
684
- ``A`` - abelian variety (identity component of
685
intersection) If other is a finite group:
686
687
- ``G`` - a finite group
688
689
690
EXAMPLES: We intersect some abelian varieties with finite
691
intersection.
692
693
::
694
695
sage: J = J0(37)
696
sage: J[0].intersection(J[1])
697
(Finite subgroup with invariants [2, 2] over QQ of Simple abelian subvariety 37a(1,37) of dimension 1 of J0(37), Simple abelian subvariety of dimension 0 of J0(37))
698
699
::
700
701
sage: D = list(J0(65)); D
702
[Simple abelian subvariety 65a(1,65) of dimension 1 of J0(65), Simple abelian subvariety 65b(1,65) of dimension 2 of J0(65), Simple abelian subvariety 65c(1,65) of dimension 2 of J0(65)]
703
sage: D[0].intersection(D[1])
704
(Finite subgroup with invariants [2] over QQ of Simple abelian subvariety 65a(1,65) of dimension 1 of J0(65), Simple abelian subvariety of dimension 0 of J0(65))
705
sage: (D[0]+D[1]).intersection(D[1]+D[2])
706
(Finite subgroup with invariants [2] over QQbar of Abelian subvariety of dimension 3 of J0(65), Abelian subvariety of dimension 2 of J0(65))
707
708
::
709
710
sage: J = J0(33)
711
sage: J[0].intersection(J[1])
712
(Finite subgroup with invariants [5] over QQ of Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33), Simple abelian subvariety of dimension 0 of J0(33))
713
714
Next we intersect two abelian varieties with non-finite
715
intersection::
716
717
sage: J = J0(67); D = J.decomposition(); D
718
[
719
Simple abelian subvariety 67a(1,67) of dimension 1 of J0(67),
720
Simple abelian subvariety 67b(1,67) of dimension 2 of J0(67),
721
Simple abelian subvariety 67c(1,67) of dimension 2 of J0(67)
722
]
723
sage: (D[0] + D[1]).intersection(D[1] + D[2])
724
(Finite subgroup with invariants [5, 10] over QQbar of Abelian subvariety of dimension 3 of J0(67), Abelian subvariety of dimension 2 of J0(67))
725
"""
726
# First check whether we are intersecting an abelian variety
727
# with a finite subgroup. If so, call the intersection method
728
# for the finite group, which does know how to intersect with
729
# an abelian variety.
730
if isinstance(other, FiniteSubgroup):
731
return other.intersection(self)
732
733
# Now both self and other are abelian varieties. We require
734
# at least that the ambient Jacobian product is the same for
735
# them.
736
if not self.in_same_ambient_variety(other):
737
raise TypeError, "other must be an abelian variety in the same ambient space"
738
739
# 1. Compute the abelian variety (connected) part of the intersection
740
V = self.vector_space().intersection(other.vector_space())
741
if V.dimension() > 0:
742
# If there is a nonzero abelian variety, get the actual
743
# lattice that defines it. We intersect (=saturate) in
744
# the sum of the lattices, to ensure that the intersection
745
# is an abelian subvariety of both self and other (even if
746
# they aren't subvarieties of the ambient Jacobian).
747
lattice = V.intersection(self.lattice() + other.lattice())
748
A = ModularAbelianVariety(self.groups(), lattice, self.base_field(), check=False)
749
else:
750
A = self.zero_subvariety()
751
752
# 2. Compute the finite intersection group when the
753
# intersection is finite, or a group that maps surjectively
754
# onto the component group in general.
755
756
# First we get basis matrices for the lattices that define
757
# both abelian varieties.
758
L = self.lattice().basis_matrix()
759
M = other.lattice().basis_matrix()
760
761
# Then we stack matrices and find a subset that forms a
762
# basis.
763
LM = L.stack(M)
764
P = LM.pivot_rows()
765
V = (ZZ**L.ncols()).span_of_basis([LM.row(p) for p in P])
766
S = (self.lattice() + other.lattice()).saturation()
767
n = self.lattice().rank()
768
# Finally we project onto the L factor.
769
gens = [L.linear_combination_of_rows(v.list()[:n])
770
for v in V.coordinate_module(S).basis()]
771
772
if A.dimension() > 0:
773
finitegroup_base_field = QQbar
774
else:
775
finitegroup_base_field = self.base_field()
776
G = self.finite_subgroup(gens, field_of_definition=finitegroup_base_field)
777
778
779
return G, A
780
781
782
def __add__(self, other):
783
r"""
784
Returns the sum of the *images* of self and other inside the
785
ambient Jacobian product. self and other must be abelian
786
subvarieties of the ambient Jacobian product.
787
788
..warning::
789
790
The sum of course only makes sense in some ambient variety,
791
and by definition this function takes the sum of the images
792
of both self and other in the ambient product Jacobian.
793
794
EXAMPLES: We compute the sum of two abelian varieties of
795
`J_0(33)`::
796
797
sage: J = J0(33)
798
sage: J[0] + J[1]
799
Abelian subvariety of dimension 2 of J0(33)
800
801
We sum all three and get the full `J_0(33)`::
802
803
sage: (J[0] + J[1]) + (J[1] + J[2])
804
Abelian variety J0(33) of dimension 3
805
806
Adding to zero works::
807
808
sage: J[0] + 0
809
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
810
811
Hence the sum command works::
812
813
sage: sum([J[0], J[2]])
814
Abelian subvariety of dimension 2 of J0(33)
815
816
We try to add something in `J_0(33)` to something in
817
`J_0(11)`; this shouldn't and doesn't work.
818
819
::
820
821
sage: J[0] + J0(11)
822
Traceback (most recent call last):
823
...
824
TypeError: sum not defined since ambient spaces different
825
826
We compute the diagonal image of `J_0(11)` in
827
`J_0(33)`, then add the result to the new elliptic curve
828
of level `33`.
829
830
::
831
832
sage: A = J0(11)
833
sage: B = (A.degeneracy_map(33,1) + A.degeneracy_map(33,3)).image()
834
sage: B + J0(33)[2]
835
Abelian subvariety of dimension 2 of J0(33)
836
837
TESTS: This exposed a bug in HNF (see trac #4527)::
838
839
sage: A = J0(206).new_subvariety().decomposition()[3] ; A # long time
840
Simple abelian subvariety 206d(1,206) of dimension 4 of J0(206)
841
sage: B = J0(206).old_subvariety(2) ; B # long time
842
Abelian subvariety of dimension 16 of J0(206)
843
sage: A+B # long time
844
Abelian subvariety of dimension 20 of J0(206)
845
"""
846
if not is_ModularAbelianVariety(other):
847
if other == 0:
848
return self
849
raise TypeError, "other must be a modular abelian variety"
850
if self.groups() != other.groups():
851
raise ValueError, "incompatible ambient Jacobians"
852
L = self.vector_space() + other.vector_space()
853
M = L.intersection(self._ambient_lattice())
854
return ModularAbelianVariety(self.groups(), M, self.base_field(), check=False)
855
856
def direct_product(self, other):
857
"""
858
Compute the direct product of self and other.
859
860
INPUT:
861
862
863
- ``self, other`` - modular abelian varieties
864
865
866
OUTPUT: abelian variety
867
868
EXAMPLES::
869
870
sage: J0(11).direct_product(J1(13))
871
Abelian variety J0(11) x J1(13) of dimension 3
872
sage: A = J0(33)[0].direct_product(J0(33)[1]); A
873
Abelian subvariety of dimension 2 of J0(33) x J0(33)
874
sage: A.lattice()
875
Free module of degree 12 and rank 4 over Integer Ring
876
Echelon basis matrix:
877
[ 1 1 -2 0 2 -1 0 0 0 0 0 0]
878
[ 0 3 -2 -1 2 0 0 0 0 0 0 0]
879
[ 0 0 0 0 0 0 1 0 0 0 -1 2]
880
[ 0 0 0 0 0 0 0 1 -1 1 0 -2]
881
"""
882
return self * other
883
884
def __pow__(self, n):
885
"""
886
Return `n^{th}` power of self.
887
888
INPUT:
889
890
891
- ``n`` - a nonnegative integer
892
893
894
OUTPUT: an abelian variety
895
896
EXAMPLES::
897
898
sage: J = J0(37)
899
sage: J^0
900
Simple abelian subvariety of dimension 0 of J0(37)
901
sage: J^1
902
Abelian variety J0(37) of dimension 2
903
sage: J^1 is J
904
True
905
"""
906
n = ZZ(n)
907
if n < 0:
908
raise ValueError, "n must be nonnegative"
909
if n == 0:
910
return self.zero_subvariety()
911
if n == 1:
912
return self
913
groups = self.groups() * n
914
L = self.lattice().basis_matrix()
915
lattice = block_diagonal_matrix([L]*n).row_module(ZZ)
916
return ModularAbelianVariety(groups, lattice, self.base_field(), check=False)
917
918
def __mul__(self, other):
919
"""
920
Compute the direct product of self and other.
921
922
EXAMPLES: Some modular Jacobians::
923
924
sage: J0(11) * J0(33)
925
Abelian variety J0(11) x J0(33) of dimension 4
926
sage: J0(11) * J0(33) * J0(11)
927
Abelian variety J0(11) x J0(33) x J0(11) of dimension 5
928
929
We multiply some factors of `J_0(65)`::
930
931
sage: d = J0(65).decomposition()
932
sage: d[0] * d[1] * J0(11)
933
Abelian subvariety of dimension 4 of J0(65) x J0(65) x J0(11)
934
"""
935
if not is_ModularAbelianVariety(other):
936
raise TypeError, "other must be a modular abelian variety"
937
if other.base_ring() != self.base_ring():
938
raise TypeError, "self and other must have the same base ring"
939
groups = tuple(list(self.groups()) + list(other.groups()))
940
lattice = self.lattice().direct_sum(other.lattice())
941
base_field = self.base_ring()
942
return ModularAbelianVariety(groups, lattice, base_field, check=False)
943
944
def quotient(self, other):
945
"""
946
Compute the quotient of self and other, where other is either an
947
abelian subvariety of self or a finite subgroup of self.
948
949
INPUT:
950
951
952
- ``other`` - a finite subgroup or subvariety
953
954
955
OUTPUT: a pair (A, phi) with phi the quotient map from self to A
956
957
EXAMPLES: We quotient `J_0(33)` out by an abelian
958
subvariety::
959
960
sage: Q, f = J0(33).quotient(J0(33)[0])
961
sage: Q
962
Abelian variety factor of dimension 2 of J0(33)
963
sage: f
964
Abelian variety morphism:
965
From: Abelian variety J0(33) of dimension 3
966
To: Abelian variety factor of dimension 2 of J0(33)
967
968
We quotient `J_0(33)` by the cuspidal subgroup::
969
970
sage: C = J0(33).cuspidal_subgroup()
971
sage: Q, f = J0(33).quotient(C)
972
sage: Q
973
Abelian variety factor of dimension 3 of J0(33)
974
sage: f.kernel()[0]
975
Finite subgroup with invariants [10, 10] over QQ of Abelian variety J0(33) of dimension 3
976
sage: C
977
Finite subgroup with invariants [10, 10] over QQ of Abelian variety J0(33) of dimension 3
978
sage: J0(11).direct_product(J1(13))
979
Abelian variety J0(11) x J1(13) of dimension 3
980
"""
981
return self.__div__(other)
982
983
def __div__(self, other):
984
"""
985
Compute the quotient of self and other, where other is either an
986
abelian subvariety of self or a finite subgroup of self.
987
988
INPUT:
989
990
991
- ``other`` - a finite subgroup or subvariety
992
993
994
EXAMPLES: Quotient out by a finite group::
995
996
sage: J = J0(67); G = (J[0] + J[1]).intersection(J[1] + J[2])
997
sage: Q, _ = J/G[0]; Q
998
Abelian variety factor of dimension 5 of J0(67) over Algebraic Field
999
sage: Q.base_field()
1000
Algebraic Field
1001
sage: Q.lattice()
1002
Free module of degree 10 and rank 10 over Integer Ring
1003
Echelon basis matrix:
1004
[1/10 1/10 3/10 1/2 0 0 0 3/10 0 1/2]
1005
[ 0 1/5 4/5 4/5 0 0 0 0 0 3/5]
1006
...
1007
1008
Quotient out by an abelian subvariety::
1009
1010
sage: A, B, C = J0(33)
1011
sage: Q, phi = J0(33)/A
1012
sage: Q
1013
Abelian variety factor of dimension 2 of J0(33)
1014
sage: phi.domain()
1015
Abelian variety J0(33) of dimension 3
1016
sage: phi.codomain()
1017
Abelian variety factor of dimension 2 of J0(33)
1018
sage: phi.kernel()
1019
(Finite subgroup with invariants [2] over QQbar of Abelian variety J0(33) of dimension 3,
1020
Abelian subvariety of dimension 1 of J0(33))
1021
sage: phi.kernel()[1] == A
1022
True
1023
1024
The abelian variety we quotient out by must be an abelian
1025
subvariety.
1026
1027
::
1028
1029
sage: Q = (A + B)/C; Q
1030
Traceback (most recent call last):
1031
...
1032
TypeError: other must be a subgroup or abelian subvariety
1033
"""
1034
if isinstance(other, FiniteSubgroup):
1035
if other.abelian_variety() != self:
1036
other = self.finite_subgroup(other)
1037
return self._quotient_by_finite_subgroup(other)
1038
elif isinstance(other, ModularAbelianVariety_abstract) and other.is_subvariety(self):
1039
return self._quotient_by_abelian_subvariety(other)
1040
else:
1041
raise TypeError, "other must be a subgroup or abelian subvariety"
1042
1043
def degeneracy_map(self, M_ls, t_ls):
1044
"""
1045
Return the degeneracy map with domain self and given
1046
level/parameter. If self.ambient_variety() is a product of
1047
Jacobians (as opposed to a single Jacobian), then one can provide a
1048
list of new levels and parameters, corresponding to the ambient
1049
Jacobians in order. (See the examples below.)
1050
1051
INPUT:
1052
1053
1054
- ``M, t`` - integers level and `t`, or
1055
1056
- ``Mlist, tlist`` - if self is in a nontrivial
1057
product ambient Jacobian, input consists of a list of levels and
1058
corresponding list of `t`'s.
1059
1060
1061
OUTPUT: a degeneracy map
1062
1063
EXAMPLES: We make several degeneracy maps related to
1064
`J_0(11)` and `J_0(33)` and compute their
1065
matrices.
1066
1067
::
1068
1069
sage: d1 = J0(11).degeneracy_map(33, 1); d1
1070
Degeneracy map from Abelian variety J0(11) of dimension 1 to Abelian variety J0(33) of dimension 3 defined by [1]
1071
sage: d1.matrix()
1072
[ 0 -3 2 1 -2 0]
1073
[ 1 -2 0 1 0 -1]
1074
sage: d2 = J0(11).degeneracy_map(33, 3); d2
1075
Degeneracy map from Abelian variety J0(11) of dimension 1 to Abelian variety J0(33) of dimension 3 defined by [3]
1076
sage: d2.matrix()
1077
[-1 0 0 0 1 -2]
1078
[-1 -1 1 -1 1 0]
1079
sage: d3 = J0(33).degeneracy_map(11, 1); d3
1080
Degeneracy map from Abelian variety J0(33) of dimension 3 to Abelian variety J0(11) of dimension 1 defined by [1]
1081
1082
He we verify that first mapping from level `11` to level
1083
`33`, then back is multiplication by `4`::
1084
1085
sage: d1.matrix() * d3.matrix()
1086
[4 0]
1087
[0 4]
1088
1089
We compute a more complicated degeneracy map involving nontrivial
1090
product ambient Jacobians; note that this is just the block direct
1091
sum of the two matrices at the beginning of this example::
1092
1093
sage: d = (J0(11)*J0(11)).degeneracy_map([33,33], [1,3]); d
1094
Degeneracy map from Abelian variety J0(11) x J0(11) of dimension 2 to Abelian variety J0(33) x J0(33) of dimension 6 defined by [1, 3]
1095
sage: d.matrix()
1096
[ 0 -3 2 1 -2 0 0 0 0 0 0 0]
1097
[ 1 -2 0 1 0 -1 0 0 0 0 0 0]
1098
[ 0 0 0 0 0 0 -1 0 0 0 1 -2]
1099
[ 0 0 0 0 0 0 -1 -1 1 -1 1 0]
1100
"""
1101
if not isinstance(M_ls, list):
1102
M_ls = [M_ls]
1103
if not isinstance(t_ls, list):
1104
t_ls = [t_ls]
1105
1106
groups = self.groups()
1107
length = len(M_ls)
1108
if length != len(t_ls):
1109
raise ValueError, "must have same number of Ms and ts"
1110
if length != len(groups):
1111
raise ValueError, "must have same number of Ms and groups in ambient variety"
1112
1113
for i in range(length):
1114
N = groups[i].level()
1115
if (M_ls[i]%N) and (N%M_ls[i]):
1116
raise ValueError, "one level must divide the other in %s-th component"%i
1117
if (( max(M_ls[i],N) // min(M_ls[i],N) ) % t_ls[i]):
1118
raise ValueError, "each t must divide the quotient of the levels"
1119
1120
ls = [ self.groups()[i].modular_abelian_variety().degeneracy_map(M_ls[i], t_ls[i]).matrix() for i in range(length) ]
1121
1122
1123
new_codomain = prod([ self.groups()[i]._new_group_from_level(M_ls[i]).modular_abelian_variety()
1124
for i in range(length) ])
1125
M = block_diagonal_matrix(ls, subdivide=False)
1126
1127
H = self.Hom(new_codomain)
1128
return H(DegeneracyMap(H, M.restrict_domain(self.lattice()), t_ls))
1129
1130
def _quotient_by_finite_subgroup(self, G):
1131
"""
1132
Return the quotient of self by the finite subgroup `G`.
1133
This is used internally by the quotient and __div__ commands.
1134
1135
INPUT:
1136
1137
1138
- ``G`` - a finite subgroup of self
1139
1140
1141
OUTPUT: abelian variety - the quotient `Q` of self by
1142
`G`
1143
1144
1145
- ``morphism`` - from self to the quotient
1146
`Q`
1147
1148
1149
EXAMPLES: We quotient the elliptic curve `J_0(11)` out by
1150
its cuspidal subgroup.
1151
1152
::
1153
1154
sage: A = J0(11)
1155
sage: G = A.cuspidal_subgroup(); G
1156
Finite subgroup with invariants [5] over QQ of Abelian variety J0(11) of dimension 1
1157
sage: Q, f = A._quotient_by_finite_subgroup(G)
1158
sage: Q
1159
Abelian variety factor of dimension 1 of J0(11)
1160
sage: f
1161
Abelian variety morphism:
1162
From: Abelian variety J0(11) of dimension 1
1163
To: Abelian variety factor of dimension 1 of J0(11)
1164
1165
We compute the finite kernel of `f` (hence the [0]) and
1166
note that it equals the subgroup `G` that we quotiented out
1167
by::
1168
1169
sage: f.kernel()[0] == G
1170
True
1171
"""
1172
if G.order() == 1:
1173
return self
1174
L = self.lattice() + G.lattice()
1175
A = ModularAbelianVariety(self.groups(), L, G.field_of_definition())
1176
M = L.coordinate_module(self.lattice()).basis_matrix()
1177
phi = self.Hom(A)(M)
1178
return A, phi
1179
1180
def _quotient_by_abelian_subvariety(self, B):
1181
"""
1182
Return the quotient of self by the abelian variety `B`.
1183
This is used internally by the quotient and __div__ commands.
1184
1185
INPUT:
1186
1187
1188
- ``B`` - an abelian subvariety of self
1189
1190
1191
OUTPUT:
1192
1193
1194
- ``abelian variety`` - quotient `Q` of self
1195
by B
1196
1197
- ``morphism`` - from self to the quotient
1198
`Q`
1199
1200
1201
EXAMPLES: We compute the new quotient of `J_0(33)`.
1202
1203
::
1204
1205
sage: A = J0(33); B = A.old_subvariety()
1206
sage: Q, f = A._quotient_by_abelian_subvariety(B)
1207
1208
Note that the quotient happens to also be an abelian subvariety::
1209
1210
sage: Q
1211
Abelian subvariety of dimension 1 of J0(33)
1212
sage: Q.lattice()
1213
Free module of degree 6 and rank 2 over Integer Ring
1214
Echelon basis matrix:
1215
[ 1 0 0 -1 0 0]
1216
[ 0 0 1 0 1 -1]
1217
sage: f
1218
Abelian variety morphism:
1219
From: Abelian variety J0(33) of dimension 3
1220
To: Abelian subvariety of dimension 1 of J0(33)
1221
1222
We verify that `B` is equal to the kernel of the quotient
1223
map.
1224
1225
::
1226
1227
sage: f.kernel()[1] == B
1228
True
1229
1230
Next we quotient `J_0(33)` out by `Q` itself::
1231
1232
sage: C, g = A._quotient_by_abelian_subvariety(Q)
1233
1234
The result is not a subvariety::
1235
1236
sage: C
1237
Abelian variety factor of dimension 2 of J0(33)
1238
sage: C.lattice()
1239
Free module of degree 6 and rank 4 over Integer Ring
1240
Echelon basis matrix:
1241
[ 1/3 0 0 2/3 -1 0]
1242
[ 0 1 0 0 -1 1]
1243
[ 0 0 1/3 0 -2/3 2/3]
1244
[ 0 0 0 1 -1 -1]
1245
"""
1246
1247
# We first compute the complement of B in self to get
1248
# an abelian variety C also in self such that self/B
1249
# is isogenous to C. This is the case because the
1250
# projection map pi:self --> C is surjective and has
1251
# kernel a finite extension of the abelian variety B.
1252
C = B.complement(self)
1253
1254
# Now that we have C we need to find some abelian variety Q
1255
# isogenous to C and a map self --> Q whose kernel is exactly
1256
# B. We do this by computing the kernel of the map pi below,
1257
# which is an extension of the abelian variety B by a finite
1258
# group Phi of complements. Our strategy is to enlarge the
1259
# lattice that defines C so that the map pi below suddenly
1260
# has connected kernel.
1261
1262
pi = self.projection(C)
1263
psi = pi.factor_out_component_group()
1264
Q = psi.codomain()
1265
return Q, psi
1266
1267
def projection(self, A, check=True):
1268
"""
1269
Given an abelian subvariety A of self, return a projection morphism
1270
from self to A. Note that this morphism need not be unique.
1271
1272
INPUT:
1273
1274
1275
- ``A`` - an abelian variety
1276
1277
1278
OUTPUT: a morphism
1279
1280
EXAMPLES::
1281
1282
sage: a,b,c = J0(33)
1283
sage: pi = J0(33).projection(a); pi.matrix()
1284
[ 3 -2]
1285
[-5 5]
1286
[-4 1]
1287
[ 3 -2]
1288
[ 5 0]
1289
[ 1 1]
1290
sage: pi = (a+b).projection(a); pi.matrix()
1291
[ 0 0]
1292
[-3 2]
1293
[-4 1]
1294
[-1 -1]
1295
sage: pi = a.projection(a); pi.matrix()
1296
[1 0]
1297
[0 1]
1298
1299
We project onto a factor in a product of two Jacobians::
1300
1301
sage: A = J0(11)*J0(11); A
1302
Abelian variety J0(11) x J0(11) of dimension 2
1303
sage: A[0]
1304
Simple abelian subvariety 11a(1,11) of dimension 1 of J0(11) x J0(11)
1305
sage: A.projection(A[0])
1306
Abelian variety morphism:
1307
From: Abelian variety J0(11) x J0(11) of dimension 2
1308
To: Simple abelian subvariety 11a(1,11) of dimension 1 of J0(11) x J0(11)
1309
sage: A.projection(A[0]).matrix()
1310
[0 0]
1311
[0 0]
1312
[1 0]
1313
[0 1]
1314
sage: A.projection(A[1]).matrix()
1315
[1 0]
1316
[0 1]
1317
[0 0]
1318
[0 0]
1319
"""
1320
if check and not A.is_subvariety(self):
1321
raise ValueError, "A must be an abelian subvariety of self"
1322
1323
W = A.complement(self)
1324
mat = A.lattice().basis_matrix().stack(W.lattice().basis_matrix())
1325
1326
# solve X * mat = self, i.e. write each row of self in terms of the
1327
# rows of mat.
1328
X = mat.solve_left(self.lattice().basis_matrix())
1329
1330
# The projection map is got from the first 2*dim(A) columns of X.
1331
X = X.matrix_from_columns(range(2*A.dimension()))
1332
1333
X, _ = X._clear_denom()
1334
1335
return Morphism(self.Hom(A), X)
1336
1337
def project_to_factor(self, n):
1338
"""
1339
If self is an ambient product of Jacobians, return a projection
1340
from self to the nth such Jacobian.
1341
1342
EXAMPLES::
1343
1344
sage: J = J0(33)
1345
sage: J.project_to_factor(0)
1346
Abelian variety endomorphism of Abelian variety J0(33) of dimension 3
1347
1348
::
1349
1350
sage: J = J0(33) * J0(37) * J0(11)
1351
sage: J.project_to_factor(2)
1352
Abelian variety morphism:
1353
From: Abelian variety J0(33) x J0(37) x J0(11) of dimension 6
1354
To: Abelian variety J0(11) of dimension 1
1355
sage: J.project_to_factor(2).matrix()
1356
[0 0]
1357
[0 0]
1358
[0 0]
1359
[0 0]
1360
[0 0]
1361
[0 0]
1362
[0 0]
1363
[0 0]
1364
[0 0]
1365
[0 0]
1366
[1 0]
1367
[0 1]
1368
"""
1369
if not self.is_ambient():
1370
raise ValueError, "self is not ambient"
1371
if n >= len(self.groups()):
1372
raise IndexError, "index (=%s) too large (max = %s)"%(n, len(self.groups()))
1373
1374
G = self.groups()[n]
1375
A = G.modular_abelian_variety()
1376
index = sum([ gp.modular_symbols().cuspidal_subspace().dimension()
1377
for gp in self.groups()[0:n] ])
1378
1379
H = self.Hom(A)
1380
mat = H.matrix_space()(0)
1381
mat.set_block(index, 0, identity_matrix(2*A.dimension()))
1382
1383
return H(Morphism(H, mat))
1384
1385
1386
def is_subvariety_of_ambient_jacobian(self):
1387
"""
1388
Return True if self is (presented as) a subvariety of the ambient
1389
product Jacobian.
1390
1391
Every abelian variety in Sage is a quotient of a subvariety of an
1392
ambient Jacobian product by a finite subgroup.
1393
1394
EXAMPLES::
1395
1396
sage: J0(33).is_subvariety_of_ambient_jacobian()
1397
True
1398
sage: A = J0(33)[0]; A
1399
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
1400
sage: A.is_subvariety_of_ambient_jacobian()
1401
True
1402
sage: B, phi = A / A.torsion_subgroup(2)
1403
sage: B
1404
Abelian variety factor of dimension 1 of J0(33)
1405
sage: phi.matrix()
1406
[2 0]
1407
[0 2]
1408
sage: B.is_subvariety_of_ambient_jacobian()
1409
False
1410
"""
1411
try:
1412
return self.__is_sub_ambient
1413
except AttributeError:
1414
self.__is_sub_ambient = (self.lattice().denominator() == 1)
1415
return self.__is_sub_ambient
1416
1417
def ambient_variety(self):
1418
"""
1419
Return the ambient modular abelian variety that contains this
1420
abelian variety. The ambient variety is always a product of
1421
Jacobians of modular curves.
1422
1423
OUTPUT: abelian variety
1424
1425
EXAMPLES::
1426
1427
sage: A = J0(33)[0]; A
1428
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
1429
sage: A.ambient_variety()
1430
Abelian variety J0(33) of dimension 3
1431
"""
1432
try:
1433
return self.__ambient_variety
1434
except AttributeError:
1435
A = ModularAbelianVariety(self.groups(), ZZ**(2*self._ambient_dimension()),
1436
self.base_field(), check=False)
1437
self.__ambient_variety = A
1438
return A
1439
1440
def ambient_morphism(self):
1441
"""
1442
Return the morphism from self to the ambient variety. This is
1443
injective if self is natural a subvariety of the ambient product
1444
Jacobian.
1445
1446
OUTPUT: morphism
1447
1448
The output is cached.
1449
1450
EXAMPLES: We compute the ambient structure morphism for an abelian
1451
subvariety of `J_0(33)`::
1452
1453
sage: A,B,C = J0(33)
1454
sage: phi = A.ambient_morphism()
1455
sage: phi.domain()
1456
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
1457
sage: phi.codomain()
1458
Abelian variety J0(33) of dimension 3
1459
sage: phi.matrix()
1460
[ 1 1 -2 0 2 -1]
1461
[ 0 3 -2 -1 2 0]
1462
1463
phi is of course injective
1464
1465
::
1466
1467
sage: phi.kernel()
1468
(Finite subgroup with invariants [] over QQ of Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33),
1469
Abelian subvariety of dimension 0 of J0(33))
1470
1471
This is the same as the basis matrix for the lattice corresponding
1472
to self::
1473
1474
sage: A.lattice()
1475
Free module of degree 6 and rank 2 over Integer Ring
1476
Echelon basis matrix:
1477
[ 1 1 -2 0 2 -1]
1478
[ 0 3 -2 -1 2 0]
1479
1480
We compute a non-injective map to an ambient space::
1481
1482
sage: Q,pi = J0(33)/A
1483
sage: phi = Q.ambient_morphism()
1484
sage: phi.matrix()
1485
[ 1 4 1 9 -1 -1]
1486
[ 0 15 0 0 30 -75]
1487
[ 0 0 5 10 -5 15]
1488
[ 0 0 0 15 -15 30]
1489
sage: phi.kernel()[0]
1490
Finite subgroup with invariants [5, 15, 15] over QQ of Abelian variety factor of dimension 2 of J0(33)
1491
"""
1492
try:
1493
return self.__ambient_morphism
1494
except AttributeError:
1495
matrix,_ = self.lattice().basis_matrix()._clear_denom()
1496
phi = Morphism(self.Hom(self.ambient_variety()), matrix)
1497
self.__ambient_morphism = phi
1498
return phi
1499
1500
def is_ambient(self):
1501
"""
1502
Return True if self equals the ambient product Jacobian.
1503
1504
OUTPUT: bool
1505
1506
EXAMPLES::
1507
1508
sage: A,B,C = J0(33)
1509
sage: A.is_ambient()
1510
False
1511
sage: J0(33).is_ambient()
1512
True
1513
sage: (A+B).is_ambient()
1514
False
1515
sage: (A+B+C).is_ambient()
1516
True
1517
"""
1518
try:
1519
return self.__is_ambient
1520
except AttributeError:
1521
pass
1522
L = self.lattice()
1523
self.__is_ambient = (self.lattice() == ZZ**L.degree())
1524
return self.__is_ambient
1525
1526
def dimension(self):
1527
"""
1528
Return the dimension of this abelian variety.
1529
1530
EXAMPLES::
1531
1532
sage: A = J0(23)
1533
sage: A.dimension()
1534
2
1535
"""
1536
return self.lattice().rank() // 2
1537
1538
def rank(self):
1539
"""
1540
Return the rank of the underlying lattice of self.
1541
1542
EXAMPLES::
1543
1544
sage: J = J0(33)
1545
sage: J.rank()
1546
6
1547
sage: J[1]
1548
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33)
1549
sage: (J[1] * J[1]).rank()
1550
4
1551
"""
1552
return self.lattice().rank()
1553
1554
def degree(self):
1555
"""
1556
Return the degree of this abelian variety, which is the dimension
1557
of the ambient Jacobian product.
1558
1559
EXAMPLES::
1560
1561
sage: A = J0(23)
1562
sage: A.dimension()
1563
2
1564
"""
1565
return self._ambient_dimension()
1566
1567
def endomorphism_ring(self):
1568
"""
1569
Return the endomorphism ring of self.
1570
1571
OUTPUT: b = self.sturm_bound()
1572
1573
EXAMPLES: We compute a few endomorphism rings::
1574
1575
sage: J0(11).endomorphism_ring()
1576
Endomorphism ring of Abelian variety J0(11) of dimension 1
1577
sage: J0(37).endomorphism_ring()
1578
Endomorphism ring of Abelian variety J0(37) of dimension 2
1579
sage: J0(33)[2].endomorphism_ring()
1580
Endomorphism ring of Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33)
1581
1582
No real computation is done::
1583
1584
sage: J1(123456).endomorphism_ring()
1585
Endomorphism ring of Abelian variety J1(123456) of dimension 423185857
1586
"""
1587
try:
1588
return self.__endomorphism_ring
1589
except AttributeError:
1590
pass
1591
1592
self.__endomorphism_ring = homspace.EndomorphismSubring(self)
1593
return self.__endomorphism_ring
1594
1595
def sturm_bound(self):
1596
r"""
1597
Return a bound `B` such that all Hecke operators
1598
`T_n` for `n\leq B` generate the Hecke algebra.
1599
1600
OUTPUT: integer
1601
1602
EXAMPLES::
1603
1604
sage: J0(11).sturm_bound()
1605
2
1606
sage: J0(33).sturm_bound()
1607
8
1608
sage: J1(17).sturm_bound()
1609
48
1610
sage: J1(123456).sturm_bound()
1611
1693483008
1612
sage: JH(37,[2,3]).sturm_bound()
1613
7
1614
sage: J1(37).sturm_bound()
1615
228
1616
"""
1617
try:
1618
return self.__sturm_bound
1619
except AttributeError:
1620
B = max([G.sturm_bound(2) for G in self.groups()])
1621
self.__sturm_bound = B
1622
return B
1623
1624
def is_hecke_stable(self):
1625
"""
1626
Return True if self is stable under the Hecke operators of its
1627
ambient Jacobian.
1628
1629
OUTPUT: bool
1630
1631
EXAMPLES::
1632
1633
sage: J0(11).is_hecke_stable()
1634
True
1635
sage: J0(33)[2].is_hecke_stable()
1636
True
1637
sage: J0(33)[0].is_hecke_stable()
1638
False
1639
sage: (J0(33)[0] + J0(33)[1]).is_hecke_stable()
1640
True
1641
"""
1642
try:
1643
return self._is_hecke_stable
1644
except AttributeError:
1645
pass
1646
1647
#b = self.modular_symbols().sturm_bound()
1648
b = max([ m.sturm_bound() for m in self._ambient_modular_symbols_spaces() ])
1649
J = self.ambient_variety()
1650
L = self.lattice()
1651
B = self.lattice().basis()
1652
1653
for n in prime_range(1,b+1):
1654
Tn_matrix = J.hecke_operator(n).matrix()
1655
for v in B:
1656
if not (v*Tn_matrix in L):
1657
self._is_hecke_stable = False
1658
return False
1659
1660
self._is_hecke_stable = True
1661
return True
1662
1663
def is_subvariety(self, other):
1664
"""
1665
Return True if self is a subvariety of other as they sit in a
1666
common ambient modular Jacobian. In particular, this function will
1667
only return True if self and other have exactly the same ambient
1668
Jacobians.
1669
1670
EXAMPLES::
1671
1672
sage: J = J0(37); J
1673
Abelian variety J0(37) of dimension 2
1674
sage: A = J[0]; A
1675
Simple abelian subvariety 37a(1,37) of dimension 1 of J0(37)
1676
sage: A.is_subvariety(A)
1677
True
1678
sage: A.is_subvariety(J)
1679
True
1680
"""
1681
if not is_ModularAbelianVariety(other):
1682
return False
1683
if self is other:
1684
return True
1685
if self.groups() != other.groups():
1686
return False
1687
L = self.lattice()
1688
M = other.lattice()
1689
# self is an abelian subvariety of other if and only if
1690
# 1. L is a subset of M (so the abelian subvarieties of
1691
# the ambient J are equal), and
1692
# 2. L is relatively saturated in M, i.e., M/L is
1693
# torsion free.
1694
if not L.is_submodule(M):
1695
return False
1696
# To determine if L is relatively saturated we compute the
1697
# intersection of M with (L tensor Q) and see if that equals
1698
# L.
1699
return L.change_ring(QQ).intersection(M) == L
1700
1701
def change_ring(self, R):
1702
"""
1703
Change the base ring of this modular abelian variety.
1704
1705
EXAMPLES::
1706
1707
sage: A = J0(23)
1708
sage: A.change_ring(QQ)
1709
Abelian variety J0(23) of dimension 2
1710
"""
1711
return ModularAbelianVariety(self.groups(), self.lattice(), R, check=False)
1712
1713
def level(self):
1714
"""
1715
Return the level of this modular abelian variety, which is an
1716
integer N (usually minimal) such that this modular abelian variety
1717
is a quotient of `J_1(N)`. In the case that the ambient
1718
variety of self is a product of Jacobians, return the LCM of their
1719
levels.
1720
1721
EXAMPLES::
1722
1723
sage: J1(5077).level()
1724
5077
1725
sage: JH(389,[4]).level()
1726
389
1727
sage: (J0(11)*J0(17)).level()
1728
187
1729
"""
1730
try:
1731
return self.__level
1732
except AttributeError:
1733
self.__level = LCM([G.level() for G in self.groups()])
1734
return self.__level
1735
1736
def newform_level(self, none_if_not_known=False):
1737
"""
1738
Write self as a product (up to isogeny) of newform abelian
1739
varieties `A_f`. Then this function return the least
1740
common multiple of the levels of the newforms `f`, along
1741
with the corresponding group or list of groups (the groups do not
1742
appear with multiplicity).
1743
1744
INPUT:
1745
1746
1747
- ``none_if_not_known`` - (default: False) if True,
1748
return None instead of attempting to compute the newform level, if
1749
it isn't already known. This None result is not cached.
1750
1751
1752
OUTPUT: integer group or list of distinct groups
1753
1754
EXAMPLES::
1755
1756
sage: J0(33)[0].newform_level()
1757
(11, Congruence Subgroup Gamma0(33))
1758
sage: J0(33)[0].newform_level(none_if_not_known=True)
1759
(11, Congruence Subgroup Gamma0(33))
1760
1761
Here there are multiple groups since there are in fact multiple
1762
newforms::
1763
1764
sage: (J0(11) * J1(13)).newform_level()
1765
(143, [Congruence Subgroup Gamma0(11), Congruence Subgroup Gamma1(13)])
1766
"""
1767
try:
1768
return self.__newform_level
1769
except AttributeError:
1770
if none_if_not_known:
1771
return None
1772
N = [A.newform_level() for A in self.decomposition()]
1773
level = LCM([z[0] for z in N])
1774
groups = list(set([z[1] for z in N]))
1775
groups.sort()
1776
if len(groups) == 1:
1777
groups = groups[0]
1778
self.__newform_level = level, groups
1779
return self.__newform_level
1780
1781
def zero_subvariety(self):
1782
"""
1783
Return the zero subvariety of self.
1784
1785
EXAMPLES::
1786
1787
sage: J = J0(37)
1788
sage: J.zero_subvariety()
1789
Simple abelian subvariety of dimension 0 of J0(37)
1790
sage: J.zero_subvariety().level()
1791
37
1792
sage: J.zero_subvariety().newform_level()
1793
(1, [])
1794
"""
1795
try:
1796
return self.__zero_subvariety
1797
except AttributeError:
1798
lattice = (ZZ**(2*self.degree())).zero_submodule()
1799
A = ModularAbelianVariety(self.groups(), lattice, self.base_field(),
1800
is_simple=True, check=False)
1801
self.__zero_subvariety = A
1802
return A
1803
1804
1805
###############################################################################
1806
# Properties of the ambient product of Jacobians
1807
###############################################################################
1808
def _ambient_repr(self):
1809
"""
1810
OUTPUT: string
1811
1812
EXAMPLES::
1813
1814
sage: (J0(33)*J1(11))._ambient_repr()
1815
'J0(33) x J1(11)'
1816
"""
1817
v = []
1818
for G in self.groups():
1819
if is_Gamma0(G):
1820
v.append('J0(%s)'%G.level())
1821
elif is_Gamma1(G):
1822
v.append('J1(%s)'%G.level())
1823
elif is_GammaH(G):
1824
v.append('JH(%s,%s)'%(G.level(), G._generators_for_H()))
1825
return ' x '.join(v)
1826
1827
def _ambient_latex_repr(self):
1828
"""
1829
Return Latex representation of the ambient product.
1830
1831
OUTPUT: string
1832
1833
EXAMPLES::
1834
1835
sage: (J0(11) * J0(33))._ambient_latex_repr()
1836
'J_0(11) \\times J_0(33)'
1837
"""
1838
v = []
1839
for G in self.groups():
1840
if is_Gamma0(G):
1841
v.append('J_0(%s)'%G.level())
1842
elif is_Gamma1(G):
1843
v.append('J_1(%s)'%G.level())
1844
elif is_GammaH(G):
1845
v.append('J_H(%s,%s)'%(G.level(), G._generators_for_H()))
1846
return ' \\times '.join(v)
1847
1848
1849
def _ambient_lattice(self):
1850
"""
1851
Return free lattice of rank twice the degree of self. This is the
1852
lattice corresponding to the ambient product Jacobian.
1853
1854
OUTPUT: lattice
1855
1856
EXAMPLES: We compute the ambient lattice of a product::
1857
1858
sage: (J0(33)*J1(11))._ambient_lattice()
1859
Ambient free module of rank 8 over the principal ideal domain Integer Ring
1860
1861
We compute the ambient lattice of an abelian subvariety
1862
`J_0(33)`, which is the same as the lattice for the
1863
`J_0(33)` itself::
1864
1865
sage: A = J0(33)[0]; A._ambient_lattice()
1866
Ambient free module of rank 6 over the principal ideal domain Integer Ring
1867
sage: J0(33)._ambient_lattice()
1868
Ambient free module of rank 6 over the principal ideal domain Integer Ring
1869
"""
1870
try:
1871
return self.__ambient_lattice
1872
except AttributeError:
1873
self.__ambient_lattice = ZZ**(2*self.degree())
1874
return self.__ambient_lattice
1875
1876
def _ambient_modular_symbols_spaces(self):
1877
"""
1878
Return a tuple of the ambient cuspidal modular symbols spaces that
1879
make up the Jacobian product that contains self.
1880
1881
OUTPUT: tuple of cuspidal modular symbols spaces
1882
1883
EXAMPLES::
1884
1885
sage: (J0(11) * J0(33))._ambient_modular_symbols_spaces()
1886
(Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field,
1887
Modular Symbols subspace of dimension 6 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field)
1888
sage: (J0(11) * J0(33)[0])._ambient_modular_symbols_spaces()
1889
(Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field,
1890
Modular Symbols subspace of dimension 6 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field)
1891
"""
1892
if not self.is_ambient():
1893
return self.ambient_variety()._ambient_modular_symbols_spaces()
1894
try:
1895
return self.__ambient_modular_symbols_spaces
1896
except AttributeError:
1897
X = tuple([ModularSymbols(G).cuspidal_subspace() for G in self.groups()])
1898
self.__ambient_modular_symbols_spaces = X
1899
return X
1900
1901
def _ambient_modular_symbols_abvars(self):
1902
"""
1903
Return a tuple of the ambient modular symbols abelian varieties
1904
that make up the Jacobian product that contains self.
1905
1906
OUTPUT: tuple of modular symbols abelian varieties
1907
1908
EXAMPLES::
1909
1910
sage: (J0(11) * J0(33))._ambient_modular_symbols_abvars()
1911
(Abelian variety J0(11) of dimension 1, Abelian variety J0(33) of dimension 3)
1912
"""
1913
if not self.is_ambient():
1914
return self.ambient_variety()._ambient_modular_symbols_abvars()
1915
try:
1916
return self.__ambient_modular_symbols_abvars
1917
except AttributeError:
1918
X = tuple([ModularAbelianVariety_modsym(M) for M in self._ambient_modular_symbols_spaces()])
1919
self.__ambient_modular_symbols_abvars = X
1920
return X
1921
1922
def _ambient_dimension(self):
1923
"""
1924
Return the dimension of the ambient Jacobian product.
1925
1926
EXAMPLES::
1927
1928
sage: A = J0(37) * J1(13); A
1929
Abelian variety J0(37) x J1(13) of dimension 4
1930
sage: A._ambient_dimension()
1931
4
1932
sage: B = A[0]; B
1933
Simple abelian subvariety 13aG1(1,13) of dimension 2 of J0(37) x J1(13)
1934
sage: B._ambient_dimension()
1935
4
1936
1937
This example is fast because it implicitly calls
1938
_ambient_dimension.
1939
1940
::
1941
1942
sage: J0(902834082394)
1943
Abelian variety J0(902834082394) of dimension 113064825881
1944
"""
1945
try:
1946
return self.__ambient_dimension
1947
except AttributeError:
1948
d = sum([G.dimension_cusp_forms(2) for G in self.groups()], Integer(0))
1949
self.__ambient_dimension = d
1950
return d
1951
1952
def _ambient_hecke_matrix_on_modular_symbols(self, n):
1953
r"""
1954
Return block direct sum of the matrix of the Hecke operator
1955
`T_n` acting on each of the ambient modular symbols
1956
spaces.
1957
1958
INPUT:
1959
1960
1961
- ``n`` - an integer `\geq 1`.
1962
1963
1964
OUTPUT: a matrix
1965
1966
EXAMPLES::
1967
1968
sage: (J0(11) * J1(13))._ambient_hecke_matrix_on_modular_symbols(2)
1969
[-2 0 0 0 0 0]
1970
[ 0 -2 0 0 0 0]
1971
[ 0 0 -2 0 -1 1]
1972
[ 0 0 1 -1 0 -1]
1973
[ 0 0 1 1 -2 0]
1974
[ 0 0 0 1 -1 -1]
1975
"""
1976
if not self.is_ambient():
1977
return self.ambient_variety()._ambient_hecke_matrix_on_modular_symbols(n)
1978
try:
1979
return self.__ambient_hecke_matrix_on_modular_symbols[n]
1980
except AttributeError:
1981
self.__ambient_hecke_matrix_on_modular_symbols = {}
1982
except KeyError:
1983
pass
1984
M = self._ambient_modular_symbols_spaces()
1985
if len(M) == 0:
1986
return matrix(QQ,0)
1987
T = M[0].hecke_matrix(n)
1988
for i in range(1,len(M)):
1989
T = T.block_sum(M[i].hecke_matrix(n))
1990
self.__ambient_hecke_matrix_on_modular_symbols[n] = T
1991
return T
1992
1993
###############################################################################
1994
# Rational and Integral Homology
1995
###############################################################################
1996
def _rational_homology_space(self):
1997
"""
1998
Return the rational homology of this modular abelian variety.
1999
2000
EXAMPLES::
2001
2002
sage: J = J0(11)
2003
sage: J._rational_homology_space()
2004
Vector space of dimension 2 over Rational Field
2005
2006
The result is cached::
2007
2008
sage: J._rational_homology_space() is J._rational_homology_space()
2009
True
2010
"""
2011
try:
2012
return self.__rational_homology_space
2013
except AttributeError:
2014
HQ = self.rational_homology().free_module()
2015
self.__rational_homology_space = HQ
2016
return HQ
2017
2018
def homology(self, base_ring=ZZ):
2019
"""
2020
Return the homology of this modular abelian variety.
2021
2022
.. warning::
2023
2024
For efficiency reasons the basis of the integral homology
2025
need not be the same as the basis for the rational
2026
homology.
2027
2028
EXAMPLES::
2029
2030
sage: J0(389).homology(GF(7))
2031
Homology with coefficients in Finite Field of size 7 of Abelian variety J0(389) of dimension 32
2032
sage: J0(389).homology(QQ)
2033
Rational Homology of Abelian variety J0(389) of dimension 32
2034
sage: J0(389).homology(ZZ)
2035
Integral Homology of Abelian variety J0(389) of dimension 32
2036
"""
2037
try:
2038
return self._homology[base_ring]
2039
except AttributeError:
2040
self._homology = {}
2041
except KeyError:
2042
pass
2043
if base_ring == ZZ:
2044
H = homology.IntegralHomology(self)
2045
elif base_ring == QQ:
2046
H = homology.RationalHomology(self)
2047
else:
2048
H = homology.Homology_over_base(self, base_ring)
2049
self._homology[base_ring] = H
2050
return H
2051
2052
def integral_homology(self):
2053
"""
2054
Return the integral homology of this modular abelian variety.
2055
2056
EXAMPLES::
2057
2058
sage: H = J0(43).integral_homology(); H
2059
Integral Homology of Abelian variety J0(43) of dimension 3
2060
sage: H.rank()
2061
6
2062
sage: H = J1(17).integral_homology(); H
2063
Integral Homology of Abelian variety J1(17) of dimension 5
2064
sage: H.rank()
2065
10
2066
2067
If you just ask for the rank of the homology, no serious
2068
calculations are done, so the following is fast::
2069
2070
sage: H = J0(50000).integral_homology(); H
2071
Integral Homology of Abelian variety J0(50000) of dimension 7351
2072
sage: H.rank()
2073
14702
2074
2075
A product::
2076
2077
sage: H = (J0(11) * J1(13)).integral_homology()
2078
sage: H.hecke_operator(2)
2079
Hecke operator T_2 on Integral Homology of Abelian variety J0(11) x J1(13) of dimension 3
2080
sage: H.hecke_operator(2).matrix()
2081
[-2 0 0 0 0 0]
2082
[ 0 -2 0 0 0 0]
2083
[ 0 0 -2 0 -1 1]
2084
[ 0 0 1 -1 0 -1]
2085
[ 0 0 1 1 -2 0]
2086
[ 0 0 0 1 -1 -1]
2087
"""
2088
return self.homology(ZZ)
2089
2090
def rational_homology(self):
2091
"""
2092
Return the rational homology of this modular abelian variety.
2093
2094
EXAMPLES::
2095
2096
sage: H = J0(37).rational_homology(); H
2097
Rational Homology of Abelian variety J0(37) of dimension 2
2098
sage: H.rank()
2099
4
2100
sage: H.base_ring()
2101
Rational Field
2102
sage: H = J1(17).rational_homology(); H
2103
Rational Homology of Abelian variety J1(17) of dimension 5
2104
sage: H.rank()
2105
10
2106
sage: H.base_ring()
2107
Rational Field
2108
"""
2109
return self.homology(QQ)
2110
2111
###############################################################################
2112
# L-series
2113
###############################################################################
2114
def lseries(self):
2115
"""
2116
Return the complex `L`-series of this modular abelian
2117
variety.
2118
2119
EXAMPLES::
2120
2121
sage: A = J0(37)
2122
sage: A.lseries()
2123
Complex L-series attached to Abelian variety J0(37) of dimension 2
2124
"""
2125
try:
2126
return self.__lseries
2127
except AttributeError:
2128
pass
2129
self.__lseries = lseries.Lseries_complex(self)
2130
return self.__lseries
2131
2132
def padic_lseries(self, p):
2133
"""
2134
Return the `p`-adic `L`-series of this modular
2135
abelian variety.
2136
2137
EXAMPLES::
2138
2139
sage: A = J0(37)
2140
sage: A.padic_lseries(7)
2141
7-adic L-series attached to Abelian variety J0(37) of dimension 2
2142
"""
2143
p = int(p)
2144
try:
2145
return self.__lseries_padic[p]
2146
except AttributeError:
2147
self.__lseries_padic = {}
2148
except KeyError:
2149
pass
2150
self.__lseries_padic[p] = lseries.Lseries_padic(self, p)
2151
return self.__lseries_padic[p]
2152
2153
###############################################################################
2154
# Hecke Operators
2155
###############################################################################
2156
def hecke_operator(self, n):
2157
"""
2158
Return the `n^{th}` Hecke operator on the modular abelian
2159
variety, if this makes sense [[elaborate]]. Otherwise raise a
2160
ValueError.
2161
2162
EXAMPLES: We compute `T_2` on `J_0(37)`.
2163
2164
::
2165
2166
sage: t2 = J0(37).hecke_operator(2); t2
2167
Hecke operator T_2 on Abelian variety J0(37) of dimension 2
2168
sage: t2.charpoly().factor()
2169
x * (x + 2)
2170
sage: t2.index()
2171
2
2172
2173
Note that there is no matrix associated to Hecke operators on
2174
modular abelian varieties. For a matrix, instead consider, e.g.,
2175
the Hecke operator on integral or rational homology.
2176
2177
::
2178
2179
sage: t2.action_on_homology().matrix()
2180
[-1 1 1 -1]
2181
[ 1 -1 1 0]
2182
[ 0 0 -2 1]
2183
[ 0 0 0 0]
2184
"""
2185
try:
2186
return self._hecke_operator[n]
2187
except AttributeError:
2188
self._hecke_operator = {}
2189
except KeyError:
2190
pass
2191
Tn = HeckeOperator(self, n)
2192
self._hecke_operator[n] = Tn
2193
return Tn
2194
2195
def hecke_polynomial(self, n, var='x'):
2196
r"""
2197
Return the characteristic polynomial of the `n^{th}` Hecke
2198
operator `T_n` acting on self. Raises an ArithmeticError
2199
if self is not Hecke equivariant.
2200
2201
INPUT:
2202
2203
2204
- ``n`` - integer `\geq 1`
2205
2206
- ``var`` - string (default: 'x'); valid variable
2207
name
2208
2209
2210
EXAMPLES::
2211
2212
sage: J0(33).hecke_polynomial(2)
2213
x^3 + 3*x^2 - 4
2214
sage: f = J0(33).hecke_polynomial(2, 'y'); f
2215
y^3 + 3*y^2 - 4
2216
sage: f.parent()
2217
Univariate Polynomial Ring in y over Rational Field
2218
sage: J0(33)[2].hecke_polynomial(3)
2219
x + 1
2220
sage: J0(33)[0].hecke_polynomial(5)
2221
x - 1
2222
sage: J0(33)[0].hecke_polynomial(11)
2223
x - 1
2224
sage: J0(33)[0].hecke_polynomial(3)
2225
Traceback (most recent call last):
2226
...
2227
ArithmeticError: subspace is not invariant under matrix
2228
"""
2229
n = Integer(n)
2230
if n <= 0:
2231
raise ValueError, "n must be a positive integer"
2232
key = (n,var)
2233
try:
2234
return self.__hecke_polynomial[key]
2235
except AttributeError:
2236
self.__hecke_polynomial = {}
2237
except KeyError:
2238
pass
2239
f = self._compute_hecke_polynomial(n, var=var)
2240
self.__hecke_polynomial[key] = f
2241
return f
2242
2243
def _compute_hecke_polynomial(self, n, var='x'):
2244
"""
2245
Return the Hecke polynomial of index `n` in terms of the
2246
given variable.
2247
2248
INPUT:
2249
2250
2251
- ``n`` - positive integer
2252
2253
- ``var`` - string (default: 'x')
2254
2255
2256
EXAMPLES::
2257
2258
sage: A = J0(33)*J0(11)
2259
sage: A._compute_hecke_polynomial(2)
2260
x^4 + 5*x^3 + 6*x^2 - 4*x - 8
2261
"""
2262
return self.hecke_operator(n).charpoly(var=var)
2263
2264
def _integral_hecke_matrix(self, n):
2265
"""
2266
Return the matrix of the Hecke operator `T_n` acting on
2267
the integral homology of this modular abelian variety, if the
2268
modular abelian variety is stable under `T_n`. Otherwise,
2269
raise an ArithmeticError.
2270
2271
EXAMPLES::
2272
2273
sage: A = J0(23)
2274
sage: t = A._integral_hecke_matrix(2); t
2275
[ 0 1 -1 0]
2276
[ 0 1 -1 1]
2277
[-1 2 -2 1]
2278
[-1 1 0 -1]
2279
sage: t.parent()
2280
Full MatrixSpace of 4 by 4 dense matrices over Integer Ring
2281
"""
2282
A = self._ambient_hecke_matrix_on_modular_symbols(n)
2283
return A.restrict(self.lattice())
2284
2285
def _rational_hecke_matrix(self, n):
2286
r"""
2287
Return the matrix of the Hecke operator `T_n` acting on
2288
the rational homology `H_1(A,\QQ)` of this modular
2289
abelian variety, if this action is defined. Otherwise, raise an
2290
ArithmeticError.
2291
2292
EXAMPLES::
2293
2294
sage: A = J0(23)
2295
sage: t = A._rational_hecke_matrix(2); t
2296
[ 0 1 -1 0]
2297
[ 0 1 -1 1]
2298
[-1 2 -2 1]
2299
[-1 1 0 -1]
2300
sage: t.parent()
2301
Full MatrixSpace of 4 by 4 dense matrices over Rational Field
2302
"""
2303
return self._integral_hecke_matrix(n)
2304
2305
###############################################################################
2306
# Subgroups
2307
###############################################################################
2308
def qbar_torsion_subgroup(self):
2309
r"""
2310
Return the group of all points of finite order in the algebraic
2311
closure of this abelian variety.
2312
2313
EXAMPLES::
2314
2315
sage: T = J0(33).qbar_torsion_subgroup(); T
2316
Group of all torsion points in QQbar on Abelian variety J0(33) of dimension 3
2317
2318
The field of definition is the same as the base field of the
2319
abelian variety.
2320
2321
::
2322
2323
sage: T.field_of_definition()
2324
Rational Field
2325
2326
On the other hand, T is a module over `\ZZ`.
2327
2328
::
2329
2330
sage: T.base_ring()
2331
Integer Ring
2332
"""
2333
try:
2334
return self.__qbar_torsion_subgroup
2335
except AttributeError:
2336
G = QQbarTorsionSubgroup(self)
2337
self.__qbar_torsion_subgroup = G
2338
return G
2339
2340
def rational_torsion_subgroup(self):
2341
"""
2342
Return the maximal torsion subgroup of self defined over QQ.
2343
2344
EXAMPLES::
2345
2346
sage: J = J0(33)
2347
sage: A = J.new_subvariety()
2348
sage: A
2349
Abelian subvariety of dimension 1 of J0(33)
2350
sage: t = A.rational_torsion_subgroup()
2351
sage: t.multiple_of_order()
2352
4
2353
sage: t.divisor_of_order()
2354
4
2355
sage: t.order()
2356
4
2357
sage: t.gens()
2358
[[(1/2, 0, 0, -1/2, 0, 0)], [(0, 0, 1/2, 0, 1/2, -1/2)]]
2359
sage: t
2360
Torsion subgroup of Abelian subvariety of dimension 1 of J0(33)
2361
"""
2362
try:
2363
return self.__rational_torsion_subgroup
2364
except AttributeError:
2365
T = RationalTorsionSubgroup(self)
2366
self.__rational_torsion_subgroup = T
2367
return T
2368
2369
def cuspidal_subgroup(self):
2370
"""
2371
Return the cuspidal subgroup of this modular abelian variety. This
2372
is the subgroup generated by rational cusps.
2373
2374
EXAMPLES::
2375
2376
sage: J = J0(54)
2377
sage: C = J.cuspidal_subgroup()
2378
sage: C.gens()
2379
[[(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)]]
2380
sage: C.invariants()
2381
[3, 3, 3, 3, 3, 9]
2382
sage: J1(13).cuspidal_subgroup()
2383
Finite subgroup with invariants [19, 19] over QQ of Abelian variety J1(13) of dimension 2
2384
sage: A = J0(33)[0]
2385
sage: A.cuspidal_subgroup()
2386
Finite subgroup with invariants [5] over QQ of Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
2387
"""
2388
try:
2389
return self._cuspidal_subgroup
2390
except AttributeError:
2391
if not self.is_subvariety_of_ambient_jacobian():
2392
raise ValueError, "self must be a subvariety of the ambient variety"
2393
if self.is_ambient():
2394
T = self._ambient_cuspidal_subgroup(rational_only=False)
2395
else:
2396
T = self.ambient_variety().cuspidal_subgroup().intersection(self)
2397
self._cuspidal_subgroup = T
2398
return T
2399
2400
def _ambient_cuspidal_subgroup(self, rational_only=False, rational_subgroup=False):
2401
"""
2402
EXAMPLES::
2403
2404
sage: (J1(13)*J0(11))._ambient_cuspidal_subgroup()
2405
Finite subgroup with invariants [19, 95] over QQ of Abelian variety J1(13) x J0(11) of dimension 3
2406
sage: (J0(33))._ambient_cuspidal_subgroup()
2407
Finite subgroup with invariants [10, 10] over QQ of Abelian variety J0(33) of dimension 3
2408
sage: (J0(33)*J0(33))._ambient_cuspidal_subgroup()
2409
Finite subgroup with invariants [10, 10, 10, 10] over QQ of Abelian variety J0(33) x J0(33) of dimension 6
2410
"""
2411
n = 2 * self.degree()
2412
i = 0
2413
lattice = (ZZ**n).zero_submodule()
2414
if rational_subgroup:
2415
CS = RationalCuspidalSubgroup
2416
elif rational_only:
2417
CS = RationalCuspSubgroup
2418
else:
2419
CS = CuspidalSubgroup
2420
for J in self._ambient_modular_symbols_abvars():
2421
L = CS(J).lattice().basis_matrix()
2422
Z_left = matrix(QQ,L.nrows(),i)
2423
Z_right = matrix(QQ,L.nrows(),n-i-L.ncols())
2424
lattice += (Z_left.augment(L).augment(Z_right)).row_module(ZZ)
2425
i += L.ncols()
2426
return FiniteSubgroup_lattice(self, lattice, field_of_definition=self.base_field())
2427
2428
def shimura_subgroup(self):
2429
r"""
2430
Return the Shimura subgroup of this modular abelian variety. This is
2431
the kernel of $J_0(N) \rightarrow J_1(N)$ under the natural map.
2432
Here we compute the Shimura subgroup as the kernel of
2433
$J_0(N) \rightarrow J_0(Np)$ where the map is the difference between the
2434
two degeneracy maps.
2435
2436
EXAMPLES::
2437
2438
sage: J=J0(11)
2439
sage: J.shimura_subgroup()
2440
Finite subgroup with invariants [5] over QQ of Abelian variety J0(11) of dimension 1
2441
2442
sage: J=J0(17)
2443
sage: G=J.cuspidal_subgroup(); G
2444
Finite subgroup with invariants [4] over QQ of Abelian variety J0(17) of dimension 1
2445
sage: S=J.shimura_subgroup(); S
2446
Finite subgroup with invariants [4] over QQ of Abelian variety J0(17) of dimension 1
2447
sage: G.intersection(S)
2448
Finite subgroup with invariants [2] over QQ of Abelian variety J0(17) of dimension 1
2449
2450
sage: J=J0(33)
2451
sage: A=J.decomposition()[0]
2452
sage: A.shimura_subgroup()
2453
Finite subgroup with invariants [5] over QQ of Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
2454
sage: J.shimura_subgroup()
2455
Finite subgroup with invariants [10] over QQ of Abelian variety J0(33) of dimension 3
2456
"""
2457
N=self.level()
2458
J=self.ambient_variety()
2459
for p in prime_range(100):
2460
if N%p!=0:
2461
break
2462
phi=J.degeneracy_map(N*p,1)
2463
phip=J.degeneracy_map(N*p,p)
2464
SIG = (phi-phip).kernel()
2465
assert SIG[1].dimension()==0, "The intersection should have dimension 0"
2466
2467
return self.intersection(SIG[0])
2468
2469
def rational_cusp_subgroup(self):
2470
r"""
2471
Return the subgroup of this modular abelian variety generated by
2472
rational cusps.
2473
2474
This is a subgroup of the group of rational points in the cuspidal
2475
subgroup.
2476
2477
.. warning::
2478
2479
This is only currently implemented for
2480
`\Gamma_0(N)`.
2481
2482
EXAMPLES::
2483
2484
sage: J = J0(54)
2485
sage: CQ = J.rational_cusp_subgroup(); CQ
2486
Finite subgroup with invariants [3, 3, 9] over QQ of Abelian variety J0(54) of dimension 4
2487
sage: CQ.gens()
2488
[[(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)]]
2489
sage: factor(CQ.order())
2490
3^4
2491
sage: CQ.invariants()
2492
[3, 3, 9]
2493
2494
In this example the rational cuspidal subgroup and the cuspidal
2495
subgroup differ by a lot.
2496
2497
::
2498
2499
sage: J = J0(49)
2500
sage: J.cuspidal_subgroup()
2501
Finite subgroup with invariants [2, 14] over QQ of Abelian variety J0(49) of dimension 1
2502
sage: J.rational_cusp_subgroup()
2503
Finite subgroup with invariants [2] over QQ of Abelian variety J0(49) of dimension 1
2504
2505
Note that computation of the rational cusp subgroup isn't
2506
implemented for `\Gamma_1`.
2507
2508
::
2509
2510
sage: J = J1(13)
2511
sage: J.cuspidal_subgroup()
2512
Finite subgroup with invariants [19, 19] over QQ of Abelian variety J1(13) of dimension 2
2513
sage: J.rational_cusp_subgroup()
2514
Traceback (most recent call last):
2515
...
2516
NotImplementedError: computation of rational cusps only implemented in Gamma0 case.
2517
"""
2518
try:
2519
return self._rational_cusp_subgroup
2520
except AttributeError:
2521
if not self.is_subvariety_of_ambient_jacobian():
2522
raise ValueError, "self must be a subvariety of the ambient variety"
2523
if self.is_ambient():
2524
T = self._ambient_cuspidal_subgroup(rational_only=True)
2525
else:
2526
T = self.ambient_variety().rational_cusp_subgroup().intersection(self)
2527
self._rational_cusp_subgroup = T
2528
return T
2529
2530
def rational_cuspidal_subgroup(self):
2531
r"""
2532
Return the rational subgroup of the cuspidal subgroup of this
2533
modular abelian variety.
2534
2535
This is a subgroup of the group of rational points in the
2536
cuspidal subgroup.
2537
2538
.. warning::
2539
2540
This is only currently implemented for
2541
`\Gamma_0(N)`.
2542
2543
EXAMPLES::
2544
2545
sage: J = J0(54)
2546
sage: CQ = J.rational_cuspidal_subgroup(); CQ
2547
Finite subgroup with invariants [3, 3, 9] over QQ of Abelian variety J0(54) of dimension 4
2548
sage: CQ.gens()
2549
[[(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)]]
2550
sage: factor(CQ.order())
2551
3^4
2552
sage: CQ.invariants()
2553
[3, 3, 9]
2554
2555
In this example the rational cuspidal subgroup and the cuspidal
2556
subgroup differ by a lot.
2557
2558
::
2559
2560
sage: J = J0(49)
2561
sage: J.cuspidal_subgroup()
2562
Finite subgroup with invariants [2, 14] over QQ of Abelian variety J0(49) of dimension 1
2563
sage: J.rational_cuspidal_subgroup()
2564
Finite subgroup with invariants [2] over QQ of Abelian variety J0(49) of dimension 1
2565
2566
Note that computation of the rational cusp subgroup isn't
2567
implemented for `\Gamma_1`.
2568
2569
::
2570
2571
sage: J = J1(13)
2572
sage: J.cuspidal_subgroup()
2573
Finite subgroup with invariants [19, 19] over QQ of Abelian variety J1(13) of dimension 2
2574
sage: J.rational_cuspidal_subgroup()
2575
Traceback (most recent call last):
2576
...
2577
NotImplementedError: only implemented when group is Gamma0
2578
"""
2579
try:
2580
return self._rational_cuspidal_subgroup
2581
except AttributeError:
2582
if not self.is_subvariety_of_ambient_jacobian():
2583
raise ValueError, "self must be a subvariety of the ambient variety"
2584
if self.is_ambient():
2585
T = self._ambient_cuspidal_subgroup(rational_subgroup=True)
2586
else:
2587
T = self.ambient_variety().rational_cuspidal_subgroup().intersection(self)
2588
self._rational_cuspidal_subgroup = T
2589
return T
2590
2591
def zero_subgroup(self):
2592
"""
2593
Return the zero subgroup of this modular abelian variety, as a
2594
finite group.
2595
2596
EXAMPLES::
2597
2598
sage: A =J0(54); G = A.zero_subgroup(); G
2599
Finite subgroup with invariants [] over QQ of Abelian variety J0(54) of dimension 4
2600
sage: G.is_subgroup(A)
2601
True
2602
"""
2603
try:
2604
return self.__zero_subgroup
2605
except AttributeError:
2606
G = FiniteSubgroup_lattice(self, self.lattice(), field_of_definition=QQ)
2607
self.__zero_subgroup = G
2608
return G
2609
2610
def finite_subgroup(self, X, field_of_definition=None, check=True):
2611
"""
2612
Return a finite subgroup of this modular abelian variety.
2613
2614
INPUT:
2615
2616
2617
- ``X`` - list of elements of other finite subgroups
2618
of this modular abelian variety or elements that coerce into the
2619
rational homology (viewed as a rational vector space); also X could
2620
be a finite subgroup itself that is contained in this abelian
2621
variety.
2622
2623
- ``field_of_definition`` - (default: None) field
2624
over which this group is defined. If None try to figure out the
2625
best base field.
2626
2627
2628
OUTPUT: a finite subgroup of a modular abelian variety
2629
2630
EXAMPLES::
2631
2632
sage: J = J0(11)
2633
sage: J.finite_subgroup([[1/5,0], [0,1/3]])
2634
Finite subgroup with invariants [15] over QQbar of Abelian variety J0(11) of dimension 1
2635
2636
::
2637
2638
sage: J = J0(33); C = J[0].cuspidal_subgroup(); C
2639
Finite subgroup with invariants [5] over QQ of Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
2640
sage: J.finite_subgroup([[0,0,0,0,0,1/6]])
2641
Finite subgroup with invariants [6] over QQbar of Abelian variety J0(33) of dimension 3
2642
sage: J.finite_subgroup(C)
2643
Finite subgroup with invariants [5] over QQ of Abelian variety J0(33) of dimension 3
2644
"""
2645
if isinstance(X, (list, tuple)):
2646
X = self._ambient_lattice().span(X)
2647
elif isinstance(X, FiniteSubgroup):
2648
if field_of_definition is None:
2649
field_of_definition = X.field_of_definition()
2650
A = X.abelian_variety()
2651
if A.groups() != self.groups():
2652
raise ValueError, "ambient product Jacobians must be equal"
2653
if A == self:
2654
X = X.lattice()
2655
else:
2656
if X.is_subgroup(self):
2657
X = (X.lattice() + self.lattice()).intersection(self.vector_space())
2658
else:
2659
raise ValueError, "X must be a subgroup of self."
2660
2661
2662
if field_of_definition is None:
2663
field_of_definition = QQbar
2664
else:
2665
field_of_definition = field_of_definition
2666
2667
return FiniteSubgroup_lattice(self, X, field_of_definition=field_of_definition, check=check)
2668
2669
2670
def torsion_subgroup(self, n):
2671
"""
2672
If n is an integer, return the subgroup of points of order n.
2673
Return the `n`-torsion subgroup of elements of order
2674
dividing `n` of this modular abelian variety `A`,
2675
i.e., the group `A[n]`.
2676
2677
EXAMPLES::
2678
2679
sage: J1(13).torsion_subgroup(19)
2680
Finite subgroup with invariants [19, 19, 19, 19] over QQ of Abelian variety J1(13) of dimension 2
2681
2682
::
2683
2684
sage: A = J0(23)
2685
sage: G = A.torsion_subgroup(5); G
2686
Finite subgroup with invariants [5, 5, 5, 5] over QQ of Abelian variety J0(23) of dimension 2
2687
sage: G.order()
2688
625
2689
sage: G.gens()
2690
[[(1/5, 0, 0, 0)], [(0, 1/5, 0, 0)], [(0, 0, 1/5, 0)], [(0, 0, 0, 1/5)]]
2691
sage: A = J0(23)
2692
sage: A.torsion_subgroup(2).order()
2693
16
2694
"""
2695
try:
2696
return self.__torsion_subgroup[n]
2697
except KeyError:
2698
pass
2699
except AttributeError:
2700
self.__torsion_subgroup = {}
2701
lattice = self.lattice().scale(1/Integer(n))
2702
H = FiniteSubgroup_lattice(self, lattice, field_of_definition=self.base_field())
2703
self.__torsion_subgroup[n] = H
2704
return H
2705
2706
2707
###############################################################################
2708
# Decomposition
2709
###############################################################################
2710
def degen_t(self, none_if_not_known=False):
2711
"""
2712
If this abelian variety is obtained via decomposition then it gets
2713
labeled with the newform label along with some information about
2714
degeneracy maps. In particular, the label ends in a pair
2715
`(t,N)`, where `N` is the ambient level and
2716
`t` is an integer that divides the quotient of `N`
2717
by the newform level. This function returns the tuple
2718
`(t,N)`, or raises a ValueError if self isn't simple.
2719
2720
.. note::
2721
2722
It need not be the case that self is literally equal to the
2723
image of the newform abelian variety under the `t^{th}`
2724
degeneracy map. See the documentation for the label method
2725
for more details.
2726
2727
INPUT:
2728
2729
2730
- ``none_if_not_known`` - (default: False) - if
2731
True, return None instead of attempting to compute the degen map's
2732
`t`, if it isn't known. This None result is not cached.
2733
2734
2735
OUTPUT: a pair (integer, integer)
2736
2737
EXAMPLES::
2738
2739
sage: D = J0(33).decomposition(); D
2740
[
2741
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33),
2742
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33),
2743
Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33)
2744
]
2745
sage: D[0].degen_t()
2746
(1, 33)
2747
sage: D[1].degen_t()
2748
(3, 33)
2749
sage: D[2].degen_t()
2750
(1, 33)
2751
sage: J0(33).degen_t()
2752
Traceback (most recent call last):
2753
...
2754
ValueError: self must be simple
2755
"""
2756
try:
2757
return self.__degen_t
2758
except AttributeError:
2759
if none_if_not_known:
2760
return None
2761
elif self.dimension() > 0 and self.is_simple():
2762
self.__degen_t = self.decomposition()[0].degen_t()
2763
return self.__degen_t
2764
raise ValueError, "self must be simple"
2765
2766
def isogeny_number(self, none_if_not_known=False):
2767
"""
2768
Return the number (starting at 0) of the isogeny class of new
2769
simple abelian varieties that self is in. If self is not simple,
2770
raises a ValueError exception.
2771
2772
INPUT:
2773
2774
2775
- ``none_if_not_known`` - bool (default: False); if
2776
True then this function may return None instead of True of False if
2777
we don't already know the isogeny number of self.
2778
2779
2780
EXAMPLES: We test the none_if_not_known flag first::
2781
2782
sage: J0(33).isogeny_number(none_if_not_known=True) is None
2783
True
2784
2785
Of course, `J_0(33)` is not simple, so this function
2786
raises a ValueError::
2787
2788
sage: J0(33).isogeny_number()
2789
Traceback (most recent call last):
2790
...
2791
ValueError: self must be simple
2792
2793
Each simple factor has isogeny number 1, since that's the number at
2794
which the factor is new.
2795
2796
::
2797
2798
sage: J0(33)[1].isogeny_number()
2799
0
2800
sage: J0(33)[2].isogeny_number()
2801
0
2802
2803
Next consider `J_0(37)` where there are two distinct
2804
newform factors::
2805
2806
sage: J0(37)[1].isogeny_number()
2807
1
2808
"""
2809
try:
2810
return self.__isogeny_number
2811
except AttributeError:
2812
if none_if_not_known:
2813
return None
2814
elif self.is_simple():
2815
self.__isogeny_number = self.decomposition()[0].isogeny_number()
2816
return self.__isogeny_number
2817
else:
2818
raise ValueError, "self must be simple"
2819
2820
2821
def is_simple(self, none_if_not_known=False):
2822
"""
2823
Return whether or not this modular abelian variety is simple, i.e.,
2824
has no proper nonzero abelian subvarieties.
2825
2826
INPUT:
2827
2828
2829
- ``none_if_not_known`` - bool (default: False); if
2830
True then this function may return None instead of True of False if
2831
we don't already know whether or not self is simple.
2832
2833
2834
EXAMPLES::
2835
2836
sage: J0(5).is_simple(none_if_not_known=True) is None # this may fail if J0(5) comes up elsewhere...
2837
True
2838
sage: J0(33).is_simple()
2839
False
2840
sage: J0(33).is_simple(none_if_not_known=True)
2841
False
2842
sage: J0(33)[1].is_simple()
2843
True
2844
sage: J1(17).is_simple()
2845
False
2846
"""
2847
try:
2848
return self.__is_simple
2849
except AttributeError:
2850
if none_if_not_known:
2851
return None
2852
self.__is_simple = len(self.decomposition()) <= 1
2853
return self.__is_simple
2854
2855
def decomposition(self, simple=True, bound=None):
2856
"""
2857
Return a sequence of abelian subvarieties of self that are all
2858
simple, have finite intersection and sum to self.
2859
2860
INPUT: simple- bool (default: True) if True, all factors are
2861
simple. If False, each factor returned is isogenous to a power of a
2862
simple and the simples in each factor are distinct.
2863
2864
2865
- ``bound`` - int (default: None) if given, only use
2866
Hecke operators up to this bound when decomposing. This can give
2867
wrong answers, so use with caution!
2868
2869
2870
EXAMPLES::
2871
2872
sage: m = ModularSymbols(11).cuspidal_submodule()
2873
sage: d1 = m.degeneracy_map(33,1).matrix(); d3=m.degeneracy_map(33,3).matrix()
2874
sage: w = ModularSymbols(33).submodule((d1 + d3).image(), check=False)
2875
sage: A = w.abelian_variety(); A
2876
Abelian subvariety of dimension 1 of J0(33)
2877
sage: D = A.decomposition(); D
2878
[
2879
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33)
2880
]
2881
sage: D[0] == A
2882
True
2883
sage: B = A + J0(33)[0]; B
2884
Abelian subvariety of dimension 2 of J0(33)
2885
sage: dd = B.decomposition(simple=False); dd
2886
[
2887
Abelian subvariety of dimension 2 of J0(33)
2888
]
2889
sage: dd[0] == B
2890
True
2891
sage: dd = B.decomposition(); dd
2892
[
2893
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33),
2894
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33)
2895
]
2896
sage: sum(dd) == B
2897
True
2898
2899
We decompose a product of two Jacobians::
2900
2901
sage: (J0(33) * J0(11)).decomposition()
2902
[
2903
Simple abelian subvariety 11a(1,11) of dimension 1 of J0(33) x J0(11),
2904
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33) x J0(11),
2905
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33) x J0(11),
2906
Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33) x J0(11)
2907
]
2908
"""
2909
try:
2910
return self.__decomposition[(simple, bound)]
2911
except KeyError:
2912
pass
2913
except AttributeError:
2914
self.__decomposition = {}
2915
2916
if self.is_ambient():
2917
# Decompose each piece, then lift
2918
if len(self.groups()) == 0:
2919
D = []
2920
elif len(self.groups()) == 1:
2921
D = ModularAbelianVariety_modsym(ModularSymbols(self.groups()[0], sign=0).cuspidal_submodule()).decomposition(simple=simple, bound=bound)
2922
else:
2923
# Decompose each ambient modular symbols factor.
2924
#X = [ModularAbelianVariety_modsym(ModularSymbols(G,sign=0).cuspidal_submodule()) for G in self.groups()]
2925
from abvar_ambient_jacobian import ModAbVar_ambient_jacobian_class
2926
X = [ModAbVar_ambient_jacobian_class(G) for G in self.groups()]
2927
E = [A.decomposition(simple=simple, bound=bound) for A in X]
2928
i = 0
2929
n = 2*self.dimension()
2930
# Now lift each factor of the decomposition to self.
2931
G = self.groups()
2932
D = []
2933
K = self.base_field()
2934
for C in E:
2935
for B in C:
2936
L = B.lattice().basis_matrix()
2937
if simple:
2938
is_simple = True
2939
else:
2940
is_simple = None
2941
lattice = matrix(QQ,L.nrows(),i).augment(L).augment(matrix(QQ,L.nrows(),n-i-L.ncols())).row_module(ZZ)
2942
D.append(ModularAbelianVariety(G, lattice, K, is_simple=is_simple, newform_level=B.newform_level(),
2943
isogeny_number=B.isogeny_number(none_if_not_known=True),
2944
number=B.degen_t(none_if_not_known=True)))
2945
if len(C) > 0:
2946
i += L.ncols()
2947
elif not simple:
2948
# In this case decompose the ambient space into powers of
2949
# simple abelian varieties (i.e. with
2950
# \code{simple=False)}, and then intersect the lattice
2951
# corresponding to self with each of these factors.
2952
D = []
2953
L = self.lattice()
2954
groups = self.groups()
2955
K = self.base_ring()
2956
for X in self.ambient_variety().decomposition(simple=False):
2957
lattice = L.intersection(X.vector_space())
2958
if lattice.rank() > 0:
2959
the_factor = ModularAbelianVariety(groups, lattice, K, is_simple=X.is_simple(none_if_not_known=True), newform_level=X.newform_level(), isogeny_number=X.isogeny_number(none_if_not_known=True), number=X.degen_t(none_if_not_known=True))
2960
D.append(the_factor)
2961
2962
else:
2963
# See the documentation for self._classify_ambient_factors
2964
# in order to understand what we're doing here.
2965
I_F, I_E, X = self._classify_ambient_factors(simple=simple, bound=bound)
2966
Z_E = [X[i] for i in I_E]
2967
Z_F = [X[i] for i in I_F]
2968
F = sum(Z_F, self.zero_subvariety())
2969
# Now self is isogenous to the sum of the factors in Z.
2970
# We use this isogeny to obtain a product decomposition of
2971
# self.
2972
if F == self:
2973
# The easy case -- it is already such a decomposition
2974
D = Z_F
2975
else:
2976
# The hard case -- now we have to pull back the
2977
# factorization
2978
2979
# Suppose $B$ is an abelian variety and there is a
2980
# finite degree map $B\to J$, where $J$ is an ambient
2981
# Jacobian. Suppose further that we find abelian
2982
# subvarieties $E$ and $F$ of $J$ such that $E + F =
2983
# J$, $E$ and $F$ have finite intersection, the
2984
# composition $B \to J \to J/E$ is an isogeny, and we
2985
# know an explicit decomposition of $F$. Then we can
2986
# compute a decomposition of $B$ as follows. Let
2987
# $L_E$ and $L_F$ be the lattices corresponding to $E$
2988
# and $F$ inside of $L_J$. Compute a matrix $\Phi$
2989
# representing the composition $L_B \to L_J \to L_F
2990
# \otimes \QQ$, where the map $L_J$ to $L_F\otimes
2991
# \QQ$ is projection onto the second factor in the
2992
# decomposition of $L_J$ as $L_E + L_F$ (up to finite
2993
# index). Finally, for each factor $A_i$ of $F$ with
2994
# lattice $L_{A_i}$, compute the saturation $S_i$ of
2995
# $\Phi^{-1}(L_{A_i})$. Then the $S_i$ define a
2996
# decomposition of $B$.
2997
E = sum(Z_E, self.zero_subvariety())
2998
L_B = self.lattice()
2999
L_E = E.lattice()
3000
L_F = F.lattice()
3001
decomp_matrix = L_E.basis_matrix().stack(L_F.basis_matrix())
3002
# Now we compute explicitly the ZZ-linear map (over
3003
# QQ) from L_B that is "projection onto L_F". This
3004
# means write each element of a basis for L_B in terms
3005
# of decomp_matrix, then take the bottom coordinates.
3006
X = decomp_matrix.solve_left(L_B.basis_matrix())
3007
# Now row of X gives each element of L_B as a linear
3008
# combination of the rows of decomp_matrix. We
3009
# project onto L_F by taking the right-most part of
3010
# this matrix.
3011
n = X.ncols()
3012
proj = X.matrix_from_columns(range(n-L_F.rank(), n))
3013
# Now proj is the matrix of projection that goes from
3014
# L_B to L_F, wrt the basis of those spaces.
3015
section = proj**(-1)
3016
3017
# Now section maps L_F to L_B (tensor QQ). Now we
3018
# just take each factor of F, which corresponds to a
3019
# submodule of L_F, and map it over to L_B tensor QQ
3020
# and saturate.
3021
D = []
3022
groups = self.groups()
3023
K = self.base_field()
3024
for A in Z_F:
3025
L_A = A.lattice()
3026
M = L_F.coordinate_module(L_A).basis_matrix() * section
3027
M, _ = M._clear_denom()
3028
M = M.saturation()
3029
M = M * L_B.basis_matrix()
3030
lattice = M.row_module(ZZ)
3031
the_factor = ModularAbelianVariety(groups, lattice, K, is_simple=True, newform_level=A.newform_level(),
3032
isogeny_number=A.isogeny_number(), number=A.degen_t())
3033
D.append(the_factor)
3034
3035
################
3036
3037
if isinstance(D, Sequence_generic):
3038
S = D
3039
else:
3040
D.sort()
3041
S = Sequence(D, immutable=True, cr=True, universe=self.category())
3042
self.__decomposition[(simple, bound)] = S
3043
return S
3044
3045
def _classify_ambient_factors(self, simple=True, bound=None):
3046
r"""
3047
This function implements the following algorithm, which produces
3048
data useful in finding a decomposition or complement of self.
3049
3050
3051
#. Suppose `A_1 + \cdots + A_n` is a simple decomposition
3052
of the ambient space.
3053
3054
#. For each `i`, let
3055
`B_i = A_1 + \cdots + A_i`.
3056
3057
#. For each `i`, compute the intersection `C_i` of
3058
`B_i` and self.
3059
3060
#. For each `i`, if the dimension of `C_i` is
3061
bigger than `C_{i-1}` put `i` in the "in" list;
3062
otherwise put `i` in the "out" list.
3063
3064
3065
Then one can show that self is isogenous to the sum of the
3066
`A_i` with `i` in the "in" list. Moreover, the sum
3067
of the `A_j` with `i` in the "out" list is a
3068
complement of self in the ambient space.
3069
3070
INPUT:
3071
3072
3073
- ``simple`` - bool (default: True)
3074
3075
- ``bound`` - integer (default: None); if given,
3076
passed onto decomposition function
3077
3078
3079
OUTPUT: IN list OUT list simple (or power of simple) factors
3080
3081
EXAMPLES::
3082
3083
sage: d1 = J0(11).degeneracy_map(33, 1); d1
3084
Degeneracy map from Abelian variety J0(11) of dimension 1 to Abelian variety J0(33) of dimension 3 defined by [1]
3085
sage: d2 = J0(11).degeneracy_map(33, 3); d2
3086
Degeneracy map from Abelian variety J0(11) of dimension 1 to Abelian variety J0(33) of dimension 3 defined by [3]
3087
sage: A = (d1 + d2).image(); A
3088
Abelian subvariety of dimension 1 of J0(33)
3089
sage: A._classify_ambient_factors()
3090
([1], [0, 2], [
3091
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33),
3092
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33),
3093
Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33)
3094
])
3095
"""
3096
# Decompose an arbitrary abelian variety
3097
amb = self.ambient_variety()
3098
S = self.vector_space()
3099
X = amb.decomposition(simple=simple, bound=bound)
3100
IN = []; OUT = []
3101
i = 0
3102
V = 0
3103
last_dimension = 0
3104
for j in range(len(X)):
3105
V += X[j].vector_space()
3106
d = S.intersection(V).dimension()
3107
if d > last_dimension:
3108
IN.append(j)
3109
last_dimension = d
3110
else:
3111
OUT.append(j)
3112
return IN, OUT, X
3113
3114
def _isogeny_to_product_of_simples(self):
3115
r"""
3116
Given an abelian variety `A`, return an isogeny
3117
`\phi: A \rightarrow B_1 \times \cdots \times B_n`, where
3118
each `B_i` is simple. Note that this isogeny is not
3119
unique.
3120
3121
EXAMPLES::
3122
3123
sage: J = J0(37) ; J.decomposition()
3124
[
3125
Simple abelian subvariety 37a(1,37) of dimension 1 of J0(37),
3126
Simple abelian subvariety 37b(1,37) of dimension 1 of J0(37)
3127
]
3128
sage: phi = J._isogeny_to_product_of_simples() ; phi
3129
Abelian variety morphism:
3130
From: Abelian variety J0(37) of dimension 2
3131
To: Abelian subvariety of dimension 2 of J0(37) x J0(37)
3132
sage: J[0].intersection(J[1]) == phi.kernel()
3133
True
3134
3135
::
3136
3137
sage: J = J0(22) * J0(37)
3138
sage: J._isogeny_to_product_of_simples()
3139
Abelian variety morphism:
3140
From: Abelian variety J0(22) x J0(37) of dimension 4
3141
To: Abelian subvariety of dimension 4 of J0(11) x J0(11) x J0(37) x J0(37)
3142
"""
3143
try:
3144
return self._simple_product_isogeny
3145
except AttributeError:
3146
pass
3147
3148
D = self.decomposition()
3149
dest = prod([d._isogeny_to_newform_abelian_variety().image() for d in D])
3150
A = self.ambient_variety()
3151
dim = sum([d.dimension() for d in D])
3152
3153
proj_ls = [ A.projection(factor) for factor in D ]
3154
3155
mat = matrix(ZZ, 2*self.dimension(), 2*dim)
3156
ind = 0
3157
3158
for i in range(len(D)):
3159
factor = D[i]
3160
proj = proj_ls[i]
3161
mat.set_block(0, ind, proj.restrict_domain(self).matrix())
3162
ind += 2*factor.dimension()
3163
3164
H = self.Hom(dest)
3165
self._simple_product_isogeny = H(Morphism(H, mat))
3166
return self._simple_product_isogeny
3167
3168
def _isogeny_to_product_of_powers(self):
3169
r"""
3170
Given an abelian variety `A`, return an isogeny
3171
`\phi: A \rightarrow B_1 \times \cdots \times B_n`, where
3172
each `B_i` is a power of a simple abelian variety. These
3173
factors will be exactly those returned by
3174
self.decomposition(simple=False).Note that this isogeny is not
3175
unique.
3176
3177
EXAMPLES::
3178
3179
sage: J = J0(33) ; D = J.decomposition(simple=False) ; len(D)
3180
2
3181
sage: phi = J._isogeny_to_product_of_powers() ; phi
3182
Abelian variety morphism:
3183
From: Abelian variety J0(33) of dimension 3
3184
To: Abelian subvariety of dimension 3 of J0(33) x J0(33)
3185
3186
::
3187
3188
sage: J = J0(22) * J0(37)
3189
sage: J._isogeny_to_product_of_powers()
3190
Abelian variety morphism:
3191
From: Abelian variety J0(22) x J0(37) of dimension 4
3192
To: Abelian subvariety of dimension 4 of J0(22) x J0(37) x J0(22) x J0(37) x J0(22) x J0(37)
3193
"""
3194
try:
3195
return self._simple_power_product_isogeny
3196
except AttributeError:
3197
pass
3198
3199
D = self.decomposition(simple=False)
3200
A = self.ambient_variety()
3201
proj_ls = [ A.projection(factor) for factor in D ]
3202
dest = prod([phi.image() for phi in proj_ls])
3203
dim = sum([d.dimension() for d in D])
3204
3205
mat = matrix(ZZ, 2*self.dimension(), 2*dim)
3206
ind = 0
3207
3208
for i in range(len(D)):
3209
factor = D[i]
3210
proj = proj_ls[i]
3211
mat.set_block(0, ind, proj.restrict_domain(self).matrix())
3212
ind += 2*factor.dimension()
3213
3214
H = self.Hom(dest)
3215
self._simple_power_product_isogeny = H(Morphism(H, mat))
3216
return self._simple_power_product_isogeny
3217
3218
3219
def complement(self, A=None):
3220
"""
3221
Return a complement of this abelian variety.
3222
3223
INPUT:
3224
3225
3226
- ``A`` - (default: None); if given, A must be an
3227
abelian variety that contains self, in which case the complement of
3228
self is taken inside A. Otherwise the complement is taken in the
3229
ambient product Jacobian.
3230
3231
3232
OUTPUT: abelian variety
3233
3234
EXAMPLES::
3235
3236
sage: a,b,c = J0(33)
3237
sage: (a+b).complement()
3238
Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33)
3239
sage: (a+b).complement() == c
3240
True
3241
sage: a.complement(a+b)
3242
Abelian subvariety of dimension 1 of J0(33)
3243
"""
3244
try:
3245
C = self.__complement
3246
except AttributeError:
3247
pass
3248
if self.dimension() is 0:
3249
if A is None:
3250
C = self.ambient_variety()
3251
else:
3252
C = A
3253
elif A is not None and self.dimension() == A.dimension():
3254
if not self.is_subvariety(A):
3255
raise ValueError, "self must be a subvariety of A"
3256
C = self.zero_subvariety()
3257
else:
3258
_, factors, X = self._classify_ambient_factors()
3259
D = [X[i] for i in factors]
3260
C = sum(D)
3261
if C:
3262
self.__complement = C
3263
if A is not None:
3264
C = C.intersection(A)[1]
3265
else:
3266
C = self.zero_subvariety()
3267
return C
3268
3269
def dual(self):
3270
r"""
3271
Return the dual of this abelian variety.
3272
3273
OUTPUT:
3274
- dual abelian variety
3275
- morphism from self to dual
3276
- covering morphism from J to dual
3277
3278
.. warning::
3279
3280
This is currently only implemented when self is an abelian
3281
subvariety of the ambient Jacobian product, and the
3282
complement of self in the ambient product Jacobian share no
3283
common factors. A more general implementation will require
3284
implementing computation of the intersection pairing on
3285
integral homology and the resulting Weil pairing on
3286
torsion.
3287
3288
EXAMPLES: We compute the dual of the elliptic curve newform abelian
3289
variety of level `33`, and find the kernel of the modular
3290
map, which has structure `(\ZZ/3)^2`.
3291
3292
::
3293
3294
sage: A,B,C = J0(33)
3295
sage: C
3296
Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33)
3297
sage: Cd, f, pi = C.dual()
3298
sage: f.matrix()
3299
[3 0]
3300
[0 3]
3301
sage: f.kernel()[0]
3302
Finite subgroup with invariants [3, 3] over QQ of Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33)
3303
3304
By a theorem the modular degree must thus be `3`::
3305
3306
sage: E = EllipticCurve('33a')
3307
sage: E.modular_degree()
3308
3
3309
3310
Next we compute the dual of a `2`-dimensional new simple
3311
abelian subvariety of `J_0(43)`.
3312
3313
::
3314
3315
sage: A = AbelianVariety('43b'); A
3316
Newform abelian subvariety 43b of dimension 2 of J0(43)
3317
sage: Ad, f, pi = A.dual()
3318
3319
The kernel shows that the modular degree is `2`::
3320
3321
sage: f.kernel()[0]
3322
Finite subgroup with invariants [2, 2] over QQ of Newform abelian subvariety 43b of dimension 2 of J0(43)
3323
3324
Unfortunately, the dual is not implemented in general::
3325
3326
sage: A = J0(22)[0]; A
3327
Simple abelian subvariety 11a(1,22) of dimension 1 of J0(22)
3328
sage: A.dual()
3329
Traceback (most recent call last):
3330
...
3331
NotImplementedError: dual not implemented unless complement shares no simple factors with self.
3332
"""
3333
try:
3334
return self.__dual
3335
except AttributeError:
3336
if not self.is_subvariety_of_ambient_jacobian():
3337
raise NotImplementedError, "dual not implemented unless abelian variety is a subvariety of the ambient Jacobian product"
3338
if not self._complement_shares_no_factors_with_same_label():
3339
raise NotImplementedError, "dual not implemented unless complement shares no simple factors with self."
3340
C = self.complement()
3341
Q, phi = self.ambient_variety().quotient(C)
3342
psi = self.ambient_morphism()
3343
self.__dual = Q, phi*psi, phi
3344
return self.__dual
3345
3346
def _factors_with_same_label(self, other):
3347
"""
3348
Given two modular abelian varieties self and other, this function
3349
returns a list of simple abelian subvarieties appearing in the
3350
decomposition of self that have the same newform labels. Each
3351
simple factor with a given newform label appears at most one.
3352
3353
INPUT:
3354
3355
3356
- ``other`` - abelian variety
3357
3358
3359
OUTPUT: list of simple abelian varieties
3360
3361
EXAMPLES::
3362
3363
sage: D = J0(33).decomposition(); D
3364
[
3365
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33),
3366
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33),
3367
Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33)
3368
]
3369
sage: D[0]._factors_with_same_label(D[1])
3370
[Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)]
3371
sage: D[0]._factors_with_same_label(D[2])
3372
[]
3373
sage: (D[0]+D[1])._factors_with_same_label(D[1] + D[2])
3374
[Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)]
3375
3376
This illustrates that the multiplicities in the returned list are
3377
1::
3378
3379
sage: (D[0]+D[1])._factors_with_same_label(J0(33))
3380
[Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)]
3381
3382
This illustrates that the ambient product Jacobians do not have to
3383
be the same::
3384
3385
sage: (D[0]+D[1])._factors_with_same_label(J0(22))
3386
[Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)]
3387
3388
This illustrates that the actual factor labels are relevant, not
3389
just the isogeny class.
3390
3391
::
3392
3393
sage: (D[0]+D[1])._factors_with_same_label(J1(11))
3394
[]
3395
sage: J1(11)[0].newform_label()
3396
'11aG1'
3397
"""
3398
if not isinstance(other, ModularAbelianVariety_abstract):
3399
raise TypeError, "other must be an abelian variety"
3400
D = self.decomposition()
3401
C = set([A.newform_label() for A in other.decomposition()])
3402
Z = []
3403
for X in D:
3404
lbl = X.newform_label()
3405
if lbl in C:
3406
Z.append(X)
3407
C.remove(lbl)
3408
Z.sort()
3409
return Z
3410
3411
def _complement_shares_no_factors_with_same_label(self):
3412
"""
3413
Return True if no simple factor of self has the same newform_label
3414
as any factor in a Poincare complement of self in the ambient
3415
product Jacobian.
3416
3417
EXAMPLES: `J_0(37)` is made up of two non-isogenous
3418
elliptic curves::
3419
3420
sage: J0(37)[0]._complement_shares_no_factors_with_same_label()
3421
True
3422
3423
`J_0(33)` decomposes as a product of two isogenous
3424
elliptic curves with a third nonisogenous curve::
3425
3426
sage: D = J0(33).decomposition(); D
3427
[
3428
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33),
3429
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33),
3430
Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33)
3431
]
3432
sage: D[0]._complement_shares_no_factors_with_same_label()
3433
False
3434
sage: (D[0]+D[1])._complement_shares_no_factors_with_same_label()
3435
True
3436
sage: D[2]._complement_shares_no_factors_with_same_label()
3437
True
3438
3439
This example illustrates the relevance of the ambient product
3440
Jacobian.
3441
3442
::
3443
3444
sage: D = (J0(11) * J0(11)).decomposition(); D
3445
[
3446
Simple abelian subvariety 11a(1,11) of dimension 1 of J0(11) x J0(11),
3447
Simple abelian subvariety 11a(1,11) of dimension 1 of J0(11) x J0(11)
3448
]
3449
sage: D[0]._complement_shares_no_factors_with_same_label()
3450
False
3451
3452
This example illustrates that it is the newform label, not the
3453
isogeny, class that matters::
3454
3455
sage: D = (J0(11)*J1(11)).decomposition(); D
3456
[
3457
Simple abelian subvariety 11aG1(1,11) of dimension 1 of J0(11) x J1(11),
3458
Simple abelian subvariety 11a(1,11) of dimension 1 of J0(11) x J1(11)
3459
]
3460
sage: D[0]._complement_shares_no_factors_with_same_label()
3461
True
3462
sage: D[0].newform_label()
3463
'11aG1'
3464
sage: D[1].newform_label()
3465
'11a'
3466
"""
3467
try:
3468
return self.__complement_shares
3469
except AttributeError:
3470
t = len(self._factors_with_same_label(self.complement())) == 0
3471
self.__complement_shares = t
3472
return t
3473
3474
def __getitem__(self, i):
3475
"""
3476
Returns the `i^{th}` decomposition factor of self
3477
or returns the slice `i` of decompositions of self.
3478
3479
EXAMPLES::
3480
3481
sage: J = J0(389)
3482
sage: J.decomposition()
3483
[
3484
Simple abelian subvariety 389a(1,389) of dimension 1 of J0(389),
3485
Simple abelian subvariety 389b(1,389) of dimension 2 of J0(389),
3486
Simple abelian subvariety 389c(1,389) of dimension 3 of J0(389),
3487
Simple abelian subvariety 389d(1,389) of dimension 6 of J0(389),
3488
Simple abelian subvariety 389e(1,389) of dimension 20 of J0(389)
3489
]
3490
sage: J[2]
3491
Simple abelian subvariety 389c(1,389) of dimension 3 of J0(389)
3492
sage: J[-1]
3493
Simple abelian subvariety 389e(1,389) of dimension 20 of J0(389)
3494
sage: J = J0(125); J.decomposition()
3495
[
3496
Simple abelian subvariety 125a(1,125) of dimension 2 of J0(125),
3497
Simple abelian subvariety 125b(1,125) of dimension 2 of J0(125),
3498
Simple abelian subvariety 125c(1,125) of dimension 4 of J0(125)
3499
]
3500
sage: J[:2]
3501
[
3502
Simple abelian subvariety 125a(1,125) of dimension 2 of J0(125),
3503
Simple abelian subvariety 125b(1,125) of dimension 2 of J0(125)
3504
]
3505
"""
3506
return self.decomposition()[i]
3507
3508
3509
class ModularAbelianVariety(ModularAbelianVariety_abstract):
3510
def __init__(self, groups, lattice=None, base_field=QQ, is_simple=None, newform_level=None,
3511
isogeny_number=None, number=None, check=True):
3512
r"""
3513
Create a modular abelian variety with given level and base field.
3514
3515
INPUT:
3516
3517
3518
- ``groups`` - a tuple of congruence subgroups
3519
3520
- ``lattice`` - (default: `\ZZ^n`) a
3521
full lattice in `\ZZ^n`, where `n` is the
3522
sum of the dimensions of the spaces of cuspidal modular symbols
3523
corresponding to each `\Gamma \in` groups
3524
3525
- ``base_field`` - a field (default:
3526
`\QQ`)
3527
3528
3529
EXAMPLES::
3530
3531
sage: J0(23)
3532
Abelian variety J0(23) of dimension 2
3533
"""
3534
ModularAbelianVariety_abstract.__init__(self, groups, base_field, is_simple=is_simple, newform_level=newform_level,
3535
isogeny_number=isogeny_number, number=number, check=check)
3536
if lattice is None:
3537
lattice = ZZ**(2*self._ambient_dimension())
3538
if check:
3539
n = self._ambient_dimension()
3540
if not is_FreeModule(lattice):
3541
raise TypeError, "lattice must be a free module"
3542
if lattice.base_ring() != ZZ:
3543
raise TypeError, "lattice must be over ZZ"
3544
if lattice.degree() != 2*n:
3545
raise ValueError, "lattice must have degree 2*n (=%s)"%(2*n)
3546
if not lattice.saturation().is_submodule(lattice): # potentially expensive
3547
raise ValueError, "lattice must be full"
3548
self.__lattice = lattice
3549
3550
3551
def lattice(self):
3552
"""
3553
Return the lattice that defines this abelian variety.
3554
3555
OUTPUT:
3556
3557
3558
- ``lattice`` - a lattice embedded in the rational
3559
homology of the ambient product Jacobian
3560
3561
3562
EXAMPLES::
3563
3564
sage: A = (J0(11) * J0(37))[1]; A
3565
Simple abelian subvariety 37a(1,37) of dimension 1 of J0(11) x J0(37)
3566
sage: type(A)
3567
<class 'sage.modular.abvar.abvar.ModularAbelianVariety_with_category'>
3568
sage: A.lattice()
3569
Free module of degree 6 and rank 2 over Integer Ring
3570
Echelon basis matrix:
3571
[ 0 0 1 -1 1 0]
3572
[ 0 0 0 0 2 -1]
3573
"""
3574
return self.__lattice
3575
3576
3577
class ModularAbelianVariety_modsym_abstract(ModularAbelianVariety_abstract):
3578
# Anything that derives from this class must define the
3579
# modular_symbols method, which returns a cuspidal modular symbols
3580
# space over QQ. It can have any sign.
3581
def _modular_symbols(self):
3582
"""
3583
Return the space of modular symbols corresponding to this modular
3584
symbols abelian variety.
3585
3586
EXAMPLES: This function is in the abstract base class, so it raises
3587
a NotImplementedError::
3588
3589
sage: M = ModularSymbols(37).cuspidal_submodule()
3590
sage: A = M.abelian_variety(); A
3591
Abelian variety J0(37) of dimension 2
3592
sage: sage.modular.abvar.abvar.ModularAbelianVariety_modsym_abstract._modular_symbols(A)
3593
Traceback (most recent call last):
3594
...
3595
NotImplementedError: bug -- must define this
3596
3597
Of course this function isn't called in practice, so this works::
3598
3599
sage: A._modular_symbols()
3600
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 5 for Gamma_0(37) of weight 2 with sign 0 over Rational Field
3601
"""
3602
raise NotImplementedError, "bug -- must define this"
3603
3604
def __add__(self, other):
3605
"""
3606
Add two modular abelian variety factors.
3607
3608
EXAMPLES::
3609
3610
sage: A = J0(42); D = A.decomposition(); D
3611
[
3612
Simple abelian subvariety 14a(1,42) of dimension 1 of J0(42),
3613
Simple abelian subvariety 14a(3,42) of dimension 1 of J0(42),
3614
Simple abelian subvariety 21a(1,42) of dimension 1 of J0(42),
3615
Simple abelian subvariety 21a(2,42) of dimension 1 of J0(42),
3616
Simple abelian subvariety 42a(1,42) of dimension 1 of J0(42)
3617
]
3618
sage: D[0] + D[1]
3619
Abelian subvariety of dimension 2 of J0(42)
3620
sage: D[1].is_subvariety(D[0] + D[1])
3621
True
3622
sage: D[0] + D[1] + D[2]
3623
Abelian subvariety of dimension 3 of J0(42)
3624
sage: D[0] + D[0]
3625
Abelian subvariety of dimension 1 of J0(42)
3626
sage: D[0] + D[0] == D[0]
3627
True
3628
sage: sum(D, D[0]) == A
3629
True
3630
"""
3631
if not is_ModularAbelianVariety(other):
3632
if other == 0:
3633
return self
3634
raise TypeError, "sum not defined"
3635
if not isinstance(other, ModularAbelianVariety_modsym_abstract):
3636
return ModularAbelianVariety_abstract.__add__(self, other)
3637
if self.groups() != other.groups():
3638
raise TypeError, "sum not defined since ambient spaces different"
3639
M = self.modular_symbols() + other.modular_symbols()
3640
return ModularAbelianVariety_modsym(M)
3641
3642
def groups(self):
3643
"""
3644
Return the tuple of groups associated to the modular symbols
3645
abelian variety. This is always a 1-tuple.
3646
3647
OUTPUT: tuple
3648
3649
EXAMPLES::
3650
3651
sage: A = ModularSymbols(33).cuspidal_submodule().abelian_variety(); A
3652
Abelian variety J0(33) of dimension 3
3653
sage: A.groups()
3654
(Congruence Subgroup Gamma0(33),)
3655
sage: type(A)
3656
<class 'sage.modular.abvar.abvar.ModularAbelianVariety_modsym_with_category'>
3657
"""
3658
return (self._modular_symbols().group(), )
3659
3660
def lattice(self):
3661
r"""
3662
Return the lattice the defines this modular symbols modular abelian
3663
variety.
3664
3665
OUTPUT: a free `\ZZ`-module embedded in an ambient
3666
`\QQ`-vector space
3667
3668
EXAMPLES::
3669
3670
sage: A = ModularSymbols(33).cuspidal_submodule()[0].abelian_variety(); A
3671
Abelian subvariety of dimension 1 of J0(33)
3672
sage: A.lattice()
3673
Free module of degree 6 and rank 2 over Integer Ring
3674
User basis matrix:
3675
[ 1 0 0 -1 0 0]
3676
[ 0 0 1 0 1 -1]
3677
sage: type(A)
3678
<class 'sage.modular.abvar.abvar.ModularAbelianVariety_modsym_with_category'>
3679
"""
3680
try:
3681
return self.__lattice
3682
except AttributeError:
3683
M = self.modular_symbols()
3684
S = M.ambient_module().cuspidal_submodule()
3685
if M.dimension() == S.dimension():
3686
L = ZZ**M.dimension()
3687
else:
3688
K0 = M.integral_structure()
3689
K1 = S.integral_structure()
3690
L = K1.coordinate_module(K0)
3691
self.__lattice = L
3692
return self.__lattice
3693
3694
def _set_lattice(self, lattice):
3695
"""
3696
Set the lattice of this modular symbols abelian variety.
3697
3698
.. warning::
3699
3700
This is only for internal use. Do not use this unless you
3701
really really know what you're doing. That's why there is
3702
an underscore in this method name.
3703
3704
INPUT:
3705
3706
3707
- ``lattice`` - a lattice
3708
3709
3710
EXAMPLES: We do something evil - there's no type checking since
3711
this function is for internal use only::
3712
3713
sage: A = ModularSymbols(33).cuspidal_submodule().abelian_variety()
3714
sage: A._set_lattice(5)
3715
sage: A.lattice()
3716
5
3717
"""
3718
self.__lattice = lattice
3719
3720
def modular_symbols(self, sign=0):
3721
"""
3722
Return space of modular symbols (with given sign) associated to
3723
this modular abelian variety, if it can be found by cutting down
3724
using Hecke operators. Otherwise raise a RuntimeError exception.
3725
3726
EXAMPLES::
3727
3728
sage: A = J0(37)
3729
sage: A.modular_symbols()
3730
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 5 for Gamma_0(37) of weight 2 with sign 0 over Rational Field
3731
sage: A.modular_symbols(1)
3732
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(37) of weight 2 with sign 1 over Rational Field
3733
3734
More examples::
3735
3736
sage: J0(11).modular_symbols()
3737
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
3738
sage: J0(11).modular_symbols(sign=1)
3739
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
3740
sage: J0(11).modular_symbols(sign=0)
3741
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
3742
sage: J0(11).modular_symbols(sign=-1)
3743
Modular Symbols space of dimension 1 for Gamma_0(11) of weight 2 with sign -1 over Rational Field
3744
3745
Even more examples::
3746
3747
sage: A = J0(33)[1]; A
3748
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33)
3749
sage: A.modular_symbols()
3750
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field
3751
3752
It is not always possible to determine the sign subspaces::
3753
3754
sage: A.modular_symbols(1)
3755
Traceback (most recent call last):
3756
...
3757
RuntimeError: unable to determine sign (=1) space of modular symbols
3758
3759
::
3760
3761
sage: A.modular_symbols(-1)
3762
Traceback (most recent call last):
3763
...
3764
RuntimeError: unable to determine sign (=-1) space of modular symbols
3765
"""
3766
M = self._modular_symbols().modular_symbols_of_sign(sign)
3767
if (sign != 0 and M.dimension() != self.dimension()) or (sign == 0 and M.dimension() != 2*self.dimension()):
3768
raise RuntimeError, "unable to determine sign (=%s) space of modular symbols"%sign
3769
return M
3770
3771
def _compute_hecke_polynomial(self, n, var='x'):
3772
"""
3773
Return the characteristic polynomial of the `n^{th}` Hecke
3774
operator on self.
3775
3776
.. note::
3777
3778
If self has dimension d, then this is a polynomial of
3779
degree d. It is not of degree 2\*d, so it is the square
3780
root of the characteristic polynomial of the Hecke operator
3781
on integral or rational homology (which has degree 2\*d).
3782
3783
EXAMPLES::
3784
3785
sage: J0(11).hecke_polynomial(2)
3786
x + 2
3787
sage: J0(23)._compute_hecke_polynomial(2)
3788
x^2 + x - 1
3789
sage: J1(13).hecke_polynomial(2)
3790
x^2 + 3*x + 3
3791
sage: factor(J0(43).hecke_polynomial(2))
3792
(x + 2) * (x^2 - 2)
3793
3794
The Hecke polynomial is the square root of the characteristic
3795
polynomial::
3796
3797
sage: factor(J0(43).hecke_operator(2).charpoly())
3798
(x + 2) * (x^2 - 2)
3799
"""
3800
return sqrt_poly(self.modular_symbols().hecke_polynomial(n, var))
3801
3802
def _integral_hecke_matrix(self, n, sign=0):
3803
"""
3804
Return the action of the Hecke operator `T_n` on the
3805
integral homology of self.
3806
3807
INPUT:
3808
3809
3810
- ``n`` - a positive integer
3811
3812
- ``sign`` - 0, +1, or -1; if 1 or -1 act on the +1 or
3813
-1 quotient of the integral homology.
3814
3815
3816
EXAMPLES::
3817
3818
sage: J1(13)._integral_hecke_matrix(2) # slightly random choice of basis
3819
[-2 0 -1 1]
3820
[ 1 -1 0 -1]
3821
[ 1 1 -2 0]
3822
[ 0 1 -1 -1]
3823
sage: J1(13)._integral_hecke_matrix(2,sign=1) # slightly random choice of basis
3824
[-1 1]
3825
[-1 -2]
3826
sage: J1(13)._integral_hecke_matrix(2,sign=-1) # slightly random choice of basis
3827
[-2 -1]
3828
[ 1 -1]
3829
"""
3830
return self.modular_symbols(sign).integral_hecke_matrix(n)
3831
3832
def _rational_hecke_matrix(self, n, sign=0):
3833
"""
3834
Return the action of the Hecke operator `T_n` on the
3835
rational homology of self.
3836
3837
INPUT:
3838
3839
3840
- ``n`` - a positive integer
3841
3842
- ``sign`` - 0, +1, or -1; if 1 or -1 act on the +1 or
3843
-1 quotient of the rational homology.
3844
3845
3846
EXAMPLES::
3847
3848
sage: J1(13)._rational_hecke_matrix(2) # slightly random choice of basis
3849
[-2 0 -1 1]
3850
[ 1 -1 0 -1]
3851
[ 1 1 -2 0]
3852
[ 0 1 -1 -1]
3853
sage: J0(43)._rational_hecke_matrix(2,sign=1) # slightly random choice of basis
3854
[-2 0 1]
3855
[-1 -2 2]
3856
[-2 0 2]
3857
"""
3858
return self._integral_hecke_matrix(n, sign=sign).change_ring(QQ)
3859
3860
def group(self):
3861
"""
3862
Return the congruence subgroup associated that this modular abelian
3863
variety is associated to.
3864
3865
EXAMPLES::
3866
3867
sage: J0(13).group()
3868
Congruence Subgroup Gamma0(13)
3869
sage: J1(997).group()
3870
Congruence Subgroup Gamma1(997)
3871
sage: JH(37,[3]).group()
3872
Congruence Subgroup Gamma_H(37) with H generated by [3]
3873
sage: J0(37)[1].groups()
3874
(Congruence Subgroup Gamma0(37),)
3875
"""
3876
return self.modular_symbols().group()
3877
3878
def is_subvariety(self, other):
3879
"""
3880
Return True if self is a subvariety of other.
3881
3882
EXAMPLES::
3883
3884
sage: J = J0(37); J
3885
Abelian variety J0(37) of dimension 2
3886
sage: A = J[0]; A
3887
Simple abelian subvariety 37a(1,37) of dimension 1 of J0(37)
3888
sage: A.is_subvariety(J)
3889
True
3890
sage: A.is_subvariety(J0(11))
3891
False
3892
3893
There may be a way to map `A` into `J_0(74)`, but
3894
`A` is not equipped with any special structure of an
3895
embedding.
3896
3897
::
3898
3899
sage: A.is_subvariety(J0(74))
3900
False
3901
3902
Some ambient examples::
3903
3904
sage: J = J0(37)
3905
sage: J.is_subvariety(J)
3906
True
3907
sage: J.is_subvariety(25)
3908
False
3909
3910
More examples::
3911
3912
sage: A = J0(42); D = A.decomposition(); D
3913
[
3914
Simple abelian subvariety 14a(1,42) of dimension 1 of J0(42),
3915
Simple abelian subvariety 14a(3,42) of dimension 1 of J0(42),
3916
Simple abelian subvariety 21a(1,42) of dimension 1 of J0(42),
3917
Simple abelian subvariety 21a(2,42) of dimension 1 of J0(42),
3918
Simple abelian subvariety 42a(1,42) of dimension 1 of J0(42)
3919
]
3920
sage: D[0].is_subvariety(A)
3921
True
3922
sage: D[1].is_subvariety(D[0] + D[1])
3923
True
3924
sage: D[2].is_subvariety(D[0] + D[1])
3925
False
3926
"""
3927
if not is_ModularAbelianVariety(other):
3928
return False
3929
if not isinstance(other, ModularAbelianVariety_modsym_abstract):
3930
return ModularAbelianVariety_abstract.is_subvariety(self, other)
3931
return self.modular_symbols().is_submodule(other.modular_symbols())
3932
3933
def is_ambient(self):
3934
"""
3935
Return True if this abelian variety attached to a modular symbols
3936
space space is attached to the cuspidal subspace of the ambient
3937
modular symbols space.
3938
3939
OUTPUT: bool
3940
3941
EXAMPLES::
3942
3943
sage: A = ModularSymbols(43).cuspidal_subspace().abelian_variety(); A
3944
Abelian variety J0(43) of dimension 3
3945
sage: A.is_ambient()
3946
True
3947
sage: type(A)
3948
<class 'sage.modular.abvar.abvar.ModularAbelianVariety_modsym_with_category'>
3949
sage: A = ModularSymbols(43).cuspidal_subspace()[1].abelian_variety(); A
3950
Abelian subvariety of dimension 2 of J0(43)
3951
sage: A.is_ambient()
3952
False
3953
"""
3954
return self.degree() == self.dimension()
3955
3956
def dimension(self):
3957
"""
3958
Return the dimension of this modular abelian variety.
3959
3960
EXAMPLES::
3961
3962
sage: J0(37)[0].dimension()
3963
1
3964
sage: J0(43)[1].dimension()
3965
2
3966
sage: J1(17)[1].dimension()
3967
4
3968
"""
3969
try:
3970
return self._dimension
3971
except AttributeError:
3972
M = self._modular_symbols()
3973
if M.sign() == 0:
3974
d = M.dimension() // 2
3975
else:
3976
d = M.dimension()
3977
self._dimension = d
3978
return d
3979
3980
def new_subvariety(self, p=None):
3981
"""
3982
Return the new or `p`-new subvariety of self.
3983
3984
INPUT:
3985
3986
3987
- ``self`` - a modular abelian variety
3988
3989
- ``p`` - prime number or None (default); if p is a
3990
prime, return the p-new subvariety. Otherwise return the full new
3991
subvariety.
3992
3993
3994
EXAMPLES::
3995
3996
sage: J0(33).new_subvariety()
3997
Abelian subvariety of dimension 1 of J0(33)
3998
sage: J0(100).new_subvariety()
3999
Abelian subvariety of dimension 1 of J0(100)
4000
sage: J1(13).new_subvariety()
4001
Abelian variety J1(13) of dimension 2
4002
"""
4003
try:
4004
return self.__new_subvariety[p]
4005
except AttributeError:
4006
self.__new_subvariety = {}
4007
except KeyError:
4008
pass
4009
A = self.modular_symbols()
4010
N = A.new_submodule(p=p)
4011
B = ModularAbelianVariety_modsym(N)
4012
self.__new_subvariety[p] = B
4013
return B
4014
4015
def old_subvariety(self, p=None):
4016
"""
4017
Return the old or `p`-old abelian variety of self.
4018
4019
INPUT:
4020
4021
4022
- ``self`` - a modular abelian variety
4023
4024
- ``p`` - prime number or None (default); if p is a
4025
prime, return the p-old subvariety. Otherwise return the full old
4026
subvariety.
4027
4028
4029
EXAMPLES::
4030
4031
sage: J0(33).old_subvariety()
4032
Abelian subvariety of dimension 2 of J0(33)
4033
sage: J0(100).old_subvariety()
4034
Abelian subvariety of dimension 6 of J0(100)
4035
sage: J1(13).old_subvariety()
4036
Abelian subvariety of dimension 0 of J1(13)
4037
"""
4038
try:
4039
return self.__old_subvariety[p]
4040
except AttributeError:
4041
self.__old_subvariety = {}
4042
except KeyError:
4043
pass
4044
A = self.modular_symbols()
4045
N = A.old_submodule(p=p)
4046
B = ModularAbelianVariety_modsym(N)
4047
self.__old_subvariety[p] = B
4048
return B
4049
4050
def decomposition(self, simple=True, bound=None):
4051
r"""
4052
Decompose this modular abelian variety as a product of abelian
4053
subvarieties, up to isogeny.
4054
4055
INPUT: simple- bool (default: True) if True, all factors are
4056
simple. If False, each factor returned is isogenous to a power of a
4057
simple and the simples in each factor are distinct.
4058
4059
4060
- ``bound`` - int (default: None) if given, only use
4061
Hecke operators up to this bound when decomposing. This can give
4062
wrong answers, so use with caution!
4063
4064
4065
EXAMPLES::
4066
4067
sage: J = J0(33)
4068
sage: J.decomposition()
4069
[
4070
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33),
4071
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33),
4072
Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33)
4073
]
4074
sage: J1(17).decomposition()
4075
[
4076
Simple abelian subvariety 17aG1(1,17) of dimension 1 of J1(17),
4077
Simple abelian subvariety 17bG1(1,17) of dimension 4 of J1(17)
4078
]
4079
"""
4080
try:
4081
return self.__decomposition[(simple, bound)]
4082
except KeyError:
4083
pass
4084
except AttributeError:
4085
self.__decomposition = {}
4086
if not self.is_ambient():
4087
S = ModularAbelianVariety_abstract.decomposition(self, simple=simple, bound=bound)
4088
else:
4089
A = self.modular_symbols()
4090
amb = A.ambient_module()
4091
G = amb.group()
4092
S = amb.cuspidal_submodule().integral_structure()
4093
if simple:
4094
M = A.level()
4095
D = []
4096
for N in reversed(divisors(M)):
4097
if N > 1:
4098
isogeny_number = 0
4099
A = amb.modular_symbols_of_level(N).cuspidal_subspace().new_subspace()
4100
if bound is None:
4101
X = factor_new_space(A)
4102
else:
4103
X = A.decomposition(bound = bound)
4104
for B in X:
4105
for t in divisors(M//N):
4106
D.append(ModularAbelianVariety_modsym(B.degeneracy_map(M, t).image(),
4107
is_simple=True, newform_level=(N, G),
4108
isogeny_number=isogeny_number,
4109
number=(t,M)))
4110
isogeny_number += 1
4111
elif A == amb.cuspidal_submodule():
4112
D = [ModularAbelianVariety_modsym(B) for B in A.decomposition(bound = bound)]
4113
else:
4114
D = ModularAbelianVariety_abstract.decomposition(self, simple=simple, bound=bound)
4115
D.sort()
4116
S = Sequence(D, immutable=True, cr=True, universe=self.category())
4117
self.__decomposition[(simple, bound)] = S
4118
return S
4119
4120
4121
class ModularAbelianVariety_modsym(ModularAbelianVariety_modsym_abstract):
4122
4123
def __init__(self, modsym, lattice=None, newform_level=None,
4124
is_simple=None, isogeny_number=None, number=None, check=True):
4125
"""
4126
Modular abelian variety that corresponds to a Hecke stable space of
4127
cuspidal modular symbols.
4128
4129
EXAMPLES: We create a modular abelian variety attached to a space
4130
of modular symbols.
4131
4132
::
4133
4134
sage: M = ModularSymbols(23).cuspidal_submodule()
4135
sage: A = M.abelian_variety(); A
4136
Abelian variety J0(23) of dimension 2
4137
"""
4138
if check:
4139
if not isinstance(modsym, ModularSymbolsSpace):
4140
raise TypeError, "modsym must be a modular symbols space"
4141
if modsym.sign() != 0:
4142
raise TypeError, "modular symbols space must have sign 0"
4143
if not modsym.is_cuspidal():
4144
raise ValueError, "modsym must be cuspidal"
4145
4146
ModularAbelianVariety_abstract.__init__(self, (modsym.group(), ), modsym.base_ring(),
4147
newform_level=newform_level, is_simple=is_simple,
4148
isogeny_number=isogeny_number, number=number, check=check)
4149
if lattice is not None:
4150
self._set_lattice(lattice)
4151
self.__modsym = modsym
4152
4153
def _modular_symbols(self):
4154
"""
4155
Return the modular symbols space that defines this modular abelian
4156
variety.
4157
4158
OUTPUT: space of modular symbols
4159
4160
EXAMPLES::
4161
4162
sage: M = ModularSymbols(37).cuspidal_submodule()
4163
sage: A = M.abelian_variety(); A
4164
Abelian variety J0(37) of dimension 2
4165
sage: A._modular_symbols()
4166
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 5 for Gamma_0(37) of weight 2 with sign 0 over Rational Field
4167
"""
4168
return self.__modsym
4169
4170
def component_group_order(self, p):
4171
"""
4172
Return the order of the component group of the special fiber
4173
at p of the Neron model of self.
4174
4175
NOTE: For bad primes, this is only implemented when the group
4176
if Gamma0 and p exactly divides the level.
4177
4178
NOTE: the input abelian variety must be simple
4179
4180
ALGORITHM: See "Component Groups of Quotients of J0(N)" by Kohel and Stein. That
4181
paper is about optimal quotients; however, section 4.1 of Conrad-Stein "Component
4182
Groups of Purely Toric Quotients", one sees that the component group of an optimal
4183
quotient is the same as the component group of its dual (which is the subvariety).
4184
4185
INPUT:
4186
- p -- a prime number
4187
4188
OUTPUT:
4189
- Integer
4190
4191
EXAMPLES::
4192
4193
sage: A = J0(37)[1]
4194
sage: A.component_group_order(37)
4195
3
4196
sage: A = J0(43)[1]
4197
sage: A.component_group_order(37)
4198
1
4199
sage: A.component_group_order(43)
4200
7
4201
sage: A = J0(23)[0]
4202
sage: A.component_group_order(23)
4203
11
4204
"""
4205
if not self.is_simple():
4206
raise ValueError, "self must be simple"
4207
p = Integer(p)
4208
if not p.is_prime(): raise ValueError, "p must be a prime integer"
4209
try: return self.__component_group[p][0]
4210
except AttributeError:
4211
self.__component_group = {}
4212
except KeyError: pass
4213
# Easy special case -- a prime of good reduction
4214
if self.level() % p != 0:
4215
one = Integer(1)
4216
self.__component_group[p] = (one,one,one)
4217
return one
4218
# Cases that we don't know how to handle yet.
4219
if not is_Gamma0(self.group()):
4220
raise NotImplementedError, "computation of component group not implemented when group isn't Gamma0"
4221
if self.level() % (p*p) == 0:
4222
raise NotImplementedError, "computation of component group not implemented when p^2 divides the level"
4223
4224
# Now we're on Gamma0(p*M) with gcd(p,M) = 1.
4225
# 1. Compute factor of Brandt module space, and put integral structure on it.
4226
4227
# TODO -- in case self.level() is prime, should use
4228
# supersingular module instead for massive speedup... Of
4229
# course, then one can just use Emertons theorem that the
4230
# component group order equals the torsion order, and avoid
4231
# all of this!
4232
XI = self.brandt_module(p)
4233
Y = XI.ambient_module()
4234
n = Y.dimension()
4235
4236
# X_ZZ is the submodule of degree 0 divisors
4237
M = ZZ**n
4238
deg_zero = []
4239
for k in range(1,n):
4240
v = vector(ZZ, n)
4241
v[0] = 1
4242
v[k] = -1
4243
deg_zero.append(v)
4244
X_ZZ = M.span(deg_zero, ZZ)
4245
XI_ZZ = XI.free_module().intersection(M)
4246
4247
# 2. Compute the map alpha: X --> Hom(X[I],Z) over ZZ
4248
# todo -- this could be done more quickly with a clever matrix multiply
4249
B = [XI(v) for v in XI_ZZ.basis()]
4250
mat = []
4251
for v in M.basis():
4252
w = Y(v)
4253
mat.append([w.monodromy_pairing(b) for b in B])
4254
monodromy = matrix(ZZ, mat)
4255
alpha = X_ZZ.basis_matrix().change_ring(ZZ) * monodromy
4256
4257
# 3. Compute invariants:
4258
# * Phi_X = #coker(alpha)
4259
# * m_X = #(alpha(X)/alpha(X[I]))
4260
alphaX = alpha.row_module()
4261
Phi_X_invariants = alphaX.basis_matrix().change_ring(ZZ).elementary_divisors()
4262
Phi_X = prod(Phi_X_invariants + [Integer(1)])
4263
4264
W = alphaX.span([b*monodromy for b in XI_ZZ.basis()], ZZ)
4265
m_X = Integer(W.index_in(alphaX))
4266
4267
# 4. Compute the modular degree
4268
moddeg = self.modular_degree()
4269
4270
# 5. Obtain the component group order using Theorem 1 of [Kohel-Stein]
4271
Phi = Phi_X * moddeg / m_X
4272
4273
# 6. Record the answer
4274
self.__component_group[p] = (Phi, Phi_X_invariants, m_X)
4275
return Phi
4276
4277
def _invariants_of_image_of_component_group_of_J0(self, p):
4278
"""
4279
Return the elementary invariants of the image of the component
4280
group of J0(N). The API of this function is subject to
4281
change, which is why it starts with an underscore.
4282
4283
INPUT:
4284
- p -- integer
4285
OUTPUT:
4286
- list -- of elementary invariants
4287
4288
EXAMPLES::
4289
4290
sage: A = J0(62).new_subvariety()[1]; A
4291
Simple abelian subvariety 62b(1,62) of dimension 2 of J0(62)
4292
sage: A._invariants_of_image_of_component_group_of_J0(2)
4293
[1, 6]
4294
sage: A.component_group_order(2)
4295
66
4296
"""
4297
self.component_group_order(p)
4298
return list(self.__component_group[p][1]) # make a copy
4299
4300
def tamagawa_number(self, p):
4301
"""
4302
Return the Tamagawa number of this abelian variety at p.
4303
4304
NOTE: For bad primes, this is only implemented when the group
4305
if Gamma0 and p exactly divides the level and Atkin-Lehner
4306
acts diagonally on this abelian variety (e.g., if this variety
4307
is new and simple). See the self.component_group command for
4308
more information.
4309
4310
NOTE: the input abelian variety must be simple
4311
4312
In cases where this function doesn't work, consider using the
4313
self.tamagawa_number_bounds functions.
4314
4315
INPUT:
4316
- p -- a prime number
4317
4318
OUTPUT:
4319
- Integer
4320
4321
EXAMPLES::
4322
4323
sage: A = J0(37)[1]
4324
sage: A.tamagawa_number(37)
4325
3
4326
sage: A = J0(43)[1]
4327
sage: A.tamagawa_number(37)
4328
1
4329
sage: A.tamagawa_number(43)
4330
7
4331
sage: A = J0(23)[0]
4332
sage: A.tamagawa_number(23)
4333
11
4334
"""
4335
try: return self.__tamagawa_number[p]
4336
except AttributeError: self.__tamagawa_number = {}
4337
except KeyError: pass
4338
if not self.is_simple():
4339
raise ValueError, "self must be simple"
4340
try:
4341
g = self.component_group_order(p)
4342
except NotImplementedError:
4343
raise NotImplementedError, "Tamagawa number can't be determined using known algorithms, so consider using the tamagawa_number_bounds function instead"
4344
div, mul, mul_primes = self.tamagawa_number_bounds(p)
4345
if div == mul:
4346
cp = div
4347
else:
4348
raise NotImplementedError, "the Tamagawa number at %s is a power of 2, but the exact power can't be determined using known algorithms. Consider using the tamagawa_number_bounds function instead."%p
4349
self.__tamagawa_number[p] = cp
4350
return cp
4351
4352
def tamagawa_number_bounds(self, p):
4353
"""
4354
Return a divisor and multiple of the Tamagawa number of self at p.
4355
4356
NOTE: the input abelian variety must be simple
4357
4358
INPUT:
4359
- p -- a prime number
4360
4361
OUTPUT:
4362
- div -- integer; divisor of Tamagawa number at p
4363
- mul -- integer; multiple of Tamagawa number at p
4364
- mul_primes -- tuple; in case mul==0, a list of all
4365
primes that can possibly divide the Tamagawa number at p.
4366
4367
EXAMPLES::
4368
4369
sage: A = J0(63).new_subvariety()[1]; A
4370
Simple abelian subvariety 63b(1,63) of dimension 2 of J0(63)
4371
sage: A.tamagawa_number_bounds(7)
4372
(3, 3, ())
4373
sage: A.tamagawa_number_bounds(3)
4374
(1, 0, (2, 3, 5))
4375
"""
4376
try: return self.__tamagawa_number_bounds[p]
4377
except AttributeError: self.__tamagawa_number_bounds = {}
4378
except KeyError: pass
4379
if not self.is_simple():
4380
raise ValueError, "self must be simple"
4381
N = self.level()
4382
div = 1; mul = 0; mul_primes = []
4383
if N % p != 0:
4384
div = 1; mul = 1
4385
elif N.valuation(p) == 1:
4386
M = self.modular_symbols(sign=1)
4387
if is_Gamma0(M.group()):
4388
g = self.component_group_order(p)
4389
W = M.atkin_lehner_operator(p).matrix()
4390
cp = None
4391
if W == -1:
4392
# Frob acts trivially
4393
div = g; mul = g
4394
elif W == 1:
4395
# Frob acts by -1
4396
n = g.valuation(2)
4397
if n <= 1:
4398
div = 2**n
4399
else:
4400
phi_X_invs = self._invariants_of_image_of_component_group_of_J0(p)
4401
m = max(1, len([z for z in phi_X_invs if z%2==0]))
4402
div = 2**m
4403
mul = 2**n
4404
else:
4405
raise NotImplementedError, "Atkin-Lehner at p must act as a scalar"
4406
else:
4407
mul_primes = list(sorted(set([p] + [q for q in prime_range(2,2*self.dimension()+2)])))
4408
div = Integer(div)
4409
mul = Integer(mul)
4410
mul_primes = tuple(mul_primes)
4411
self.__tamagawa_number_bounds[p] = (div, mul, mul_primes)
4412
return (div, mul, mul_primes)
4413
4414
4415
def brandt_module(self, p):
4416
"""
4417
Return the Brandt module at p that corresponds to self. This
4418
is the factor of the vector space on the ideal class set in an
4419
order of level N in the quaternion algebra ramified at p and
4420
infinity.
4421
4422
INPUT:
4423
- p -- prime that exactly divides the level
4424
4425
OUTPUT:
4426
- Brandt module space that corresponds to self.
4427
4428
EXAMPLES::
4429
4430
sage: J0(43)[1].brandt_module(43)
4431
Subspace of dimension 2 of Brandt module of dimension 4 of level 43 of weight 2 over Rational Field
4432
sage: J0(43)[1].brandt_module(43).basis()
4433
((1, 0, -1/2, -1/2), (0, 1, -1/2, -1/2))
4434
sage: J0(43)[0].brandt_module(43).basis()
4435
((0, 0, 1, -1),)
4436
sage: J0(35)[0].brandt_module(5).basis()
4437
((1, 0, -1, 0),)
4438
sage: J0(35)[0].brandt_module(7).basis()
4439
((1, -1, 1, -1),)
4440
"""
4441
try: return self.__brandt_module[p]
4442
except AttributeError: self.__brandt_module = {}
4443
except KeyError: pass
4444
p = Integer(p)
4445
if not is_Gamma0(self.group()):
4446
raise NotImplementedError, "Brandt module only defined on Gamma0"
4447
if not p.is_prime(): raise ValueError, "p must be a prime integer"
4448
if self.level().valuation(p) != 1:
4449
raise ValueError, "p must exactly divide the level"
4450
M = self.level() / p
4451
from sage.modular.all import BrandtModule
4452
V = BrandtModule(p, M)
4453
# now cut out version of self in B
4454
S = self.modular_symbols(sign=1)
4455
B = S.hecke_bound()
4456
if self.dimension() <= 3:
4457
q = 2
4458
while V.dimension() > self.dimension() and q <= B:
4459
f = S.hecke_polynomial(q)
4460
V = f(V.hecke_operator(q)).kernel()
4461
q = next_prime(q)
4462
if V.dimension() > self.dimension():
4463
raise RuntimeError, "unable to cut out Brandt module (got dimension %s instead of %s)"%(V.dimension(), self.dimension())
4464
else:
4465
D = V.decomposition()
4466
D = [A for A in D if A.dimension() == self.dimension()]
4467
# now figure out which element of D is isomorphic to self.
4468
q = 2
4469
while len(D) > 1 and q <= B:
4470
f = S.hecke_polynomial(q)
4471
D = [A for A in D if A.hecke_polynomial(q) == f]
4472
q = next_prime(q)
4473
if len(D) != 1:
4474
raise RuntimeError, "unable to locate Brandt module (got %s candidates instead of 1)"%(len(D))
4475
V = D[0]
4476
self.__brandt_module[p] = V
4477
return V
4478
4479
4480
def sqrt_poly(f):
4481
"""
4482
Return the square root of the polynomial `f`.
4483
4484
.. note::
4485
4486
At some point something like this should be a member of the
4487
polynomial class. For now this is just used internally by some
4488
charpoly functions above.
4489
4490
EXAMPLES::
4491
4492
sage: R.<x> = QQ[]
4493
sage: f = (x-1)*(x+2)*(x^2 + 1/3*x + 5)
4494
sage: f
4495
x^4 + 4/3*x^3 + 10/3*x^2 + 13/3*x - 10
4496
sage: sage.modular.abvar.abvar.sqrt_poly(f^2)
4497
x^4 + 4/3*x^3 + 10/3*x^2 + 13/3*x - 10
4498
sage: sage.modular.abvar.abvar.sqrt_poly(f)
4499
Traceback (most recent call last):
4500
...
4501
ValueError: f must be a perfect square
4502
sage: sage.modular.abvar.abvar.sqrt_poly(2*f^2)
4503
Traceback (most recent call last):
4504
...
4505
ValueError: f must be monic
4506
"""
4507
if not f.is_monic():
4508
raise ValueError, "f must be monic"
4509
try:
4510
return prod([g**Integer(e/Integer(2)) for g,e in f.factor()])
4511
except TypeError:
4512
raise ValueError, "f must be a perfect square"
4513
4514
4515
####################################################################################################
4516
# Useful for decomposing exactly the sort of modular symbols spaces that come up here.
4517
from random import randrange
4518
from sage.rings.arith import next_prime
4519
4520
def random_hecke_operator(M, t=None, p=2):
4521
"""
4522
Return a random Hecke operator acting on `M`, got by adding
4523
to `t` a random multiple of `T_p`
4524
4525
INPUT:
4526
4527
4528
- ``M`` - modular symbols space
4529
4530
- ``t`` - None or a Hecke operator
4531
4532
- ``p`` - a prime
4533
4534
4535
OUTPUT: Hecke operator prime
4536
4537
EXAMPLES::
4538
4539
sage: M = ModularSymbols(11).cuspidal_subspace()
4540
sage: t, p = sage.modular.abvar.abvar.random_hecke_operator(M)
4541
sage: p
4542
3
4543
sage: t, p = sage.modular.abvar.abvar.random_hecke_operator(M, t, p)
4544
sage: p
4545
5
4546
"""
4547
r = 0
4548
while r == 0:
4549
r = randrange(1,p//2+1) * ZZ.random_element()
4550
t = (0 if t is None else t) + r*M.hecke_operator(p)
4551
return t, next_prime(p)
4552
4553
def factor_new_space(M):
4554
"""
4555
Given a new space `M` of modular symbols, return the
4556
decomposition into simple of `M` under the Hecke
4557
operators.
4558
4559
INPUT:
4560
4561
4562
- ``M`` - modular symbols space
4563
4564
4565
OUTPUT: list of factors
4566
4567
EXAMPLES::
4568
4569
sage: M = ModularSymbols(37).cuspidal_subspace()
4570
sage: sage.modular.abvar.abvar.factor_new_space(M)
4571
[
4572
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 5 for Gamma_0(37) of weight 2 with sign 0 over Rational Field,
4573
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 5 for Gamma_0(37) of weight 2 with sign 0 over Rational Field
4574
]
4575
"""
4576
t = None; p = 2
4577
for i in range(200):
4578
t, p = random_hecke_operator(M, t, p)
4579
f = t.charpoly()
4580
cube_free = True
4581
for _, e in f.factor():
4582
if e > 2:
4583
cube_free = False
4584
break
4585
if cube_free:
4586
return t.decomposition()
4587
t, p = random_hecke_operator(M, t, p)
4588
raise RuntimeError, "unable to factor new space -- this should not happen" # should never happen
4589
4590
def factor_modsym_space_new_factors(M):
4591
"""
4592
Given an ambient modular symbols space, return complete
4593
factorization of it.
4594
4595
INPUT:
4596
4597
4598
- ``M`` - modular symbols space
4599
4600
4601
OUTPUT: list of decompositions corresponding to each new space.
4602
4603
EXAMPLES::
4604
4605
sage: M = ModularSymbols(33)
4606
sage: sage.modular.abvar.abvar.factor_modsym_space_new_factors(M)
4607
[[
4608
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
4609
],
4610
[
4611
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field
4612
]]
4613
"""
4614
eps = M.character()
4615
K = eps.conductor() if eps is not None else 1
4616
N = [M.modular_symbols_of_level(d).cuspidal_subspace().new_subspace() \
4617
for d in M.level().divisors() if d%K == 0 and (d == 11 or d >= 13)]
4618
return [factor_new_space(A) for A in N]
4619
4620
def simple_factorization_of_modsym_space(M, simple=True):
4621
"""
4622
Return factorization of `M`. If simple is False, return
4623
powers of simples.
4624
4625
INPUT:
4626
4627
4628
- ``M`` - modular symbols space
4629
4630
- ``simple`` - bool (default: True)
4631
4632
4633
OUTPUT: sequence
4634
4635
EXAMPLES::
4636
4637
sage: M = ModularSymbols(33)
4638
sage: sage.modular.abvar.abvar.simple_factorization_of_modsym_space(M)
4639
[
4640
(11, 0, 1, Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field),
4641
(11, 0, 3, Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field),
4642
(33, 0, 1, Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field)
4643
]
4644
sage: sage.modular.abvar.abvar.simple_factorization_of_modsym_space(M, simple=False)
4645
[
4646
(11, 0, None, Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field),
4647
(33, 0, None, Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field)
4648
]
4649
"""
4650
D = []
4651
N = M.level()
4652
for G in factor_modsym_space_new_factors(M):
4653
if len(G) > 0:
4654
# Compute the matrices of the degeneracy maps up.
4655
T = divisors(N//G[0].level())
4656
degen = [G[0].ambient_module().degeneracy_map(N, t).matrix() for t in T]
4657
# Construct a matrix with rows the basis for all the factors
4658
# stacked on top of each other. We just multiply this by each
4659
# degeneracy matrix to get the basis for the images of the
4660
# factors at higher level. By doing matrix multiplies, we
4661
# save time over taking images of individual factors.
4662
matrix = G[0].basis_matrix()
4663
for A in G[1:]:
4664
matrix = matrix.stack(A.basis_matrix())
4665
4666
# Compute the actual images
4667
ims = [matrix * z for z in degen]
4668
4669
# Construct the corresponding subspaces at higher level.
4670
j = 0
4671
for (isog,A) in enumerate(G):
4672
d = A.dimension()
4673
if simple:
4674
for i in range(len(T)):
4675
V = ims[i].matrix_from_rows(range(j, j+d)).row_module()
4676
W = M.submodule(V, check=False)
4677
D.append( (A.level(), isog, T[i], W) )
4678
else:
4679
V = sum(ims[i].matrix_from_rows(range(j, j+d)).row_module() for i in range(len(T)))
4680
W = M.submodule(V, check=False)
4681
D.append( (A.level(), isog, None, W))
4682
j += d
4683
return Sequence(D, cr=True)
4684
4685
def modsym_lattices(M, factors):
4686
"""
4687
Append lattice information to the output of
4688
simple_factorization_of_modsym_space.
4689
4690
INPUT:
4691
4692
4693
- ``M`` - modular symbols spaces
4694
4695
- ``factors`` - Sequence
4696
(simple_factorization_of_modsym_space)
4697
4698
4699
OUTPUT: sequence with more information for each factor (the
4700
lattice)
4701
4702
EXAMPLES::
4703
4704
sage: M = ModularSymbols(33)
4705
sage: factors = sage.modular.abvar.abvar.simple_factorization_of_modsym_space(M, simple=False)
4706
sage: sage.modular.abvar.abvar.modsym_lattices(M, factors)
4707
[
4708
(11, 0, None, Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field, Free module of degree 6 and rank 4 over Integer Ring
4709
Echelon basis matrix:
4710
[ 1 0 0 0 -1 2]
4711
[ 0 1 0 0 -1 1]
4712
[ 0 0 1 0 -2 2]
4713
[ 0 0 0 1 -1 -1]),
4714
(33, 0, None, Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field, Free module of degree 6 and rank 2 over Integer Ring
4715
Echelon basis matrix:
4716
[ 1 0 0 -1 0 0]
4717
[ 0 0 1 0 1 -1])
4718
]
4719
"""
4720
# 1. Change basis of everything to the ambient integral modular symbols space
4721
# 2. Clear denominator.
4722
# 3. Echelonize/saturate each factor
4723
if len(factors) == 0:
4724
return factors
4725
4726
D = []
4727
I = M.cuspidal_submodule().integral_structure().basis_matrix()
4728
A = factors[0][-1].basis_matrix()
4729
rows = [range(A.nrows())]
4730
for F in factors[1:]:
4731
mat = F[-1].basis_matrix()
4732
i = rows[-1][-1]+1
4733
rows.append(range(i, i + mat.nrows()))
4734
A = A.stack(mat)
4735
X = I.solve_left(A)
4736
X, _ = X._clear_denom()
4737
for i, R in enumerate(rows):
4738
A = X.matrix_from_rows(R)
4739
A = copy(A.saturation())
4740
A.echelonize()
4741
D.append(tuple(list(factors[i]) + [A.row_module()]))
4742
return Sequence(D, cr=True)
4743
4744
4745