# The following code is used in # "Birational Classification for Algebraic Tori" # by Akinari Hoshi and Aiichi Yamasaki # new functions are added to FlabbyResolutionFromBase.gap # Written by Aiichi Yamasaki (2020-2021) Hminus1:= function(g) local m,gg,i,s,r; m:=[]; gg:=GeneratorsOfGroup(g); if gg=[] then return []; else for i in gg do m:=Concatenation(m,i-Identity(g)); od; s:=SmithNormalFormIntegerMat(m); r:=Rank(s); return List([1..r],x->s[x][x]); fi; end; Z0lattice:= function(g) local gg,m,i; gg:=GeneratorsOfGroup(g); if gg=[] then return Identity(g); else m:=[]; for i in gg do m:=Concatenation(m,TransposedMat(i)-Identity(g)); od; m:=TransposedMat(m); return NullspaceIntMat(m); fi; end; H0:= function(g) local m,s,r; m:=Sum(g); s:=SmithNormalFormIntegerMat(m); r:=Rank(s); return List([1..r],x->s[x][x]); end; H1:= function(g) local m,gg,i,s,r; m:=[]; gg:=GeneratorsOfGroup(g); if gg=[] then return []; else for i in gg do m:=Concatenation(m,TransposedMat(i)-Identity(g)); od; m:=TransposedMat(m); s:=SmithNormalFormIntegerMat(m); r:=Rank(s); return List([1..r],x->s[x][x]); fi; end; ConjugacyClassesSubgroups2:= function(g) Reset(GlobalMersenneTwister); Reset(GlobalRandomSource); return ConjugacyClassesSubgroups(g); end; ConjugacyClassesSubgroupsFromPerm:= function(g) local iso,h,i; Reset(GlobalMersenneTwister); Reset(GlobalRandomSource); iso:=IsomorphismPermGroup(g); h:=ConjugacyClassesSubgroups2(Range(iso)); h:=List(h,Representative); h:=List(h,x->PreImage(iso,x)); return h; end; IsFlabby:= function(g) local h; h:=List(ConjugacyClassesSubgroups2(g),Representative); return ForAll(h,x->Product(Hminus1(x))=1); end; IsCoflabby:= function(g) local h; h:=List(ConjugacyClassesSubgroups2(g),Representative); return ForAll(h,x->Product(H1(x))=1); end; # "H2 and "H2sub" options for # PossibilityOfStablyPermutationH # PossibilityOfStablyEquivalentHSubdirectProduct # PossibilityOfStablyEquivalentFSubdirectProduct # and related functions # need GAP package HAP version>=1.11.15 LoadPackage("HAP"); CochainComplexMatrixGroup:= function(M,n) local IA,G,A,R,TR; IA:=RegularActionHomomorphism(TransposedMatrixGroup(M)); G:=Image(IA); A:=InverseGeneralMapping(IA); R:=ResolutionFiniteGroup(G,n); TR:=HomToIntegralModule(R,A); return TR; end; ChainComplexMatrixGroup:= function(M,n) local IA,G,A,R,TR; IA:=RegularActionHomomorphism(TransposedMatrixGroup(M)); G:=Image(IA); A:=InverseGeneralMapping(IA); R:=ResolutionFiniteGroup(G,n); TR:=TensorWithIntegralModule(R,A); return TR; end; TateCohomology:= function(g,n) local m,gg,i,s,r,TR; if n=0 then m:=Sum(g); s:=SmithNormalFormIntegerMat(m); r:=Rank(s); return List([1..r],x->s[x][x]); elif n>0 then TR:=CochainComplexMatrixGroup(g,n+1); return Cohomology(TR,n); elif n=-1 then m:=[]; gg:=GeneratorsOfGroup(g); if gg=[] then return []; else for i in gg do m:=Concatenation(m,i-Identity(g)); od; s:=SmithNormalFormIntegerMat(m); r:=Rank(s); r:=List([1..r],x->s[x][x]); return Filtered(r,x->x>1); fi; else TR:=ChainComplexMatrixGroup(g,-n); return Homology(TR,-n-1); fi; end; MaximalNormalSeries:= function(G) local M,ans,Ns,N; Reset(GlobalMersenneTwister); Reset(GlobalRandomSource); M:=G; ans:=[G]; Ns:=NormalSubgroups(G); while Order(M)>1 do Ns:=Filtered(Ns,x->x<>M and IsSubgroup(M,x)); M:=Ns[1]; for N in Ns do if Order(N)>Order(M) then M:=N; fi; od; Add(ans,M); od; return ans; end; Hn:= function(g,n) local iso,gp,Rgp,MNS,d1,d2,ij,mij,i,j,k,l,m,s,r; if Order(g)=1 then return []; fi; iso:=IsomorphismPermGroup(g); gp:=Image(iso); if IsNilpotentGroup(gp) then Rgp:=ResolutionNormalSeries(LowerCentralSeries(gp),n); elif IsSolvable(gp) then Rgp:=ResolutionNormalSeries(DerivedSeries(gp),n); else MNS:=MaximalNormalSeries(gp); if Length(MNS)>2 then Rgp:=ResolutionNormalSeries(MNS,n); else Rgp:=ResolutionFiniteGroup(gp,n); fi; fi; d1:=Rgp!.dimension(n-1); d2:=Rgp!.dimension(n); ij:=[]; mij:=[]; for j in [1..d2] do for l in Rgp!.boundary(n,j) do i:=AbsInt(l[1]); m:=SignInt(l[1])*Representative(PreImages(iso,Rgp!.elts[l[2]]^-1)); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(mij,m); else mij[k]:=mij[k]+m; fi; od; od; m:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],mij[x]]),d1,d2); m:=MatrixByBlockMatrix(m); s:=SmithNormalFormIntegerMat(m); r:=Rank(s); return Filtered(List([1..r],x->s[x][x]),y->y>1); end; HnFromGroup:= function(g,n,G) local iso,hom,gp,Rgp,MNS,d1,d2,ij,mij,i,j,k,l,m,s,r; iso:=IsomorphismPermGroup(G); hom:=GroupHomomorphismByImages(G,g,GeneratorsOfGroup(G),GeneratorsOfGroup(g)); gp:=Image(iso); if IsNilpotentGroup(gp) then Rgp:=ResolutionNormalSeries(LowerCentralSeries(gp),n); elif IsSolvable(gp) then Rgp:=ResolutionNormalSeries(DerivedSeries(gp),n); else MNS:=MaximalNormalSeries(gp); if Length(MNS)>2 then Rgp:=ResolutionNormalSeries(MNS,n); else Rgp:=ResolutionFiniteGroup(gp,n); fi; fi; d1:=Rgp!.dimension(n-1); d2:=Rgp!.dimension(n); ij:=[]; mij:=[]; for j in [1..d2] do for l in Rgp!.boundary(n,j) do i:=AbsInt(l[1]); m:=SignInt(l[1])*Image(hom,PreImage(iso,Rgp!.elts[l[2]]^-1)); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(mij,m); else mij[k]:=mij[k]+m; fi; od; od; m:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],mij[x]]),d1,d2); m:=MatrixByBlockMatrix(m); s:=SmithNormalFormIntegerMat(m); r:=Rank(s); return Filtered(List([1..r],x->s[x][x]),y->y>1); end; HnSubdirectProduct:= function(g,n) local iso,gp,Rgp,MNS,d1,d2,ij,m1ij,m2ij,i,j,k,l,m1,m2,s1,s2,r1,r2,hn1,hn2; iso:=IsomorphismPermGroup(g); gp:=Image(iso); if IsNilpotentGroup(gp) then Rgp:=ResolutionNormalSeries(LowerCentralSeries(gp),n); elif IsSolvable(gp) then Rgp:=ResolutionNormalSeries(DerivedSeries(gp),n); else MNS:=MaximalNormalSeries(gp); if Length(MNS)>2 then Rgp:=ResolutionNormalSeries(MNS,n); else Rgp:=ResolutionFiniteGroup(gp,n); fi; fi; d1:=Rgp!.dimension(n-1); d2:=Rgp!.dimension(n); ij:=[]; m1ij:=[]; m2ij:=[]; for j in [1..d2] do for l in Rgp!.boundary(n,j) do i:=AbsInt(l[1]); m1:=SignInt(l[1])*Image(Projection(g,1),PreImage(iso,Rgp!.elts[l[2]]^-1)); m2:=SignInt(l[1])*Image(Projection(g,2),PreImage(iso,Rgp!.elts[l[2]]^-1)); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(m1ij,m1); Add(m2ij,m2); else m1ij[k]:=m1ij[k]+m1; m2ij[k]:=m2ij[k]+m2; fi; od; od; m1:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],m1ij[x]]),d1,d2); m1:=MatrixByBlockMatrix(m1); m2:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],m2ij[x]]),d1,d2); m2:=MatrixByBlockMatrix(m2); s1:=SmithNormalFormIntegerMat(m1); s2:=SmithNormalFormIntegerMat(m2); r1:=Rank(s1); r2:=Rank(s2); hn1:=Filtered(List([1..r1],x->s1[x][x]),y->y>1); hn2:=Filtered(List([1..r2],x->s2[x][x]),y->y>1); return [hn1,hn2]; end; HnsubSubdirectProduct:= function(g,n,proj) local iso,gp,Rgp,MNS,d1,d2,ij,m1ij,m2ij,i,j,k,l,m1,m2,s1,s2,r1,r2,hn1,hn2; iso:=IsomorphismPermGroup(g); gp:=Image(iso); if IsNilpotentGroup(gp) then Rgp:=ResolutionNormalSeries(LowerCentralSeries(gp),n); elif IsSolvable(gp) then Rgp:=ResolutionNormalSeries(DerivedSeries(gp),n); else MNS:=MaximalNormalSeries(gp); if Length(MNS)>2 then Rgp:=ResolutionNormalSeries(MNS,n); else Rgp:=ResolutionFiniteGroup(gp,n); fi; fi; d1:=Rgp!.dimension(n-1); d2:=Rgp!.dimension(n); ij:=[]; m1ij:=[]; m2ij:=[]; for j in [1..d2] do for l in Rgp!.boundary(n,j) do i:=AbsInt(l[1]); m1:=SignInt(l[1])*Image(proj[1],PreImage(iso,Rgp!.elts[l[2]]^-1)); m2:=SignInt(l[1])*Image(proj[2],PreImage(iso,Rgp!.elts[l[2]]^-1)); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(m1ij,m1); Add(m2ij,m2); else m1ij[k]:=m1ij[k]+m1; m2ij[k]:=m2ij[k]+m2; fi; od; od; m1:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],m1ij[x]]),d1,d2); m1:=MatrixByBlockMatrix(m1); m2:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],m2ij[x]]),d1,d2); m2:=MatrixByBlockMatrix(m2); s1:=SmithNormalFormIntegerMat(m1); s2:=SmithNormalFormIntegerMat(m2); r1:=Rank(s1); r2:=Rank(s2); hn1:=Filtered(List([1..r1],x->s1[x][x]),y->y>1); hn2:=Filtered(List([1..r2],x->s2[x][x]),y->y>1); return [hn1,hn2]; end; HnSubdirectProductToHom:= function(g,n,hom) local iso,gp,Rgp,MNS,d1,d2,ij,m1ij,m2ij,i,j,k,l,m1,m2,s1,s2,r1,r2,hn1,hn2; iso:=IsomorphismPermGroup(g); gp:=Image(iso); if IsNilpotentGroup(gp) then Rgp:=ResolutionNormalSeries(LowerCentralSeries(gp),n); elif IsSolvable(gp) then Rgp:=ResolutionNormalSeries(DerivedSeries(gp),n); else MNS:=MaximalNormalSeries(gp); if Length(MNS)>2 then Rgp:=ResolutionNormalSeries(MNS,n); else Rgp:=ResolutionFiniteGroup(gp,n); fi; fi; d1:=Rgp!.dimension(n-1); d2:=Rgp!.dimension(n); ij:=[]; m1ij:=[]; m2ij:=[]; for j in [1..d2] do for l in Rgp!.boundary(n,j) do i:=AbsInt(l[1]); m1:=SignInt(l[1])*Image(hom[1],Image(Projection(g,1),PreImage(iso,Rgp!.elts[l[2]]^-1))); m2:=SignInt(l[1])*Image(hom[2],Image(Projection(g,2),PreImage(iso,Rgp!.elts[l[2]]^-1))); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(m1ij,m1); Add(m2ij,m2); else m1ij[k]:=m1ij[k]+m1; m2ij[k]:=m2ij[k]+m2; fi; od; od; m1:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],m1ij[x]]),d1,d2); m1:=MatrixByBlockMatrix(m1); m2:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],m2ij[x]]),d1,d2); m2:=MatrixByBlockMatrix(m2); s1:=SmithNormalFormIntegerMat(m1); s2:=SmithNormalFormIntegerMat(m2); r1:=Rank(s1); r2:=Rank(s2); hn1:=Filtered(List([1..r1],x->s1[x][x]),y->y>1); hn2:=Filtered(List([1..r2],x->s2[x][x]),y->y>1); return [hn1,hn2]; end; HnsubSubdirectProductToHom:= function(g,n,proj,hom) local iso,gp,Rgp,MNS,d1,d2,ij,m1ij,m2ij,i,j,k,l,m1,m2,s1,s2,r1,r2,hn1,hn2; iso:=IsomorphismPermGroup(g); gp:=Image(iso); if IsNilpotentGroup(gp) then Rgp:=ResolutionNormalSeries(LowerCentralSeries(gp),n); elif IsSolvable(gp) then Rgp:=ResolutionNormalSeries(DerivedSeries(gp),n); else MNS:=MaximalNormalSeries(gp); if Length(MNS)>2 then Rgp:=ResolutionNormalSeries(MNS,n); else Rgp:=ResolutionFiniteGroup(gp,n); fi; fi; d1:=Rgp!.dimension(n-1); d2:=Rgp!.dimension(n); ij:=[]; m1ij:=[]; m2ij:=[]; for j in [1..d2] do for l in Rgp!.boundary(n,j) do i:=AbsInt(l[1]); m1:=SignInt(l[1])*Image(hom[1],Image(proj[1],PreImage(iso,Rgp!.elts[l[2]]^-1))); m2:=SignInt(l[1])*Image(hom[2],Image(proj[2],PreImage(iso,Rgp!.elts[l[2]]^-1))); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(m1ij,m1); Add(m2ij,m2); else m1ij[k]:=m1ij[k]+m1; m2ij[k]:=m2ij[k]+m2; fi; od; od; m1:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],m1ij[x]]),d1,d2); m1:=MatrixByBlockMatrix(m1); m2:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],m2ij[x]]),d1,d2); m2:=MatrixByBlockMatrix(m2); s1:=SmithNormalFormIntegerMat(m1); s2:=SmithNormalFormIntegerMat(m2); r1:=Rank(s1); r2:=Rank(s2); hn1:=Filtered(List([1..r1],x->s1[x][x]),y->y>1); hn2:=Filtered(List([1..r2],x->s2[x][x]),y->y>1); return [hn1,hn2]; end; ReduceCoflabbyResolutionBase:= function(g,hh,mi) local o,oo,z0,mi2; oo:=Orbits(g,mi); z0:=List(hh,Z0lattice); for o in oo do mi2:=Filtered(mi,x->(x in o)=fail); if ForAll([1..Length(hh)],i->LatticeBasis(List(Orbits(hh[i],mi2),Sum))=z0[i]) then mi:=mi2; fi; od; return mi; end; FindCoflabbyResolutionBase:= function(g,hh) local d,mi,h,z0,ll,i,o; d:=Length(Identity(g)); mi:=[]; for h in hh do z0:=Z0lattice(h); ll:=LatticeBasis(List(Orbits(h,mi),Sum)); for i in z0 do if LatticeBasis(Concatenation(ll,[i]))<>ll then o:=Orbit(g,i); mi:=Concatenation(mi,o); o:=List(Orbits(h,o),Sum); ll:=LatticeBasis(Concatenation(ll,o)); fi; od; od; return ReduceCoflabbyResolutionBase(g,hh,mi); end; FlabbyResolution:= function(g) local tg,gg,d,th,mi,ms,o,r,gg1,gg2,v1,mg,img; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); o:=IdentityMat(r); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return rec(injection:=TransposedMat(mi), surjection:=NullMat(r,0), actionP:=TransposedMatrixGroup(Group(gg1,o)) ); else ms:=NullspaceIntMat(mi); v1:=NullspaceIntMat(TransposedMat(ms)); mg:=Concatenation(v1,ms); img:=mg^-1; gg2:=List(gg1,x->mg*x*img); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); return rec(injection:=TransposedMat(mi), surjection:=TransposedMat(ms), actionP:=TransposedMatrixGroup(Group(gg1)), actionF:=TransposedMatrixGroup(Group(gg2)) ); fi; end; ModpTest:= function(g,p) local tg,gg,d,th,mi,z0,ll,h,r,i,j,k,gg1,g1,oo,iso,l1,l2,m1,m2; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); gg1:=List(gg,x->Permutation(x,mi)); gg:=GeneratorsOfGroup(g); gg1:=List(gg1,x->x^-1); g1:=Group(gg1,()); mi:=TransposedMat(mi); iso:=GroupHomomorphismByImagesNC(g1,g,gg1,gg); oo:=OrbitsDomain(g1,[1..r]); m1:=[]; for i in oo do h:=Stabilizer(g1,i[1]); ll:=List(RightCosetsNC(g1,h),Representative); l1:=List(ll,x->i[1]^x); l2:=List(ll,x->Image(iso,x)); z0:=Z0lattice(Image(iso,h)); for j in z0 do m2:=NullMat(r,d); for k in [1..Length(ll)] do m2[l1[k]]:=j*l2[k]; od; Add(m1,Flat(mi*m2)); od; od; m2:=Concatenation(m1,[Flat(IdentityMat(d))]); m1:=m1*Z(p); m2:=m2*Z(p); return RankMat(m1)=RankMat(m2); end; SplitTest:= function(g) local tg,gg,d,th,mi,z0,ll,h,r,i,j,k,gg1,g1,oo,iso,l1,l2,m1,m2; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); gg1:=List(gg,x->Permutation(x,mi)); gg:=GeneratorsOfGroup(g); gg1:=List(gg1,x->x^-1); g1:=Group(gg1,()); mi:=TransposedMat(mi); iso:=GroupHomomorphismByImagesNC(g1,g,gg1,gg); oo:=OrbitsDomain(g1,[1..r]); m1:=[]; for i in oo do h:=Stabilizer(g1,i[1]); ll:=List(RightCosetsNC(g1,h),Representative); l1:=List(ll,x->i[1]^x); l2:=List(ll,x->Image(iso,x)); z0:=Z0lattice(Image(iso,h)); for j in z0 do m2:=NullMat(r,d); for k in [1..Length(ll)] do m2[l1[k]]:=j*l2[k]; od; Add(m1,Flat(mi*m2)); od; od; m2:=Concatenation(m1,[Flat(IdentityMat(d))]); m1:=NullspaceIntMat(m2); return Gcd(TransposedMat(m1)[Length(m2)])=1; end; IsInvertibleF:= function(g) local tg,gg,d,th,mi,mi2,ms,z0,ll,h,r,i,j,k,gg1,gg2,g1,g2,oo,iso,ker,tg2,th2,h2,l1,l2,v1,m1,m2; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return true; else ms:=NullspaceIntMat(mi); v1:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v1,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); for h in th2 do if Product(Hminus1(h))>1 then return false; fi; od; for h in th do if Product(Hminus1(h))>1 then d:=r-d; mi:=FindCoflabbyResolutionBase(tg2,th2); r:=Length(mi); gg1:=List(gg2,x->Permutation(x,mi)); gg2:=List(gg2,TransposedMat); g2:=Group(gg2); gg1:=List(gg1,x->x^-1); g1:=Group(gg1); mi:=TransposedMat(mi); iso:=GroupHomomorphismByImagesNC(g1,g2,gg1,gg2); oo:=OrbitsDomain(g1,[1..r]); m1:=[]; for i in oo do h:=Stabilizer(g1,i[1]); ll:=List(RightCosetsNC(g1,h),Representative); l1:=List(ll,x->i[1]^x); l2:=List(ll,x->Image(iso,x)); z0:=Z0lattice(Image(iso,h)); for j in z0 do m2:=NullMat(r,d); for k in [1..Length(ll)] do m2[l1[k]]:=j*l2[k]; od; Add(m1,Flat(mi*m2)); od; od; m2:=Concatenation(m1,[Flat(IdentityMat(d))]); m1:=NullspaceIntMat(m2); return Gcd(TransposedMat(m1)[Length(m2)])=1; fi; od; gg1:=List(gg,x->Permutation(x,mi)); gg:=GeneratorsOfGroup(g); gg1:=List(gg1,x->x^-1); g1:=Group(gg1); mi:=TransposedMat(mi); iso:=GroupHomomorphismByImagesNC(g1,g,gg1,gg); oo:=OrbitsDomain(g1,[1..r]); m1:=[]; for i in oo do h:=Stabilizer(g1,i[1]); ll:=List(RightCosetsNC(g1,h),Representative); l1:=List(ll,x->i[1]^x); l2:=List(ll,x->Image(iso,x)); z0:=Z0lattice(Image(iso,h)); for j in z0 do m2:=NullMat(r,d); for k in [1..Length(ll)] do m2[l1[k]]:=j*l2[k]; od; Add(m1,Flat(mi*m2)); od; od; m2:=Concatenation(m1,[Flat(IdentityMat(d))]); m1:=NullspaceIntMat(m2); return Gcd(TransposedMat(m1)[Length(m2)])=1; fi; end; flfl:= function(g) local tg,gg,d,th,mi,ms,r,gg1,gg2,v1,mg,img,tg2,iso,ker; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return []; else ms:=NullspaceIntMat(mi); v1:=NullspaceIntMat(TransposedMat(ms)); mg:=Concatenation(v1,ms); img:=mg^-1; gg2:=List(gg1,x->mg*x*img); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th:=List(Filtered(th,x->IsSubset(x,ker)),x->Image(iso,x)); tg:=tg2; gg:=gg2; d:=r-d; mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return []; else ms:=NullspaceIntMat(mi); v1:=NullspaceIntMat(TransposedMat(ms)); mg:=Concatenation(v1,ms); img:=mg^-1; gg2:=List(gg1,x->mg*x*img); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); return TransposedMatrixGroup(Group(gg2)); fi; fi; end; PossibilityOfStablyPermutationH:= function(g,hh) local gg,hg,hgg,hom,c,h,m,m1,m2,v,h0,og,oh,p,e,h2; gg:=GeneratorsOfGroup(g); hg:=List(hh,x->RightCosets(g,x)); hgg:=List(hg,x->List(gg,y->Permutation(y,x,OnRight))); hom:=List(hgg,x->GroupHomomorphismByImages(g,Group(x,()),gg,x)); c:=List(ConjugacyClasses(g),Representative); og:=Order(g); m:=List(c,x->List([1..Length(hh)],y->og/Order(hh[y])-NrMovedPoints(Image(hom[y],x)))); v:=List(c,Trace); for h in hh do h0:=H0(h); oh:=Order(h); m1:=List([1..Length(hh)],x->List(OrbitLengths(Image(hom[x],h),[1..og/Order(hh[x])]),y->oh/y)); Add(m,List(m1,Length)); Add(v,Length(h0)); if oh>1 then for p in Set(FactorsInt(oh)) do for e in [1..PadicValuation(oh,p)] do Add(m,List(m1,x->Number(x,y->PadicValuation(y,p)=e))); Add(v,Number(h0,x->PadicValuation(x,p)=e)); od; od; fi; od; if ValueOption("H2")<>fail or ValueOption("h2")<>fail then if ValueOption("H2")="Tate" or ValueOption("h2")="Tate" then h2:=TateCohomology(g,2); else h2:=Hn(g,2); fi; m1:=List(hh,x->AbelianInvariants(x/DerivedSubgroup(x))); if og>1 then for p in Set(FactorsInt(og)) do for e in [1..PadicValuation(og,p)] do Add(m,List(m1,x->Number(x,y->PadicValuation(y,p)=e))); Add(v,Number(h2,x->PadicValuation(x,p)=e)); od; od; fi; fi; if ValueOption("H2sub")<>fail or ValueOption("h2sub")<>fail then for h in hh do if ValueOption("H2sub")="Tate" or ValueOption("h2sub")="Tate" then h2:=TateCohomology(h,2); else h2:=Hn(h,2); fi; oh:=Order(h); m1:=List([1..Length(hh)],x->List(OrbitsDomain(Image(hom[x],h),[1..og/Order(hh[x])]),y->Intersection(h,PreImage(hom[x],Stabilizer(Image(hom[x],h),y[1]))))); m1:=List([1..Length(hh)],x->Concatenation(List(m1[x],y->AbelianInvariants(y/DerivedSubgroup(y))))); if oh>1 then for p in Set(FactorsInt(oh)) do for e in [1..PadicValuation(oh,p)] do Add(m,List(m1,x->Number(x,y->PadicValuation(y,p)=e))); Add(v,Number(h2,x->PadicValuation(x,p)=e)); od; od; fi; od; fi; if ValueOption("H3")<>fail or ValueOption("h3")<>fail then if ValueOption("H3")="Tate" or ValueOption("h3")="Tate" then h2:=TateCohomology(g,3); else h2:=Hn(g,3); fi; m1:=List(hh,x->AbelianInvariantsMultiplier(x)); if og>1 then for p in Set(FactorsInt(og)) do for e in [1..PadicValuation(og,p)] do Add(m,List(m1,x->Number(x,y->PadicValuation(y,p)=e))); Add(v,Number(h2,x->PadicValuation(x,p)=e)); od; od; fi; fi; m:=TransposedMat(m); m:=Concatenation(m,[v]); return NullspaceIntMat(m); end; PossibilityOfStablyPermutationM:= function(g) local hh; hh:=List(ConjugacyClassesSubgroups2(g),Representative); return PossibilityOfStablyPermutationH(g,hh); end; PossibilityOfStablyPermutationF:= function(g) local tg,gg,d,th,mi,ms,r,gg1,gg2,g2,iso,ker,tg2,th2,h2,m1,m2,v; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return [0,1]; else ms:=NullspaceIntMat(mi); v:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); g2:=TransposedMatrixGroup(tg2); h2:=List(th2,TransposedMatrixGroup); return PossibilityOfStablyPermutationH(g2,h2); fi; end; CosetRepresentation:= function(g,h) local gg,hg,og; gg:=GeneratorsOfGroup(g); hg:=SortedList(RightCosets(g,h)); og:=Length(hg); return List(gg,x->PermutationMat(Permutation(x,hg,OnRight),og)); end; StablyPermutationCheckH:= function(g,hh,c1,c2) local gg,g1,g2,dx,m,i,j,d; gg:=List(hh,x->CosetRepresentation(g,x)); Add(gg,GeneratorsOfGroup(g)); g1:=[]; g2:=[]; for i in [1..Length(gg[1])] do m:=[]; for j in [1..Length(gg)] do m:=Concatenation(m,List([1..c1[j]],x->gg[j][i])); od; Add(g1,DirectSumMat(m)); m:=[]; for j in [1..Length(gg)] do m:=Concatenation(m,List([1..c2[j]],x->gg[j][i])); od; Add(g2,DirectSumMat(m)); od; d:=Length(g1[1]); if d<>Length(g2[1]) then return fail; else return RepresentativeAction(GL(d,Integers),Group(g1),Group(g2)); fi; end; StablyPermutationMCheck:= function(g,c1,c2) local h; h:=List(ConjugacyClassesSubgroups2(g),Representative); return StablyPermutationCheckH(g,h,c1,c2); end; StablyPermutationFCheck:= function(g,c1,c2) local tg,gg,d,th,mi,ms,o,h,r,gg1,gg2,g2,iso,ker,tg2,th2,h2,m1,m2,v; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return true; else ms:=NullspaceIntMat(mi); v:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); g2:=TransposedMatrixGroup(tg2); h2:=List(th2,TransposedMatrixGroup); return StablyPermutationCheckH(g2,h2,c1,c2); fi; end; Plist:= function(l) return List(l,x->Maximum([x,0])); end; Nlist:= function(l) return List(l,x->Maximum([-x,0])); end; TransformationMatSaveSpace:= function(l1,l2) local d1,d2,l,l1i,prm,m,tf,i,j,ij,q,q0,q1,q2,qg,p,eff,k,m1; d1:=Length(l1[1]); d2:=Length(l2[1]); l:=Length(l1); l1i:=List(l1,x->x^-1); prm:=Union(Factors(Order(Group(l1))),Factors(Order(Group(l2)))); m:=[]; tf:=List([1..d1*d2],x->false); ij:=Position(tf,false); while ij<>fail do tf[ij]:=true; q:=NullMat(d1,d2); j:=((ij-1) mod d2)+1; i:=(ij-j)/d2+1; q[i][j]:=1; q0:=[q]; q1:=[q]; while q1<>[] do q2:=[]; for q in q1 do for k in [1..l] do qg:=l1i[k]*q*l2[k]; Add(q2,qg); qg:=Flat(qg); if Sum(qg,AbsInt)=1 then tf:=List([1..d1*d2],x->tf[x] or AbsInt(qg[x])=1); fi; od; od; q1:=Difference(q2,q0); q0:=Union(q0,q1); od; Add(m,Flat(Sum(q0))); m:=LatticeBasis(m); ij:=Position(tf,false); od; for p in prm do eff:=List([0..p-1],x->x*Z(p)^0); k:=NullspaceMat(m*Z(p)^0); while k<>[] do m1:=List(k,x->List(x,y->Position(eff,y)-1)*m/p); m:=Concatenation(m,m1); m:=LatticeBasis(m); k:=NullspaceMat(m*Z(p)^0); od; od; return List(m,x->List([1..d1],y->x{[(y-1)*d2+1..y*d2]})); end; TransformationMat:= function(l1,l2) local d1,d2,l,m,p,i,j; if ValueOption("SaveSpace")=true or ValueOption("savespace")=true then return TransformationMatSaveSpace(l1,l2); fi; d1:=Length(l1[1]); d2:=Length(l2[1]); l:=Length(l1); m:=[]; for i in [1..d1] do for j in [1..d2] do p:=NullMat(d1,d2); p[i][j]:=1; Add(m,Flat(List([1..l],x->l1[x]*p-p*l2[x]))); od; od; p:=NullspaceIntMat(m); return List(p,x->List([1..d1],y->x{[(y-1)*d2+1..y*d2]})); end; StablyPermutationCheckHP:= function(g,hh,c1,c2) local gg,l,m,m1,m2,tm,d1,d2,s1,s2,i,j,k; gg:=List(hh,x->CosetRepresentation(g,x)); Add(gg,GeneratorsOfGroup(g)); l:=List([1..Length(gg)],x->Length(gg[x][1])); d1:=Sum([1..Length(gg)],x->c1[x]*l[x]); d2:=Sum([1..Length(gg)],x->c2[x]*l[x]); m:=[]; s1:=0; for i in [1..Length(gg)] do if c1[i]>0 then m1:=[]; s2:=0; for j in [1..Length(gg)] do if c2[j]>0 then tm:=TransformationMat(gg[i],gg[j]); for k in [1..c2[j]] do m2:=List(tm,x->TransposedMat(Concatenation( [NullMat(s2,l[i]),TransposedMat(x), NullMat(d2-s2-l[j],l[i])]))); m1:=Concatenation(m1,m2); s2:=s2+l[j]; od; fi; od; m1:=LatticeBasis(List(m1,Flat)); m1:=List(m1,x->List([1..l[i]],y->x{[(y-1)*s2+1..y*s2]})); for k in [1..c1[i]] do m:=Concatenation(m,List(m1,x->Concatenation( [NullMat(s1,d2),x,NullMat(d1-s1-l[i],d2)]))); s1:=s1+l[i]; od; fi; od; return m; end; StablyPermutationMCheckP:= function(g,c1,c2) local h; h:=List(ConjugacyClassesSubgroups2(g),Representative); return StablyPermutationCheckHP(g,h,c1,c2); end; StablyPermutationFCheckP:= function(g,c1,c2) local tg,gg,d,th,mi,ms,o,h,r,gg1,gg2,g2,iso,ker,tg2,th2,h2,m1,m2,v; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return true; else ms:=NullspaceIntMat(mi); v:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); g2:=TransposedMatrixGroup(tg2); h2:=List(th2,TransposedMatrixGroup); return StablyPermutationCheckHP(g2,h2,c1,c2); fi; end; StablyPermutationCheckHMat:= function(g,hh,c1,c2,p) local gg,g1,g2,dx,m,i,j,d; gg:=List(hh,x->CosetRepresentation(g,x)); Add(gg,GeneratorsOfGroup(g)); g1:=[]; g2:=[]; for i in [1..Length(gg[1])] do m:=[]; for j in [1..Length(gg)] do m:=Concatenation(m,List([1..c1[j]],x->gg[j][i])); od; Add(g1,DirectSumMat(m)); m:=[]; for j in [1..Length(gg)] do m:=Concatenation(m,List([1..c2[j]],x->gg[j][i])); od; Add(g2,DirectSumMat(m)); od; d:=Length(g1[1]); if d<>Length(g2[1]) or d<>Length(p) or DeterminantMat(p)^2<>1 then return fail; else return List(g1,x->x^p)=g2; fi; end; StablyPermutationMCheckMat:= function(g,c1,c2,p) local h; h:=List(ConjugacyClassesSubgroups2(g),Representative); return StablyPermutationCheckHMat(g,h,c1,c2,p); end; StablyPermutationFCheckMat:= function(g,c1,c2,p) local tg,gg,d,th,mi,ms,o,h,r,gg1,gg2,g2,iso,ker,tg2,th2,h2,m1,m2,v; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return true; else ms:=NullspaceIntMat(mi); v:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); g2:=TransposedMatrixGroup(tg2); h2:=List(th2,TransposedMatrixGroup); return StablyPermutationCheckHMat(g2,h2,c1,c2,p); fi; end; StablyPermutationCheckHGen:= function(g,hh,c1,c2) local gg,g1,g2,dx,m,i,j; gg:=List(hh,x->CosetRepresentation(g,x)); Add(gg,GeneratorsOfGroup(g)); g1:=[]; g2:=[]; for i in [1..Length(gg[1])] do m:=[]; for j in [1..Length(gg)] do m:=Concatenation(m,List([1..c1[j]],x->gg[j][i])); od; Add(g1,DirectSumMat(m)); m:=[]; for j in [1..Length(gg)] do m:=Concatenation(m,List([1..c2[j]],x->gg[j][i])); od; Add(g2,DirectSumMat(m)); od; return [g1,g2]; end; StablyPermutationMCheckGen:= function(g,c1,c2) local h; h:=List(ConjugacyClassesSubgroups2(g),Representative); return StablyPermutationCheckHGen(g,h,c1,c2); end; StablyPermutationFCheckGen:= function(g,c1,c2) local tg,gg,d,th,mi,ms,o,h,r,gg1,gg2,g2,iso,ker,tg2,th2,h2,m1,m2,v; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return true; else ms:=NullspaceIntMat(mi); v:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); g2:=TransposedMatrixGroup(tg2); h2:=List(th2,TransposedMatrixGroup); return StablyPermutationCheckHGen(g2,h2,c1,c2); fi; end; CheckCoflabbyResolutionBaseH:= function(g,hh,mi) local z0; z0:=List(hh,Z0lattice); return ForAll([1..Length(hh)],i->LatticeBasis(List(OrbitsDomain(hh[i],mi),Sum))=z0[i]); end; CheckCoflabbyResolutionBase:= function(g,mi) local hh,z0; hh:=List(ConjugacyClassesSubgroups2(g),Representative); return CheckCoflabbyResolutionBaseH(g,hh,mi); end; SearchCoflabbyResolutionBaseH:= function(g,hh,b) local z0,orbs,imgs,i,j,mi,mis; mis:=[]; z0:=List(hh,Z0lattice); orbs:=Set(Union(z0),x->Orbit(g,x)); imgs:=List(orbs,x->List(hh,y->LatticeBasis(List(OrbitsDomain(y,x),Sum)))); if b=0 then for i in [1..Length(orbs)] do for j in Combinations([1..Length(orbs)],i) do if ForAll([1..Length(hh)],x->LatticeBasis( Union(List(j,y->imgs[y][x])))=z0[x]) then mi:=Union(List(j,x->orbs[x])); if mis=[] or Length(mi)[] then if ValueOption("info")=true then return [mis,i]; else return mis; fi; fi; od; else for i in [1..b] do for j in Combinations([1..Length(orbs)],i) do if ForAll([1..Length(hh)],x->LatticeBasis( Union(List(j,y->imgs[y][x])))=z0[x]) then mi:=Union(List(j,x->orbs[x])); Add(mis,mi); fi; od; od; return Set(mis); fi; end; SearchCoflabbyResolutionBaseLowRankH:= function(g,hh,b) local z0,orbs,imgs,lens,i,l,rk,mi,mis; mis:=[]; z0:=List(hh,Z0lattice); orbs:=Set(Union(z0),x->Orbit(g,x)); orbs:=OrbitsDomain(g,Union(orbs)); imgs:=List(orbs,x->List(hh,y->LatticeBasis(List(OrbitsDomain(y,x),Sum)))); lens:=List(orbs,Length); if b=0 then i:=Rank(Identity(g)); while true do l:=[1]; while l<>[] do if l[Length(l)]>Length(orbs) then l:=l{[1..Length(l)-1]}; if l<>[] then l[Length(l)]:=l[Length(l)]+1; fi; else rk:=Sum(l,x->lens[x]); if rk>i then l[Length(l)]:=l[Length(l)]+1; else if rk=i and ForAll([1..Length(hh)],x->LatticeBasis( Union(List(l,y->imgs[y][x])))=z0[x]) then mi:=Union(List(l,x->orbs[x])); return mi; fi; l:=Concatenation(l,[l[Length(l)]+1]); fi; fi; od; i:=i+1; od; else l:=[1]; while l<>[] do if l[Length(l)]>Length(orbs) then l:=l{[1..Length(l)-1]}; if l<>[] then l[Length(l)]:=l[Length(l)]+1; fi; else rk:=Sum(l,x->lens[x]); if rk>b then l[Length(l)]:=l[Length(l)]+1; else if rk>=Rank(Identity(g)) and ForAll([1..Length(hh)],x->LatticeBasis( Union(List(l,y->imgs[y][x])))=z0[x]) then mi:=Union(List(l,x->orbs[x])); Add(mis,mi); fi; l:=Concatenation(l,[l[Length(l)]+1]); fi; fi; od; return Set(mis); fi; end; ConjugacyClassesSubgroups2FromGroup:= function(g,G) local Gs,hom; Gs:=List(ConjugacyClassesSubgroups2(G),Representative); hom:=GroupHomomorphismByImages(G,g,GeneratorsOfGroup(G),GeneratorsOfGroup(g)); return List(Gs,x->Image(hom,x)); end; ConjugacyClassesSubgroups2FromTransposedIsomorphicGroup:= function(g,G) local Gs,hom; Gs:=List(ConjugacyClassesSubgroups2(G),Representative); hom:=GroupHomomorphismByImages(G,g,GeneratorsOfGroup(G),List(GeneratorsOfGroup(g),x->x^-1)); return List(Gs,x->Image(hom,x)); end; SearchCoflabbyResolutionBase:= function(g,b) local hh; hh:=List(ConjugacyClassesSubgroups2(g),Representative); return SearchCoflabbyResolutionBaseH(g,hh,b); end; SearchCoflabbyResolutionBaseLowRank:= function(g,b) local hh; hh:=List(ConjugacyClassesSubgroups2(g),Representative); return SearchCoflabbyResolutionBaseLowRankH(g,hh,b); end; SearchCoflabbyResolutionBaseTr:= function(M,T,b) local tM,hh; tM:=TransposedMatrixGroup(M); hh:=ConjugacyClassesSubgroups2FromTransposedIsomorphicGroup(tM,T); return SearchCoflabbyResolutionBaseH(tM,hh,b); end; SearchCoflabbyResolutionBaseLowRankTr:= function(M,T,b) local tM,hh; tM:=TransposedMatrixGroup(M); hh:=ConjugacyClassesSubgroups2FromTransposedIsomorphicGroup(tM,T); return SearchCoflabbyResolutionBaseLowRankH(tM,hh,b); end; FlabbyResolutionFromBase:= function(g,mi) local tg,gg,d,th,ms,o,r,gg1,gg2,v1,mg,img; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); r:=Length(mi); o:=IdentityMat(r); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return rec(injection:=TransposedMat(mi), surjection:=NullMat(r,0), actionP:=TransposedMatrixGroup(Group(gg1,o)) ); else ms:=NullspaceIntMat(mi); v1:=NullspaceIntMat(TransposedMat(ms)); mg:=Concatenation(v1,ms); img:=mg^-1; gg2:=List(gg1,x->mg*x*img); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); return rec(injection:=TransposedMat(mi), surjection:=TransposedMat(ms), actionP:=TransposedMatrixGroup(Group(gg1)), actionF:=TransposedMatrixGroup(Group(gg2)) ); fi; end; FlabbyResolutionLowRank:= function(g) local mi; mi:=SearchCoflabbyResolutionBaseLowRank(TransposedMatrixGroup(g),0); return FlabbyResolutionFromBase(g,mi); end; FlabbyResolutionLowRankFromGroup:= function(g,T) local mi; mi:=SearchCoflabbyResolutionBaseLowRankTr(g,T,0); return FlabbyResolutionFromBase(g,mi); end; IsInvertibleFLowRank:= function(g) local tg,gg,d,th,mi,mi2,ms,z0,ll,h,r,i,j,k,gg1,gg2,g1,g2,oo,iso,ker,tg2,th2,h2,l1,l2,v1,m1,m2; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); if ValueOption("fromperm")=true or ValueOption("FromPerm")=true then th:=ConjugacyClassesSubgroupsFromPerm(tg); else th:=List(ConjugacyClassesSubgroups2(tg),Representative); fi; mi:=SearchCoflabbyResolutionBaseLowRankH(tg,th,0); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return true; else ms:=NullspaceIntMat(mi); v1:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v1,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); for h in th2 do if Product(Hminus1(h))>1 then return false; fi; od; for h in th do if Product(Hminus1(h))>1 then d:=r-d; mi:=FindCoflabbyResolutionBase(tg2,th2); r:=Length(mi); gg1:=List(gg2,x->Permutation(x,mi)); gg2:=List(gg2,TransposedMat); g2:=Group(gg2); gg1:=List(gg1,x->x^-1); g1:=Group(gg1); mi:=TransposedMat(mi); iso:=GroupHomomorphismByImagesNC(g1,g2,gg1,gg2); oo:=OrbitsDomain(g1,[1..r]); m1:=[]; for i in oo do h:=Stabilizer(g1,i[1]); ll:=List(RightCosetsNC(g1,h),Representative); l1:=List(ll,x->i[1]^x); l2:=List(ll,x->Image(iso,x)); z0:=Z0lattice(Image(iso,h)); for j in z0 do m2:=NullMat(r,d); for k in [1..Length(ll)] do m2[l1[k]]:=j*l2[k]; od; Add(m1,Flat(mi*m2)); od; od; m2:=Concatenation(m1,[Flat(IdentityMat(d))]); m1:=NullspaceIntMat(m2); return Gcd(TransposedMat(m1)[Length(m2)])=1; fi; od; gg1:=List(gg,x->Permutation(x,mi)); gg:=GeneratorsOfGroup(g); gg1:=List(gg1,x->x^-1); g1:=Group(gg1); mi:=TransposedMat(mi); iso:=GroupHomomorphismByImagesNC(g1,g,gg1,gg); oo:=OrbitsDomain(g1,[1..r]); m1:=[]; for i in oo do h:=Stabilizer(g1,i[1]); ll:=List(RightCosetsNC(g1,h),Representative); l1:=List(ll,x->i[1]^x); l2:=List(ll,x->Image(iso,x)); z0:=Z0lattice(Image(iso,h)); for j in z0 do m2:=NullMat(r,d); for k in [1..Length(ll)] do m2[l1[k]]:=j*l2[k]; od; Add(m1,Flat(mi*m2)); od; od; m2:=Concatenation(m1,[Flat(IdentityMat(d))]); m1:=NullspaceIntMat(m2); return Gcd(TransposedMat(m1)[Length(m2)])=1; fi; end; IsInvertible:= function(g) local tg,gg,d,th,mi,mi2,ms,z0,ll,h,r,i,j,k,gg1,gg2,g1,g2,oo,iso,ker,tg2,th2,h2,l1,l2,v1,m1,m2; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); if gg=[] then return true; fi; d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); for h in th do if Product(Hminus1(h))>1 then return false; fi; od; gg1:=List(gg,x->Permutation(x,mi)); gg:=GeneratorsOfGroup(g); gg1:=List(gg1,x->x^-1); g1:=Group(gg1); mi:=TransposedMat(mi); iso:=GroupHomomorphismByImagesNC(g1,g,gg1,gg); oo:=OrbitsDomain(g1,[1..r]); m1:=[]; for i in oo do h:=Stabilizer(g1,i[1]); ll:=List(RightCosetsNC(g1,h),Representative); l1:=List(ll,x->i[1]^x); l2:=List(ll,x->Image(iso,x)); z0:=Z0lattice(Image(iso,h)); for j in z0 do m2:=NullMat(r,d); for k in [1..Length(ll)] do m2[l1[k]]:=j*l2[k]; od; Add(m1,Flat(mi*m2)); od; od; m2:=Concatenation(m1,[Flat(IdentityMat(d))]); m1:=NullspaceIntMat(m2); return Gcd(TransposedMat(m1)[Length(m2)])=1; end; IsInvertibleFFromBase:= function(g,mi) local tg,gg,d,th,mi2,ms,z0,ll,h,r,i,j,k,gg1,gg2,g1,g2,oo,iso,ker,tg2,th2,h2,l1,l2,v1,m1,m2; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return true; else ms:=NullspaceIntMat(mi); v1:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v1,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); for h in th2 do if Product(Hminus1(h))>1 then return false; fi; od; for h in th do if Product(Hminus1(h))>1 then d:=r-d; mi:=FindCoflabbyResolutionBase(tg2,th2); r:=Length(mi); gg1:=List(gg2,x->Permutation(x,mi)); gg2:=List(gg2,TransposedMat); g2:=Group(gg2); gg1:=List(gg1,x->x^-1); g1:=Group(gg1); mi:=TransposedMat(mi); iso:=GroupHomomorphismByImagesNC(g1,g2,gg1,gg2); oo:=OrbitsDomain(g1,[1..r]); m1:=[]; for i in oo do h:=Stabilizer(g1,i[1]); ll:=List(RightCosetsNC(g1,h),Representative); l1:=List(ll,x->i[1]^x); l2:=List(ll,x->Image(iso,x)); z0:=Z0lattice(Image(iso,h)); for j in z0 do m2:=NullMat(r,d); for k in [1..Length(ll)] do m2[l1[k]]:=j*l2[k]; od; Add(m1,Flat(mi*m2)); od; od; m2:=Concatenation(m1,[Flat(IdentityMat(d))]); m1:=NullspaceIntMat(m2); return Gcd(TransposedMat(m1)[Length(m2)])=1; fi; od; gg1:=List(gg,x->Permutation(x,mi)); gg:=GeneratorsOfGroup(g); gg1:=List(gg1,x->x^-1); g1:=Group(gg1); mi:=TransposedMat(mi); iso:=GroupHomomorphismByImagesNC(g1,g,gg1,gg); oo:=OrbitsDomain(g1,[1..r]); m1:=[]; for i in oo do h:=Stabilizer(g1,i[1]); ll:=List(RightCosetsNC(g1,h),Representative); l1:=List(ll,x->i[1]^x); l2:=List(ll,x->Image(iso,x)); z0:=Z0lattice(Image(iso,h)); for j in z0 do m2:=NullMat(r,d); for k in [1..Length(ll)] do m2[l1[k]]:=j*l2[k]; od; Add(m1,Flat(mi*m2)); od; od; m2:=Concatenation(m1,[Flat(IdentityMat(d))]); m1:=NullspaceIntMat(m2); return Gcd(TransposedMat(m1)[Length(m2)])=1; fi; end; PossibilityOfStablyPermutationFFromBase:= function(g,mi) local tg,gg,d,th,ms,r,gg1,gg2,g2,iso,ker,tg2,th2,h2,m1,m2,v; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return [0,1]; else ms:=NullspaceIntMat(mi); v:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); g2:=TransposedMatrixGroup(tg2); h2:=List(th2,TransposedMatrixGroup); return PossibilityOfStablyPermutationH(g2,h2); fi; end; StablyPermutationFCheckFromBase:= function(g,mi,c1,c2) local tg,gg,d,th,ms,o,h,r,gg1,gg2,g2,iso,ker,tg2,th2,h2,m1,m2,v; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return true; else ms:=NullspaceIntMat(mi); v:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); g2:=TransposedMatrixGroup(tg2); h2:=List(th2,TransposedMatrixGroup); return StablyPermutationCheckH(g2,h2,c1,c2); fi; end; StablyPermutationFCheckPFromBase:= function(g,mi,c1,c2) local tg,gg,d,th,ms,o,h,r,gg1,gg2,g2,iso,ker,tg2,th2,h2,m1,m2,v; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return true; else ms:=NullspaceIntMat(mi); v:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); g2:=TransposedMatrixGroup(tg2); h2:=List(th2,TransposedMatrixGroup); return StablyPermutationCheckHP(g2,h2,c1,c2); fi; end; StablyPermutationFCheckMatFromBase:= function(g,mi,c1,c2,p) local tg,gg,d,th,ms,o,h,r,gg1,gg2,g2,iso,ker,tg2,th2,h2,m1,m2,v; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return true; else ms:=NullspaceIntMat(mi); v:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); g2:=TransposedMatrixGroup(tg2); h2:=List(th2,TransposedMatrixGroup); return StablyPermutationCheckHMat(g2,h2,c1,c2,p); fi; end; StablyPermutationFCheckGenFromBase:= function(g,mi,c1,c2) local tg,gg,d,th,ms,o,h,r,gg1,gg2,g2,iso,ker,tg2,th2,h2,m1,m2,v; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=List(ConjugacyClassesSubgroups2(tg),Representative); r:=Length(mi); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return true; else ms:=NullspaceIntMat(mi); v:=NullspaceIntMat(TransposedMat(ms)); m1:=Concatenation(v,ms); m2:=m1^-1; gg2:=List(gg1,x->m1*x*m2); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); tg2:=Group(gg2); iso:=GroupHomomorphismByImages(tg,tg2,gg,gg2); ker:=Kernel(iso); th2:=List(Filtered(th,x->IsSubgroup(x,ker)),x->Image(iso,x)); g2:=TransposedMatrixGroup(tg2); h2:=List(th2,TransposedMatrixGroup); return StablyPermutationCheckHGen(g2,h2,c1,c2); fi; end; Norm1TorusJ :=function(d,n) local I,M1,M2,M,f,Sn,T; I:=IdentityMat(d-1); Sn:=SymmetricGroup(d); T:=TransitiveGroup(d,n); M1:=Concatenation(List([2..d-1],x->I[x]),[-List([1..d-1],One)]); if d=2 then M:=[M1]; else M2:=Concatenation([I[2],I[1]],List([3..d-1],x->I[x])); M:=[M1,M2]; fi; f:=GroupHomomorphismByImages(Sn,Group(M),GeneratorsOfGroup(Sn),M); return Image(f,T); end; DirectSumMatrixGroup:= function(l) local gg,gg1; gg:=List(l,GeneratorsOfGroup); if Length(Set(gg,Length))>1 then return fail; else gg1:=List([1..Length(gg[1])],x->DirectSumMat(List(gg,y->y[x]))); fi; return Group(gg1,DirectSumMat(List(l,Identity))); end; DirectProductMatrixGroup:= function(l) local gg,gg1,o,o1,i,j,gx; gg:=List(l,GeneratorsOfGroup); gg1:=[]; for i in [1..Length(l)] do o:=List(l,Identity); for j in gg[i] do o[i]:=j; Add(gg1,DirectSumMat(o)); od; od; return Group(gg1,DirectSumMat(List(l,Identity))); end; FlabbyResolutionFromPerm:= function(g) local tg,gg,d,th,mi,ms,o,r,gg1,gg2,v1,mg,img; tg:=TransposedMatrixGroup(g); gg:=GeneratorsOfGroup(tg); d:=Length(Identity(g)); th:=ConjugacyClassesSubgroupsFromPerm(tg); mi:=FindCoflabbyResolutionBase(tg,th); r:=Length(mi); o:=IdentityMat(r); gg1:=List(gg,x->PermutationMat(Permutation(x,mi),r)); if r=d then return rec(injection:=TransposedMat(mi), surjection:=NullMat(r,0), actionP:=TransposedMatrixGroup(Group(gg1,o)), actionF:=[] ); else ms:=NullspaceIntMat(mi); v1:=NullspaceIntMat(TransposedMat(ms)); mg:=Concatenation(v1,ms); img:=mg^-1; gg2:=List(gg1,x->mg*x*img); gg2:=List(gg2,x->x{[d+1..r]}{[d+1..r]}); return rec(injection:=TransposedMat(mi), surjection:=TransposedMat(ms), actionP:=TransposedMatrixGroup(Group(gg1)), actionF:=TransposedMatrixGroup(Group(gg2)) ); fi; end; NormalSubgroups2:= function(g) Reset(GlobalMersenneTwister); Reset(GlobalRandomSource); return NormalSubgroups(g); end; DoubleCosets2:= function(g,u,v) Reset(GlobalMersenneTwister); Reset(GlobalRandomSource); return DoubleCosets(g,u,v); end; ChangeLast:= function(l,c) local ans; ans:=List([1..Length(l)-1],x->l[x]); Add(ans,c*l[Length(l)]); return ans; end; LHSlist:= function(l) if l[Length(l)]>=0 then return List(l,x->Maximum([x,0])); else return List(l,x->Maximum([-x,0])); fi; end; RHSlist:= function(l) return LHSlist(ChangeLast(l,-1)); end; EndomorphismRingBasis:= function(G) local gg; gg:=GeneratorsOfGroup(G); return TransformationMat(gg,gg); end; IsCodimJacobsonEnd1:= function(G,p) local d,eb,zero,e1,e2,R,c,i,j; d:=Length(Identity(G)); eb:=EndomorphismRingBasis(G); zero:=NullMat(d,d,Integers); if d mod p>0 then e1:=Filtered(eb,x->Trace(x) mod p=0); e2:=Difference(eb,e1); R:=Concatenation(e1,List([1..Length(e2)-1], x->Trace(e2[x+1])*e2[x]-Trace(e2[x])*e2[x+1])); else e1:=Filtered(eb,x->x^d mod p=zero); e2:=Difference(eb,e1); R:=Difference(eb,e2); for i in [1..Length(e2)-1] do for j in [1..p-1] do if (e2[i]+j*e2[i+1])^d mod p=zero then Add(R,e2[i]+j*e2[i+1]); fi; od; od; if Length(R)zero then return false; fi; od; return true; end; IdempotentsModp:= function(e,p) local d,i,P,ans; d:=Length(e); ans:=[]; for i in Tuples([0..p-1],d) do P:=i*e mod p; if P^2 mod p=P then Add(ans,P); fi; od; return ans; end; chooseCyclic:= function(G) local Gc,Gcr,tf,i,j; Gc:=ConjugacyClasses(G); Gcr:=List(Gc,Representative); tf:=List(Gcr,x->Order(x)>1); while ForAny(tf,x->x=false) do Gc:=List(Filtered([1..Length(tf)],x->tf[x]=true),y->Gc[y]); Gcr:=List(Filtered([1..Length(tf)],x->tf[x]=true),y->Gcr[y]); tf:=Filtered(tf,x->x=true); for i in [1..Length(Gc)-1] do if tf[i]=true then for j in [i+1..Length(Gc)] do if tf[j]=true then if Order(Gcr[i]) mod Order(Gcr[j])=0 then if ForAny(Group(Gcr[i]^(Order(Gcr[i])/Order(Gcr[j]))),x->x in Gc[j]) then tf[j]:=false; fi; elif Order(Gcr[j]) mod Order(Gcr[i])=0 then if ForAny(Group(Gcr[j]^(Order(Gcr[j])/Order(Gcr[i]))),x->x in Gc[i]) then tf[i]:=false; break; fi; fi; fi; od; fi; od; od; return List(Gcr,Group); end; Sha1Omega:= function(g) local m,gg,i,c,s,h1,h1g,sha1,cc,mc,sc,h1c,h1cg,im,f; m:=[]; gg:=GeneratorsOfGroup(g); if gg=[] then return []; else for i in gg do m:=Concatenation(m,TransposedMat(i)-Identity(g)); od; m:=TransposedMat(m); s:=SmithNormalFormIntegerMatTransforms(m); h1:=AbelianGroup(List([1..s.rank],x->s.normal[x][x])); if Order(h1)=1 then return []; fi; h1g:=GeneratorsOfGroup(h1); sha1:=h1; cc:=chooseCyclic(g); for c in cc do mc:=c.1-Identity(c); mc:=s.rowtrans*mc; sc:=SmithNormalFormIntegerMatTransforms(mc); h1c:=AbelianGroup(List([1..sc.rank],x->sc.normal[x][x])); if Order(h1c)>1 then h1cg:=GeneratorsOfGroup(h1c); im:=List([1..s.rank],x->mc[x]/s.normal[x][x]*sc.coltrans); im:=List(im,x->Product(List([1..sc.rank],y->h1cg[y]^x[y]))); f:=GroupHomomorphismByImages(h1,h1c,h1g,im); sha1:=Intersection(sha1,Kernel(f)); if Order(sha1)=1 then return []; fi; fi; od; return AbelianInvariants(sha1); fi; end; Sha1OmegaTr:= function(g) return Sha1Omega(TransposedMatrixGroup(g)); end; ShaOmega:= function(g,n) local iso,gp,Rgp,MNS,d1,d2,ij,mij,i,j,k,l,m,mgp,s,hn,hng,Shan,cc,c,Rc,dc1,dc2,mc,sc,hnc,hncg,emb,res,id,c1,l1,l2,mres,im,f; iso:=IsomorphismPermGroup(g); gp:=Image(iso); if IsNilpotentGroup(gp) then Rgp:=ResolutionNormalSeries(LowerCentralSeries(gp),n+1); elif IsSolvable(gp) then Rgp:=ResolutionNormalSeries(DerivedSeries(gp),n+1); else MNS:=MaximalNormalSeries(gp); if Length(MNS)>2 then Rgp:=ResolutionNormalSeries(MNS,n+1); else Rgp:=ResolutionFiniteGroup(gp,n+1); fi; fi; d1:=Rgp!.dimension(n-1); d2:=Rgp!.dimension(n); ij:=[]; mij:=[]; for j in [1..d2] do for l in Rgp!.boundary(n,j) do i:=AbsInt(l[1]); m:=SignInt(l[1])*PreImage(iso,Rgp!.elts[l[2]]^-1); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(mij,m); else mij[k]:=mij[k]+m; fi; od; od; mgp:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],mij[x]]),d1,d2); mgp:=MatrixByBlockMatrix(mgp); s:=SmithNormalFormIntegerMatTransforms(mgp); hn:=AbelianGroup(List([1..s.rank],x->s.normal[x][x])); if Order(hn)=1 then return []; fi; hng:=GeneratorsOfGroup(hn); Shan:=hn; cc:=chooseCyclic(gp); for c in cc do Rc:=ResolutionAbelianGroup(c,n); dc1:=Rc!.dimension(n-1); dc2:=Rc!.dimension(n); ij:=[]; mij:=[]; for j in [1..dc2] do for l in Rc!.boundary(n,j) do i:=AbsInt(l[1]); m:=SignInt(l[1])*PreImage(iso,Rc!.elts[l[2]]^-1); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(mij,m); else mij[k]:=mij[k]+m; fi; od; od; mc:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],mij[x]]),dc1,dc2); mc:=MatrixByBlockMatrix(mc); sc:=SmithNormalFormIntegerMatTransforms(mc); hnc:=AbelianGroup(List([1..sc.rank],x->sc.normal[x][x])); if Order(hnc)>1 then hncg:=GeneratorsOfGroup(hnc); emb:=GroupHomomorphismByFunction(c,gp,x->x); res:=EquivariantChainMap(Rc,Rgp,emb); id:=Position(Rgp!.elts,Identity(gp)); ij:=[]; mij:=[]; for j in [1..dc2] do for l in res!.mapping([[j,id]],n) do i:=AbsInt(l[1]); m:=SignInt(l[1])*PreImage(iso,Rgp!.elts[l[2]]^-1); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(mij,m); else mij[k]:=mij[k]+m; fi; od; od; mres:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],mij[x]]),d2,dc2); mres:=MatrixByBlockMatrix(mres); mres:=s.rowtrans*mgp*mres; im:=List([1..s.rank],x->mres[x]/s.normal[x][x]*sc.coltrans); im:=List(im,x->Product(List([1..sc.rank],y->hncg[y]^x[y]))); f:=GroupHomomorphismByImages(hn,hnc,hng,im); Shan:=Intersection(Shan,Kernel(f)); if Order(Shan)=1 then return []; fi; fi; od; return AbelianInvariants(Shan); end; ShaOmegaFromGroup:= function(g,n,G) local iso,hom,gp,Rgp,MNS,d1,d2,ij,mij,i,j,k,l,m,mgp,s,hn,hng,Shan,cc,c,Rc,dc1,dc2,mc,sc,hnc,hncg,emb,res,id,c1,l1,l2,mres,im,f; iso:=IsomorphismPermGroup(G); hom:=GroupHomomorphismByImages(G,g,GeneratorsOfGroup(G),GeneratorsOfGroup(g)); gp:=Image(iso); if IsNilpotentGroup(gp) then Rgp:=ResolutionNormalSeries(LowerCentralSeries(gp),n+1); elif IsSolvable(gp) then Rgp:=ResolutionNormalSeries(DerivedSeries(gp),n+1); else MNS:=MaximalNormalSeries(gp); if Length(MNS)>2 then Rgp:=ResolutionNormalSeries(MNS,n+1); else Rgp:=ResolutionFiniteGroup(gp,n+1); fi; fi; d1:=Rgp!.dimension(n-1); d2:=Rgp!.dimension(n); ij:=[]; mij:=[]; for j in [1..d2] do for l in Rgp!.boundary(n,j) do i:=AbsInt(l[1]); m:=SignInt(l[1])*Image(hom,PreImage(iso,Rgp!.elts[l[2]]^-1)); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(mij,m); else mij[k]:=mij[k]+m; fi; od; od; mgp:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],mij[x]]),d1,d2); mgp:=MatrixByBlockMatrix(mgp); s:=SmithNormalFormIntegerMatTransforms(mgp); hn:=AbelianGroup(List([1..s.rank],x->s.normal[x][x])); if Order(hn)=1 then return []; fi; hng:=GeneratorsOfGroup(hn); Shan:=hn; cc:=chooseCyclic(gp); for c in cc do Rc:=ResolutionAbelianGroup(c,n); dc1:=Rc!.dimension(n-1); dc2:=Rc!.dimension(n); ij:=[]; mij:=[]; for j in [1..dc2] do for l in Rc!.boundary(n,j) do i:=AbsInt(l[1]); m:=SignInt(l[1])*Image(hom,PreImage(iso,Rc!.elts[l[2]]^-1)); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(mij,m); else mij[k]:=mij[k]+m; fi; od; od; mc:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],mij[x]]),dc1,dc2); mc:=MatrixByBlockMatrix(mc); sc:=SmithNormalFormIntegerMatTransforms(mc); hnc:=AbelianGroup(List([1..sc.rank],x->sc.normal[x][x])); if Order(hnc)>1 then hncg:=GeneratorsOfGroup(hnc); emb:=GroupHomomorphismByFunction(c,gp,x->x); res:=EquivariantChainMap(Rc,Rgp,emb); id:=Position(Rgp!.elts,Identity(gp)); ij:=[]; mij:=[]; for j in [1..dc2] do for l in res!.mapping([[j,id]],n) do i:=AbsInt(l[1]); m:=SignInt(l[1])*Image(hom,PreImage(iso,Rgp!.elts[l[2]]^-1)); k:=Position(ij,[i,j]); if k=fail then Add(ij,[i,j]); Add(mij,m); else mij[k]:=mij[k]+m; fi; od; od; mres:=BlockMatrix(List([1..Length(ij)],x->[ij[x][1],ij[x][2],mij[x]]),d2,dc2); mres:=MatrixByBlockMatrix(mres); mres:=s.rowtrans*mgp*mres; im:=List([1..s.rank],x->mres[x]/s.normal[x][x]*sc.coltrans); im:=List(im,x->Product(List([1..sc.rank],y->hncg[y]^x[y]))); f:=GroupHomomorphismByImages(hn,hnc,hng,im); Shan:=Intersection(Shan,Kernel(f)); if Order(Shan)=1 then return []; fi; fi; od; return AbelianInvariants(Shan); end; OuterConjugateSubgroups:= function(N,H) local n,hc,hc1,hc2; n:=GeneratorsOfGroup(N); hc:=[]; hc1:=[H]; while hc1<>[] do Append(hc,hc1); hc2:=Flat(List(hc1,x->List(n,y->x^y))); hc1:=Difference(hc2,hc); od; return hc; end; AllSubdirectProducts:= function(G1,G2) local G1g,Ng1,Ng2,N1,N2,nn1,nn2,Nnn1,Nnn2,n,nn,nc,ans,n1,n2,epi1,epi2,iso,aut,cc1,cc2,c1,c2,d,dr,f; G1g:=GeneratorsOfGroup(G1); if Rank(Identity(G1))=1 then Ng1:=[[[-1]]]; else Ng1:=Unique(GeneratorsOfGroup(NormalizerInGLnZ(G1))); fi; if Rank(Identity(G2))=1 then Ng2:=[[[-1]]]; else Ng2:=Unique(GeneratorsOfGroup(NormalizerInGLnZ(G2))); fi; N1:=NormalSubgroups2(G1); nn1:=[]; Nnn1:=[]; while N1<>[] do n:=N1[1]; nn:=Unique(GeneratorsOfGroup(Normalizer(Group(Ng1),n))); Add(nn1,n); Add(Nnn1,nn); nc:=OuterConjugateSubgroups(Group(Ng1),n); N1:=Filtered(N1,x->not x in nc); od; N2:=NormalSubgroups2(G2); nn2:=[]; Nnn2:=[]; while N2<>[] do n:=N2[1]; nn:=Unique(GeneratorsOfGroup(Normalizer(Group(Ng2),n))); Add(nn2,n); Add(Nnn2,nn); nc:=OuterConjugateSubgroups(Group(Ng2),n); N2:=Filtered(N2,x->not x in nc); od; ans:=[]; for n1 in nn1 do epi1:=NaturalHomomorphismByNormalSubgroup(G1,n1); for n2 in nn2 do epi2:=NaturalHomomorphismByNormalSubgroup(G2,n2); iso:=IsomorphismGroups(Image(epi1),Image(epi2)); if iso<>fail then aut:=AutomorphismGroup(Image(epi2)); cc1:=List(Nnn1[Position(nn1,n1)],x->ConjugatorAutomorphism(G1,x)); c1:=Group(List(cc1,x->InducedAutomorphism(iso,InducedAutomorphism(epi1,x)))); cc2:=List(Nnn2[Position(nn2,n2)],x->ConjugatorAutomorphism(G2,x)); c2:=Group(List(cc2,x->InducedAutomorphism(epi2,x))); d:=DoubleCosets2(aut,c1,c2); dr:=List(d,Representative); for f in dr do Add(ans,SubdirectProduct(G1,G2,CompositionMapping(f,iso,epi1),epi2)); od; fi; od; od; return ans; end; InvF := function(G) local d,N,I,id; d:=Length(Identity(G)); N:=Union([N3,N4,N31]); I:=I4; if d<=2 then return 0; elif d<=4 then id:=CrystCatZClass(G); if id in N then return 2; elif id in I then return 1; else return 0; fi; else return fail; fi; end; IsInvariantNormalSubgroup := function(arg) local G,alpha,n,invnames,hh,a,epi,l,l1,l2,i,j,h,hn; G:=arg[1]; alpha:=arg[2]; n:=arg[3]; if Length(arg)=3 then invnames:=["TorusInvariants"]; else invnames:=arg[4]; fi; if Order(n)=1 then return true; fi; hh:=alpha.ConjugacyClassesSubgroups2; a:=List([1..Length(hh)],x->List(invnames,y->alpha.(y)[x])); epi:=NaturalHomomorphismByNormalSubgroup(G,n); l:=[1..Length(hh)]; l2:=List(hh,x->Image(epi,Representative(x))); while l<>[] do l1:=Filtered(l,x->IsConjugate(Image(epi),l2[l[1]],l2[x])); if Length(Set(l1,x->a[x]))>1 then return false; fi; l:=Difference(l,l1); od; return true; end; InvariantNormalSubgroups := function(arg) local G,alpha,invnames,nn; G:=arg[1]; alpha:=arg[2]; if Length(arg)=2 then invnames:=["TorusInvariants"]; else invnames:=arg[3]; fi; nn:=NormalSubgroups2(G); return Filtered(nn,x->IsInvariantNormalSubgroup(G,alpha,x,invnames)); end; MaximalInvariantNormalSubgroup := function(arg) local G,alpha,invnames,nn,ans,n; G:=arg[1]; alpha:=arg[2]; if Length(arg)=2 then invnames:=["WSEC"]; else invnames:=arg[3]; fi; nn:=NormalSubgroups2(G); ans:=TrivialSubgroup(G); for n in nn do if Order(n)>Order(ans) and IsSubgroup(n,ans) then if IsInvariantNormalSubgroup(G,alpha,n,invnames) then ans:=n; fi; fi; od; return ans; end; ConjugacyClassesSubgroups2overMaximalInvariantNormalSubgroup := function(arg) local G,alpha,invnames,hh,a,n,hs,inv,i,h; G:=arg[1]; alpha:=arg[2]; if Length(arg)=2 then invnames:=["WSEC"]; else invnames:=arg[3]; fi; hh:=alpha.ConjugacyClassesSubgroups2; a:=List([1..Length(hh)],x->List(invnames,y->alpha.(y)[x])); n:=MaximalInvariantNormalSubgroup(G,alpha,invnames); hs:=[]; inv:=[]; for i in [1..Length(hh)] do h:=Representative(hh[i]); if IsSubgroup(h,n) then Add(hs,hh[i]); Add(inv,[a[i],Index(G,h),Number(hh[i]),Index(G,Core(G,h))]); fi; od; return rec(ConjugacyClassesSubgroups2:=hs, Invariants:=inv); end; TorusInvariants := function(arg) local G,fl,F,flF,ans; G:=arg[1]; if Length(arg)=1 then fl:=FlabbyResolution(G); if not "actionF" in RecNames(fl) then F:=Group(List(GeneratorsOfGroup(G),x->[[1]]),[[1]]); else F:=fl.actionF; fi; else F:=arg[2]; fi; if Length(arg)<3 then flF:=flfl(G); else flF:=arg[3]; fi; ans:=[InvF(G)]; Add(ans,Filtered(H1(F),x->x>1)); Add(ans,Sha1OmegaTr(G)); Add(ans,Filtered(H1(flF),x->x>1)); return ans; end; TorusInvariantsHAP := function(arg) local G,fl,F,ans; G:=arg[1]; if Length(arg)=1 then fl:=FlabbyResolution(G); if not "actionF" in RecNames(fl) then F:=Group(List(GeneratorsOfGroup(G),x->[[1]]),[[1]]); else F:=fl.actionF; fi; else F:=arg[2]; fi; ans:=[InvF(G)]; Add(ans,Filtered(H1(F),x->x>1)); Add(ans,Sha1OmegaTr(G)); Add(ans,ShaOmegaFromGroup(F,2,G)); return ans; end; TorusInvariantsFromTable := function(G) local d,id,i; d:=Length(Identity(G)); if d<=2 then return [0,[],[],[]]; elif d<=4 then id:=CrystCatZClass(G); i:=Position(N3,id); if i<>fail then return TorusInvariantsN3[i]; fi; i:=Position(N31,id); if i<>fail then return TorusInvariantsN31[i]; fi; i:=Position(N4,id); if i<>fail then return TorusInvariantsN4[i]; fi; i:=Position(I4,id); if i<>fail then return TorusInvariantsI4[i]; fi; return [0,[],[],[]]; else return fail; fi; end; ConjugacyClassesSubgroups2TorusInvariants := function(G) local hh,ans; hh:=ConjugacyClassesSubgroups2(G); ans:=List(List(hh,Representative),TorusInvariantsFromTable); if fail in ans then return fail; else return rec(ConjugacyClassesSubgroups2:=hh, TorusInvariants:=ans); fi; end; ConjugacyClassesSubgroups2Invariants := function(arg) local G,invnames,primes,hh,i,inv,ans,ret; G:=arg[1]; invnames:=arg[2]; hh:=ConjugacyClassesSubgroups2(G); ret:=rec(ConjugacyClassesSubgroups2:=hh); for i in invnames do if i="TorusInvariants" then inv:=TorusInvariantsFromTable; else inv:=EvalString(i); fi; ans:=List(hh,x->inv(Representative(x))); if fail in ans then return fail; fi; ret.(i):=ans; od; return ret; end; PositionIn := function(list,elt) local i; for i in [1..Length(list)] do if elt in list[i] then return i; fi; od; return fail; end; IsInvariantSubdirectProduct := function(arg) local G1xG2,alpha1,alpha2,invnames,G1,G2,hh1,hh2,a1,a2,hh,h,i,h1,h2,i1,i2; G1xG2:=arg[1]; alpha1:=arg[2]; alpha2:=arg[3]; if Length(arg)=3 then invnames:=["TorusInvariants"]; else invnames:=arg[4]; fi; G1:=Image(Projection(G1xG2,1)); G2:=Image(Projection(G1xG2,2)); hh1:=alpha1.ConjugacyClassesSubgroups2; hh2:=alpha2.ConjugacyClassesSubgroups2; a1:=List([1..Length(hh1)],x->List(invnames,y->alpha1.(y)[x])); a2:=List([1..Length(hh2)],x->List(invnames,y->alpha2.(y)[x])); hh:=ConjugacyClassesSubgroups2(G1xG2); for i in [1..Length(hh)] do h:=Representative(hh[i]); h1:=Image(Projection(G1xG2,1),h); h2:=Image(Projection(G1xG2,2),h); i1:=PositionIn(List(hh1,Elements),h1); i2:=PositionIn(List(hh2,Elements),h2); if a1[i1]<>a2[i2] then return false; fi; od; return true; end; PossibilityOfStablyEquivalentSubdirectProducts := function(arg) local G1,G2,alpha1,alpha2,invnames,G1g,Ng1,Ng2,N1,N2,nn1,nn2,Nnn1,Nnn2,n,nn,nc,ans,n1,n2,epi1,epi2,iso,aut,cc1,cc2,c1,c2,d,dr,f,G1xG2; G1:=arg[1]; G2:=arg[2]; alpha1:=arg[3]; alpha2:=arg[4]; if Length(arg)=4 then invnames:=["TorusInvariants"]; else invnames:=arg[5]; fi; G1g:=GeneratorsOfGroup(G1); if Rank(Identity(G1))=1 then Ng1:=[[[-1]]]; else Ng1:=Unique(GeneratorsOfGroup(NormalizerInGLnZ(G1))); fi; if Rank(Identity(G2))=1 then Ng2:=[[[-1]]]; else Ng2:=Unique(GeneratorsOfGroup(NormalizerInGLnZ(G2))); fi; N1:=InvariantNormalSubgroups(G1,alpha1,invnames); nn1:=[]; Nnn1:=[]; while N1<>[] do n:=N1[1]; nn:=Unique(GeneratorsOfGroup(Normalizer(Group(Ng1),n))); Add(nn1,n); Add(Nnn1,nn); nc:=OuterConjugateSubgroups(Group(Ng1),n); N1:=Filtered(N1,x->not x in nc); od; N2:=InvariantNormalSubgroups(G2,alpha2,invnames); nn2:=[]; Nnn2:=[]; while N2<>[] do n:=N2[1]; nn:=Unique(GeneratorsOfGroup(Normalizer(Group(Ng2),n))); Add(nn2,n); Add(Nnn2,nn); nc:=OuterConjugateSubgroups(Group(Ng2),n); N2:=Filtered(N2,x->not x in nc); od; ans:=[]; for n1 in nn1 do epi1:=NaturalHomomorphismByNormalSubgroup(G1,n1); for n2 in nn2 do epi2:=NaturalHomomorphismByNormalSubgroup(G2,n2); iso:=IsomorphismGroups(Image(epi1),Image(epi2)); if iso<>fail then aut:=AutomorphismGroup(Image(epi2)); cc1:=List(Nnn1[Position(nn1,n1)],x->ConjugatorAutomorphism(G1,x)); c1:=Group(List(cc1,x->InducedAutomorphism(iso,InducedAutomorphism(epi1,x)))); cc2:=List(Nnn2[Position(nn2,n2)],x->ConjugatorAutomorphism(G2,x)); c2:=Group(List(cc2,x->InducedAutomorphism(epi2,x))); d:=DoubleCosets2(aut,c1,c2); dr:=List(d,Representative); for f in dr do G1xG2:=SubdirectProduct(G1,G2,CompositionMapping(f,iso,epi1),epi2); if IsInvariantSubdirectProduct(G1xG2,alpha1,alpha2,invnames) then Add(ans,G1xG2); fi; od; fi; od; od; return ans; end; PossibilityOfStablyEquivalentHSubdirectProduct:= function(g,hh) local gg,hg,hgg,hom,c,h,m,m1,m2,v,h1,h2,h01,h02,og,oh,p,e,IA,gp,ggp,R,gg1,gg2,tgg1,tgg2,A1,A2,TR1,TR2,h21,h22,h21h22,hp,hgp,hg1,hg2,thg1,thg2; gg:=GeneratorsOfGroup(g); hg:=List(hh,x->RightCosets(g,x)); hgg:=List(hg,x->List(gg,y->Permutation(y,x,OnRight))); hom:=List(hgg,x->GroupHomomorphismByImages(g,Group(x,()),gg,x)); c:=List(ConjugacyClasses(g),Representative); og:=Order(g); m:=List(c,x->List([1..Length(hh)],y->og/Order(hh[y])-NrMovedPoints(Image(hom[y],x)))); v:=List(c,x->Trace(Image(Projection(g,1),x))-Trace(Image(Projection(g,2),x))); for h in hh do h1:=Image(Projection(g,1),h); h2:=Image(Projection(g,2),h); oh:=Order(h); h01:=H0(h1)*(oh/Order(h1)); h02:=H0(h2)*(oh/Order(h2)); m1:=List([1..Length(hh)],x->List(OrbitLengths(Image(hom[x],h),[1..og/Order(hh[x])]),y->oh/y)); Add(m,List(m1,Length)); Add(v,Length(h01)-Length(h02)); if oh>1 then for p in Set(FactorsInt(oh)) do for e in [1..PadicValuation(oh,p)] do Add(m,List(m1,x->Number(x,y->PadicValuation(y,p)=e))); Add(v,Number(h01,x->PadicValuation(x,p)=e)-Number(h02,x->PadicValuation(x,p)=e)); od; od; fi; od; if ValueOption("H2")<>fail or ValueOption("h2")<>fail then if ValueOption("H2")="Tate" or ValueOption("h2")="Tate" then IA:=RegularActionHomomorphism(g); gp:=Image(IA); ggp:=List(gg,x->Image(IA,x)); R:=ResolutionFiniteGroup(gp,3); gg1:=List(gg,x->Image(Projection(g,1),x)); gg2:=List(gg,x->Image(Projection(g,2),x)); tgg1:=List(gg1,x->TransposedMat(x)^-1); tgg2:=List(gg2,x->TransposedMat(x)^-1); A1:=GroupHomomorphismByImages(gp,Group(tgg1),ggp,tgg1); A2:=GroupHomomorphismByImages(gp,Group(tgg2),ggp,tgg2); TR1:=HomToIntegralModule(R,A1); TR2:=HomToIntegralModule(R,A2); h21:=Cohomology(TR1,2); h22:=Cohomology(TR2,2); else h21h22:=HnSubdirectProduct(g,2); h21:=h21h22[1]; h22:=h21h22[2]; fi; m1:=List(hh,x->AbelianInvariants(x/DerivedSubgroup(x))); if og>1 then for p in Set(FactorsInt(og)) do for e in [1..PadicValuation(og,p)] do Add(m,List(m1,x->Number(x,y->PadicValuation(y,p)=e))); Add(v,Number(h21,x->PadicValuation(x,p)=e)-Number(h22,x->PadicValuation(x,p)=e)); od; od; fi; fi; if ValueOption("H2sub")<>fail or ValueOption("h2sub")<>fail then for h in hh do oh:=Order(h); if oh>1 then if ValueOption("H2sub")="Tate" or ValueOption("h2sub")="Tate" then IA:=RegularActionHomomorphism(h); hp:=Image(IA); hgp:=List(GeneratorsOfGroup(h),x->Image(IA,x)); R:=ResolutionFiniteGroup(hp,3); hg1:=List(GeneratorsOfGroup(h),x->Image(Projection(g,1),x)); hg2:=List(GeneratorsOfGroup(h),x->Image(Projection(g,2),x)); thg1:=List(hg1,x->TransposedMat(x)^-1); thg2:=List(hg2,x->TransposedMat(x)^-1); A1:=GroupHomomorphismByImages(hp,Group(thg1),ggp,tgg1); A2:=GroupHomomorphismByImages(hp,Group(thg2),ggp,tgg2); TR1:=HomToIntegralModule(R,A1); TR2:=HomToIntegralModule(R,A2); h21:=Cohomology(TR1,2); h22:=Cohomology(TR2,2); else h21h22:=HnsubSubdirectProduct(h,2,[Projection(g,1),Projection(g,2)]); h21:=h21h22[1]; h22:=h21h22[2]; fi; m1:=List([1..Length(hh)],x->List(OrbitsDomain(Image(hom[x],h),[1..og/Order(hh[x])]),y->Intersection(h,PreImage(hom[x],Stabilizer(Image(hom[x],h),y[1]))))); m1:=List([1..Length(hh)],x->Concatenation(List(m1[x],y->AbelianInvariants(y/DerivedSubgroup(y))))); for p in Set(FactorsInt(oh)) do for e in [1..PadicValuation(oh,p)] do Add(m,List(m1,x->Number(x,y->PadicValuation(y,p)=e))); Add(v,Number(h21,x->PadicValuation(x,p)=e)-Number(h22,x->PadicValuation(x,p)=e)); od; od; fi; od; fi; m:=TransposedMat(m); m:=Concatenation(m,[v]); return NullspaceIntMat(m); end; PossibilityOfStablyEquivalentMSubdirectProduct:= function(g) local hh; hh:=List(ConjugacyClassesSubgroups2(g),Representative); return PossibilityOfStablyEquivalentHSubdirectProduct(g,hh); end; PossibilityOfStablyEquivalentFSubdirectProduct:= function(arg) local g,hh,G1,G2,fl1,fl2,F1,F2,epi1,epi2,gg,hg,hgg,hom,c,h,m,m1,m2,v,h1,h2,h01,h02,og,oh,p,e,IA,gp,ggp,R,fg1,fg2,tfg1,tfg2,A1,A2,TR1,TR2,h21,h22,h21h22,hp,hgp; g:=arg[1]; hh:=List(ConjugacyClassesSubgroups2(g),Representative); G1:=Image(Projection(g,1)); G2:=Image(Projection(g,2)); if Length(arg)=1 then fl1:=FlabbyResolutionLowRank(G1); if not "actionF" in RecNames(fl1) then F1:=Group(List(GeneratorsOfGroup(G1),x->[[1]]),[[1]]); else F1:=fl1.actionF; fi; else F1:=arg[2]; fi; epi1:=GroupHomomorphismByImages(G1,F1,GeneratorsOfGroup(G1),GeneratorsOfGroup(F1)); if Length(arg)<3 then fl2:=FlabbyResolutionLowRank(G2); if not "actionF" in RecNames(fl2) then F2:=Group(List(GeneratorsOfGroup(G2),x->[[1]]),[[1]]); else F2:=fl2.actionF; fi; else F2:=arg[3]; fi; epi2:=GroupHomomorphismByImages(G2,F2,GeneratorsOfGroup(G2),GeneratorsOfGroup(F2)); gg:=GeneratorsOfGroup(g); hg:=List(hh,x->RightCosets(g,x)); hgg:=List(hg,x->List(gg,y->Permutation(y,x,OnRight))); hom:=List(hgg,x->GroupHomomorphismByImages(g,Group(x,()),gg,x)); c:=List(ConjugacyClasses(g),Representative); og:=Order(g); m:=List(c,x->List([1..Length(hh)],y->og/Order(hh[y])-NrMovedPoints(Image(hom[y],x)))); v:=List(c,x->Trace(Image(epi1,Image(Projection(g,1),x)))-Trace(Image(epi2,Image(Projection(g,2),x)))); for h in hh do h1:=Image(epi1,Image(Projection(g,1),h)); h2:=Image(epi2,Image(Projection(g,2),h)); oh:=Order(h); h01:=H0(h1)*(oh/Order(h1)); h02:=H0(h2)*(oh/Order(h2)); m1:=List([1..Length(hh)],x->List(OrbitLengths(Image(hom[x],h),[1..og/Order(hh[x])]),y->oh/y)); Add(m,List(m1,Length)); Add(v,Length(h01)-Length(h02)); if oh>1 then for p in Set(FactorsInt(oh)) do for e in [1..PadicValuation(oh,p)] do Add(m,List(m1,x->Number(x,y->PadicValuation(y,p)=e))); Add(v,Number(h01,x->PadicValuation(x,p)=e)-Number(h02,x->PadicValuation(x,p)=e)); od; od; fi; od; if ValueOption("H2")<>fail or ValueOption("h2")<>fail then if ValueOption("H2")="Tate" or ValueOption("h2")="Tate" then IA:=RegularActionHomomorphism(g); gp:=Image(IA); ggp:=List(gg,x->Image(IA,x)); R:=ResolutionFiniteGroup(gp,3); fg1:=List(gg,x->Image(epi1,Image(Projection(g,1),x))); fg2:=List(gg,x->Image(epi2,Image(Projection(g,2),x))); tfg1:=List(fg1,x->TransposedMat(x)^-1); tfg2:=List(fg2,x->TransposedMat(x)^-1); A1:=GroupHomomorphismByImages(gp,Group(tfg1),ggp,tfg1); A2:=GroupHomomorphismByImages(gp,Group(tfg2),ggp,tfg2); TR1:=HomToIntegralModule(R,A1); TR2:=HomToIntegralModule(R,A2); h21:=Cohomology(TR1,2); h22:=Cohomology(TR2,2); else h21h22:=HnSubdirectProductToHom(g,2,[epi1,epi2]); h21:=h21h22[1]; h22:=h21h22[2]; fi; m1:=List(hh,x->AbelianInvariants(x/DerivedSubgroup(x))); if og>1 then for p in Set(FactorsInt(og)) do for e in [1..PadicValuation(og,p)] do Add(m,List(m1,x->Number(x,y->PadicValuation(y,p)=e))); Add(v,Number(h21,x->PadicValuation(x,p)=e)-Number(h22,x->PadicValuation(x,p)=e)); od; od; fi; fi; if ValueOption("H2sub")<>fail or ValueOption("h2sub")<>fail then for h in hh do oh:=Order(h); if oh>1 then if ValueOption("H2sub")="Tate" or ValueOption("h2sub")="Tate" then IA:=RegularActionHomomorphism(h); hp:=Image(IA); hgp:=List(GeneratorsOfGroup(h),x->Image(IA,x)); R:=ResolutionFiniteGroup(hp,3); fg1:=List(GeneratorsOfGroup(h),x->Image(epi1,Image(Projection(g,1),x))); fg2:=List(GeneratorsOfGroup(h),x->Image(epi2,Image(Projection(g,2),x))); tfg1:=List(fg1,x->TransposedMat(x)^-1); tfg2:=List(fg2,x->TransposedMat(x)^-1); A1:=GroupHomomorphismByImages(hp,Group(tfg1),hgp,tfg1); A2:=GroupHomomorphismByImages(hp,Group(tfg2),hgp,tfg2); TR1:=HomToIntegralModule(R,A1); TR2:=HomToIntegralModule(R,A2); h21:=Cohomology(TR1,2); h22:=Cohomology(TR2,2); else h21h22:=HnsubSubdirectProductToHom(h,2,[Projection(g,1),Projection(g,2)],[epi1,epi2]); h21:=h21h22[1]; h22:=h21h22[2]; fi; m1:=List([1..Length(hh)],x->List(OrbitsDomain(Image(hom[x],h),[1..og/Order(hh[x])]),y->Intersection(h,PreImage(hom[x],Stabilizer(Image(hom[x],h),y[1]))))); m1:=List([1..Length(hh)],x->Concatenation(List(m1[x],y->AbelianInvariants(y/DerivedSubgroup(y))))); for p in Set(FactorsInt(oh)) do for e in [1..PadicValuation(oh,p)] do Add(m,List(m1,x->Number(x,y->PadicValuation(y,p)=e))); Add(v,Number(h21,x->PadicValuation(x,p)=e)-Number(h22,x->PadicValuation(x,p)=e)); od; od; fi; od; fi; m:=TransposedMat(m); m:=Concatenation(m,[v]); return NullspaceIntMat(m); end; StablyEquivalentCheckHPSubdirectProduct:= function(g,hh,c1,c2) local gg1,gg2,ll1,ll2,m,m1,m2,tm,d1,d2,s1,s2,i,j,k; gg1:=List(hh,x->CosetRepresentation(g,x)); gg2:=List(hh,x->CosetRepresentation(g,x)); Add(gg1,List(GeneratorsOfGroup(g),x->Image(Projection(g,1),x))); Add(gg2,List(GeneratorsOfGroup(g),x->Image(Projection(g,2),x))); ll1:=List([1..Length(gg1)],x->Length(gg1[x][1])); ll2:=List([1..Length(gg2)],x->Length(gg2[x][1])); d1:=Sum([1..Length(gg1)],x->c1[x]*ll1[x]); d2:=Sum([1..Length(gg2)],x->c2[x]*ll2[x]); m:=[]; s1:=0; for i in [1..Length(gg1)] do if c1[i]>0 then m1:=[]; s2:=0; for j in [1..Length(gg2)] do if c2[j]>0 then tm:=TransformationMat(gg1[i],gg2[j]); for k in [1..c2[j]] do m2:=List(tm,x->TransposedMat(Concatenation( [NullMat(s2,ll1[i]),TransposedMat(x), NullMat(d2-s2-ll2[j],ll1[i])]))); m1:=Concatenation(m1,m2); s2:=s2+ll2[j]; od; fi; od; m1:=LatticeBasis(List(m1,Flat)); m1:=List(m1,x->List([1..ll1[i]],y->x{[(y-1)*s2+1..y*s2]})); for k in [1..c1[i]] do m:=Concatenation(m,List(m1,x->Concatenation( [NullMat(s1,d2),x,NullMat(d1-s1-ll1[i],d2)]))); s1:=s1+ll1[i]; od; fi; od; return m; end; StablyEquivalentMCheckPSubdirectProduct:= function(g,c1,c2) local hh; hh:=List(ConjugacyClassesSubgroups2(g),Representative); return StablyEquivalentCheckHPSubdirectProduct(g,hh,c1,c2); end; StablyEquivalentFCheckPSubdirectProduct:= function(arg) local g,hh,c1,c2,G1,G2,fl1,fl2,F1,F2,epi1,epi2,gg1,gg2,ll1,ll2,m,m1,m2,tm,d1,d2,s1,s2,i,j,k; g:=arg[1]; hh:=List(ConjugacyClassesSubgroups2(g),Representative); c1:=arg[2]; c2:=arg[3]; G1:=Image(Projection(g,1)); G2:=Image(Projection(g,2)); if Length(arg)=3 then fl1:=FlabbyResolutionLowRank(G1); if not "actionF" in RecNames(fl1) then F1:=Group(List(GeneratorsOfGroup(G1),x->[[1]]),[[1]]); else F1:=fl1.actionF; fi; else F1:=arg[4]; fi; epi1:=GroupHomomorphismByImages(G1,F1,GeneratorsOfGroup(G1),GeneratorsOfGroup(F1)); if Length(arg)<5 then fl2:=FlabbyResolutionLowRank(G2); if not "actionF" in RecNames(fl2) then F2:=Group(List(GeneratorsOfGroup(G2),x->[[1]]),[[1]]); else F2:=fl2.actionF; fi; else F2:=arg[5]; fi; epi2:=GroupHomomorphismByImages(G2,F2,GeneratorsOfGroup(G2),GeneratorsOfGroup(F2)); gg1:=List(hh,x->CosetRepresentation(g,x)); gg2:=List(hh,x->CosetRepresentation(g,x)); Add(gg1,List(GeneratorsOfGroup(g),x->Image(epi1,Image(Projection(g,1),x)))); Add(gg2,List(GeneratorsOfGroup(g),x->Image(epi2,Image(Projection(g,2),x)))); ll1:=List([1..Length(gg1)],x->Length(gg1[x][1])); ll2:=List([1..Length(gg2)],x->Length(gg2[x][1])); d1:=Sum([1..Length(gg1)],x->c1[x]*ll1[x]); d2:=Sum([1..Length(gg2)],x->c2[x]*ll2[x]); m:=[]; s1:=0; for i in [1..Length(gg1)] do if c1[i]>0 then m1:=[]; s2:=0; for j in [1..Length(gg2)] do if c2[j]>0 then tm:=TransformationMat(gg1[i],gg2[j]); for k in [1..c2[j]] do m2:=List(tm,x->TransposedMat(Concatenation( [NullMat(s2,ll1[i]),TransposedMat(x), NullMat(d2-s2-ll2[j],ll1[i])]))); m1:=Concatenation(m1,m2); s2:=s2+ll2[j]; od; fi; od; m1:=LatticeBasis(List(m1,Flat)); m1:=List(m1,x->List([1..ll1[i]],y->x{[(y-1)*s2+1..y*s2]})); for k in [1..c1[i]] do m:=Concatenation(m,List(m1,x->Concatenation( [NullMat(s1,d2),x,NullMat(d1-s1-ll1[i],d2)]))); s1:=s1+ll1[i]; od; fi; od; return m; end; StablyEquivalentCheckHMatSubdirectProduct:= function(g,hh,c1,c2,p) local gg1,gg2,g1,g2,dx,m,i,j,d; gg1:=List(hh,x->CosetRepresentation(g,x)); gg2:=List(hh,x->CosetRepresentation(g,x)); Add(gg1,List(GeneratorsOfGroup(g),x->Image(Projection(g,1),x))); Add(gg2,List(GeneratorsOfGroup(g),x->Image(Projection(g,2),x))); g1:=[]; g2:=[]; for i in [1..Length(gg1[1])] do m:=[]; for j in [1..Length(gg1)] do m:=Concatenation(m,List([1..c1[j]],x->gg1[j][i])); od; Add(g1,DirectSumMat(m)); m:=[]; for j in [1..Length(gg2)] do m:=Concatenation(m,List([1..c2[j]],x->gg2[j][i])); od; Add(g2,DirectSumMat(m)); od; d:=Length(g1[1]); if d<>Length(g2[1]) or d<>Length(p) or DeterminantMat(p)^2<>1 then return fail; else return List(g1,x->x^p)=g2; fi; end; StablyEquivalentMCheckMatSubdirectProduct:= function(g,c1,c2,p) local hh; hh:=List(ConjugacyClassesSubgroups2(g),Representative); return StablyEquivalentCheckHMatSubdirectProduct(g,hh,c1,c2,p); end; StablyEquivalentFCheckMatSubdirectProduct:= function(arg) local g,hh,c1,c2,p,G1,G2,fl1,fl2,F1,F2,epi1,epi2,gg1,gg2,g1,g2,dx,m,i,j,d; g:=arg[1]; hh:=List(ConjugacyClassesSubgroups2(g),Representative); c1:=arg[2]; c2:=arg[3]; p:=arg[4]; G1:=Image(Projection(g,1)); G2:=Image(Projection(g,2)); if Length(arg)=4 then fl1:=FlabbyResolutionLowRank(G1); if not "actionF" in RecNames(fl1) then F1:=Group(List(GeneratorsOfGroup(G1),x->[[1]]),[[1]]); else F1:=fl1.actionF; fi; else F1:=arg[5]; fi; epi1:=GroupHomomorphismByImages(G1,F1,GeneratorsOfGroup(G1),GeneratorsOfGroup(F1)); if Length(arg)<6 then fl2:=FlabbyResolutionLowRank(G2); if not "actionF" in RecNames(fl2) then F2:=Group(List(GeneratorsOfGroup(G2),x->[[1]]),[[1]]); else F2:=fl2.actionF; fi; else F2:=arg[6]; fi; epi2:=GroupHomomorphismByImages(G2,F2,GeneratorsOfGroup(G2),GeneratorsOfGroup(F2)); gg1:=List(hh,x->CosetRepresentation(g,x)); gg2:=List(hh,x->CosetRepresentation(g,x)); Add(gg1,List(GeneratorsOfGroup(g),x->Image(epi1,Image(Projection(g,1),x)))); Add(gg2,List(GeneratorsOfGroup(g),x->Image(epi2,Image(Projection(g,2),x)))); g1:=[]; g2:=[]; for i in [1..Length(gg1[1])] do m:=[]; for j in [1..Length(gg1)] do m:=Concatenation(m,List([1..c1[j]],x->gg1[j][i])); od; Add(g1,DirectSumMat(m)); m:=[]; for j in [1..Length(gg2)] do m:=Concatenation(m,List([1..c2[j]],x->gg2[j][i])); od; Add(g2,DirectSumMat(m)); od; d:=Length(g1[1]); if d<>Length(g2[1]) or d<>Length(p) or DeterminantMat(p)^2<>1 then return fail; else return List(g1,x->x^p)=g2; fi; end; StablyEquivalentCheckHGenSubdirectProduct:= function(g,hh,c1,c2) local gg1,gg2,g1,g2,dx,m,i,j; gg1:=List(hh,x->CosetRepresentation(g,x)); gg2:=List(hh,x->CosetRepresentation(g,x)); Add(gg1,List(GeneratorsOfGroup(g),x->Image(Projection(g,1),x))); Add(gg2,List(GeneratorsOfGroup(g),x->Image(Projection(g,2),x))); g1:=[]; g2:=[]; for i in [1..Length(gg1[1])] do m:=[]; for j in [1..Length(gg1)] do m:=Concatenation(m,List([1..c1[j]],x->gg1[j][i])); od; Add(g1,DirectSumMat(m)); m:=[]; for j in [1..Length(gg2)] do m:=Concatenation(m,List([1..c2[j]],x->gg2[j][i])); od; Add(g2,DirectSumMat(m)); od; return [g1,g2]; end; StablyEquivalentMCheckGenSubdirectProduct:= function(g,c1,c2) local hh; hh:=List(ConjugacyClassesSubgroups2(g),Representative); return StablyEquivalentCheckHGenSubdirectProduct(g,hh,c1,c2); end; StablyEquivalentFCheckGenSubdirectProduct:= function(arg) local g,hh,c1,c2,G1,G2,fl1,fl2,F1,F2,epi1,epi2,gg1,gg2,g1,g2,dx,m,i,j; g:=arg[1]; hh:=List(ConjugacyClassesSubgroups2(g),Representative); c1:=arg[2]; c2:=arg[3]; G1:=Image(Projection(g,1)); G2:=Image(Projection(g,2)); if Length(arg)=3 then fl1:=FlabbyResolutionLowRank(G1); if not "actionF" in RecNames(fl1) then F1:=Group(List(GeneratorsOfGroup(G1),x->[[1]]),[[1]]); else F1:=fl1.actionF; fi; else F1:=arg[4]; fi; epi1:=GroupHomomorphismByImages(G1,F1,GeneratorsOfGroup(G1),GeneratorsOfGroup(F1)); if Length(arg)<5 then fl2:=FlabbyResolutionLowRank(G2); if not "actionF" in RecNames(fl2) then F2:=Group(List(GeneratorsOfGroup(G2),x->[[1]]),[[1]]); else F2:=fl2.actionF; fi; else F2:=arg[5]; fi; epi2:=GroupHomomorphismByImages(G2,F2,GeneratorsOfGroup(G2),GeneratorsOfGroup(F2)); gg1:=List(hh,x->CosetRepresentation(g,x)); gg2:=List(hh,x->CosetRepresentation(g,x)); Add(gg1,List(GeneratorsOfGroup(g),x->Image(epi1,Image(Projection(g,1),x)))); Add(gg2,List(GeneratorsOfGroup(g),x->Image(epi2,Image(Projection(g,2),x)))); g1:=[]; g2:=[]; for i in [1..Length(gg1[1])] do m:=[]; for j in [1..Length(gg1)] do m:=Concatenation(m,List([1..c1[j]],x->gg1[j][i])); od; Add(g1,DirectSumMat(m)); m:=[]; for j in [1..Length(gg2)] do m:=Concatenation(m,List([1..c2[j]],x->gg2[j][i])); od; Add(g2,DirectSumMat(m)); od; return [g1,g2]; end; oplusZ := function(arg) local l,c,n; l:=arg[1]; if Length(arg)=1 then c:=1; else c:=arg[2]; fi; n:=Length(l); l[n-1]:=l[n-1]+c; return l; end; SubdirectProduct2Matrix:= function(G) local gg,G1,G2; gg:=GeneratorsOfGroup(G); G1:=Group(List(gg,x->Image(Projection(G,1),x))); G2:=Group(List(gg,x->Image(Projection(G,2),x))); return DirectSumMatrixGroup([G1,G2]); end; SearchPRowBlocks := function(bp) local n,d,row_nonzero,tf,bpBlock,i,j,l,f,rowBlock; n:=Length(bp); d:=Length(bp[1]); row_nonzero:=List([1..d],x->Filtered([1..n],y->bp[y][x]<>List([1..d],Zero))); tf:=List([1..n],Zero); bpBlock:=[]; for i in [1..n] do if tf[i]=0 then l:=[i]; f:=true; while f=true do f:=false; for j in [1..d] do if Intersection(row_nonzero[j],l)<>[] and Difference(row_nonzero[j],l)<>[] then l:=Union(l,row_nonzero[j]); f:=true; fi; od; od; Add(bpBlock,l); for j in l do tf[j]:=1; od; fi; od; rowBlock:=List(bpBlock,x->Filtered([1..d],y->Intersection(x,row_nonzero[y])<>[])); return rec(bpBlocks:=bpBlock, rowBlocks:=rowBlock); end; SearchP1 := function(arg) local bp,ll,l0,n,i,combi,tup,jc,jt,P; bp:=arg[1]; if Length(arg)=1 then ll:=[0,1]; else ll:=arg[2]; fi; l0:=Filtered(ll,x->x<>0); n:=Length(bp); for i in [1..n] do if AbsInt(Determinant(bp[i]))=1 then return bp[i]; fi; od; for i in [2..n] do combi:=Combinations([1..n],i); tup:=Tuples(l0,i); for jc in combi do for jt in tup do P:=Sum([1..i],x->jt[x]*bp[jc[x]]); if AbsInt(Determinant(P))=1 then return P; fi; od; od; od; return fail; end; SearchPFilterRowBlocks := function(arg) local bp,bpBlocks,rowBlocks,k,ll,bpb,n,r,ans,lnonzero,i,combi,tup,jc,jt,P; bp:=arg[1]; bpBlocks:=arg[2]; rowBlocks:=arg[3]; bpb:=bp{bpBlocks}{rowBlocks}; n:=Length(bpBlocks); r:=Length(rowBlocks); k:=arg[4]; if k>n then k:=n; fi; if Length(arg)<5 then ll:=[0,1]; else ll:=arg[5]; fi; ans:=[]; lnonzero:=Filtered(ll,x->x<>0); for i in [1..k] do combi:=Combinations([1..n],i); tup:=Tuples(lnonzero,i); for jc in combi do for jt in tup do P:=Sum([1..i],x->jt[x]*bpb[jc[x]]); if Rank(P*Z(2)^0)=r and Rank(P*Z(3)^0)=r and Rank(P*Z(5)^0)=r then Add(ans,P); fi; od; od; od; return Filtered(ans,x->SmithNormalFormIntegerMat(x)[r][r]=1); end; SearchPFilterRowBlocksRandomMT := function(arg) local bp,bpBlocks,rowBlocks,k,ll,bpb,n,r,rs,i,ans,v,P; bp:=arg[1]; bpBlocks:=arg[2]; rowBlocks:=arg[3]; bpb:=bp{bpBlocks}{rowBlocks}; n:=Length(bpBlocks); r:=Length(rowBlocks); k:=arg[4]; if Length(arg)<5 then ll:=[0,1]; else ll:=arg[5]; fi; rs:=RandomSource(IsMersenneTwister); ans:=[]; for i in [1..k] do v:=List([1..n],x->Random(rs,ll)); P:=v*bpb; if Rank(P*Z(2)^0)=r and Rank(P*Z(3)^0)=r and Rank(P*Z(5)^0)=r then Add(ans,P); fi; od; return Filtered(ans,x->SmithNormalFormIntegerMat(x)[r][r]=1); end; SearchPMergeRowBlock := function(l1,l2) local r1,r2,d,ans,P1,P2,P0; if l1=[] or l2=[] then return []; fi; r1:=Length(l1[1]); r2:=Length(l2[1]); d:=Length(l1[1][1]); ans:=[]; for P1 in l1 do for P2 in l2 do P0:=Concatenation([P1,P2]); if r1+r2=d then if AbsInt(Determinant(P0))=1 then return P0; fi; else if Rank(P0*Z(2)^0)=r1+r2 and Rank(P0*Z(3)^0)=r1+r2 and Rank(P0*Z(5)^0)=r1+r2 then Add(ans,P0); fi; fi; od; od; if r1+r2=d then return fail; else return Filtered(ans,x->SmithNormalFormIntegerMat(x)[r1+r2][r1+r2]=1); fi; end; SearchPLinear := function(Q, br) return List(br,x->Determinant(Q+x)); end; SearchPBilinear := function(Q, br1, br2) return List(br1,x->List(br2,y->Determinant(Q+x+y))); end; SearchPQuadratic := function(Q, br) local n,M,i; n:=Length(br); M:=NullMat(n,n); for i in [1..n] do M[i][i]:=Determinant(Q+br[i]); od; for i in Combinations([1..n],2) do M[i[1]][i[2]]:=(Determinant(Q+br[i[1]]+br[i[2]])-M[i[1]][i[1]]-M[i[2]][i[2]])/2; M[i[2]][i[1]]:=M[i[1]][i[2]]; od; return M; end; WSEC := function(G) local ID,position; if Length(Identity(G))>4 then return fail; fi; ID:=CrystCatZClass(G); position:=Position(N3,ID); if position<>fail then return N3WSECNumberTable[position]; fi; position:=Position(N31,ID); if position<>fail then return N31WSECNumberTable[position]; fi; position:=Position(N4,ID); if position<>fail then return N4WSECNumberTable[position]; fi; position:=Position(I4,ID); if position<>fail then return I4WSECNumberTable[position]; fi; return 0; end; WSECNumber := WSEC; ConjugacyClassesSubgroups2WSEC := function(G) local hh,ans; hh:=ConjugacyClassesSubgroups2(G); ans:=List(hh,x->WSEC(Representative(x))); if fail in ans then return fail; else return rec(ConjugacyClassesSubgroups2:=hh, WSEC:=ans); fi; end; IsWSECInvariantNormalSubgroup := function(G,n) local wsec; wsec:=ConjugacyClassesSubgroups2WSEC(G); if wsec=fail then return fail; fi; wsec.TorusInvariants:=wsec.WSEC; return IsInvariantNormalSubgroup(G,wsec,n); end; WSECInvariantNormalSubgroups := function(G) local wsec; wsec:=ConjugacyClassesSubgroups2WSEC(G); if wsec=fail then return fail; fi; wsec.TorusInvariants:=wsec.WSEC; return InvariantNormalSubgroups(G,wsec); end; WSECInvariantSubdirectProducts := function(G1,G2) local wsec1,wsec2; wsec1:=ConjugacyClassesSubgroups2WSEC(G1); if wsec1=fail then return fail; fi; wsec2:=ConjugacyClassesSubgroups2WSEC(G2); if wsec2=fail then return fail; fi; return PossibilityOfStablyEquivalentSubdirectProducts(G1,G2,wsec1,wsec2,["WSEC"]); end; IsWSECInvariantAutomorphism := function(arg) local G,hom,wsec,hh,he,c,i,h,h2,i2; G:=arg[1]; hom:=arg[2]; if Length(arg)<3 then wsec:=ConjugacyClassesSubgroups2WSEC(G); else wsec:=arg[3]; fi; if wsec=fail then return fail; fi; hh:=wsec.ConjugacyClassesSubgroups2; he:=List(hh,Elements); c:=wsec.WSEC; for i in [1..Length(hh)] do h:=Representative(hh[i]); h2:=Image(hom,h); i2:=PositionIn(he,h2); if c[i]<>c[i2] then return false; fi; od; return true; end; AutGLnZ := function(G) local Ng,autgl; if Rank(Identity(G))=1 then Ng:=[[[-1]]]; else Ng:=Unique(GeneratorsOfGroup(NormalizerInGLnZ(G))); fi; autgl:=Group(List(Ng,x->ConjugatorAutomorphism(G,x))); return autgl; end; AutGLnZDoubleCosetsRepresentative := function(G) local aut,autgl,d,dr; aut:=AutomorphismGroup(G); autgl:=AutGLnZ(G); d:=DoubleCosets2(aut,autgl,autgl); dr:=List(d,Representative); return dr; end; AutGLnZDoubleCosetsWSECInvariantRepresentative := function(arg) local G,wsec,dr; G:=arg[1]; if Length(arg)=1 then wsec:=ConjugacyClassesSubgroups2WSEC(G); else wsec:=arg[2]; fi; if wsec=fail then return fail; fi; dr:=AutGLnZDoubleCosetsRepresentative(G); return Filtered(dr,x->IsWSECInvariantAutomorphism(G,x,wsec)); end; AutGLnZDoubleCosetsWSECInvariantGenRepresentative := function(arg) local G,wsec,aut,autg,autinv,dr,k,i,c; G:=arg[1]; if Length(arg)=1 then wsec:=ConjugacyClassesSubgroups2WSEC(G); else wsec:=arg[2]; fi; if wsec=fail then return fail; fi; aut:=AutGLnZ(G); autg:=Unique(GeneratorsOfGroup(aut)); dr:=AutGLnZDoubleCosetsWSECInvariantRepresentative(G,wsec); autinv:=Group(Concatenation(autg,dr)); k:=Length(dr); if k=1 then return []; fi; for i in [1..k-1] do for c in Combinations([1..k],i) do if Order(Group(Concatenation(autg,dr{c})))=Order(autinv) then return dr{c}; fi; od; od; end; AutGSubdirectProductsWSECInvariant := function(arg) local G,wsec,dr,dri; G:=arg[1]; if Length(arg)=1 then wsec:=ConjugacyClassesSubgroups2WSEC(G); else wsec:=arg[2]; fi; if wsec=fail then return fail; fi; dr:=AutGLnZDoubleCosetsRepresentative(G); dri:=Filtered(dr,x->IsWSECInvariantAutomorphism(G,x,wsec)); return List(dri,x->SubdirectProduct(G,G,x,dr[1]^0)); end; AutGSubdirectProductsWSECInvariantGen := function(arg) local G,wsec,aut,autg,autinv,dr,k,i,c; G:=arg[1]; if Length(arg)=1 then wsec:=ConjugacyClassesSubgroups2WSEC(G); else wsec:=arg[2]; fi; if wsec=fail then return fail; fi; aut:=AutGLnZ(G); autg:=Unique(GeneratorsOfGroup(aut)); dr:=AutGLnZDoubleCosetsWSECInvariantRepresentative(G,wsec); autinv:=Group(Concatenation(autg,dr)); k:=Length(dr); if k=1 then return []; fi; for i in [1..k-1] do for c in Combinations([1..k],i) do if Order(Group(Concatenation(autg,dr{c})))=Order(autinv) then return List(dr{c},x->SubdirectProduct(G,G,x,Identity(autinv))); fi; od; od; end; AutGWSECInvariantSimpleTest := function(arg) local G,wsec,hh,he,c,dr,m,row,hom,i,h,h2,i2,nr,S,k,ans,cmb,ind; G:=arg[1]; if Length(arg)=1 then wsec:=ConjugacyClassesSubgroups2WSEC(G); else wsec:=arg[2]; fi; if wsec=fail then return fail; fi; hh:=wsec.ConjugacyClassesSubgroups2; he:=List(hh,Elements); c:=wsec.WSEC; dr:=AutGLnZDoubleCosetsRepresentative(G); m:=[]; for hom in dr do row:=[]; for i in [1..Length(hh)] do h:=Representative(hh[i]); h2:=Image(hom,h); i2:=PositionIn(he,h2); Add(row,c[i2]); od; Add(m,row); od; nr:=Number(m,x->x=c); if nr=Length(m) then return []; fi; S:=Difference(c,[0]); k:=Length(S); ans:=[]; for i in [1..k] do for cmb in Combinations(S,i) do ind:=Filtered([1..Length(m[1])],x->c[x] in cmb); if Number(m,x->x{ind}=c{ind})=nr then Add(ans,cmb); fi; od; if ans<>[] then return ans; fi; od; end; ReversedBinary := function(n) local ans; if(n<2) then return [n]; fi; return Concatenation([n mod 2],ReversedBinary(Int(n/2))); end; AutGWSECInvariantSmallDegreeTest := function(arg) local G,wsec,hh,he,c,dr,m,row,hom,i,h,h2,i2,nr,S,b,i1,S1,ind; G:=arg[1]; if Length(arg)=1 then wsec:=ConjugacyClassesSubgroups2WSEC(G); else wsec:=arg[2]; fi; if wsec=fail then return fail; fi; hh:=wsec.ConjugacyClassesSubgroups2; he:=List(hh,Elements); c:=wsec.WSEC; dr:=AutGLnZDoubleCosetsRepresentative(G); m:=[]; for hom in dr do row:=[]; for i in [1..Length(hh)] do h:=Representative(hh[i]); h2:=Image(hom,h); i2:=PositionIn(he,h2); Add(row,c[i2]); od; Add(m,row); od; nr:=Number(m,x->x=c); if nr=Length(m) then return [1]; fi; S:=Set(hh,x->Order(G)/Order(Representative(x))); i:=1; while i<2^Length(S) do b:=ReversedBinary(i); i1:=Filtered([1..Length(b)],x->b[x]=1); S1:=List(i1,x->S[x]); ind:=Filtered([1..Length(m[1])],x->Order(G)/Order(Representative(hh[x])) in S1); if Number(m,x->x{ind}=c{ind})=nr then return S1; fi; i:=i+2; od; end; IsomorphismFromSubdirectProduct := function(G) local p1,p2,G1,G2,Gg,N1,pi1,f1,GN1,GN1g,N2,pi2,f2,GN2,GN2g; p1:=Projection(G,1); p2:=Projection(G,2); G1:=Image(p1); G2:=Image(p2); Gg:=GeneratorsOfGroup(G); N1:=Image(p1,PreImage(p2,Group(Identity(G2)))); if Order(N1)=1 then f1:=p1; GN1:=G1; else pi1:=NaturalHomomorphismByNormalSubgroup(G1,N1); f1:=CompositionMapping(pi1,p1); GN1:=Image(f1); fi; GN1g:=List(Gg,x->Image(f1,x)); N2:=Image(p2,PreImage(p1,Group(Identity(G1)))); if Order(N2)=1 then f2:=p2; GN2:=G2; else pi2:=NaturalHomomorphismByNormalSubgroup(G2,N2); f2:=CompositionMapping(pi2,p2); GN2:=Image(f2); fi; GN2g:=List(Gg,x->Image(f2,x)); return GroupHomomorphismByImages(GN1,GN2,GN1g,GN2g); end;