#These set of function provides a calculation of the representation of #the automorphism group g on a canonical homology basis of a Riemann surface #with many automorphisms. The input is a regular hypermap in form of a group #g :=Group(a,b,c) where c=(a*b)^-1, a,b,c three permutations of order na,nb,nc #such that 1/na+1/nb+1/nc < 1 (hyperbolicity). The function call AutoMat(g) #returns the representation as a symplectic group inside Sp(2k,Z) where Z #denotes the ring of integers and k is the genus of the corresponding Riemann #surface (2k=Size(g)*(1-1/na-1/nb-1/nc)+2). #You can use this function by simply reading this file in (Read("Homologie")). # This function expects a group g generated by three elements g.1, g.2, g.3 # such that their product equals 1, their orders satisfying the hyperbolic # inequality. It returns the corresponding regular hypermap and its # autopmorphismgroup in terms of 6 permutations [lambda1,lambda2,lambda3,rho1, # rho2, rho3]. The function call is Hypermap(g). Hypermap := function( g ) local liste1, liste2 , i, g1, g2 ; liste2:=AsSet(g); g1:=Action(g,liste2,OnRight); g2:=Action(g,liste2,OnLeftAntiOperation); liste1:=[]; Append(liste1,GeneratorsOfGroup(g2)); Append(liste1,GeneratorsOfGroup(g1)); return liste1; end; # In diesem Schritt wird das reguläre Hypermap vom Grad n auf ein Hypermap # vom Grad 2n normalisiert. In HypermapNorm wird eine Liste erwartet vom Typ # [lambda1,lambda2,lambda3,rho1,rho2,rho3] der Return ist ein normalisiertes # Hypermap vom Typ [rhonorm1,rhonorm2] HypermapNorm:= function (liste) local liste1, liste2, n , i, perm ; n:=LargestMovedPointPerm(liste[4]); liste1:=[]; liste2:=[]; for i in [1..n] do liste2[2*i]:=2*i^liste[4]-1; liste2[2*i-1]:=2*i; od; Add(liste1,PermList(liste2)); liste2:=[]; perm:=liste[6]^-1; for i in [1..n] do liste2[2*i^liste[4]-1]:=2*i; liste2[2*i]:=2*i^perm-1; od; Add(liste1,PermList(liste2)); return liste1 ; end; # Die folgende Funktion ersetzt die Funktion Orbit und ist nur für zyklische Gruppen g gedacht. # Sie liefert eine Liste zurück, in welcher Reihenfolge die Bahn eines Punktes durchschritten wird. NeuOrbit:=function(g,p) local i,l; l:=[]; for i in [1..Size(g)] do Add(l,p^(g.1^(i-1))); od; return l; end; # Diese Funktion enfernt den Eintrag an der Stelle "listenplatz" einer Liste # "liste" und returniert eine um diesen Eintrag verkürzte Liste # l:=[...,liste[listenplatz-1],liste[listenplatz+1],...] Entferne:=function(liste, listenplatz) local l; l:=liste{[1..listenplatz-1]}; Append(l,liste{[listenplatz+1..Length(liste)]}); return l; end; # Diese Funktion fügt die Liste "liste2" in die Liste "liste1" # im Anschluß an den Listenplatz "listenplatz" ein. # Returniert wird die Liste # l:=[liste1[1],...,liste1[listenplatz],liste2[1],...,liste2[Length(liste2)], # liste1[listenplatz+1],...] Einfuegen:=function(liste1, liste2, listenplatz) local l; l:=liste1{[1..listenplatz]}; Append(l,liste2); Append(l,liste1{[listenplatz+1..Length(liste1)]}); return l; end; # Diese Funktion normalisiert ein reguläres Hypermaps derart, dass # der Rand des Hypermaps perm:=[perm[1],perm[2]] durch # [1..LargestMovedPointPerm(alpha3)] gegeben ist. Dies geschieht indem # die durch perm[1] gegebenen regulären Order(perm[1])-gone aneinander- # gesteckt werden, so wie es durch perm[2] vorgegeben ist. # Der Return ist eine Liste [perm[1]^p,perm[2]^p,p,Baumtiefe], # wobei p die Permutation ist, mit der das Hypermap perm normalisiert wird. # Die Baumtiefe ist eine Liste die die Lage eines Dreiecks i beschreibt. # Wenn also i das i-te Dreieck eines Fundamentalbereichs des normalisierten # Hypermaps perm^p ist, dann gibt Baumtiefe[i] die Entfernung des # an Order(perm[1])-gon indem i steckt, relativ zu dem ersten # Order(perm[1])-gon, mit dem der Fundamentalbereich von perm^p aufgebaut # wurde. RandNorm:=function(perm) local g1, n, s, s1, s2, rand, rand1, i, m,k, trans, pos; g1:=Group(perm[1]); n:=LargestMovedPointPerm(perm[1]); s:=Orbits(g1,[1..n]); rand:=s[1]; rand1:=rand; s1:=[]; for i in s[1] do Add(s1,1); od; s2:=s1; s1:=s1+1; s:=Entferne(s,1); while Length(rand1) < n do for i in [1..Length(rand1)] do m:=0; for k in [1..Length(s)] do if rand1[i]^perm[2] in s[k] then pos:=Position(rand,rand1[i]); rand:=Einfuegen(rand,NeuOrbit(g1,rand1[i]^perm[2]),pos); s2:=Einfuegen(s2,s1,pos); m:=k; fi; od; if m > 0 then s:=Entferne(s,m); fi; od; if Length(rand1) < Length(rand) then s1:=s1+1; fi; rand1:=rand; od; trans:=(PermList(rand))^-1; return [perm[1]^trans,perm[2]^trans,trans,s2]; end; # Diese Funktion hängt einer n*n Matrix S einen n-dim Zeilenvektor als # (n+1)-Zeile an, verlängert den Vektor um 0, und hängt das Negative des # verlängerten Vektors als (n+1)-te Spalte der Matrix an. Anhaengen:=function(m,v) local m1,n,i; n:=Length(v); m1:=m; Add(v,0); Add(m1,v); for i in [1..n] do Add(m1[i],-v[i]); od; return m1; end; # Die Funktion SymplecticMat normalisiert eine schief-symmetrische # unimodulare Matrix s auf Normalform (0,I/-I,0). # Returniert wir die Transformationsmatrix trans mit # trans*s*TransposedMat(trans)=(0,I/-I,0). SymplecticMat:=function(s) local a,k,s1,i, s2,trans,trans1,Id,n,m,j,vec,l; a:=[]; s1:=[]; Append(s1,s); n:=Length(s); Id:=IdentityMat(n); trans:=IdentityMat(n); for i in [1..n/2] do vec:=SolutionMat(s1,Id[n-i+1]); l:=Concatenation([],Id{[1..i-1]}); Add(l,vec); k:=0; for m in [i..n] do if vec[m]<>0 and k=0 then k:=m; fi; od; Append(l,Id{[i..k-1]}); Append(l,Id{[k+1..n]}); trans:=l*trans; s1:=l*s1*TransposedMat(l); od; for i in [n/2+1..n] do vec:=SolutionMat(s1,-Id[n-i+1]); l:=Concatenation([],Id{[1..i-1]}); Add(l,vec); k:=0; for m in [i..n] do if (vec[m]>0 or vec[m]<0) and k=0 then k:=m; fi; od; Append(l,Id{[i..k-1]}); Append(l,Id{[k+1..n]}); trans:=l*trans; s1:=l*s1*TransposedMat(l); od; return trans; end; # Diese Funktion entfernt aus einer Liste von Seitenpaarenden # diejenigen, die offensichtlich einen nur trivialen Beitrag zur # Schnittmatrix leisten. Verkuerze:=function(S) local S2,S1, j , k, i ; k:=2*Length(S); S1:=Filtered(S,j -> j[3]-j[4] mod k <>1 and j[4]-j[3] mod k <>1 ); S2:=List(S1,j->j[3]); Append(S2,List(S1,j->j[4])); Sort(S2); for j in S1 do j[3]:=Position(S2,j[3]); j[4]:=Position(S2,j[4]); od; return S1; end; # Diese Funktion erwartet eine Liste der Länge 6 wobei die beiden ersten # Einträge ein Randnormalisiertes Hypermap sind und der fünfte Eintrag # die Erzeugendenpaare der 2g Kurven aus Schnittmat(). Die anderen EInträge # aus der Liste werden nicht benötigt. # HomologieBasis:=function(l) local i,j,m,n,k,k1,vec,vec1,ll,erzeugende1,erzeugende,perm; k1:=Length(l[4]); erzeugende:=[]; j:=0; vec:=NullMat(2,k1); for m in l[5] do for n in m do j:=j+1; k:=l[4][n]; vec[j][n]:=1; for i in [1..(n-1)] do if l[4][n-i] < k then vec[j][n-i]:=1; vec[j][n-i+1]:=-1; k:=k-1; fi; od; od; Add(erzeugende,vec[1]-vec[2]); j:=0; vec:=NullMat(2,k1); od; ll:=[]; for i in [1..2] do Add(ll,l[i]^(l[3]^-1)); od; for i in [1..Length(erzeugende)] do erzeugende[i]:=Permuted(erzeugende[i],l[3]^-1); od; k:=k1/2; vec:=NullMat(1,k); erzeugende1:=[]; perm:=ll[1]^-1; for n in erzeugende do for m in [1..k] do vec[1][m]:=n[2*m-1]+n[(2*m-1)^perm]; od; Add(erzeugende1,vec[1]); vec:=NullMat(1,k); od; return erzeugende1; end; # Diese Funktion berechnet die 2g Kurven einer Homologie Basis # und die Schnittmatrix eines normalisierten Hypermaps. # Normalisert heisst hierbei RandNorm(HypermapNorm(l)); SchnittMatrix:=function(g) local l1,g1,g2,g3,k1,k2,k3,n,erzeugende,erz1,erz2,erz3, a,i,vec,doppelg,S,S1,S2,j,t1,perm,l; l:=Hypermap(g); l1:=RandNorm(HypermapNorm(l)); n:=LargestMovedPointPerm(l[3]); g1:=Group(l[1]); g2:=Group(l[2]); g3:=Group(l[3]); k1:=Size(g1); k2:=Size(g2); k3:=Size(g3); doppelg:=n*(1-1/k1-1/k2-1/k3)+2; if doppelg = 0 then return doppelg; else i:=1; erzeugende:=[]; fi; S:=[[0]]; perm:=l1[2]^-1; S1:=List([1..n],j->[2*j-1,(2*j-1)^perm]); S1:=List(S1,j -> Concatenation(j,j)); repeat a:=Length(S1); S1:=Verkuerze(S1); until Length(S1)=a; S1:=List(S1,j -> [j[1],j[2]]); i:=1; repeat i:=i+1; vec:=[]; for j in [1..i-1] do erz1:=[]; Append(erz1,S1[i]); Append(erz1,S1[j]); erz1:=Set(erz1); if erz1{[2,3]} = Set(S1[i]) or erz1{[1,2]}=Set(S1[i]) or erz1{[3,4]} =Set(S1[i]) or erz1{[1,4]}=Set(S1[i]) then Add(vec,0); elif erz1{[1,3]} = Set(S1[i]) then Add(vec,(-1)^erz1[3]*(-1)^erz1[4]); else Add(vec,(-1)*(-1)^erz1[3]*(-1)^erz1[4]); fi; od; S:=Anhaengen(S,vec); until RankMat(S)=doppelg; vec:=List([1..Length(S)],j -> 0); erzeugende:=[]; erz1:=[]; erz2:=[]; i:=1; S2:=[]; while Length(erz1) vec then Add(erz1,i); fi; i:=i+1; od; erzeugende:=S1{erz1}; S1:=S{erz1}; S:=TransposedMat(S1){erz1}; S:=TransposedMat(S); Add(l1,erzeugende); Add(l1,S); l1:=Concatenation(l,[HomologieBasis(l1),S]); return l1; end; # Diese Funktion erwartet als Argument eine Gruppe die von 3 Elementen # erzeugt wird. Zu diesen Erzeugenden gehört eine Fläche vom Geschlecht # g. Die Funktion AutoMat liefer die Darstellung der Gruppe auf einer # kanonischen Homologiebasis AutoMat:=function(g) local S,m,n,m1,l,vec,i,j,mat,mat1,k,k1,k2,erz,liste1,trans,liste2,nn; liste1:=SchnittMatrix(g); n:=LargestMovedPointPerm(liste1[1]); g:=Group(liste1[6]); l:=Orbits(g,[1..n]); vec:=List([1..n],j->0); erz:=[]; for i in l do for j in i do vec[j]:=1; od; vec:=vec-Permuted(vec,(liste1[5])^-1); Add(erz,vec); vec:=List([1..n],j->0); od; k2:=Length(erz); TriangulizeMat(erz); mat:=Concatenation([],liste1[7]); k1:=Length(liste1[7]); Append(mat,erz{[1..k2-1]}); l:=[]; nn:=[]; for j in liste1{[1,2]} do mat1:=[]; for k in liste1[7] do vec:=SolutionMat(mat,Permuted(k,j)); Add(mat1,vec); od; Add(l,mat1{[1..k1]}{[1..k1]}); Add(nn,mat1); od; trans:=SymplecticMat(liste1[8]); liste2:=[]; for i in l do Add(liste2,trans*i*trans^-1); od; Add(liste2,(liste2[1]*liste2[2])^-1); m:=Length(liste2[1]); S:=NullMat(m,m); S{[1..m/2]}{[1..m/2]}:=IdentityMat(m/2); m1:=List([1..m/2],j->m/2+1-j); S{[m/2+1..m]}{[m/2+1..m]}:=IdentityMat(m/2){m1}; liste2:=S*liste2*S; return liste2; end;