// *********************************************************************************************************************************************************************************** // ************************************************************* Classification of the groups **************************************************************************************** // *********************************************************************************************************************************************************************************** /* In this file, we collect all functions that we need for the classification of the groups. The code consists of three parts: Part I: general help functions Part II: functions to check the "standard properties" for a given group (cf. Notation 3.0.12) Part III: Main functions: - Proof of Theorem 3.0.5 (stabilizer groups) - Proof of Corollary 3.0.9 (baskets of singularities) - Proof of Proposition 3.0.14 (p_g=0, -id in im(rho)) - Proof of Proposition 3.0.15 (p_g=0, ze*id in im(rho)) - Proof of Lemma 3.0.20 (2-Sylows, free case) - Proof of Proposition 3.0.16 (no central element in im(rho)) */ /************************************************************************************************************ ****************************** PART I: General help functions *********************************************** *************************************************************************************************************/ /* The function "DimChar" collects all irreducible characters of a finite group "G" of degree i. As input, it additionally takes the character table "CT" of "G". */ function DimChar(G,CT,i) Set:=[]; for x in CT do if Degree(x) eq i then Set:=Append(Set,x); end if; end for; return Set; end function; /* The function "CharPol" determines the characterisitc polynomial of rho(g), where rho is a 3-dimensional representation with character "x". */ function CharPol(x,g) L:=[x(g^i): i in[1..3]]; return Polynomial(PowerSumToCoefficients(L)); end function; /* The function "ElsOfOrder" determines for a group "G" the elements of order "m". */ function ElsOfOrder(G,m) list:=[]; for g in G do if Order(g) eq m then Append(~list,g); end if; end for; return list; end function; /* The function "CandidatesChar" lists all characters of degree 3 of a given group "G" with character table "CT". */ function CandidatesChar(G,CT) CT:=CharacterTable(G); listChar:=[]; if IsAbelian (G) then for n1 in [1..#CT] do for n2 in [n1..#CT] do for n3 in [n2..#CT] do x:=CT[n1]+CT[n2]+CT[n3]; Append(~listChar,x); end for; end for; end for; else listChar:=listChar cat DimChar(G,CT,3); for x1 in DimChar(G,CT,1) do for x2 in DimChar(G,CT,2) do x:=x1+x2; Append(~listChar,x); end for; end for; end if; return listChar; end function; /* The function "Eigen1" checks, for a given character "x" of a group "G", whether all elements of order "i" have eigenvalue 1. */ function Eigen1(x,G,i) for g in ElsOfOrder(G,i) do pol:=CharPol(x,g); if Evaluate(pol,1) ne 0 then return false; end if; end for; return true; end function; /* The function "TestOrder4" checks, for a character "x" of "G", whether for all elements of order 4, either 1 is an eigenvalue or the set of eigenvalues is {i,-i}. */ function TestOrder4(x,G) F:=CyclotomicField(8); i:=z^2; for g in ElsOfOrder(G,4) do pol:=CharPol(x,g); if Evaluate(pol,1) ne 0 then if Evaluate(pol,-1) eq 0 then return false; end if; if {Evaluate(pol,i),Evaluate(pol,-i)} ne {0} then return false; end if; end if; end for; return true; end function; /************************************************************************************************************ **************************** PART II: Check STANDARD-PROPERTIES ********************************************* ************************************************************************************************************/ /* This part of the program is used to check for a finite group G whether it satisfies the "standard properties" (cf. Notation 3.0.12), i.e., if there exists a linear 3-dimensional representation rho st (1) rigid: (rho,\bar{rho})=0, (2) rho is faithful, (3) for all g in G, the characteristic polynomial of rho(g)+\bar{rho}(g) has integer coefficients, and furthermore, the group G fulfills: (4) the orders of the elements of G belong to {1,2,3,4,5,6,7,8,9,10,12,14} (5) the elements with order in {5,8,10,12} have to have eigenvalue 1 (6) the elements with order in {7,9,14} don't have 1 as eigenvalue */ /* The function "CheckOrders" checks condition (4). */ function CheckOrders(G) L:={1,2,3,4,5,6,7,8,9,10,12,14}; for g in G do if not Order(g) in L then return false; end if; end for; return true; end function; /* The function "CondCharpol" checks the conditions (3), (5), (6) for a 3-dimensional character "x" of a group "G". */ function CondCharpol(x,G) F:=CyclotomicField(#G); P:=PolynomialRing(F); for d in {5,8,10,12} do if not Eigen1(x,G,d) then return false; end if; end for; for d in {7,9,14} do for g in ElsOfOrder(G,d) do if Evaluate(CharPol(x,g),1) eq 0 then return false; end if; end for; end for; for g in G do f:=CharPol(x,g)*CharPol(ComplexConjugate(x),g); coeff:=Coefficients(f); for a in coeff do if a notin IntegerRing() then return false; end if; end for; end for; return true; end function; /* The function "StandardProperties" checks for a finite group G whether it has the standard properties. */ function StandardProperties(G) if not CheckOrders(G) then return false; end if; CT:=CharacterTable(G); for x in CandidatesChar(G,CT) do if #Kernel(x) eq 1 and InnerProduct(x,ComplexConjugate(x)) eq 0 and CondCharpol(x,G) then return true; end if; end for; return false; end function; /************************************************************************************************************ ******************************** PART III: MAIN FUNCTIONS *************************************************** *************************************************************************************************************/ /***************************** Proof of Theorem (3.5) (stabilizer groups) ***********************************/ /* The function "LinearGroups" determines all non abelian groups G of order 2^a*3^b*7^c, where a in [0..2], b in [1,2], c in [0,1] with the following properties: - if c=0: G admits an irreducible representation of dimension 3 (here, we only have to check a=2) - if c=1: G admits an irreducible representation of dimension 3 and G has at most one element of order 2 Furthermore, the output "testC1" is true if all determined groups in case c=1 have either C7:C3 or C7:C9 as a subgroups. */ function LinearGroups() ListCandidatesC0:=[]; ListCandidatesC1:=[]; testC1:=true; for b in [1..2] do n:=2^2*3^b; for G in SmallGroups(n) do CT:=CharacterTable(G); if #DimChar(G,CT,3) ge 1 then Append(~ListCandidatesC0, IdentifyGroup(G)); end if; end for; end for; H1:=Group("C7:C3"); H2:=Group("C7:C9"); for b in [1..2] do for a in [0..2] do m:=2^a*3^b*7; for G in SmallGroups(m) do if #ElsOfOrder(G,2) le 1 then CT:=CharacterTable(G); if #DimChar(G,CT,3) ge 1 then Append(~ListCandidatesC1, IdentifyGroup(G)); testG:=false; for H in AllSubgroups(G) do if IsIsomorphic(H,H1) or IsIsomorphic(H,H2) then testG:=true; end if; end for; if not testG then testC1:=false; end if; end if; end if; end for; end for; end for; return ListCandidatesC0, ListCandidatesC1, testC1; end function; /* output: ListCandidatesC0=[<12,3>,<36,3>,<36,11>] = [A4, C2^2:C9, A4*C3] ListCandidatesC1=[ <21, 1>, <42, 2>, <84, 2>, <63, 1>, <63, 3>, <126, 2>, <126, 10>, <252, 2>, <252, 17>, <252, 19> ] testC1=true */ /**************************** Proof of Corollary (3.9) (baskets of singularities) ************************/ function Baskets() basket:=[]; for N2 in [0..16] do for N3 in [0..9] do for N4 in [0..6] do for N6 in [0..4] do for N9 in [0..3] do for N14 in [0..2] do if 1 eq 1/16*N2+1/9*N3+5/32*N4+35/144*N6+1/3*N9+7/16*N14 then Append(~basket,[N2,N3,N4,N6,N9,N14]); end if; end for; end for; end for; end for; end for; end for; return basket; end function; /* ouptut: Baskets()=[ [ 0, 0, 0, 0, 3, 0 ], [ 0, 1, 2, 1, 1, 0 ], [ 0, 3, 0, 0, 2, 0 ], [ 0, 4, 2, 1, 0, 0 ], [ 0, 6, 0, 0, 1, 0 ], [ 0, 9, 0, 0, 0, 0 ], [ 1, 0, 6, 0, 0, 0 ], [ 2, 0, 0, 0, 0, 2 ], [ 4, 0, 2, 0, 0, 1 ], [ 5, 1, 0, 1, 1, 0 ], [ 5, 4, 0, 1, 0, 0 ], [ 6, 0, 4, 0, 0, 0 ], [ 9, 0, 0, 0, 0, 1 ], [ 11, 0, 2, 0, 0, 0 ], [ 16, 0, 0, 0, 0, 0 ] ] */ /********************** Proof of Proposition (3.15) (p_g=0, -id in im(rho)) ********************************/ /******* cases k=3, 8, 11 ********/ /* The function "TwoGroups" checks for a group of order 2^a, a=3,4,5, the conditions explained in the proof of Proposition (3.15), cases 3, 8 and 11. */ function Cases3and8and11() list:=[]; for a in [3..5] do for G in SmallGroups(2^a) do CT:=CharacterTable(G); if CheckOrders(G) then for x in CandidatesChar(G,CT) do if #Kernel(x) eq 1 and InnerProduct(x,ComplexConjugate(x)) eq 0 and CondCharpol(x,G) then if a eq 4 then // if ord(g)=4 then rho(g) has to have eigenvalue 1, this is checked by "Eigen1" if Eigen1(x,G,4) then Append(~list, IdentifyGroup(G)); break x; end if; else if TestOrder4(x,G) then Append(~list, IdentifyGroup(G)); break x; end if; end if; end if; end for; end if; end for; end for; return list; end function; /* output: Cases3and8and11=[] */ /********* cases k=2, 7 *******/ /* The function "TestOrder6" checks the conditions about the eigenvalues of elements of order 6 as explained in the proof of Proposition 3.15, cases 2 and 7. Note that for the elements of order 6 without eigenvalue 1, we only check whether all eigenvalues are of order 6. Since this already leads to a contradiction, this is enough.*/ function TestOrder6(x,G) F:=CyclotomicField(24); z6:=ze^4; m6:=0; for g in ElsOfOrder(G,6) do pol:=CharPol(x,g); if Evaluate(pol,1) ne 0 then if Evaluate(pol,z6^2) eq 0 or Evaluate(pol,z6^3) eq 0 or Evaluate(pol,z6^4) eq 0 then return false; end if; m6:=m6+1; end if; end for; if m6 ne 2*#G/6 then return false; end if; return true; end function; /* With the function "Cases2and7", we show that the cases 2 and 7 cannot occur. Note that n=#G=96 in case 2, and n=#G=24 in case 7.*/ function Cases2and7() list:=[]; for n in {24,96} do for G in SmallGroups(n) do CT:=CharacterTable(G); if CheckOrders(G) and #ElsOfOrder(G,6) ge 2*n/6 then for x in CandidatesChar(G,CT) do if #Kernel(x) eq 1 and InnerProduct(x,ComplexConjugate(x)) eq 0 and CondCharpol(x,G) and TestOrder6(x,G) then if n eq 24 and Eigen1(x,G,4) then Append(~list,IdentifyGroup(G)); else Append(~list,IdentifyGroup(G)); end if; end if; end for; end if; end for; end for; return list; end function; /* output: Cases2and7()=[] */ /**************************** Proof of Proposition (3.16) (p_g=0, ze_3 id in im(rho)) **********************/ /* The function "Case14" excludes case 14.*/ function Case14() list:=[]; checklist:=[]; for G in SmallGroups(3^5) do if #ElsOfOrder(G,9) eq 54 and CheckOrders(G) then Append(~list, IdentifyGroup(G)); Append(~checklist, StandardProperties(G)); end if; end for; return list, checklist; end function; /* output: list= [ <243, 53>, <243, 58> ], checklist=[ false, false ] */ /* The function "Case12" excludes case 12 if G has 3^4 elements.*/ function Case12() list:=[]; checklist:=[]; for G in SmallGroups(3^4) do if #ElsOfOrder(G,9) eq 54 and CheckOrders(G) then Append(~list, IdentifyGroup(G)); Append(~checklist, StandardProperties(G)); end if; end for; return list, checklist; end function; /* output: list=[ <81, 3>, <81, 8>, <81, 11>, <81, 13>, <81, 14> ], checklist=[ false, false, false, false, false ] */ /**************************** Proof of Lemma (3.21) (2-Sylows, free case) **********************************/ /* We want to find all possible 2-Sylow subgroups acting freely. So, we have to check if there exists a 3-dimensional representation rho where (1) rho is faithful (2) for all g in G, the characterisitc polynomial of rho(g)+\bar{rho}(g) has integer coefficients. (3) for all g in G, rho(g) has eigenvalue 1 Furthermore, the group G has to fulfil: (4) the orders of the elements of G belong to {1,2,4,8}*/ function CondCharpolFree(x,G) for g in G do pol:=CharPol(x,g); if Evaluate(pol,1) ne 0 then return false; end if; f:=CharPol(x,g)*CharPol(ComplexConjugate(x),g); coeff:=Coefficients(f); for a in coeff do if a notin IntegerRing() then return false; end if; end for; end for; return true; end function; function CheckGroupFree(G) if not CheckOrders(G) then return false; end if; CT:=CharacterTable(G); for x in CandidatesChar(G,CT) do if #Kernel(x) eq 1 and CondCharpolFree(x,G) then return true; end if; end for; return false; end function; function AllTwoSylow(k,SetGroups) n:=2^k; for G in SmallGroups(n: Warning := false) do N:=Subgroups(G); subs:={IdentifyGroup(N[i]`subgroup) : i in [1..#N]| N[i]`order lt n}; if subs subset SetGroups then if CheckGroupFree(G) then SetGroups:=Include(SetGroups,IdentifyGroup(G)); end if; end if; end for; return SetGroups; end function; function ListTwoSylows() SetGroups:={<1,1>}; k:=1; test:=true; while test do if k ge 10 then print "Warning: Group order becomes to big"; return false; end if; k; SetGroupsRef:=SetGroups; SetGroups:=AllTwoSylow(k,SetGroups); if SetGroups eq SetGroupsRef then test:=false; end if; k:=k+1; end while; return SetGroups; end function; /* output: ListTwoSylows= { <2, 1>, <8, 4>, <4, 2>, <4, 1>, <16, 13>, <8, 2>, <16, 6>, <1, 1>, <16, 2>, <16, 8>, <8, 1>, <8, 3>, <32, 11> } */ /************************ Proof of Proposition (3.17) (no central element in im(rho)) *****************/ /* The function "TestOrder3" checks the conditions for the elements of order 3 for a character "x" of a group "G", as explained in the proof of Proposition 3.17. */ function TestOrder3(x,G) F:=CyclotomicField(24); z3:=ze^8; m3:=0; for g in ElsOfOrder(G,3) do pol:=CharPol(x,g); if Evaluate(pol,1) ne 0 then if {Evaluate(pol,ze), Evaluate(pol,ze^2)} ne {0} then return false; end if; m3:=m3+1; end if; end for; if m3 ne 2*#G/9 then return false; end if; return true; end function; /* Since in the situation of Proposition 3.17, no elements of order 9 are allowed, we write a new function to check the orders of the elemnts of group "G". */ function CheckOrdersCase15(G) L:={1,2,3,4,5,6,8,10,12}; for g in G do if not Order(g) in L then return false; end if; end for; return true; end function; /* The function "WithOrd5" shows that if a group fitting in the setup of Proposition 3.17 has an element of order 5, then it is the group with MAGMA ID <360, 118>. */ function WithOrd5() list:=[]; for a in [0..5] do for G in SmallGroups(2^a*3^2*5: Warning:=false) do if CheckOrdersCase15(G) and #ElsOfOrder(G,3) ge 2^a*2*5 then Append(~list,IdentifyGroup(G)); end if; end for; end for; return list; end function; /* output: list=[ <360, 118> ] */ /* The function "NoOrd5" excludes all groups in the setup of Proposition 3.17 of order 2^a*3^2 with a=1,...,5. */ function NoOrd5() list:=[]; for a in [1..5] do n:=2^a*3^2; for G in SmallGroups(n: Warning:=false) do if CheckOrders(G) and #ElsOfOrder(G,3) ge 2*#G/9 then CT:=CharacterTable(G); for x in CandidatesChar(G,CT) do if #Kernel(x) eq 1 and InnerProduct(x,ComplexConjugate(x)) eq 0 and TestOrder3(x,G) and CondCharpol(x,G) then Append(~list, IdentifyGroup(G)); break x; end if; end for; end if; end for; end for; return list; end function; /* output: NoOrd5()=[] */ // *********************************************************************************************************************************************************************************** // ************************************************************* Classification of the quotients ***************************************************************************** // *********************************************************************************************************************************************************************************** /* In this file, we collect all functions that we need for the classification of the quotients. More precisely, we classify all three-dimensional quotients of complex tori by an action of a finite group G with finite fixed locus and such that the quotient T/G is rigid with canonical singularities and geometric genus 0. The code consists of two parts: Part I: general functions that we need for several groups Part II: specific classification functions for each group: a) G=Z3^3 (proof of Proposition 4.10) b) G=Z3^2, rho=rho_1 (proof of Proposition 4.12) c) G=Z3^2, rho=rho_2 (proof of Proposition 4.20) d) G=Z9:Z3 (proof of Proposition 4.21) */ /********************************************************************************************************************* ************************************* PART I: general functions ***************************************************** *********************************************************************************************************************/ // We work with the 3rd cyclotomic field; ze is a 3rd primitive root of unity. F:=CyclotomicField(3); // E3 denotes the group of 3-torsion of the Fermat elliptic curve E. // t is a generator of the fixed locus of ze in E. E3:={1/3*(a+b*ze): a, b in {0,1,2}}; t:=1/3+2/3*ze; I3:=DiagonalMatrix([1,1,1]); /* The function "IntegralTest" checks if the entries of a 3-vector v (given as 3x1-matrix) are Eisenstein integers, i.e., integral over Z. */ function IntegralTest(v) return IsIntegral(v[1][1]) and IsIntegral(v[2][1]) and IsIntegral(v[3][1]); end function; /* The function "InLatt" takes as input a vector "v" and a kernel "K" and decides whether "v" belongs to the lattice "Lambda_K=Z[ze]^3+K". */ function InLatt(v,K) for l in K do if IntegralTest(v-l) then return true; end if; end for; return false; end function; /* The function "TestKernelEndo" decides whether the vector "d" belongs to the kernel of the endomorphism "A" of the torus "T=E^3/K". */ function TestKernelEndo(A,d,K) if InLatt(A*d,K) then return true; end if; return false; end function; /* The function "Fix" determines the fixed points of an automorphism "A" of T=E^3/K, "candidates": list of all candidates for the fixed points. */ function FixPoints(A,K,candidates) list:=[]; for d in candidates do if TestKernelEndo((A-I3),d,K) then Append(~list,d); end if; end for; Fix:=[]; while not IsEmpty(list) do Reflist:=list; d:=Rep(list); Append(~Fix,d); for e in Reflist do if InLatt(d-e,K) then Exclude(~list,e); end if; end for; end while; return Fix; end function; /* With the function "TestCohom" we test if two given cocycles give the same cohomology class in H^1(Z_3^2,E^3/K). Input: "v1", "v2": two lists of translation vectors; "listGen": corresponding generators of the groups, "K": kernel; "coboundaries": list of candidates for the coboundaries */ function TestCohom(v1,v2,listGen,K,coboundaries) for d in coboundaries do test:=true; for i in [1..#listGen] do if not InLatt(v1[i]-v2[i]-(listGen[i]*d-d),K) then test:=false; end if; end for; if test then return true; end if; end for; return false; end function; /* The function "Normal" determines the normalizers "N_C(Lambda_K)" in the cases G=Z3^3 and G=Z3^2, where "N_C(Lambda_K)" is just the subgroup of "N"=normalizer of G in Aut(E^3) fixing K. */ function Normal(K,N) List:={}; for C in N do test:= true; for l in K do if not InLatt(C*l,K) or not InLatt(C^-1*l,K) then test:=false; break l; end if; end for; if test then List:=Include(List,C); end if; end for; return List; end function; /* Given an affinity "f(z)=Cz + d" as a 4x4 matrix "B=[C d] [0 1]", the function "PartsAff" returns the translation vector "d". */ function TransVec(B) return Submatrix(B,[1,2,3],[4]); end function; /* Given an affinity "f(z)=Cz+d", the function "MatAff" returns the affinity as 4x4-matrix [C d] [0 1] */ function MatAff(C,d) Z:=ZeroMatrix(F,4,4); return InsertBlock(InsertBlock(InsertBlock(Z,C,1,1),d,1,4),Matrix(F,1,1,[1]),4,4); end function; /* Given a matrix C in "N_C(Lambda_K)" and a list of generators "listGen=[g_1,...,g_k]" of the group "G", the function "IdAuto" determines the automorphism "phi" of "G" fullfilling equation (a). More precisely, it returns tuples of exponents such that the i-th tuple [n_1,...,n_k] of the output fulfills phi(g_i)=g_1^(n_1)*...*g_k^(n_k). */ function IdAuto(C,listGen) seq:=[{0..Order(u)-1}: u in listGen]; loop:=CartesianProduct(seq); phi:=[]; for i in [1..#listGen] do for exp in loop do if C*listGen[i]*C^-1 eq &*[listGen[i]^exp[i]: i in [1..#listGen]] then Append(~phi,exp); end if; end for; end for; return phi; end function; /* The function "TestIso" checks if two given actions "v1" and "v2" (given as lists of translations parts) lead to biholomorphic quotients. As an input it gets the actions "v1" and "v2", the kernel "K", the normalizer "Nor=N_C(Lambda_K)", and the list of possible translation vectors "coboundaries" of the affinities. */ function TestIso(v1,v2,K,Nor,coboundaries,listGen) W1:=[MatAff(listGen[i],v1[i]): i in [1..#listGen]]; W2:= [MatAff(listGen[i],v2[i]): i in [1..#listGen]]; for C in Nor do phi:=IdAuto(C,listGen); phiW2:=W2; for i in [1..#listGen] do phiW2[i]:=&*[W2[i]^phi[i][j]: j in [1..#listGen]]; end for; for d in coboundaries do aff:=MatAff(C,d); test:=true; for i in [1..#listGen] do if not InLatt(TransVec(aff*W1[i]-phiW2[i]*aff),K) then test:=false; end if; end for; if test then return true; end if; end for; end for; return false; end function; /********************************************************************************************************************* ******************* PART II: specific functions for the classification for each group ******************************* *********************************************************************************************************************/ /****************************************** (a) G=Z3^3 **************************************************************/ /* The analytic representation of G=Z3^3= is given by rho(h)=Diag(1,ze^2,ze), rho(g)=Diag(ze,1,1), rho(k)=Diag(ze,ze,ze). The translation parts of the actions of the generators are given by tau(h)=a=(a1,a2,a3), tau(g)=b=(b1,b2,b3), tau(k)=0 (cocycle in standard form). */ /* Given "a" and "b" in Fix_ze3(E^3/K), the function "WellDefinedZ3xZ3xZ3" checks whether these two vectors define a well-defined action on T=E^3/K (cf. Lemma 4.3) */ function WellDefinedZ3xZ3xZ3(a,b,K) if not IsIntegral(3*a[1][1]) then return false; end if; if not InLatt(Matrix(F,3,1,[0,3*b[2][1],3*b[3][1]]),K) then return false; end if; if not TestKernelEndo(DiagonalMatrix([ze-1,1-ze^2,1-ze]),Matrix(F,3,1,[a[1][1],b[2][1],b[3][1]]),K) then return false; end if; return true; end function; /* The function "GoodCondZ3xZ3xZ3" checks whether a cocycle in standard form is good, i.e., the action has only isolated fixed points (cf. Lemma 4.4). Here, a=tau(h) and b=tau(g). */ function GoodCondZ3xZ3xZ3(a,b,K) for t1 in [0,t,-t] do w1:=Matrix(F,3,1,[t1,b[2][1],b[3][1]]); w2:=Matrix(F,3,1,[ze*a[1][1]+b[1][1],t1,a[3][1]+b[3][1]]); w3:=Matrix(F,3,1,[2*ze*a[1][1]+b[1][1],-ze*a[2][1]+b[2][1],t1]); if InLatt(w1,K) or InLatt(w2,K) or InLatt(w3,K) then return false; end if; for t2 in [0,t,-t] do w4:=Matrix(F,3,1,[a[1][1],t1,t2]); w5:=Matrix(F,3,1,[t1,a[2][1],t2]); w6:=Matrix(F,3,1,[t1,t2,a[3][1]]); w7:=Matrix(F,3,1,[b[1][1],t1,t2]); w8:=Matrix(F,3,1,[t1,a[2][1]+b[2][1],t2]); w9:=Matrix(F,3,1,[t1,t2,-ze^2*a[3][1]+b[3][1]]); if InLatt(w4,K) or InLatt(w5,K) or InLatt(w6,K) or InLatt(w7,K) or InLatt(w8,K) or InLatt(w9,K) then return false; end if; end for; end for; return true; end function; /* The function "ActionsZ3xZ3xZ3" determines all good cocycles in standard form on E^3/K for each kernel K (first output). The second output is a list consisting of one representative for each good comohomology class in H^1(Z_3^3,E^3/K). The actions are given as tuples of tranlsation parts of the generators h,g,k. As an input, it takes the kernel "K", the linear parts "listGen" of the actions of the generators, and the list "Fix" of fixed points of ze*id giving the coboundaries */ function ActionsZ3xZ3xZ3(K,Fix,listGen) ListTransVec:={}; ListOfActions:={}; for a in Fix do for b in Fix do if WellDefinedZ3xZ3xZ3(a,b,K) and GoodCondZ3xZ3xZ3(a,b,K) then ListTransVec:=Include(ListTransVec, [a,b,Matrix(F,3,1,[0,0,0])]); end if; end for; end for; ListOfActions:=ListTransVec; GoodClasses:={}; RefList:=ListTransVec; while not IsEmpty(ListTransVec) do RefList:=ListTransVec; v1:=Rep(ListTransVec); Include(~GoodClasses,v1); for v2 in ListTransVec do if TestCohom(v1,v2,listGen,K,Fix) then Exclude(~ListTransVec,v2); end if; end for; end while; return ListOfActions, GoodClasses; end function; /* The function "ClassZ3xZ3xZ3" is the main classification function. It determines for each kernel "K" all biholomorphism classes of three-dimensional quotients of the complex torus "T=E^3/K" by a rigid action of Z_3^3 that has finite fixed locus. Because of the size of the output and the length of the computation a file "Z3xZ3xZ3.txt" is created. It contains for each Kernel 1) the number of actions, 2) the number of good cohomology classes, 3) the size of the normalizer N_C(Lambda_K), 4) the number of biholomorphism classes and 5) for each biholomorphism class a corresponding action on E^3/K. "j" counts the kernels K=K_j. With the output of this function, we finish the classifification of Proposition 4.10 */ function ClassZ3xZ3xZ3(K,listGen,N,j) File:="Z3xZ3xZ3.txt"; fprintf File, "Kernel %o)\n \n", j; IsoClasses:=[]; Fix:=FixPoints(DiagonalMatrix([ze,ze,ze]),K,{Matrix(F,3,1,[d1,d2,d3]): d1,d2,d3 in E3}); LA,GoodClasses:=ActionsZ3xZ3xZ3(K,Fix,listGen); fprintf File, "Number of actions with isolated fixed points: %o \n \n", #LA; fprintf File, "Number of good cohomology classes: %o\n\n", #GoodClasses; RefListAct:=GoodClasses; Nor:=Normal(K,N); fprintf File, "Size of the normalizer: %o \n \n", #Nor; while not IsEmpty(GoodClasses) do RefListAct:=GoodClasses; v1:=Rep(GoodClasses); Append(~IsoClasses,v1); for v2 in RefListAct do if TestIso(v1,v2,K,Nor,Fix,listGen) then Exclude(~GoodClasses,v2); end if; end for; end while; fprintf File, "Number of biholomorphism classes: %o \n \n", #IsoClasses; fprintf File, "Actions [tau(h),tau(g),tau(k)]: \n %o \n \n \n \n", IsoClasses; return "Classification for kernel", j, "is completed!"; end function; /* With the procedure "MainZ3xZ3xZ3", we run the classification for the group "G=Z3^3". */ procedure MainZ3xZ3xZ3() g:=DiagonalMatrix([ze,1,1]); h:=DiagonalMatrix([1,ze^2,ze]); k:=DiagonalMatrix([ze,ze,ze]); listGen:=[h,g,k]; K1:={Matrix(F,3,1,[0,0,0])}; K2:={a*Matrix(F,3,1,[t,t,0]): a in {0,1,-1}}; K3:={a*Matrix(F,3,1,[t,t,t]): a in {0,1,-1}}; K4:={a*Matrix(F,3,1,[t,t,t])+b*Matrix(F,3,1,[t,-t,0]): a,b in {0,1,-1}}; Kernels:=[K1,K2,K3,K4]; N:=MatrixGroup<3,F| DiagonalMatrix([-ze,1,1]), Matrix([[0,1,0],[1,0,0],[0,0,1]]), Matrix([[0,1,0],[0,0,1],[1,0,0]])>; for j in [1..#Kernels] do ClassZ3xZ3xZ3(Kernels[j],listGen,N,j); end for; end procedure; /****************************************** (b) G=Z3^2, rho=rho_1 *****************************************************/ /* The first analytic representation of G=Z3^2=, rho=rho_1, is given by rho(h)=Diag(1,ze^2,ze^2), rho(k)=Diag(ze,ze,ze^2) The translation parts of the actions of the generators are given by tau(h)=a=(a1,a2,a3), tau(k)=0 (cocycle in standard form). */ /* The tranlsation vector a gives a well-defined action if and only if all entries a_i belong to E3 and a is a fixed point of rho(k). Since Fix(rho(k)) is contained in E3^3 and since we only consider these fixed points as candidates for a, we don't need a function "WellDefined" as before. */ /* The function "GoodCondZ3xZ3_1" checks whether a cocycle in standard form is good, i.e., the action has only isolated fixed points. Here, a=tau(h). */ function GoodCondZ3xZ3_1(a,K) for t1 in [0,t,-t] do for t2 in [0,t,-t] do w1:=Matrix(F,3,1,[a[1][1],t1,t2]); w2:=Matrix(F,3,1,[t1,a[2][1],t2]); w3:=Matrix(F,3,1,[t1,t2,a[3][1]]); if InLatt(w1,K) or InLatt(w2,K) or InLatt(w3,K) then return false; end if; end for; end for; return true; end function; /* The function "ActionsZ3xZ3_1" determines all good cocycles in standard form on E^3/K for each kernel K (first output). The second output is a list consisting of one representative for each good comohomology class in H^1(Z_3^2,E^3/K). The actions are given as tuples of tranlsation parts of the generators h,k. As an input, it takes the kernel "K", the linear parts "listGen" of the actions of the generators, and the list "Fix" of fixed points of "rho(k)" giving the coboundaries and the candidates for "a=tau(h)". */ function ActionsZ3xZ3_1(K,Fix,listGen) ListTransVec:={}; ListOfActions:={}; for a in Fix do if GoodCondZ3xZ3_1(a,K) then ListTransVec:=Include(ListTransVec, [a,Matrix(F,3,1,[0,0,0])]); end if; end for; ListOfActions:=ListTransVec; GoodClasses:={}; RefList:=ListTransVec; while not IsEmpty(ListTransVec) do RefList:=ListTransVec; v1:=Rep(ListTransVec); Include(~GoodClasses,v1); for v2 in ListTransVec do if TestCohom(v1,v2,listGen,K,Fix) then Exclude(~ListTransVec,v2); end if; end for; end while; return ListOfActions, GoodClasses; end function; /* The function "ClassZ3xZ3_1" is the main classification function. It determines for each kernel "K" all biholomorphism classes of three-dimensional quotients of the complex torus "T=E^3/K" by a rigid action of Z_3^2 with rho=rho_1 that has finite fixed locus. Because of the size of the output and the length of the computation a file "Z3xZ3_rho1.txt" is created. It contains for each Kernel 1) the number of actions, 2) the number of good cohomology classes, 3) the size of the normalizer N_C(Lambda_K), 4) the number of biholomorphism classes and 5) for each biholomorphism class a corresponding action on E^3/K. With the output of this function, we finish the classifification of Proposition 4.12. */ function ClassZ3xZ3_1(K,listGen,N,j) File:="Z3xZ3_rho1.txt"; fprintf File, "Kernel %o)\n \n", j; IsoClasses:=[]; Fix:=FixPoints(DiagonalMatrix([ze,ze,ze^2]),K,{Matrix(F,3,1,[d1,d2,d3]): d1,d2,d3 in E3}); LA,GoodClasses:=ActionsZ3xZ3_1(K,Fix,listGen); fprintf File, "Number of actions with isolated fixed points: %o \n \n", #LA; fprintf File, "Number of good cohomology classes: %o\n\n", #GoodClasses; RefListAct:=GoodClasses; Nor:=Normal(K,N); fprintf File, "Size of the normalizer: %o \n \n", #Nor; while not IsEmpty(GoodClasses) do RefListAct:=GoodClasses; v1:=Rep(GoodClasses); Append(~IsoClasses,v1); for v2 in RefListAct do if TestIso(v1,v2,K,Nor,Fix,listGen) then Exclude(~GoodClasses,v2); end if; end for; end while; fprintf File, "Number of biholomorphism classes: %o \n \n", #IsoClasses; fprintf File, "Actions [tau(h),tau(k)]: \n %o \n \n \n \n", IsoClasses; return "Classification for kernel", j, "is completed!"; end function; /* With the procedure "MainZ3xZ3_1", we run the classification for the group "G=Z3^2", where "rho=rho_1". */ procedure MainZ3xZ3_1() h:=DiagonalMatrix([1,ze^2,ze^2]); k:=DiagonalMatrix([ze,ze,ze^2]); listGen:=[h,k]; K1:={Matrix(F,3,1,[0,0,0])}; K2:={a*Matrix(F,3,1,[t,t,0]): a in {0,1,-1}}; K3:={a*Matrix(F,3,1,[t,0,t]): a in {0,1,-1}}; K4:={a*Matrix(F,3,1,[t,t,t]): a in {0,1,-1}}; K5:={a*Matrix(F,3,1,[t,t,t])+b*Matrix(F,3,1,[t,-t,0]): a,b in {0,1,-1}}; Kernels:=[K1,K2,K3,K4,K5]; N:=MatrixGroup<3,F| DiagonalMatrix([-ze,1,1]), DiagonalMatrix([1,1,-ze]), Matrix([[0,1,0],[1,0,0],[0,0,1]])>; for j in [1..#Kernels] do ClassZ3xZ3_1(Kernels[j],listGen,N,j); end for; end procedure; /****************************************** (c) G=Z3^2, rho=rho_2 *****************************************************/ /* The second analytic representation of G=Z3^2=, rho=rho_2, is given by rho(h)=Diag(ze,ze,1), rho(k)=Diag(ze,ze,ze). The translation parts of the actions of the generators are given by tau(h)=a=(a1,a2,a3), tau(k)=0 (cocycle in standard form). The torus is T=E^3/K, where K=<(t,t,t)>. (The classification for the other torus T=E^3 is done without MAGMA). */ /* The tranlsation vector a gives a well-defined action if and only if all entries a_i belong to E3 and a is a fixed point of rho(k) (cf. Lemma 4.15). Since Fix(rho(k)) is contained in E3^3 and since we only consider these fixed points as candidates for a, we don't need a function "WellDefined" as before. */ /* The function "GoodCondZ3xZ3_2" checks whether a cocycle in standard form is good, i.e., the action has only isolated fixed points (cf. Lemma 4.16). Here, a=tau(h). */ function GoodCondZ3xZ3_2(a,K) for t1 in [0,t,-t] do if InLatt(Matrix(F,3,1,[a[1][1],a[2][1],t1]),K) then return false; end if; for t2 in [0,t,-t] do if InLatt(Matrix(F,3,1,[t1,t2,a[3][1]]),K) then return false; end if; end for; end for; return true; end function; /* The function "ActionsZ3xZ3_2" determines all good cocycles in standard form on T=E^3/K (first output). The second output is a list consisting of one representative for each good comohomology class in H^1(Z_3^2,E^3/K). The actions are given as tuples of tranlsation parts of the generators h,k. As an input, it takes the kernel "K", the linear parts "listGen" of the actions of the generators, and the list "Fix" of fixed points of "rho(k)" giving the coboundaries and the candidates for "a=tau(h)". The list of actions/cohomology classes is used in the proof of Proposition 4.20 in order to finish the classification. */ function ActionsZ3xZ3_2(K,Fix,listGen) ListTransVec:={}; ListOfActions:={}; for a in Fix do if GoodCondZ3xZ3_2(a,K) then ListTransVec:=Include(ListTransVec, [a,Matrix(F,3,1,[0,0,0])]); end if; end for; ListOfActions:=ListTransVec; GoodClasses:={}; RefList:=ListTransVec; while not IsEmpty(ListTransVec) do RefList:=ListTransVec; v1:=Rep(ListTransVec); Include(~GoodClasses,v1); for v2 in ListTransVec do if TestCohom(v1,v2,listGen,K,Fix) then Exclude(~ListTransVec,v2); end if; end for; end while; return ListOfActions, GoodClasses; end function; /* The procedure "MainZ3xZ3_2", displays one representative of each good cohomology class in H^1(Z3^2, E^3/K). Since the output isn't long, we don't create a file. Note that these representatives may differ by the ones given in the prove of Proposition 4.20, but they are cohomologuos as can be seen using the function "TestCohom" with "coboundaries= fixed points of rho(k)". */ procedure MainZ3xZ3_2() h:=DiagonalMatrix([ze,ze,1]); k:=DiagonalMatrix([ze,ze,ze]); listGen:=[h,k]; K:={a*Matrix(F,3,1,[t,t,t]): a in {0,1,-1}}; Fix:=FixPoints(k,K,{Matrix(F,3,1,[d1,d2,d3]): d1,d2,d3 in E3}); LA, GC:=ActionsZ3xZ3_2(K,Fix,listGen); GC; end procedure; /****************************************** (d) G=Z9:Z3 *****************************************************/ /* The analytic representation of G=Z9:Z3= is given by rho(h)=Diag(1,ze^2,ze) and rho(g)=[0,1,0], [0,0,1] [ze,0,0] The translation parts of the actions of the generators are tau(h)=a=(a1,a2,a3), tau(g)=0 (cocycle in standard form). */ /* Given "a" in E3^3, the function "WellDefinedZ9Z3" checks whether this vector defines a well-defined action on T=E^3/K (cf. proof of Proposition 4.21) */ function WellDefinedZ9Z3(a,K) if TestKernelEndo(Matrix(F,3,3,[0,1,0,0,0,1,ze,0,0])-I3,a,K) then return true; end if; return false; end function; /* The function "GoodCondZ9Z3" checks whether a cocycle in standard form is good, i.e., the action has only isolated fixed points (cf. proof of Proposition 4.21). Here, a=tau(h). */ function GoodCondZ9Z3(a,K) for t1 in [0,t,-t] do for t2 in [0,t,-t] do w1:=Matrix(F,3,1,[a[1][1],t1,t2]); w2:=Matrix(F,3,1,[t1,a[2][1],t2]); w3:=Matrix(F,3,1,[t1,t2,a[3][1]]); if InLatt(w1,K) or InLatt(w2,K) or InLatt(w3,K) then return false; end if; end for; end for; return true; end function; /* The function "Actions" determines all actions with only isolated fixed points with translation part in standard form on E^3/K, for each kernel K. output: list of possible translation vectors tau(h) for each kernel */ function Actions(K) list:=[]; for a1 in E3 do for a2 in E3 do for a3 in E3 do a:=Matrix(F,3,1,[a1,a2,a3]); if WellDefinedZ9Z3(a,K) and GoodCondZ9Z3(a,K) then Append(~list,a); end if; end for; end for; end for; transpart:=[]; while not IsEmpty(list) do a:=Rep(list); Append(~transpart,a); for b in list do if InLatt(a-b,K) then Exclude(~list,b); end if; end for; end while; return transpart; end function; /* With the procedure "MainZ9Z3", we generate all actions for the group "G=Z9:Z3". Since the output is not long, we don't create a file. */ procedure MainZ9Z3() K1:={Matrix(F,3,1,[0,0,0])}; K2:={a*Matrix(F,3,1,[t,t,t]): a in {0,1,-1}}; K3:={a*Matrix(F,3,1,[t,t,t])+b*Matrix(F,3,1,[t,-t,0]): a,b in {0,1,-1}}; Kernels:=[K1,K2,K3]; for j in [1..#Kernels] do Actions(Kernels[j]); end for; end procedure;