From d294bbc9a21f8c256102b1f68d03099f51c86634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Giulia=20Orr=C3=B9?= Date: Thu, 5 Feb 2026 14:38:42 +0000 Subject: [PATCH] Add some functions --- ...HAP_TransversalCongruenceSubgroups_SL3Z.gi | 66 ++++++ lib/Orru/decsOrru.gd | 4 + lib/Orru/initOrru.gi | 3 +- lib/Orru/script.g | 222 ++++++++++++++++++ lib/Orru/subgroups.gi | 34 ++- 5 files changed, 327 insertions(+), 2 deletions(-) create mode 100644 lib/Orru/HAP_TransversalCongruenceSubgroups_SL3Z.gi create mode 100644 lib/Orru/script.g diff --git a/lib/Orru/HAP_TransversalCongruenceSubgroups_SL3Z.gi b/lib/Orru/HAP_TransversalCongruenceSubgroups_SL3Z.gi new file mode 100644 index 00000000..5d9594a6 --- /dev/null +++ b/lib/Orru/HAP_TransversalCongruenceSubgroups_SL3Z.gi @@ -0,0 +1,66 @@ +InstallGlobalFunction(HAP_TransversalCongruenceSubgroups_SL3Z, +function ( G, H ) + local tree, InH, S, T, U, v, p, g, s, n, q, vv, gens, nodes, nodesinv, leaves, + ambientGenerators, InLowDegreeNodesModH, one, poscan, nind; + S := [ [1,0,1], [0,-1,-1], [0,1,0] ]; + T := [ [0,1,0], [0,0,1], [1,0,0]]; + U := [[0,1,0], [1,0,0], [-1,-1,-1]]; + one := IdentityMat( 3 ); + ambientGenerators := [S, T, U]; + tree := [ 1 ]; + cnt := 1; + leaves := NewDictionary( S, true, SL( 3, Integers ) ); + nodes := [ one ]; + AddDictionary( leaves, one, 1 ); + InH := H!.membershipLight; + InLowDegreeNodesModH := function ( g ) + local x, gg, B1, B2; + gg := g ^ -1; + for x in nodes do + if InH( x * gg ) then + return x; + fi; + od; + return false; + end; + while Size( leaves ) > 0 do + vv := leaves!.entries[1]; + v := vv[1]; + for s in [ 1 .. Length( ambientGenerators ) ] do + g := v * ambientGenerators[s]; + q := InLowDegreeNodesModH( g ); + if q = false then + Add( nodes, g ); + AddDictionary( leaves, g, Length( nodes ) ); + p := LookupDictionary( leaves, v ); + Add( tree, [ p, s ] ); + fi; + od; + RemoveDictionary( leaves, v ); + od; + #nodes := Filtered( nodes, function ( g ) + # return g in G; + # end ); + nodesinv := List( nodes, function ( g ) + return g ^ -1; + end ); + nind := [ 1 .. Length( nodes ) ]; + poscan := function ( x ) + local i; + for i in nind do + if InH( x * nodesinv[i] ) then + return i; + fi; + od; + return fail; + end; + return + Objectify( + NewType( FamilyObj( G ), + IsHapRightTransversalSL3ZSubgroup and IsList and IsDuplicateFreeList + and IsAttributeStoringRep ), rec( + group := G, + subgroup := H, + cosets := nodes, + poscan := poscan ) ); +end); \ No newline at end of file diff --git a/lib/Orru/decsOrru.gd b/lib/Orru/decsOrru.gd index 1a56af76..6439a4ab 100644 --- a/lib/Orru/decsOrru.gd +++ b/lib/Orru/decsOrru.gd @@ -1,10 +1,14 @@ IsHapCongruenceSubgroup:=NewFilter("IsHapCongruenceSubgroup");; +IsHapRightTransversalSL3ZSubgroup:=NewFilter("IsHapRightTransversalSL3ZSubgroup");; DeclareGlobalFunction("HAP_GenericCongruenceSubgroup"); DeclareGlobalFunction("FiniteProjectiveLine"); DeclareGlobalFunction("FiniteProjectivePlane"); DeclareGlobalFunction("HAP_SL3ZSubgroupTree_fast"); +DeclareGlobalFunction("HAP_TransversalCongruenceSubgroups_SL3Z"); DeclareOperation("HAPCongruenceSubgroupGamma0",[IsInt,IsInt]); DeclareOperation("HAPCongruenceSubgroupTree",[IsHapCongruenceSubgroup]); +DeclareOperation("in",[IsMatrix, IsHapCongruenceSubgroup and IsGroup]); +DeclareOperation("RightTransversal",[IsMatrixGroup, IsHapCongruenceSubgroup]); InstallMethod( ViewObj, "for HapCongruenceSubgroup", diff --git a/lib/Orru/initOrru.gi b/lib/Orru/initOrru.gi index 7df0f304..5a780bd5 100644 --- a/lib/Orru/initOrru.gi +++ b/lib/Orru/initOrru.gi @@ -1,3 +1,4 @@ ReadPackageHap( "lib/Orru/subgroups.gi"); ReadPackageHap( "lib/Orru/finiteProjectiveSpaces.gi"); -ReadPackageHap( "lib/Orru/HAP_SL3ZSubgroupTree_fast.gi"); \ No newline at end of file +ReadPackageHap( "lib/Orru/HAP_SL3ZSubgroupTree_fast.gi"); +ReadPackageHap( "lib/Orru/HAP_TransversalCongruenceSubgroups_SL3Z.gi"); \ No newline at end of file diff --git a/lib/Orru/script.g b/lib/Orru/script.g new file mode 100644 index 00000000..d4e24ba9 --- /dev/null +++ b/lib/Orru/script.g @@ -0,0 +1,222 @@ +# SchreierGens := []; +# n:=3; +# ProjPlane := FiniteProjectivePlane(n); +# G:=HAPCongruenceSubgroupGamma0(3,n); +# S := [ +# [[1,1,0],[0,1,0],[0,0,1]], +# [[1,0,0],[1,1,0],[0,0,1]], +# [[0,-1,0],[1,0,0],[0,0,1]], +# [[1,0,0],[0,0,-1],[0,1,0]] +# ]; +# for i in [1..Length(ProjPlane.Reps)] do +# for s in S do +# r := G!.cosetRep(i); +# j := G!.cosetPos(r*s); +# g := r * s * Inverse(G!.cosetRep(j)); +# if G!.membershipLight(g) then +# Add(SchreierGens, g); +# fi; +# od; +# od; +# +# SchreierGens := Set(SchreierGens); +# Print(SchreierGens); + +#function ( G ) +# local ambientGenerators, tree, InGmodU, Ugrp, S, T, U, v, p, g, s, n, q, #vv, leaves, +# genTriples, generators, InLowDegreeNodesModG, csts, cnt, vertex2word, one, #triple2word, i, +# j, u, c, a, b; +# S := [ [ 0, -1 ], [ 1, 0 ] ]; +# T := [ [ 1, 1 ], [ 0, 1 ] ]; +# U := S * T; +# one := IdentityMat( 2 ); +# ambientGenerators := [ S * U, S * U ^ 2 ]; +# Ugrp := G!.ugrp; +# Ugrp := Elements( Ugrp ); +# tree := [ ]; +# genTriples := [ ]; +# cnt := 1; +# leaves := NewDictionary( S, true, SL( 2, Integers ) ); +# csts := [ ]; +# csts[G!.cosetPos( one )] := 1; +# AddDictionary( leaves, one, G!.cosetPos( one ) ); +# InLowDegreeNodesModG := function ( g ) +# local pos; +# pos := G!.cosetPos( g ); +# if not IsBound( csts[pos] ) then +# return false; +# else +# ; +# return pos; +# fi; +# return; +# end; +# while Size( leaves ) > 0 do +# vv := 1 * leaves!.entries[1]; +# v := vv[1]; +# p := G!.cosetPos( v ); +# for s in [ 1 .. Length( ambientGenerators ) ] do +# g := ambientGenerators[s] * v; +# q := InLowDegreeNodesModG( g ); +# if q = false then +# q := G!.cosetPos( g ); +# AddDictionary( leaves, g, q ); +# csts[q] := 1; +# tree[q] := [ p, s ]; +# else +# Add( genTriples, [ p, s, v, g ] ); +# fi; +# od; +# RemoveDictionary( leaves, v ); +# od; +# vertex2word := function ( v ) +# local word; +# word := one; +# while IsBound( tree[v] ) do +# word := word * ambientGenerators[tree[v][2]]; +# v := tree[v][1]; +# od; +# return word; +# end; +# triple2word := function ( x ) +# local u, uu, g, q, c; +# for u in Ugrp do +# c := x[4] ^ -1 * u * vertex2word( G!.cosetPos( x[4] ) ); +# if G!.membership( c ) then +# return c; +# fi; +# od; +# return fail; +# end; +# genTriples := List( genTriples, function ( x ) +# return triple2word( x ); +# end ); +# genTriples := List( genTriples, function ( x ) +# return Minimum( x, x ^ -1 ); +# end ); +# genTriples := SSortedList( genTriples ); +# G!.tree := tree; +# G!.GeneratorsOfMagmaWithInverses := genTriples; +# return; +#end + +K := ContractibleGcomplex("SL(3,Z)s"); +KK:=BarycentricSubdivision(K); +G := HAPCongruenceSubgroupGamma0(3,2); +HAPCongruenceSubgroupTree(G); +#gens := G!.GeneratorsOfMagmaWithInverses; +#G := Group(gens); +SetGeneratorsOfGroup(G,G!.GeneratorsOfMagmaWithInverses); +Y := GComplexToRegularCWComplex(KK,G); + +#prova := function ( R, N ) +# local Y, dim, dim1, Cells, boundaries, StandardForm, Tiles, tile, pos, #NeighbourGens, +# TileReps, w, NewLeaves, Leaves, i, e, f, n, k, g, b, x, T; +# T := RightTransversal( R!.group, N ); +# dim := 0; +# for n in [ 1 .. Length( R ) ] do +# if R!.dimension( n ) > 0 then +# dim := dim + 1; +# else +# break; +# fi; +# od; +# dim1 := dim - 1; +# StandardForm := function ( n, x ) +# local e, g, gc, stab; +# e := AbsInt( x[1] ); +# g := x[2]; +# stab := R!.stabilizer( n, e ); +# gc := g * Elements( stab ); +# gc := List( gc, function ( a ) +# return T[T!.poscan( a )]; +# end ); +# gc := Minimum( gc ); +# return [ e, gc ]; +# end; +# Tiles := [ ]; +# for k in [ 1 .. R!.dimension( dim ) ] do +# tile := 1 * R!.boundary( dim, k ); +# Apply( tile, function ( x ) +# return [ x[1], R!.elts[x[2]] ]; +# end ); +# Apply( tile, function ( e ) +# return StandardForm( dim1, e ); +# end ); +# Add( Tiles, tile ); +# od; +# TileReps := List( [ 1 .. Length( Tiles ) ], function ( i ) +# return T; +# end ); +# Cells := List( [ 1 .. dim + 1 ], function ( i ) +# return [ ]; +# end ); +# for k in [ 1 .. R!.dimension( dim ) ] do +# for g in TileReps[k] do +# Add( Cells[dim + 1], StandardForm( dim, [ k, g ] ) ); +# od; +# od; +# Cells[dim + 1] := SSortedList( Cells[dim + 1] ); +# for n in Reversed( [ 1 .. dim ] ) do +# for x in Cells[n + 1] do +# b := 1 * R!.boundary( n, x[1] ); +# Apply( b, function ( z ) +# return [ z[1], R!.elts[z[2]] ]; +# end ); +# Apply( b, function ( y ) +# return [ y[1], x[2] * y[2] ]; +# end ); +# Apply( b, function ( y ) +# return StandardForm( n - 1, y ); +# end ); +# Append( Cells[n], b ); +# od; +# Cells[n] := SSortedList( Cells[n] ); +# od; +# boundaries := List( [ 1 .. dim + 2 ], function ( n ) +# return [ ]; +# end ); +# boundaries[1] := List( Cells[1], function ( x ) +# return [ 1, 0 ]; +# end ); +# for n in [ 1 .. dim ] do +# for k in [ 1 .. Length( Cells[n + 1] ) ] do +# x := Cells[n + 1][k]; +# b := 1 * R!.boundary( n, x[1] ); +# Apply( b, function ( z ) +# return [ z[1], R!.elts[z[2]] ]; +# end ); +# Apply( b, function ( y ) +# return [ y[1], x[2] * y[2] ]; +# end ); +# Apply( b, function ( y ) +# return StandardForm( n - 1, y ); +# end ); +# Apply( b, function ( c ) +# return PositionSorted( Cells[n], c ); +# end ); +# b := Concatenation( [ Length( b ) ], b ); +# boundaries[n + 1][k] := b; +# od; +# od; +# Y := RegularCWComplex( boundaries ); +# return Y; +#end; + +N := HAP_CongruenceSubgroupGamma0(2);; +gens:=GeneratorsOfGroup(N);; +x:=gens[1]*gens[2];; +x in N; + +N := HAPCongruenceSubgroupGamma0(3,2);; +HAPCongruenceSubgroupTree(N); +SetGeneratorsOfGroup(N,N!.GeneratorsOfMagmaWithInverses); +gens:=GeneratorsOfGroup(N);; +x:=gens[1]*gens[2];; +x in N; +#Error, no method found! For debugging hints type ?Recovery from NoMethodFound +#Error, no 3rd choice method found for `Enumerator' on 1 arguments at /usr/share/#gap-4.14.0/lib/methsel2.g:250 called from +#Enumerator( D ) at /usr/share/gap-4.14.0/lib/domain.gi:285 called from +#( ) +# called from read-eval loop at *stdin*:139 +#type 'quit;' to quit to outer loop \ No newline at end of file diff --git a/lib/Orru/subgroups.gi b/lib/Orru/subgroups.gi index 966e193c..4e742668 100644 --- a/lib/Orru/subgroups.gi +++ b/lib/Orru/subgroups.gi @@ -274,4 +274,36 @@ InstallMethod(HAPCongruenceSubgroupTree, function(G) if not (G!.dimension=3 and G!.ringOfIntegers=Integers) then TryNextMethod(); fi; HAP_SL3ZSubgroupTree_fast(G); -end); \ No newline at end of file +end); + +InstallMethod(\in, +"membership test for HapCongruenceSubgroups", +[IsMatrix, IsHapCongruenceSubgroup and IsGroup], +1000000, #There must be a better way to ensure this method is used! +function(g,G) +return G!.membership(g); +end); + +InstallMethod(GeneratorsOfGroup, +"Generating set for HapCongruenceSubgroups", +[IsHapCongruenceSubgroup and IsGroup], +1000000, #There must be a better way to ensure this method is used! +function(G) +HAPCongruenceSubgroupTree(G); +return G!.GeneratorsOfMagmaWithInverses; +end); + +InstallOtherMethod( RightTransversal, +"Right transversal of congruence subgroup G in SL(3,Z)", +[IsMatrixGroup, IsHapCongruenceSubgroup], +1000000, +function(G,H) + if not (H!.dimension = 3 and Name(G) = "SL(3,Integers)") then + TryNextMethod(); + fi; + + HAPCongruenceSubgroupTree(H); + + return HAP_TransversalCongruenceSubgroups_SL3Z(G,H); +end); +