\\ --------------- GP code ------------------------------------------------------------ \\ Library for the program Bianchi.gp \\ \\ Description: Compute the quotient of Hyperbolic Space by PSL_2 of imaginary \\ quadratic number fields \\ \\ \\ Author: Alexander D. Rahm \\ \\ Copyright (C) 2010 by Alexander D. Rahm. \\ Bianchi.gp is a free software covered by the GNU General Public License. \\ Version 1.0.0 of October 29th, 2010. \\--------------------------------------------------------------------------------------- Covolume()= { local(discriminant, numberField, zetaValue); numberField = zetakinit(x^2 +m); if ( mIs3mod4 == 0, /* m not congruent to 3 mod 4 */ discriminant = -4*m; , /* else m congruent 3 mod 4 */ discriminant = -m; ); zetaValue = zetak( numberField, 2); /* return the covolume: */ zetaValue/(4*(Pi^2))*sqrt((-discriminant)^3) }; OutputFiles() = { writeVertexStabilizers(); writeStabilizersOfOrbits(); writeEdgeStabilizers(); writeRepresentativeEdgeStabilizers(); printEdges(); print2cellEdges(); writeEquivariantEulerCharacteristic(); plotColouredGraph(); writeE2pages(); write("logfile.txt", logfile); }; /* end of procedure Output. */ drawLinesOfSpheres() = { local(parametricPlotVector, numberOfLinesToDraw: small, numberOfRegisteredLines: small, xOrigin, yOrigin, xTarget, yTarget); numberOfLinesToDraw = 0; for (j = 1, numberOfSpheres, numberOfLinesToDraw = numberOfLinesToDraw +length(linesOfSphere[j]:list); ); parametricPlotVector = vector(2*numberOfLinesToDraw); numberOfRegisteredLines = 0; for (j = 1, numberOfSpheres, if(sphereCenter[j] == [0,0]~, for (r = 1, length(linesOfSphere[j]:list), xOrigin = component(linesOfSphere[j]:list[r][1],1); xTarget = component(linesOfSphere[j]:list[r][2],1); yOrigin = component(linesOfSphere[j]:list[r][1],2); yTarget = component(linesOfSphere[j]:list[r][2],2); if ( mIs3mod4, /* To get coordinates a +b*i*sqrt(m) := x +y*w, put a := x -y/2 and b := y/2 */ parametricPlotVector[2*numberOfRegisteredLines +2*r -1] = xOrigin -yOrigin/2 + 't*(xTarget -yTarget/2); parametricPlotVector[2*numberOfRegisteredLines +2*r] = (yOrigin/2 + 't*yTarget/2) * sqrt(m); , /* else m not congruent 3 mod 4 */ parametricPlotVector[2*numberOfRegisteredLines +2*r -1] = xOrigin + 't*xTarget; parametricPlotVector[2*numberOfRegisteredLines +2*r] = (yOrigin + 't*yTarget) * sqrt(m); ); ); numberOfRegisteredLines = numberOfRegisteredLines + length(linesOfSphere[j]:list); ); ); default( psfile, Str("sketch_m=",m, ".ps") ); eval(Str("psploth(t=0,1,"parametricPlotVector",1)")); }; /* end of the output procedure drawLinesOfSpheres */ printEdges(psPrint = 0, Scale = 35/sqrt(m) ) = { local( edgeOrigin:list, edgeEnd:list, drawparameter); drawparameter = 0; edgeOrigin = listcreate(2*numberOfLines); edgeEnd = listcreate(2*numberOfLines); for (j = 1, length( edgesList), listput(edgeOrigin, component(eval(edgesList[j]),1) ); listput(edgeEnd, component(eval(edgesList[j]),2) ); drawparameter = drawparameter + 2; ); if( psPrint == 1, /* obsolete: */ drawpolygons(edgeOrigin,edgeEnd,drawparameter); ,/* else the standard: */ polygonsToPSTricks(edgeOrigin, edgeEnd, Scale); ); }; {addhelp(printEdges, "The Bianchi diagram is drawn by printEdges(psPrint). Writes PSTricks code if the flag psPrint is omitted. m=mdiagram.ps is plotted with psPrint = 1.");} /* end of output procedure printEdges. */ print2cellEdges( Scale = 35/sqrt(m) ) = { /* Write in PSTricks code the edges of the 2-cells which are in the quotient, with the vertices labeled by their orbits. */ local( edgeOrigin:list, edgeEnd:list, edgesToPrint:list); edgeOrigin = listcreate( 2*numberOfLines); edgeEnd = listcreate( 2*numberOfLines); edgesToPrint = List([]); for (j = 1, numberOf2cells, if( deleteCellFlag[j] == 0, /* Put the edges of the 2-cell on this hemisphere into the list edgesToPrint. */ for(k = 1, length(edgesOf2cell[j]), listput( edgesToPrint, edgesOf2cell[j][k]); ); if( length( edgesOf2cell[j]) < 3, print("***Error in output procedure print2cellEdges: Less than three edges on 2-cell number ",j); ); ); ); /* Cleanse the edgesToPrint list of the double entries. */ listsort( edgesToPrint, 1); for( r = 1, length( edgesToPrint), listput(edgeOrigin, component( eval( edgesList[ edgesToPrint[r]]), 1) ); listput(edgeEnd, component( eval( edgesList[ edgesToPrint[r]]), 2) ); ); /* Write in PSTricks code these edges. */ polygonsToPSTricks(edgeOrigin, edgeEnd, Scale, Str("m",m,"quotient2cells.tex") ); }; {addhelp(print2cellEdges, "Writes in PSTricks code the edges of the 2-cells which are in the quotient, with the vertices labeled by their orbits.");} /* end of output procedure print2cellEdges. */ PSprintGeneratorsOfH2( A = matker(CellBoundaryMatrix), Scale = 35/sqrt(m) ) = { /* Write in PSTricks code the edges of the 2-chains which are in the kernel of the d^1_{2,0} differential. */ /* Optional input is a transformed matrix for the kernel of the d^1_{2,0} differential. */ local( twoCellColour); twoCellColour = vector(numberOf2cells); for (k = 1, matrank(A), for( j = 1, numberOf2cells, /* If the 2-cell number j appears in the k-th generating chain of the kernel of the d^1_{2,0} differential, */ if( A[j,k] != 0, /* Add the colour number k to the 2-cell number j in the vector twoCellColour. */ twoCellColour[j] = twoCellColour[j] +2^k; ); ); ); twoCellsToPSTricks(twoCellColour,Scale); }; /* end of the output procedure PSprintGeneratorsOfH2. */ twoCellsToPSTricks(twoCellColour, Scale = 35/sqrt(m), filename = Str("m",m,"GeneratorsOfH2.tex") ) = { local( vertexNumber, Corner, a, cellColour); write( filename, "\\documentclass[oneside,a4paper,11 pt]{article} ", "\\usepackage[dvipsnames]{pstricks} \\usepackage{pstricks-add} \\begin{document} \\pagestyle{empty}"); if( Mod(m,4) == Mod(3,4), write( filename, Str("\\begin{pspicture}(",Scale,",",Scale*sqrt(m)/2,")") ); , /* else */ write( filename, Str("\\begin{pspicture}(",Scale,",",Scale*sqrt(m),")") ); ); for( j = 1, numberOf2cells, if( twoCellColour[j] > 0, cellColour = pickColour(twoCellColour[j]); write( filename, " \\pspolygon[fillstyle = solid, fillcolor = ",cellColour,"]"); if( cellColour == 0, print("Please define colour ",twoCellColour[j]," in pickColour."); ); for (r = 1, length(cornersOf2cell[j]), vertexNumber = cornersOf2cell[j][r]; Corner = component( eval(totalPointSet[vertexNumber]), 1); if ( Mod(m,4) != Mod(3,4), write(filename, Str("(",component( Corner, 1)*Scale, ",", component( Corner, 2)*Scale*sqrt(m),")" )); ,/* else for m congruent 3 mod 4, a +b*i*sqrt(m) := x +w*y, */ /* a:= x -y/2 and b := y/2 */ a = component( Corner, 1)*Scale -1/2*component( Corner, 2)*Scale; if ( abs( frac( a)) < 10^(-20), a = round(a); /* Round an imprecise integer to its "almost" value.*/; ); write(filename, Str("(", a,",", 1/2*component(Corner, 2)*Scale*sqrt(m),")" )); ); ); ); ); labelSingularVertices(filename, Scale); write(filename, " \\end{pspicture} \\end{document}"); }; pickColour(k) = { local( palette); palette = vector(2129); /* Cold (blue) colours for the unique occurencies (powers of 2). */ palette[2] = "CornflowerBlue"; palette[4] = "cyan "; palette[8] = "Cerulean"; palette[16] = " MidnightBlue"; palette[32] = "RoyalBlue"; palette[64] = "SkyBlue"; /* Warm colours for the multiple occurencies. */ palette[6] = "BurntOrange "; palette[10] = " brown"; palette[12] = "red "; palette[14] = " orange"; palette[18] = "Mahogany "; palette[20] = "Mulberry "; palette[24] = "RubineRed"; palette[36] = "Melon"; palette[38] = "Dandelion"; palette[44] = "RedOrange"; palette[48] = "Rhodamine"; palette[52] = "Lavender"; palette[72] = "WildStrawberry"; palette[106] = "GreenYellow"; palette[102] = "Yellow"; palette[76] = "Peach"; palette[74] = "Magenta"; palette[122] ="VioletRed"; palette[98] = "RedViolet"; palette[90] = "Fuchsia"; palette[104] = "Thistle"; palette[128] = "Orchid"; palette[88] = "YellowOrange"; palette[34] = "RawSienna"; palette[50] = "Tan"; palette[92] = "Goldenrod"; palette[96] = "Salmon"; palette[112] = "Bittersweet"; palette[116] = "CarnationPink"; palette[120] = "BrickRed"; palette[124] = "Maroon"; palette[126] = "Apricot"; /* return */ palette[k] }; printEdgeRepresentatives( Scale = 35/sqrt(m) ) = { /* Write in PSTricks code the edge representatives, in the colours of the ell-axis graphs if they belong to some. Label only the vertices which lie on some axis graph. */ local( edgeOrigin:list, edgeEnd:list, edgeStabilizerType:list); edgeOrigin = listcreate( numberOfEdgeOrbits); edgeEnd = listcreate( numberOfEdgeOrbits); edgeStabilizerType = listcreate( numberOfEdgeOrbits); for( r = 1, numberOfEdgeOrbits, listput(edgeOrigin, component( eval( edgesList[ edgeOrbitRepresentative[r]]), 1) ); listput(edgeEnd, component( eval( edgesList[ edgeOrbitRepresentative[r]]), 2) ); listput(edgeStabilizerType, length( edgeStabilizer[ edgeOrbitRepresentative[r]])); ); /* Write in PSTricks code these edges. */ printGraphInPSTricks(edgeOrigin, edgeEnd, edgeStabilizerType:list, Scale, ); }; /* end of output procedure printEdgeRepresentatives */ plotColouredGraph( Scale = 20.0/sqrt(m), mode="normal" ) = { /* Write in PSTricks code the edges of the 2-cells which are in the quotient, */ /* in the colours of the ell-axis graphs if they belong to some. Label only the vertices which lie on some axis graph. */ local( edgeOrigin:list, edgeEnd:list, edgesToPrint:list, edgeStabilizerType:list, IsRepresentative); edgeOrigin = listcreate( 2*numberOfLines); edgeEnd = listcreate( 2*numberOfLines); edgeStabilizerType = listcreate( 2*numberOfLines); IsRepresentative = vector( 2*numberOfLines); edgesToPrint = listcreate( 2*numberOfLines); if( mIs3mod4, Scale = Scale*2; ); for (j = 1, numberOf2cells, if( deleteCellFlag[j] == 0, /* Put the edges of the 2-cell on this hemisphere into the list edgesToPrint. */ for(k = 1, length(edgesOf2cell[j]), listput( edgesToPrint, edgesOf2cell[j][k]); ); if( length( edgesOf2cell[j]) < 3, print("***Error in output procedure plotColouredGraph: Less than three edges on 2-cell number ",j); ); ); ); /* Cleanse the edgesToPrint list of the double entries. */ listsort( edgesToPrint, 1); for( r = 1, length( edgesToPrint), listput(edgeOrigin, component( eval( edgesList[ edgesToPrint[r]]), 1) ); listput(edgeEnd, component( eval( edgesList[ edgesToPrint[r]]), 2) ); listput(edgeStabilizerType, length( edgeStabilizer[ edgesToPrint[r]])); if( edgesToPrint[r] == edgeOrbitRepresentative[edgeOrbitNumber[edgesToPrint[r]]], IsRepresentative[r] = 1; ); ); /* Write in PSTricks code these edges. */ printAxesGraphInPSTricks(edgeOrigin:list, edgeEnd:list, edgeStabilizerType:list, IsRepresentative, Scale, ,mode); }; /* end of output procedure plotColouredGraph.*/ CountEdgesOnOrbits() = { /* Count the maximal number of edges in the Bianchi Fundamental Polyhedron, which are on the same orbit. */ local( edgesToCount:list, edgesCounter, n); edgesToCount =listcreate( 2*numberOfLines); for (j = 1, numberOf2cells, if( deleteCellFlag[j] == 0, /* Put the edges of the 2-cell on this hemisphere */ /* into the list edgesToCount. */ for(k = 1, length(edgesOf2cell[j]), listput( edgesToCount, edgesOf2cell[j][k]); ); ); ); /* Cleanse the edgesToCount list of the double entries. */ listsort( edgesToCount, 1); edgesCounter = vector(numberOfEdgeOrbits); for( k = 1, length( edgesToCount), n = edgeOrbitNumber[ edgesToCount[k]]; if( n > 0, edgesCounter[n]++; ); ); print("Maximal number of edges in the Bianchi Fundamental Polyhedron, which are on the same orbit: ",vecmax(edgesCounter)); print("Covolume: ",Covolume()); }; /* end of output procedure CountEdgesOnOrbits.*/ writeEdgeStabilizers() = { local(filename, Output, groups, edgeOrigin, edgeEnd, endPointNumber, originPointNumber, Cardinal); filename = concat("m=",m); filename = concat(filename,"edgeStabilizers.tex"); groups = loadFiniteSubgroupTable(); write(filename, "Edge stabilizers for m = ", m); for ( j = 1, length(edgesList), edgeOrigin = eval(edgesList[j][1]); edgeEnd = eval(edgesList[j][2]); Cardinal = length( edgeStabilizer[j]); if ( Cardinal != 2, /* non-trivial stabilizer */ if ( component(edgeOrigin,2) == 0 || component(edgeEnd,2) == 0, /* cusps have height zero */ error("Arc from a cusp non-trivially stabilized. Check the computation of edgeStabilizer"); ); ); originPointNumber = setsearch( totalPointSet, edgeOrigin); endPointNumber = setsearch( totalPointSet, edgeEnd); if (Cardinal == 23, /* 23 is artificially associated to Z^2 */ error("Singular edge. Check the computation of edgeStabilizer"); ); Cardinal = Cardinal /2; /* PSL_2 */ Output = concat( "{", groups[Cardinal]); if (Cardinal != 1, write(filename, "\\Gamma_{(", originPointNumber,"),(", endPointNumber,")} = "); writeMatrixList( edgeStabilizer[j], filename); write( filename, " \\cong ", Output, "} $$ $$" ); ); ); }; /* end of the output procedure writeEdgeStabilizers(). */ writeRepresentativeEdgeStabilizers() = { local(filename2, filename3, Output, edgeOrigin, edgeEnd, endPointNumber, originPointNumber, Cardinal, Stabilizer, edgeNumber, OrbitRepr, groups); filename2 = Str("2primary_m=",m,"RepresentativeEdgeStabilizers.tex"); filename3 = Str("3primary_m=",m,"RepresentativeEdgeStabilizers.tex"); write(filename2, "2-primary part of representative edge stabilizers for m = ",m); write(filename3, "3-primary part of representative edge stabilizers for m = ",m); write(filename2, "\\scriptsize $$"); write(filename3, "\\scriptsize $$"); groups = loadFiniteSubgroupTable(); for ( j = 1, numberOfEdgeOrbits, edgeNumber = edgeOrbitRepresentative[j]; edgeOrigin = eval(edgesList[ edgeNumber][1]); edgeEnd = eval(edgesList[ edgeNumber][2]); Stabilizer = edgeStabilizer[ edgeNumber]; Cardinal = length( Stabilizer); originPointNumber = setsearch( totalPointSet, edgeOrigin); endPointNumber = setsearch( totalPointSet, edgeEnd); Cardinal = Cardinal /2; /* From now on, pass from SL_2 to PSL_2 */ Output = concat( "{", groups[Cardinal]); if (Cardinal == 2, write(filename2, "\\Gamma_{(", originPointNumber,"),(", endPointNumber,")} = "); writeMatrixList( Stabilizer, filename2); write( filename2, " \\cong ", Output, "} $$ $$" ); /* If the vertex "edgeOrigin" doesn't represent its orbit, */ /* write its stabilizer and the conjugated representative stabilizer. */ OrbitRepr = vertexOrbitRepresentative[ vertexOrbitNumber[originPointNumber]]; if( originPointNumber != OrbitRepr, write(filename2, "$$ We use the identification of (", originPointNumber,") with ("); write( filename2, OrbitRepr,"). $$"); /* writeMatrixList( stabilizer[ OrbitRepr], filename2); */ ); /* If the vertex "edgeEnd" doesn't represent its orbit, */ /* write its stabilizer and the conjugated representative stabilizer. */ OrbitRepr = vertexOrbitRepresentative[ vertexOrbitNumber[endPointNumber]]; if( endPointNumber != OrbitRepr, write(filename2, "$$ We use the identification of (", endPointNumber,") with ("); write( filename2, OrbitRepr,"). $$"); /* writeMatrixList( stabilizer[ OrbitRepr], filename2); */ ); ); if (Cardinal == 3, write(filename3, "\\Gamma_{(", originPointNumber,"),(", endPointNumber,")} = "); writeMatrixList( Stabilizer, filename3); write( filename3, " \\cong ", Output, "} $$ $$" ); /* If the vertex "edgeOrigin" doesn't represent its orbit, */ /* write its stabilizer and the conjugation matrices to reach */ /* the representative stabilizer. */ OrbitRepr = vertexOrbitRepresentative[ vertexOrbitNumber[originPointNumber]]; if( originPointNumber != OrbitRepr, write(filename3, "$$ The conjugation matrices $$"); writeMatrixList( vertexIdentifications[ originPointNumber, OrbitRepr], filename3); write(filename3, "$$ give an identification of (", originPointNumber,") with ("); write( filename3, OrbitRepr,"). $$"); /* writeMatrixList( stabilizer[ OrbitRepr], filename3); */ ); /* If the vertex "edgeEnd" doesn't represent its orbit, */ /* write its stabilizer and the conjugation matrices to reach */ /* the representative stabilizer. */ OrbitRepr = vertexOrbitRepresentative[ vertexOrbitNumber[endPointNumber]]; if( endPointNumber != OrbitRepr, write(filename3, "$$ The conjugation matrices $$"); writeMatrixList( vertexIdentifications[ endPointNumber, OrbitRepr], filename3); write(filename3, "$$ give an identification of (", endPointNumber,") with (");; write( filename3, OrbitRepr,"). $$"); /* writeMatrixList( stabilizer[ OrbitRepr], filename3); */ ); ); if (Cardinal > 3, print( "***Error in output procedure writeRepresentativeEdgeStabilizers: size of edge stabilizer exceeds 3."); ); ); write( filename2, "$$ \\normalsize"); write( filename3, "$$ \\normalsize"); }; /* end of output procedure writeRepresentativeEdgeStabilizers. */ drawpolygons(edgeOrigin:list,edgeEnd:list,drawparameter) = { local(parametricPlotVector, projectedOrigin, projectedEnd); parametricPlotVector = vector(drawparameter); for (r = 1, length(edgeOrigin), projectedOrigin = component( edgeOrigin[r], 1); projectedEnd = component( edgeEnd[r], 1); if ( mIs3mod4, /* As w = -1/2 +1/2*sqrt(-m), let a +b*i*sqrt(m) := x +w*y, */ /* more precisely a:= x -y/2 and b := y/2 */ parametricPlotVector[2*r] = component(projectedOrigin,1) -component(projectedOrigin,2)/2 + 't*(component(projectedEnd-projectedOrigin,1) -component(projectedEnd-projectedOrigin,2)/2); parametricPlotVector[2*r-1] = (component(projectedOrigin,2)/2 + 't*component(projectedEnd-projectedOrigin,2)/2 ) * sqrt(m); ,/* else for m not congruent to 3 mod 4, */ parametricPlotVector[2*r] = component(projectedOrigin,1) + 't*component(projectedEnd-projectedOrigin,1); parametricPlotVector[2*r-1] = (component(projectedOrigin,2) + 't*component(projectedEnd-projectedOrigin,2)) * sqrt(m); ); ); eval(Str("psploth(t=0,1,"parametricPlotVector",25)")); }; /* end of output procedure drawpolygons */ polygonsToPSTricks( edgeOrigin:list, edgeEnd:list, Scale = 35/sqrt(m), filename = Str("m",m,"polygons.tex") ) = { local( endPointList:list, vertexNumber, projectedOrigin, projectedEnd); local( origin_a, end_a); endPointList = listcreate( 4*numberOfEdgeOrbits ); write( filename, "\\documentclass[oneside,a4paper,11 pt]{article} ", "\\usepackage{pstricks, pstricks-add} \\begin{document} \\pagestyle{empty}"); if( mIs3mod4, write( filename, Str("\\begin{pspicture}(",Scale,",",Scale*sqrt(m)/2,") {") ); , /* else */ write( filename, Str("\\begin{pspicture}(",Scale,",",Scale*sqrt(m),") {") ); ); for (r = 1, length(edgeOrigin), projectedOrigin = component( edgeOrigin[r], 1); projectedEnd = component( edgeEnd[r], 1); if ( mIs3mod4 == 0, write(filename, Str("\\psline[](",component( projectedOrigin, 1)*Scale, ",", component( projectedOrigin, 2)*Scale*sqrt(m), ")(",component( projectedEnd, 1)*Scale, ",", component( projectedEnd, 2)*Scale*sqrt(m),")" )); vertexNumber = setsearch( totalPointSet, edgeOrigin[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); ); vertexNumber = setsearch( totalPointSet, edgeEnd[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); ); , /* else for m congruent 3 mod 4, a +b*i*sqrt(m) := x +w*y, a:= x -y/2 and b := y/2 */ origin_a = component(projectedOrigin,1)*Scale -1/2*component(projectedOrigin,2)*Scale; if ( abs( frac( origin_a)) < 10^(-20), origin_a = round(origin_a); /* Round an imprecise integer to its "almost" value.*/; ); end_a = component(projectedEnd,1)*Scale -1/2*component(projectedEnd,2)*Scale; if ( abs( frac( end_a)) < 10^(-20), end_a = round(end_a); /* Round an imprecise integer to its "almost" value. */ ); write(filename, Str("\\psline[](", origin_a,",", 1/2*component(projectedOrigin,2)*Scale*sqrt(m),")(", end_a,",", 1/2*component(projectedEnd,2)*Scale*sqrt(m),")" )); vertexNumber = setsearch( totalPointSet, edgeOrigin[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); ); vertexNumber = setsearch( totalPointSet, edgeEnd[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); ); ); listsort( endPointList, 1); /* The flag "1" deletes all but one occurence of each element. */ ); labelVertices(filename, endPointList:list, Scale); labelVertexRepresentatives(filename, Scale); write(filename, "} \\end{pspicture} \\end{document}"); }; /* end of output procedure polygonsToPSTricks */ printAxesGraphInPSTricks( edgeOrigin:list, edgeEnd:list, edgeStabilizerType:list, IsRepresentative, Scale = 35/sqrt(m), filename = Str("m",m,"colouredGraph.tex"), mode="normal") = { local( endPointList:list, representativePointList:list, vertexNumber, projectedOrigin, projectedEnd); local( origin_a, end_a, verticesToBeLabeled, edgesToBePrinted); endPointList = listcreate( 2*numberOfEdgeOrbits ); representativePointList = listcreate( 2*numberOfEdgeOrbits ); write( filename, "\\documentclass[oneside,a4paper,11 pt]{article} ", "\\usepackage{pstricks, pstricks-add} \\begin{document} \\pagestyle{empty}"); if( mIs3mod4, write( filename, Str("\\begin{pspicture}(",Scale,",",Scale*sqrt(m)/2,") {") ); , /* else */ write( filename, Str("\\begin{pspicture}(",Scale,",",Scale*sqrt(m),") {") ); ); for (r = 1, length(edgeOrigin), projectedOrigin = component( edgeOrigin[r], 1); projectedEnd = component( edgeEnd[r], 1); if( edgeStabilizerType[r] == 2 && mode != "reduced", write(filename, Str("\\psset{linecolor=black,linestyle = solid} \\psline[]")); ); if( edgeStabilizerType[r] == 4, if( IsRepresentative[r] == 1, write(filename, Str("\\psset{linecolor=green,linestyle = dashed} \\psline[]")); ,/*else*/ write(filename, Str("\\psset{linecolor=black,linestyle = dashed} \\psline[]")); ); ); if( edgeStabilizerType[r] == 6 && mode != "reduced", if( IsRepresentative[r] == 1, write(filename, Str( "\\psset{linecolor=blue,linestyle = dotted} \\psline[dotsep = 0.1pt]")); ,/*else*/ write(filename, Str( "\\psset{linecolor=black,linestyle = dotted} \\psline[dotsep = 0.1pt]")); ); ); if(edgeStabilizerType[r] !=2 && edgeStabilizerType[r] !=4 && edgeStabilizerType[r] !=6, print("***Error in output procedure printAxesGraphInPSTricks: edgeStabilizerType[",r,"] = ",edgeStabilizerType[r]); ); if( mode == "reduced", /* if of 2-torsion stabilizer, print edge */ edgesToBePrinted = (edgeStabilizerType[r] == 4); , /* else in the normal modes, print all the edges : */ edgesToBePrinted = 1; ); if( edgesToBePrinted, if ( mIs3mod4 == 0, /* m not congruent to 3 mod 4 */ write(filename, Str("(",component( projectedOrigin, 1)*Scale, ",", component( projectedOrigin, 2)*Scale*sqrt(m), ")(",component( projectedEnd, 1)*Scale, ",", component( projectedEnd, 2)*Scale*sqrt(m),")" )); if( mode == 2, /* if of 2-torsion stabilizer, label vertices */ verticesToBeLabeled = (edgeStabilizerType[r] == 4); , /* else in the normal mode: */ /* if not of trivial stabilizer, label vertices */ verticesToBeLabeled = (edgeStabilizerType[r] > 2); ); if( verticesToBeLabeled, vertexNumber = setsearch( totalPointSet, edgeOrigin[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); , /* else */ listput( representativePointList, vertexNumber); ); vertexNumber = setsearch( totalPointSet, edgeEnd[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); , /* else */ listput( representativePointList, vertexNumber); ); ); , /* else for m congruent 3 mod 4, a +b*i*sqrt(m) := x +w*y, a:= x -y/2 and b := y/2 */ origin_a = component(projectedOrigin,1)*Scale -1/2*component(projectedOrigin,2)*Scale; if ( abs( frac( origin_a)) < 10^(-20), origin_a = round(origin_a); /* Round an imprecise integer to its "almost" value.*/ ); end_a = component(projectedEnd,1)*Scale -1/2*component(projectedEnd,2)*Scale; if ( abs( frac( end_a)) < 10^(-20), end_a = round(end_a); /* Round an imprecise integer to its "almost" value. */ ); write(filename, Str("(", origin_a,",", 1/2*component(projectedOrigin,2)*Scale*sqrt(m),")(", end_a,",", 1/2*component(projectedEnd,2)*Scale*sqrt(m),")" )); if( mode == 2, /* if of 2-torsion stabilizer, label vertices */ verticesToBeLabeled = (edgeStabilizerType[r] == 4); , /* else in the normal mode: */ /* if not of trivial stabilizer, label vertices */ verticesToBeLabeled = (edgeStabilizerType[r] > 2); ); if( verticesToBeLabeled, vertexNumber = setsearch( totalPointSet, edgeOrigin[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); , /* else */ listput( representativePointList, vertexNumber); ); vertexNumber = setsearch( totalPointSet, edgeEnd[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); , /* else */ listput( representativePointList, vertexNumber); ); ); ); ); listsort( endPointList, 1); listsort( representativePointList, 1); /* The flag "1" deletes all but one occurence of each element. */ ); labelVertices(filename, endPointList:list, Scale); labelSpecifiedRepresentativeVertices(filename, representativePointList:list, Scale); write(filename, "} \\end{pspicture} \\end{document}"); }; /* end of output procedure printAxesGraphInPSTricks. */ printGraphInPSTricks( edgeOrigin:list, edgeEnd:list, edgeStabilizerType:list, Scale = 35/sqrt(m), filename = Str("m",m,"colouredGraph.tex") ) = { local( endPointList:list, representativePointList:list, vertexNumber, projectedOrigin, projectedEnd); local( origin_a, end_a); endPointList = listcreate( 2*numberOfEdgeOrbits ); representativePointList = listcreate( 2*numberOfEdgeOrbits ); write( filename, "\\documentclass[oneside,a4paper,11 pt]{article} ", "\\usepackage{pstricks, pstricks-add} \\begin{document} \\pagestyle{empty}"); if( mIs3mod4, write( filename, Str("\\begin{pspicture}(",Scale,",",Scale*sqrt(m)/2,") {") ); , /* else */ write( filename, Str("\\begin{pspicture}(",Scale,",",Scale*sqrt(m),") {") ); ); for (r = 1, length(edgeOrigin), projectedOrigin = component( edgeOrigin[r], 1); projectedEnd = component( edgeEnd[r], 1); if( edgeStabilizerType[r] == 2, write(filename, Str("\\psset{linecolor=black,linestyle = solid} \\psline[]")); ); if( edgeStabilizerType[r] == 4, write(filename, Str("\\psset{linecolor=green,linestyle = dashed} \\psline[]")); ); if( edgeStabilizerType[r] == 6, write(filename, Str("\\psset{linecolor=blue,linestyle = dotted} \\psline[dotsep = 0.1pt]")); ); if(edgeStabilizerType[r] !=2 && edgeStabilizerType[r] !=4 && edgeStabilizerType[r] !=6, print("***Error in output procedure printGraphInPSTricks: edgeStabilizerType[",r,"] = ",edgeStabilizerType[r]); ); if ( mIs3mod4 == 0, /* m not congruent to 3 mod 4 */ write(filename, Str("(",component( projectedOrigin, 1)*Scale, ",", component( projectedOrigin, 2)*Scale*sqrt(m), ")(",component( projectedEnd, 1)*Scale, ",", component( projectedEnd, 2)*Scale*sqrt(m),")" )); if( edgeStabilizerType[r] > 2, /* if not the trivial stabilizer, print vertices */ vertexNumber = setsearch( totalPointSet, edgeOrigin[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); , /* else */ listput( representativePointList, vertexNumber); ); vertexNumber = setsearch( totalPointSet, edgeEnd[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); , /* else */ listput( representativePointList, vertexNumber); ); ); , /* else for m congruent 3 mod 4, a +b*i*sqrt(m) := x +w*y, a:= x -y/2 and b := y/2 */ origin_a = component(projectedOrigin,1)*Scale -1/2*component(projectedOrigin,2)*Scale; if ( abs( frac( origin_a)) < 10^(-20), origin_a = round(origin_a); /* Round an imprecise integer to its "almost" value.*/ ); end_a = component(projectedEnd,1)*Scale -1/2*component(projectedEnd,2)*Scale; if ( abs( frac( end_a)) < 10^(-20), end_a = round(end_a); /* Round an imprecise integer to its "almost" value. */ ); write(filename, Str("(", origin_a,",", 1/2*component(projectedOrigin,2)*Scale*sqrt(m),")(", end_a,",", 1/2*component(projectedEnd,2)*Scale*sqrt(m),")" )); if( edgeStabilizerType[r] > 2, /* if not the trivial stabilizer, print vertices */ vertexNumber = setsearch( totalPointSet, edgeOrigin[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); , /* else */ listput( representativePointList, vertexNumber); ); vertexNumber = setsearch( totalPointSet, edgeEnd[r]); if ( vertexNumber != vertexOrbitRepresentative[ vertexOrbitNumber[ vertexNumber]], listput( endPointList, vertexNumber); , /* else */ listput( representativePointList, vertexNumber); ); ); ); listsort( endPointList, 1); listsort( representativePointList, 1); /* The flag "1" deletes all but one occurence of each element. */ ); labelVertices(filename, endPointList:list, Scale); labelSpecifiedRepresentativeVertices(filename, representativePointList:list, Scale); write(filename, "} \\end{pspicture} \\end{document}"); }; /* end of output procedure printGraphInPSTricks.*/ labelVertices(filename, endPointList:list, Scale = 35/sqrt(m) ) = { local( labelString, point); for (r = 1, length( endPointList), point = component( eval(totalPointSet[endPointList[r]]),1); if ( mIs3mod4 == 0, /* m not congruent to 3 mod 4 */ if( /* real part = */ component( point, 1) > 0, labelString = "\\uput{.2}[0]"; ,/* else */ labelString = "\\uput{.2}[180]"; ); labelString = Str( labelString, "(",component(point,1)*Scale, ",", component(point,2)*Scale*sqrt(m), ")" ); , /* else for m congruent 3 mod 4, a +b*i*sqrt(m) := x +w*y, a:= x -y/2 and b := y/2 */ if( /* real part = */ component( point, 1) -component(point,2)/2 > 0, labelString = "\\uput{.2}[0]"; ,/* else */ labelString = "\\uput{.2}[180]"; ); labelString = Str( labelString, "(",(component(point,1) -component(point,2)/2)*Scale, ",", component(point,2)/2*Scale*sqrt(m), ")" ); ); write(filename, Str( labelString, "{\\small $(", vertexOrbitRepresentative[ vertexOrbitNumber[ endPointList[r]]],")'$}" )); ); }; /* end of output procedure labelVertices. */ labelSpecifiedRepresentativeVertices(filename, representativePointList:list, Scale = 35/sqrt(m) ) = { local( labelString, point); for (r = 1, length(representativePointList), point = component( eval( totalPointSet[ representativePointList[r]]),1); if ( mIs3mod4 == 0, /* m not congruent to 3 mod 4 */ if( /* real part = */ component( point, 1) > 0, labelString = "\\uput{.2}[0]"; ,/* else */ labelString = "\\uput{.2}[180]"; ); labelString = Str( labelString, "(",component(point,1)*Scale, ",", component(point,2)*Scale*sqrt(m), ")" ); , /* else for m congruent 3 mod 4, a +b*i*sqrt(m) := x +w*y, a:= x -y/2 and b := y/2 */ if( /* real part = */ component( point, 1) -component(point,2)/2 > 0, labelString = "\\uput{.2}[0]"; ,/* else */ labelString = "\\uput{.2}[180]"; ); labelString = Str( labelString,"(",(component(point,1) -component(point,2)/2)*Scale, ",", component(point,2)/2*Scale*sqrt(m), ")"); ); write(filename, Str( labelString, "{\\small $(", representativePointList[r],")$}")); ); }; /* end of output procedure labelSpecifiedRepresentativeVertices */ labelVertexRepresentatives(filename, Scale = 35/sqrt(m) ) = { local( labelString, point); for (r = 1, numberOfVertexOrbits, point = component( eval(totalPointSet[vertexOrbitRepresentative[r]]),1); if ( mIs3mod4 == 0, /* m not congruent to 3 mod 4 */ if( /* real part = */ component( point, 1) > 0, labelString = "\\uput{.2}[0]"; ,/* else */ labelString = "\\uput{.2}[180]"; ); labelString = Str( labelString, "(",component(point,1)*Scale, ",", component(point,2)*Scale*sqrt(m), ")" ); , /* else for m congruent 3 mod 4, a +b*i*sqrt(m) := x +w*y, a:= x -y/2 and b := y/2 */ if( /* real part = */ component( point, 1) -component(point,2)/2 > 0, labelString = "\\uput{.2}[0]"; ,/* else */ labelString = "\\uput{.2}[180]"; ); labelString = Str( labelString,"(",(component(point,1) -component(point,2)/2)*Scale, ",", component(point,2)/2*Scale*sqrt(m), ")"); ); write(filename, Str( labelString, "{\\small $(", vertexOrbitRepresentative[r],")$}")); ); }; /* end of output procedure labelVertexRepresentatives */ labelSingularVertices(filename, Scale = 35/sqrt(m) ) = { local( labelString, point); for (r = 1, length( totalPointSet), if( component( eval(totalPointSet[r]),2) == 0, /* singular */ point = component( eval(totalPointSet[r]),1); if ( Mod(m,4) != Mod(3,4), if( /* real part = */ component( point, 1) > 0, labelString = "\\uput{.2}[0]"; ,/* else */ labelString = "\\uput{.2}[180]"; ); labelString = Str( labelString, "(",component(point,1)*Scale, ",", component(point,2)*Scale*sqrt(m), ")" ); , /* else for m congruent 3 mod 4, a +b*i*sqrt(m) := x +w*y, a:= x -y/2 and b := y/2 */ if( /* real part = */ component( point, 1) -component(point,2)/2 > 0, labelString = "\\uput{.2}[0]"; ,/* else */ labelString = "\\uput{.2}[180]"; ); labelString = Str( labelString, "(",(component(point,1) -component(point,2)/2)*Scale, ",", component(point,2)/2*Scale*sqrt(m), ")" ); ); write(filename, Str( labelString, "{\\small $(", point,")'$}" )); ); ); }; writeVertexStabilizers()= { local(cardinal, filename, groups); filename = Str("m=",m,"vertexStabilizers.tex"); write(filename,"% Vertex stabilizers for m = ",m); if (m == 3, write(filename,"Stabilizers not completely calculated because of additional units in the ", "ring of integers of Q(sqrt(-3)).") ); write(filename, "\\scriptsize $$"); groups = loadFiniteSubgroupTable(); for( r = 1, length( totalPointSet), cardinal = length(stabilizer[r]); if (cardinal != 23, cardinal = cardinal /2; ); /* This is the cardinal of the stabilizer group in PSL_2 of the vertex eval(totalPointSet[r]), except for the singular points which have as stabilizer the free abelian group with two generators, and are transcripted here by "cardinal = 23", abusing this notation to abbreviate the code. */ if (groups[cardinal] != "0", write(filename, "\\Gamma_{(",r, ")} = "); writeMatrixList( stabilizer[r], filename); write(filename, "\\cong {",groups[cardinal],"} $$ $$"); ); ); write(filename, "$$ \\normalsize \n",length(totalPointSet)," vertex stabilizers written."); }; /* end of output procedure writeVertexStabilizers() */ writeStabilizersOfOrbits()= { local( filename, groups, cardinal); filename = Str("m=", m, "vertexRepresentativeStabilizer.tex"); write(filename, "% Stabilizers of the vertex orbit representatives."); write(filename, "\\scriptsize"); groups = loadFiniteSubgroupTable(); for( j = 1, numberOfVertexOrbits, write(filename, "$$ \\Gamma_{(",vertexOrbitRepresentative[j], ")} = "); writeMatrixList( stabilizer[ vertexOrbitRepresentative[j]], filename,3); cardinal = length(stabilizer[vertexOrbitRepresentative[j]]); if (cardinal != 23, cardinal = cardinal /2; ); /* This is the cardinal of the stabilizer group in PSL_2 of the vertex eval(totalPointSet[r]), except for the singular points which have as stabilizer the free abelian group with two generators, and are transcripted here by "cardinal = 23", abusing this notation to abbreviate the code. */ write( filename, " \\cong {", groups[cardinal],"} $$"); ); write(filename, "\\normalsize"); }; /* end of output procedure writeStabilizerOrbits */ cleansePointsOfSphere( j, deletePointFlag) = { local( auxiliaryList); auxiliaryList = listcreate( length( pointsOfSphere[j])); for ( k = 1, length( pointsOfSphere[j]), if( deletePointFlag[k] == 0, listput(auxiliaryList, pointsOfSphere[j][k]); ); ); pointsOfSphere[j] = auxiliaryList; listkill( auxiliaryList); }; /* end of procedure cleansePointsOfSphere */ writeEquivariantEulerCharacteristic() = { /* compute the Equivariant Euler Characteristic of this PSL_2(Z[w])-cell complex */ local( stabilizerCardinal, vertexStabilizerCardinalities, filename); local( edgeStabilizerCardinalities, massFormula); vertexStabilizerCardinalities = vector(23); edgeStabilizerCardinalities = vector(3); /* Count the occurencies of the stabilizer types of the vertex orbits. */ for ( j = 1, numberOfVertexOrbits, stabilizerCardinal = length( stabilizer[vertexOrbitRepresentative[j]]); if ( stabilizerCardinal != 23, /* 23 is artificially associated to Z^2 */ stabilizerCardinal = stabilizerCardinal /2; /* PSL_2 */ ); vertexStabilizerCardinalities[stabilizerCardinal]++; ); /* Count the occurencies of the stabilizer types of the edge orbits. */ for ( j = 1, numberOfEdgeOrbits, stabilizerCardinal = length( edgeStabilizer[ edgeOrbitRepresentative[j]]); if ( stabilizerCardinal == 23, /* 23 is artificially associated to Z^2 */ error("Singular edge occured in output procedure writeEquivariantEulerCharacteristic"); ); stabilizerCardinal = stabilizerCardinal /2; /* PSL_2 */ edgeStabilizerCardinalities[stabilizerCardinal]++; ); numberOfTwoCells = 0; /* each 2-cell contributes the value 1 for the trivial stabilizer: */ for ( j = 1, numberOf2cells, if ( deleteCellFlag[j] == 0, /* only kept 2-cells may contribute */ numberOfTwoCells++; ); ); filename = Str("massFormula_m",m,".tex"); write( filename, "("); massFormula = ""; if( vertexStabilizerCardinalities[1] > 0, massFormula = Str( massFormula, vertexStabilizerCardinalities[1]); write( filename, vertexStabilizerCardinalities[1]); ); if( vertexStabilizerCardinalities[2] > 0, massFormula = Str( massFormula," +", vertexStabilizerCardinalities[2],"/2"); write( filename, "+\\frac{",vertexStabilizerCardinalities[2],"}{2}"); ); if( vertexStabilizerCardinalities[3] > 0, massFormula = Str( massFormula," +", vertexStabilizerCardinalities[3],"/3"); write( filename, "+\\frac{",vertexStabilizerCardinalities[3],"}{3}"); ); if( vertexStabilizerCardinalities[4] > 0, massFormula = Str( massFormula," +", vertexStabilizerCardinalities[4],"/4"); write( filename, "+\\frac{",vertexStabilizerCardinalities[4],"}{4}"); ); if( vertexStabilizerCardinalities[6] > 0, massFormula = Str( massFormula," +", vertexStabilizerCardinalities[6],"/6"); write( filename, "+\\frac{",vertexStabilizerCardinalities[6],"}{6}"); ); if( vertexStabilizerCardinalities[12] > 0, massFormula = Str( massFormula," +", vertexStabilizerCardinalities[12],"/12"); write( filename, "+\\frac{",vertexStabilizerCardinalities[12],"}{12}"); ); write( filename, ") -("); if( edgeStabilizerCardinalities[1] > 0, massFormula = Str( massFormula," -", edgeStabilizerCardinalities[1]); write( filename, edgeStabilizerCardinalities[1]); ); if( edgeStabilizerCardinalities[2] > 0, massFormula = Str( massFormula," -", edgeStabilizerCardinalities[2],"/2"); write( filename, "+\\frac{",edgeStabilizerCardinalities[2],"}{2}"); ); if( edgeStabilizerCardinalities[3] > 0, massFormula = Str( massFormula," -", edgeStabilizerCardinalities[3],"/3"); write( filename, "+\\frac{",edgeStabilizerCardinalities[3],"}{3}"); ); massFormula = Str( massFormula," +", numberOfTwoCells); write( filename, ") +", numberOfTwoCells," = ",eval(massFormula),",\n"); write( filename, "m & total & Z^2 & 1 & \\Z/2 & \\Z/3 & {\\cal D}_2 & {\\cal S}_3 & {\\cal A}_4", "& total & 1 & \\Z/2 & \\Z/3 & 2-cells \\\\"); write( filename, m, " & ", numberOfVertexOrbits, " & ", vertexStabilizerCardinalities[23], " & ", vertexStabilizerCardinalities[1], " & ", vertexStabilizerCardinalities[2], " & ", vertexStabilizerCardinalities[3], " & ", vertexStabilizerCardinalities[4], " & ", vertexStabilizerCardinalities[6], " & ", vertexStabilizerCardinalities[12], " & ", numberOfEdgeOrbits, " & ", edgeStabilizerCardinalities[1], " & ", edgeStabilizerCardinalities[2], " & ", edgeStabilizerCardinalities[3], " & ", numberOfTwoCells, "\\\\"); }; /* end of output procedure writeEquivariantEulerCharacteristic */ writeInTexZ2( Mod2homology) = { local( filename); filename = Str("HomolZ2coeffs_m",m,".tex"); write( filename, Str("$$ \\dim \\Homol_q({\\rm PSL}_2(\\ringO_{-",m, "}); \\Z/2) = \\scriptsize \\begin{cases}")); for( j = 3,8, write( filename, Mod2homology[8-j+3],", & q = 6n+",8-j+3,", \\\\ "); ); write( filename, "\\end{cases} $$ \\normalsize"); }; /* end of output procedure writeInTexZ2 */ writeInTexEvenRow( q, Rank) = { local( Output, filename); filename = Str("E2m",m,".tex"); Output = Str("q = ",q," & "); if( Rank != 0, Output = Str( Output, "(\\Z/2)^{",Rank,"}"); ); write( filename, Output, "\\\\"); }; /* end of output procedure writeInTexEvenRow */ writeInTexOddRow( q, cokernelTwoDim, cokernelThreeDim, kernelTwoDim, kernelThreeDim) = { local( Output, filename); filename = Str("E2m",m,".tex"); Output = Str("q = ",q," & "); if( cokernelTwoDim != 0, Output = Str( Output, "(\\Z/2)^{",cokernelTwoDim,"}"); ); if( cokernelThreeDim > 0, if( cokernelThreeDim == 1, Output = Str( Output, " \\oplus \\Z/3"); ,/* else */ Output = Str( Output, " \\oplus (\\Z/3)^",cokernelThreeDim); ); ); Output = concat( Output, " & "); if( kernelTwoDim != 0, Output = Str( Output, "(\\Z/2)^",kernelTwoDim); ); if( kernelThreeDim > 0, if( kernelTwoDim > 0, Output = Str( Output, "\\oplus "); ); if( kernelThreeDim == 1, Output = Str( Output, "\\Z/3"); ,/* else */ Output = Str( Output, "(\\Z/3)^",kernelThreeDim); ); ); write( filename, Output, "\\\\"); }; /* end of output procedure writeInTexOddRow */ writeE2pages() = { local( kernelThreeDim1, kernelThreeDim3, cokernelThreeDim1, cokernelThreeDim3, computedDimensions); local( KleinOccurencies, AlternatingOccurencies); local( TwoRank1, TwoRank3, VertexTwoDim1, VertexTwoDim3); computedDimensions = getKleinFourAndAlternatingGroupOccurencies(); KleinOccurencies = computedDimensions[1]; AlternatingOccurencies = computedDimensions[2]; computedDimensions = getThreePrimaryPart(1); kernelThreeDim1 = computedDimensions[1]; cokernelThreeDim1 = computedDimensions[2]; computedDimensions = getThreePrimaryPart(3); kernelThreeDim3 = computedDimensions[1]; cokernelThreeDim3 = computedDimensions[2]; computedDimensions = getTwoPrimaryPart(1); TwoRank1 = computedDimensions[1]; VertexTwoDim1 = computedDimensions[2]; computedDimensions = getTwoPrimaryPart(3); /* returns [Rank, VertexTwoDim3] */ /* print("For q >= 3 odd, the matrix (d^1_{1,",q,"})_(2) has rank ", Rank, ", a kernel of dimension ",EdgeTwoDim -Rank, " and cokernel dimension ",VertexTwoDim3 -Rank); */ TwoRank3 = computedDimensions[1]; VertexTwoDim3 = computedDimensions[2]; writeInTexmod2E2page( TwoRank1, TwoRank3, VertexTwoDim1, VertexTwoDim3, KleinOccurencies, AlternatingOccurencies); writeInTexE2page( kernelThreeDim1, kernelThreeDim3, cokernelThreeDim1, cokernelThreeDim3, KleinOccurencies, AlternatingOccurencies, TwoRank1, TwoRank3, VertexTwoDim1, VertexTwoDim3); if( classNumber == 1 && m > 3, texResults( kernelThreeDim1, kernelThreeDim3, cokernelThreeDim1, cokernelThreeDim3, KleinOccurencies, AlternatingOccurencies, TwoRank1, TwoRank3, VertexTwoDim1, VertexTwoDim3); ); }; /* end of output procedure writeE2pages */ writeInTexE2page( kernelThreeDim1, kernelThreeDim3, cokernelThreeDim1, cokernelThreeDim3, KleinOccurencies, AlternatingOccurencies, TwoRank1, TwoRank3, VertexTwoDim1, VertexTwoDim3) = { local( kernelTwoDim, cokernelTwoDim, n='n); kernelTwoDim = EdgeTwoDim -TwoRank3; writeInTexEvenRow( 12*n+14, KleinOccurencies*(6*n+7) +AlternatingOccurencies*(2*n+3) ); cokernelTwoDim = VertexTwoDim3 +(6*n+5)*KleinOccurencies +(2*n+1)*AlternatingOccurencies -TwoRank3; writeInTexOddRow(12*n+13, cokernelTwoDim, cokernelThreeDim1, kernelTwoDim, kernelThreeDim1); writeInTexEvenRow( 12*n+12, KleinOccurencies*(6*n+6) +AlternatingOccurencies*(2*n+2) ); cokernelTwoDim = VertexTwoDim3 +(6*n+4)*KleinOccurencies +(2*n+2)*AlternatingOccurencies -TwoRank3; writeInTexOddRow( 12*n+11, cokernelTwoDim, cokernelThreeDim3, kernelTwoDim, kernelThreeDim3); writeInTexEvenRow( 12*n+10, KleinOccurencies*(6*n+5) +AlternatingOccurencies*(2*n+1) ); cokernelTwoDim = VertexTwoDim3 +(6*n+3)*KleinOccurencies +(2*n+1)*AlternatingOccurencies -TwoRank3; writeInTexOddRow(12*n+9, cokernelTwoDim, cokernelThreeDim1, kernelTwoDim, kernelThreeDim1); writeInTexEvenRow(12*n+8, KleinOccurencies*(6*n+4) +(2*n+2)*AlternatingOccurencies); cokernelTwoDim = VertexTwoDim3 +(6*n+2)*KleinOccurencies +(2*n)*AlternatingOccurencies -TwoRank3; writeInTexOddRow(12*n+7, cokernelTwoDim, cokernelThreeDim3, kernelTwoDim, kernelThreeDim3); writeInTexEvenRow( 12*n+6, KleinOccurencies*(6*n+3) +(2*n+1)*AlternatingOccurencies); cokernelTwoDim = VertexTwoDim3 +(6*n+1)*KleinOccurencies +(2*n+1)*AlternatingOccurencies -TwoRank3; writeInTexOddRow(12*n+5, cokernelTwoDim, cokernelThreeDim1, kernelTwoDim, kernelThreeDim1); writeInTexEvenRow( 12*n+4, KleinOccurencies*(6*n+2) +(2*n)*AlternatingOccurencies ); cokernelTwoDim = VertexTwoDim3 +(6*n)*KleinOccurencies +(2*n)*AlternatingOccurencies -TwoRank3; writeInTexOddRow(12*n+3, cokernelTwoDim, cokernelThreeDim3, kernelTwoDim, kernelThreeDim3); }; /* end of output procedure writeInTexE2page */ writeInTexmod2E2page( TwoRank1, TwoRank3, VertexTwoDim1, VertexTwoDim3, KleinOccurencies, AlternatingOccurencies) = { local( kernelTwoDim, cokernelTwoDim, Mod2homology, n='n); Mod2homology = vector(8); kernelTwoDim = EdgeTwoDim -TwoRank3; cokernelTwoDim = VertexTwoDim3 +(6*n+6)*KleinOccurencies +(2*n+2)*AlternatingOccurencies -TwoRank3; Mod2homology[8] = cokernelTwoDim +kernelTwoDim; cokernelTwoDim = VertexTwoDim3 +(6*n+5)*KleinOccurencies +(2*n+1)*AlternatingOccurencies -TwoRank3; Mod2homology[7] = cokernelTwoDim +kernelTwoDim; cokernelTwoDim = VertexTwoDim3 +(6*n+4)*KleinOccurencies +(2*n+2)*AlternatingOccurencies -TwoRank3; Mod2homology[6] = cokernelTwoDim +kernelTwoDim; cokernelTwoDim = VertexTwoDim3 +(6*n+3)*KleinOccurencies +(2*n+1)*AlternatingOccurencies -TwoRank3; Mod2homology[5] = cokernelTwoDim +kernelTwoDim; cokernelTwoDim = VertexTwoDim3 +(6*n+2)*KleinOccurencies +(2*n)*AlternatingOccurencies -TwoRank3; Mod2homology[4] = cokernelTwoDim +kernelTwoDim; cokernelTwoDim = VertexTwoDim3 +(6*n+1)*KleinOccurencies +(2*n+1)*AlternatingOccurencies -TwoRank3; Mod2homology[3] = cokernelTwoDim +kernelTwoDim; cokernelTwoDim = classNumber -1 +VertexTwoDim3 -TwoRank3; kernelTwoDim = EdgeTwoDim -TwoRank1; Mod2homology[2] = cokernelTwoDim +kernelTwoDim; /* Write up dim H_q(Gamma; Z/2) for q greater than or equal 3. */ writeInTexZ2( Mod2homology); }; /* end of output procedure writeInTexmod2E2page */ texResults( kernelThreeDim1, kernelThreeDim3, cokernelThreeDim1, cokernelThreeDim3, KleinOccurencies, AlternatingOccurencies, TwoRank1, TwoRank3, VertexTwoDim1, VertexTwoDim3) = { local( oddKernelTwoDim, cokernelTwoDim, filename, n='n); filename = Str("higherDegreeResults_m",m,".tex"); oddKernelTwoDim = EdgeTwoDim -TwoRank3; if( kernelThreeDim1 == 0, kernelThreeDim1 = "}"; ,/* else */ if( kernelThreeDim1 == 1, kernelThreeDim1 = "} \\oplus \\Z/3"; ,/* else */ kernelThreeDim1 = Str("} \\oplus \\Z/3^", kernelThreeDim1); ); ); if( kernelThreeDim3 == 0, kernelThreeDim3 = "}"; ,/* else */ if( kernelThreeDim3 == 1, kernelThreeDim3 = "} \\oplus \\Z/3"; ,/* else */ kernelThreeDim3 = Str("} \\oplus \\Z/3^", kernelThreeDim3); ); ); if( cokernelThreeDim1 == 0, cokernelThreeDim1 = "}"; ,/* else */ if( cokernelThreeDim1 == 1, cokernelThreeDim1 = "} \\oplus \\Z/3"; ,/* else */ cokernelThreeDim1 = Str("} \\oplus \\Z/3^", cokernelThreeDim1); ); ); if( cokernelThreeDim3 == 0, cokernelThreeDim3 = "}"; ,/* else */ if( cokernelThreeDim3 == 1, cokernelThreeDim3 = "} \\oplus \\Z/3"; ,/* else */ cokernelThreeDim3 = Str("} \\oplus \\Z/3^", cokernelThreeDim3); ); ); write( filename, Str("$$ \\Homol_q({\\rm PSL}_2(\\ringO_{-",m,"}); \\Z) \\cong")); write( filename, "\\begin{cases}"); write( filename, Str("(\\Z/2)^{", KleinOccurencies*(6*n+7) +AlternatingOccurencies*(2*n+3) +oddKernelTwoDim, kernelThreeDim1,", & q = ",12*n+14, ", \\\\")); cokernelTwoDim = VertexTwoDim3 +(6*n+5)*KleinOccurencies +(2*n+1)*AlternatingOccurencies -TwoRank3; write(filename, Str("(\\Z/2)^{",cokernelTwoDim, cokernelThreeDim1, ", & q = ",12*n+13, ", \\\\")); write( filename, Str("(\\Z/2)^{", KleinOccurencies*(6*n+6) +AlternatingOccurencies*(2*n+2) +oddKernelTwoDim, kernelThreeDim3,", & q = ",12*n+12, ", \\\\")); cokernelTwoDim = VertexTwoDim3 +(6*n+4)*KleinOccurencies +(2*n+2)*AlternatingOccurencies -TwoRank3; write(filename, Str("(\\Z/2)^{",cokernelTwoDim, cokernelThreeDim3, ", & q = ",12*n+11, ", \\\\")); write( filename, Str("(\\Z/2)^{", KleinOccurencies*(6*n+5) +AlternatingOccurencies*(2*n+1) +oddKernelTwoDim, kernelThreeDim1,", & q = ",12*n+10, ", \\\\")); cokernelTwoDim = VertexTwoDim3 +(6*n+3)*KleinOccurencies +(2*n+1)*AlternatingOccurencies -TwoRank3; write(filename, Str("(\\Z/2)^{",cokernelTwoDim, cokernelThreeDim1, ", & q = ",12*n+9, ", \\\\")); write( filename, Str("(\\Z/2)^{", KleinOccurencies*(6*n+4) +(2*n+2)*AlternatingOccurencies +oddKernelTwoDim, kernelThreeDim3,", & q = ",12*n+8, ", \\\\")); cokernelTwoDim = VertexTwoDim3 +(6*n+2)*KleinOccurencies +(2*n)*AlternatingOccurencies -TwoRank3; write(filename, Str("(\\Z/2)^{",cokernelTwoDim, cokernelThreeDim3, ", & q = ",12*n+7, ", \\\\")); write( filename, Str("(\\Z/2)^{", KleinOccurencies*(6*n+3) +(2*n+1)*AlternatingOccurencies +oddKernelTwoDim, kernelThreeDim1,", & q = ",12*n+6, ", \\\\")); cokernelTwoDim = VertexTwoDim3 +(6*n+1)*KleinOccurencies +(2*n+1)*AlternatingOccurencies -TwoRank3; write(filename, Str("(\\Z/2)^{",cokernelTwoDim, cokernelThreeDim1, ", & q = ",12*n+5, ", \\\\")); write( filename, Str("(\\Z/2)^{", KleinOccurencies*(6*n+2) +(2*n)*AlternatingOccurencies +oddKernelTwoDim, kernelThreeDim3,", & q = ",12*n+4, ", \\\\")); cokernelTwoDim = VertexTwoDim3 +(6*n)*KleinOccurencies +(2*n)*AlternatingOccurencies -TwoRank3; write(filename, Str("(\\Z/2)^{",cokernelTwoDim, cokernelThreeDim3, ", & q = ",12*n+3, ", \\\\")); write(filename,"\\end{cases} $$"); }; /* end of output procedure texResults */ writeMatrixList( MatrixList: list, filename, Beginning=1) = { /* Writes a list of matrices as a set in LaTeX code. */ local( Entry, PLUS); write( filename, "\\{"); for ( j = Beginning, length( MatrixList), write( filename, "\\left( \\begin{array}{*{2}{c}}"); for( k = 1, 2, for( l = 1, 2, Entry = component(eval( MatrixList[j])[k,l], 1); if ( Entry != 0, write( filename, Entry); PLUS = "+"; ,/* else don't write the "+" sign before the omega part */ PLUS = ""; ); Entry = component( eval(MatrixList[j])[k,l], 2); if ( Entry != 0, if( Entry > 0, if( Entry == 1, write( filename, Str( PLUS, " \\omega")); ,/* else Entry > 0 and not 1 */ write( filename, Str( PLUS, Entry," \\omega")); ); , /* else Entry < 0 */ if( Entry == -1, write( filename, "- \\omega"); ,/* else Entry < 0 and not -1 */ write( filename, Str( Entry," \\omega")); ); ); ); if( l ==1, write( filename, " & ");); ); if( k ==1, write( filename, " \\\\ ");); ); write( filename, "\\end{array} \\right) , "); if( Mod(j,4) == Mod (0,4), write(filename, "$$ $$") ); ); write( filename, "\\}"); }; /* end of output procedure writeMatrixList */ PariToGAPmatrix( PariMatrix) = { local( variableMatrix, GAPstring); variableMatrix = matrix(2,2); for( j = 1, 2, for( k = 1, 2, variableMatrix[j,k] = component( PariMatrix[j,k], 1) +x*component( PariMatrix[j,k], 2); ); ); GAPstring = Str("[[ ",variableMatrix[1,1],", ",variableMatrix[1,2]," ],[ "); GAPstring = Str( GAPstring, variableMatrix[2,1],", ",variableMatrix[2,2],"]]"); /* return */ GAPstring }; /* end of output function PariToGAPmatrix */ WriteHAPvertex( filename, k) = { write( filename, "[rec( TheMatrixStab := Group(["); for( r = 1, length( stabilizer[k]), write( filename, PariToGAPmatrix( stabilizer[k][r])); if( r < length( stabilizer[k]), write( filename, ","); ); ); write( filename, "]),"); write( filename, "TheRotSubgroup := Group(["); for( r = 1, length( stabilizer[k]), write( filename, PariToGAPmatrix( stabilizer[k][r])); if( r < length( stabilizer[k]), write( filename, ","); ); ); write( filename, "]),"); write( filename, "BoundaryImage := rec( ListIFace:=[], ListSign:=[], ListElt:=[])"); write( filename, ")],"); }; /* end of output procedure WriteHAPvertex */ WriteHAPedge( filename, j) = { local( k, SignsFound); k = edgeOrbitRepresentative[j]; write( filename, "[rec( TheMatrixStab := Group(["); for( r = 1, length( edgeStabilizer[k]), write( filename, PariToGAPmatrix( eval(edgeStabilizer[k])[r])); if( r < length( edgeStabilizer[k]), write( filename, ","); ); ); write( filename, "]),"); write( filename, "TheRotSubgroup := Group(["); for( r = 1, length( edgeStabilizer[k]), write( filename, PariToGAPmatrix( eval(edgeStabilizer[k])[r])); if( r < length( edgeStabilizer[k]), write( filename, ","); ); ); write( filename, "]),"); write( filename, "BoundaryImage := rec("); write( filename, Str("ListIFace:=[ ", vertexOrbitNumber[ EdgeOrigin[k]], ", ", vertexOrbitNumber[ EdgeEnd[k]],"],") ); write( filename, " ListSign := ["); SignsFound = 0; for ( r = 1, numberOfVertexOrbits, if( boundaryMatrix[r,j] != 0, write( filename, boundaryMatrix[r,j]); SignsFound++; if( SignsFound == 1, write( filename, ", "); ); ); ); if( SignsFound <> 2, print( "***Error in output procedure WriteHAPedge: Edge number ",j", does not admit origin and end sign."); ); write( filename, " ],"); write( filename, "ListElt := ["); for( r = 1, length( edgeStabilizer[k]), write( filename, PariToGAPmatrix( eval(edgeStabilizer[k])[r])); if( r < length( edgeStabilizer[k]), write( filename, ","); ); ); write( filename,"])"); write( filename, ")],"); }; /* end of output subprocedure WriteHAPedge .*/ WriteHAP2cell( filename, j) = { local(edgesPassed, Sign); write( filename, "[rec( TheMatrixStab := Group([-IdentityMat(2)]),"); write( filename, "TheRotSubgroup := Group([-IdentityMat(2)]),"); write( filename, "BoundaryImage := rec("); write( filename, "ListIFace:=[ "); for( r = 1, length( edgesOf2cell[j]), /* To address the boundary 1-cells, we first pass by the vertices in the list, */ /* by adding numberOfVertexOrbits, and then go to the suitable edgeOrbitNumber. */ write( filename, numberOfVertexOrbits + edgeOrbitNumber[edgesOf2cell[j][r]]); if( r < length( edgesOf2cell[j]), write( filename, ","); ); ); write( filename, "], ListSign := ["); edgesPassed = 0; Sign = recordEdgeOrientations(j); for ( r = 1, length( edgesOf2cell[j]), write( filename, Sign[r]); if( r < length( edgesOf2cell[j]), write( filename, ", "); ); ); write( filename, " ],"); write( filename, "ListElt := [ IdentityMat(2), -IdentityMat(2)]"); write( filename, "))]"); }; /* end of output procedure WriteHAP2cell */ writeHAPdata() = { /* Write the combinatorical information about the quotient of the cell complex, */ /* and the associated stabilizers into a HAP file. */ local( filename); filename = Str("SL_2(O_-",m,").hap"); write( filename, "HAP_GCOMPLEX_LIST := ["); for ( j = 1, numberOfVertexOrbits, WriteHAPvertex( filename, vertexOrbitRepresentative[j]); ); for ( j = 1, numberOfEdgeOrbits, WriteHAPedge( filename, j); ); for ( j = 1, numberOf2cells, WriteHAP2cell( filename, j); if( j < numberOf2cells, write( filename, ", "); ); ); write( filename, "];"); }; /* end of output procedure writeHAPdata */ loadFiniteSubgroupTable() = { local(groups); groups = vector(23); /* Finite subgroup table for PSL_2(O), classified by their order */ groups[1] = "0"; groups[2] = "\\mathbb{Z} /2"; groups[3] = "\\mathbb{Z} /3"; groups[4] = "D_2"; groups[6] = "S_3"; groups[12] = "A_4"; groups[23] = "\\mathbb{Z}^2"; /* this index is artificially attributed to infinity */ /* Return */ groups }; /* end of function loadFiniteSubgroupTable() */ getAssociatedMatrices() = { /* For each hemisphere S_{mu,lambda}, there is an associated element g of PSL_2(Z[w]), */ /* which maps it onto a hemisphere of Floege's extended fundamental domain \hat{G}. */ /* If g maps S_{mu,lambda} onto itself, we divide out this symmetry here. */ local( Fraction, Matrices, k, n ); Matrices = vector( numberOfSpheres); for( j= 1, numberOfSpheres, /* Check the condition that Fraction := (lambda^2 +1)/mu is in the ring of */ /* integers R. By Floege's lemma 10.4, this is equivalent to the existence of */ /* a matrix g which mirrors the 2-cell with respect to a geodesic half-plane */ /* passing through the hemisphere center. In this case, */ /* g = [ lambda, -(lambda^2 +1)/mu; mu, -lambda]. */ Fraction = nfeltdiv(K, nfeltmul(K, Lambda[j], Lambda[j])+[1,0]~, Mu[j]); if( frac( Fraction) == [0,0]~, Matrices[j] = [Lambda[j], -Fraction; Mu[j], -Lambda[j]]; , /* else */ n = -2; k = 1; while( frac( Fraction) <> [0,0]~ && n < 1000, Fraction = nfeltdiv(K, [1,0]~ -nfeltmul(K, Lambda[j], [k,n]~), Mu[j]); k++; if( k > 1000, k = 0; n++); ); Matrices[j] = [-[k,n]~, -Fraction; Mu[j], -Lambda[j]]; ); ); /* return */ Matrices }; /* end of procedure getAssociatedMatrices */