diff --git a/lib/CongruenceGroups/congGroups.gi b/lib/CongruenceGroups/congGroups.gi index d26fa38b..98c06695 100644 --- a/lib/CongruenceGroups/congGroups.gi +++ b/lib/CongruenceGroups/congGroups.gi @@ -503,7 +503,6 @@ InstallMethod( IsSubset, leaves,genTriples,generators, InLowDegreeNodesModG, csts, cnt, vertex2word, one, cosetPos, cosetRep, triple2word, i,j,u,c,a,b; -Print(IsHapCongruenceSubgroup(G),"\n"); if DimensionOfMatrixGroup(G)>2 and not (DimensionOfMatrixGroup(G) in [3,4] and IsHAPCongruenceSubgroupGamma0(G)) diff --git a/lib/Orru/SL3ZTopHomology.gi b/lib/Orru/SL3ZTopHomology.gi index 7964aeb2..8b35d961 100644 --- a/lib/Orru/SL3ZTopHomology.gi +++ b/lib/Orru/SL3ZTopHomology.gi @@ -3,119 +3,65 @@ ########################################################### InstallGlobalFunction(Gamma0_SL3ZTopRationalHomology, function(n) - local FirstCondition, SecondCondition, ThirdCondition_1, ThirdCondition_2, A, B, C, i, j, M, SolutionSpace,FiniteProjectivePlane,P; + local ProjPlane, M, S; #Returns the dimension of the degree 3 rational homology of the #congruence subgroup Gamma_0(n) in SL(3,Z). -########################################## -########################################## -FiniteProjectivePlane := function(n) - local UnitEls, x, y, z, i, c, d, u, UnitsAction, Representatives, - RepOf, r, v, w, m, min; - - - UnitEls := Units(Integers mod n); - - UnitsAction := function(c, u) - local uu; - uu:=Int(u); - return List(c, x -> (uu * x) mod n); - end; - - Representatives:=[]; - - RepOf:=[]; - for x in [1..n] do - RepOf[x]:=[]; - for y in [1..n] do - RepOf[x][y]:=[]; - od; - od; - - for x in [0..n-1] do - for y in [0..n-1] do - for z in [0..n-1] do - if Gcd(x,y,z,n) = 1 then - v := [x,y,z]; - if not IsBound(RepOf[x+1][y+1][z+1]) then - m:=Orbit(UnitEls,v,UnitsAction); - min:=Minimum(m); - AddSet(Representatives,min); - for w in m+1 do - RepOf[w[1]][w[2]][w[3]]:=min; - od; - fi; - fi; - od; - od; - od; + ProjPlane := FiniteProjectiveSpace(2,n); + M := Gamma0_SL3ZModularSymbolRelations(ProjPlane,n); + S := SparseSmithNormalForm(M); + return S.freeRank; +end); +########################################################### +########################################################### - return rec( - Reps := Set(Representatives), - RepOf:= RepOf - ); -end; -########################################## -########################################## +InstallGlobalFunction(Gamma0_SL3ZModularSymbolRelations, +function(ProjPlane, n) + local FirstCondition, SecondCondition, ThirdCondition_1, ThirdCondition_2, A, B, C, i, j, M; -P:=FiniteProjectivePlane(n); FirstCondition := function(p) local v; v := [-p[2],p[1],p[3]] mod n; - v:=v+1; - return P.RepOf[v[1]][v[2]][v[3]]; + return ProjPlane.RepOf(v); end; SecondCondition := function(p) local v; v := [p[3],p[1],p[2]] mod n; - v:=v+1; - return P.RepOf[v[1]][v[2]][v[3]]; + return ProjPlane.RepOf(v); end; ThirdCondition_1 := function(p) local v; v := [-p[2],p[1]-p[2],p[3]] mod n; - v:=v+1; - return P.RepOf[v[1]][v[2]][v[3]]; + return ProjPlane.RepOf(v); end; ThirdCondition_2 := function(p) local v; v := [p[2]-p[1],p[1],p[3]] mod n; - v:=v+1; - return P.RepOf[v[1]][v[2]][v[3]]; + return ProjPlane.RepOf(v); end; - A := SparseIdentityMat(Length(P.Reps)); - B := SparseIdentityMat(Length(P.Reps)); - C := SparseIdentityMat(Length(P.Reps)); - - for i in [1..Length(P.Reps)] do - if FirstCondition(P.Reps[i]) in P.Reps then - j := Position(P.Reps,FirstCondition(P.Reps[i])); - SparseMatAddToEntry(A,i,j,1); - fi; - if SecondCondition(P.Reps[i]) in P.Reps then - j := Position(P.Reps,SecondCondition(P.Reps[i])); - SparseMatAddToEntry(B,i,j,-1); - fi; - if ThirdCondition_1(P.Reps[i]) in P.Reps then - j := Position(P.Reps,ThirdCondition_1(P.Reps[i])); - SparseMatAddToEntry(C,i,j,1); - fi; - if ThirdCondition_2(P.Reps[i]) in P.Reps then - j := Position(P.Reps,ThirdCondition_2(P.Reps[i])); - SparseMatAddToEntry(C,i,j,1); - fi; + A := SparseIdentityMat(Length(ProjPlane.Reps)); + B := SparseIdentityMat(Length(ProjPlane.Reps)); + C := SparseIdentityMat(Length(ProjPlane.Reps)); + + for i in [1..Length(ProjPlane.Reps)] do + j := Position(ProjPlane.Reps,FirstCondition(ProjPlane.Reps[i])); + SparseMatAddToEntry(A,i,j,1); + j := Position(ProjPlane.Reps,SecondCondition(ProjPlane.Reps[i])); + SparseMatAddToEntry(B,i,j,-1); + j := Position(ProjPlane.Reps,ThirdCondition_1(ProjPlane.Reps[i])); + SparseMatAddToEntry(C,i,j,1); + j := Position(ProjPlane.Reps,ThirdCondition_2(ProjPlane.Reps[i])); + SparseMatAddToEntry(C,i,j,1); od; M:=SparseMatConcatenation(A,B);Unbind(A);Unbind(B); M:=SparseMatConcatenation(M,C);Unbind(C); - return Length(P.Reps) - RankMatDestructive(M); -end); -########################################################### -########################################################### + return M; +end); \ No newline at end of file diff --git a/lib/Orru/SparseSNF.gi b/lib/Orru/SparseSNF.gi new file mode 100644 index 00000000..3f992897 --- /dev/null +++ b/lib/Orru/SparseSNF.gi @@ -0,0 +1,231 @@ +# Smith normal form of a sparse integer matrix. +# +# Rows are relations, columns are generators (as in ThirdHomologySparseMatrix), +# so coker = Z^cols / (row span) and the SNF describes that quotient. +# +# Method: +# 1. Sparse elimination of unit pivots. If a relation r has coefficient +# e = +-1 on column b, then [b] = -e*(rest of r) in the cokernel: we record +# this substitution, add multiples of r to the other relations to clear +# column b, and delete r and b. Each step contributes one 1 to the SNF. +# 2. Dense SmithNormalFormIntegerMatTransforms on what is left (the +# "survivor" columns), which is where any torsion lives. +# +# The full transforms P, Q are dense (rows x rows, cols x cols), so they are +# not returned. With transforms = true you get instead what is needed to work +# in the cokernel: +# generators : the generators g_j of the nontrivial summands Z/d_j +# (d_j <> 1), as dense vectors in Z^cols (rows of Q^-1); +# divisors : the d_j (0 = free summand); +# Coordinates : v in Z^cols -> coordinates of the class of v in the g_j, +# reduced mod d_j (this is v*Q restricted to the g_j). + +# SparseSmithNormalForm(S) or SparseSmithNormalForm(S, true) +# S is a HAP sparse matrix (S!.mat, S!.rows, S!.cols). +InstallGlobalFunction(SparseSmithNormalForm, +function(arg) + local S, transforms, ncols, rels, cobounds, subs, alive, changed, order, + k, row, cands, i, b, e, bnd, j, pos, c, x, survivors, posOf, + smallM, v, nsurv, SNF, Qs, Qsinv, smallDiag, smallRank, nelim, + idx, divisors, generators, Coordinates, result, r, SNF_NormalizeRow, SNF_AddRows; + + # Sort a sparse row [[col,val],...], add up repeated columns, drop zeros. + SNF_NormalizeRow := function(row) + local out, x; + + out := []; + for x in SortedList(row) do + if Length(out) > 0 and out[Length(out)][1] = x[1] then + out[Length(out)][2] := out[Length(out)][2] + x[2]; + else + Add(out, [x[1], x[2]]); + fi; + od; + return Filtered(out, x -> x[2] <> 0); + end; + + # Sum of two normalized sparse rows. + SNF_AddRows := function(B, Y) + local U, pB, pY, lB, lY; + + lB := Length(B); lY := Length(Y); + U := []; pB := 1; pY := 1; + while pB <= lB and pY <= lY do + if B[pB][1] < Y[pY][1] then + Add(U, B[pB]); pB := pB + 1; + elif B[pB][1] > Y[pY][1] then + Add(U, Y[pY]); pY := pY + 1; + else + if B[pB][2] + Y[pY][2] <> 0 then + Add(U, [B[pB][1], B[pB][2] + Y[pY][2]]); + fi; + pB := pB + 1; pY := pY + 1; + fi; + od; + Append(U, B{[pB..lB]}); + Append(U, Y{[pY..lY]}); + return U; + end; + + S := arg[1]; + transforms := Length(arg) > 1 and arg[2] = true; + ncols := S!.cols; + + rels := List(Filtered(S!.mat, r -> Length(r) > 0), SNF_NormalizeRow); + rels := Filtered(rels, r -> Length(r) > 0); + + # cobounds[x] = relations in which column x (may) occur. + cobounds := List([1..ncols], x -> []); + for k in [1..Length(rels)] do + for x in rels[k] do + AddSet(cobounds[x[1]], k); + od; + od; + + subs := []; + alive := ListWithIdenticalEntries(ncols, true); + + ########## 1. Sparse elimination of unit pivots ########## + changed := true; + while changed do + changed := false; + # Short relations first: less fill-in. + order := Filtered([1..Length(rels)], k -> rels[k] <> 0); + SortBy(order, k -> Length(rels[k])); + for k in order do + row := rels[k]; + if row = 0 then continue; fi; + cands := Filtered([1..Length(row)], i -> AbsInt(row[i][2]) = 1); + if cands = [] then continue; fi; + # Among the unit entries, eliminate the column occurring least often. + i := cands[PositionMinimum(List(cands, i -> Length(cobounds[row[i][1]])))]; + + # row = e*[b] + rest = 0 with e = +-1, so [b] = -e*rest. + b := row[i][1]; + e := row[i][2]; + bnd := List(Concatenation(row{[1..i-1]}, row{[i+1..Length(row)]}), + x -> [x[1], -e*x[2]]); + Add(subs, [b, bnd]); + alive[b] := false; + rels[k] := 0; + changed := true; + + # Substitute [b] = bnd in every other relation containing b. + for j in cobounds[b] do + if rels[j] = 0 then continue; fi; + pos := PositionProperty(rels[j], x -> x[1] = b); + if pos = fail then continue; fi; + c := rels[j][pos][2]; + rels[j] := SNF_AddRows( + Concatenation(rels[j]{[1..pos-1]}, rels[j]{[pos+1..Length(rels[j])]}), + List(bnd, x -> [x[1], c*x[2]])); + for x in bnd do + AddSet(cobounds[x[1]], j); + od; + if rels[j] = [] then rels[j] := 0; fi; + od; + cobounds[b] := []; + od; + od; + nelim := Length(subs); + + ########## 2. Dense SNF on the survivor columns ########## + survivors := Filtered([1..ncols], x -> alive[x]); + nsurv := Length(survivors); + posOf := []; + for i in [1..nsurv] do + posOf[survivors[i]] := i; + od; + + smallM := []; + for row in Filtered(rels, r -> r <> 0) do + v := ListWithIdenticalEntries(nsurv, 0); + for x in row do + v[posOf[x[1]]] := x[2]; + od; + Add(smallM, v); + od; + + for i in [1..Length(smallM)] do + r := smallM[i]; + r := SignInt(First(r, x -> x <> 0))*r; + smallM[i] := r; + od; + + smallM := Set(smallM); + + if nsurv = 0 or smallM = [] then + Qs := IdentityMat(nsurv); + smallDiag := []; + smallRank := 0; + else + SNF := SmithNormalFormIntegerMatTransforms(smallM); + Qs := SNF.coltrans; + smallRank := SNF.rank; + smallDiag := List([1..smallRank], j -> AbsInt(SNF.normal[j][j])); + fi; + + result := rec( + rows := S!.rows, + cols := ncols, + rank := nelim + smallRank, + # Nonzero diagonal entries of the SNF, in divisibility order. + elementaryDivisors := Concatenation(ListWithIdenticalEntries(nelim, 1), smallDiag), + torsion := Filtered(smallDiag, d -> d <> 1), + freeRank := ncols - nelim - smallRank, + survivors := survivors, + smallMatrix := smallM + ); + + if not transforms then + return result; + fi; + + ########## Generators and coordinates of the cokernel ########## + # divisors[j] for the survivor-level Smith columns j = 1..nsurv. + divisors := List([1..nsurv], j -> 0); + for j in [1..smallRank] do + divisors[j] := smallDiag[j]; + od; + idx := Filtered([1..nsurv], j -> divisors[j] <> 1); + + if nsurv = 0 then Qsinv := []; else Qsinv := Qs^-1; fi; + generators := []; + for j in idx do + v := ListWithIdenticalEntries(ncols, 0); + for i in [1..nsurv] do + v[survivors[i]] := Qsinv[j][i]; + od; + Add(generators, v); + od; + + Coordinates := function(w) + local s, c, x, u, i; + + w := ShallowCopy(w); + # Substitutions in elimination order: bnd of the j-th elimination + # only involves survivors and columns eliminated later. + for s in subs do + c := w[s[1]]; + if c <> 0 then + w[s[1]] := 0; + for x in s[2] do + w[x[1]] := w[x[1]] + c*x[2]; + od; + fi; + od; + if nsurv = 0 then return []; fi; + u := (w{survivors}*Qs){idx}; + for i in [1..Length(idx)] do + if divisors[idx[i]] <> 0 then + u[i] := u[i] mod divisors[idx[i]]; + fi; + od; + return u; + end; + + result.divisors := divisors{idx}; + result.generators := generators; + result.Coordinates := Coordinates; + return result; +end); diff --git a/lib/Orru/decsOrru.gd b/lib/Orru/decsOrru.gd index 33d02885..f52c6595 100644 --- a/lib/Orru/decsOrru.gd +++ b/lib/Orru/decsOrru.gd @@ -24,6 +24,10 @@ DeclareOperation("HAPCongruenceSubgroupGamma0_alt",[IsInt,IsInt]); DeclareOperation("HAPIntersectionConjugatedCongruenceSubgroup",[IsHapCongruenceSubgroup,IsMatrix]); DeclareOperation("HAPCongruenceSubgroupTree",[IsHapCongruenceSubgroup]); DeclareGlobalFunction("Gamma0_SL3ZTopRationalHomology"); +DeclareGlobalFunction("Gamma0_SL3ZModularSymbolRelations"); +DeclareGlobalFunction("SparseSmithNormalForm"); + + InstallMethod( ViewObj, "for HapCongruenceSubgroup", diff --git a/lib/Orru/initOrru.gi b/lib/Orru/initOrru.gi index 59428c2a..c6d28d0b 100644 --- a/lib/Orru/initOrru.gi +++ b/lib/Orru/initOrru.gi @@ -6,3 +6,5 @@ ReadPackageHap( "lib/Orru/sl2methodsExtra.gi"); ReadPackageHap( "lib/Orru/sl3methods.gi"); ReadPackageHap( "lib/Orru/sl4methods.gi"); ReadPackageHap( "lib/Orru/slnmethods.gi"); +ReadPackageHap( "lib/Orru/SparseSNF.gi"); + diff --git a/lib/Orru/sl3methods.gi b/lib/Orru/sl3methods.gi index 16cbb4c0..342bd1ff 100644 --- a/lib/Orru/sl3methods.gi +++ b/lib/Orru/sl3methods.gi @@ -16,7 +16,7 @@ InstallMethod(ProjectiveSpace, n := LevelOfCongruenceSubgroup(G); - return FiniteProjectivePlane(n); + return FiniteProjectiveSpace(2,n); end); ########################################################################## ## diff --git a/lib/Orru/tutorial/tutex/gamma0.1.2.txt b/lib/Orru/tutorial/tutex/gamma0.1.2.txt new file mode 100644 index 00000000..2b0c9721 --- /dev/null +++ b/lib/Orru/tutorial/tutex/gamma0.1.2.txt @@ -0,0 +1,4 @@ +gap> H := CongruenceSubgroupGamma0(SL(5,Integers),3); +<group of 5x5 matrices in characteristic 0> +gap> IndexInAmbientGroup(H); +121 \ No newline at end of file diff --git a/lib/Orru/tutorial/tutex/gamma0.1.txt b/lib/Orru/tutorial/tutex/gamma0.1.txt new file mode 100644 index 00000000..1ce851bb --- /dev/null +++ b/lib/Orru/tutorial/tutex/gamma0.1.txt @@ -0,0 +1,2 @@ +gap> G := CongruenceSubgroupGamma0(SL(3,Integers),6); +<group of 3x3 matrices in characteristic 0> \ No newline at end of file diff --git a/lib/Orru/tutorial/tutex/gamma0.2.txt b/lib/Orru/tutorial/tutex/gamma0.2.txt new file mode 100644 index 00000000..d2bc541c --- /dev/null +++ b/lib/Orru/tutorial/tutex/gamma0.2.txt @@ -0,0 +1,8 @@ +gap> M := [[1, 0, 0], [30, 1, 0], [12, 0, 1]];; +gap> G!.membership(M); +true +gap> A := [[1, 1, 0], [1, 2, 0], [0, 0, 1]];; +gap> G!.membership(A); +false +gap> G!.membership([[1, 0, 0], [6, 1, 0], [0, 0, 2]]); +false \ No newline at end of file diff --git a/lib/Orru/tutorial/tutex/gamma0.3.txt b/lib/Orru/tutorial/tutex/gamma0.3.txt new file mode 100644 index 00000000..ccb922a3 --- /dev/null +++ b/lib/Orru/tutorial/tutex/gamma0.3.txt @@ -0,0 +1,6 @@ +gap> Length(G!.ProjectiveSpace.Reps); #Note that this coincides with the index +91 +gap> G!.ProjectiveSpace.Reps{[1..5]}; #The first five elements of the representatives +[ [ 0, 0, 1 ], [ 0, 1, 0 ], [ 0, 1, 1 ], [ 0, 1, 2 ], [ 0, 1, 3 ] ] +gap> G!.ProjectiveSpace.RepOf([5,2,7]); +[ 1, 4, 5 ] \ No newline at end of file diff --git a/lib/Orru/tutorial/tutex/gamma0.4.txt b/lib/Orru/tutorial/tutex/gamma0.4.txt new file mode 100644 index 00000000..a26b6538 --- /dev/null +++ b/lib/Orru/tutorial/tutex/gamma0.4.txt @@ -0,0 +1,8 @@ +gap> G!.AmbientRepresentation(M); +[ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ] +gap> G!.AmbientPosition(M); #Position in Reps +13 +gap> G!.AmbientRepresentation(A); +[ [ 1, 0, 0 ], [ 1, 1, 0 ], [ 0, 0, 1 ] ] +gap> G!.AmbientPosition(A); #Position in Reps +19 \ No newline at end of file diff --git a/lib/Orru/tutorial/tutex/gamma0.5.txt b/lib/Orru/tutorial/tutex/gamma0.5.txt new file mode 100644 index 00000000..8023046b --- /dev/null +++ b/lib/Orru/tutorial/tutex/gamma0.5.txt @@ -0,0 +1,2 @@ +gap> G!.AmbientTransversal; +Transversal of <group of 3x3 matrices in characteristic 0> in SL(3,Integers). \ No newline at end of file diff --git a/lib/Orru/tutorial/tutex/projspaces.1.txt b/lib/Orru/tutorial/tutex/projspaces.1.txt new file mode 100644 index 00000000..39a7d14c --- /dev/null +++ b/lib/Orru/tutorial/tutex/projspaces.1.txt @@ -0,0 +1,4 @@ +gap> FiniteProjectiveSpace(2,2); +rec( RepOf := function( v ) ... end, + Reps := [ [ 0, 0, 1 ], [ 0, 1, 0 ], [ 0, 1, 1 ], [ 1, 0, 0 ], + [ 1, 0, 1 ], [ 1, 1, 0 ], [ 1, 1, 1 ] ] ) \ No newline at end of file diff --git a/lib/Orru/tutorial/tutex/projspaces.2.txt b/lib/Orru/tutorial/tutex/projspaces.2.txt new file mode 100644 index 00000000..57c1d481 --- /dev/null +++ b/lib/Orru/tutorial/tutex/projspaces.2.txt @@ -0,0 +1,7 @@ +gap> P := FiniteProjectiveSpace(2,6);; +gap> Length(P.Reps); +91 +gap> P.RepOf([5,2,7]); +[ 1, 4, 5 ] +gap> Length(FiniteProjectiveSpace(4,3).Reps); +121 \ No newline at end of file diff --git a/lib/Orru/tutorial/tutex/sl3.1.txt b/lib/Orru/tutorial/tutex/sl3.1.txt index 74b1829d..f8e3606a 100644 --- a/lib/Orru/tutorial/tutex/sl3.1.txt +++ b/lib/Orru/tutorial/tutex/sl3.1.txt @@ -1,3 +1,2 @@ - gap> Gamma0_SL3ZTopRationalHomology(31); -4 +4 \ No newline at end of file diff --git a/lib/Orru/tutorial/tutex/sl3.2.txt b/lib/Orru/tutorial/tutex/sl3.2.txt index bcf35f53..345b45e6 100644 --- a/lib/Orru/tutorial/tutex/sl3.2.txt +++ b/lib/Orru/tutorial/tutex/sl3.2.txt @@ -1,15 +1,14 @@ - -gap> G:=HAPCongruenceSubgroupGamma0(3,31);; -gap> K:=ContractibleGcomplex("SL(3,Z)s");; -gap> Y:=GComplexToRegularCWComplex(K,G);; -gap> Y:=SimplifiedComplex(Y); +gap> G := CongruenceSubgroupGamma0(SL(3,Integers),31);; +gap> K := ContractibleGcomplex("SL(3,Z)s");; +gap> Y := GComplexToRegularCWComplex(K,G);; +gap> Y := SimplifiedComplex(Y); Regular CW-complex of dimension 3 gap> Size(Y); #number of cells -1353 +1349 gap> Homology(Y,1); [ 5 ] gap> Homology(Y,2); [ 3 ] gap> Homology(Y,3); -[ 0, 0, 0, 0 ] +[ 0, 0, 0, 0 ] \ No newline at end of file diff --git a/lib/Orru/tutorial/tutex/sl3.3.txt b/lib/Orru/tutorial/tutex/sl3.3.txt index 88249645..4ab56c89 100644 --- a/lib/Orru/tutorial/tutex/sl3.3.txt +++ b/lib/Orru/tutorial/tutex/sl3.3.txt @@ -1,13 +1,12 @@ - -gap> G:=HAPCongruenceSubgroupGamma0(3,31);; -gap> K:=ContractibleGcomplex("SL(3,Z)s");; -gap> R:=FreeGResolution(K,4);; -gap> S:=ResolutionFiniteSubgroup(R,G);; -gap> C:=TensorWithIntegers(S);; -gap> D:=ContractedComplex(C);; +gap> G := CongruenceSubgroupGamma0(SL(3,Integers),31);; +gap> K := ContractibleGcomplex("SL(3,Z)s");; +gap> R := FreeGResolution(K,4);; +gap> S := ResolutionFiniteSubgroup(R,G);; +gap> C := TensorWithIntegers(S);; +gap> D := ContractedComplex(C);; gap> Homology(D,1); [ 30 ] gap> Homology(D,2); [ 2, 2, 2, 2, 2, 2, 2, 2 ] gap> Homology(D,3); -[ 6, 6, 12, 12, 0, 0, 0, 0 ] +[ 6, 6, 12, 12, 0, 0, 0, 0 ] \ No newline at end of file diff --git a/lib/Orru/tutorial/tutorialSL3.xml b/lib/Orru/tutorial/tutorialSL3.xml index 3d80b975..264758b3 100755 --- a/lib/Orru/tutorial/tutorialSL3.xml +++ b/lib/Orru/tutorial/tutorialSL3.xml @@ -1,81 +1,128 @@ -Congruence Subgroups of SL_3(\mathbb Z) (by Giulia Orrù) +Congruence Subgroups of SL_n(\mathbb Z) (by Giulia Orrù) +
The congruence subgroups \Gamma_0(N) +Let N \geq 1. The congruence subgroup \Gamma_0(N)\subset SL_n(\mathbb Z) consists of the matrices (a_{ij}) with a_{i1} \equiv 0 \bmod N for all i \neq 1. The following command builds \Gamma_0(6) \subset SL_3(\mathbb Z): + +<#Include SYSTEM "../lib/Orru/tutorial/tutex/gamma0.1.txt"> + +We can test whether a matrix belongs to \Gamma_0(6). The test also checks that the matrix is in SL_3(\mathbb Z): + +<#Include SYSTEM "../lib/Orru/tutorial/tutex/gamma0.2.txt"> + - Let \Gamma_0(N) = \{\left(\begin{array}{lll} - a_{11} &a_{12} &a_{13}\\ - a_{21} &a_{22} &a_{23}\\ - a_{31} &a_{32} &a_{33} - \end{array}\right) \in SL_3(\mathbb Z)\ \colon \ a_{21}\equiv a_{31} \equiv 0 \mod N \}. - -
Rational homology in degree 3 - The homology H_3(\Gamma_0(N),\mathbb Q) was computed for all 10 \le N\le 209 and many 210\le N\le 250 in . The following command, based on the same method, computes H_3(\Gamma_0(31),\mathbb Q) =\mathbb Q^{4}. +The following commands compute the index of \Gamma_0(3) in SL_5(\mathbb Z): + +<#Include SYSTEM "../lib/Orru/tutorial/tutex/gamma0.1.2.txt"> + + +The object G also stores the following data: + +A representative of each point of the space \mathbb{P}^2(\mathbb Z / 6 +\mathbb Z) \cong SL_3(\mathbb Z)/\Gamma_0(6), where the coset g\Gamma_0(6) corresponds to the first column of g, see Section . These are stored in Reps, together with a function RepOf that takes +a unimodular vector in \mathbb Z^3 and returns its representative: + +<#Include SYSTEM "../lib/Orru/tutorial/tutex/gamma0.3.txt"> + + +Two functions for the left cosets of G. For a matrix g in +SL_3(\mathbb Z), AmbientRepresentation returns a canonical +representative of the coset gG, and AmbientPosition returns the +position in Reps of the corresponding point. Since M lies in +G, its coset is the trivial one, with the identity as representative. +The first column of A is (1,1,0), the 19th element of Reps: + +<#Include SYSTEM "../lib/Orru/tutorial/tutex/gamma0.4.txt"> + + +A right transversal of G in its ambient group, that is, one representative t of each right coset Gt. Note that the previous item uses left cosets gG instead: the inverses t^{-1} of the elements of the transversal are representatives of the left cosets. + +<#Include SYSTEM "../lib/Orru/tutorial/tutex/gamma0.5.txt"> + + + + + +
+ +
Projective spaces over \mathbb Z/N\mathbb Z +The space \mathbb P^d(\mathbb Z / N\mathbb Z) is the set of vectors (x_0,\ldots,x_d) \in (\mathbb Z/N\mathbb Z)^{d+1} such that \gcd(x_0,\ldots,x_d,N) = 1, modulo multiplication by units of \mathbb Z / N \mathbb Z. +

The function FiniteProjectiveSpace takes the dimension d and the +level N. It returns a record containing a list Reps with one representative of each point, and a function RepOf that returns the representative of a given vector. For example, the following command computes the Fano plane, that is, the finite projective plane of order 2: + +<#Include SYSTEM "../lib/Orru/tutorial/tutex/projspaces.1.txt"> + +It is worth noting that, when N is prime, \mathbb P^d(\mathbb Z/N\mathbb Z) is the finite projective space over the field with N elements. +Two other examples: + +<#Include SYSTEM "../lib/Orru/tutorial/tutex/projspaces.2.txt"> + +The function FiniteProjectiveSpace is used in the construction of the +congruence subgroups \Gamma_0(N), see Section . +Note that the length of Reps equals, in both cases, the index of the +corresponding subgroup built there. This is because SL_n(\mathbb Z)/\Gamma_0(N) \cong \mathbb P^{n-1}(\mathbb Z/N\mathbb Z). +

+ + + +
Rational homology in degree 3 +The homology H_3(\Gamma_0(N),\mathbb Q) for \Gamma_0(N) \subset SL_3(\mathbb Z) was computed for all 10 \le N\le 209 and many 210\le N\le 250 in . The following command, based on the same method, computes H_3(\Gamma_0(31),\mathbb Q) =\mathbb Q^{4}. - <#Include SYSTEM "../lib/Orru/tutorial/tutex/sl3.1.txt"> +<#Include SYSTEM "../lib/Orru/tutorial/tutex/sl3.1.txt">

This command can be used to extend the computations to the following table of dimensions of H_3(\Gamma_0(N),\mathbb Q) for all 10\le N\le 300. The table corrects slips in - for N=27,92,93,240,250. + for N=27,92,93,240,250 (in bold).

- \begin{array}{l|llllllllll} - x= &0 &1 &2 &3 &4 &5 &6 &7 &8 &9 \\ - N &&&&&&&&&&\hline\\ - 10+x &2 &2 &7 &0 &4 &4 &6 &2 &7&2 \\ -20+x &9 &4&8&4&17&4&6&5&13&4\\ -30+x &20&4&12&10&10&8&21&4&12&8\\ -40+x &&&&&&&&&&\\ -50+x &&&&&&&&&&\\ -60+x &&&&&&&&&&\\ -70+x &&&&&&&&&&\\ -80+x &&&&&&&&&&\\ -90+x &&&&&&&&&&\\ -100+x &&&&&&&&&&\\ -110+x &&&&&&&&&&\\ -120+x &&&&&&&&&&\\ -130+x &&&&&&&&&&\\ -140+x &&&&&&&&&&\\ -150+x &&&&&&&&&&\\ -160+x &&&&&&&&&&\\ -170+x &&&&&&&&&&\\ -180+x &&&&&&&&&&\\ -190+x &&&&&&&&&&\\ -200+x &&&&&&&&&&\\ -210+x &&&&&&&&&&\\ -220+x &&&&&&&&&&\\ -230+x &&&&&&&&&&\\ -240+x &&&&&&&&&&\\ -250+x &&&&&&&&&&\\ -260+x &&&&&&&&&&\\ -270+x &&&&&&&&&&\\ -280+x &&&&&&&&&&\\ -290+x &142&78&121&48&239&70&141&107&98&60\\ -300+x &325&&&&&&&&& - \end{array} +\begin{array}{r|rrrrrrrrrr} +{}_{N}\diagdown{}^{x} &0 &1 &2 &3 &4 &5 &6 &7 &8 &9 \\ \hline +10+x &2 &2 &7 &0 &4 &4 &6 &2 &7 &2 \\ +20+x &9 &4 &8 &4 &17 &4 &6 &\mathbf{5} &13 &4 \\ +30+x &20 &4 &12 &10 &10 &8 &21 &4 &12 &8 \\ +40+x &23 &6 &26 &6 &21 &15 &16 &8 &34 &9 \\ +50+x &20 &14 &21 &10 &25 &14 &31 &14 &20 &10 \\ +60+x &55 &10 &20 &19 &26 &12 &42 &10 &29 &20 \\ +70+x &38 &12 &51 &10 &22 &28 &33 &18 &44 &14 \\ +80+x &48 &23 &26 &14 &71 &18 &28 &24 &49 &16 \\ +90+x &67 &16 &\mathbf{41} &\mathbf{24} &32 &22 &68 &14 &43 &33 \\ +100+x &59 &16 &60 &16 &51 &48 &42 &18 &69 &16 \\ +110+x &58 &28 &64 &18 &66 &28 &57 &35 &40 &26 \\ +120+x &125 &29 &44 &40 &53 &28 &89 &20 &58 &34 \\ +130+x &60 &22 &107 &26 &44 &51 &67 &22 &82 &22 \\ +140+x &101 &40 &50 &30 &111 &32 &46 &55 &61 &24 \\ +150+x &122 &24 &75 &51 &76 &36 &119 &24 &62 &50 \\ +160+x &100 &36 &101 &26 &69 &74 &56 &28 &161 &40 \\ +170+x &80 &53 &73 &28 &106 &56 &102 &50 &64 &30 \\ +180+x &177 &28 &82 &54 &93 &40 &106 &40 &81 &67 \\ +190+x &94 &32 &146 &30 &62 &80 &121 &32 &139 &32 \\ +200+x &141 &54 &66 &44 &155 &48 &68 &67 &108 &44 \\ +210+x &204 &34 &109 &60 &72 &50 &163 &44 &70 &58 \\ +220+x &149 &44 &124 &38 &130 &107 &74 &38 &173 &36 \\ +230+x &114 &94 &129 &38 &155 &56 &101 &70 &110 &40 \\ +240+x &\mathbf{256} &38 &119 &79 &117 &83 &158 &46 &119 &70 \\ +250+x &\mathbf{122} &42 &233 &54 &84 &106 &134 &42 &146 &52 \\ +260+x &165 &83 &88 &44 &243 &66 &120 &80 &113 &44 \\ +270+x &217 &44 &140 &100 &90 &86 &207 &44 &92 &87 \\ +280+x &227 &46 &162 &46 &127 &118 &126 &62 &235 &74 \\ +290+x &142 &78 &121 &48 &239 &70 &141 &107 &98 &60 \\ +300+x &325 & & & & & & & & & +\end{array} -

-
Integral homology modulo the primes 2 and 3 - The group SL_3(\mathbb Z) acts cellularly on a 3-dimensional contractible - regular CW complex K - with each cell stabilizer group finite of order dividing 24. Hence, the finite index subgroup -\Gamma_0(N) also acts on this space. -The quotient Y=K/\Gamma_0(N) - has integral homology H_n(Y,\mathbb Z) equal to the group homology H_n(\Gamma_0(N),\mathbb Z) modulo any 2-torsion and 3-torsion. For N=31 the - following example computes H_1(Y,\mathbb Z)=\mathbb Z_{5}, H_2(Y,\mathbb Z)=\mathbb Z_3 and H_3(Y,\mathbb Z)= \mathbb Z^4. +
+
Integral homology away from the primes 2 and + 3 +The group SL_3(\mathbb Z) acts cellularly on a 3-dimensional contractible regular CW complex K, with finite cell stabilizers of order dividing 24. Hence the finite index subgroup \Gamma_0(N) also acts on K. The quotient Y=K/\Gamma_0(N) has the same integral homology as \Gamma_0(N) away from the primes 2 and 3: the free parts and the p-torsion for p \geq 5 agree, while the 2 and 3-torsion may differ. For N=31, the following example computes H_1(Y,\mathbb Z)=\mathbb Z_{5}, H_2(Y,\mathbb Z)=\mathbb Z_3 and H_3(Y,\mathbb Z)= \mathbb Z^4. <#Include SYSTEM "../lib/Orru/tutorial/tutex/sl3.2.txt"> +
-
- -
Low-dimensional integral homology - The following example computes H_1(\Gamma_0(31),\mathbb Z)= \mathbb Z_{30}, - H_2(\Gamma_0(31),\mathbb Z)= (\mathbb Z_2)^8 , - H_3(\Gamma_0(31),\mathbb Z)=(\mathbb Z_6)^2 \oplus (\mathbb Z_{12})^2 - \oplus \mathbb Z^4. +
Low-dimensional integral homology +To compute the homology exactly, including the 2- and 3-torsion, we need a free \mathbb Z\Gamma_0(N)-resolution. Its tensor product with \mathbb Z gives H_n(\Gamma_0(N),\mathbb Z), at a higher computational cost than the quotient Y. The following example computes H_1(\Gamma_0(31),\mathbb Z)= \mathbb Z_{30}, H_2(\Gamma_0(31),\mathbb Z)= (\mathbb Z_2)^8 , H_3(\Gamma_0(31),\mathbb Z)=(\mathbb Z_6)^2 \oplus (\mathbb Z_{12})^2 \oplus \mathbb Z^4. <#Include SYSTEM "../lib/Orru/tutorial/tutex/sl3.3.txt"> diff --git a/tutorial/HapTutorial.xml b/tutorial/HapTutorial.xml index 22638f3e..baba0ca8 100644 --- a/tutorial/HapTutorial.xml +++ b/tutorial/HapTutorial.xml @@ -33,7 +33,7 @@ or related <#Include SYSTEM "tutorialSimplicialGroups.xml"> <#Include SYSTEM "tutorialCongruence.xml"> <#Include SYSTEM "tutorialBianchi.xml"> - +<#Include SYSTEM "../lib/Orru/tutorial/tutorialSL3.xml"> <#Include SYSTEM "tutorialParallel.xml"> <#Include SYSTEM "../lib/Kelvin/cw-functions-tutorial.xml">