
| Current Path : /usr/share/gap/lib/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //usr/share/gap/lib/gprd.gi |
#############################################################################
##
#W gprd.gi GAP library Bettina Eick
## Heiko Theißen
##
##
#Y Copyright (C) 1997, Lehrstuhl D für Mathematik, RWTH Aachen, Germany
#Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
#Y Copyright (C) 2002 The GAP Group
##
#############################################################################
##
#F DirectProduct( <arg> )
##
InstallGlobalFunction( DirectProduct, function( arg )
local d, prop;
if Length( arg ) = 0 then
Error( "<arg> must be nonempty" );
elif Length( arg ) = 1 and IsList( arg[1] ) then
if IsEmpty( arg[1] ) then
Error( "<arg>[1] must be nonempty" );
fi;
arg:= arg[1];
fi;
d:=DirectProductOp( arg, arg[1] );
# test/set a few properties and attributes from factors
for prop in [IsFinite, IsNilpotentGroup, IsAbelian, IsSolvableGroup] do
if ForAll(arg, Tester(prop)) then
Setter(prop)(d, ForAll(arg, prop));
fi;
od;
if ForAll(arg,HasSize) then
if ForAll(arg,IsFinite)
then SetSize(d,Product(List(arg,Size)));
else SetSize(d,infinity); fi;
fi;
return d;
end );
#############################################################################
##
#M DirectProductOp( <list>, <G> )
##
InstallMethod( DirectProductOp,
"for a list (of groups), and a group",
[ IsList, IsGroup ],
function( list, gp )
local ids, tup, first, i, G, gens, g, new, D;
# Check the arguments.
if IsEmpty( list ) then
Error( "<list> must be nonempty" );
elif ForAny( list, G -> not IsGroup( G ) ) then
TryNextMethod();
fi;
ids := List( list, One );
tup := [];
first := [1];
for i in [1..Length( list )] do
G := list[i];
gens := GeneratorsOfGroup( G );
for g in gens do
new := ShallowCopy( ids );
new[i] := g;
new := DirectProductElement( new );
Add( tup, new );
od;
Add( first, Length( tup )+1 );
od;
D := GroupByGenerators( tup, DirectProductElement( ids ) );
SetDirectProductInfo( D, rec( groups := list,
first := first,
embeddings := [],
projections := [] ) );
if ForAll( list, CanEasilyComputeWithIndependentGensAbelianGroup ) then
SetFilterObj( D, CanEasilyComputeWithIndependentGensAbelianGroup );
fi;
return D;
end );
#############################################################################
##
#M \in( <dpelm>, <G> )
##
InstallMethod( \in,"generic direct product", IsElmsColls,
[ IsDirectProductElement, IsGroup and HasDirectProductInfo ],
function( g, G )
local n, info;
n := Length( g );
info := DirectProductInfo( G );
return ForAll( [1..n], x -> g[x] in info.groups[x] );
end );
#############################################################################
##
#A Embedding
##
InstallMethod( Embedding, "group direct product and integer",
[ IsGroup and HasDirectProductInfo, IsPosInt ],
function( D, i )
local info, G, imgs, hom, gens;
# check
info := DirectProductInfo( D );
if IsBound( info.embeddings[i] ) then
return info.embeddings[i];
fi;
info.onelist:=List(info.groups,One);
# compute embedding
G := info.groups[i];
gens := GeneratorsOfGroup( G );
imgs := GeneratorsOfGroup( D ){[info.first[i] .. info.first[i+1]-1]};
if Length(imgs)>0 and IsDirectProductElement(imgs[1]) then
# the direct product is represented by direct product elements.
# The easiest way to compute the embedding is to construct
# direct product elements.
hom:=GroupHomomorphismByFunction(G,D,function(elm)
local l;
l:=ShallowCopy(info.onelist);
l[i]:=elm;
return DirectProductElement(l);
end);
else
hom := GroupHomomorphismByImagesNC( G, D, gens, imgs );
fi;
SetIsInjective( hom, true );
# store information
info.embeddings[i] := hom;
return hom;
end );
#############################################################################
##
#A Projection
##
InstallMethod( Projection, "group direct product and integer",
[ IsGroup and HasDirectProductInfo, IsPosInt ],
function( D, i )
local info, G, imgs, hom, N, gens;
# check
info := DirectProductInfo( D );
if IsBound( info.projections[i] ) then
return info.projections[i];
fi;
# compute projection
G := info.groups[i];
gens := GeneratorsOfGroup( D );
imgs := Concatenation(
List( [1..info.first[i]-1], x -> One( G ) ),
GeneratorsOfGroup( G ),
List( [info.first[i+1]..Length(gens)], x -> One(G)));
if Length(gens)>0 and IsDirectProductElement(gens[1]) then
# The direct product is represented by direct product elements.
# The easiest way to compute the projection is to take elements apart.
hom:=GroupHomomorphismByFunction( D, G, elm -> elm[i] );
else
hom := GroupHomomorphismByImagesNC( D, G, gens, imgs );
fi;
N := SubgroupNC( D, gens{Concatenation( [1..info.first[i]-1],
[info.first[i+1]..Length(gens)])});
SetIsSurjective( hom, true );
SetKernelOfMultiplicativeGeneralMapping( hom, N );
# store information
info.projections[i] := hom;
return hom;
end );
#############################################################################
##
#M Size( <D> )
##
InstallMethod( Size, "group direct product",
[IsGroup and HasDirectProductInfo],
function( D )
return Product( List( DirectProductInfo( D ).groups, Size ) );
end );
#############################################################################
##
#M IsSolvableGroup( <D> )
##
InstallMethod( IsSolvableGroup, "for direct products",
[IsGroup and HasDirectProductInfo],
function( D )
return ForAll( DirectProductInfo( D ).groups, IsSolvableGroup );
end );
#############################################################################
##
#M IsNilpotentGroup( <D> )
##
InstallMethod( IsNilpotentGroup, "for direct products",
[IsGroup and HasDirectProductInfo], 30,
function( D )
return ForAll( DirectProductInfo( D ).groups, IsNilpotentGroup );
end );
#############################################################################
##
#M IsAbelian( <D> )
##
InstallMethod( IsAbelian, "for direct products",
[IsGroup and HasDirectProductInfo],
function( D )
return ForAll( DirectProductInfo( D ).groups, IsAbelian );
end );
#############################################################################
##
#M IsPGroup( <D> )
##
InstallMethod( IsPGroup, "for direct products",
[IsGroup and HasDirectProductInfo],
function( D )
local list, G, p;
list := DirectProductInfo( D ).groups;
if ForAll (list, G -> IsPGroup(G)) then
p := fail;
for G in list do
if not IsTrivial (G) then
if p = fail then
p := PrimePGroup (G);
elif p <> PrimePGroup (G) then
p := false;
break;
fi;
fi;
od;
if p <> false then
SetPrimePGroup (D, p);
return true;
fi;
fi;
return false;
end );
#############################################################################
##
#M PrimePGroup( <D> )
##
InstallMethod( PrimePGroup, "for direct products",
[IsPGroup and HasDirectProductInfo],
function( D )
local groups, p, H;
groups := DirectProductInfo(D).groups;
Assert(1, ForAll(groups, IsPGroup));
H := First(groups, G -> PrimePGroup(G) <> fail);
if H = fail then
SetIsTrivial(D, true);
return fail;
fi;
p := PrimePGroup(H);
Assert(1, ForAll(groups, G -> PrimePGroup(G) in [fail, p]));
return p;
end );
#############################################################################
##
#F AbelianInvariants( <D > )
##
InstallMethod( AbelianInvariants, "for direct products",
[IsGroup and HasDirectProductInfo],
function( D )
local info, ai;
info := DirectProductInfo( D );
ai := Concatenation( List( info.groups, AbelianInvariants ) );
Sort(ai);
return ai;
end );
#############################################################################
##
#A IndependentGeneratorsOfAbelianGroup( <D> )
##
InstallMethod( IndependentGeneratorsOfAbelianGroup, "for direct products",
[IsGroup and HasDirectProductInfo and IsAbelian],
function(D)
local info, ai, gens, i, phi;
info := DirectProductInfo( D );
ai := Concatenation( List( info.groups, AbelianInvariants ) );
gens := [];
for i in [ 1..Length(info.groups) ] do
phi := Embedding( D, i );
Append( gens, List( IndependentGeneratorsOfAbelianGroup( info.groups[i] ),
g -> ImageElm( phi, g ) ) );
od;
SortParallel(ai, gens);
return gens;
end );
#############################################################################
##
#O IndependentGeneratorExponents( <D>, <g> )
##
InstallMethod( IndependentGeneratorExponents, "for direct products",
IsCollsElms,
[IsGroup and HasDirectProductInfo and IsAbelian,
IsMultiplicativeElementWithInverse and IsDirectProductElement],
function(D,g)
local info, ai, exps, i, phi;
info := DirectProductInfo( D );
ai := Concatenation( List( info.groups, AbelianInvariants ) );
exps := [];
for i in [ 1..Length(info.groups) ] do
phi := Projection( D, i );
Append( exps, IndependentGeneratorExponents(info.groups[i], ImageElm( phi, g )) );
od;
SortParallel(ai, exps);
return exps;
end);
#############################################################################
##
#R IsPcgsDirectProductRep
##
DeclareRepresentation ("IsPcgsDirectProductRep", IsPcgsDefaultRep, ["pcgs","len"]);
#############################################################################
##
#M Pcgs( <D> )
#M PcgsElementaryAbelianSeries( <D> )
#M PcgsCentralSeries( <D> )
##
InstallGlobalFunction (PcgsDirectProduct,
function( D, pcgsop, indsop, filter )
local info, pcs, i, pcgs, rels, indices, inds, offset, one, new, g, attl;
if not IsDirectProductElement( One( D ) ) then TryNextMethod(); fi;
info := DirectProductInfo( D );
pcs := [];
rels := [];
pcgs := [];
indices := [];
one := List( info.groups, x -> One(x) );
offset := 0;
for i in [1..Length(info.groups)] do
pcgs[i] := pcgsop ( info.groups[i] );
if indsop <> fail then
inds := indsop (pcgs[i]) + offset;
Append (indices, inds{[1..Length(inds)-1]});
fi;
for g in pcgs[i] do
new := ShallowCopy( one );
new[i] := g;
Add( pcs, DirectProductElement( new ) );
od;
Append( rels, RelativeOrders( pcgs[i] ) );
offset := offset + Length (pcgs[i]);
od;
attl := [RelativeOrders, rels, GroupOfPcgs, D, One, One(D)];
if indsop <> fail then
Add (indices, offset + 1);
Append (attl, [indsop, indices, filter, true]);
fi;
pcs := PcgsByPcSequenceCons(
IsPcgsDefaultRep,
IsPcgs and IsPcgsDirectProductRep,
ElementsFamily(FamilyObj( D ) ),
pcs,
attl );
pcs!.pcgs := pcgs;
return pcs;
end
);
InstallMethod( Pcgs, "for direct products", true,
[IsGroup and HasDirectProductInfo],
Maximum(
RankFilter(IsPcGroup),
RankFilter(IsPermGroup and IsSolvableGroup)
),# this is better than these two common alternatives
D -> PcgsDirectProduct (D, Pcgs, fail, fail));
InstallMethod( PcgsElementaryAbelianSeries, "for direct products", true,
[IsGroup and HasDirectProductInfo],
Maximum(
RankFilter(IsPcGroup),
RankFilter(IsPermGroup and IsSolvableGroup)
),# this is better than these two common alternatives
D -> PcgsDirectProduct (D,
PcgsElementaryAbelianSeries,
IndicesEANormalSteps,
IsPcgsElementaryAbelianSeries)
);
InstallMethod( PcgsCentralSeries, "for direct products", true,
[IsGroup and HasDirectProductInfo],
Maximum(
RankFilter(IsPcGroup),
RankFilter(IsPermGroup and IsSolvableGroup)
),# this is better than these two common alternatives
D -> PcgsDirectProduct (D,
PcgsCentralSeries,
IndicesCentralNormalSteps,
IsPcgsCentralSeries)
);
InstallMethod( PcgsChiefSeries, "for direct products", true,
[IsGroup and HasDirectProductInfo],
Maximum(
RankFilter(IsPcGroup),
RankFilter(IsPermGroup and IsSolvableGroup)
),# this is better than these two common alternatives
D -> PcgsDirectProduct (D, PcgsChiefSeries, IndicesChiefNormalSteps, IsPcgsChiefSeries)
);
InstallMethod( PcgsPCentralSeriesPGroup, "for direct products", true,
[IsGroup and HasDirectProductInfo],
Maximum(
RankFilter(IsPcGroup),
RankFilter(IsPermGroup and IsSolvableGroup)
),# this is better than these two common alternatives
D -> PcgsDirectProduct (D,
PcgsCentralSeries,
IndicesPCentralNormalStepsPGroup,
IsPcgsPCentralSeriesPGroup)
);
#############################################################################
##
#M ExponentsOfPcElement( <pcgs>, <g> )
##
InstallMethod (ExponentsOfPcElement, "for pcgs of direct product", IsCollsElms,
[IsPcgs and IsPcgsDirectProductRep, IsDirectProductElement], 0,
function (pcgs, g)
local exp, i;
if Length (pcgs!.pcgs) <> Length (g) then
TryNextMethod ();
fi;
exp := [];
for i in [1..Length (g)] do
Append (exp, ExponentsOfPcElement (pcgs!.pcgs[i], g[i]));
od;
return exp;
end
);
#############################################################################
##
#M DepthOfPcElement( <pcgs>, <g> )
##
InstallMethod (DepthOfPcElement, "for pcgs of direct product", IsCollsElms,
[IsPcgs and IsPcgsDirectProductRep, IsDirectProductElement], 0,
function (pcgs, g)
local i, d, prevdepth;
if Length (pcgs!.pcgs) <> Length (g) then
TryNextMethod ();
fi;
prevdepth := 0;
for i in [1..Length (g)] do
d := DepthOfPcElement (pcgs!.pcgs[i], g[i]);
if d <= Length (pcgs!.pcgs[i]) then
return d + prevdepth;
fi;
prevdepth := prevdepth + Length (pcgs!.pcgs[i]);
od;
return prevdepth + 1;
end
);
#############################################################################
##
## subdirect product stuff
##
InstallGlobalFunction(SubdirectProduct,function(G,H,ghom,hhom)
local iso;
if Image(ghom,G)<>Image(hhom,H) then
# are they isomorphic?
iso:=IsomorphismGroups(Image(ghom,G),Image(hhom,H));
if iso=fail then
Error("the image groups are nonisomorphic");
else
Info(InfoWarning,1,
"The image groups are inequal. Computed an isomorphism between them.");
ghom:=ghom*iso;
fi;
fi;
# the ...Op is installed for `IsGroupHomomorphism'. So we have to enforce
# the filter to be set.
if not IsGroupHomomorphism(ghom) or not IsGroupHomomorphism(hhom) then
Error("mappings are not homomorphisms");
fi;
return SubdirectProductOp(G,H,ghom,hhom);
end);
#############################################################################
##
#M SubdirectProduct( <G1>, <G2>, <phi1>, <phi2> )
##
InstallMethod( SubdirectProductOp,"groups", true,
[ IsGroup, IsGroup, IsGroupHomomorphism, IsGroupHomomorphism ], 0,
function( G, H, gh, hh )
local gc,hc,S,info;
# try to enforce a common representation
if not (IsFinite(G) and IsFinite(H)) then
TryNextMethod();
fi;
if IsSolvableGroup(G) and IsSolvableGroup(H) and
not (IsPcGroup(G) and IsPcGroup(H)) then
# enforce pc groups
gc:=IsomorphismPcGroup(G);
hc:=IsomorphismPcGroup(H);
elif not (IsPermGroup(G) and IsPermGroup(H)) then
# enforce perm groups
gc:=IsomorphismPermGroup(G);
hc:=IsomorphismPermGroup(H);
else
TryNextMethod();
fi;
gh:=InverseGeneralMapping(gc)*gh;
hh:=InverseGeneralMapping(hc)*hh;
# the ...Op is installed for `IsGroupHomomorphism'. So we have to enforce
# the filter to be set.
if not IsGroupHomomorphism(gh) or not IsGroupHomomorphism(hh) then
Error("mappings are not homomorphisms");
fi;
S:=SubdirectProductOp(Image(gc,G),Image(hc,H),gh,hh);
info:=rec(groups:=[G,H],
homomorphisms:=[gh,hh],
projections:=[Projection(S,1)*InverseGeneralMapping(gc),
Projection(S,2)*InverseGeneralMapping(hc)]);
S:=Group(GeneratorsOfGroup(S));
SetSubdirectProductInfo(S,info);
return S;
end);
#############################################################################
##
#M Projection( <S>, <i> ) . . . . . . . . . . . . . . . . . make projection
##
InstallMethod( Projection,"pc subdirect product", true,
[ IsGroup and HasSubdirectProductInfo, IsPosInt ], 0,
function( S, i )
local prj, info;
if not i in [1,2] then
Error("only 2 embeddings");
fi;
info := SubdirectProductInfo( S );
if not IsBound(info.projections[i]) then
TryNextMethod();
fi;
return info.projections[i];
end);
#############################################################################
##
#M Size( <S> ) . . . . . . . . . . . . . . . . . . . . of subdirect product
##
InstallMethod( Size,"subdirect product", true,
[ IsGroup and HasSubdirectProductInfo ], 0,
function( S )
local info;
info := SubdirectProductInfo( S );
return Size( info.groups[ 1 ] ) * Size( info.groups[ 2 ] )
/ Size( ImagesSource( info.homomorphisms[ 1 ] ) );
end );
#
# functions for finding all SDP's
#
#############################################################################
##
#F InnerSubdirectProducts2( D, U, V ) . . . . . . . . . .up to conjugacy in D
##
InstallGlobalFunction(InnerSubdirectProducts2,function( D, U, V )
local normsU, normsV, div, fac, Syl, NormU, orb, NormV, pairs, i, j,
homU, homV, iso, subdir, gensU, gensV, N, UN, M, VM, Aut, gamma,
P, NormUN, autU, n, alpha, NormVM, autV, reps, rep, gens, r, g, h,
S, pair, imgs;
# compute necessary normal subgroups in U and V
if IsAbelian( U ) and IsAbelian( V ) then
normsU := List( ConjugacyClassesSubgroups( U ), Representative );
normsV := List( ConjugacyClassesSubgroups( V ), Representative );
elif IsAbelian( U ) then
normsU := List( ConjugacyClassesSubgroups( U ), Representative );
normsV := NormalSubgroupsAbove( V, DerivedSubgroup(V),[]);
elif IsAbelian( V ) then
normsU := NormalSubgroupsAbove( U, DerivedSubgroup(U),[]);
normsV := List( ConjugacyClassesSubgroups( V ), Representative );
else
div := PrimeDivisors( Gcd( Size( U ), Size( V ) ) );
# in U
fac := PrimeDivisors( Size( U ) );
fac := Filtered( fac, x -> not x in div );
Syl := List( fac, x -> GeneratorsOfGroup( SylowSubgroup( U, x ) ) );
Syl := Concatenation( Syl );
Syl := NormalClosure( U, Subgroup( U, Syl ) );
normsU := NormalSubgroupsAbove( U, Syl, [] );
# in V
fac := PrimeDivisors( Size( V ) );
fac := Filtered( fac, x -> not x in div );
Syl := List( fac, x -> GeneratorsOfGroup( SylowSubgroup( V, x ) ) );
Syl := Concatenation( Syl );
Syl := NormalClosure( V, Subgroup( V, Syl ) );
normsV := NormalSubgroupsAbove( V, Syl, [] );
fi;
# compute orbits on normal subgroups in U
NormU := Normalizer( D, U );
orb := OrbitsDomain( NormU, normsU, OnPoints );
normsU := List( orb, x -> x[1] );
# compute orbits on normal subgroups in V
NormV := Normalizer( D, V );
orb := OrbitsDomain( NormV, normsV, OnPoints );
normsV := List( orb, x -> x[1] );
# find isomorphic pairs of factors
pairs := [];
for i in [1..Length(normsU)] do
for j in [1..Length(normsV)] do
if Index( U, normsU[i] ) = Index( V, normsV[j] ) then
homU := NaturalHomomorphismByNormalSubgroup( U, normsU[i] );
homV := NaturalHomomorphismByNormalSubgroup( V, normsV[j] );
iso := IsomorphismGroups( Image( homU ), Image( homV ) );
if not IsBool( iso ) then
Add( pairs, [ homU, homV, iso] );
fi;
fi;
od;
od;
# loop over pairs
subdir := [];
gensU := GeneratorsOfGroup( U );
gensV := GeneratorsOfGroup( V );
for pair in pairs do
N := KernelOfMultiplicativeGeneralMapping( pair[1] );
UN := Image( pair[1] );
M := KernelOfMultiplicativeGeneralMapping( pair[2] );
VM := Image( pair[2] );
iso := pair[3];
# calculate Aut( U / N )
Aut := AutomorphismGroup( UN );
gamma := IsomorphismPermGroup( Aut );
P := Image( gamma );
# calculate induced autos in G
NormUN := Normalizer( NormU, N );
autU := [];
for n in GeneratorsOfGroup( NormUN ) do
gens := List( gensU, x -> Image( pair[1], x ) );
imgs := List( gensU, x -> Image( pair[1], x^n ) );
if gens <> imgs then
alpha := GroupHomomorphismByImagesNC( UN, UN, gens, imgs );
SetFilterObj( alpha, IsMultiplicativeElementWithInverse );
Add( autU, Image( gamma, alpha ) );
fi;
od;
autU := SubgroupNC( P, autU );
# calculate induced autos in H
NormVM := Normalizer( NormV, M );
autV := [];
for n in GeneratorsOfGroup( NormVM ) do
gens := List( gensV, x -> Image( pair[2], x ) );
imgs := List( gensV, x -> Image( pair[2], x^n ) );
if gens <> imgs then
alpha := GroupHomomorphismByImagesNC( VM, VM, gens, imgs );
alpha := iso * alpha * InverseGeneralMapping( iso );
SetFilterObj( alpha, IsMultiplicativeElementWithInverse );
Add( autV, Image( gamma, alpha ) );
fi;
od;
autV := SubgroupNC( P, autV );
# and obtain double coset reps
reps := List( DoubleCosets( P, autU, autV ), Representative );
reps := List( reps, x -> PreImagesRepresentative( gamma, x ) );
# loop over automorphisms
for rep in reps do
# compute corresponding group
gens := Concatenation( GeneratorsOfGroup( N ),
GeneratorsOfGroup( M ) );
for r in GeneratorsOfGroup( UN ) do
g := PreImagesRepresentative( pair[1], r );
h := Image( iso, Image( rep, r ) );
h := PreImagesRepresentative( pair[2], h );
Add( gens, g * h );
od;
S := SubgroupNC( D, gens );
SetSize( S, Size( N ) * Size( M ) * Size( UN ) );
Add( subdir, S );
od;
od;
# return
return subdir;
end);
#############################################################################
##
#F InnerSubdirectProducts( D, list ) . . . . . . .iterated subdirect products
##
InstallGlobalFunction(InnerSubdirectProducts,function( P, list )
local subdir, i, U, tmp, S, new;
subdir := [list[1]];
for i in [2..Length(list)] do
U := list[i];
tmp := [];
for S in subdir do
new := InnerSubdirectProducts2( P, S, U );
Append( tmp, new );
od;
subdir := tmp;
od;
return subdir;
end);
#############################################################################
##
#F SubdirectProducts( S, T ) . . . . . . . . . . . up to conjugacy in parents
##
InstallGlobalFunction(SubdirectProducts,function( S, T )
local G, H, D, emb1, emb2, U, V, subdir, info, i;
# go over to direct product
G := Parent( S );
H := Parent( T );
D := DirectProduct( G, H );
# create embeddings
emb1 := Embedding( D, 1 );
emb2 := Embedding( D, 2 );
# compute subdirect products
U := Image( emb1, S );
V := Image( emb2, T );
subdir := InnerSubdirectProducts2( D, U, V );
# create info
info := rec( groups := [S, T],
projections := [Projection( D, 1 ), Projection( D, 2 )] );
for i in [1..Length( subdir )] do
SetSubdirectProductInfo( subdir[i], info );
od;
return subdir;
end);
#
# wreath products: generic code
#
InstallOtherMethod( WreathProduct,"generic groups, no perm", true,
[ IsGroup, IsGroup ], 0,
function(G,H)
if IsPermGroup(H) then TryNextMethod();fi;
Error("WreathProduct requires permgroup or group and permrep");
end);
InstallMethod( WreathProduct,"generic groups with perm", true,
[ IsGroup, IsPermGroup ], 0,
function(G,H)
return WreathProduct(G,H,IdentityMapping(H));
end);
InstallMethod( StandardWreathProduct,"generic groups", true,
[ IsGroup, IsGroup ], 0,
function(G,H)
local iso;
iso:=ActionHomomorphism(H,AsSSortedList(H),OnRight,"surjective");
return WreathProduct(G,H,iso);
end);
#############################################################################
##
#M WreathProduct(<G>,<H>,<alpha>)
##
InstallOtherMethod( WreathProduct,"generic groups with permhom", true,
[ IsGroup, IsGroup, IsSPGeneralMapping ], 0,
function(G,H,alpha)
local I,n,fam,typ,gens,hgens,id,i,e,info,W,p,dom;
I:=Image(alpha,H);
# avoid sparse first points.
dom:=MovedPoints(I);
if Length(dom)=0 then
dom:=[1];
n:=1;
elif Maximum(dom)>Length(dom) then
alpha:=alpha*ActionHomomorphism(I,dom);
I:=Image(alpha,H);
n:=LargestMovedPoint(I);
else
n:=LargestMovedPoint(I);
fi;
fam:=NewFamily("WreathProductElemFamily",IsWreathProductElement);
typ:=NewType(fam,IsWreathProductElementDefaultRep);
fam!.defaultType:=typ;
info:=rec(groups:=[G,H],
family:=fam,
I:=I,
degI:=n,
alpha:=alpha,
embeddings:=[]);
fam!.info:=info;
if CanEasilyCompareElements(One(G)) then
SetCanEasilyCompareElements(fam,true);
fi;
if CanEasilySortElements(One(G)) then
SetCanEasilySortElements(fam,true);
fi;
gens:=[];
id:=ListWithIdenticalEntries(n,One(G));
Add(id,One(I));
info.identvec:=ShallowCopy(id);
for p in List(Orbits(I,[1..n]),i->i[1]) do
for i in GeneratorsOfGroup(G) do
e:=ShallowCopy(id);
e[p]:=i;
Add(gens,Objectify(typ,e));
od;
od;
info.basegens:=ShallowCopy(gens);
hgens:=[];
for i in GeneratorsOfGroup(H) do
e:=ShallowCopy(id);
e[n+1]:=Image(alpha,i);
Add(hgens,Objectify(typ,e));
od;
Append(gens,hgens);
info.hgens:=hgens;
SetOne(fam,Objectify(typ,id));
W:=Group(gens,One(fam));
SetWreathProductInfo(W,info);
SetIsWholeFamily(W,true);
if HasSize(G) then
if IsFinite(G) then
SetSize(W,Size(G)^n*Size(I));
else
SetSize(W,infinity);
fi;
fi;
if HasIsFinite(G) then
SetIsFinite(W,IsFinite(G));
fi;
return W;
end);
#############################################################################
##
#M PrintObj(<x>)
##
InstallMethod(PrintObj,"wreath elements",true,[IsWreathProductElement],0,
function(x)
local i,info;
info:=FamilyObj(x)!.info;
Print("WreathProductElement(");
for i in [1..info!.degI] do
Print(x![i],",");
od;
Print(x![info!.degI+1],")");
end);
#############################################################################
##
#M OneOp(<x>)
##
InstallMethod(OneOp,"wreath elements",true,[IsWreathProductElement],0,
x->One(FamilyObj(x)));
#############################################################################
##
#M InverseOp(<x>)
##
InstallMethod(InverseOp,"wreath elements",true,
[IsWreathProductElement],0,
function(x)
local l,p,i,j,info,fam;
fam:=FamilyObj(x);
info:=fam!.info;
l:=[];
p:=x![info!.degI+1]^-1;
for i in [1..info!.degI] do
l[i]:=x![i^p]^-1;
od;
l[info!.degI+1]:=p;
return Objectify(fam!.defaultType,l);
end);
#############################################################################
##
#M \*(<x>,<y>)
##
InstallMethod(\*,"wreath elements",IsIdenticalObj,
[IsWreathProductElement,IsWreathProductElement],0,
function(x,y)
local l,p,i,j,info,fam;
fam:=FamilyObj(x);
info:=fam!.info;
l:=[];
p:=x![info!.degI+1];
for i in [1..info!.degI] do
j:=i^p;
l[i]:=x![i]*y![j];
od;
i:=info!.degI+1;
l[i]:=p*y![i];
return Objectify(fam!.defaultType,l);
end);
#############################################################################
##
#M \=(<x>,<y>)
##
InstallMethod(\=,"wreath elements",IsIdenticalObj,
[IsWreathProductElement,IsWreathProductElement],0,
function(x,y)
local i,info;
info:=FamilyObj(x)!.info;
for i in [1..info!.degI+1] do
if x![i]<>y![i] then
return false;
fi;
od;
return true;
end);
#############################################################################
##
#M \<(<x>,<y>)
##
InstallMethod(\<,"wreath elements",IsIdenticalObj,
[IsWreathProductElement,IsWreathProductElement],0,
function(x,y)
local i,info;
info:=FamilyObj(x)!.info;
for i in [1..info!.degI+1] do
if x![i]>y![i] then
return false;
elif x![i]<y![i] then
return true;
fi;
od;
return false;
end);
#############################################################################
##
#M Embedding( <W>, <i> )
##
InstallMethod( Embedding,"generic wreath product", true,
[ IsGroup and HasWreathProductInfo and IsWreathProductElementCollection,
IsPosInt ], 0,
function(G,n)
local info,map,U,mapfun,P;
info:=WreathProductInfo(G);
if n<1 or n-1>info.degI then
Error("wrong index");
else
if not IsBound(info.embeddings[n]) then
mapfun:=function(elm)
local a;
a:=ShallowCopy(info.identvec);
if n>info.degI then
elm:=Image(info.alpha,elm);
fi;
a[n]:=elm;
return Objectify(info.family!.defaultType,a);
end;
if n<=info.degI then
P:=info.groups[1];
U:=SubgroupNC(G,List(GeneratorsOfGroup(P),mapfun));
else
P:=info.groups[2];
U:=SubgroupNC(G,info.hgens);
fi;
map:=GroupHomomorphismByFunction(P,U,mapfun,
function(elm)
elm:=elm![n];
if n>info.degI then
elm:=PreImagesRepresentative(info.alpha,elm);
fi;
return elm;
end);
info.embeddings[n]:=map;
fi;
return info.embeddings[n];
fi;
end);
#############################################################################
##
#M Projection( <W> )
##
InstallOtherMethod( Projection,"generic wreath product", true,
[ IsGroup and HasWreathProductInfo and IsWreathProductElementCollection],0,
function(G)
local info,map,np;
info:=WreathProductInfo(G);
if not IsBound(info.projection) then
np:=info.degI+1;
map:=GroupHomomorphismByFunction(G,info.groups[2],
function(elm)
return PreImagesRepresentative(info.alpha,elm![np]);
end,
false, # not bijective
function(elm)
local a;
a:=ShallowCopy(info.identvec);
elm:=Image(info.alpha,elm);
a[np]:=elm;
return Objectify(info.family!.defaultType,a);
end);
info.projection:=map;
fi;
return info.projection;
end);
#############################################################################
##
#M \in(<G>,<elm>
##
InstallMethod( \in,"generic wreath product", IsCollsElms,
[ IsGroup and HasWreathProductInfo and IsWreathProductElementCollection
and IsWholeFamily, IsWreathProductElement ], 0,
function(G,e)
return true;
end);
#
# semidirect product
#
##############################################################################
##
#M SemidirectProduct
##
InstallOtherMethod( SemidirectProduct, "automorphisms group with group", true,
[ IsGroup, IsObject ], 0,
function( G, N )
return SemidirectProduct(G,IdentityMapping(G),N);
end);
InstallMethod( SemidirectProduct,"different representations",true,
[ IsGroup and IsFinite, IsGroupHomomorphism, IsGroup and IsFinite],
# don't be higher than specific perm/pc methods
-20,
function( G, aut, N )
local giso,niso,P,gens,a,Go,No,i;
Go:=G;
No:=N;
if IsSolvableGroup(N) and IsSolvableGroup(G) then
giso:=IsomorphismPcGroup(G);
niso:=IsomorphismPcGroup(N);
else
giso:=IsomorphismPermGroup(G);
niso:=IsomorphismPermGroup(N);
fi;
G:=Image(giso,G);
N:=Image(niso,N);
gens:=[];
for i in GeneratorsOfGroup(G) do
i:=Image(aut,PreImagesRepresentative(giso,i));
i:=InducedAutomorphism(niso,i);
Add(gens,i);
od;
a:=Group(gens,IdentityMapping(N));
if IsFinite(N) then
SetIsGroupOfAutomorphismsFiniteGroup(a,true);
else
SetIsGroupOfAutomorphisms(a,true);
fi;
a:=GroupHomomorphismByImagesNC(G,a,GeneratorsOfGroup(G),gens);
P:=SemidirectProduct(G,a,N);
# trick the embeddings and projections (dirty tricks)
i:=rec(groups:=[Go,No],
embeddings:=[giso*Embedding(P,1),niso*Embedding(P,2)],
projections:=Projection(P)*InverseGeneralMapping(giso));
P:=Group(GeneratorsOfGroup(P));
SetSemidirectProductInfo(P,i);
return P;
end );
# semidirect product as finitely presented
SemidirectFp:=function( G, aut, N )
local Go,No,giso,niso,FG,GP,FN,NP,F,GI,NI,rels,i,j,P;
Go:=G;
No:=N;
if not IsFpGroup(G) then
giso:=IsomorphismFpGroup(G);
else
giso:=IdentityMapping(G);
fi;
if not IsFpGroup(N) then
niso:=IsomorphismFpGroup(N);
else
niso:=IdentityMapping(N);
fi;
G:=Image(giso,G);
N:=Image(niso,N);
FG:=FreeGeneratorsOfFpGroup(G);
GP:=List(GeneratorsOfGroup(G),x->PreImagesRepresentative(giso,x));
FN:=FreeGeneratorsOfFpGroup(N);
NP:=List(GeneratorsOfGroup(N),x->PreImagesRepresentative(niso,x));
F:=FreeGroup(List(Concatenation(FG,FN),String));
GI:=GeneratorsOfGroup(F){[1..Length(FG)]};
NI:=GeneratorsOfGroup(F){[Length(FG)+1..Length(GeneratorsOfGroup(F))]};
rels:=[];
for i in RelatorsOfFpGroup(G) do
Add(rels,MappedWord(i,FG,GI));
od;
for i in RelatorsOfFpGroup(N) do
Add(rels,MappedWord(i,FN,NI));
od;
for i in [1..Length(FG)] do
for j in [1..Length(FN)] do
Add(rels,NI[j]^GI[i]/(
MappedWord(UnderlyingElement(Image(niso,Image(Image(aut,GP[i]),NP[j]))),FN,NI) ));
od;
od;
P:=F/rels;
GI:=GeneratorsOfGroup(P){[1..Length(FG)]};
NI:=GeneratorsOfGroup(P){[Length(FG)+1..Length(GeneratorsOfGroup(P))]};
# set the embeddings and projections
i:=rec(groups:=[Go,No],
embeddings:=[GroupHomomorphismByImagesNC(Go,P,GP,GI),
GroupHomomorphismByImagesNC(No,P,NP,NI)],
projections:=GroupHomomorphismByImagesNC(P,Go,
Concatenation(GI,NI),
Concatenation(GP,List(NI,x->One(Go)))) );
SetSemidirectProductInfo(P,i);
return P;
end;
InstallMethod( SemidirectProduct,"fp with group",true,
[ IsSubgroupFpGroup, IsGroupHomomorphism, IsGroup ], 0, SemidirectFp);
InstallMethod( SemidirectProduct,"group with fp",true,
[ IsGroup, IsGroupHomomorphism, IsSubgroupFpGroup ], 0, SemidirectFp);
#############################################################################
##
#A Embedding/Projection
##
InstallMethod( Embedding,"of semidirect product and integer",true,
[ IsGroup and HasSemidirectProductInfo, IsPosInt ], 0,
function( P, i )
local info, G, imgs, hom;
info := SemidirectProductInfo( P );
if IsBound( info.embeddings[i] ) then
return info.embeddings[i];
else
TryNextMethod();
fi;
end);
InstallOtherMethod( Projection,"of semidirect product", true,
[ IsGroup and HasSemidirectProductInfo ], 0,
function( P )
local info;
info := SemidirectProductInfo( P );
if not IsBool( info.projections ) then
return info.projections;
else
TryNextMethod();
fi;
end);
##############################################################################
##
#M SemidirectProduct: with vector space
##
InstallOtherMethod( SemidirectProduct, "group with vector space: affine", true,
[ IsGroup, IsGroupHomomorphism, IsFullRowModule and IsVectorSpace ], 0,
function( G, map, V )
local pm,F,d,b,s,t,pos,i,j,img,m,P,info,Go,bnt,N,pcgs,auts,mapi,ag,phi,imgs;
# construction assumes faithful action. AH
if Size(KernelOfMultiplicativeGeneralMapping(map))<>1 then
# not faithful -- cannot simply build as matrices
N:=ElementaryAbelianGroup(Size(V));
pcgs:=Pcgs(N);
auts:=[];
mapi:=MappingGeneratorsImages(map);
for i in mapi[2] do
imgs:=List(i,x->PcElementByExponents(pcgs,x));
Add(auts,GroupHomomorphismByImagesNC(N,N,pcgs,imgs));
od;
ag:=Group(auts,IdentityMapping(N));
SetIsGroupOfAutomorphismsFiniteGroup(ag,true);
phi:=GroupHomomorphismByImages(G,ag,mapi[1],auts);
s:=SemidirectProduct(G,phi,N);
return s;
fi;
G:=Image(map,G);
F:=LeftActingDomain(V);
d:=DimensionOfVectors(V);
# if G is a permgroup, take permutation matrices
Go:=G;
if IsPermGroup(G) then
m:=List(GeneratorsOfGroup(G),i->PermutationMat(i,d,F));
s:=Group(m);
pm:=GroupHomomorphismByImagesNC(G,s,GeneratorsOfGroup(G),m);
map:=map*pm;
G:=s;
fi;
if not IsMatrixGroup(G) or d<>DimensionOfMatrixGroup(G) or not
IsSubset(F,FieldOfMatrixGroup(G)) then
Error("the matrices do not fit with the field");
fi;
b:=BasisVectors(Basis(V));
# spin up a basis
s:=[];
pos:=1;
t:=[];
while Length(s)<Length(b) do
# skip basis vectors that give nothing new
while Length(s)>0 and RankMat(s)=RankMat(Concatenation(s,[b[pos]])) do
pos:=pos+1;
od;
Add(s,b[pos]);
Add(t,b[pos]); # those vectors need own affine matrices
# spin the new vector
i:=Length(s);
while i<=Length(s) and Length(s)<Length(b) do
for j in GeneratorsOfGroup(G) do
img:=s[i]*j;
if RankMat(s)<RankMat(Concatenation(s,[img])) then
# new dimension
Add(s,img);
fi;
od;
i:=i+1;
od;
od;
# do we need to take extra vectors to extend the field?
if FieldOfMatrixGroup(G)<>F then
b:=BasisVectors(Basis(Field(FieldOfMatrixGroup(G),GeneratorsOfField(F))));
s:=[];
for i in t do
for j in b do
Add(s,i*j);
od;
od;
t:=s;
fi;
m:=[];
# build affine matrices from group generators
for i in GeneratorsOfGroup(G) do
b:=IdentityMat(d+1,F);
b{[1..d]}{[1..d]}:=i;
Add(m,ImmutableMatrix(F,b));
od;
# and from basis vectors
bnt:=[];
for i in t do
b:=IdentityMat(d+1,F);
b[d+1]{[1..d]}:=i;
b:=ImmutableMatrix(F,b);
Add(m,b);
Add(bnt,b);
od;
P:=Group(m,One(m[1]));
SetSize(P,Size(G)*Size(V));
info:=rec(group:=Go,
vectorspace:=V,
normalsub:=bnt,
lenlist:=[0,Length(GeneratorsOfGroup(G))],
embeddings:=[],
field:=F,
dimension:=d,
projections:=true);
SetSemidirectProductInfo( P, info );
return P;
end);
##############################################################################
##
#M Embedding
##
InstallMethod( Embedding, "vectorspace semidirect products",
true, [ IsGroup and HasSemidirectProductInfo, IsPosInt ], 0,
function( S, i )
local info, G, genG, imgs, hom,j,k,m,n,d,v,w;
info := SemidirectProductInfo( S );
if not IsBound(info.vectorspace) then
# its not a vectorspace product
TryNextMethod();
fi;
if IsBound( info.embeddings[i] ) then
return info.embeddings[i];
fi;
if i=1 then
G := info.group;
genG := GeneratorsOfGroup( G );
imgs := GeneratorsOfGroup( S ){[info.lenlist[i]+1 .. info.lenlist[i+1]]};
hom := GroupHomomorphismByImages( G, S, genG, imgs );
elif i=2 then
d:=info.dimension;
# image of vectorspace
n:=[];
v:=BasisVectors(Basis(info.vectorspace));
w:=[];
for j in BasisVectors(Basis(info.field)) do
for k in v do
Add(w,j*k);
od;
od;
for j in w do
m:=IdentityMat(d+1,info.field);
m[d+1]{[1..d]}:=j;
Add(n,ImmutableMatrix(info.field,m));
od;
n:=SubgroupNC(S,n);
hom:=MappingByFunction(info.vectorspace,n,function(v)
local m;
m:=IdentityMat(d+1,info.field);
m[d+1]{[1..d]}:=v;
return ImmutableMatrix(info.field,m);
end,
function(a)
if not a in n then
Error("not in image");
fi;
return a[d+1]{[1..d]};
end);
SetImagesSource(hom,n);
else
Error("wrong index");
fi;
SetIsInjective( hom, true );
info.embeddings[i] := hom;
return hom;
end );
#############################################################################
##
#F FreeProduct( arg ) Robert F, Morse
##
##
InstallGlobalFunction( FreeProduct,
function( arg )
## Check to see that the proper argument number is given
##
if Length( arg ) = 0 then
Error( "<arg> must be nonempty" );
elif Length( arg ) = 1 and IsList( arg[1] ) then
if IsEmpty( arg[1] ) then
Error( "<arg>[1] must be nonempty" );
fi;
arg:= arg[1];
fi;
## Delegate the construction to FreeProductOp
##
return FreeProductOp(arg,arg[1]);
end
);
############################################################################
##
#O FreeProductOp( list, group ) Robert F. Morse
##
InstallMethod( FreeProductOp,
"for a list (of groups), and a group",
true,
[ IsList, IsGroup ], 0,
function( list, gp )
local fpisolist, # list of isomorphism from each group to an fp group
genindlist, # Ranges into the free generators of the free
# product
gennum, # total number of free generators
gens, # slice of generators of the free group of the free
# product associated with a base group
fpgens, # fp generators of a base group
r, # relations index
g, # particular base group either as given or its fp
# repesentation
ggens, # generators of base group g
i, # index of generator range
embeddings, # monomorphisms of base groups into free product
hom, # holds a monomorphism
F, # free group of free product
FP, # free product
rels # free product relators
;
## Check the arguments.
##
if IsEmpty( list ) then
Error( "<list> must be nonempty" );
elif ForAny( list, G -> not IsGroup( G ) ) then
TryNextMethod();
fi;
## Create isomorphisms from the given group list to an
## isomorphic finitely presented group.
##
fpisolist := List(list,IsomorphismFpGroup);
## Create a list if indices for the generators of the free product
##
genindlist := List(fpisolist, x->Length(GeneratorsOfGroup(Image(x))));
gennum := Sum(genindlist);
## Compute the accummalive sums which are the indices into
## the free group. Add a zero for convienence.
##
genindlist := List([1..Length(genindlist)],i->genindlist{[1..i]});
genindlist := List(genindlist, Sum);
genindlist := Concatenation([0], genindlist);
## Create the free group of the free product
##
F := FreeGroup(gennum);
## Create the relations for the for free product
##
rels := [];
## for each range of generators in the free group of the free product
## create the relations of the for ith base group.
##
for i in [1..Length(genindlist)-1] do
## get the generator range for this group in the free group
## of the free product
gens := List([genindlist[i]+1..genindlist[i+1]],x->F.(x));
## Fp representation of a base group of the free product
## and its free generators
g := Image(fpisolist[i]);
fpgens := GeneratorsOfGroup(FreeGroupOfFpGroup(g));
## Map the relations of the base group into words in the
## free group of the free product
for r in RelatorsOfFpGroup(g) do
Add(rels, MappedWord(r, fpgens, gens));
od;
od;
## Create the free product.
FP := F/rels;
## Create all the embeddings into the free product since we have
## all the needed information
##
embeddings :=[];
for i in [1..Length(genindlist)-1] do
## get the generator range for this group in the free product
gens := List([genindlist[i]+1..genindlist[i+1]],x->FP.(x));
## get the ith base group as given and the generators in
## g of the FP image -- which may not be the same as
## the generators of g
g := list[i];
ggens := List(GeneratorsOfGroup(Image(fpisolist[i])),
x->PreImage(fpisolist[i],x));
hom := GroupHomomorphismByImagesNC(g,FP,ggens,gens);
SetIsInjective(hom,true);
Add(embeddings,hom);
od;
## Save the embedding information for possible use later.
SetFreeProductInfo( FP,
rec( groups := list,
embeddings := embeddings ) );
return FP;
end
);
#############################################################################
##
#M Embedding (for free product) Robert F. Morse
##
InstallMethod( Embedding, "free products",
true, [ IsGroup and HasFreeProductInfo, IsPosInt ], 0,
function( G, i )
if i > Length(FreeProductInfo(G).embeddings) then
Error("Base group with index ",i, " does not exist");
else
return FreeProductInfo(G).embeddings[i];
fi;
end
);
#############################################################################
##
#E