Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/abvar/finite_subgroup.py
4069 views
1
r"""
2
Finite subgroups of modular abelian varieties
3
4
Sage can compute with fairly general finite subgroups of modular
5
abelian varieties. Elements of finite order are represented by
6
equivalence classes of elements in `H_1(A,\QQ)`
7
modulo `H_1(A,\ZZ)`. A finite subgroup can be
8
defined by giving generators and via various other constructions.
9
Given a finite subgroup, one can compute generators, as well as the
10
structure as an abstract group. Arithmetic on subgroups is also
11
supported, including adding two subgroups together, checking
12
inclusion, etc.
13
14
TODO: Intersection, action of Hecke operators.
15
16
AUTHORS:
17
18
- William Stein (2007-03)
19
20
EXAMPLES::
21
22
sage: J = J0(33)
23
sage: C = J.cuspidal_subgroup()
24
sage: C
25
Finite subgroup with invariants [10, 10] over QQ of Abelian variety J0(33) of dimension 3
26
sage: C.order()
27
100
28
sage: C.gens()
29
[[(1/10, 0, 1/10, 1/10, 1/10, 3/10)], [(0, 1/5, 1/10, 0, 1/10, 9/10)], [(0, 0, 1/2, 0, 1/2, 1/2)]]
30
sage: C.0 + C.1
31
[(1/10, 1/5, 1/5, 1/10, 1/5, 6/5)]
32
sage: 10*(C.0 + C.1)
33
[(0, 0, 0, 0, 0, 0)]
34
sage: G = C.subgroup([C.0 + C.1]); G
35
Finite subgroup with invariants [10] over QQbar of Abelian variety J0(33) of dimension 3
36
sage: G.gens()
37
[[(1/10, 1/5, 1/5, 1/10, 1/5, 1/5)]]
38
sage: G.order()
39
10
40
sage: G <= C
41
True
42
sage: G >= C
43
False
44
45
We make a table of the order of the cuspidal subgroup for the first
46
few levels::
47
48
sage: for N in range(11,40): print N, J0(N).cuspidal_subgroup().order()
49
...
50
11 5
51
12 1
52
13 1
53
14 6
54
15 8
55
16 1
56
17 4
57
18 1
58
19 3
59
20 6
60
21 8
61
22 25
62
23 11
63
24 8
64
25 1
65
26 21
66
27 9
67
28 36
68
29 7
69
30 192
70
31 5
71
32 8
72
33 100
73
34 48
74
35 48
75
36 12
76
37 3
77
38 135
78
39 56
79
80
TESTS::
81
82
sage: G = J0(11).finite_subgroup([[1/3,0], [0,1/5]]); G
83
Finite subgroup with invariants [15] over QQbar of Abelian variety J0(11) of dimension 1
84
sage: loads(dumps(G)) == G
85
True
86
sage: loads(dumps(G.0)) == G.0
87
True
88
"""
89
90
###########################################################################
91
# Copyright (C) 2007 William Stein <[email protected]> #
92
# Distributed under the terms of the GNU General Public License (GPL) #
93
# http://www.gnu.org/licenses/ #
94
###########################################################################
95
96
from sage.modules.module import Module_old
97
from sage.modules.free_module import is_FreeModule
98
from sage.structure.element import ModuleElement
99
from sage.structure.sequence import Sequence
100
from sage.rings.all import gcd, lcm, QQ, ZZ, QQbar, is_Field, Integer, composite_field
101
from sage.misc.misc import prod
102
103
import abvar as abelian_variety
104
105
class FiniteSubgroup(Module_old):
106
def __init__(self, abvar, field_of_definition=QQ):
107
"""
108
A finite subgroup of a modular abelian variety.
109
110
INPUT:
111
112
113
- ``abvar`` - a modular abelian variety
114
115
- ``field_of_definition`` - a field over which this
116
group is defined.
117
118
119
EXAMPLES: This is an abstract base class, so there are no instances
120
of this class itself.
121
122
::
123
124
sage: A = J0(37)
125
sage: G = A.torsion_subgroup(3); G
126
Finite subgroup with invariants [3, 3, 3, 3] over QQ of Abelian variety J0(37) of dimension 2
127
sage: type(G)
128
<class 'sage.modular.abvar.finite_subgroup.FiniteSubgroup_lattice'>
129
sage: from sage.modular.abvar.finite_subgroup import FiniteSubgroup
130
sage: isinstance(G, FiniteSubgroup)
131
True
132
"""
133
if not is_Field(field_of_definition):
134
raise TypeError, "field_of_definition must be a field"
135
if not abelian_variety.is_ModularAbelianVariety(abvar):
136
raise TypeError, "abvar must be a modular abelian variety"
137
Module_old.__init__(self, ZZ)
138
self.__abvar = abvar
139
self.__field_of_definition = field_of_definition
140
141
################################################################
142
# DERIVED CLASS MUST OVERRIDE THE lattice METHOD
143
################################################################
144
def lattice(self):
145
"""
146
Return the lattice corresponding to this subgroup in the rational
147
homology of the modular Jacobian product. The elements of the
148
subgroup are represented by vectors in the ambient vector space
149
(the rational homology), and this returns the lattice they span.
150
EXAMPLES::
151
152
sage: J = J0(33); C = J[0].cuspidal_subgroup(); C
153
Finite subgroup with invariants [5] over QQ of Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
154
sage: C.lattice()
155
Free module of degree 6 and rank 2 over Integer Ring
156
Echelon basis matrix:
157
[ 1/5 13/5 -2 -4/5 2 -1/5]
158
[ 0 3 -2 -1 2 0]
159
"""
160
raise NotImplementedError
161
162
def _relative_basis_matrix(self):
163
"""
164
Return matrix of this finite subgroup, but relative to the homology
165
of the parent abelian variety.
166
167
EXAMPLES::
168
169
sage: A = J0(43)[1]; A
170
Simple abelian subvariety 43b(1,43) of dimension 2 of J0(43)
171
sage: C = A.cuspidal_subgroup(); C
172
Finite subgroup with invariants [7] over QQ of Simple abelian subvariety 43b(1,43) of dimension 2 of J0(43)
173
sage: C._relative_basis_matrix()
174
[ 1 0 0 0]
175
[ 0 1/7 6/7 5/7]
176
[ 0 0 1 0]
177
[ 0 0 0 1]
178
"""
179
try:
180
return self.__relative_basis_matrix
181
except AttributeError:
182
M = self.__abvar.lattice().coordinate_module(self.lattice()).basis_matrix()
183
self.__relative_basis_matrix = M
184
return M
185
186
# General functionality
187
def __cmp__(self, other):
188
"""
189
Compare this finite subgroup to other.
190
191
If other is not a modular abelian variety finite subgroup, then the
192
types of self and other are compared. If other is a finite
193
subgroup, and the ambient abelian varieties are equal, then the
194
subgroups themselves are compared, by comparing their full modules.
195
If the containing abelian varieties are not equal and their ambient
196
varieties are different they are compared; if they are the same,
197
then a NotImplemnetedError is raised (this is temporary).
198
199
EXAMPLES: We first compare to subgroups of `J_0(37)`::
200
201
sage: A = J0(37)
202
sage: G = A.torsion_subgroup(3); G.order()
203
81
204
sage: H = A.cuspidal_subgroup(); H.order()
205
3
206
sage: H < G
207
True
208
sage: H.is_subgroup(G)
209
True
210
sage: H < 5 #random (meaningless since it depends on memory layout)
211
False
212
sage: 5 < H #random (meaningless since it depends on memory layout)
213
True
214
215
The ambient varieties are compared::
216
217
sage: cmp(A[0].cuspidal_subgroup(), J0(11).cuspidal_subgroup())
218
1
219
220
Comparing subgroups sitting in different abelian varieties::
221
222
sage: cmp(A[0].cuspidal_subgroup(), A[1].cuspidal_subgroup())
223
-1
224
"""
225
if not isinstance(other, FiniteSubgroup):
226
return cmp(type(self), type(other))
227
A = self.abelian_variety()
228
B = other.abelian_variety()
229
if not A.in_same_ambient_variety(B):
230
return cmp(A.ambient_variety(), B.ambient_variety())
231
L = A.lattice() + B.lattice()
232
# Minus sign because order gets reversed in passing to lattices.
233
return -cmp(self.lattice() + L, other.lattice() + L)
234
235
def is_subgroup(self, other):
236
"""
237
Return True exactly if self is a subgroup of other, and both are
238
defined as subgroups of the same ambient abelian variety.
239
240
EXAMPLES::
241
242
sage: C = J0(22).cuspidal_subgroup()
243
sage: H = C.subgroup([C.0])
244
sage: K = C.subgroup([C.1])
245
sage: H.is_subgroup(K)
246
False
247
sage: K.is_subgroup(H)
248
False
249
sage: K.is_subgroup(C)
250
True
251
sage: H.is_subgroup(C)
252
True
253
"""
254
# We use that self is contained in other, whether other is
255
# either a finite group or an abelian variety, if and only
256
# if self doesn't shrink when intersected with other.
257
try:
258
return self.intersection(other).order() == self.order()
259
except TypeError:
260
return False
261
262
def __add__(self, other):
263
"""
264
Return the sum of two subgroups.
265
266
EXAMPLES::
267
268
sage: C = J0(22).cuspidal_subgroup()
269
sage: C.gens()
270
[[(1/5, 1/5, 4/5, 0)], [(0, 0, 0, 1/5)]]
271
sage: A = C.subgroup([C.0]); B = C.subgroup([C.1])
272
sage: A + B == C
273
True
274
"""
275
if not isinstance(other, FiniteSubgroup):
276
raise TypeError, "only addition of two finite subgroups is defined"
277
A = self.abelian_variety()
278
B = other.abelian_variety()
279
if not A.in_same_ambient_variety(B):
280
raise ValueError("self and other must be in the same ambient Jacobian")
281
K = composite_field(self.field_of_definition(), other.field_of_definition())
282
lattice = self.lattice() + other.lattice()
283
if A != B:
284
lattice += C.lattice()
285
286
return FiniteSubgroup_lattice(self.abelian_variety(), lattice, field_of_definition=K)
287
288
def exponent(self):
289
"""
290
Return the exponent of this finite abelian group.
291
292
OUTPUT: Integer
293
294
EXAMPLES::
295
296
sage: t = J0(33).hecke_operator(7)
297
sage: G = t.kernel()[0]; G
298
Finite subgroup with invariants [2, 2, 2, 2, 4, 4] over QQ of Abelian variety J0(33) of dimension 3
299
sage: G.exponent()
300
4
301
"""
302
try:
303
return self.__exponent
304
except AttributeError:
305
e = lcm(self.invariants())
306
self.__exponent = e
307
return e
308
309
def intersection(self, other):
310
"""
311
Return the intersection of the finite subgroups self and other.
312
313
INPUT:
314
315
316
- ``other`` - a finite group
317
318
319
OUTPUT: a finite group
320
321
EXAMPLES::
322
323
sage: E11a0, E11a1, B = J0(33)
324
sage: G = E11a0.torsion_subgroup(6); H = E11a0.torsion_subgroup(9)
325
sage: G.intersection(H)
326
Finite subgroup with invariants [3, 3] over QQ of Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
327
sage: W = E11a1.torsion_subgroup(15)
328
sage: G.intersection(W)
329
Finite subgroup with invariants [] over QQ of Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
330
sage: E11a0.intersection(E11a1)[0]
331
Finite subgroup with invariants [5] over QQ of Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
332
333
We intersect subgroups of different abelian varieties.
334
335
::
336
337
sage: E11a0, E11a1, B = J0(33)
338
sage: G = E11a0.torsion_subgroup(5); H = E11a1.torsion_subgroup(5)
339
sage: G.intersection(H)
340
Finite subgroup with invariants [5] over QQ of Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
341
sage: E11a0.intersection(E11a1)[0]
342
Finite subgroup with invariants [5] over QQ of Simple abelian subvariety 11a(1,33) of dimension 1 of J0(33)
343
344
We intersect abelian varieties with subgroups::
345
346
sage: t = J0(33).hecke_operator(7)
347
sage: G = t.kernel()[0]; G
348
Finite subgroup with invariants [2, 2, 2, 2, 4, 4] over QQ of Abelian variety J0(33) of dimension 3
349
sage: A = J0(33).old_subvariety()
350
sage: A.intersection(G)
351
Finite subgroup with invariants [2, 2, 2, 2] over QQ of Abelian subvariety of dimension 2 of J0(33)
352
sage: A.hecke_operator(7).kernel()[0]
353
Finite subgroup with invariants [2, 2, 2, 2] over QQ of Abelian subvariety of dimension 2 of J0(33)
354
sage: B = J0(33).new_subvariety()
355
sage: B.intersection(G)
356
Finite subgroup with invariants [4, 4] over QQ of Abelian subvariety of dimension 1 of J0(33)
357
sage: B.hecke_operator(7).kernel()[0]
358
Finite subgroup with invariants [4, 4] over QQ of Abelian subvariety of dimension 1 of J0(33)
359
sage: A.intersection(B)[0]
360
Finite subgroup with invariants [3, 3] over QQ of Abelian subvariety of dimension 2 of J0(33)
361
"""
362
A = self.abelian_variety()
363
if abelian_variety.is_ModularAbelianVariety(other):
364
amb = other
365
B = other
366
M = B.lattice().scale(Integer(1)/self.exponent())
367
K = composite_field(self.field_of_definition(), other.base_field())
368
else:
369
amb = A
370
if not isinstance(other, FiniteSubgroup):
371
raise TypeError, "only addition of two finite subgroups is defined"
372
B = other.abelian_variety()
373
if A.ambient_variety() != B.ambient_variety():
374
raise TypeError, "finite subgroups must be in the same ambient product Jacobian"
375
M = other.lattice()
376
K = composite_field(self.field_of_definition(), other.field_of_definition())
377
378
L = self.lattice()
379
if A != B:
380
# TODO: This might be way slower than what we could do if
381
# we think more carefully.
382
C = A + B
383
L = L + C.lattice()
384
M = M + C.lattice()
385
W = L.intersection(M).intersection(amb.vector_space())
386
return FiniteSubgroup_lattice(amb, W, field_of_definition=K)
387
388
def __mul__(self, right):
389
"""
390
Multiply this subgroup by the rational number right.
391
392
If right is an integer the result is a subgroup of self. If right
393
is a rational number `n/m`, then this group is first
394
divided by `m` then multiplied by `n`.
395
396
INPUT:
397
398
399
- ``right`` - a rational number
400
401
402
OUTPUT: a subgroup
403
404
EXAMPLES::
405
406
sage: J = J0(37)
407
sage: H = J.cuspidal_subgroup(); H.order()
408
3
409
sage: G = H * 3; G.order()
410
1
411
sage: G = H * (1/2); G.order()
412
48
413
sage: J.torsion_subgroup(2) + H == G
414
True
415
sage: G = H*(3/2); G.order()
416
16
417
sage: J = J0(42)
418
sage: G = J.cuspidal_subgroup(); factor(G.order())
419
2^8 * 3^2
420
sage: (G * 3).order()
421
256
422
sage: (G * 0).order()
423
1
424
sage: (G * (1/5)).order()
425
22500000000
426
"""
427
lattice = self.lattice().scale(right)
428
return FiniteSubgroup_lattice(self.abelian_variety(), lattice,
429
field_of_definition = self.field_of_definition())
430
431
def __rmul__(self, left):
432
"""
433
Multiply this finite subgroup on the left by an integer.
434
435
EXAMPLES::
436
437
sage: J = J0(42)
438
sage: G = J.cuspidal_subgroup(); factor(G.order())
439
2^8 * 3^2
440
sage: H = G.__rmul__(2)
441
sage: H.order().factor()
442
2^4 * 3^2
443
sage: 2*G
444
Finite subgroup with invariants [6, 24] over QQ of Abelian variety J0(42) of dimension 5
445
"""
446
return self * left
447
448
def abelian_variety(self):
449
"""
450
Return the abelian variety that this is a finite subgroup of.
451
452
EXAMPLES::
453
454
sage: J = J0(42)
455
sage: G = J.rational_torsion_subgroup(); G
456
Torsion subgroup of Abelian variety J0(42) of dimension 5
457
sage: G.abelian_variety()
458
Abelian variety J0(42) of dimension 5
459
"""
460
return self.__abvar
461
462
def field_of_definition(self):
463
"""
464
Return the field over which this finite modular abelian variety
465
subgroup is defined. This is a field over which this subgroup is
466
defined.
467
468
EXAMPLES::
469
470
sage: J = J0(42)
471
sage: G = J.rational_torsion_subgroup(); G
472
Torsion subgroup of Abelian variety J0(42) of dimension 5
473
sage: G.field_of_definition()
474
Rational Field
475
"""
476
return self.__field_of_definition
477
478
def _repr_(self):
479
"""
480
Return string representation of this finite subgroup.
481
482
EXAMPLES::
483
484
sage: J = J0(42)
485
sage: G = J.torsion_subgroup(3); G._repr_()
486
'Finite subgroup with invariants [3, 3, 3, 3, 3, 3, 3, 3, 3, 3] over QQ of Abelian variety J0(42) of dimension 5'
487
"""
488
K = self.__field_of_definition
489
if K == QQbar:
490
field = "QQbar"
491
elif K == QQ:
492
field = "QQ"
493
else:
494
field = str(K)
495
return "Finite subgroup %sover %s of %s"%(self._invariants_repr(), field, self.__abvar)
496
497
def _invariants_repr(self):
498
"""
499
The string representation of the 'invariants' part of this group.
500
501
We make this a separate function so it is possible to create finite
502
subgroups that don't print their invariants, since printing them
503
could be expensive.
504
505
EXAMPLES::
506
507
sage: J0(42).cuspidal_subgroup()._invariants_repr()
508
'with invariants [2, 2, 12, 48] '
509
"""
510
return 'with invariants %s '%(self.invariants(), )
511
512
def order(self):
513
"""
514
Return the order (number of elements) of this finite subgroup.
515
516
EXAMPLES::
517
518
sage: J = J0(42)
519
sage: C = J.cuspidal_subgroup()
520
sage: C.order()
521
2304
522
"""
523
try:
524
return self.__order
525
except AttributeError:
526
if self.__abvar.dimension() == 0:
527
self.__order = ZZ(1)
528
return self.__order
529
o = prod(self.invariants())
530
self.__order = o
531
return o
532
533
def gens(self):
534
"""
535
Return generators for this finite subgroup.
536
537
EXAMPLES: We list generators for several cuspidal subgroups::
538
539
sage: J0(11).cuspidal_subgroup().gens()
540
[[(0, 1/5)]]
541
sage: J0(37).cuspidal_subgroup().gens()
542
[[(0, 0, 0, 1/3)]]
543
sage: J0(43).cuspidal_subgroup().gens()
544
[[(0, 1/7, 0, 6/7, 0, 5/7)]]
545
sage: J1(13).cuspidal_subgroup().gens()
546
[[(1/19, 0, 0, 9/19)], [(0, 1/19, 1/19, 18/19)]]
547
sage: J0(22).torsion_subgroup(6).gens()
548
[[(1/6, 0, 0, 0)], [(0, 1/6, 0, 0)], [(0, 0, 1/6, 0)], [(0, 0, 0, 1/6)]]
549
"""
550
try:
551
return self.__gens
552
except AttributeError:
553
pass
554
555
B = [TorsionPoint(self, v) for v in self.lattice().basis() if v.denominator() > 1]
556
self.__gens = Sequence(B, immutable=True)
557
return self.__gens
558
559
def gen(self, n):
560
r"""
561
Return `n^{th}` generator of self.
562
563
EXAMPLES::
564
565
sage: J = J0(23)
566
sage: C = J.torsion_subgroup(3)
567
sage: C.gens()
568
[[(1/3, 0, 0, 0)], [(0, 1/3, 0, 0)], [(0, 0, 1/3, 0)], [(0, 0, 0, 1/3)]]
569
sage: C.gen(0)
570
[(1/3, 0, 0, 0)]
571
sage: C.gen(3)
572
[(0, 0, 0, 1/3)]
573
sage: C.gen(4)
574
Traceback (most recent call last):
575
...
576
IndexError: list index out of range
577
578
Negative indices wrap around::
579
580
sage: C.gen(-1)
581
[(0, 0, 0, 1/3)]
582
"""
583
return self.gens()[n]
584
585
def __call__(self, x):
586
r"""
587
Coerce `x` into this finite subgroup.
588
589
This works when the abelian varieties that contains x and self are
590
the same, or if `x` is coercible into the rational homology
591
(viewed as an abstract `\QQ`-vector space).
592
593
EXAMPLES: We first construct the `11`-torsion subgroup of
594
`J_0(23)`::
595
596
sage: J = J0(23)
597
sage: G = J.torsion_subgroup(11)
598
sage: G.invariants()
599
[11, 11, 11, 11]
600
601
We also construct the cuspidal subgroup.
602
603
::
604
605
sage: C = J.cuspidal_subgroup()
606
sage: C.invariants()
607
[11]
608
609
Coercing something into its parent returns it::
610
611
sage: G(G.0) is G.0
612
True
613
614
We coerce an element from the cuspidal subgroup into the
615
`11`-torsion subgroup::
616
617
sage: z = G(C.0); z
618
[(1/11, 10/11, 0, 8/11)]
619
sage: z.parent() == G
620
True
621
622
We coerce a list, which defines an element of the underlying
623
``full_module`` into `G`, and verify an
624
equality::
625
626
sage: x = G([1/11, 1/11, 0, -1/11])
627
sage: x == G([1/11, 1/11, 0, 10/11])
628
True
629
630
Finally we attempt to coerce in an element that shouldn't work,
631
since is is not in `G`::
632
633
sage: G(J.torsion_subgroup(3).0)
634
Traceback (most recent call last):
635
...
636
TypeError: x does not define an element of self
637
"""
638
if isinstance(x, TorsionPoint):
639
if x.parent() is self:
640
return x
641
elif x.parent() == self:
642
return TorsionPoint(self, x.element(), check=False)
643
elif x.parent().abelian_variety() == self.abelian_variety():
644
return self(x.element())
645
else:
646
raise TypeError, "x does not define an element of self"
647
else:
648
z = self.abelian_variety().vector_space()(x)
649
if not z in self.lattice():
650
raise TypeError, "x does not define an element of self"
651
return TorsionPoint(self, z, check=False)
652
653
654
def __contains__(self, x):
655
"""
656
Returns True if x is contained in this finite subgroup.
657
658
EXAMPLES: We define two distinct finite subgroups of
659
`J_0(27)`::
660
661
sage: G1 = J0(27).rational_cusp_subgroup(); G1
662
Finite subgroup with invariants [3] over QQ of Abelian variety J0(27) of dimension 1
663
sage: G1.0
664
[(1/3, 0)]
665
sage: G2 = J0(27).cuspidal_subgroup(); G2
666
Finite subgroup with invariants [3, 3] over QQ of Abelian variety J0(27) of dimension 1
667
sage: G2.gens()
668
[[(1/3, 0)], [(0, 1/3)]]
669
670
Now we check whether various elements are in `G_1` and
671
`G_2`::
672
673
sage: G2.0 in G1
674
True
675
sage: G2.1 in G1
676
False
677
sage: G1.0 in G1
678
True
679
sage: G1.0 in G2
680
True
681
682
The integer `0` is in, since it coerces in::
683
684
sage: 0 in G1
685
True
686
687
Elements that have a completely different ambient product Jacobian
688
are never in `G`::
689
690
sage: J0(23).cuspidal_subgroup().0 in G1
691
False
692
sage: J0(23).cuspidal_subgroup()(0) in G1
693
False
694
"""
695
try:
696
self(x)
697
except TypeError:
698
return False
699
return True
700
701
def subgroup(self, gens):
702
"""
703
Return the subgroup of self spanned by the given generators, which
704
all must be elements of self.
705
706
EXAMPLES::
707
708
sage: J = J0(23)
709
sage: G = J.torsion_subgroup(11); G
710
Finite subgroup with invariants [11, 11, 11, 11] over QQ of Abelian variety J0(23) of dimension 2
711
712
We create the subgroup of the 11-torsion subgroup of
713
`J_0(23)` generated by the first `11`-torsion
714
point::
715
716
sage: H = G.subgroup([G.0]); H
717
Finite subgroup with invariants [11] over QQbar of Abelian variety J0(23) of dimension 2
718
sage: H.invariants()
719
[11]
720
721
We can also create a subgroup from a list of objects that coerce
722
into the ambient rational homology.
723
724
::
725
726
sage: H == G.subgroup([[1/11,0,0,0]])
727
True
728
"""
729
if not isinstance(gens, (tuple, list)):
730
raise TypeError, "gens must be a list or tuple"
731
A = self.abelian_variety()
732
lattice = A._ambient_lattice().span([self(g).element() for g in gens])
733
return FiniteSubgroup_lattice(self.abelian_variety(), lattice, field_of_definition=QQbar)
734
735
def invariants(self):
736
r"""
737
Return elementary invariants of this abelian group, by which we
738
mean a nondecreasing (immutable) sequence of integers
739
`n_i`, `1 \leq i \leq k`, with `n_i`
740
dividing `n_{i+1}`, and such that this group is abstractly
741
isomorphic to
742
`\ZZ/n_1\ZZ \times\cdots\times \ZZ/n_k\ZZ.`
743
744
EXAMPLES::
745
746
sage: J = J0(38)
747
sage: C = J.cuspidal_subgroup(); C
748
Finite subgroup with invariants [3, 45] over QQ of Abelian variety J0(38) of dimension 4
749
sage: v = C.invariants(); v
750
[3, 45]
751
sage: v[0] = 5
752
Traceback (most recent call last):
753
...
754
ValueError: object is immutable; please change a copy instead.
755
sage: type(v[0])
756
<type 'sage.rings.integer.Integer'>
757
758
::
759
760
sage: C * 3
761
Finite subgroup with invariants [15] over QQ of Abelian variety J0(38) of dimension 4
762
763
An example involving another cuspidal subgroup::
764
765
sage: C = J0(22).cuspidal_subgroup(); C
766
Finite subgroup with invariants [5, 5] over QQ of Abelian variety J0(22) of dimension 2
767
sage: C.lattice()
768
Free module of degree 4 and rank 4 over Integer Ring
769
Echelon basis matrix:
770
[1/5 1/5 4/5 0]
771
[ 0 1 0 0]
772
[ 0 0 1 0]
773
[ 0 0 0 1/5]
774
sage: C.invariants()
775
[5, 5]
776
"""
777
try:
778
return self.__invariants
779
except AttributeError:
780
pass
781
M = self.lattice().coordinate_module(self.abelian_variety().lattice())
782
E = M.basis_matrix().change_ring(ZZ).elementary_divisors()
783
v = [Integer(x) for x in E if x != 1]
784
I = Sequence(v)
785
I.sort()
786
I.set_immutable()
787
self.__invariants = I
788
return I
789
790
class FiniteSubgroup_lattice(FiniteSubgroup):
791
def __init__(self, abvar, lattice, field_of_definition=QQbar, check=True):
792
"""
793
A finite subgroup of a modular abelian variety that is defined by a
794
given lattice.
795
796
INPUT:
797
798
799
- ``abvar`` - a modular abelian variety
800
801
- ``lattice`` - a lattice that contains the lattice of
802
abvar
803
804
- ``field_of_definition`` - the field of definition
805
of this finite group scheme
806
807
- ``check`` - bool (default: True) whether or not to
808
check that lattice contains the abvar lattice.
809
810
811
EXAMPLES::
812
813
sage: J = J0(11)
814
sage: G = J.finite_subgroup([[1/3,0], [0,1/5]]); G
815
Finite subgroup with invariants [15] over QQbar of Abelian variety J0(11) of dimension 1
816
"""
817
if check:
818
if not is_FreeModule(lattice) or lattice.base_ring() != ZZ:
819
raise TypeError, "lattice must be a free module over ZZ"
820
if not abelian_variety.is_ModularAbelianVariety(abvar):
821
raise TypeError, "abvar must be a modular abelian variety"
822
if not abvar.lattice().is_submodule(lattice):
823
lattice += abvar.lattice()
824
if lattice.rank() != abvar.lattice().rank():
825
raise ValueError, "lattice must contain the lattice of abvar with finite index"
826
FiniteSubgroup.__init__(self, abvar, field_of_definition)
827
self.__lattice = lattice
828
829
def lattice(self):
830
r"""
831
Return lattice that defines this finite subgroup.
832
833
EXAMPLES::
834
835
sage: J = J0(11)
836
sage: G = J.finite_subgroup([[1/3,0], [0,1/5]]); G
837
Finite subgroup with invariants [15] over QQbar of Abelian variety J0(11) of dimension 1
838
sage: G.lattice()
839
Free module of degree 2 and rank 2 over Integer Ring
840
Echelon basis matrix:
841
[1/3 0]
842
[ 0 1/5]
843
"""
844
return self.__lattice
845
846
###########################################################################
847
# Elements of finite order
848
###########################################################################
849
850
class TorsionPoint(ModuleElement):
851
def __init__(self, parent, element, check=True):
852
"""
853
An element of a finite subgroup of a modular abelian variety.
854
855
INPUT:
856
857
858
- ``parent`` - a finite subgroup of a modular abelian
859
variety
860
861
- ``element`` - a QQ vector space element that
862
represents this element in terms of the ambient rational homology
863
864
- ``check`` - bool (default: True) whether to check
865
that element is in the appropriate vector space
866
867
868
EXAMPLES: The following calls the TorsionPoint constructor
869
implicitly::
870
871
sage: J = J0(11)
872
sage: G = J.finite_subgroup([[1/3,0], [0,1/5]]); G
873
Finite subgroup with invariants [15] over QQbar of Abelian variety J0(11) of dimension 1
874
sage: type(G.0)
875
<class 'sage.modular.abvar.finite_subgroup.TorsionPoint'>
876
"""
877
ModuleElement.__init__(self, parent)
878
if check:
879
if not element in parent.abelian_variety().vector_space():
880
raise TypeError, "element must be a vector in the abelian variety's rational homology (embedded in the ambient Jacobian product)"
881
if element.denominator() == 1:
882
element = element.parent().zero_vector()
883
self.__element = element
884
885
def element(self):
886
"""
887
Return an underlying QQ-vector space element that defines this
888
element of a modular abelian variety. This is a vector in the
889
ambient Jacobian variety's rational homology.
890
891
EXAMPLES: We create some elements of `J_0(11)`::
892
893
sage: J = J0(11)
894
sage: G = J.finite_subgroup([[1/3,0], [0,1/5]]); G
895
Finite subgroup with invariants [15] over QQbar of Abelian variety J0(11) of dimension 1
896
sage: G.0.element()
897
(1/3, 0)
898
899
The underlying element is a vector over the rational numbers::
900
901
sage: v = (G.0-G.1).element(); v
902
(1/3, -1/5)
903
sage: type(v)
904
<type 'sage.modules.vector_rational_dense.Vector_rational_dense'>
905
"""
906
return self.__element
907
908
def _repr_(self):
909
r"""
910
Return string representation of this finite subgroup element. Since
911
they are represented as equivalences classes of rational homology
912
modulo integral homology, we represent an element corresponding to
913
`v` in the rational homology by ``[v]``.
914
915
EXAMPLES::
916
917
sage: J = J0(11)
918
sage: G = J.finite_subgroup([[1/3,0], [0,1/5]]); G
919
Finite subgroup with invariants [15] over QQbar of Abelian variety J0(11) of dimension 1
920
sage: G.0._repr_()
921
'[(1/3, 0)]'
922
"""
923
return '[%s]'%self.__element
924
925
def _add_(self, other):
926
"""
927
Add two finite subgroup elements with the same parent. This is
928
called implicitly by +.
929
930
INPUT:
931
932
933
- ``other`` - a TorsionPoint with the same parent as
934
self
935
936
937
OUTPUT: a TorsionPoint
938
939
EXAMPLES::
940
941
sage: J = J0(11); G = J.finite_subgroup([[1/3,0], [0,1/5]])
942
sage: G.0._add_(G.1)
943
[(1/3, 1/5)]
944
sage: G.0 + G.1
945
[(1/3, 1/5)]
946
"""
947
return TorsionPoint(self.parent(), self.__element + other.__element, check=False)
948
949
def _sub_(self, other):
950
"""
951
Subtract two finite subgroup elements with the same parent. This is
952
called implicitly by +.
953
954
INPUT:
955
956
957
- ``other`` - a TorsionPoint with the same parent as
958
self
959
960
961
OUTPUT: a TorsionPoint
962
963
EXAMPLES::
964
965
sage: J = J0(11); G = J.finite_subgroup([[1/3,0], [0,1/5]])
966
sage: G.0._sub_(G.1)
967
[(1/3, -1/5)]
968
sage: G.0 - G.1
969
[(1/3, -1/5)]
970
"""
971
return TorsionPoint(self.parent(), self.__element - other.__element, check=False)
972
973
def _neg_(self):
974
"""
975
Negate a finite subgroup element.
976
977
EXAMPLES::
978
979
sage: J = J0(11); G = J.finite_subgroup([[1/3,0], [0,1/5]])
980
sage: G.0._neg_()
981
[(-1/3, 0)]
982
"""
983
return TorsionPoint(self.parent(), -self.__element, check=False)
984
985
def _rmul_(self, left):
986
"""
987
Left multiply a finite subgroup element by an integer.
988
989
EXAMPLES::
990
991
sage: J = J0(11); G = J.finite_subgroup([[1/3,0], [0,1/5]])
992
sage: G.0._rmul_(2)
993
[(2/3, 0)]
994
sage: 2*G.0
995
[(2/3, 0)]
996
"""
997
return TorsionPoint(self.parent(), ZZ(left) * self.__element, check=False)
998
999
def _lmul_(self, right):
1000
"""
1001
Right multiply a finite subgroup element by an integer.
1002
1003
EXAMPLES::
1004
1005
sage: J = J0(11); G = J.finite_subgroup([[1/3,0], [0,1/5]])
1006
sage: G.0._lmul_(2)
1007
[(2/3, 0)]
1008
sage: G.0 * 2
1009
[(2/3, 0)]
1010
"""
1011
return TorsionPoint(self.parent(), self.__element * right, check=False)
1012
1013
def __cmp__(self, right):
1014
"""
1015
Compare self and right.
1016
1017
INPUT:
1018
1019
1020
- ``self, right`` - elements of the same finite
1021
abelian variety subgroup.
1022
1023
1024
OUTPUT: -1, 0, or 1
1025
1026
EXAMPLES::
1027
1028
sage: J = J0(11); G = J.finite_subgroup([[1/3,0], [0,1/5]])
1029
sage: cmp(G.0, G.1)
1030
1
1031
sage: cmp(G.0, G.0)
1032
0
1033
sage: 3*G.0 == 0
1034
True
1035
sage: 3*G.0 == 5*G.1
1036
True
1037
1038
We make sure things that shouldn't be equal aren't::
1039
1040
sage: H = J0(14).finite_subgroup([[1/3,0]])
1041
sage: G.0 == H.0
1042
False
1043
sage: cmp(G.0, H.0)
1044
-1
1045
sage: G.0
1046
[(1/3, 0)]
1047
sage: H.0
1048
[(1/3, 0)]
1049
"""
1050
if not isinstance(right, TorsionPoint):
1051
return cmp(type(self), type(right))
1052
A = self.parent().abelian_variety()
1053
B = right.parent().abelian_variety()
1054
if A.groups() != B.groups():
1055
return cmp(A,B)
1056
elif self.__element.change_ring(QQ) - right.__element.change_ring(QQ) in A.lattice() + B.lattice():
1057
return 0
1058
else:
1059
return cmp(self.__element, right.__element)
1060
1061
def additive_order(self):
1062
"""
1063
Return the additive order of this element.
1064
1065
EXAMPLES::
1066
1067
sage: J = J0(11); G = J.finite_subgroup([[1/3,0], [0,1/5]])
1068
sage: G.0.additive_order()
1069
3
1070
sage: G.1.additive_order()
1071
5
1072
sage: (G.0 + G.1).additive_order()
1073
15
1074
sage: (3*G.0).additive_order()
1075
1
1076
"""
1077
return self._relative_element().denominator()
1078
1079
def _relative_element(self):
1080
"""
1081
Return coordinates of this element in terms of basis for the
1082
integral homology of the containing abelian variety.
1083
1084
OUTPUT: vector
1085
1086
EXAMPLES::
1087
1088
sage: A = J0(43)[1]; A
1089
Simple abelian subvariety 43b(1,43) of dimension 2 of J0(43)
1090
sage: C = A.cuspidal_subgroup(); C
1091
Finite subgroup with invariants [7] over QQ of Simple abelian subvariety 43b(1,43) of dimension 2 of J0(43)
1092
sage: x = C.0; x
1093
[(0, 1/7, 0, 6/7, 0, 5/7)]
1094
sage: x._relative_element()
1095
(0, 1/7, 6/7, 5/7)
1096
"""
1097
return self.parent().abelian_variety().lattice().coordinate_vector(self.__element)
1098
1099
1100