|
| 1 | +################################################################### |
| 2 | +################################################################### |
| 3 | +InstallGlobalFunction(HAP_GenericCongruenceSubgroup, |
| 4 | +function(family,integer,ring,ideal) |
| 5 | +local R, n, one, mat, type, G, I, fam; |
| 6 | + |
| 7 | +# This function returns a template for a congruence subgroup G in some |
| 8 | +# classical group such as GL(n,R), SL(n,R), Sp_n(R) over a ring of integers R. |
| 9 | +# The subgroup G is defined using some condition involving an ideal I<=R. |
| 10 | +# The input "family" is a string such as "SL", "GL", Sp". In this code we |
| 11 | +# denote any such family by "SL". |
| 12 | +# |
| 13 | +# Various components such as "membership, "tree", "cosetPos" will ineed to be |
| 14 | +# implemented using a specific secondary function that depends on the specific |
| 15 | +# family and ring. |
| 16 | +# |
| 17 | +# The *fast* method will use a formula to first implement "cosetPos" and then |
| 18 | +# compute the coset "tree", The *slow* method will use a general brute force |
| 19 | +# algorithm to first comput the "tree" and then implement "cosetPos". |
| 20 | + |
| 21 | +R:=ring; |
| 22 | +n:=integer; |
| 23 | +if IsInt(ideal) then I:=IdealByGenerators(R,[ideal]); |
| 24 | +else |
| 25 | + I:=ideal; |
| 26 | +fi; |
| 27 | +if not IsBound(I) then return fail; |
| 28 | +fi; |
| 29 | + |
| 30 | +one:=One(R); |
| 31 | +mat:=one*IdentityMat(n); |
| 32 | +fam:=Concatenation(family,"(",String(n),", ",Name(R)," )"); |
| 33 | + |
| 34 | + type := NewType( FamilyObj([ mat ]), |
| 35 | + IsGroup and |
| 36 | + IsAttributeStoringRep and |
| 37 | + IsFinitelyGeneratedGroup and |
| 38 | + IsMatrixGroup and |
| 39 | + IsHapCongruenceSubgroup); |
| 40 | + |
| 41 | +G:=rec( |
| 42 | + ringOfIntegers:=R, #Matrices in the subgroup G lie in the ring R. |
| 43 | + level:=I, #This ideal I<=R is used to define G. |
| 44 | + fam:=fam, #The string "SL(n,R)". |
| 45 | + dimension:=n, |
| 46 | + membership:= fail, #true if a matrix g lies in G. |
| 47 | + membershipLight:=fail, #true if a matrix g in SL(n,R) lies in G. |
| 48 | + gens:=fail, #"Nice" generating set for SL(n,R). |
| 49 | + tree:= fail, #Coset tree of G with respect to gens. |
| 50 | + generators:= fail, #Generating set for G. |
| 51 | + index:=fail, #Index of G in SL(n,R). |
| 52 | + cosetRep:= fail, #CosetRep(g) represents g*G for g in SL(n,R). |
| 53 | + cosetPos:= fail, #cosetPos(g) is the position of the coset g*G. |
| 54 | + ugrp:= Group(mat), #The trivial (or vertex stabilizer) group. |
| 55 | + name:="Congruence subgroup"); |
| 56 | + |
| 57 | +ObjectifyWithAttributes( G, type, |
| 58 | + DimensionOfMatrixGroup, n |
| 59 | + ); |
| 60 | + |
| 61 | +return G; |
| 62 | +end); |
| 63 | +################################################################### |
| 64 | +################################################################### |
| 65 | + |
| 66 | +################################################################### |
| 67 | +################################################################### |
| 68 | +InstallMethod( HAPCongruenceSubgroupGamma0, |
| 69 | +"for integer n and integer m", |
| 70 | +[IsInt, IsInt], |
| 71 | +function(n,m) |
| 72 | +local G,sl,membership,membershipLight,CosetRep, CosetPos; |
| 73 | +if not (n=2 and m>0) then TryNextMethod(); fi; |
| 74 | + |
| 75 | +#The following implements G=Gamm0(m) < SL(2,Z) |
| 76 | + |
| 77 | +sl:=SL(2,Integers); |
| 78 | +G:=HAP_GenericCongruenceSubgroup("SL",2,Integers,m); |
| 79 | + |
| 80 | +################################################### |
| 81 | +membership:=function(g) |
| 82 | +if not g in sl then return false; fi; |
| 83 | +if not g[2][1] mod m = 0 then return false; |
| 84 | +else return true; fi; |
| 85 | +end; |
| 86 | +################################################### |
| 87 | +################################################### |
| 88 | +membershipLight:=function(g) |
| 89 | +if not g[2][1] mod m = 0 then return false; |
| 90 | +else return true; fi; |
| 91 | +end; |
| 92 | +################################################### |
| 93 | + |
| 94 | +G!.membership:=membership; |
| 95 | +G!.membershipLight:=membershipLight; |
| 96 | +G!.level:=m; |
| 97 | + |
| 98 | +G!.ugrp:=Group([[1,0],[0,1]]); |
| 99 | +G!.name:="CongruenceSubgroupGamma0"; |
| 100 | +if m=1 then |
| 101 | +G!.index:=m; |
| 102 | +else |
| 103 | +G!.index:=m*Product(List(SSortedList(Factors(m)), p->1+1/p)); |
| 104 | +fi; |
| 105 | + |
| 106 | +if IsPrimeInt(m) then #NEEDS TO BE EXTENDED TO NONE PRIMES. THAT IS, NEED |
| 107 | + #TO IMPLEMENT THE PROJECTIVE LINE P^1(Z/mZ) |
| 108 | +########################################### |
| 109 | +CosetPos:=function(g) |
| 110 | +if g[1][1] mod m =0 then return m+1; fi; |
| 111 | +return 1 +((g[2][1]*g[1][1]^-1) mod m); |
| 112 | +end; |
| 113 | +########################################### |
| 114 | + |
| 115 | +########################################### |
| 116 | +CosetRep:=function(g) |
| 117 | +if g[1][1] mod m=0 then return [[0,-1],[1,0]]; fi; |
| 118 | +return [[1,0],[(g[2][1]*g[1][1]^-1) mod m,1]]; |
| 119 | +end; |
| 120 | +########################################### |
| 121 | +G!.cosetRep:=CosetRep; |
| 122 | +G!.cosetPos:=CosetPos; |
| 123 | +fi; |
| 124 | + |
| 125 | +G:=ObjectifyWithAttributes(G, TypeObj(G), |
| 126 | +IsIntegerMatrixGroup, true, |
| 127 | +IsFinite, false); |
| 128 | +return G; |
| 129 | + |
| 130 | +end); |
| 131 | +################################################################### |
| 132 | +################################################################### |
| 133 | + |
| 134 | +################################################################### |
| 135 | +################################################################### |
| 136 | +#THERE SHOULD BE JUST ONE IMPLEMENTATION FOR ALL CASES. |
| 137 | +#NEED TO ADJUST THIS. |
| 138 | +InstallMethod(HAPCongruenceSubgroupTree, |
| 139 | +"Coset tree for congruence subgroup", |
| 140 | +[IsHapCongruenceSubgroup], |
| 141 | +function(G) |
| 142 | +if not (G!.dimension=2 and G!.ringOfIntegers=Integers) then TryNextMethod(); fi; |
| 143 | +HAP_SL2ZSubgroupTree_fast(G); |
| 144 | +end); |
| 145 | +################################################################### |
| 146 | +################################################################### |
| 147 | + |
| 148 | +################################################################### |
| 149 | +################################################################### |
| 150 | + |
| 151 | +InstallOtherMethod( RightTransversal, |
| 152 | +"Right transversal of congruence subgroup G in SL(2,Z)", |
| 153 | +[IsMatrixGroup, IsHapCongruenceSubgroup], |
| 154 | +100000, |
| 155 | +function(G,H) |
| 156 | +if not (H!.dimension=2 and Name(G)="SL(2,Integers)") then TryNextMethod(); fi; |
| 157 | +HAPCongruenceSubgroupTree(H); |
| 158 | +return HAP_TransversalCongruenceSubgroups(G,H); |
| 159 | +end); |
| 160 | +################################################################### |
| 161 | +################################################################### |
| 162 | + |
| 163 | + |
0 commit comments