Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/abvar/homspace.py
4078 views
1
"""
2
Spaces of homomorphisms between modular abelian varieties
3
4
EXAMPLES:
5
6
First, we consider J0(37). This Jacobian has two simple factors,
7
corresponding to distinct newforms. These two intersect
8
nontrivially in J0(37).
9
10
::
11
12
sage: J = J0(37)
13
sage: D = J.decomposition() ; D
14
[
15
Simple abelian subvariety 37a(1,37) of dimension 1 of J0(37),
16
Simple abelian subvariety 37b(1,37) of dimension 1 of J0(37)
17
]
18
sage: D[0].intersection(D[1])
19
(Finite subgroup with invariants [2, 2] over QQ of Simple abelian subvariety 37a(1,37) of dimension 1 of J0(37),
20
Simple abelian subvariety of dimension 0 of J0(37))
21
22
As an abstract product, since these newforms are distinct, the
23
corresponding simple abelian varieties are not isogenous, and so
24
there are no maps between them. The endomorphism ring of the
25
corresponding product is thus isomorphic to the direct sum of the
26
endomorphism rings for each factor. Since the factors correspond to
27
abelian varieties of dimension 1, these endomorphism rings are each
28
isomorphic to ZZ.
29
30
::
31
32
sage: Hom(D[0],D[1]).gens()
33
()
34
sage: A = D[0] * D[1] ; A
35
Abelian subvariety of dimension 2 of J0(37) x J0(37)
36
sage: A.endomorphism_ring().gens()
37
(Abelian variety endomorphism of Abelian subvariety of dimension 2 of J0(37) x J0(37),
38
Abelian variety endomorphism of Abelian subvariety of dimension 2 of J0(37) x J0(37))
39
sage: [ x.matrix() for x in A.endomorphism_ring().gens() ]
40
[
41
[1 0 0 0] [0 0 0 0]
42
[0 1 0 0] [0 0 0 0]
43
[0 0 0 0] [0 0 1 0]
44
[0 0 0 0], [0 0 0 1]
45
]
46
47
However, these two newforms have a congruence between them modulo
48
2, which gives rise to interesting endomorphisms of J0(37).
49
50
::
51
52
sage: E = J.endomorphism_ring()
53
sage: E.gens()
54
(Abelian variety endomorphism of Abelian variety J0(37) of dimension 2,
55
Abelian variety endomorphism of Abelian variety J0(37) of dimension 2)
56
sage: [ x.matrix() for x in E.gens() ]
57
[
58
[1 0 0 0] [ 0 1 1 -1]
59
[0 1 0 0] [ 1 0 1 0]
60
[0 0 1 0] [ 0 0 -1 1]
61
[0 0 0 1], [ 0 0 0 1]
62
]
63
sage: (-1*E.gens()[0] + E.gens()[1]).matrix()
64
[-1 1 1 -1]
65
[ 1 -1 1 0]
66
[ 0 0 -2 1]
67
[ 0 0 0 0]
68
69
Of course, these endomorphisms will be reflected in the Hecke
70
algebra, which is in fact the full endomorphism ring of J0(37) in
71
this case::
72
73
sage: J.hecke_operator(2).matrix()
74
[-1 1 1 -1]
75
[ 1 -1 1 0]
76
[ 0 0 -2 1]
77
[ 0 0 0 0]
78
sage: T = E.image_of_hecke_algebra()
79
sage: T.gens()
80
(Abelian variety endomorphism of Abelian variety J0(37) of dimension 2,
81
Abelian variety endomorphism of Abelian variety J0(37) of dimension 2)
82
sage: [ x.matrix() for x in T.gens() ]
83
[
84
[1 0 0 0] [ 0 1 1 -1]
85
[0 1 0 0] [ 1 0 1 0]
86
[0 0 1 0] [ 0 0 -1 1]
87
[0 0 0 1], [ 0 0 0 1]
88
]
89
sage: T.index_in(E)
90
1
91
92
Next, we consider J0(33). In this case, we have both oldforms and
93
newforms. There are two copies of J0(11), one for each degeneracy
94
map from J0(11) to J0(33). There is also one newform at level 33.
95
The images of the two degeneracy maps are, of course, isogenous.
96
97
::
98
99
sage: J = J0(33)
100
sage: D = J.decomposition()
101
sage: D
102
[
103
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33),
104
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33),
105
Simple abelian subvariety 33a(1,33) of dimension 1 of J0(33)
106
]
107
sage: Hom(D[0],D[1]).gens()
108
(Abelian variety morphism:
109
From: Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
110
To: Simple abelian subvariety 11a(3,33) of dimension 1 of J0(33),)
111
sage: Hom(D[0],D[1]).gens()[0].matrix()
112
[ 0 1]
113
[-1 0]
114
115
Then this gives that the component corresponding to the sum of the
116
oldforms will have a rank 4 endomorphism ring. We also have a rank
117
one endomorphism ring for the newform 33a (since it is again
118
1-dimensional), which gives a rank 5 endomorphism ring for J0(33).
119
120
::
121
122
sage: DD = J.decomposition(simple=False) ; DD
123
[
124
Abelian subvariety of dimension 2 of J0(33),
125
Abelian subvariety of dimension 1 of J0(33)
126
]
127
sage: A, B = DD
128
sage: A == D[0] + D[1]
129
True
130
sage: A.endomorphism_ring().gens()
131
(Abelian variety endomorphism of Abelian subvariety of dimension 2 of J0(33),
132
Abelian variety endomorphism of Abelian subvariety of dimension 2 of J0(33),
133
Abelian variety endomorphism of Abelian subvariety of dimension 2 of J0(33),
134
Abelian variety endomorphism of Abelian subvariety of dimension 2 of J0(33))
135
sage: B.endomorphism_ring().gens()
136
(Abelian variety endomorphism of Abelian subvariety of dimension 1 of J0(33),)
137
sage: E = J.endomorphism_ring() ; E.gens() # long time (3s on sage.math, 2011)
138
(Abelian variety endomorphism of Abelian variety J0(33) of dimension 3,
139
Abelian variety endomorphism of Abelian variety J0(33) of dimension 3,
140
Abelian variety endomorphism of Abelian variety J0(33) of dimension 3,
141
Abelian variety endomorphism of Abelian variety J0(33) of dimension 3,
142
Abelian variety endomorphism of Abelian variety J0(33) of dimension 3)
143
144
In this case, the image of the Hecke algebra will only have rank 3,
145
so that it is of infinite index in the full endomorphism ring.
146
However, if we call this image T, we can still ask about the index
147
of T in its saturation, which is 1 in this case.
148
149
::
150
151
sage: T = E.image_of_hecke_algebra() # long time
152
sage: T.gens() # long time
153
(Abelian variety endomorphism of Abelian variety J0(33) of dimension 3,
154
Abelian variety endomorphism of Abelian variety J0(33) of dimension 3,
155
Abelian variety endomorphism of Abelian variety J0(33) of dimension 3)
156
sage: T.index_in(E) # long time
157
+Infinity
158
sage: T.index_in_saturation() # long time
159
1
160
161
AUTHORS:
162
163
- William Stein (2007-03)
164
165
- Craig Citro, Robert Bradshaw (2008-03): Rewrote with modabvar overhaul
166
"""
167
168
###########################################################################
169
# Copyright (C) 2007 William Stein <[email protected]> #
170
# Distributed under the terms of the GNU General Public License (GPL) #
171
# http://www.gnu.org/licenses/ #
172
###########################################################################
173
174
from copy import copy
175
176
from sage.categories.homset import HomsetWithBase
177
from sage.misc.functional import parent
178
179
import abvar as abelian_variety
180
import morphism
181
182
import sage.rings.integer_ring
183
import sage.rings.all
184
185
from sage.rings.ring import Ring
186
from sage.categories.category import Category
187
from sage.categories.rings import Rings
188
from sage.matrix.matrix_space import MatrixSpace
189
from sage.matrix.constructor import Matrix, identity_matrix
190
from sage.structure.element import is_Matrix
191
192
ZZ = sage.rings.integer_ring.ZZ
193
194
class Homspace(HomsetWithBase):
195
"""
196
A space of homomorphisms between two modular abelian varieties.
197
"""
198
def __init__(self, domain, codomain, cat):
199
"""
200
Create a homspace.
201
202
INPUT:
203
204
205
- ``domain, codomain`` - modular abelian varieties
206
207
- ``cat`` - category
208
209
210
EXAMPLES::
211
212
sage: H = Hom(J0(11), J0(22)); H
213
Space of homomorphisms from Abelian variety J0(11) of dimension 1 to Abelian variety J0(22) of dimension 2
214
sage: Hom(J0(11), J0(11))
215
Endomorphism ring of Abelian variety J0(11) of dimension 1
216
sage: type(H)
217
<class 'sage.modular.abvar.homspace.Homspace_with_category'>
218
sage: H.homset_category()
219
Category of modular abelian varieties over Rational Field
220
"""
221
if not abelian_variety.is_ModularAbelianVariety(domain):
222
raise TypeError, "domain must be a modular abelian variety"
223
if not abelian_variety.is_ModularAbelianVariety(codomain):
224
raise TypeError, "codomain must be a modular abelian variety"
225
self._matrix_space = MatrixSpace(ZZ,2*domain.dimension(), 2*codomain.dimension())
226
self._gens = None
227
HomsetWithBase.__init__(self, domain, codomain, cat)
228
229
def __call__(self, M):
230
r"""
231
Create a homomorphism in this space from M. M can be any of the
232
following:
233
234
- a Morphism of abelian varieties
235
236
- a matrix of the appropriate size
237
(i.e. 2\*self.domain().dimension() x
238
2\*self.codomain().dimension()) whose entries are coercible
239
into self.base_ring()
240
241
- anything that can be coerced into self.matrix_space()
242
243
EXAMPLES::
244
245
sage: H = Hom(J0(11), J0(22))
246
sage: phi = H(matrix(ZZ,2,4,[5..12])) ; phi
247
Abelian variety morphism:
248
From: Abelian variety J0(11) of dimension 1
249
To: Abelian variety J0(22) of dimension 2
250
sage: phi.matrix()
251
[ 5 6 7 8]
252
[ 9 10 11 12]
253
sage: phi.matrix().parent()
254
Full MatrixSpace of 2 by 4 dense matrices over Integer Ring
255
256
::
257
258
sage: H = J0(22).Hom(J0(11)*J0(11))
259
sage: m1 = J0(22).degeneracy_map(11,1).matrix() ; m1
260
[ 0 1]
261
[-1 1]
262
[-1 0]
263
[ 0 -1]
264
sage: m2 = J0(22).degeneracy_map(11,2).matrix() ; m2
265
[ 1 -2]
266
[ 0 -2]
267
[ 1 -1]
268
[ 0 -1]
269
sage: m = m1.transpose().stack(m2.transpose()).transpose() ; m
270
[ 0 1 1 -2]
271
[-1 1 0 -2]
272
[-1 0 1 -1]
273
[ 0 -1 0 -1]
274
sage: phi = H(m) ; phi
275
Abelian variety morphism:
276
From: Abelian variety J0(22) of dimension 2
277
To: Abelian variety J0(11) x J0(11) of dimension 2
278
sage: phi.matrix()
279
[ 0 1 1 -2]
280
[-1 1 0 -2]
281
[-1 0 1 -1]
282
[ 0 -1 0 -1]
283
"""
284
if isinstance(M, morphism.Morphism):
285
if M.parent() is self:
286
return M
287
elif M.domain() == self.domain() and M.codomain() == self.codomain():
288
M = M.matrix()
289
else:
290
raise ValueError, "cannot convert %s into %s" % (M, self)
291
elif is_Matrix(M):
292
if M.base_ring() != ZZ:
293
M = M.change_ring(ZZ)
294
if M.nrows() != 2*self.domain().dimension() or M.ncols() != 2*self.codomain().dimension():
295
raise TypeError, "matrix has wrong dimension"
296
elif self.matrix_space().has_coerce_map_from(parent(M)):
297
M = self.matrix_space()(M)
298
else:
299
raise TypeError, "can only coerce in matrices or morphisms"
300
return morphism.Morphism(self, M)
301
302
def _coerce_impl(self, x):
303
"""
304
Coerce x into self, if possible.
305
306
EXAMPLES::
307
308
sage: J = J0(37) ; J.Hom(J)._coerce_impl(matrix(ZZ,4,[5..20]))
309
Abelian variety endomorphism of Abelian variety J0(37) of dimension 2
310
sage: K = J0(11) * J0(11) ; J.Hom(K)._coerce_impl(matrix(ZZ,4,[5..20]))
311
Abelian variety morphism:
312
From: Abelian variety J0(37) of dimension 2
313
To: Abelian variety J0(11) x J0(11) of dimension 2
314
"""
315
if self.matrix_space().has_coerce_map_from(parent(x)):
316
return self(x)
317
else:
318
return HomsetWithBase._coerce_impl(self, x)
319
320
def _repr_(self):
321
"""
322
String representation of a modular abelian variety homspace.
323
324
EXAMPLES::
325
326
sage: J = J0(11)
327
sage: End(J)._repr_()
328
'Endomorphism ring of Abelian variety J0(11) of dimension 1'
329
"""
330
return "Space of homomorphisms from %s to %s"%\
331
(self.domain(), self.codomain())
332
333
def _get_matrix(self, g):
334
"""
335
Given an object g, try to return a matrix corresponding to g with
336
dimensions the same as those of self.matrix_space().
337
338
INPUT:
339
340
341
- ``g`` - a matrix or morphism or object with a list
342
method
343
344
345
OUTPUT: a matrix
346
347
EXAMPLES::
348
349
sage: E = End(J0(11))
350
sage: E._get_matrix(matrix(QQ,2,[1,2,3,4]))
351
[1 2]
352
[3 4]
353
sage: E._get_matrix(J0(11).hecke_operator(2))
354
[-2 0]
355
[ 0 -2]
356
357
::
358
359
sage: H = Hom(J0(11) * J0(17), J0(22))
360
sage: H._get_matrix(tuple([8..23]))
361
[ 8 9 10 11]
362
[12 13 14 15]
363
[16 17 18 19]
364
[20 21 22 23]
365
sage: H._get_matrix(tuple([8..23]))
366
[ 8 9 10 11]
367
[12 13 14 15]
368
[16 17 18 19]
369
[20 21 22 23]
370
sage: H._get_matrix([8..23])
371
[ 8 9 10 11]
372
[12 13 14 15]
373
[16 17 18 19]
374
[20 21 22 23]
375
"""
376
try:
377
if g.parent() is self.matrix_space():
378
return g
379
except AttributeError:
380
pass
381
382
if isinstance(g, morphism.Morphism):
383
return g.matrix()
384
elif hasattr(g, 'list'):
385
return self.matrix_space()(g.list())
386
else:
387
return self.matrix_space()(g)
388
389
def free_module(self):
390
r"""
391
Return this endomorphism ring as a free submodule of a big
392
`\ZZ^{4nm}`, where `n` is the dimension of
393
the domain abelian variety and `m` the dimension of the
394
codomain.
395
396
OUTPUT: free module
397
398
EXAMPLES::
399
400
sage: E = Hom(J0(11), J0(22))
401
sage: E.free_module()
402
Free module of degree 8 and rank 2 over Integer Ring
403
Echelon basis matrix:
404
[ 1 0 -3 1 1 1 -1 -1]
405
[ 0 1 -3 1 1 1 -1 0]
406
"""
407
self.calculate_generators()
408
V = ZZ**(4*self.domain().dimension() * self.codomain().dimension())
409
return V.submodule([ V(m.matrix().list()) for m in self.gens() ])
410
411
def gen(self, i=0):
412
"""
413
Return i-th generator of self.
414
415
INPUT:
416
417
418
- ``i`` - an integer
419
420
421
OUTPUT: a morphism
422
423
EXAMPLES::
424
425
sage: E = End(J0(22))
426
sage: E.gen(0).matrix()
427
[1 0 0 0]
428
[0 1 0 0]
429
[0 0 1 0]
430
[0 0 0 1]
431
"""
432
self.calculate_generators()
433
if i > self.ngens():
434
raise ValueError, "self only has %s generators"%self.ngens()
435
return morphism.Morphism(self, self._gens[i])
436
437
def ngens(self):
438
"""
439
Return number of generators of self.
440
441
OUTPUT: integer
442
443
EXAMPLES::
444
445
sage: E = End(J0(22))
446
sage: E.ngens()
447
4
448
"""
449
self.calculate_generators()
450
return len(self._gens)
451
452
def gens(self):
453
"""
454
Return tuple of generators for this endomorphism ring.
455
456
EXAMPLES::
457
458
sage: E = End(J0(22))
459
sage: E.gens()
460
(Abelian variety endomorphism of Abelian variety J0(22) of dimension 2,
461
Abelian variety endomorphism of Abelian variety J0(22) of dimension 2,
462
Abelian variety endomorphism of Abelian variety J0(22) of dimension 2,
463
Abelian variety endomorphism of Abelian variety J0(22) of dimension 2)
464
"""
465
try:
466
return self._gen_morphisms
467
except AttributeError:
468
self.calculate_generators()
469
self._gen_morphisms = tuple([self.gen(i) for i in range(self.ngens())])
470
return self._gen_morphisms
471
472
def matrix_space(self):
473
"""
474
Return the underlying matrix space that we view this endomorphism
475
ring as being embedded into.
476
477
EXAMPLES::
478
479
sage: E = End(J0(22))
480
sage: E.matrix_space()
481
Full MatrixSpace of 4 by 4 dense matrices over Integer Ring
482
"""
483
return self._matrix_space
484
485
def calculate_generators(self):
486
"""
487
If generators haven't already been computed, calculate generators
488
for this homspace. If they have been computed, do nothing.
489
490
EXAMPLES::
491
492
sage: E = End(J0(11))
493
sage: E.calculate_generators()
494
"""
495
496
if self._gens is not None:
497
return
498
499
if (self.domain() == self.codomain()) and (self.domain().dimension() == 1):
500
self._gens = tuple([ identity_matrix(ZZ,2) ])
501
return
502
503
phi = self.domain()._isogeny_to_product_of_powers()
504
psi = self.codomain()._isogeny_to_product_of_powers()
505
506
H_simple = phi.codomain().Hom(psi.codomain())
507
im_gens = H_simple._calculate_product_gens()
508
509
M = phi.matrix()
510
Mt = psi.complementary_isogeny().matrix()
511
512
R = ZZ**(4*self.domain().dimension()*self.codomain().dimension())
513
gens = R.submodule([ (M*self._get_matrix(g)*Mt).list()
514
for g in im_gens ]).saturation().basis()
515
self._gens = tuple([ self._get_matrix(g) for g in gens ])
516
517
def _calculate_product_gens(self):
518
"""
519
For internal use.
520
521
Calculate generators for self, assuming that self is a product of
522
simple factors.
523
524
EXAMPLES::
525
526
sage: E = End(J0(37))
527
sage: E.gens()
528
(Abelian variety endomorphism of Abelian variety J0(37) of dimension 2,
529
Abelian variety endomorphism of Abelian variety J0(37) of dimension 2)
530
sage: [ x.matrix() for x in E.gens() ]
531
[
532
[1 0 0 0] [ 0 1 1 -1]
533
[0 1 0 0] [ 1 0 1 0]
534
[0 0 1 0] [ 0 0 -1 1]
535
[0 0 0 1], [ 0 0 0 1]
536
]
537
sage: E._calculate_product_gens()
538
[
539
[1 0 0 0] [0 0 0 0]
540
[0 1 0 0] [0 0 0 0]
541
[0 0 0 0] [0 0 1 0]
542
[0 0 0 0], [0 0 0 1]
543
]
544
"""
545
546
Afactors = self.domain().decomposition(simple=False)
547
Bfactors = self.codomain().decomposition(simple=False)
548
matrix_space = self.matrix_space()
549
if len(Afactors) == 1 and len(Bfactors) == 1:
550
Asimples = Afactors[0].decomposition()
551
Bsimples = Bfactors[0].decomposition()
552
if len(Asimples) == 1 and len(Bsimples) == 1:
553
# Handle the base case of A, B simple
554
gens = self._calculate_simple_gens()
555
556
else:
557
# Handle the case of A, B simple powers
558
gens = []
559
phi_matrix = Afactors[0]._isogeny_to_product_of_simples().matrix()
560
psi_t_matrix = Bfactors[0]._isogeny_to_product_of_simples().complementary_isogeny().matrix()
561
for i in range(len(Asimples)):
562
for j in range(len(Bsimples)):
563
hom_gens = Asimples[i].Hom(Bsimples[j]).gens()
564
for sub_gen in hom_gens:
565
sub_mat = sub_gen.matrix()
566
M = copy(self.matrix_space().zero_matrix())
567
M.set_block(sub_mat.nrows()*i, sub_mat.ncols()*j, sub_mat)
568
gens.append(phi_matrix * M * psi_t_matrix)
569
570
else:
571
# Handle the case of A, B generic
572
gens = []
573
cur_row = 0
574
for Afactor in Afactors:
575
cur_row += Afactor.dimension() * 2
576
cur_col = 0
577
for Bfactor in Bfactors:
578
cur_col += Bfactor.dimension() * 2
579
Asimple = Afactor[0]
580
Bsimple = Bfactor[0]
581
if Asimple.newform_label() == Bsimple.newform_label():
582
for sub_gen in Afactor.Hom(Bfactor).gens():
583
sub_mat = sub_gen.matrix()
584
M = copy(self.matrix_space().zero_matrix())
585
M.set_block(cur_row - sub_mat.nrows(),
586
cur_col - sub_mat.ncols(),
587
sub_mat)
588
gens.append(M)
589
590
return gens
591
592
def _calculate_simple_gens(self):
593
"""
594
Calculate generators for self, where both the domain and codomain
595
for self are assumed to be simple abelian varieties. The saturation
596
of the span of these generators in self will be the full space of
597
homomorphisms from the domain of self to its codomain.
598
599
EXAMPLES::
600
601
sage: H = Hom(J0(11), J0(22)[0])
602
sage: H._calculate_simple_gens()
603
[
604
[1 0]
605
[1 1]
606
]
607
sage: J = J0(11) * J0(33) ; J.decomposition()
608
[
609
Simple abelian subvariety 11a(1,11) of dimension 1 of J0(11) x J0(33),
610
Simple abelian subvariety 11a(1,33) of dimension 1 of J0(11) x J0(33),
611
Simple abelian subvariety 11a(3,33) of dimension 1 of J0(11) x J0(33),
612
Simple abelian subvariety 33a(1,33) of dimension 1 of J0(11) x J0(33)
613
]
614
sage: J[0].Hom(J[1])._calculate_simple_gens()
615
[
616
[ 0 -1]
617
[ 1 -1]
618
]
619
sage: J[0].Hom(J[2])._calculate_simple_gens()
620
[
621
[-1 0]
622
[-1 -1]
623
]
624
sage: J[0].Hom(J[0])._calculate_simple_gens()
625
[
626
[1 0]
627
[0 1]
628
]
629
sage: J[1].Hom(J[2])._calculate_simple_gens()
630
[
631
[ 0 -4]
632
[ 4 0]
633
]
634
635
::
636
637
sage: J = J0(23) ; J.decomposition()
638
[
639
Simple abelian variety J0(23) of dimension 2
640
]
641
sage: J[0].Hom(J[0])._calculate_simple_gens()
642
[
643
[1 0 0 0] [ 0 1 -1 0]
644
[0 1 0 0] [ 0 1 -1 1]
645
[0 0 1 0] [-1 2 -2 1]
646
[0 0 0 1], [-1 1 0 -1]
647
]
648
sage: J.hecke_operator(2).matrix()
649
[ 0 1 -1 0]
650
[ 0 1 -1 1]
651
[-1 2 -2 1]
652
[-1 1 0 -1]
653
654
::
655
656
sage: H = Hom(J0(11), J0(22)[0])
657
sage: H._calculate_simple_gens()
658
[
659
[1 0]
660
[1 1]
661
]
662
"""
663
A = self.domain()
664
B = self.codomain()
665
666
if A.newform_label() != B.newform_label():
667
return []
668
669
f = A._isogeny_to_newform_abelian_variety()
670
g = B._isogeny_to_newform_abelian_variety().complementary_isogeny()
671
672
Af = f.codomain()
673
ls = Af._calculate_endomorphism_generators()
674
675
Mf = f.matrix()
676
Mg = g.matrix()
677
678
return [ Mf * self._get_matrix(e) * Mg for e in ls ]
679
680
# NOTE/WARNING/TODO: Below in the __init__, etc. we do *not* check
681
# that the input gens are give something that spans a sub*ring*, as apposed
682
# to just a subgroup.
683
class EndomorphismSubring(Homspace, Ring):
684
685
def __init__(self, A, gens=None):
686
"""
687
A subring of the endomorphism ring.
688
689
INPUT:
690
691
692
- ``A`` - an abelian variety
693
694
- ``gens`` - (default: None); optional; if given
695
should be a tuple of the generators as matrices
696
697
698
EXAMPLES::
699
700
sage: J0(23).endomorphism_ring()
701
Endomorphism ring of Abelian variety J0(23) of dimension 2
702
sage: sage.modular.abvar.homspace.EndomorphismSubring(J0(25))
703
Endomorphism ring of Abelian variety J0(25) of dimension 0
704
sage: E = J0(11).endomorphism_ring()
705
sage: type(E)
706
<class 'sage.modular.abvar.homspace.EndomorphismSubring_with_category'>
707
sage: E.category()
708
Join of Category of hom sets in Category of sets and Category of rings
709
sage: E.homset_category()
710
Category of modular abelian varieties over Rational Field
711
sage: TestSuite(E).run(skip=["_test_elements"])
712
713
TESTS:
714
715
The following tests against a problem on 32 bit machines that
716
occured while working on trac ticket #9944::
717
718
sage: sage.modular.abvar.homspace.EndomorphismSubring(J1(12345))
719
Endomorphism ring of Abelian variety J1(12345) of dimension 5405473
720
721
"""
722
self._J = A.ambient_variety()
723
self._A = A
724
725
# Initialise self with the correct category.
726
# TODO: a category should be able to specify the appropriate
727
# category for its endomorphism sets
728
# We need to initialise it as a ring first
729
homset_cat = A.category()
730
cat = Category.join([homset_cat.hom_category(),Rings()])
731
Ring.__init__(self, A.base_ring())
732
Homspace.__init__(self, A, A, cat=homset_cat)
733
self._refine_category_(Rings())
734
if gens is None:
735
self._gens = None
736
else:
737
self._gens = tuple([ self._get_matrix(g) for g in gens ])
738
self._is_full_ring = gens is None
739
740
def _repr_(self):
741
"""
742
Return the string representation of self.
743
744
EXAMPLES::
745
746
sage: J0(31).endomorphism_ring()._repr_()
747
'Endomorphism ring of Abelian variety J0(31) of dimension 2'
748
sage: J0(31).endomorphism_ring().image_of_hecke_algebra()._repr_()
749
'Subring of endomorphism ring of Abelian variety J0(31) of dimension 2'
750
"""
751
if self._is_full_ring:
752
return "Endomorphism ring of %s" % self._A
753
else:
754
return "Subring of endomorphism ring of %s" % self._A
755
756
def abelian_variety(self):
757
"""
758
Return the abelian variety that this endomorphism ring is attached
759
to.
760
761
EXAMPLES::
762
763
sage: J0(11).endomorphism_ring().abelian_variety()
764
Abelian variety J0(11) of dimension 1
765
"""
766
return self._A
767
768
def index_in(self, other, check=True):
769
"""
770
Return the index of self in other.
771
772
INPUT:
773
774
775
- ``other`` - another endomorphism subring of the
776
same abelian variety
777
778
- ``check`` - bool (default: True); whether to do some
779
type and other consistency checks
780
781
782
EXAMPLES::
783
784
sage: R = J0(33).endomorphism_ring()
785
sage: R.index_in(R)
786
1
787
sage: J = J0(37) ; E = J.endomorphism_ring() ; T = E.image_of_hecke_algebra()
788
sage: T.index_in(E)
789
1
790
sage: J = J0(22) ; E = J.endomorphism_ring() ; T = E.image_of_hecke_algebra()
791
sage: T.index_in(E)
792
+Infinity
793
"""
794
if check:
795
if not isinstance(other, EndomorphismSubring):
796
raise ValueError, "other must be a subring of an endomorphism ring of an abelian variety."
797
if not (self.abelian_variety() == other.abelian_variety()):
798
raise ValueError, "self and other must be endomorphisms of the same abelian variety"
799
800
M = self.free_module()
801
N = other.free_module()
802
if M.rank() < N.rank():
803
return sage.rings.all.Infinity
804
return M.index_in(N)
805
806
def index_in_saturation(self):
807
"""
808
Given a Hecke algebra T, compute its index in its saturation.
809
810
EXAMPLES::
811
812
sage: End(J0(23)).image_of_hecke_algebra().index_in_saturation()
813
1
814
sage: End(J0(44)).image_of_hecke_algebra().index_in_saturation()
815
2
816
"""
817
A = self.abelian_variety()
818
d = A.dimension()
819
M = ZZ**(4*d**2)
820
gens = [ x.matrix().list() for x in self.gens() ]
821
R = M.submodule(gens)
822
return R.index_in_saturation()
823
824
def discriminant(self):
825
"""
826
Return the discriminant of this ring, which is the discriminant of
827
the trace pairing.
828
829
.. note::
830
831
One knows that for modular abelian varieties, the
832
endomorphism ring should be isomorphic to an order in a
833
number field. However, the discriminant returned by this
834
function will be `2^n` ( `n =`
835
self.dimension()) times the discriminant of that order,
836
since the elements are represented as 2d x 2d
837
matrices. Notice, for example, that the case of a one
838
dimensional abelian variety, whose endomorphism ring must
839
be ZZ, has discriminant 2, as in the example below.
840
841
EXAMPLES::
842
843
sage: J0(33).endomorphism_ring().discriminant()
844
-64800
845
sage: J0(46).endomorphism_ring().discriminant() # long time (6s on sage.math, 2011)
846
24200000000
847
sage: J0(11).endomorphism_ring().discriminant()
848
2
849
"""
850
g = self.gens()
851
M = Matrix(ZZ,len(g), [ (g[i]*g[j]).trace()
852
for i in range(len(g)) for j in range(len(g)) ])
853
return M.determinant()
854
855
def image_of_hecke_algebra(self, check_every=1):
856
"""
857
Compute the image of the Hecke algebra inside this endomorphism
858
subring.
859
860
We simply calculate Hecke operators up to the Sturm bound, and look
861
at the submodule spanned by them. While computing, we can check to
862
see if the submodule spanned so far is saturated and of maximal
863
dimension, in which case we may be done. The optional argument
864
check_every determines how many Hecke operators we add in before
865
checking to see if this condition is met.
866
867
EXAMPLES::
868
869
sage: E = J0(33).endomorphism_ring()
870
sage: E.image_of_hecke_algebra()
871
Subring of endomorphism ring of Abelian variety J0(33) of dimension 3
872
sage: E.image_of_hecke_algebra().gens()
873
(Abelian variety endomorphism of Abelian variety J0(33) of dimension 3,
874
Abelian variety endomorphism of Abelian variety J0(33) of dimension 3,
875
Abelian variety endomorphism of Abelian variety J0(33) of dimension 3)
876
sage: [ x.matrix() for x in E.image_of_hecke_algebra().gens() ]
877
[
878
[1 0 0 0 0 0] [ 0 2 0 -1 1 -1] [ 0 0 1 -1 1 -1]
879
[0 1 0 0 0 0] [-1 -2 2 -1 2 -1] [ 0 -1 1 0 1 -1]
880
[0 0 1 0 0 0] [ 0 0 1 -1 3 -1] [ 0 0 1 0 2 -2]
881
[0 0 0 1 0 0] [-2 2 0 1 1 -1] [-2 0 1 1 1 -1]
882
[0 0 0 0 1 0] [-1 1 0 2 0 -3] [-1 0 1 1 0 -1]
883
[0 0 0 0 0 1], [-1 1 -1 1 1 -2], [-1 0 0 1 0 -1]
884
]
885
sage: J0(33).hecke_operator(2).matrix()
886
[-1 0 1 -1 1 -1]
887
[ 0 -2 1 0 1 -1]
888
[ 0 0 0 0 2 -2]
889
[-2 0 1 0 1 -1]
890
[-1 0 1 1 -1 -1]
891
[-1 0 0 1 0 -2]
892
"""
893
try:
894
return self.__hecke_algebra_image
895
except AttributeError:
896
pass
897
898
A = self.abelian_variety()
899
if not A.is_hecke_stable():
900
raise ValueError, "ambient variety is not Hecke stable"
901
902
M = A.modular_symbols()
903
904
d = A.dimension()
905
EndVecZ = ZZ**(4*d**2)
906
907
if d == 1:
908
self.__hecke_algebra_image = EndomorphismSubring(A, [[1,0,0,1]])
909
return self.__hecke_algebra_image
910
911
V = EndVecZ.submodule([A.hecke_operator(1).matrix().list()])
912
913
for n in range(2,M.sturm_bound()+1):
914
V += EndVecZ.submodule([ A.hecke_operator(n).matrix().list() ])
915
916
self.__hecke_algebra_image = EndomorphismSubring(A, V.basis())
917
return self.__hecke_algebra_image
918
919
920
921
922