GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#(C)2009 Graham Ellis
#########################################################
InstallGlobalFunction(HAPTietzeReduction_OneStep,
function(R,N,bound)
local
CR,
Dimension,
Boundary,
Homotopy,
PseudoBoundary,
PseudoBoundaryN,
PseudoBoundaryNplus2,
FindFreeFace,
Action, ActionInv, Elts,
modN, modNplus1,
triple,
tmp,
newb,bool,i,j,b,e,g,x,w,D,D2;;
Elts:=R!.elts;
modN:=[];
modNplus1:=[];
PseudoBoundary:=List([1..R!.dimension(N+1)],i->
StructuralCopy(R!.boundary(N+1,i)));
PseudoBoundaryN:=List([1..R!.dimension(N)],i->
StructuralCopy(R!.boundary(N,i)));
if Length(R)>N+1 then
PseudoBoundaryNplus2:=List([1..R!.dimension(N+2)],i->
StructuralCopy(R!.boundary(N+2,i)));
fi;
###################################################################################
#####################################################################
Action:=function(g,l)
local pos, h;
h:=Elts[g]*Elts[l[2]];
pos:=Position(Elts,h);
if pos=fail then
Add(Elts, h);
pos:=Length(Elts);
fi;
return [l[1],pos];
end;
#####################################################################
#####################################################################
ActionInv:=function(g,l)
local pos, h;
h:=Elts[g]^-1*Elts[l[2]];
pos:=Position(Elts,h);
if pos=fail then
Add(Elts, h);
pos:=Length(Elts);
fi;
return [l[1],pos];
end;
#####################################################################
########################################################
FindFreeFace:=function()
local i,b,pos,y, wrd,e, g;
#returns either fail, or a triple [e,wrd,i] such that we can
#replace all g multiples of the generating cell [e,1] with g multiples
#of the word wrd in boundaries of N+1-dimensional cells, and delete the
#i-th free cell in dimension N+1;.
for i in [1..Length(PseudoBoundary)] do
b:=List(PseudoBoundary[i],x->AbsInt(x[1]));
b:=Collected(b);
pos:=PositionProperty(b,x->x[2]=1);
if IsInt(pos) and Length(b)<=bound then
y:=b[pos][1];
b:=StructuralCopy(PseudoBoundary[i]);
pos:=PositionProperty(b,x->AbsInt(x[1]) =y);
wrd:=b{Concatenation([1..pos-1],[pos+1..Length(b)])};
g:=b[pos][2];
if b[pos][1]>0 then
wrd:=NegateWord(wrd);
e:=b[pos][1];
else e:=-b[pos][1];
fi;
wrd:=List(wrd,x->ActionInv(g,x));
return [e,wrd,i,g];
fi;
od;
return fail;
end;
########################################################
####################
####################
while true do
triple:=FindFreeFace();
if triple=fail or Length(modN)>0
then break; fi;
e:=triple[1];
Add(modNplus1,triple[3]);
Add(modN,e);
###############
for j in [1..Length(PseudoBoundary)] do
b:=PseudoBoundary[j];
newb:=[];
for i in [1..Length(b)] do
if not AbsInt(b[i][1])=e then
Add(newb,StructuralCopy(b[i]));
else
w:=StructuralCopy(triple[2]);
if b[i][1]<0 then
w:=NegateWord(w);
fi;
w:=List(w,x->Action(b[i][2],x));
Append(newb,w);
fi;
od;
PseudoBoundary[j]:=AlgebraicReduction(newb);
od;
######################
od;
##############################
##############################
modN:=Difference([1..R!.dimension(N)],modN);
modNplus1:=Difference([1..R!.dimension(N+1)],modNplus1);
PseudoBoundary:=PseudoBoundary{modNplus1};
#####################################
for b in PseudoBoundary do
for x in b do
x[1]:=SignInt(x[1])*Position(modN,AbsInt(x[1]));
od;od;
#####################################
PseudoBoundaryN:=PseudoBoundaryN{modN};
#####################################
if Length(R)>N+1 then
for j in [1..Length(PseudoBoundaryNplus2)] do
b:=PseudoBoundaryNplus2[j];
newb:=[];
for x in b do
if AbsInt(x[1]) in modNplus1 then
Add(newb,[SignInt(x[1])*Position(modNplus1,AbsInt(x[1])),x[2]]);
fi;
od;
PseudoBoundaryNplus2[j]:=newb;
od;
fi;
#####################################
####################################################
Dimension:=function(i);
if not i in [N,N+1] then return R!.dimension(i); fi;
if i=N then return Length(PseudoBoundaryN); fi;
return Length(PseudoBoundary);
end;
####################################################
####################################################
Boundary:=function(n,i);
if not n in [N,N+1,N+2] then return R!.boundary(n,i); fi;
if i>0 then
if n=N then return PseudoBoundaryN[i]; fi;
if n=N+1 then return PseudoBoundary[i]; fi;
if n=N+2 then return PseudoBoundaryNplus2[i]; fi;
fi;
if i<0 then
if n=N then return NegateWord(PseudoBoundaryN[AbsInt(i)]); fi;
if n=N+1 then return NegateWord(PseudoBoundary[AbsInt(i)]); fi;
if n=N+2 then return NegateWord(PseudoBoundaryNplus2[AbsInt(i)]); fi;
fi;
end;
####################################################
CR:=Objectify(HapResolution,
rec(
dimension:=Dimension,
boundary:=Boundary,
homotopy:=fail,
elts:=R!.elts,
group:=R!.group,
properties:=
[["length",EvaluateProperty(R,"length")],
["reduced",EvaluateProperty(R,"reduced")],
["type","resolution"],
["characteristic",EvaluateProperty(R,"characteristic")] ]));
return CR;
end);
#########################################################
#########################################################
InstallGlobalFunction(HAPTietzeReduction_OneLevel,
function(R,i,bound)
local T, s;
s:=R!.dimension(i);
T:=HAPTietzeReduction_OneStep(R,i,bound);
while s>T!.dimension(i) do
s:=T!.dimension(i);
T:=HAPTietzeReduction_OneStep(T,i,bound);
od;
return T;
end);
#########################################################
#########################################################
InstallGlobalFunction(HAPTietzeReduction_Inf,
function(arg)
local R,bound, T, s;
R:=arg[1];
if Length(arg)=2 then bound:=arg[2]; else bound:=infinity; fi;
T:=R;
for s in Reversed([0..Length(R)-1]) do
T:=HAPTietzeReduction_OneLevel(T,s,bound);
od;
return T;
end);
#########################################################