GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#(C) Graham Ellis, 2005-2007
#####################################################################
#####################################################################
InstallGlobalFunction(DesuspensionFpGModule,
function(arg)
local
R,G,kk,KK,Mdule, Action,
PseudoBoundaryAsVec,
WordToVectorList,
prime, pp,
BoundaryMatrix,
MT,
GactMat,
one,
zero,
n;
if IsHapFPGModule(arg[1]) then
R:=ResolutionFpGModule(arg[1],Maximum(arg[2],1));
else
R:=arg[1];
fi;
G:=R!.group;
kk:=arg[2];
KK:=Maximum(kk,1);
prime:=EvaluateProperty(R,"characteristic");
pp:=Order(G);
one:=Identity(GaloisField(prime));
zero:=0*one;
MT:=MultiplicationTable(R!.elts);
PseudoBoundaryAsVec:=[];
#####################################################################
WordToVectorList:=function(w,k) #w is a word in R_k.
local v,x,a; #v is a list of vectors mod p.
v:=List([1..R!.dimension(k)],i->List([1..pp],j->0) );
for x in w do
a:=AbsoluteValue(x[1]);
v[a][x[2]]:=v[a][x[2]] + SignInt(x[1]);
od;
return v mod prime;
end;
#####################################################################
#####################################################################
GactMat:=function(g,tB)
local k,q,h,C;
C:=[];
k:=0;
for q in [0..(-1+Length(tB)/pp)] do
for h in [1..pp] do
C[k+MT[g][h]]:=tB[k+h];
od;
k:=k+pp;
od;
ConvertToMatrixRepNC(C);
return C;
end;
#####################################################################
#####################################################################
Action:=function(g,B);
return TransposedMat(GactMat(
Position(R!.elts,g),
TransposedMat(B)));
end;
#####################################################################
PseudoBoundaryAsVec:=[];
for n in [1..R!.dimension(KK)] do
PseudoBoundaryAsVec[n]:=Flat(WordToVectorList(R!.boundary(KK,n),KK-1));
od;
#####################################################################
BoundaryMatrix:=function() #Returns the matrix of d_k:R_k->R_k-1
local B,M,r, b, i, g,j,gB;
#M is actually the transpose of the matrix!
B:=TransposedMat(PseudoBoundaryAsVec);
M:=[];
for g in [1..pp] do
gB:=TransposedMat(GactMat(g,B));
for i in [0..R!.dimension(KK)-1] do
M[i*pp+g]:=gB[i+1];
od;
od;
M:=M*one;
ConvertToMatrixRep(M);
return (M);
end;
#####################################################################
if kk=0 then
Mdule:=SemiEchelonMat(BoundaryMatrix()).vectors;
else
Mdule:=SemiEchelonMat(NullspaceMat(BoundaryMatrix())).vectors;
fi;
#####################################################################
return Objectify(HapFPGModule,
rec(
group:=G,
matrix:=Mdule,
action:=Action,
dimension:=Length(Mdule),
ambientDimension:=R!.dimension(kk)*pp,
characteristic:=prime
));
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(RadicalOfFpGModule,
function(M)
local G, B, prime, g,radB, gens;
if M!.matrix=[] then return M; fi;
G:=M!.group;
prime:=M!.characteristic;
B:=M!.matrix;
ConvertToMatrixRepNC(B,prime);
radB:=[];
gens:=GeneratorsOfGroup(SylowSubgroup(G,prime));
#gens:=ReduceGenerators(gens,G);
for g in gens do
Append(radB,SemiEchelonMat(B-M!.action(g,B)).vectors);
od;
if Length(radB)>0 then
radB:=SemiEchelonMat(radB).vectors;
fi;
return Objectify(HapFPGModule,
rec(
group:=M!.group,
matrix:=radB,
action:=M!.action,
dimension:=Length(radB),
ambientDimension:=M!.ambientDimension,
characteristic:=prime));
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(MultipleOfFpGModule,
function(wrd,M)
local G, B, BB,prime, g, gens;
if M!.matrix=[] then return M; fi;
G:=M!.group;
prime:=M!.characteristic;
B:=MutableCopyMat(M!.matrix);
BB:=B*0;
ConvertToMatrixRepNC(B,prime);
for g in wrd do
BB:=BB+ M!.action(g,B);
od;
if Length(BB)>0 then
BB:=SemiEchelonMat(BB).vectors;
fi;
return BB;
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(GeneratorsOfFpGModule,
function(M)
local
G,prime,pp,one,zero,rad,gens, v, NS, rrb,rrb1, Reducedgens;
if "generators" in NamesOfComponents(M) then
return M!.generators;
fi;
G:=M!.group;
prime:=M!.characteristic;
pp:=Order(G);
one:=Identity(GaloisField(prime));
zero:=0*one;
rad:=RadicalOfFpGModule(M);
rad!.matrix:=Concatenation(rad!.matrix,ComplementaryBasis([M!.matrix,M]));
gens:=ComplementaryBasis([ rad!.matrix, M],
SemiEchelonMat(M!.matrix));
NS:=Length(M!.matrix);
if not IsPrimePowerInt(Order(G)) then
Reducedgens:=[];
rrb:=0;
rrb1:=0;
for v in gens do
if rrb1=NS then break; fi;
rrb1:=FpGModule
(Concatenation(Reducedgens,[v]),G,prime)!.dimension;
if rrb1>rrb then
rrb:=rrb1;
Reducedgens:=Concatenation(Reducedgens,[v]);
fi;
od;
gens:=StructuralCopy(Reducedgens);
for v in gens do
Reducedgens:=Filtered(Reducedgens,x->not x=v);
rrb:=FpGModule
(Reducedgens,G,prime)!.dimension;
if rrb<NS then Add(Reducedgens,v); fi;
od;
gens:=Reducedgens;
fi;
M!.generators:=gens;
return gens;
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(ComplementaryBasis,
function(arg)
local
M,G,prime,pp,one,zero,B, NS, BC, heads,ln, i, v,zeroheads;
M:=arg[1][2];
G:=M!.group;
pp:=Order(G);
prime:=M!.characteristic;
one:=Identity(GaloisField(prime));
zero:=0*one;
B:=StructuralCopy(arg[1][1]);
if Length(arg)>1 then
NS:=StructuralCopy(arg[2]);
fi;
ConvertToMatrixRepNC(B,prime);
B:=MutableCopyMat(B);
heads:=SemiEchelonMatDestructive(B).heads;
ln:=Length(B[1]);
BC:=[];
zeroheads:=Filtered([1..ln],i->heads[i]=0);
if Length(arg)=1 then
for i in zeroheads do
v:=ListWithIdenticalEntries(ln,zero);
v[i]:=one;
ConvertToVectorRep(v,prime);
Add(BC,v);
od;
else
for i in zeroheads do
v:=NS.vectors[NS.heads[i]];
ConvertToVectorRep(v,prime);
Add(BC,v);
od;
fi;
return BC;
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(FpGModule,
function(arg)
local
A,G,M,one,ambdim,pp,prime,MT,GactMat,Action,Elts,g;
A:=arg[1];
G:=arg[2];
pp:=Order(G);
if Length(arg)>2 then prime:=arg[3];
else
if IsPrimePowerInt(Order(G)) then prime:=PrimePGroup(G);
else Print("A prime must be entered for non-prime-power groups.\n");
return fail; fi;
fi;
if Length(A)>0 then
ambdim:=Length(A[1]);
else ambdim:=0;fi;
Elts:=Elements(G);
MT:=MultiplicationTable(Elements(G));
one:=Identity(GF(prime));
#####################################################################
GactMat:=function(g,tB)
local k,q,h,C;
C:=[];
k:=0;
for q in [0..(-1+Length(tB)/pp)] do
for h in [1..pp] do
C[k+MT[g][h]]:=tB[k+h];
od;
k:=k+pp;
od;
ConvertToMatrixRepNC(C);
return C;
end;
#####################################################################
#####################################################################
Action:=function(g,B);
return TransposedMat(GactMat(
Position(Elts,g),
TransposedMat(B)));
end;
#####################################################################
if Length(A)>0 then
for g in G do
A:=MutableCopyMat(A);
Append(A,Action(g,A));
A:=SemiEchelonMat(A).vectors;
od;
fi;
A:=MutableCopyMat(A);
TriangulizeMat(A);
M:=rec(
group:=G,
matrix:=A,
dimension:=Length(A),
ambientDimension:=ambdim,
action:=Action,
characteristic:=prime
);
return Objectify(HapFPGModule, M);
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(FpGModuleHomomorphismNC,
function(M,N,A);
return Objectify(HapFPGModuleHomomorphism,
rec( source:=M,
target:=N,
matrix:=A )
);
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(FpGModuleHomomorphism,
function(M,N,A);
if not IsFpGModuleHomomorphismData(M,N,A) then
return fail;
else
return FpGModuleHomomorphismNC(M,N,A); fi;
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(DirectSumOfFpGModules,
function(arg)
local M,N,A,B,G, zero, prime, v,w;
if Length(arg)=1 and IsList(arg) then
if Length(arg[1])=2
then return DirectSumOfFpGModules(arg[1][1],arg[1][2]);
fi;
M:=arg[1][1];
N:=arg[1]{[2..Length(arg[1])]};
return
DirectSumOfFpGModules(M,DirectSumOfFpGModules(N));
fi;
M:=arg[1];
N:=arg[2];
G:=M!.group;
prime:=M!.characteristic;
if not (G=N!.group and prime=N!.characteristic) then
Print("Modules must be over the same group ring. \n");
return fail; fi;
zero:=Zero(GF(prime));
A:=[];
B:=[];
for w in M!.matrix do
v:=MutableCopyMat([w])[1];
while Length(v)<M!.ambientDimension + N!.ambientDimension do
Add(v,zero);
od;
Add(A,v);
od;
for w in N!.matrix do
v:=Reversed(MutableCopyMat([w])[1]);
while Length(v)<M!.ambientDimension + N!.ambientDimension do
Add(v,zero);
od;
v:=Reversed(v);
Add(B,v);
od;
Append(A,B);
A:=SemiEchelonMat(A).vectors;
return Objectify(HapFPGModule,
rec(
group:=G,
matrix:=A,
dimension:=Length(A),
ambientDimension:=M!.ambientDimension + N!.ambientDimension,
action:=M!.action,
characteristic:=prime)
);
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(IsFpGModuleHomomorphismData,
function(M,N,F)
local
R, Boundary, i, vector, w,x, elts;
elts:=Elements(N!.group);
R:=ResolutionFpGModule(M,2);
if not (elts=R!.elts and M!.characteristic = N!.characteristic) then
Print("The two modules are over different group rings.\n");
return fail; fi;
Boundary:=[];
for i in [1..R!.dimension(2)] do
Add(Boundary,R!.boundary(2,i));
od;
for w in Boundary do
vector:=N!.matrix[1]*Zero(GF(N!.characteristic));
for x in w do
vector:=vector+SignInt(x[1])*N!.action(elts[x[2]],[F[AbsInt(x[1])]])[1];
od;
if not IsZero(vector) then return false; fi;
od;
return true;
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(IntersectionOfFpGModules,
function(M,N)
local V;
if not (M!.group = N!.group and M!.characteristic=N!.characteristic)
or not M!.ambientDimension = N!.ambientDimension
then
Print("Modules are not compatible. \n"); return fail;
fi;
V:=SumIntersectionMat(M!.matrix,N!.matrix)[2];
return Objectify(HapFPGModule,
rec(
group:=M!.group,
matrix:=V,
dimension:=Length(V),
ambientDimension:=M!.ambientDimension,
action:=M!.action,
characteristic:=M!.characteristic)
);
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(SumOfFpGModules,
function(M,N)
local V;
if not (M!.group = N!.group and M!.characteristic=N!.characteristic)
or not M!.ambientDimension = N!.ambientDimension
then
Print("Modules are not compatible. \n"); return fail;
fi;
V:=SumIntersectionMat(M!.matrix,N!.matrix)[1];
return Objectify(HapFPGModule,
rec(
group:=M!.group,
matrix:=V,
dimension:=Length(V),
ambientDimension:=M!.ambientDimension,
action:=M!.action,
characteristic:=M!.characteristic)
);
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(VectorsToFpGModuleWords,
function(M,v)
local #v is a list of vectors
G,gens, Ggens,
VecToWord,g,w;
G:=M!.group;
gens:=GeneratorsOfFpGModule(M);
Ggens:=[];
for g in G do
Append(Ggens, M!.action(g,gens));
od;
ConvertToMatrixRep(Ggens);
########################################
VecToWord:=function(w)
local wrd,i,g ;
wrd:=[];
for i in [0..Length(gens)-1] do
for g in [1..Order(G)] do
if not IsZero(w[i*Order(G)+g]) then
Append(wrd,
MultiplyWord(IntFFE(w[i*Order(G)+g]),[[i+1,g]])
);fi;
od;od;
return wrd;
end;
########################################
w:=SolutionsMatDestructive(MutableCopyMat(Ggens),MutableCopyMat(v));
Apply(w,y->VecToWord(y));
return w;
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallOtherMethod(\+,
"for FpG homomorphisms",
[IsHapFPGModuleHomomorphism,IsHapFPGModuleHomomorphism],
function(x,y)
if not (Source(x)=Source(y) and Target(x)=Target(y)) then return fail; fi;
return FpGModuleHomomorphismNC(x!.source,x!.target,x!.matrix + x!.matrix);
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallOtherMethod(\<,
"for FpG modules",
[IsHapFPGModule,IsHapFPGModule],
function(x,y)
if x!.group=y!.group then
return x!.matrix < y!.matrix;
else return false; fi;
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallOtherMethod(\=,
"for FpG modules",
[IsHapFPGModule,IsHapFPGModule],
function(x,y)
if x!.group=y!.group then
return x!.matrix = y!.matrix;
else return false; fi;
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallOtherMethod(SumOp,
"for FpG homomorphisms",
[IsHapFPGModuleHomomorphism,IsHapFPGModuleHomomorphism],
function(x,y)
if not (Source(x)=Source(y) and Target(x)=Target(y)) then return fail; fi;
return FpGModuleHomomorphismNC(x!.source,x!.target,x!.matrix + x!.matrix);
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallOtherMethod(Source,
"for FpG homomorphisms",
[IsHapFPGModuleHomomorphism],
function(x)
return x!.source;
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallOtherMethod(Target,
"for FpG homomorphisms",
[IsHapFPGModuleHomomorphism],
function(x)
return x!.target;
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(ImageOfFpGModuleHomomorphism,
function(x)
return FpGModule(x!.matrix,Target(x)!.group);
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallOtherMethod(Rank,
"for FpG homomorphisms",
[IsHapFPGModuleHomomorphism],
function(x)
return Dimension(FpGModule(x!.matrix,Target(x)!.group));
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(GroupAlgebraAsFpGModule,
function(G)
local S,M,p,V,A;
if not IsPGroup(G) then
Print("G must be a finite p-group\n");
return fail; fi;
p:=PrimePGroup(G);
V:=List([1..Order(G)],i->0);
V[1]:=1;
V:=One(GF(p))*V;
return FpGModule([V],G);
end);
#####################################################################
#####################################################################
#####################################################################
#####################################################################
InstallGlobalFunction(MaximalSubmodulesOfFpGModule,
function(M)
local R,L,gens,dim,prime,V,v,SSP,B;
if not IsHapFPGModule(M) then
Print("Input is not an FpG-module\n");
return fail;
fi;
L:=[];
if Dimension(M)= 0 then return L; fi;
prime:=PrimePGroup(M!.group);
R:=RadicalOfFpGModule(M);
if Dimension(R)>0 then
R:=GeneratorsOfFpGModule(R);
else R:=[];fi;
gens:=GeneratorsOfFpGModule(M);
dim:=Length(gens);
SSP:=Subspaces(GF(prime)^dim,dim-1);
for V in List(SSP,x->x) do
B:=[];
for v in Basis(V) do
Add(B,v*gens);
od;
Add(L,Concatenation(B,R));
od;
for B in L do
TriangulizeMat(B);
od;
Apply(L,b->FpGModule(b,M!.group));
return L;
end);
########################################
########################################
#####################################################################
#####################################################################
InstallGlobalFunction(MaximalSubmoduleOfFpGModule,
function(M)
local R,gens,dim,prime;
if not IsHapFPGModule(M) then
Print("Input is not an FpG-module\n");
return fail;
fi;
if Dimension(M)= 0 then return M; fi;
prime:=PrimePGroup(M!.group);
R:=RadicalOfFpGModule(M);
if Dimension(R)>0 then
R:=GeneratorsOfFpGModule(R);
else R:=[];fi;
gens:=GeneratorsOfFpGModule(M);
dim:=Length(gens);
Append(R,gens{[1..dim-1]});
return FpGModule(R,M!.group);
end);
########################################
########################################
########################################
########################################
InstallGlobalFunction(RadicalSeriesOfFpGModule,
function(M)
local S;
S:=[M];
while Dimension(M)>0 do
M:=RadicalOfFpGModule(M);
Add(S,M);
od;
return S;
end);
########################################
########################################
########################################
########################################
InstallGlobalFunction(CompositionSeriesOfFpGModule,
function(M)
local S;
S:=[M];
while Dimension(M)>0 do
M:=MaximalSubmoduleOfFpGModule(M);
Add(S,M);
od;
return S;
end);
########################################
########################################
########################################
########################################
InstallGlobalFunction(Classify,
function(L,Inv)
local Class, ValInv, x,c;
ValInv:=[];
Class:=[];
for x in L do
c:=Inv(x);
if not c in ValInv then Add(ValInv,c); Add(Class,[]);fi;
Add(Class[Position(ValInv,c)],x);
od;
return Class;
end);
########################################
########################################
########################################
########################################
InstallGlobalFunction(RefineClassification,
function(C,Inv)
local x,RefC;
RefC:=[];
for x in C do
if Length(x)=1 then
Add(RefC,x);
else
Append(RefC,Classify(x,Inv));
fi;
od;
return RefC;
end);
########################################
########################################
#########################################
#########################################
InstallGlobalFunction(FpGModuleSection,
function(M,w)
local gens, G, A, B, g, S, pp, fn1, fn, u,v,zz;
gens:=GeneratorsOfFpGModule(M);
G:=M!.group;
pp:=Order(G);
if not IsBound(M!.section) then
###############
fn1:=function(i)
local n;
n:=i/pp;
if IsInt(n) then return [n,pp];
else return [1+Int(n),i mod pp];
fi;
end;
###############
###############
fn:=function(v)
local j,i,x,w;
w:=[];
for i in [1..Length(v)] do
for j in [1..IntFFE(v[i])] do
Add(w,fn1(i));
od;
od;
return w;
end;
###############
A:=[];
for zz in gens do
for g in G do
Append(A,M!.action(g,[zz]));
od;
od;
B:=MutableCopyMat(M!.matrix);
A:=MutableCopyMat(A);
S:=SolutionsMatDestructive(A,B);
M!.section:=[S,fn];
fi;
##########################################
S:=M!.section[1];
fn:=M!.section[2];
u:=SolutionMat(M!.matrix,w);
return fn(u*S);
end);
########################################
########################################