Path: blob/master/src/sage/modular/arithgroup/congroup_generic.py
8820 views
r"""1Congruence arithmetic subgroups of `{\rm SL}_2(\ZZ)`23Sage can compute extensively with the standard congruence subgroups4`\Gamma_0(N)`, `\Gamma_1(N)`, and `\Gamma_H(N)`.56AUTHORS:78- William Stein9- David Loeffler (2009, 10) -- modifications to work with more general arithmetic subgroups10"""1112################################################################################13#14# Copyright (C) 2004, 2006 William Stein <[email protected]>15#16# Distributed under the terms of the GNU General Public License (GPL)17#18# The full text of the GPL is available at:19#20# http://www.gnu.org/licenses/21#22################################################################################2324from sage.rings.all import QQ, ZZ, Zmod25from sage.rings.arith import gcd26from sage.sets.set import Set27from sage.groups.matrix_gps.all import MatrixGroup28from sage.matrix.matrix_space import MatrixSpace29from sage.misc.misc_c import prod30from arithgroup_generic import ArithmeticSubgroup313233def CongruenceSubgroup_constructor(*args):34r"""35Attempt to create a congruence subgroup from the given data.3637The allowed inputs are as follows:3839- A :class:`~sage.groups.matrix_gps.matrix_group.MatrixGroup` object. This40must be a group of matrices over `\ZZ / N\ZZ` for some `N`, with41determinant 1, in which case the function will return the group of42matrices in `SL(2, \ZZ)` whose reduction mod `N` is in the given group.4344- A list of matrices over `\ZZ / N\ZZ` for some `N`. The function will then45compute the subgroup of `SL(2, \ZZ)` generated by these matrices, and46proceed as above.4748- An integer `N` and a list of matrices (over any ring coercible to `\ZZ /49N\ZZ`, e.g. over `\ZZ`). The matrices will then be coerced to `\ZZ /50N\ZZ`.5152The function checks that the input G is valid. It then tests to see if53`G` is the preimage mod `N` of some group of matrices modulo a proper54divisor `M` of `N`, in which case it replaces `G` with this group before55continuing.5657EXAMPLES::5859sage: from sage.modular.arithgroup.congroup_generic import CongruenceSubgroup_constructor as CS60sage: CS(2, [[1,1,0,1]])61Congruence subgroup of SL(2,Z) of level 2, preimage of:62Matrix group over Ring of integers modulo 2 with 1 generators (63[1 1]64[0 1]65)66sage: CS([matrix(Zmod(2), 2, [1,1,0,1])])67Congruence subgroup of SL(2,Z) of level 2, preimage of:68Matrix group over Ring of integers modulo 2 with 1 generators (69[1 1]70[0 1]71)72sage: CS(MatrixGroup([matrix(Zmod(2), 2, [1,1,0,1])]))73Congruence subgroup of SL(2,Z) of level 2, preimage of:74Matrix group over Ring of integers modulo 2 with 1 generators (75[1 1]76[0 1]77)78sage: CS(SL(2, 2))79Modular Group SL(2,Z)8081Some invalid inputs::8283sage: CS(SU(2, 7))84Traceback (most recent call last):85...86TypeError: Ring of definition must be Z / NZ for some N87"""88from sage.groups.matrix_gps.matrix_group import is_MatrixGroup89if is_MatrixGroup(args[0]):90G = args[0]9192elif type(args[0]) == type([]):93G = MatrixGroup(args[0])9495elif args[0] in ZZ:96M = MatrixSpace(Zmod(args[0]), 2)97G = MatrixGroup([M(x) for x in args[1]])9899R = G.matrix_space().base_ring()100if not hasattr(R, "cover_ring") or R.cover_ring() != ZZ:101raise TypeError, "Ring of definition must be Z / NZ for some N"102103if not all([x.matrix().det() == 1 for x in G.gens()]):104raise ValueError, "Group must be contained in SL(2, Z / N)"105GG = _minimize_level(G)106if GG in ZZ:107from all import Gamma108return Gamma(GG)109else:110return CongruenceSubgroupFromGroup(GG)111112def is_CongruenceSubgroup(x):113"""114Return True if x is of type CongruenceSubgroup.115116Note that this may be False even if `x` really is a congruence subgroup --117it tests whether `x` is "obviously" congruence, i.e.~whether it has a118congruence subgroup datatype. To test whether or not an arithmetic subgroup119of `SL(2, \ZZ)` is congruence, use the ``is_congruence()`` method instead.120121EXAMPLES::122123sage: from sage.modular.arithgroup.congroup_generic import is_CongruenceSubgroup124sage: is_CongruenceSubgroup(SL2Z)125True126sage: is_CongruenceSubgroup(Gamma0(13))127True128sage: is_CongruenceSubgroup(Gamma1(6))129True130sage: is_CongruenceSubgroup(GammaH(11, [3]))131True132sage: G = ArithmeticSubgroup_Permutation(L = "(1, 2)", R = "(1, 2)"); is_CongruenceSubgroup(G)133False134sage: G.is_congruence()135True136sage: is_CongruenceSubgroup(SymmetricGroup(3))137False138"""139return isinstance(x, CongruenceSubgroupBase)140141class CongruenceSubgroupBase(ArithmeticSubgroup):142143def __init__(self, level):144"""145Create a congruence subgroup with given level.146147EXAMPLES::148149sage: Gamma0(500)150Congruence Subgroup Gamma0(500)151"""152level = ZZ(level)153if level <= 0:154raise ArithmeticError, "Congruence groups only defined for positive levels."155self.__level = level156ArithmeticSubgroup.__init__(self)157158def _an_element_(self):159r"""160Return an element of self (mainly for use by the test suite).161162EXAMPLE::163164sage: Gamma(3).an_element() # indirect doctest165[-2 -3]166[ 3 4]167"""168N = self.level()169return self([1-N, -N, N, 1+N])170171def is_congruence(self):172r"""173Return True, since this is a congruence subgroup.174175EXAMPLE::176177sage: Gamma0(7).is_congruence()178True179"""180181return True182183def level(self):184"""185Return the level of this congruence subgroup.186187EXAMPLES::188189sage: SL2Z.level()1901191sage: Gamma0(20).level()19220193sage: Gamma1(11).level()19411195sage: GammaH(14, [5]).level()19614197"""198return self.__level199200def __cmp__(self, other):201r"""202EXAMPLE::203204sage: CongruenceSubgroup(3,[ [1,1,0,1] ]) == Gamma1(3)205True206sage: CongruenceSubgroup(3,[ [1,1,0,1] ]) == Gamma(3)207False208sage: CongruenceSubgroup(3,[ [1,1,0,1] ]) == QQ209False210"""211# This is carefully laid out so it can be called early on in the Sage212# startup process when we want to create the standard generators of213# SL2Z for use in arithgroup_perm. Hence it must work in this case214# without being able to import the arithgroup_perm module. That's why215# the most general case is *first*, not last.216# Note that lazy_import doesn't work here, because it doesn't play217# nicely with isinstance().218if not isinstance(other, ArithmeticSubgroup):219return cmp(type(self), type(other))220221elif is_CongruenceSubgroup(other):222t = cmp(self.level(), other.level())223if t: return t224if self.level() == 1: return 0 # shouldn't come up except with pickling/unpickling225t = cmp(self.index(), other.index())226if t: return t227return cmp(self.image_mod_n(),other.image_mod_n())228229from sage.modular.arithgroup.arithgroup_perm import ArithmeticSubgroup_Permutation_class230if isinstance(other, ArithmeticSubgroup_Permutation_class):231return cmp(self.as_permutation_group(), other)232233else:234# we shouldn't ever get here235raise NotImplementedError236237class CongruenceSubgroupFromGroup(CongruenceSubgroupBase):238r"""239A congruence subgroup, defined by the data of an integer `N` and a subgroup240`G` of the finite group `SL(2, \ZZ / N\ZZ)`; the congruence subgroup241consists of all the matrices in `SL(2, \ZZ)` whose reduction modulo `N`242lies in `G`.243244This class should not be instantiated directly, but created using the245factory function246:func:`~sage.modular.arithgroup.congroup_generic.CongruenceSubgroup_constructor`,247which accepts much more flexible input, and checks the input to make sure248it is valid.249250TESTS::251252sage: G = CongruenceSubgroup(5, [[0,-1,1,0]]); G253Congruence subgroup of SL(2,Z) of level 5, preimage of:254Matrix group over Ring of integers modulo 5 with 1 generators (255[0 4]256[1 0]257)258sage: TestSuite(G).run()259"""260261def __init__(self, G):262r"""263Standard init function.264265TESTS::266267sage: from sage.modular.arithgroup.congroup_generic import CongruenceSubgroupFromGroup268sage: G = MatrixGroup([matrix(Zmod(2), 2, [1,1,1,0])])269sage: CongruenceSubgroupFromGroup(G).index() # indirect doctest2702271"""272N = G.base_ring().characteristic()273self.__G = G274CongruenceSubgroupBase.__init__(self, N)275276def __reduce__(self):277r"""278Data defining self (for pickling).279280EXAMPLE::281282sage: G = CongruenceSubgroup(5, [[0,-1,1,0]])283sage: G.__reduce__()284(<function CongruenceSubgroup_constructor at ...>,285(Matrix group over Ring of integers modulo 5 with 1 generators (286[0 4]287[1 0]288),))289"""290return CongruenceSubgroup_constructor, (self.image_mod_n(),)291292def _contains_sl2(self, a,b,c,d):293r"""294Test whether ``[a,b;c,d]`` is an element of self.295296EXAMPLE::297298sage: G = MatrixGroup([matrix(Zmod(2), 2, [1,1,1,0])])299sage: H = sage.modular.arithgroup.congroup_generic.CongruenceSubgroupFromGroup(G)300sage: H(1)301[1 0]302[0 1]303sage: H([0,-1,1,0])304Traceback (most recent call last):305...306TypeError: matrix [ 0 -1]307[ 1 0] is not an element of Congruence subgroup of SL(2,Z) of level 2, preimage of:308Matrix group over Ring of integers modulo 2 with 1 generators (309[1 1]310[1 0]311)312sage: H([1,2,0,1])313[1 2]314[0 1]315sage: H(SL2Z([0,-1,1,0]), check=False)316[ 0 -1]317[ 1 0]318sage: H([1,2,0,1]).parent()319Modular Group SL(2,Z)320"""321return ([a,b,c,d] in self.image_mod_n())322323def to_even_subgroup(self):324r"""325Return the smallest even subgroup of `SL(2, \ZZ)` containing self.326327EXAMPLE::328329sage: G = Gamma(3)330sage: G.to_even_subgroup()331Congruence subgroup of SL(2,Z) of level 3, preimage of:332Matrix group over Ring of integers modulo 3 with 1 generators (333[2 0]334[0 2]335)336"""337if self.is_even():338return self339else:340G = self.image_mod_n()341H = MatrixGroup([ g.matrix() for g in G.gens()] + [G.matrix_space()(-1)])342return CongruenceSubgroup_constructor(H)343344def _repr_(self):345r"""346String representation of self.347348EXAMPLE::349350sage: sage.modular.arithgroup.congroup_generic.CongruenceSubgroupFromGroup(MatrixGroup([matrix(Zmod(2), 2, [1,1,1,0])]))._repr_()351'Congruence subgroup of SL(2,Z) of level 2, preimage of:\n Matrix group over Ring of integers modulo 2 with 1 generators (\n[1 1]\n[1 0]\n)'352"""353return "Congruence subgroup of SL(2,Z) of level %s, preimage of:\n %s" % (self.level(), self.image_mod_n())354355def index(self):356r"""357Return the index of self in the full modular group. This is equal to358the index in `SL(2, \ZZ / N\ZZ)` of the image of this group modulo359`\Gamma(N)`.360361EXAMPLE::362363sage: sage.modular.arithgroup.congroup_generic.CongruenceSubgroupFromGroup(MatrixGroup([matrix(Zmod(2), 2, [1,1,1,0])])).index()3642365"""366return prod([p**(3*e-2)*(p*p-1) for (p,e) in self.level().factor()]) // self.image_mod_n().order()367368def image_mod_n(self):369r"""370Return the subgroup of `SL(2, \ZZ / N\ZZ)` of which this is the preimage, where `N` is the level of self.371372EXAMPLE::373374sage: G = MatrixGroup([matrix(Zmod(2), 2, [1,1,1,0])])375sage: H = sage.modular.arithgroup.congroup_generic.CongruenceSubgroupFromGroup(G); H.image_mod_n()376Matrix group over Ring of integers modulo 2 with 1 generators (377[1 1]378[1 0]379)380sage: H.image_mod_n() == G381True382"""383return self.__G384385class CongruenceSubgroup(CongruenceSubgroupFromGroup):386r"""387One of the "standard" congruence subgroups `\Gamma_0(N)`, `\Gamma_1(N)`,388`\Gamma(N)`, or `\Gamma_H(N)` (for some `H`).389390This class is not intended to be instantiated directly. Derived subclasses391must override ``_contains_sl2``, ``_repr_``, and ``image_mod_n``.392"""393394def image_mod_n(self):395r"""396Raise an error: all derived subclasses should override this function.397398EXAMPLE::399400sage: sage.modular.arithgroup.congroup_generic.CongruenceSubgroup(5).image_mod_n()401Traceback (most recent call last):402...403NotImplementedError404"""405raise NotImplementedError406407def __init__(self,*args, **kwds):408r"""409Bypass the init function of the CongruenceSubgroupFromGroup class.410411EXAMPLE::412413sage: sage.modular.arithgroup.congroup_generic.CongruenceSubgroup(5) # indirect doctest414Generic congruence subgroup of level 5415"""416return CongruenceSubgroupBase.__init__(self, *args, **kwds)417418def _repr_(self):419"""420Return the string representation of self.421422NOTE: This function should be overridden by all subclasses.423424EXAMPLES::425426sage: sage.modular.arithgroup.congroup_generic.CongruenceSubgroup(5)._repr_()427'Generic congruence subgroup of level 5'428"""429return "Generic congruence subgroup of level %s" % self.level()430431def modular_symbols(self, sign=0, weight=2, base_ring=QQ):432"""433Return the space of modular symbols of the specified weight and sign434on the congruence subgroup self.435436EXAMPLES::437438sage: G = Gamma0(23)439sage: G.modular_symbols()440Modular Symbols space of dimension 5 for Gamma_0(23) of weight 2 with sign 0 over Rational Field441sage: G.modular_symbols(weight=4)442Modular Symbols space of dimension 12 for Gamma_0(23) of weight 4 with sign 0 over Rational Field443sage: G.modular_symbols(base_ring=GF(7))444Modular Symbols space of dimension 5 for Gamma_0(23) of weight 2 with sign 0 over Finite Field of size 7445sage: G.modular_symbols(sign=1)446Modular Symbols space of dimension 3 for Gamma_0(23) of weight 2 with sign 1 over Rational Field447"""448from sage.modular.modsym.modsym import ModularSymbols449return ModularSymbols(self, sign=sign, weight=weight, base_ring=base_ring)450451def modular_abelian_variety(self):452"""453Return the modular abelian variety corresponding to the congruence454subgroup self.455456EXAMPLES::457458sage: Gamma0(11).modular_abelian_variety()459Abelian variety J0(11) of dimension 1460sage: Gamma1(11).modular_abelian_variety()461Abelian variety J1(11) of dimension 1462sage: GammaH(11,[3]).modular_abelian_variety()463Abelian variety JH(11,[3]) of dimension 1464"""465from sage.modular.abvar.abvar_ambient_jacobian import ModAbVar_ambient_jacobian466return ModAbVar_ambient_jacobian(self)467468def _new_group_from_level(self, level):469r"""470Return a new group of the same type (Gamma0, Gamma1, or471GammaH) as self of the given level. In the case that self is of type472GammaH, we take the largest H inside `(\ZZ/ \text{level}\ZZ)^\times`473which maps to H, namely its inverse image under the natural reduction474map.475476EXAMPLES::477478sage: G = Gamma0(20)479sage: G._new_group_from_level(4)480Congruence Subgroup Gamma0(4)481sage: G._new_group_from_level(40)482Congruence Subgroup Gamma0(40)483484sage: G = Gamma1(10)485sage: G._new_group_from_level(6)486Traceback (most recent call last):487...488ValueError: one level must divide the other489490sage: G = GammaH(50,[7]); G491Congruence Subgroup Gamma_H(50) with H generated by [7]492sage: G._new_group_from_level(25)493Congruence Subgroup Gamma_H(25) with H generated by [7]494sage: G._new_group_from_level(10)495Congruence Subgroup Gamma0(10)496sage: G._new_group_from_level(100)497Congruence Subgroup Gamma_H(100) with H generated by [7, 57]498"""499from congroup_gamma0 import is_Gamma0500from congroup_gamma1 import is_Gamma1501from congroup_gammaH import is_GammaH502from all import Gamma0, Gamma1, GammaH503N = self.level()504if (level%N) and (N%level):505raise ValueError, "one level must divide the other"506if is_Gamma0(self):507return Gamma0(level)508elif is_Gamma1(self):509return Gamma1(level)510elif is_GammaH(self):511H = self._generators_for_H()512if level > N:513d = level // N514diffs = [ N*i for i in range(d) ]515newH = [ h + diff for h in H for diff in diffs ]516return GammaH(level, [x for x in newH if gcd(level, x) == 1])517else:518return GammaH(level, [ h%level for h in H ])519else:520raise NotImplementedError521522def _minimize_level(G):523r"""524Utility function. Given a matrix group `G` contained in `SL(2, \ZZ / N\ZZ)`525for some `N`, test whether or not `G` is the preimage of a subgroup of526smaller level, and if so, return that subgroup.527528The trivial group is handled specially: instead of returning a group, it529returns an integer `N`, representing the trivial subgroup of `SL(2, \ZZ /530N\ZZ)`.531532EXAMPLE::533534sage: M = MatrixSpace(Zmod(9), 2, 2)535sage: G = MatrixGroup([M(x) for x in [[1,1,0,1],[1,3,0,1],[1,0,3,1],[4,0,0,7]]]); G536Matrix group over Ring of integers modulo 9 with 4 generators (537[1 1] [1 3] [1 0] [4 0]538[0 1], [0 1], [3 1], [0 7]539)540sage: sage.modular.arithgroup.congroup_generic._minimize_level(G)541Matrix group over Ring of integers modulo 3 with 1 generators (542[1 1]543[0 1]544)545sage: G = MatrixGroup([M(x) for x in [[1,3,0,1],[1,0,3,1],[4,0,0,7]]]); G546Matrix group over Ring of integers modulo 9 with 3 generators (547[1 3] [1 0] [4 0]548[0 1], [3 1], [0 7]549)550sage: sage.modular.arithgroup.congroup_generic._minimize_level(G)5513552"""553from congroup_gamma import Gamma_constructor as Gamma554Glist = list(G)555N = G.base_ring().characteristic()556i = Gamma(N).index()557558for p in N.prime_divisors():559j = Gamma(N // p).index()560k = len([g for g in Glist if g.matrix().change_ring(Zmod(N // p)) == 1])561if k == i // j:562if N // p == 1:563return ZZ(1)564H = MatrixGroup([g.matrix().change_ring(Zmod(N//p)) for g in G.gens()])565return _minimize_level(H)566567# now sanitize the generators (remove duplicates and copies of the identity)568new_gens = [x.matrix() for x in G.gens() if x.matrix() != 1]569all([x.set_immutable() for x in new_gens])570new_gens = list(Set(new_gens))571if new_gens == []:572return ZZ(G.base_ring().characteristic())573return MatrixGroup(new_gens)574575576