GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
####################################################################### #0 #F ControlledSubdivision ## Input: A pair of positive integers (m,n) ## ## Output: The first n+1 terms of a free ZG-resolution ## where G is SL2Z(1/m) ## InstallGlobalFunction(BaryCentricSubdivision, function(C) local W, StabRec, i, j, N, x, bdry, s1, s2, p, k, w, t, DimRec, BoundaryRec, id, dims, NotRigid, NewCell, AddCell, Cell, Elts, Boundary, Dimension, CLeftCosetElt, pos, IsSameOrbit, Stab, Mult, ConnectToCenter, Stabilizer, Action, IsRigidCell, ReplaceCell, SubdividingCell; Elts:=C!.elts; StabRec:=[]; DimRec:=[]; ################################################################## # If g in Elts return the position of g in the list, # otherwise, add g to Elts and return the position. pos:=function(g) local posit; posit:=Position(Elts,g); if posit=fail then Add(Elts,g); return Length(Elts); else return posit; fi; end; ################################################################## id:=pos(One(C!.group)); ################################################################## # return the stabilizer of g*e, # Stab:=function(e,g) return ConjugateGroup(StabRec[e[1]+1][e[2]],Elts[g]^-1); end; ################################################################## # returns a "canonical" representative of the right coset # Elts[g]*Stab[i+1][j] CLeftCosetElt:=function(i,j,g) return pos(CanonicalRightCountableCosetElement (StabRec[AbsInt(i)+1][j],Elts[g]^-1)^-1); end; ################################################################## ## ## Input: A list L, degree k, position g of an element ## Output: Product of g and L. ## Mult:=function(L,k,g) local x,w,t,h,y,vv; vv:=[]; for x in [1..Length(L)] do w:=Elts[g]*Elts[L[x][2]]; t:=CLeftCosetElt(k,AbsInt(L[x][1]),pos(w)); Add(vv,[L[x][1],t]); od; return vv; end; ################################################################### # Store essential data: stabilizers, boundaries, dimensions i:=0; while C!.dimension(i)>0 do i:=i+1; od; N:=i-1; # Length of the chain complex NewCell:=[]; for i in [1..N] do NewCell[i]:=[]; od; for i in [0..N] do StabRec[i+1]:=[]; DimRec[i+1]:=C!.dimension(i); for j in [1..C!.dimension(i)] do StabRec[i+1][j]:=C!.stabilizer(i,j); od; od; BoundaryRec:=[]; for i in [1..N] do BoundaryRec[i]:=[]; for j in [1..DimRec[i+1]] do bdry:=C!.boundary(i,j); BoundaryRec[i][j]:=[]; for x in bdry do s1:=C!.action(i-1,AbsInt(x[1]),x[2]); p:=pos(CanonicalRightCountableCosetElement (C!.stabilizer(i-1,AbsInt(x[1])),Elts[x[2]]^-1)^-1); s2:=C!.action(i-1,AbsInt(x[1]),p); Add(BoundaryRec[i][j],[s1*s2*x[1],p]); od; # BoundaryRec[i][j]:=ShallowCopy(C!.boundary(i,j)); od; od; ################################################################## # Data type for a k-cell with stabilizer stab and boundary bdry Cell:=function(k,stab,bdry) return rec( dimension:=k, stabilizer:=stab, boundary:=bdry ); end; ################################################################## # Add a k-cell with stabilizer stab and boundary bdry # to the cell complex AddCell:=function(k,stab,bdry) local i,g; if k=0 then DimRec[k+1]:=DimRec[k+1]+1; Add(StabRec[k+1],stab); return [DimRec[k+1],CLeftCosetElt(0,DimRec[k+1],id)]; fi; for i in [(dims[k+1]+1)..DimRec[k+1]] do g:=IsSameOrbit([k,StabRec[k+1][i], BoundaryRec[k][i]],[k,stab,bdry]); if not g=false then #Print("the cell ",[i, CLeftCosetElt(k,i,g)],"\n"); return [i, CLeftCosetElt(k,i,g)]; fi; od; DimRec[k+1]:=DimRec[k+1]+1; Add(StabRec[k+1],stab); Add(BoundaryRec[k],bdry); return [DimRec[k+1],CLeftCosetElt(k,DimRec[k+1],id)]; end; ################################################################## # check if two k-cells are in the same orbit IsSameOrbit:=function(e,f) local p, bdry1, bdry2, i, a, b, x; if not e[1]=f[1] then return false; fi; bdry1:=ShallowCopy(e[3]); bdry2:=ShallowCopy(f[3]); bdry2:=List(bdry2,w->[w[1],CLeftCosetElt(e[1]-1,AbsInt(w[1]),w[2])]); #Print("bdry1 ",bdry1,"\n"); #Print("bdry2 ",bdry2,"\n"); p:=PositionsProperty(bdry2,w->AbsInt(w[1])=AbsInt(bdry1[1][1])); #Print("p ",p,"\n"); for i in p do for a in Elements(StabRec[e[1]][AbsInt(bdry1[1][1])]) do b:=Elts[bdry2[i][2]]*a*Elts[bdry1[1][2]]^-1; x:=List(bdry1,w->[w[1],CLeftCosetElt(e[1]-1, AbsInt(w[1]),pos(b*Elts[w[2]]))]); if Set(x)=Set(bdry2) then #Print("b ",pos(b),"\n"); return pos(b); fi; od; od; return false; end; ################################################################## # Connect the cell e to the barycenter of the cell f # e and f are in the form [k,i,g]: dimension k, obtain by sending # ith-representative under the action of the element g in G ConnectToCenter:=function(e,f) local bdry, x, stab, bdrye, w, stablst; if e[1]=0 then stab:=Intersection(Stab([e[1],e[2]],e[3]),Stab([f[1],f[2]],f[3])); bdry:=[[-f[2],f[3]],[e[2],e[3]]]; #Print(e," ",AddCell(e[1]+1,stab,bdry),"\n"); return AddCell(1,stab,bdry); fi; stablst:=[]; Add(stablst,Stab([e[1],e[2]],e[3])); # stab:=Intersection(Stab([e[1],e[2]],e[3]),Stab([f[1],f[2]],f[3])); bdry:=[]; Add(bdry,[e[2],e[3]]); bdrye:=Mult(BoundaryRec[e[1]][e[2]],e[1]-1,e[3]); for x in bdrye do w:=ConnectToCenter([e[1]-1,AbsInt(x[1]),x[2]],f); Add(bdry,[-SignInt(x[1])*w[1],w[2]]); Add(stablst,Stab([e[1],w[1]],w[2])); od; stab:=Intersection(stablst); #Print(e," ",AddCell(e[1]+1,stab,bdry),"\n"); return AddCell(e[1]+1,stab,bdry); end; ################################################################## # Check if the cell is whether rigid or not IsRigidCell:=function(k,m) local bdry, intst, L; bdry:=BoundaryRec[k][m]; L:=List(bdry,w->Elements(ConjugateGroup(StabRec[k][AbsInt(w[1])],Elts[w[2]]^-1))); intst:=Intersection(L); if not Elements(StabRec[k+1][m])=Elements(intst) then return false; else return true; fi; end; ################################################################## # Subdividing a cell SubdividingCell:=function(k,i) local bdry, w, x, d, y; y:=AddCell(0,StabRec[k+1][i],[]); bdry:=BoundaryRec[k][i]; w:=[]; #Print([k,i]," ",bdry,"\n"); for x in bdry do d:=ConnectToCenter([k-1,AbsInt(x[1]),x[2]],[0,y[1],y[2]]); if x[1]<0 then Add(w,[-d[1],d[2]]); else Add(w,d); fi; od; return w; end; ################################################################## # Replacing a cell by its subdivision ReplaceCell:=function(k,m) local i, j, p, w, x, bdry, y, ww; w:=ShallowCopy(SubdividingCell(k,m)); if k<N then for i in [1..DimRec[k+2]] do bdry:=ShallowCopy(BoundaryRec[k+1][i]); p:=PositionsProperty(bdry,w->AbsInt(w[1])=m); for j in p do x:=bdry[j]; ww:=ShallowCopy(w); if x[1]<0 then ww:=NegateWord(ww);fi; ww:=Mult(ww,k,x[2]); Append(bdry,ww); od; y:=bdry{p}; bdry:=Set(bdry); SubtractSet(bdry,y); BoundaryRec[k+1][i]:=bdry; od; fi; BoundaryRec[k][m]:="del"; StabRec[k+1][m]:="del"; end; ################################################################## # Main part: subdividing the fundamental domain NotRigid:=[]; dims:=ShallowCopy(DimRec); i:=1; # Print("The cells which are not rigid: \n"); while i<=N do j:=1; while j<=dims[i+1] do # if not IsRigidCell(i,j) then # Print([i,j]); Add(NotRigid,[i,j]); # fi; j:=j+1; od; i:=i+1; od; for x in NotRigid do # Print("\n The cell ",x," is in process of subdividing \n"); ReplaceCell(x[1],x[2]); od; #Delete cells which are already replaced by its subdivision # Print("Deleting cells which are already replaced by its subdivision... \n"); t:=1; for w in [1..Length(NotRigid)] do k:=NotRigid[w][1]; j:=NotRigid[w][2]; if k<N then for i in [1..DimRec[k+2]] do bdry:=BoundaryRec[k+1][i]; if not IsString(bdry) then for x in bdry do if AbsInt(x[1])>j then x[1]:=x[1]-SignInt(x[1]); fi; od; fi; BoundaryRec[k+1][i]:=bdry; od; fi; dims[k+1]:=dims[k+1]-1; DimRec[k+1]:=DimRec[k+1]-1; Remove(BoundaryRec[k],j); Remove(StabRec[k+1],j); if IsBound(NotRigid[w+1]) and NotRigid[w+1][1]=NotRigid[w][1] then NotRigid[w+1][2]:=NotRigid[w+1][2]-t; t:=t+1; else t:=1; fi; od; # Print("Done!","\n"); ################################################################## Boundary:=function(k,m) return BoundaryRec[k][m]; end; Stabilizer:=function(k,m) return StabRec[k+1][m]; end; Dimension:=function(k) if k>N then return 0;fi; return DimRec[k+1]; end; Action:=function(k,i,j) return 1; end; ################################################################## return Objectify(HapNonFreeResolution, rec( dimension:=Dimension, boundary:=Boundary, homotopy:=fail, elts:=Elts, group:=C!.group, stabilizer:=Stabilizer, action:=Action, subdividing:=SubdividingCell, replacecell:=ReplaceCell, issameorbit:=IsSameOrbit, isrigid:=IsRigidCell, properties:= [["length",Maximum(1000,N)], ["characteristic",0], ["type","resolution"]] )); end); ################### end of ControlledSubdivision ############################