Torsion subgroups of modular abelian varieties¶
Sage can compute information about the structure of the torsion subgroup of a modular abelian variety. Sage computes a multiple of the order by computing the greatest common divisor of the orders of the torsion subgroup of the reduction of the abelian variety modulo p for various primes p. Sage computes a divisor of the order by computing the rational cuspidal subgroup. When these two bounds agree (which is often the case), we determine the exact structure of the torsion subgroup.
AUTHORS:
- William Stein (2007-03) 
EXAMPLES: First we consider \(J_0(50)\) where everything works out nicely:
sage: J = J0(50)
sage: T = J.rational_torsion_subgroup(); T
Torsion subgroup of Abelian variety J0(50) of dimension 2
sage: T.multiple_of_order()
15
sage: T.divisor_of_order()
15
sage: T.gens()
[[(1/15, 3/5, 2/5, 14/15)]]
sage: T.invariants()
[15]
sage: d = J.decomposition(); d
[Simple abelian subvariety 50a(1,50) of dimension 1 of J0(50),
 Simple abelian subvariety 50b(1,50) of dimension 1 of J0(50)]
sage: d[0].rational_torsion_subgroup().order()
3
sage: d[1].rational_torsion_subgroup().order()
5
>>> from sage.all import *
>>> J = J0(Integer(50))
>>> T = J.rational_torsion_subgroup(); T
Torsion subgroup of Abelian variety J0(50) of dimension 2
>>> T.multiple_of_order()
15
>>> T.divisor_of_order()
15
>>> T.gens()
[[(1/15, 3/5, 2/5, 14/15)]]
>>> T.invariants()
[15]
>>> d = J.decomposition(); d
[Simple abelian subvariety 50a(1,50) of dimension 1 of J0(50),
 Simple abelian subvariety 50b(1,50) of dimension 1 of J0(50)]
>>> d[Integer(0)].rational_torsion_subgroup().order()
3
>>> d[Integer(1)].rational_torsion_subgroup().order()
5
Next we make a table of the upper and lower bounds for each new factor.
sage: for N in range(1,38):
....:    for A in J0(N).new_subvariety().decomposition():
....:        T = A.rational_torsion_subgroup()
....:        print('%-5s%-5s%-5s%-5s'%(N, A.dimension(), T.divisor_of_order(), T.multiple_of_order()))
11   1    5    5
14   1    6    6
15   1    8    8
17   1    4    4
19   1    3    3
20   1    6    6
21   1    8    8
23   2    11   11
24   1    8    8
26   1    3    3
26   1    7    7
27   1    3    3
29   2    7    7
30   1    6    6
31   2    5    5
32   1    4    4
33   1    4    4
34   1    6    6
35   1    3    3
35   2    16   16
36   1    6    6
37   1    1    1
37   1    3    3
>>> from sage.all import *
>>> for N in range(Integer(1),Integer(38)):
...    for A in J0(N).new_subvariety().decomposition():
...        T = A.rational_torsion_subgroup()
...        print('%-5s%-5s%-5s%-5s'%(N, A.dimension(), T.divisor_of_order(), T.multiple_of_order()))
11   1    5    5
14   1    6    6
15   1    8    8
17   1    4    4
19   1    3    3
20   1    6    6
21   1    8    8
23   2    11   11
24   1    8    8
26   1    3    3
26   1    7    7
27   1    3    3
29   2    7    7
30   1    6    6
31   2    5    5
32   1    4    4
33   1    4    4
34   1    6    6
35   1    3    3
35   2    16   16
36   1    6    6
37   1    1    1
37   1    3    3
- class sage.modular.abvar.torsion_subgroup.QQbarTorsionSubgroup(abvar)[source]¶
- Bases: - Module- Group of all torsion points over the algebraic closure on an abelian variety. - INPUT: - abvar– an abelian variety
 - EXAMPLES: - sage: A = J0(23) sage: A.qbar_torsion_subgroup() # needs sage.rings.number_field Group of all torsion points in QQbar on Abelian variety J0(23) of dimension 2 - >>> from sage.all import * >>> A = J0(Integer(23)) >>> A.qbar_torsion_subgroup() # needs sage.rings.number_field Group of all torsion points in QQbar on Abelian variety J0(23) of dimension 2 - abelian_variety()[source]¶
