GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#(C) This function was written by Bui Anh Tuan
################################################
################################################
InstallGlobalFunction(ContractibleSL2ZComplex,
function()
local
C,
G, StabilizerGroups, Stabilizer,
lnth,
dims,Dimension,
Boundary,
boundaryList,
Elts,
Rot,Stab,
RotSubGroups,Action, ActionRecord,
TransMat,
St0,St1, x, n,k,s,BI,SGN,tmp, LstEl ,
bool, name,
GeneratorsRepresentation,SimplifyGeneratorsRepresentation,EdgeFinder,
pos,AddList,Chomotopy,Path2Gindex,FinalHomotopy,Homotopy,Sign,
EdgeFinder1,RefineEdge,Edge;
bool:=ReadPackage("HAP","lib/Perturbations/Gcomplexes/SL2Z");
if bool = false then
Print("Complex failed to load.\n");
return fail;
fi;
if HAP_GCOMPLEX_SETUP[1] then
TransMat:=function(x); return x^-1; end;
else
TransMat:=function(x); return x; end;
fi;
C:=StructuralCopy(HAP_GCOMPLEX_LIST);
lnth:=Length(C)-1;
dims:=List([1..lnth+1],n->Length(C[n]));
###################
Dimension:=function(n);
if n>lnth then return 0; fi;
return dims[n+1];
end;
###################
Elts:=[[[1,0],[0,1]]];
StabilizerGroups:=[];
RotSubGroups:=[];
boundaryList:=[];
#######
for n in [1..lnth+1] do
boundaryList[n]:=[];
StabilizerGroups[n]:=[];
RotSubGroups[n]:=[];
for k in [1..Dimension(n-1)] do
Append(Elts,Elements(C[n][k].TheMatrixStab));
Add(StabilizerGroups[n],C[n][k].TheMatrixStab);
Add(RotSubGroups[n],C[n][k].TheRotSubgroup);
od;
od;
####
Elts:=SSortedList(Elts);
#######
for n in [1..lnth+1] do
boundaryList[n]:=[];
for k in [1..Dimension(n-1)] do
tmp:=C[n][k].BoundaryImage;
BI:=tmp.ListIFace;
SGN:=tmp.ListSign;
LstEl:=List(tmp.ListElt,w->TransMat(w));
Append(Elts,Difference(LstEl,Elts));
for s in [1..Length(BI)] do
BI[s]:=[SGN[s]*BI[s],Position(Elts,LstEl[s])];
od;
Add(boundaryList[n],BI);
od;
od;
####
ActionRecord:=[];
for n in [1..lnth+1] do
ActionRecord[n]:=[];
for k in [1..Dimension(n-1)] do
ActionRecord[n][k]:=[];
od;
od;
G:=Group(Elts);
St0:=StabilizerGroups[1][1];
St1:=StabilizerGroups[2][1];
####################
Boundary:=function(n,k)
local b;
if k>0 then
b:=boundaryList[n+1][k];
#Print("b",b,"\n\n");
Apply(b,x->[x[1], pos(CanonicalRightCosetElement(St0,Elts[x[2]]^-1)^-1)] );
#Print("b1",b,"\n\n");
return b;
#return boundaryList[n+1][k];
else
b:=boundaryList[n+1][-k];
Apply(b,x->[x[1], pos(CanonicalRightCosetElement(St0,Elts[x[2]]^-1)^-1)] );
return NegateWord(b);
#return NegateWord(boundaryList[n+1][-k]);
fi;
end;
####################
####################
Stabilizer:=function(n,k);
return StabilizerGroups[n+1][k];
end;
####################
####################
Action:=function(n,k,g)
local id,r,u,H,abk,ans;
abk:=AbsInt(k);
if not IsBound(ActionRecord[n+1][abk][g]) then
H:=StabilizerGroups[n+1][abk];
if Order(H)=infinity then ActionRecord[n+1][abk][g]:=1;
#So we are assuming that any infinite stabilizer group acts trivially!!
else
######
id:=CanonicalRightCosetElement(H,Identity(H));
r:=CanonicalRightCosetElement(H,Elts[g]^-1);
r:=id^-1*r;
u:=r*Elts[g];
if u in RotSubGroups[n+1][abk] then ans:= 1;
else ans:= -1; fi;
ActionRecord[n+1][abk][g]:=ans;
fi;
######
fi;
return ActionRecord[n+1][abk][g];
end;
####################SL2Z-homotopy########################################
GeneratorsRepresentation:=function(g)
local
S,T,
q,i,j,
index;
#g:=CanonicalRightCosetElement(St0,g^-1)^-1;
if Determinant(g)<>1 then return "input is not in SL(2,Z)";
else
S:=[[0,-1],[1,0]];
T:=[[1,1],[0,1]];
i:=0;
index:=[];
while g[2][1]<>0 do
if g[1][1]*g[2][1]<0 and IsInt(g[1][1]/g[2][1])=false then
q:=Int(g[1][1]/g[2][1])-1;
else q:=Int(g[1][1]/g[2][1]);
fi;
i:=i+1;
index[i]:=q;
i:=i+1;
index[i]:=1;
g:=S*((T^(-q))*g);
od;
if g[1][1]=1 then
i:=i+1;
index[i]:=g[1][2];
fi;
if g[1][1]=-1 then
i:=i+1;
index[i]:=-g[1][2];
fi;
fi;
return index;
end;
############
SimplifyGeneratorsRepresentation:=function(index)
local
i,j,k,p,
temp,
S,T,Y;
p:=0;
S:=[[0,-1],[1,0]];
T:=[[1,1],[0,1]];
Y:=[[0,-1],[1,1]];
temp:=[[1,0],[0,1]];
i:=Length(index);
while i>0 do
if i mod 2 =1 then
temp:=T^(index[i])*temp;
else temp:=S*temp;
fi;
for j in [1..6] do
if temp=Y^j then
if index[Length(index)]=0 then p:=1;fi;
for k in [i..Length(index)] do
Remove(index);
od;
if p=1 then Add(index,0);fi;
fi;
od;
i:=i-1;
od;
if index=[0] then return [];fi;
return index;
end;
#############
EdgeFinder:=function(index)
local
edge,S,T,
id,m,
sign;
if index=[] then return []; fi;
S:=[[0,-1],[1,0]];
T:=[[1,1],[0,1]];
id:=[[1,0],[0,1]];
if index=[1] then return id;
fi;
if index=[0] then return id;
fi;
if index=[-1] then return T^-1;
fi;
if index[1]=0 then Remove(index,1);fi;
if (Length(index) mod 2)=1 then
sign:=index[1];
index[1]:=index[1]-SignInt(index[1]);
edge:=T^SignInt(sign)*EdgeFinder(index);
else
Remove(index,1);
edge:=S*EdgeFinder(index);
fi;
return edge;
end;
###################
Edge:=function(g)
g:=CanonicalRightCosetElement(StabilizerGroups[1][1],g^-1)^-1;
return EdgeFinder(g);
end;
##################
RefineEdge:=function(g)
local S;
S:=[[0,-1],[1,0]];
if g=[] then return [];fi;
if g[1][1]<=0 then
g:=g*S^2;
if g[1][1]<g[1][2] then
g:=g*S;
fi;
fi;
return g;
end;
#################
AddList:=function(g,h)
Add(g,h);
return g;
end;
#################
Chomotopy:=function(g)
local
index,n,i,
Y,S,T,d,h,
path,edge,K;
if g=[] then return [];fi;
S:=[[0,-1],[1,0]];
T:=[[1,1],[0,1]];
Y:=[[0,-1],[1,1]];
path:=[];
for i in [1..6] do
if g=Y^i then return [];
fi;
od;
K:=Group(Y);
g:=CanonicalRightCosetElement(K,g^-1)^-1;
d:=SimplifyGeneratorsRepresentation(GeneratorsRepresentation(g));
#edge:=RefineEdge(EdgeFinder(d));
edge:=EdgeFinder(d);
edge:=CanonicalRightCosetElement(St1,edge^-1)^-1;
h:=[Sign(g,edge),edge];
return AddList(Chomotopy(edge*S*edge^-1*g),h);
end;
#################
pos:=function(g)
if Position(Elts,g)=fail then
Add(Elts,g);
fi;
return Position(Elts,g);
end;
##################
Path2Gindex:=function(path)
local g,i;
g:=[];
for i in [1..Length(path)] do
Add(g,[path[i][1],pos(path[i][2])]);
#Add(g,[1,pos(CanonicalRightCosetElement(St1,path[i]^-1)^-1)]);
#Add(g,[1,pos(path[i])]);
od;
#if Sign(g)=1 then return g;
#else
# return NegateWord(g);
#fi;
return g;
end;
##################
#Sign:=function(index)
#local g;
#if index=[] then return 1;
#else
#g:=Elts[index[1][2]];
#if g=CanonicalRightCosetElement(St1,[[1,0],[0,1]]^-1)^-1 then return -1;fi;
#if g=CanonicalRightCosetElement(St1,[[1,1],[0,1]])^-1 then return 1;fi;
#if g=CanonicalRightCosetElement(St1,[[0,-1],[1,1]]^-1)^-1 then return -1;fi;
#fi;
#end;
##################
Sign:=function(g,h)
if g^-1*h in St0 then return 1;
else return -1;fi;
end;
##################
FinalHomotopy:=function(n,p)
local
k,g;
if n<>0 then return [];
else
if IsList(p[1]) then return Path2Gindex(Chomotopy(p));
else
k:=p[1];
if AbsInt(k)<>1 then return "Number of Generators is 1";
else
g:=p[2];
if Elts[g]=[] then return [];fi;
if k>0 then return Path2Gindex(Chomotopy(Elts[g]));
else
return NegateWord(Path2Gindex(Chomotopy(Elts[g])));
fi;
fi;
fi;
fi;
end;
####################END: SL2Z-homotopy###################################
Homotopy:=function(n,g)
if name="SL2Z" then return FinalHomotopy(n,g);
else
return fail;
fi;
end;
#########################################################################
G:=SL(2,Integers);
return Objectify(HapNonFreeResolution,
rec(
dimension:=Dimension,
boundary:=Boundary,
homotopy:=FinalHomotopy,
elts:=Elts,
group:=G,
stabilizer:=Stabilizer,
action:=Action,
edge:=Edge,
gens:=GeneratorsRepresentation,
properties:=
[["length",Maximum(1000,lnth)],
["characteristic",0],
["type","resolution"],
["reduced",true]] ));
end);
################################################
################################################