Ticket #2103: 2103-rebased.patch

File 2103-rebased.patch, 47.2 KB (added by davidloeffler, 5 years ago)

rebased to 3.1.4 (also works in 3.2.alpha1)

  • sage/modular/abvar/abvar.py

    # HG changeset patch
    # User David Loeffler <D.Loeffler@dpmms.cam.ac.uk>
    # Date 1225191768 0
    # Node ID dc06bf9ff94210b7ba42e52999af0b6d27d2ffab
    # Parent  3859ace869681b4efc4ded59cf84a24e26383e9f
    #2103: equivalence classes of cusps for congruence subgroups
    
    diff -r 3859ace86968 -r dc06bf9ff942 sage/modular/abvar/abvar.py
    a b  
    30693069        class that matters: 
    30703070            sage: D = (J0(11)*J1(11)).decomposition(); D 
    30713071            [ 
    3072             Simple abelian subvariety 11a(1,11) of dimension 1 of J0(11) x J1(11), 
    3073             Simple abelian subvariety 11aG1(1,11) of dimension 1 of J0(11) x J1(11) 
     3072            Simple abelian subvariety 11aG1(1,11) of dimension 1 of J0(11) x J1(11), 
     3073            Simple abelian subvariety 11a(1,11) of dimension 1 of J0(11) x J1(11) 
    30743074            ] 
    30753075            sage: D[0]._complement_shares_no_factors_with_same_label() 
    30763076            True 
    30773077            sage: D[0].newform_label() 
    3078             '11a' 
     3078            '11aG1' 
    30793079            sage: D[1].newform_label() 
    3080             '11aG1'             
     3080            '11a'             
    30813081        """ 
    30823082        try: 
    30833083            return self.__complement_shares 
  • sage/modular/congroup.py

    diff -r 3859ace86968 -r dc06bf9ff942 sage/modular/congroup.py
    a b  
    2626import sage.rings.arith as arith 
    2727from sage.rings.integer_mod_ring import IntegerModRing 
    2828from sage.rings.all import QQ, ZZ, divisors 
    29  
    3029from sage.matrix.matrix_space import MatrixSpace 
    3130 
    3231from congroup_element import CongruenceSubgroupElement 
     32import cusps 
     33from sage.sets.set import Set 
    3334 
    3435import sage.modular.modsym.p1list 
    3536 
     
    475476            return x 
    476477        raise NotImplementedError 
    477478 
     479    def reduce_cusp(self, c): 
     480        r""" 
     481        Given a cusp $c \in \mathbb{P}^1(\mathbb{Q})$, return the unique 
     482        reduced cusp equivalent to c under the action of self, where a reduced 
     483        cusp is an element r/s with r,s coprime integers, s as small as 
     484        possible, and r as small as possible for that s. 
     485         
     486        NOTE: This function should be overridden by all subclasses. 
     487 
     488        EXAMPLES: 
     489            sage: sage.modular.congroup.CongruenceSubgroup(5).reduce_cusp(1/4) 
     490            Traceback (most recent call last): 
     491            ... 
     492            NotImplementedError 
     493        """ 
     494        raise NotImplementedError 
     495 
     496    def cusps(self, bdmap=False): 
     497        r""" 
     498        Return a set of inequivalent cusps for self, i.e. a set of 
     499        representatives for the orbits of self on $\mathbb{P}^1(\mathbb{Q})$. 
     500        These should be returned in a reduced form. 
     501 
     502        INPUTS: 
     503            (bool) -- whether to directly calculate the cusps, or to calculate 
     504            them as a by-product of computing the boundary map on the 
     505            associated space of modular symbols. The latter is slower, but is 
     506            older and presumably better-tested code. 
     507 
     508        EXAMPLES: 
     509            sage: Gamma0(36).cusps() 
     510            {1/6, 1/4, 1/3, 1/2, 1/9, 0, 1/18, 5/12, Infinity, 1/12, 2/3, 5/6} 
     511            sage: Gamma0(36).cusps(True) == Gamma0(36).cusps(False) 
     512            True 
     513            sage: GammaH(36, [19,29]).cusps() == Gamma0(36).cusps() 
     514            True 
     515            sage: Gamma0(1).cusps() 
     516            {Infinity} 
     517        """ 
     518        # special case for SL2Z as modular symbols space is zero 
     519        if bdmap == True: 
     520            # special case for SL2Z as modular symbols space is zero 
     521            if self == SL2Z: 
     522                return Set([cusps.Cusp(1,0)]) 
     523            return Set([self.reduce_cusp(c) for c in self.modular_symbols().cusps()]) 
     524        else: 
     525            return self._find_cusps() 
     526 
     527    def _find_cusps(self): 
     528        r""" 
     529        Calculate a list of inequivalent cusps.  
     530 
     531        EXAMPLES: 
     532            sage: sage.modular.congroup.CongruenceSubgroup(5)._find_cusps() 
     533            Traceback (most recent call last): 
     534            ... 
     535            NotImplementedError 
     536 
     537        NOTE: This function should be overridden by all subclasses. 
     538        """ 
     539        raise NotImplementedError 
     540 
    478541def lift_to_sl2z(c, d, N): 
    479542    """ 
    480543    Given a vector (c, d) in $(Z/NZ)^2$, this function computes and 
     
    528591    return [z2, -z1, c, d] 
    529592 
    530593 
    531 def is_Gamma0(x): 
    532     """ 
    533     Return True if x is a congruence subgroup of type Gamma0. 
    534  
    535     EXAMPLES: 
    536         sage: from sage.modular.congroup import is_Gamma0 
    537         sage: is_Gamma0(SL2Z) 
    538         True 
    539         sage: is_Gamma0(Gamma0(13)) 
    540         True 
    541         sage: is_Gamma0(Gamma1(6)) 
    542         False 
    543     """ 
    544     return isinstance(x, Gamma0_class) 
    545  
    546 _gamma0_cache = {} 
    547 def Gamma0(N): 
    548     """ 
    549     Return the congruence subgroup Gamma0(N). 
    550  
    551     EXAMPLES: 
    552         sage: G = Gamma0(51) ; G 
    553         Congruence Subgroup Gamma0(51) 
    554         sage: G == Gamma0(51) 
    555         True 
    556         sage: G is Gamma0(51) 
    557         True 
    558     """ 
    559     try: 
    560         return _gamma0_cache[N] 
    561     except KeyError: 
    562         _gamma0_cache[N] = Gamma0_class(N) 
    563         return _gamma0_cache[N] 
    564  
    565 class Gamma0_class(CongruenceSubgroup): 
    566     def __init__(self, level): 
    567         r""" 
    568         The congruence subgroup $\Gamma_0(N)$. 
    569  
    570         EXAMPLES: 
    571             sage: G = Gamma0(11); G 
    572             Congruence Subgroup Gamma0(11) 
    573             sage: loads(G.dumps()) == G 
    574             True 
    575         """ 
    576         CongruenceSubgroup.__init__(self, level) 
    577  
    578     def _repr_(self): 
    579         """ 
    580         Return the string representation of self. 
    581  
    582         EXAMPLES: 
    583             sage: Gamma0(98)._repr_() 
    584             'Congruence Subgroup Gamma0(98)' 
    585         """ 
    586         return "Congruence Subgroup Gamma0(%s)"%self.level() 
    587  
    588     def __reduce__(self): 
    589         """ 
    590         Used for pickling self. 
    591  
    592         EXAMPLES: 
    593             sage: Gamma0(22).__reduce__() 
    594             (<function Gamma0 at ...>, (22,)) 
    595         """ 
    596         return Gamma0, (self.level(),) 
    597  
    598     def _latex_(self): 
    599         r""" 
    600         Return the \LaTeX representation of self. 
    601          
    602         EXAMPLES: 
    603             sage: Gamma0(20)._latex_() 
    604             '\\Gamma_0(20)' 
    605             sage: latex(Gamma0(20)) 
    606             \Gamma_0(20) 
    607         """ 
    608         return "\\Gamma_0(%s)"%self.level() 
    609  
    610     def _generators_for_H(self): 
    611         """ 
    612         Return generators for the subgroup H of the units mod 
    613         self.level() that defines self. 
    614          
    615         EXAMPLES: 
    616             sage: Gamma0(15)._generators_for_H() 
    617             [11, 7] 
    618         """ 
    619         try: 
    620             return self.__generators_for_H 
    621         except AttributeError: 
    622             self.__generators_for_H = [int(x) for x in IntegerModRing(self.level()).unit_gens()] 
    623             return self.__generators_for_H 
    624  
    625     def _list_of_elements_in_H(self): 
    626         """ 
    627         Returns a sorted list of Python ints that are representatives 
    628         between 0 and N-1 of the elements of H. 
    629  
    630         EXAMPLES: 
    631             sage: G = Gamma0(11) 
    632             sage: G._list_of_elements_in_H() 
    633             [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
    634  
    635             sage: G = Gamma0(6) 
    636             sage: G._list_of_elements_in_H() 
    637             [1, 5] 
    638  
    639             sage: G = Gamma0(1) 
    640             sage: G._list_of_elements_in_H() 
    641             [1] 
    642         """ 
    643         N = self.level() 
    644         if N != 1: 
    645             gcd = arith.gcd 
    646             return [ x for x in range(1, N) if gcd(x, N) == 1 ] 
    647         else: 
    648             return [1] 
    649      
    650     def __cmp__(self, right): 
    651         """ 
    652         Compare self to right. 
    653  
    654         EXAMPLES: 
    655             sage: Gamma0(21).__cmp__(Gamma0(21)) 
    656             0 
    657             sage: Gamma0(21) < Gamma0(32) 
    658             True 
    659         """ 
    660         if not is_Gamma0(right): 
    661             if is_CongruenceSubgroup(right): 
    662                 c = cmp(self.level(), right.level()) 
    663                 if c: return c 
    664             return cmp(type(self), type(right)) 
    665         return cmp(self.level(), right.level()) 
    666  
    667     def is_even(self): 
    668         """ 
    669         Return True precisely if this subgroup contains the matrix -1. 
    670  
    671         Since Gamma0(N) always, contains the matrix -1, this always 
    672         returns True. 
    673  
    674         EXAMPLES: 
    675             sage: Gamma0(12).is_even() 
    676             True 
    677             sage: SL2Z.is_even() 
    678             True 
    679         """ 
    680         return True 
    681  
    682     def is_subgroup(self, right): 
    683         """ 
    684         Return True if self is a subgroup of right. 
    685  
    686         EXAMPLES: 
    687             sage: G = Gamma0(20) 
    688             sage: G.is_subgroup(SL2Z) 
    689             True 
    690             sage: G.is_subgroup(Gamma0(4)) 
    691             True 
    692             sage: G.is_subgroup(Gamma0(20)) 
    693             True 
    694             sage: G.is_subgroup(Gamma0(7)) 
    695             False 
    696             sage: Gamma0(2).is_subgroup(Gamma1(2)) 
    697             True 
    698         """ 
    699         if right.level() == 1: 
    700             return True 
    701         if is_Gamma0(right): 
    702             return self.level() % right.level() == 0 
    703         if is_Gamma1(right): 
    704             if right.level() >= 3: 
    705                 return False 
    706             elif right.level() == 2: 
    707                 return self.level() == 2 
    708             # case level 1 dealt with above 
    709         raise NotImplementedError 
    710  
    711     def coset_reps(self): 
    712         r""" 
    713         Return representatives for the right cosets of this congruence 
    714         subgroup in ${\rm SL}_2(\Z)$ as a generator object. 
    715          
    716         Use \code{list(self.coset_reps())} to obtain coset reps as a 
    717         list. 
    718  
    719         EXAMPLES: 
    720             sage: list(Gamma0(5).coset_reps()) 
    721             [[1, 0, 0, 1], 
    722             [0, -1, 1, 0], 
    723             [1, 0, 1, 1], 
    724             [1, 1, 1, 2], 
    725             [1, 2, 1, 3], 
    726             [1, 3, 1, 4]] 
    727             sage: list(Gamma0(4).coset_reps()) 
    728             [[1, 0, 0, 1], 
    729             [0, -1, 1, 0], 
    730             [1, 0, 1, 1], 
    731             [1, 1, 1, 2], 
    732             [1, 2, 1, 3], 
    733             [-1, -1, 2, 1]] 
    734             sage: list(Gamma0(1).coset_reps()) 
    735             [[1, 0, 0, 1]] 
    736         """ 
    737         N = self.level() 
    738         for z in sage.modular.modsym.p1list.P1List(N): 
    739             yield lift_to_sl2z(z[0], z[1], N) 
    740  
    741     def generators(self): 
    742         r""" 
    743         Return generators for this congruence subgroup. 
    744  
    745         The result is cached. 
    746  
    747         EXAMPLE: 
    748             sage: for g in Gamma0(3).generators(): 
    749             ...     print g 
    750             ...     print '---' 
    751             [1 1] 
    752             [0 1] 
    753             --- 
    754             [-1  0] 
    755             [ 0 -1] 
    756             --- 
    757             ... 
    758             --- 
    759             [-2  1] 
    760             [-3  1] 
    761             --- 
    762  
    763         """ 
    764         try: 
    765             return self.__gens 
    766         except AttributeError: 
    767             from sage.modular.modsym.p1list import P1List 
    768             from congroup_pyx import generators_helper 
    769             level = self.level() 
    770             gen_list = generators_helper(P1List(level), level, Mat2Z) 
    771             self.__gens = [self(g, check=False) for g in gen_list] 
    772             return self.__gens 
    773  
    774     def gamma_h_subgroups(self): 
    775         r""" 
    776         Return the subgroups of the form $\Gamma_H(N)$ contained 
    777         in self, where $N$ is the level of self. 
    778  
    779         EXAMPLES: 
    780             sage: G = Gamma0(11) 
    781             sage: G.gamma_h_subgroups() 
    782             [Congruence Subgroup Gamma_H(11) with H generated by [2], Congruence Subgroup Gamma_H(11) with H generated by [4], Congruence Subgroup Gamma_H(11) with H generated by [10], Congruence Subgroup Gamma_H(11) with H generated by []] 
    783             sage: G = Gamma0(12) 
    784             sage: G.gamma_h_subgroups() 
    785             [Congruence Subgroup Gamma_H(12) with H generated by [5, 7], Congruence Subgroup Gamma_H(12) with H generated by [7], Congruence Subgroup Gamma_H(12) with H generated by [5], Congruence Subgroup Gamma_H(12) with H generated by []] 
    786         """ 
    787         N = self.level() 
    788         R = IntegerModRing(N) 
    789         return [GammaH(N, H) for H in R.multiplicative_subgroups()] 
    790  
    791     def __call__(self, x, check=True): 
    792         r""" 
    793         Create an element of this congruence subgroup from x. 
    794  
    795         If the optional flag check is True (default), check whether 
    796         x actually gives an element of self. 
    797  
    798         EXAMPLES: 
    799             sage: G = Gamma0(12) 
    800             sage: G([1, 0, 24, 1]) 
    801             [ 1  0] 
    802             [24  1] 
    803             sage: G(matrix(ZZ, 2, [1, 1, -12, -11])) 
    804             [  1   1] 
    805             [-12 -11] 
    806             sage: G([1, 0, 23, 1]) 
    807             Traceback (most recent call last): 
    808             ... 
    809             TypeError: matrix must have lower left entry (=23) divisible by 12 
    810         """ 
    811         if isinstance(x, CongruenceSubgroupElement) and x.parent() == self: 
    812             return x 
    813         x = CongruenceSubgroupElement(self, x, check=check) 
    814         if not check: 
    815             return x 
    816          
    817         c = x.c() 
    818         N = self.level() 
    819         if c%N == 0: 
    820             return x 
    821         else: 
    822             raise TypeError, "matrix must have lower left entry (=%s) divisible by %s" %(c, N) 
    823  
    824 def is_SL2Z(x): 
    825     """ 
    826     Return True if x is the modular group ${\rm SL}_2(\Z)$. 
    827  
    828     EXAMPLES: 
    829         sage: from sage.modular.congroup import is_SL2Z     
    830         sage: is_SL2Z(SL2Z) 
    831         True 
    832         sage: is_SL2Z(Gamma0(6)) 
    833         False 
    834     """ 
    835     return isinstance(x, SL2Z_class) 
    836  
    837 class SL2Z_class(Gamma0_class): 
    838     def __init__(self): 
    839         r""" 
    840         The modular group ${\rm SL}_2(\Z)$. 
    841  
    842         EXAMPLES: 
    843             sage: G = SL2Z; G 
    844             Modular Group SL(2,Z) 
    845             sage: G.gens() 
    846             ([ 0 -1] 
    847             [ 1  0], [1 1] 
    848             [0 1]) 
    849             sage: G.0 
    850             [ 0 -1] 
    851             [ 1  0] 
    852             sage: G.1 
    853             [1 1] 
    854             [0 1] 
    855             sage: latex(G) 
    856             \mbox{\rm SL}_2(\mathbf{Z}) 
    857             sage: G([1,-1,0,1]) 
    858             [ 1 -1] 
    859             [ 0  1] 
    860             sage: loads(G.dumps()) == G 
    861             True 
    862             sage: SL2Z.0 * SL2Z.1 
    863             [ 0 -1] 
    864             [ 1  1] 
    865  
    866             sage: SL2Z == loads(dumps(SL2Z)) 
    867             True 
    868             sage: SL2Z is loads(dumps(SL2Z)) 
    869             True 
    870         """ 
    871         Gamma0_class.__init__(self, 1) 
    872  
    873     def __reduce__(self): 
    874         """ 
    875         Used for pickling self. 
    876  
    877         EXAMPLES: 
    878             sage: SL2Z.__reduce__() 
    879             (<function _SL2Z_ref at ...>, ()) 
    880         """ 
    881         return _SL2Z_ref, () 
    882  
    883     def _repr_(self): 
    884         """ 
    885         Return the string representation of self. 
    886  
    887         EXAMPLES: 
    888             sage: SL2Z._repr_() 
    889             'Modular Group SL(2,Z)' 
    890         """ 
    891         return "Modular Group SL(2,Z)" 
    892  
    893     def _latex_(self): 
    894         r""" 
    895         Return the \LaTeX representation of self. 
    896          
    897         EXAMPLES: 
    898             sage: SL2Z._latex_() 
    899             '\\mbox{\\rm SL}_2(\\mathbf{Z})' 
    900             sage: latex(SL2Z) 
    901             \mbox{\rm SL}_2(\mathbf{Z}) 
    902         """ 
    903         return "\\mbox{\\rm SL}_2(%s)"%(ZZ._latex_()) 
    904  
    905     def is_subgroup(self, right): 
    906         """ 
    907         Return True if self is a subgroup of right. 
    908  
    909         EXAMPLES: 
    910             sage: SL2Z.is_subgroup(SL2Z) 
    911             True 
    912             sage: SL2Z.is_subgroup(Gamma1(1)) 
    913             True 
    914             sage: SL2Z.is_subgroup(Gamma0(6)) 
    915             False 
    916         """ 
    917         return right.level() == 1 
    918  
    919 SL2Z = SL2Z_class() 
    920  
    921 def _SL2Z_ref(): 
    922     """ 
    923     Return SL2Z. (Used for pickling SL2Z.) 
    924  
    925     EXAMPLES: 
    926         sage: sage.modular.congroup._SL2Z_ref() 
    927         Modular Group SL(2,Z) 
    928         sage: sage.modular.congroup._SL2Z_ref() is SL2Z 
    929         True 
    930     """ 
    931     return SL2Z 
    932  
    933 def is_Gamma1(x): 
    934     """ 
    935     Return True if x is a congruence subgroup of type Gamma1. 
    936  
    937     EXAMPLES: 
    938         sage: from sage.modular.congroup import is_Gamma1     
    939         sage: is_Gamma1(SL2Z) 
    940         True 
    941         sage: is_Gamma1(Gamma1(13)) 
    942         True 
    943         sage: is_Gamma1(Gamma0(6)) 
    944         False 
    945     """ 
    946     return (isinstance(x, Gamma1_class) or is_SL2Z(x)) 
    947  
    948 _gamma1_cache = {} 
    949 def Gamma1(N): 
    950     r""" 
    951     Return the congruence subgroup $\Gamma_1(N)$. 
    952  
    953     EXAMPLES: 
    954         sage: Gamma1(5) 
    955         Congruence Subgroup Gamma1(5) 
    956         sage: G = Gamma1(23) 
    957         sage: G is Gamma1(23) 
    958         True 
    959         sage: G == loads(dumps(G)) 
    960         True 
    961         sage: G is loads(dumps(G)) 
    962         True 
    963     """ 
    964     try: 
    965         return _gamma1_cache[N] 
    966     except KeyError: 
    967         _gamma1_cache[N] = Gamma1_class(N) 
    968         return _gamma1_cache[N] 
    969  
    970 class Gamma1_class(CongruenceSubgroup): 
    971     def __init__(self, level): 
    972         r""" 
    973         The congruence subgroup $\Gamma_1(N)$. 
    974  
    975         EXAMPLES: 
    976             sage: G = Gamma1(11); G 
    977             Congruence Subgroup Gamma1(11) 
    978             sage: loads(G.dumps()) == G 
    979             True 
    980         """ 
    981         CongruenceSubgroup.__init__(self, level) 
    982  
    983     def _repr_(self): 
    984         """ 
    985         Return the string representation of self. 
    986  
    987         EXAMPLES: 
    988             sage: Gamma1(133)._repr_() 
    989             'Congruence Subgroup Gamma1(133)' 
    990         """ 
    991         return "Congruence Subgroup Gamma1(%s)"%self.level() 
    992      
    993     def __reduce__(self): 
    994         """ 
    995         Used for pickling self. 
    996  
    997         EXAMPLES: 
    998             sage: Gamma1(82).__reduce__() 
    999             (<function Gamma1 at ...>, (82,)) 
    1000         """ 
    1001         return Gamma1, (self.level(),) 
    1002  
    1003     def _latex_(self): 
    1004         r""" 
    1005         Return the \LaTeX representation of self. 
    1006          
    1007         EXAMPLES: 
    1008             sage: Gamma1(3)._latex_() 
    1009             '\\Gamma_1(3)' 
    1010             sage: latex(Gamma1(3)) 
    1011             \Gamma_1(3) 
    1012         """ 
    1013         return "\\Gamma_1(%s)"%self.level() 
    1014  
    1015     def __cmp__(self, right): 
    1016         """ 
    1017         Compare self to right. 
    1018  
    1019         EXAMPLES: 
    1020             sage: G = Gamma1(111) 
    1021             sage: G.__cmp__(Gamma1(111)) 
    1022             0 
    1023             sage: G.__cmp__(135) is not 0 
    1024             True 
    1025         """ 
    1026         if not is_Gamma1(right): 
    1027             if is_CongruenceSubgroup(right): 
    1028                 c = cmp(self.level(), right.level()) 
    1029                 if c: return c 
    1030             return cmp(type(self), type(right)) 
    1031         return cmp(self.level(), right.level()) 
    1032  
    1033     def is_even(self): 
    1034         """ 
    1035         Return True precisely if this subgroup contains the matrix -1. 
    1036  
    1037         EXAMPLES: 
    1038             sage: Gamma1(1).is_even() 
    1039             True 
    1040             sage: Gamma1(2).is_even() 
    1041             True 
    1042             sage: Gamma1(15).is_even() 
    1043             False 
    1044         """ 
    1045         return self.level() in [1,2] 
    1046  
    1047     def is_subgroup(self, right): 
    1048         """ 
    1049         Return True if self is a subgroup of right. 
    1050  
    1051         EXAMPLES: 
    1052             sage: Gamma1(3).is_subgroup(SL2Z) 
    1053             True 
    1054             sage: Gamma1(3).is_subgroup(Gamma1(5)) 
    1055             False 
    1056             sage: Gamma1(3).is_subgroup(Gamma1(6)) 
    1057             False 
    1058             sage: Gamma1(6).is_subgroup(Gamma1(3)) 
    1059             True 
    1060             sage: Gamma1(6).is_subgroup(Gamma0(2)) 
    1061             True 
    1062         """ 
    1063         if right.level() == 1: 
    1064             return True 
    1065         if is_Gamma0(right) or is_Gamma1(right): 
    1066             return self.level() % right.level() == 0 
    1067         raise NotImplementedError 
    1068  
    1069     def generators(self): 
    1070         r""" 
    1071         Return generators for this congruence subgroup. 
    1072  
    1073         The result is cached. 
    1074  
    1075         EXAMPLE: 
    1076             sage: for g in Gamma1(3).generators(): 
    1077             ...     print g 
    1078             ...     print '---' 
    1079             [1 1] 
    1080             [0 1] 
    1081             --- 
    1082             [ 31 -14] 
    1083             [ 51 -23] 
    1084             --- 
    1085             [-5  4] 
    1086             [-9  7] 
    1087             --- 
    1088             ... 
    1089             --- 
    1090             [4 3] 
    1091             [9 7] 
    1092             --- 
    1093             [ -5  -2] 
    1094             [-12  -5] 
    1095             --- 
    1096  
    1097         """ 
    1098         try: 
    1099             return self.__gens 
    1100         except AttributeError: 
    1101             from sage.modular.modsym.g1list import G1list 
    1102             from congroup_pyx import generators_helper 
    1103             level = self.level() 
    1104             gen_list = generators_helper(G1list(level), level, Mat2Z) 
    1105             self.__gens = [self(g, check=False) for g in gen_list] 
    1106             return self.__gens 
    1107  
    1108     def __call__(self, x, check=True): 
    1109         r""" 
    1110         Create an element of this congruence subgroup from x. 
    1111  
    1112         If the optional flag check is True (default), check whether 
    1113         x actually gives an element of self. 
    1114  
    1115         EXAMPLES: 
    1116             sage: G = Gamma1(5) 
    1117             sage: G([1, 0, -10, 1]) 
    1118             [ 1   0] 
    1119             [-10  1] 
    1120             sage: G(matrix(ZZ, 2, [6, 1, 5, 1])) 
    1121             [6  1] 
    1122             [5  1] 
    1123             sage: G([1, 1, 6, 7]) 
    1124             Traceback (most recent call last): 
    1125             ... 
    1126             TypeError: matrix must have diagonal entries (=1, 7) congruent to 1 modulo 5, and lower left entry (=6) divisible by 5 
    1127         """ 
    1128         if isinstance(x, CongruenceSubgroupElement) and x.parent() == self: 
    1129             return x 
    1130         x = CongruenceSubgroupElement(self, x, check=check) 
    1131         if not check: 
    1132             return x 
    1133          
    1134         a = x.a() 
    1135         c = x.c() 
    1136         d = x.d() 
    1137         N = self.level() 
    1138         if (a%N == 1) and (c%N == 0) and (d%N == 1): 
    1139             return x 
    1140         else: 
    1141             raise TypeError, "matrix must have diagonal entries (=%s, %s) congruent to 1 modulo %s, and lower left entry (=%s) divisible by %s" %(a, d, N, c, N) 
    1142  
    1143594_gammaH_cache = {} 
    1144595def GammaH(level, H): 
    1145596    r""" 
    1146     Return the congruence subgroup $\Gamma_H(N)$. 
     597    Return the congruence subgroup $\Gamma_H(N)$, which is the subgroup of 
     598    $SL_2(\Z)$ consisting of matrices of the form $\begin{pmatrix} a & b \\ 
     599    c & d \end{pmatrix$ with $N | c$ and $a, b \in H$, for $H$ a specified 
     600    subgroup of $(\Z/N\Z)^\times$. 
    1147601     
    1148602    INPUT: 
    1149603        level -- an integer 
     
    1182636    Return True if x is a congruence subgroup of type GammaH. 
    1183637 
    1184638    EXAMPLES: 
    1185         sage: from sage.modular.congroup import is_GammaH     
     639        sage: from sage.modular.congroup import is_GammaH 
    1186640        sage: is_GammaH(GammaH(13, [2])) 
    1187641        True 
    1188642        sage: is_GammaH(Gamma0(6)) 
     643        True 
     644        sage: is_GammaH(sage.modular.congroup.CongruenceSubgroup(5)) 
    1189645        False 
    1190646    """ 
    1191647    return isinstance(x, GammaH_class) 
     
    1297753 
    1298754    def __cmp__(self, other): 
    1299755        """ 
    1300         Compare self to right. 
     756        Compare self to right. The ordering on congruence subgroups is first by 
     757        level, then by the set of elements of H. Note that Gamma1 and Gamma0 
     758        groups are treated as instances of GammaH for the purposes of 
     759        comparison. 
    1301760 
    1302761        EXAMPLES: 
    1303762            sage: G = GammaH(86, [9]) 
     
    1305764            0 
    1306765            sage: G.__cmp__(GammaH(86, [11])) is not 0 
    1307766            True 
     767            sage: Gamma1(11) < Gamma0(11) 
     768            True 
     769            sage: Gamma1(11) == GammaH(11, []) 
     770            True 
     771            sage: Gamma0(11) == GammaH(11, [2]) 
     772            True 
    1308773        """ 
    1309774        if not is_CongruenceSubgroup(other): 
    1310775            return cmp(type(self), type(other)) 
     776 
     777        c = cmp(self.level(), other.level()) 
     778        if c: return c 
     779 
    1311780        if is_GammaH(other): 
    1312             c = cmp(self.level(), other.level()) 
    1313             if c: return c 
    1314781            return cmp(self._list_of_elements_in_H(), other._list_of_elements_in_H()) 
    1315782        return cmp(type(self), type(other)) 
    1316783 
     
    16371104 
    16381105        return (new_u, new_v) 
    16391106 
     1107    def reduce_cusp(self, c): 
     1108        r""" 
     1109        Compute a minimal representative for the given cusp c. Returns a cusp 
     1110        c' which is equivalent to the given cusp, and is in lowest terms with 
     1111        minimal positive denominator, and minimal positive numerator for that 
     1112        denominator.  
     1113         
     1114        Two cusps $u1/v1$ and $u2/v2$ are equivalent modulo $\Gamma_H(N)$ 
     1115        if and only if 
     1116            $v1 =  h*v2 (mod N)$ and $u1 =  h^(-1)*u2 (mod gcd(v1,N))$ 
     1117        or 
     1118            $v1 = -h*v2 (mod N)$ and $u1 = -h^(-1)*u2 (mod gcd(v1,N))$ 
     1119        for some $h \in H$.  
     1120 
     1121        EXAMPLES: 
     1122            sage: GammaH(6,[5]).reduce_cusp(Cusp(5,3)) 
     1123            1/3 
     1124            sage: GammaH(12,[5]).reduce_cusp(Cusp(8,9)) 
     1125            1/3 
     1126            sage: GammaH(12,[5]).reduce_cusp(Cusp(5,12)) 
     1127            Infinity 
     1128            sage: GammaH(12,[]).reduce_cusp(Cusp(5,12)) 
     1129            5/12 
     1130            sage: GammaH(21,[5]).reduce_cusp(Cusp(-9/14)) 
     1131            1/7 
     1132        """ 
     1133 
     1134        return self._reduce_cusp(c)[0] 
     1135 
    16401136    def _reduce_cusp(self, c): 
    16411137        r""" 
    1642         Compute a minimal representative for the given cusp c. 
    1643         Returns a pair (c', t), where c' is the minimal representative 
    1644         for the given cusp, and t is either 1 or -1, as explained 
    1645         below. 
    1646  
     1138        Compute a minimal representative for the given cusp c.  
     1139        Returns a pair (c', t), where c' is the minimal representative  
     1140        for the given cusp, and t is either 1 or -1, as explained  
     1141        below. Largely for internal use. 
     1142         
    16471143        The minimal representative for a cusp is the element in $P^1(Q)$ 
    16481144        in lowest terms with minimal positive denominator, and minimal 
    16491145        positive numerator for that denominator. 
     
    16681164            sage: GammaH(21,[5])._reduce_cusp(Cusp(-9/14)) 
    16691165            (1/7, 1) 
    16701166        """ 
     1167 
    16711168        N = int(self.level()) 
    16721169        Cusps = c.parent() 
    16731170        v = int(c.denominator() % N) 
     
    17501247                sign = s 
    17511248 
    17521249        return Cusps((u_min, val_min)), sign 
     1250      
     1251    def _find_cusps(self): 
     1252        r""" 
     1253            Return a set of inequivalent cusps for self, i.e. a set of 
     1254        representatives for the orbits of self on $\mathbb{P}^1(\mathbb{Q})$. 
     1255        These are returned in a reduced form; see self.reduce_cusp for the  
     1256        definition of reduced. 
     1257         
     1258        ALGORITHM: 
     1259            Lemma 3.2 in Cremona's 1997 book shows that for the action of 
     1260            Gamma1(N) on "signed projective space" $\Q^2 / (\Q_{\ge 0}^+)$, we 
     1261            have $u_1/v_1 \sim u_2 / v_2$ if and only if $v_1 = v_2 \bmod N$ 
     1262            and $u_1 = u_2 \bmod gcd(v_1, N)$. It follows that every orbit has 
     1263            a representative $u/v$ with $v \le N$ and $0 \le u \le gcd(v, N)$. 
     1264            We iterate through all pairs $(u,v)$ satisfying this.  
    17531265             
     1266            Having found a set containing at least one of every equivalence 
     1267            class modulo Gamma1(N), we can be sure of picking up every class 
     1268            modulo GammaH(N) since this contains Gamma1(N); and the reduce_cusp 
     1269            call does the checking to make sure we don't get too many 
     1270            duplicates. 
     1271 
     1272        EXAMPLES: 
     1273            sage: Gamma1(5)._find_cusps() 
     1274            {0, Infinity, 1/2, 2/5} 
     1275            sage: Gamma1(35)._find_cusps()  
     1276            {3/35, 9/10, 9/14, 11/35, 3/14, 9/35, 3/10, 11/14, 8/35, 4/7, 8/15, Infinity, 13/14, 16/35, 13/35, 0, 4/15, 1/13, 2/35, 1/11, 1/10, 1/17, 1/16, 1/15, 1/14, 1/7, 1/6, 1/5, 1/4, 1/3, 1/2, 6/35, 1/9, 1/8, 6/7, 3/5, 3/7, 7/10, 4/35, 2/5, 17/35, 2/7, 5/7, 1/12, 4/5, 5/14, 12/35, 2/15} 
     1277            sage: Gamma1(24)._find_cusps() == Gamma1(24).cusps(bdmap=True) 
     1278            True 
     1279            sage: GammaH(24, [13,17])._find_cusps() == GammaH(24,[13,17]).cusps(bdmap=True) 
     1280            True 
     1281        """ 
     1282 
     1283        s = [] 
     1284        N=self.level() 
     1285        for d in xrange(1, 1+N): 
     1286            w = arith.gcd(d, N) 
     1287            for a in xrange(1,(w==1 and 2) or w): 
     1288                if arith.gcd([a, d, w]) != 1:  
     1289                    continue 
     1290                while arith.gcd(a, d) != 1: 
     1291                    a += w 
     1292                s.append(self.reduce_cusp(cusps.Cusp(a,d))) 
     1293        return Set(s) 
     1294        
    17541295    def __call__(self, x, check=True): 
    17551296        r""" 
    17561297        Create an element of this congruence subgroup from x. 
     
    17881329            raise TypeError, "matrix must have lower right entry (=%s) congruent modulo %s to some element of H" %(d, N) 
    17891330 
    17901331 
     1332def is_Gamma0(x): 
     1333    """ 
     1334    Return True if x is a congruence subgroup of type Gamma0. 
     1335 
     1336    EXAMPLES: 
     1337        sage: from sage.modular.congroup import is_Gamma0 
     1338        sage: is_Gamma0(SL2Z) 
     1339        True 
     1340        sage: is_Gamma0(Gamma0(13)) 
     1341        True 
     1342        sage: is_Gamma0(Gamma1(6)) 
     1343        False 
     1344    """ 
     1345    return isinstance(x, Gamma0_class) 
     1346 
     1347_gamma0_cache = {} 
     1348def Gamma0(N): 
     1349    """ 
     1350    Return the congruence subgroup Gamma0(N). 
     1351 
     1352    EXAMPLES: 
     1353        sage: G = Gamma0(51) ; G 
     1354        Congruence Subgroup Gamma0(51) 
     1355        sage: G == Gamma0(51) 
     1356        True 
     1357        sage: G is Gamma0(51) 
     1358        True 
     1359    """ 
     1360    try: 
     1361        return _gamma0_cache[N] 
     1362    except KeyError: 
     1363        _gamma0_cache[N] = Gamma0_class(N) 
     1364        return _gamma0_cache[N] 
     1365 
     1366class Gamma0_class(GammaH_class): 
     1367    def __init__(self, level): 
     1368        r""" 
     1369        The congruence subgroup $\Gamma_0(N)$. 
     1370 
     1371        EXAMPLES: 
     1372            sage: G = Gamma0(11); G 
     1373            Congruence Subgroup Gamma0(11) 
     1374            sage: loads(G.dumps()) == G 
     1375            True 
     1376        """ 
     1377        GammaH_class.__init__(self, level, [int(x) for x in IntegerModRing(level).unit_gens()]) 
     1378 
     1379    def _repr_(self): 
     1380        """ 
     1381        Return the string representation of self. 
     1382 
     1383        EXAMPLES: 
     1384            sage: Gamma0(98)._repr_() 
     1385            'Congruence Subgroup Gamma0(98)' 
     1386        """ 
     1387        return "Congruence Subgroup Gamma0(%s)"%self.level() 
     1388 
     1389    def __reduce__(self): 
     1390        """ 
     1391        Used for pickling self. 
     1392 
     1393        EXAMPLES: 
     1394            sage: Gamma0(22).__reduce__() 
     1395            (<function Gamma0 at ...>, (22,)) 
     1396        """ 
     1397        return Gamma0, (self.level(),) 
     1398 
     1399    def _latex_(self): 
     1400        r""" 
     1401        Return the \LaTeX representation of self. 
     1402         
     1403        EXAMPLES: 
     1404            sage: Gamma0(20)._latex_() 
     1405            '\\Gamma_0(20)' 
     1406            sage: latex(Gamma0(20)) 
     1407            \Gamma_0(20) 
     1408        """ 
     1409        return "\\Gamma_0(%s)"%self.level() 
     1410 
     1411    def _generators_for_H(self): 
     1412        """ 
     1413        Return generators for the subgroup H of the units mod 
     1414        self.level() that defines self. 
     1415         
     1416        EXAMPLES: 
     1417            sage: Gamma0(15)._generators_for_H() 
     1418            [11, 7] 
     1419        """ 
     1420        try: 
     1421            return self.__generators_for_H 
     1422        except AttributeError: 
     1423            self.__generators_for_H = [int(x) for x in IntegerModRing(self.level()).unit_gens()] 
     1424            return self.__generators_for_H 
     1425 
     1426    def _list_of_elements_in_H(self): 
     1427        """ 
     1428        Returns a sorted list of Python ints that are representatives 
     1429        between 0 and N-1 of the elements of H. 
     1430 
     1431        EXAMPLES: 
     1432            sage: G = Gamma0(11) 
     1433            sage: G._list_of_elements_in_H() 
     1434            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
     1435 
     1436            sage: G = Gamma0(6) 
     1437            sage: G._list_of_elements_in_H() 
     1438            [1, 5] 
     1439 
     1440            sage: G = Gamma0(1) 
     1441            sage: G._list_of_elements_in_H() 
     1442            [1] 
     1443        """ 
     1444        N = self.level() 
     1445        if N != 1: 
     1446            gcd = arith.gcd 
     1447            return [ x for x in range(1, N) if gcd(x, N) == 1 ] 
     1448        else: 
     1449            return [1] 
     1450     
     1451    def is_even(self): 
     1452        """ 
     1453        Return True precisely if this subgroup contains the matrix -1. 
     1454 
     1455        Since Gamma0(N) always contains the matrix -1, this always 
     1456        returns True. 
     1457 
     1458        EXAMPLES: 
     1459            sage: Gamma0(12).is_even() 
     1460            True 
     1461            sage: SL2Z.is_even() 
     1462            True 
     1463        """ 
     1464        return True 
     1465 
     1466    def is_subgroup(self, right): 
     1467        """ 
     1468        Return True if self is a subgroup of right. 
     1469 
     1470        EXAMPLES: 
     1471            sage: G = Gamma0(20) 
     1472            sage: G.is_subgroup(SL2Z) 
     1473            True 
     1474            sage: G.is_subgroup(Gamma0(4)) 
     1475            True 
     1476            sage: G.is_subgroup(Gamma0(20)) 
     1477            True 
     1478            sage: G.is_subgroup(Gamma0(7)) 
     1479            False 
     1480            sage: Gamma0(2).is_subgroup(Gamma1(2)) 
     1481            True 
     1482        """ 
     1483        if right.level() == 1: 
     1484            return True 
     1485        if is_Gamma0(right): 
     1486            return self.level() % right.level() == 0 
     1487        if is_Gamma1(right): 
     1488            if right.level() >= 3: 
     1489                return False 
     1490            elif right.level() == 2: 
     1491                return self.level() == 2 
     1492            # case level 1 dealt with above 
     1493        raise NotImplementedError 
     1494 
     1495    def coset_reps(self): 
     1496        r""" 
     1497        Return representatives for the right cosets of this congruence 
     1498        subgroup in ${\rm SL}_2(\Z)$ as a generator object. 
     1499         
     1500        Use \code{list(self.coset_reps())} to obtain coset reps as a 
     1501        list. 
     1502 
     1503        EXAMPLES: 
     1504            sage: list(Gamma0(5).coset_reps()) 
     1505            [[1, 0, 0, 1], 
     1506            [0, -1, 1, 0], 
     1507            [1, 0, 1, 1], 
     1508            [1, 1, 1, 2], 
     1509            [1, 2, 1, 3], 
     1510            [1, 3, 1, 4]] 
     1511            sage: list(Gamma0(4).coset_reps()) 
     1512            [[1, 0, 0, 1], 
     1513            [0, -1, 1, 0], 
     1514            [1, 0, 1, 1], 
     1515            [1, 1, 1, 2], 
     1516            [1, 2, 1, 3], 
     1517            [-1, -1, 2, 1]] 
     1518            sage: list(Gamma0(1).coset_reps()) 
     1519            [[1, 0, 0, 1]] 
     1520        """ 
     1521        N = self.level() 
     1522        for z in sage.modular.modsym.p1list.P1List(N): 
     1523            yield lift_to_sl2z(z[0], z[1], N) 
     1524 
     1525    def generators(self): 
     1526        r""" 
     1527        Return generators for this congruence subgroup. 
     1528 
     1529        The result is cached. 
     1530 
     1531        EXAMPLE: 
     1532            sage: for g in Gamma0(3).generators(): 
     1533            ...     print g 
     1534            ...     print '---' 
     1535            [1 1] 
     1536            [0 1] 
     1537            --- 
     1538            [-1  0] 
     1539            [ 0 -1] 
     1540            --- 
     1541            ... 
     1542            --- 
     1543            [-2  1] 
     1544            [-3  1] 
     1545            --- 
     1546 
     1547        """ 
     1548        try: 
     1549            return self.__gens 
     1550        except AttributeError: 
     1551            from sage.modular.modsym.p1list import P1List 
     1552            from congroup_pyx import generators_helper 
     1553            level = self.level() 
     1554            gen_list = generators_helper(P1List(level), level, Mat2Z) 
     1555            self.__gens = [self(g, check=False) for g in gen_list] 
     1556            return self.__gens 
     1557 
     1558    def gamma_h_subgroups(self): 
     1559        r""" 
     1560        Return the subgroups of the form $\Gamma_H(N)$ contained 
     1561        in self, where $N$ is the level of self. 
     1562 
     1563        EXAMPLES: 
     1564            sage: G = Gamma0(11) 
     1565            sage: G.gamma_h_subgroups() 
     1566            [Congruence Subgroup Gamma_H(11) with H generated by [2], Congruence Subgroup Gamma_H(11) with H generated by [4], Congruence Subgroup Gamma_H(11) with H generated by [10], Congruence Subgroup Gamma_H(11) with H generated by []] 
     1567            sage: G = Gamma0(12) 
     1568            sage: G.gamma_h_subgroups() 
     1569            [Congruence Subgroup Gamma_H(12) with H generated by [5, 7], Congruence Subgroup Gamma_H(12) with H generated by [7], Congruence Subgroup Gamma_H(12) with H generated by [5], Congruence Subgroup Gamma_H(12) with H generated by []] 
     1570        """ 
     1571        N = self.level() 
     1572        R = IntegerModRing(N) 
     1573        return [GammaH(N, H) for H in R.multiplicative_subgroups()] 
     1574 
     1575    def __call__(self, x, check=True): 
     1576        r""" 
     1577        Create an element of this congruence subgroup from x. 
     1578 
     1579        If the optional flag check is True (default), check whether 
     1580        x actually gives an element of self. 
     1581 
     1582        EXAMPLES: 
     1583            sage: G = Gamma0(12) 
     1584            sage: G([1, 0, 24, 1]) 
     1585            [ 1  0] 
     1586            [24  1] 
     1587            sage: G(matrix(ZZ, 2, [1, 1, -12, -11])) 
     1588            [  1   1] 
     1589            [-12 -11] 
     1590            sage: G([1, 0, 23, 1]) 
     1591            Traceback (most recent call last): 
     1592            ... 
     1593            TypeError: matrix must have lower left entry (=23) divisible by 12 
     1594        """ 
     1595        if isinstance(x, CongruenceSubgroupElement) and x.parent() == self: 
     1596            return x 
     1597        x = CongruenceSubgroupElement(self, x, check=check) 
     1598        if not check: 
     1599            return x 
     1600         
     1601        c = x.c() 
     1602        N = self.level() 
     1603        if c%N == 0: 
     1604            return x 
     1605        else: 
     1606            raise TypeError, "matrix must have lower left entry (=%s) divisible by %s" %(c, N) 
     1607 
     1608    def _find_cusps(self): 
     1609        r""" 
     1610            Return a set of inequivalent cusps for self, i.e. a set of 
     1611        representatives for the orbits of self on $\mathbb{P}^1(\mathbb{Q})$. 
     1612        These are returned in a reduced form; see self.reduce_cusp for the  
     1613        definition of reduced. 
     1614         
     1615        ALGORITHM: 
     1616            Uses explicit formulae specific to $\Gamma_0(N)$: a reduced cusp on 
     1617            $\Gamma_0(N)$ is always of the form $a/d$ where $d | N$, and $a_1/d 
     1618            \sim a_2/d$ if and only if $a_1 \cong a_2 \bmod {\rm gcd}(d, 
     1619            N/d)$. 
     1620             
     1621        EXAMPLES: 
     1622            sage: Gamma0(90)._find_cusps() 
     1623            {1/6, 1/5, 1/3, 1/2, 11/30, 1/9, 2/3, 1/30, Infinity, 5/6, 1/45, 0, 1/18, 1/10, 1/15, 2/15} 
     1624            sage: Gamma0(1).cusps() 
     1625            {Infinity} 
     1626            sage: Gamma0(180).cusps() == Gamma0(180).cusps(bdmap=True) 
     1627            True 
     1628        """ 
     1629        N = self.level() 
     1630        s = [] 
     1631        for d in divisors(N): 
     1632            w = arith.gcd(d, N/d) 
     1633            if w == 1: 
     1634                if d == 1: 
     1635                    s.append(cusps.Cusp(1,0)) 
     1636                elif d == N: 
     1637                    s.append(cusps.Cusp(0,1)) 
     1638                else: 
     1639                    s.append(cusps.Cusp(1,d)) 
     1640            else: 
     1641                for a in xrange(1, w): 
     1642                    if arith.gcd(a, w) == 1: 
     1643                        while arith.gcd(a, d/w) != 1: 
     1644                            a += w 
     1645                        s.append(cusps.Cusp(a,d)) 
     1646        return Set(s) 
     1647 
     1648def is_SL2Z(x): 
     1649    """ 
     1650    Return True if x is the modular group ${\rm SL}_2(\Z)$. 
     1651 
     1652    EXAMPLES: 
     1653        sage: from sage.modular.congroup import is_SL2Z 
     1654        sage: is_SL2Z(SL2Z) 
     1655        True 
     1656        sage: is_SL2Z(Gamma0(6)) 
     1657        False 
     1658    """ 
     1659    return isinstance(x, SL2Z_class) 
     1660 
     1661class SL2Z_class(Gamma0_class): 
     1662    def __init__(self): 
     1663        r""" 
     1664        The modular group ${\rm SL}_2(\Z)$. 
     1665 
     1666        EXAMPLES: 
     1667            sage: G = SL2Z; G 
     1668            Modular Group SL(2,Z) 
     1669            sage: G.gens() 
     1670            ([ 0 -1] 
     1671            [ 1  0], [1 1] 
     1672            [0 1]) 
     1673            sage: G.0 
     1674            [ 0 -1] 
     1675            [ 1  0] 
     1676            sage: G.1 
     1677            [1 1] 
     1678            [0 1] 
     1679            sage: latex(G) 
     1680            \mbox{\rm SL}_2(\mathbf{Z}) 
     1681            sage: G([1,-1,0,1]) 
     1682            [ 1 -1] 
     1683            [ 0  1] 
     1684            sage: loads(G.dumps()) == G 
     1685            True 
     1686            sage: SL2Z.0 * SL2Z.1 
     1687            [ 0 -1] 
     1688            [ 1  1] 
     1689 
     1690            sage: SL2Z == loads(dumps(SL2Z)) 
     1691            True 
     1692            sage: SL2Z is loads(dumps(SL2Z)) 
     1693            True 
     1694        """ 
     1695        Gamma0_class.__init__(self, 1) 
     1696 
     1697    def __reduce__(self): 
     1698        """ 
     1699        Used for pickling self. 
     1700 
     1701        EXAMPLES: 
     1702            sage: SL2Z.__reduce__() 
     1703            (<function _SL2Z_ref at ...>, ()) 
     1704        """ 
     1705        return _SL2Z_ref, () 
     1706 
     1707    def _repr_(self): 
     1708        """ 
     1709        Return the string representation of self. 
     1710 
     1711        EXAMPLES: 
     1712            sage: SL2Z._repr_() 
     1713            'Modular Group SL(2,Z)' 
     1714        """ 
     1715        return "Modular Group SL(2,Z)" 
     1716 
     1717    def _latex_(self): 
     1718        r""" 
     1719        Return the \LaTeX representation of self. 
     1720         
     1721        EXAMPLES: 
     1722            sage: SL2Z._latex_() 
     1723            '\\mbox{\\rm SL}_2(\\mathbf{Z})' 
     1724            sage: latex(SL2Z) 
     1725            \mbox{\rm SL}_2(\mathbf{Z}) 
     1726        """ 
     1727        return "\\mbox{\\rm SL}_2(%s)"%(ZZ._latex_()) 
     1728 
     1729    def is_subgroup(self, right): 
     1730        """ 
     1731        Return True if self is a subgroup of right. 
     1732 
     1733        EXAMPLES: 
     1734            sage: SL2Z.is_subgroup(SL2Z) 
     1735            True 
     1736            sage: SL2Z.is_subgroup(Gamma1(1)) 
     1737            True 
     1738            sage: SL2Z.is_subgroup(Gamma0(6)) 
     1739            False 
     1740        """ 
     1741        return right.level() == 1 
     1742 
     1743    def reduce_cusp(self, c): 
     1744        r""" Return the unique reduced cusp equivalent to c under the action of 
     1745        self. Always returns Infinity, since there is only one equivalence 
     1746        class of cusps for $SL_2(Z)$. 
     1747 
     1748        EXAMPLES: 
     1749            sage: SL2Z.reduce_cusp(Cusps(-1/4)) 
     1750            Infinity 
     1751        """ 
     1752        return cusps.Cusp(1,0) 
     1753 
     1754SL2Z = SL2Z_class() 
     1755 
     1756def _SL2Z_ref(): 
     1757    """ 
     1758    Return SL2Z. (Used for pickling SL2Z.) 
     1759 
     1760    EXAMPLES: 
     1761        sage: sage.modular.congroup._SL2Z_ref() 
     1762        Modular Group SL(2,Z) 
     1763        sage: sage.modular.congroup._SL2Z_ref() is SL2Z 
     1764        True 
     1765    """ 
     1766    return SL2Z 
     1767 
     1768def is_Gamma1(x): 
     1769    """ 
     1770    Return True if x is a congruence subgroup of type Gamma1. 
     1771 
     1772    EXAMPLES: 
     1773        sage: from sage.modular.congroup import is_Gamma1 
     1774        sage: is_Gamma1(SL2Z) 
     1775        True 
     1776        sage: is_Gamma1(Gamma1(13)) 
     1777        True 
     1778        sage: is_Gamma1(Gamma0(6)) 
     1779        False 
     1780    """ 
     1781    return (isinstance(x, Gamma1_class) or is_SL2Z(x)) 
     1782 
     1783_gamma1_cache = {} 
     1784def Gamma1(N): 
     1785    r""" 
     1786    Return the congruence subgroup $\Gamma_1(N)$. 
     1787 
     1788    EXAMPLES: 
     1789        sage: Gamma1(5) 
     1790        Congruence Subgroup Gamma1(5) 
     1791        sage: G = Gamma1(23) 
     1792        sage: G is Gamma1(23) 
     1793        True 
     1794        sage: G == loads(dumps(G)) 
     1795        True 
     1796        sage: G is loads(dumps(G)) 
     1797        True 
     1798    """ 
     1799    try: 
     1800        return _gamma1_cache[N] 
     1801    except KeyError: 
     1802        _gamma1_cache[N] = Gamma1_class(N) 
     1803        return _gamma1_cache[N] 
     1804 
     1805class Gamma1_class(GammaH_class): 
     1806    def __init__(self, level): 
     1807        r""" 
     1808        The congruence subgroup $\Gamma_1(N)$. 
     1809 
     1810        EXAMPLES: 
     1811            sage: G = Gamma1(11); G 
     1812            Congruence Subgroup Gamma1(11) 
     1813            sage: loads(G.dumps()) == G 
     1814            True 
     1815        """ 
     1816        GammaH_class.__init__(self, level, []) 
     1817 
     1818    def _repr_(self): 
     1819        """ 
     1820        Return the string representation of self. 
     1821 
     1822        EXAMPLES: 
     1823            sage: Gamma1(133)._repr_() 
     1824            'Congruence Subgroup Gamma1(133)' 
     1825        """ 
     1826        return "Congruence Subgroup Gamma1(%s)"%self.level() 
     1827     
     1828    def __reduce__(self): 
     1829        """ 
     1830        Used for pickling self. 
     1831 
     1832        EXAMPLES: 
     1833            sage: Gamma1(82).__reduce__() 
     1834            (<function Gamma1 at ...>, (82,)) 
     1835        """ 
     1836        return Gamma1, (self.level(),) 
     1837 
     1838    def _latex_(self): 
     1839        r""" 
     1840        Return the \LaTeX representation of self. 
     1841         
     1842        EXAMPLES: 
     1843            sage: Gamma1(3)._latex_() 
     1844            '\\Gamma_1(3)' 
     1845            sage: latex(Gamma1(3)) 
     1846            \Gamma_1(3) 
     1847        """ 
     1848        return "\\Gamma_1(%s)"%self.level() 
     1849 
     1850    def is_even(self): 
     1851        """ 
     1852        Return True precisely if this subgroup contains the matrix -1. 
     1853 
     1854        EXAMPLES: 
     1855            sage: Gamma1(1).is_even() 
     1856            True 
     1857            sage: Gamma1(2).is_even() 
     1858            True 
     1859            sage: Gamma1(15).is_even() 
     1860            False 
     1861        """ 
     1862        return self.level() in [1,2] 
     1863 
     1864    def is_subgroup(self, right): 
     1865        """ 
     1866        Return True if self is a subgroup of right. 
     1867 
     1868        EXAMPLES: 
     1869            sage: Gamma1(3).is_subgroup(SL2Z) 
     1870            True 
     1871            sage: Gamma1(3).is_subgroup(Gamma1(5)) 
     1872            False 
     1873            sage: Gamma1(3).is_subgroup(Gamma1(6)) 
     1874            False 
     1875            sage: Gamma1(6).is_subgroup(Gamma1(3)) 
     1876            True 
     1877            sage: Gamma1(6).is_subgroup(Gamma0(2)) 
     1878            True 
     1879        """ 
     1880        if right.level() == 1: 
     1881            return True 
     1882        if is_Gamma0(right) or is_Gamma1(right): 
     1883            return self.level() % right.level() == 0 
     1884        raise NotImplementedError 
     1885 
     1886    def generators(self): 
     1887        r""" 
     1888        Return generators for this congruence subgroup. 
     1889 
     1890        The result is cached. 
     1891 
     1892        EXAMPLE: 
     1893            sage: for g in Gamma1(3).generators(): 
     1894            ...     print g 
     1895            ...     print '---' 
     1896            [1 1] 
     1897            [0 1] 
     1898            --- 
     1899            [ 31 -14] 
     1900            [ 51 -23] 
     1901            --- 
     1902            [-5  4] 
     1903            [-9  7] 
     1904            --- 
     1905            ... 
     1906            --- 
     1907            [4 3] 
     1908            [9 7] 
     1909            --- 
     1910            [ -5  -2] 
     1911            [-12  -5] 
     1912            --- 
     1913 
     1914        """ 
     1915        try: 
     1916            return self.__gens 
     1917        except AttributeError: 
     1918            from sage.modular.modsym.g1list import G1list 
     1919            from congroup_pyx import generators_helper 
     1920            level = self.level() 
     1921            gen_list = generators_helper(G1list(level), level, Mat2Z) 
     1922            self.__gens = [self(g, check=False) for g in gen_list] 
     1923            return self.__gens 
     1924         
     1925    def __call__(self, x, check=True): 
     1926        r""" 
     1927        Create an element of this congruence subgroup from x. 
     1928 
     1929        If the optional flag check is True (default), check whether 
     1930        x actually gives an element of self. 
     1931 
     1932        EXAMPLES: 
     1933            sage: G = Gamma1(5) 
     1934            sage: G([1, 0, -10, 1]) 
     1935            [ 1   0] 
     1936            [-10  1] 
     1937            sage: G(matrix(ZZ, 2, [6, 1, 5, 1])) 
     1938            [6  1] 
     1939            [5  1] 
     1940            sage: G([1, 1, 6, 7]) 
     1941            Traceback (most recent call last): 
     1942            ... 
     1943            TypeError: matrix must have diagonal entries (=1, 7) congruent to 1 modulo 5, and lower left entry (=6) divisible by 5 
     1944        """ 
     1945        if isinstance(x, CongruenceSubgroupElement) and x.parent() == self: 
     1946            return x 
     1947        x = CongruenceSubgroupElement(self, x, check=check) 
     1948        if not check: 
     1949            return x 
     1950         
     1951        a = x.a() 
     1952        c = x.c() 
     1953        d = x.d() 
     1954        N = self.level() 
     1955        if (a%N == 1) and (c%N == 0) and (d%N == 1): 
     1956            return x 
     1957        else: 
     1958            raise TypeError, "matrix must have diagonal entries (=%s, %s) congruent to 1 modulo %s, and lower left entry (=%s) divisible by %s" %(a, d, N, c, N) 
     1959 
    17911960import congroup_pyx 
    17921961degeneracy_coset_representatives_gamma0 = congroup_pyx.degeneracy_coset_representatives_gamma0 
    17931962degeneracy_coset_representatives_gamma1 = congroup_pyx.degeneracy_coset_representatives_gamma1 
  • sage/modular/dims.py

    diff -r 3859ace86968 -r dc06bf9ff942 sage/modular/dims.py
    a b  
    14851485    else: 
    14861486        raise TypeError 
    14871487 
     1488def dimension_modular_forms_H(X, k=2): 
     1489    return dimension_cusp_forms_H(X, k) + dimension_eis_H(X, k) 
    14881490 
    14891491def dimension_modular_forms(X, k=2): 
    14901492    r""" 
     
    15031505        1 
    15041506        sage: dimension_modular_forms(Gamma1(13),2) 
    15051507        13 
    1506          
     1508        sage: dimension_modular_forms(GammaH(11, [10]), 2) 
     1509        10 
    15071510        sage: e = DirichletGroup(20).1 
    15081511        sage: dimension_modular_forms(e,3) 
    15091512        9 
     
    15211524        raise TypeError, "Argument 1 must be a congruence subgroup or Dirichlet character." 
    15221525    if k == 0: 
    15231526        return 1 
    1524     if congroup.is_GammaH(X): 
     1527    if congroup.is_Gamma0(X) or congroup.is_Gamma1(X) or isinstance(X, dirichlet.DirichletCharacter): 
     1528        return dimension_cusp_forms(X, k) + dimension_eis(X, k) 
     1529    elif congroup.is_GammaH(X): 
    15251530        return dimension_modular_forms_H(X, k) 
    1526     return dimension_cusp_forms(X, k) + dimension_eis(X, k) 
     1531    else: 
     1532        raise NotImplementedError, "Computation of dimensions for congruence subgroups other than Gamma0, Gamma1 or GammaH not implemented" 
     1533 
     1534def dimension_modular_forms_H(X, k=2): 
     1535    return dimension_cusp_forms_H(X, k) + dimension_eis_H(X, k) 
    15271536 
    15281537def sturm_bound(level, weight=2): 
    15291538    r"""