- Return the abelian variety that this is the set of all torsion points on. - OUTPUT: abelian variety - EXAMPLES: - sage: J0(23).qbar_torsion_subgroup().abelian_variety() # needs sage.rings.number_field Abelian variety J0(23) of dimension 2 - >>> from sage.all import * >>> J0(Integer(23)).qbar_torsion_subgroup().abelian_variety() # needs sage.rings.number_field Abelian variety J0(23) of dimension 2 
 - field_of_definition()[source]¶
- Return the field of definition of this subgroup. Since this is the group of all torsion it is defined over the base field of this abelian variety. - OUTPUT: a field - EXAMPLES: - sage: J0(23).qbar_torsion_subgroup().field_of_definition() # needs sage.rings.number_field Rational Field - >>> from sage.all import * >>> J0(Integer(23)).qbar_torsion_subgroup().field_of_definition() # needs sage.rings.number_field Rational Field 
 
- class sage.modular.abvar.torsion_subgroup.RationalTorsionSubgroup(abvar)[source]¶
- Bases: - FiniteSubgroup- The torsion subgroup of a modular abelian variety. - divisor_of_order()[source]¶
- Return a divisor of the order of this torsion subgroup of a modular abelian variety. - OUTPUT: a divisor of this torsion subgroup - EXAMPLES: - sage: t = J0(37)[1].rational_torsion_subgroup() sage: t.divisor_of_order() 3 sage: J = J1(19) sage: J.rational_torsion_subgroup().divisor_of_order() 4383 sage: J = J0(45) sage: J.rational_cusp_subgroup().order() 32 sage: J.rational_cuspidal_subgroup().order() 64 sage: J.rational_torsion_subgroup().divisor_of_order() 64 - >>> from sage.all import * >>> t = J0(Integer(37))[Integer(1)].rational_torsion_subgroup() >>> t.divisor_of_order() 3 >>> J = J1(Integer(19)) >>> J.rational_torsion_subgroup().divisor_of_order() 4383 >>> J = J0(Integer(45)) >>> J.rational_cusp_subgroup().order() 32 >>> J.rational_cuspidal_subgroup().order() 64 >>> J.rational_torsion_subgroup().divisor_of_order() 64 
 - lattice()[source]¶
- Return lattice that defines this torsion subgroup, if possible. - Warning - There is no known algorithm in general to compute the rational torsion subgroup. Use rational_cusp_group to obtain a subgroup of the rational torsion subgroup in general. - EXAMPLES: - sage: J0(11).rational_torsion_subgroup().lattice() Free module of degree 2 and rank 2 over Integer Ring Echelon basis matrix: [ 1 0] [ 0 1/5] - >>> from sage.all import * >>> J0(Integer(11)).rational_torsion_subgroup().lattice() Free module of degree 2 and rank 2 over Integer Ring Echelon basis matrix: [ 1 0] [ 0 1/5] - The following fails because in fact I know of no (reasonable) algorithm to provably compute the torsion subgroup in general. - sage: T = J0(33).rational_torsion_subgroup() sage: T.lattice() Traceback (most recent call last): ... NotImplementedError: unable to compute the rational torsion subgroup in this case (there is no known general algorithm yet) - >>> from sage.all import * >>> T = J0(Integer(33)).rational_torsion_subgroup() >>> T.lattice() Traceback (most recent call last): ... NotImplementedError: unable to compute the rational torsion subgroup in this case (there is no known general algorithm yet) - The problem is that the multiple of the order obtained by counting points over finite fields is twice the divisor of the order got from the rational cuspidal subgroup. - sage: T.multiple_of_order(30) 200 sage: J0(33).rational_cusp_subgroup().order() 100 - >>> from sage.all import * >>> T.multiple_of_order(Integer(30)) 200 >>> J0(Integer(33)).rational_cusp_subgroup().order() 100 
 - multiple_of_order(maxp=None, proof=True)[source]¶
