GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#(C) Graham Ellis, 2005-2006 ##################################################################### InstallGlobalFunction(ResolutionGraphOfGroups, function(arg) local D,N,L, PositionName, Vertices, Edges, EdgeGroups, ColouredVertices, ComplementaryEdges, resVertices, resEdges, resEdgeGroups, FpHoms, F,Frels,PhomF, FundGroup, inc, Dimension, Elts, PseudoBoundary, FillPseudoBoundary, Boundary, hom, quohom, pos,e,f,g,x,P,R,S,T; ####################################READ INPUT DATA################## D:=arg[1]; N:=arg[2]; if Length(arg)>2 then L:=arg[3]; else L:=[]; fi; ########################################DATA READ#################### if not GraphOfGroupsTest(D) then Print("The list D does not represent a Graph of Groups \n"); return fail; fi; ##################################################################### PositionName:=function(L,x); return PositionProperty(L,n->Name(n)=Name(x)); end; ##################################################################### ###########EXTRACT VERTICES ABD EDGES OF GRAPH OF GROUPS ############ Vertices:=[]; Edges:=[]; for x in D do if IsGroup(x) then Append(Vertices,[x]); fi; if IsList(x) then Append(Edges,[x]); fi; od; EdgeGroups:=List(Edges,e->Source(e[1])); ##########EXTRACTED################################################## ####################FIND MAXIMAL TREE IN GRAPH OF GROUPS############# ColouredVertices:=[]; ComplementaryEdges:=[]; for e in Edges do if Name(Range(e[1])) in ColouredVertices and Name(Range(e[2])) in ColouredVertices or Name(Range(e[1]))=Name(Range(e[2])) then Append(ComplementaryEdges,[[Name(Range(e[1])),Name(Range(e[2]))]]); fi; Append(ColouredVertices,[Name(Range(e[1])),Name(Range(e[2]))]); od; #########################TREE FOUND################################## ##########CREATE GRAPH OF RESOLUTIONS################################ resVertices:=[]; for x in Vertices do pos:=Position(List(L,r->r!.group),x); if pos=fail then #R:=ResolutionFiniteGroup(x,N); R:=ResolutionGenericGroup(x,N); else R:=L[pos]; fi; SetName(R!.group,Name(x)); Append(resVertices,[R]); od; resEdgeGroups:=[]; for x in EdgeGroups do pos:=Position(List(L,r->r!.group),x); if pos=fail then #R:= ResolutionFiniteGroup(x,N-1); R:= ResolutionGenericGroup(x,N-1); else R:=L[pos]; fi; SetName(R!.group,Name(x)); Append(resEdgeGroups,[R]); od; resEdges:=[]; for x in Edges do R:=resVertices[PositionName(Vertices,Range(x[1]))]; S:=resEdgeGroups[PositionName(EdgeGroups,Source(x[1]))]; T:=resVertices[PositionName(Vertices,Range(x[2]))]; e:=[EquivariantChainMap(S,R,x[1]),EquivariantChainMap(S,T,x[2])]; Append(resEdges,[e]); od; ##########CREATED#################################################### ##########CREATE HOMOMORPHISM TO FP GROUP############################ F:=FreeGroup(Length(ComplementaryEdges)+ Sum(List(resVertices,R->R!.dimension(1)))); FpHoms:=[]; Frels:=[]; x:=0; for R in resVertices do P:=PresentationOfResolution(R); PhomF:=GroupHomomorphismByImagesNC(P.freeGroup,F, GeneratorsOfGroup(P.freeGroup), GeneratorsOfGroup(F){[x+1..x+R!.dimension(1)]}); Append(Frels, List(P.relators,r->Image(PhomF,r))); Append(FpHoms, [GroupHomomorphismByImagesNC(R!.group,F, List([1..R!.dimension(1)],i->R!.elts[R!.boundary(1,i)[1][2]]), GeneratorsOfGroup(F){[x+1..x+R!.dimension(1)]} )]); x:=x+R!.dimension(1); od; pos:=Sum(List(resVertices,R->R!.dimension(1))); for e in Edges do if not [Name(Range(e[1])),Name(Range(e[2]))] in ComplementaryEdges and not [Name(Range(e[2])),Name(Range(e[1]))] in ComplementaryEdges then for x in GeneratorsOfGroup(Source(e[1])) do Append(Frels,[ Image(FpHoms[PositionName(Vertices,Range(e[1]))], Image(e[1],x))* Image(FpHoms[PositionName(Vertices,Range(e[2]))], Image(e[2],x))^-1 ]); od; else pos:=pos+1; for x in GeneratorsOfGroup(Source(e[1])) do Append(Frels,[ Image(FpHoms[PositionName(Vertices,Range(e[1]))], Image(e[1],x))*GeneratorsOfGroup(F)[pos]* Image(FpHoms[PositionName(Vertices,Range(e[2]))], Image(e[2],x))^-1*GeneratorsOfGroup(F)[pos]^-1 ]); od; fi; od; FundGroup:=F/Frels; ###Added Aug 2013 quohom:= GroupHomomorphismByImages(F,FundGroup, ### GeneratorsOfGroup(F), ### GeneratorsOfGroup(FundGroup)); ### FundGroup:=F; ### x:=0; FpHoms:=[]; Elts:=[]; for R in resVertices do P:=PresentationOfResolution(R); Append(FpHoms, [GroupHomomorphismByImagesNC(R!.group,FundGroup, List([1..R!.dimension(1)],i->R!.elts[R!.boundary(1,i)[1][2]]), GeneratorsOfGroup(FundGroup){[x+1..x+R!.dimension(1)]} )]); Append(Elts,Image(FpHoms[Length(FpHoms)],R!.elts)); x:=x+R!.dimension(1); od; ##########DREATED#################################################### ##################################################################### Dimension:=function(k) local dim,R; if k<0 then return 0; fi; dim:=0; for R in resVertices do dim:=dim+R!.dimension(k); od; for R in resEdgeGroups do dim:=dim+R!.dimension(k-1); od; return dim; end; ##################################################################### ##################################################################### inc:=function(x,n) #x is the vertex or edge group/resolution and local pos,i,increment; #n is the dimension in the TOTAL resolution increment:=0; pos:=PositionName(Vertices,x); if not pos=fail then for i in [1..pos-1] do increment:=increment + resVertices[i]!.dimension(n); od; return increment; else for i in [1..Length(resVertices)] do increment:=increment + resVertices[i]!.dimension(n); od; pos:=PositionName(EdgeGroups,x); for i in [1..pos-1] do increment:=increment + resEdgeGroups[i]!.dimension(n-1); od; return increment; fi; end; ##################################################################### PseudoBoundary:=[]; ##################################################################### FillPseudoBoundary:=function() local b,f,g,i,k,x,hom,hom1,hom2,R,dim,dim1,dim2,bnd; for k in [1..N] do PseudoBoundary[k]:=[]; for R in resVertices do x:=PositionName(List(FpHoms,f->Source(f)),R!.group); hom:=FpHoms[x]; dim:=inc(R!.group,k-1); for i in [1..R!.dimension(k)] do Append(PseudoBoundary[k],[ List(R!.boundary(k,i),a-> [ SignInt(a[1])*(AbsoluteValue(a[1])+dim), Position(Elts,Image(hom,R!.elts[a[2]])) ])]); od; od; ####################### for e in Edges do hom:=e[1]; x:=PositionName(EdgeGroups,Source(e[1])); R:=Source(resEdges[x][1]); dim:=inc(R!.group,k-1); S:=Target(resEdges[x][1]); T:=Target(resEdges[x][2]); f:=resEdges[x][1]; g:=resEdges[x][2]; dim1:=inc(S!.group,k-1); x:=PositionName(List(FpHoms,f->Source(f)),S!.group); hom1:=FpHoms[x]; dim2:=inc(T!.group,k-1); x:=PositionName(List(FpHoms,f->Source(f)),T!.group); hom2:=FpHoms[x]; for i in [1..R!.dimension(k-1)] do bnd:=[]; b:=List( f!.mapping([[i,1]],k-1),a-> [ SignInt(a[1])*(AbsoluteValue(a[1])+dim1), Position(Elts,Image(hom1,S!.elts[a[2]])) ]); if IsOddInt(k) then Append(bnd,b); else Append(bnd,NegateWord(b)); fi; b:=List( g!.mapping([[i,1]],k-1),a-> [ SignInt(a[1])*(AbsoluteValue(a[1])+dim2), # Position(Elts,Image(hom1,T!.elts[a[2]])) #Typo found Jan 2012 Position(Elts,Image(hom2,T!.elts[a[2]])) ]); if IsOddInt(k) then Append(bnd,NegateWord(b)); else Append(bnd,b); fi; b:=List(R!.boundary(k-1,i),a-> [ SignInt(a[1])*(AbsoluteValue(a[1])+dim), Position(Elts,Image(hom1,Image(hom,R!.elts[a[2]]))) ]); Append(bnd,b); Append(PseudoBoundary[k],[bnd]); od; od; od; end; ##################################################################### FillPseudoBoundary(); ##################################################################### Boundary:=function(k,i); if k<1 then return 0; fi; if i>0 then return PseudoBoundary[k][i];fi; return NegateWord(PseudoBoundary[k][-i]); end; #################################################################### Apply(Elts,x->Image(quohom,x)); return Objectify(HapResolution, rec( dimension:=Dimension, boundary:=Boundary, homotopy:=fail, elts:=Elts, group:=Range(quohom), properties:= [["length",N], ["reduced",true], ["type","resolution"], ["characteristic",0] ])); end); #####################################################################