Path: blob/master/sage/modular/abvar/torsion_subgroup.py
4100 views
"""1Torsion subgroups of modular abelian varieties23Sage can compute information about the structure of the torsion4subgroup of a modular abelian variety. Sage computes a multiple of5the order by computing the greatest common divisor of the orders of6the torsion subgroup of the reduction of the abelian variety modulo7p for various primes p. Sage computes a divisor of the order by8computing the rational cuspidal subgroup. When these two bounds9agree (which is often the case), we determine the exact structure10of the torsion subgroup.1112AUTHORS:1314- William Stein (2007-03)1516EXAMPLES: First we consider `J_0(50)` where everything17works out nicely::1819sage: J = J0(50)20sage: T = J.rational_torsion_subgroup(); T21Torsion subgroup of Abelian variety J0(50) of dimension 222sage: T.multiple_of_order()231524sage: T.divisor_of_order()251526sage: T.gens()27[[(1/15, 3/5, 2/5, 14/15)]]28sage: T.invariants()29[15]30sage: d = J.decomposition(); d31[32Simple abelian subvariety 50a(1,50) of dimension 1 of J0(50),33Simple abelian subvariety 50b(1,50) of dimension 1 of J0(50)34]35sage: d[0].rational_torsion_subgroup().order()36337sage: d[1].rational_torsion_subgroup().order()3853940Next we make a table of the upper and lower bounds for each new41factor.4243::4445sage: for N in range(1,38):46... for A in J0(N).new_subvariety().decomposition():47... T = A.rational_torsion_subgroup()48... print '%-5s%-5s%-5s%-5s'%(N, A.dimension(), T.divisor_of_order(), T.multiple_of_order())4911 1 5 55014 1 6 65115 1 8 85217 1 4 45319 1 3 35420 1 6 65521 1 8 85623 2 11 115724 1 8 85826 1 3 35926 1 7 76027 1 3 36129 2 7 76230 1 6 126331 2 5 56432 1 4 46533 1 4 46634 1 6 66735 1 3 36835 2 16 166936 1 6 67037 1 1 17137 1 3 37273TESTS::7475sage: T = J0(54).rational_torsion_subgroup()76sage: loads(dumps(T)) == T77True78"""7980###########################################################################81# Copyright (C) 2007 William Stein <[email protected]> #82# Distributed under the terms of the GNU General Public License (GPL) #83# http://www.gnu.org/licenses/ #84###########################################################################8586from sage.modules.module import Module87from finite_subgroup import FiniteSubgroup, TorsionPoint88from sage.rings.all import divisors, gcd, ZZ, prime_range89from sage.sets.primes import Primes90from sage.modular.arithgroup.all import is_Gamma09192class RationalTorsionSubgroup(FiniteSubgroup):93"""94The torsion subgroup of a modular abelian variety.95"""96def __init__(self, abvar):97"""98Create the torsion subgroup.99100INPUT:101102103- ``abvar`` - a modular abelian variety104105106EXAMPLES::107108sage: T = J0(14).rational_torsion_subgroup(); T109Torsion subgroup of Abelian variety J0(14) of dimension 1110sage: type(T)111<class 'sage.modular.abvar.torsion_subgroup.RationalTorsionSubgroup'>112"""113FiniteSubgroup.__init__(self, abvar)114115def _repr_(self):116"""117Return string representation of this torsion subgroup.118119EXAMPLES::120121sage: T = J1(13).rational_torsion_subgroup(); T122Torsion subgroup of Abelian variety J1(13) of dimension 2123sage: T._repr_()124'Torsion subgroup of Abelian variety J1(13) of dimension 2'125"""126return "Torsion subgroup of %s"%self.abelian_variety()127128def __cmp__(self, other):129"""130Compare torsion subgroups.131132INPUT:133134135- ``other`` - an object136137138If other is a torsion subgroup, the abelian varieties are compared.139Otherwise, the generic behavior for finite abelian variety140subgroups is used.141142EXAMPLE::143144sage: G = J0(11).rational_torsion_subgroup(); H = J0(13).rational_torsion_subgroup()145sage: G == G146True147sage: G < H # since 11 < 13148True149sage: G > H150False151sage: G < 5 # random (meaningless since it depends on memory layout)152False153"""154if isinstance(other, RationalTorsionSubgroup):155return cmp(self.abelian_variety(), other.abelian_variety())156return FiniteSubgroup.__cmp__(self, other)157158def order(self):159"""160Return the order of the torsion subgroup of this modular abelian161variety.162163This may fail if the multiple obtained by counting points modulo164`p` exceeds the divisor obtained from the rational cuspidal165subgroup.166167EXAMPLES::168169sage: a = J0(11)170sage: a.rational_torsion_subgroup().order()1715172sage: a = J0(23)173sage: a.rational_torsion_subgroup().order()17411175sage: t = J0(37)[1].rational_torsion_subgroup()176sage: t.order()1773178"""179try:180return self._order181except AttributeError:182pass183O = self.possible_orders()184if len(O) == 1:185n = O[0]186self._order = n187return n188raise RuntimeError, "Unable to compute order of torsion subgroup (it is in %s)"%O189190def lattice(self):191"""192Return lattice that defines this torsion subgroup, if possible.193194.. warning::195196There is no known algorithm in general to compute the197rational torsion subgroup. Use rational_cusp_group to198obtain a subgroup of the rational torsion subgroup in199general.200201EXAMPLES::202203sage: J0(11).rational_torsion_subgroup().lattice()204Free module of degree 2 and rank 2 over Integer Ring205Echelon basis matrix:206[ 1 0]207[ 0 1/5]208209The following fails because in fact I know of no (reasonable)210algorithm to provably compute the torsion subgroup in general.211212::213214sage: T = J0(33).rational_torsion_subgroup()215sage: T.lattice()216Traceback (most recent call last):217...218NotImplementedError: unable to compute the rational torsion subgroup in this case (there is no known general algorithm yet)219220The problem is that the multiple of the order obtained by counting221points over finite fields is twice the divisor of the order got222from the rational cuspidal subgroup.223224::225226sage: T.multiple_of_order(30)227200228sage: J0(33).rational_cusp_subgroup().order()229100230"""231A = self.abelian_variety()232if A.dimension() == 0:233return []234R = A.rational_cusp_subgroup()235if R.order() == self.multiple_of_order():236return R.lattice()237else:238raise NotImplementedError, "unable to compute the rational torsion subgroup in this case (there is no known general algorithm yet)"239240def possible_orders(self):241"""242Return the possible orders of this torsion subgroup, computed from243a known divisor and multiple of the order.244245EXAMPLES::246247sage: J0(11).rational_torsion_subgroup().possible_orders()248[5]249sage: J0(33).rational_torsion_subgroup().possible_orders()250[100, 200]251252Note that this function has not been implemented for `J_1(N)`,253though it should be reasonably easy to do so soon (see Conrad,254Edixhoven, Stein)::255256sage: J1(13).rational_torsion_subgroup().possible_orders()257Traceback (most recent call last):258...259NotImplementedError: torsion multiple only implemented for Gamma0260"""261try:262return self._possible_orders263except AttributeError:264pass265u = self.multiple_of_order()266l = self.divisor_of_order()267assert u % l == 0268O = [l * d for d in divisors(u//l)]269self._possible_orders = O270return O271272def divisor_of_order(self):273"""274Return a divisor of the order of this torsion subgroup of a modular275abelian variety.276277EXAMPLES::278279sage: t = J0(37)[1].rational_torsion_subgroup()280sage: t.divisor_of_order()2813282"""283A = self.abelian_variety()284if A.dimension() == 0:285return ZZ(1)286R = A.rational_cusp_subgroup()287return R.order()288289def multiple_of_order(self, maxp=None):290"""291Return a multiple of the order of this torsion group.292293The multiple is computed using characteristic polynomials of Hecke294operators of odd index not dividing the level.295296INPUT:297298299- ``maxp`` - (default: None) If maxp is None (the300default), return gcd of best bound computed so far with bound301obtained by computing GCD's of orders modulo p until this gcd302stabilizes for 3 successive primes. If maxp is given, just use all303primes up to and including maxp.304305306EXAMPLES::307308sage: J = J0(11)309sage: G = J.rational_torsion_subgroup()310sage: G.multiple_of_order(11)3115312sage: J = J0(389)313sage: G = J.rational_torsion_subgroup(); G314Torsion subgroup of Abelian variety J0(389) of dimension 32315sage: G.multiple_of_order()31697317sage: [G.multiple_of_order(p) for p in prime_range(3,11)]318[92645296242160800, 7275, 291]319sage: [G.multiple_of_order(p) for p in prime_range(3,13)]320[92645296242160800, 7275, 291, 97]321sage: [G.multiple_of_order(p) for p in prime_range(3,19)]322[92645296242160800, 7275, 291, 97, 97, 97]323324::325326sage: J = J0(33) * J0(11) ; J.rational_torsion_subgroup().order()327Traceback (most recent call last):328...329NotImplementedError: torsion multiple only implemented for Gamma0330331The next example illustrates calling this function with a larger332input and how the result may be cached when maxp is None::333334sage: T = J0(43)[1].rational_torsion_subgroup()335sage: T.multiple_of_order()33614337sage: T.multiple_of_order(50)3387339sage: T.multiple_of_order()3407341"""342if maxp is None:343try:344return self.__multiple_of_order345except AttributeError:346pass347bnd = ZZ(0)348A = self.abelian_variety()349if A.dimension() == 0:350T = ZZ(1)351self.__multiple_of_order = T352return T353N = A.level()354if not (len(A.groups()) == 1 and is_Gamma0(A.groups()[0])):355# to generalize to this case, you'll need to356# (1) define a charpoly_of_frob function:357# this is tricky because I don't know a simple358# way to do this for Gamma1 and GammaH. Will359# probably have to compute explicit matrix for360# <p> operator (add to modular symbols code),361# then compute some charpoly involving362# that directly...363# (2) use (1) -- see my MAGMA code.364raise NotImplementedError, "torsion multiple only implemented for Gamma0"365cnt = 0366if maxp is None:367X = Primes()368else:369X = prime_range(maxp+1)370for p in X:371if (2*N) % p == 0:372continue373374f = A.hecke_polynomial(p)375b = ZZ(f(p+1))376377if bnd == 0:378bnd = b379else:380bnd_last = bnd381bnd = ZZ(gcd(bnd, b))382if bnd == bnd_last:383cnt += 1384else:385cnt = 0386if maxp is None and cnt >= 2:387break388389# The code below caches the computed bound and390# will be used if this function is called391# again with maxp equal to None (the default).392if maxp is None:393# maxp is None but self.__multiple_of_order is394# not set, since otherwise we would have immediately395# returned at the top of this function396self.__multiple_of_order = bnd397else:398# maxp is given -- record new info we get as399# a gcd...400try:401self.__multiple_of_order = gcd(self.__multiple_of_order, bnd)402except AttributeError:403# ... except in the case when self.__multiple_of_order404# was never set. In this case, we just set405# it as long as the gcd stabilized for 3 in a row.406if cnt >= 2:407self.__multiple_of_order = bnd408return bnd409410411412class QQbarTorsionSubgroup(Module):413def __init__(self, abvar):414"""415Group of all torsion points over the algebraic closure on an416abelian variety.417418INPUT:419420421- ``abvar`` - an abelian variety422423424EXAMPLES::425426sage: A = J0(23)427sage: A.qbar_torsion_subgroup()428Group of all torsion points in QQbar on Abelian variety J0(23) of dimension 2429"""430self.__abvar = abvar431Module.__init__(self, ZZ)432433def _repr_(self):434"""435Print representation of QQbar points.436437OUTPUT: string438439EXAMPLES::440441sage: J0(23).qbar_torsion_subgroup()._repr_()442'Group of all torsion points in QQbar on Abelian variety J0(23) of dimension 2'443"""444return 'Group of all torsion points in QQbar on %s'%self.__abvar445446def field_of_definition(self):447"""448Return the field of definition of this subgroup. Since this is the449group of all torsion it is defined over the base field of this450abelian variety.451452OUTPUT: a field453454EXAMPLES::455456sage: J0(23).qbar_torsion_subgroup().field_of_definition()457Rational Field458"""459return self.__abvar.base_field()460461def __call__(self, x):462r"""463Create an element in this finite group.464465INPUT:466467468- ``x`` - vector in `\QQ^{2d}`469470471OUTPUT: torsion point472473EXAMPLES::474475sage: P = J0(23).qbar_torsion_subgroup()([1,1/2,3/4,2]); P476[(1, 1/2, 3/4, 2)]477sage: P.order()4784479"""480v = self.__abvar.vector_space()(x)481return TorsionPoint(self, v)482483def abelian_variety(self):484"""485Return the abelian variety that this is the set of all torsion486points on.487488OUTPUT: abelian variety489490EXAMPLES::491492sage: J0(23).qbar_torsion_subgroup().abelian_variety()493Abelian variety J0(23) of dimension 2494"""495return self.__abvar496497498499