- Return a multiple of the order. - INPUT: - proof– boolean (default:- True)
 - The computation of the rational torsion order of J1(p) is conjectural and will only be used if proof=False. See Section 6.2.3 of [CES2003]. - EXAMPLES: - sage: J = J1(11); J Abelian variety J1(11) of dimension 1 sage: J.rational_torsion_subgroup().multiple_of_order() 5 sage: J = J0(17) sage: J.rational_torsion_subgroup().order() 4 - >>> from sage.all import * >>> J = J1(Integer(11)); J Abelian variety J1(11) of dimension 1 >>> J.rational_torsion_subgroup().multiple_of_order() 5 >>> J = J0(Integer(17)) >>> J.rational_torsion_subgroup().order() 4 - This is an example where proof=False leads to a better bound and better performance. - sage: J = J1(23) sage: J.rational_torsion_subgroup().multiple_of_order() # long time (2s) 9406793 sage: J.rational_torsion_subgroup().multiple_of_order(proof=False) 408991 - >>> from sage.all import * >>> J = J1(Integer(23)) >>> J.rational_torsion_subgroup().multiple_of_order() # long time (2s) 9406793 >>> J.rational_torsion_subgroup().multiple_of_order(proof=False) 408991 
 - multiple_of_order_using_frobp(maxp=None)[source]¶
- Return a multiple of the order of this torsion group. - In the \(Gamma_0\) case, the multiple is computed using characteristic polynomials of Hecke operators of odd index not dividing the level. In the \(Gamma_1\) case, the multiple is computed by expressing the frobenius polynomial in terms of the characteristic polynomial of left multiplication by \(a_p\) for odd primes p not dividing the level. - INPUT: - maxp– (default:- None) if- maxpis- None, return gcd of best bound computed so far with bound obtained by computing GCD’s of orders modulo \(p\) until this gcd stabilizes for 3 successive primes. If- maxpis given, just use all primes up to and including- maxp.
 - EXAMPLES: - sage: J = J0(11) sage: G = J.rational_torsion_subgroup() sage: G.multiple_of_order_using_frobp(11) 5 - >>> from sage.all import * >>> J = J0(Integer(11)) >>> G = J.rational_torsion_subgroup() >>> G.multiple_of_order_using_frobp(Integer(11)) 5 - Increasing maxp may yield a tighter bound. If maxp=None, then Sage will use more primes until the multiple stabilizes for 3 successive primes. - sage: J = J0(389) sage: G = J.rational_torsion_subgroup(); G Torsion subgroup of Abelian variety J0(389) of dimension 32 sage: G.multiple_of_order_using_frobp() 97 sage: [G.multiple_of_order_using_frobp(p) for p in prime_range(3,11)] [92645296242160800, 7275, 291] sage: [G.multiple_of_order_using_frobp(p) for p in prime_range(3,13)] [92645296242160800, 7275, 291, 97] sage: [G.multiple_of_order_using_frobp(p) for p in prime_range(3,19)] [92645296242160800, 7275, 291, 97, 97, 97] - >>> from sage.all import * >>> J = J0(Integer(389)) >>> G = J.rational_torsion_subgroup(); G Torsion subgroup of Abelian variety J0(389) of dimension 32 >>> G.multiple_of_order_using_frobp() 97 >>> [G.multiple_of_order_using_frobp(p) for p in prime_range(Integer(3),Integer(11))] [92645296242160800, 7275, 291] >>> [G.multiple_of_order_using_frobp(p) for p in prime_range(Integer(3),Integer(13))] [92645296242160800, 7275, 291, 97] >>> [G.multiple_of_order_using_frobp(p) for p in prime_range(Integer(3),Integer(19))] [92645296242160800, 7275, 291, 97, 97, 97] - We can compute the multiple of order of the torsion subgroup for Gamma0 and Gamma1 varieties, and their products. - sage: A = J0(11) * J0(33) sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp() 1000 sage: A = J1(23) sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp() 9406793 sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp(maxp=50) 408991 sage: A = J1(19) * J0(21) sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp() 35064 - >>> from sage.all import * >>> A = J0(Integer(11)) * J0(Integer(33)) >>> A.rational_torsion_subgroup().multiple_of_order_using_frobp() 1000 >>> A = J1(Integer(23)) >>> A.rational_torsion_subgroup().multiple_of_order_using_frobp() 9406793 >>> A.rational_torsion_subgroup().multiple_of_order_using_frobp(maxp=Integer(50)) 408991 >>> A = J1(Integer(19)) * J0(Integer(21)) >>> A.rational_torsion_subgroup().multiple_of_order_using_frobp() 35064 - The next example illustrates calling this function with a larger input and how the result may be cached when maxp is None: - sage: T = J0(43)[1].rational_torsion_subgroup() sage: T.multiple_of_order_using_frobp() 14 sage: T.multiple_of_order_using_frobp(50) 7 sage: T.multiple_of_order_using_frobp() 7 - >>> from sage.all import * >>> T = J0(Integer(43))[Integer(1)].rational_torsion_subgroup() >>> T.multiple_of_order_using_frobp() 14 >>> T.multiple_of_order_using_frobp(Integer(50)) 7 >>> T.multiple_of_order_using_frobp() 7 - This function is not implemented for general congruence subgroups unless the dimension is zero. - sage: A = JH(13,[2]); A Abelian variety J0(13) of dimension 0 sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp() 1 sage: A = JH(15, [2]); A Abelian variety JH(15,[2]) of dimension 1 sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp() Traceback (most recent call last): ... NotImplementedError: torsion multiple only implemented for Gamma0 and Gamma1 - >>> from sage.all import * >>> A = JH(Integer(13),[Integer(2)]); A Abelian variety J0(13) of dimension 0 >>> A.rational_torsion_subgroup().multiple_of_order_using_frobp() 1 >>> A = JH(Integer(15), [Integer(2)]); A Abelian variety JH(15,[2]) of dimension 1 >>> A.rational_torsion_subgroup().multiple_of_order_using_frobp() Traceback (most recent call last): ... NotImplementedError: torsion multiple only implemented for Gamma0 and Gamma1 
 - order(proof=True)[source]¶
