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