- Return the order of the torsion subgroup of this modular abelian variety. - This function may fail if the multiple obtained by counting points modulo \(p\) exceeds the divisor obtained from the rational cuspidal subgroup. - The computation of the rational torsion order of J1(p) is conjectural and will only be used if - proof=False. See Section 6.2.3 of [CES2003].- INPUT: - proof– boolean (default:- True)
 - OUTPUT: the order of this torsion subgroup - EXAMPLES: - sage: A = J0(11) sage: A.rational_torsion_subgroup().order() 5 sage: A = J0(23) sage: A.rational_torsion_subgroup().order() 11 sage: T = J0(37)[1].rational_torsion_subgroup() sage: T.order() 3 sage: J = J1(13) sage: J.rational_torsion_subgroup().order() 19 - >>> from sage.all import * >>> A = J0(Integer(11)) >>> A.rational_torsion_subgroup().order() 5 >>> A = J0(Integer(23)) >>> A.rational_torsion_subgroup().order() 11 >>> T = J0(Integer(37))[Integer(1)].rational_torsion_subgroup() >>> T.order() 3 >>> J = J1(Integer(13)) >>> J.rational_torsion_subgroup().order() 19 - Sometimes the order can only be computed with - proof=False.- sage: J = J1(23) sage: J.rational_torsion_subgroup().order() Traceback (most recent call last): ... RuntimeError: Unable to compute order of torsion subgroup (it is in [408991, 9406793]) sage: J.rational_torsion_subgroup().order(proof=False) 408991 - >>> from sage.all import * >>> J = J1(Integer(23)) >>> J.rational_torsion_subgroup().order() Traceback (most recent call last): ... RuntimeError: Unable to compute order of torsion subgroup (it is in [408991, 9406793]) >>> J.rational_torsion_subgroup().order(proof=False) 408991 
 - possible_orders(proof=True)[source]¶
- Return the possible orders of this torsion subgroup. Outside of special cases, this is done by computing a divisor and multiple of the order. - INPUT: - proof– boolean (default:- True)
 - OUTPUT: an array of positive integers - The computation of the rational torsion order of J1(p) is conjectural and will only be used if - proof=False. See Section 6.2.3 of [CES2003].- EXAMPLES: - sage: J0(11).rational_torsion_subgroup().possible_orders() [5] sage: J0(33).rational_torsion_subgroup().possible_orders() [100, 200] sage: J1(13).rational_torsion_subgroup().possible_orders() [19] sage: J1(16).rational_torsion_subgroup().possible_orders() [1, 2, 4, 5, 10, 20] - >>> from sage.all import * >>> J0(Integer(11)).rational_torsion_subgroup().possible_orders() [5] >>> J0(Integer(33)).rational_torsion_subgroup().possible_orders() [100, 200] >>> J1(Integer(13)).rational_torsion_subgroup().possible_orders() [19] >>> J1(Integer(16)).rational_torsion_subgroup().possible_orders() [1, 2, 4, 5, 10, 20]