SSL ctblmono.gi
Interaktion und PortierbarkeitShell
############################################################################# ## ## This file is part of GAP, a system for computational discrete algebra. ## This file's authors include Thomas Breuer, Erzsébet Horváth. ## ## Copyright of GAP belongs to its developers, whose names are too numerous ## to list here. Please refer to the COPYRIGHT file for details. ## ## SPDX-License-Identifier: GPL-2.0-or-later ## ## This file contains the functions dealing with monomiality questions for ## solvable groups. ## ## 1. Character Degrees and Derived Length ## 2. Primitivity of Characters ## 3. Testing Monomiality ## 4. Minimal Nonmonomial Groups ##
############################################################################# ## ## 1. Character Degrees and Derived Length ##
############################################################################# ## #M Alpha( <G> ) . . . . . . . . . . . . . . . . . . . . . . . . for a group ##
InstallMethod( Alpha, "for a group",
[ IsGroup ], function( G )
local irr, # irreducible characters of `G'
degrees, # set of degrees of `irr'
chars, # at position <i> all in `irr' of degree `degrees[<i>]'
chi, # one character
alpha, # result list
max, # maximal derived length found up to now
kernels, # at position <i> the kernels of all in `chars[<i>]'
minimal, # list of minimal kernels
relevant, # minimal kernels of one degree
k, # one kernel
ker,
dl; # list of derived lengths
Info( InfoMonomial, 1, "Alpha called for group ", G );
# Compute the irreducible characters and the set of their degrees; # we need all irreducibles so it is reasonable to compute the table.
irr:= List( Irr( G ), ValuesOfClassFunction );
degrees:= Set( irr, x -> x[1] );
RemoveSet( degrees, 1 );
# Distribute characters to degrees.
chars:= List( degrees, x -> [] ); for chi in irr do if chi[1] > 1then
Add( chars[ Position( degrees, chi[1], 0 ) ], chi ); fi;
od;
# Initialize
alpha:= [ 1 ];
max:= 1;
# Compute kernels (as position lists)
kernels:= List( chars, x -> Set( x, ClassPositionsOfKernel ) );
# list of all minimal elements found up to now
minimal:= [];
Info( InfoMonomial, 1, "Alpha: There are ", Length( degrees )+1, " different degrees." );
for ker in kernels do
# We may remove kernels that contain a (minimal) kernel # of a character of smaller or equal degree.
# Make sure to consider minimal elements of the actual degree first.
SortBy( ker, Length );
relevant:= [];
for k in ker do if ForAll( minimal, x -> not IsSubsetSet( k, x ) ) then
# new minimal element found
Add( relevant, k );
Add( minimal, k );
fi;
od;
# Give the trivial kernel a chance to be found first when we # consider the next larger degree.
SortBy( minimal, Length );
# Compute the derived lengths for k in relevant do
dl:= DerivedLength( FactorGroupNormalSubgroupClasses(
OrdinaryCharacterTable( G ), k ) ); if dl > max then
max:= dl; fi;
############################################################################# ## #M Delta( <G> ) . . . . . . . . . . . . . . . . . . . . . . . . for a group ##
InstallMethod( Delta, "for a group",
[ IsGroup ], function( G )
local delta, # result list
alpha, # `Alpha( <G> )'
r; # loop variable
delta:= [ 1 ];
alpha:= Alpha( G ); for r in [ 2 .. Length( alpha ) ] do
delta[r]:= alpha[r] - alpha[r-1];
od;
return delta; end );
############################################################################# ## #M IsBergerCondition( <chi> ) . . . . . . . . . . . . . . . for a character ##
InstallMethod( IsBergerCondition, "for a class function",
[ IsClassFunction ], function( chi )
local tbl, # character table of <chi>
values, # values of `chi'
ker, # intersection of kernels of smaller degree
deg, # degree of <chi>
psi, # one irreducible character of $G$
kerchi, # kernel of <chi> (as group)
isberger; # result
Info( InfoMonomial, 1, "IsBergerCondition called for character ",
CharacterString( chi, "chi" ) );
values:= ValuesOfClassFunction( chi );
deg:= values[1];
tbl:= UnderlyingCharacterTable( chi );
if1 < deg then
# We need all characters of smaller degree, # so it is reasonable to compute the character table of the group
ker:= [ 1 .. Length( values ) ]; for psi in Irr( UnderlyingCharacterTable( chi ) ) do if DegreeOfCharacter( psi ) < deg then
IntersectSet( ker, ClassPositionsOfKernel( psi ) ); fi;
od;
# Check whether the derived group of this normal subgroup # lies in the kernel of `chi'.
kerchi:= ClassPositionsOfKernel( values ); if IsSubsetSet( kerchi, ker ) then
# no need to compute subgroups
isberger:= true; else
isberger:= IsSubset( KernelOfCharacter( chi ),
DerivedSubgroup( NormalSubgroupClasses( tbl, ker ) ) ); fi;
############################################################################# ## #M IsBergerCondition( <G> ) . . . . . . . . . . . . . . . . . . for a group ##
InstallMethod( IsBergerCondition, "for a group",
[ IsGroup ], function( G )
local tbl, # character table of `G'
psi, # one irreducible character of `G'
isberger, # result
degrees, # different character degrees of `G'
kernels, #
pos, #
i, # loop variable
leftinters, #
left, #
right; #
Info( InfoMonomial, 1, "IsBergerCondition called for group ", G );
tbl:= OrdinaryCharacterTable( G );
if Size( G ) mod 2 = 1then
isberger:= true;
else
# Compute the intersections of kernels of characters of same degree
degrees:= [];
kernels:= []; for psi in List( Irr( G ), ValuesOfClassFunction ) do
pos:= Position( degrees, psi[1], 0 ); if pos = fail then
Add( degrees, psi[1] );
Add( kernels, ShallowCopy( ClassPositionsOfKernel( psi ) ) ); else
IntersectSet( kernels[ pos ], ClassPositionsOfKernel( psi ) ); fi;
od;
SortParallel( degrees, kernels );
# Let $1 = f_1 \leq f_2 \leq\ldots \leq f_n$ the distinct # irreducible degrees of `G'. # We must have for all $1 \leq i \leq n-1$ that # $$ # ( \bigcap_{\psi(1) \leq f_i} \ker(\psi) )^{\prime} \leq # \bigcap_{\chi(1) = f_{i+1}} \ker(\chi) # $$
i:= 1;
isberger:= true;
leftinters:= kernels[1];
while i < Length( degrees ) and isberger do
# `leftinters' becomes $\bigcap_{\psi(1) \leq f_i} \ker(\psi)$.
IntersectSet( leftinters, kernels[i] ); if not IsSubsetSet( kernels[i+1], leftinters ) then
# we have to compute the groups
left:= DerivedSubgroup( NormalSubgroupClasses( tbl, leftinters ) );
right:= NormalSubgroupClasses( tbl, kernels[i+1] ); if not IsSubset( right, left ) then
isberger:= false;
Info( InfoMonomial, 1, "IsBergerCondition: violated for character of degree ",
degrees[i+1] ); fi;
############################################################################# ## ## 2. Primitivity of Characters ##
############################################################################# ## #F TestHomogeneous( <chi>, <N> ) ## ## This works also for reducible <chi>. ##
InstallGlobalFunction( TestHomogeneous, function( chi, N )
local t, # character table of `G'
classes, # class lengths of `t'
values, # values of <chi>
cl, # classes of `G' that form <N>
norm, # norm of the restriction of <chi> to <N>
tn, # table of <N>
fus, # fusion of conjugacy classes <N> in $G$
rest, # restriction of <chi> to <N>
i, # loop over characters of <N>
scpr; # one scalar product in <N>
values:= ValuesOfClassFunction( chi );
if IsList( N ) then
cl:= N; else
cl:= ClassPositionsOfNormalSubgroup( UnderlyingCharacterTable( chi ),
N ); fi;
if Length( cl ) = 1then
return rec( isHomogeneous := true,
comment := "restriction to trivial subgroup" ); fi;
t:= UnderlyingCharacterTable( chi );
classes:= SizesConjugacyClasses( t );
norm:= Sum( cl, c -> classes[c] * values[c]
* GaloisCyc( values[c], -1 ), 0 );
if norm = Sum( classes{ cl }, 0 ) then
# The restriction is irreducible.
return rec( isHomogeneous := true,
comment := "restricts irreducibly" );
else
# `chi' restricts reducibly. # Compute the table of `N' if necessary, # and check the constituents of the restriction
N:= NormalSubgroupClasses( t, cl );
tn:= CharacterTable( N );
fus:= FusionConjugacyClasses( tn, t );
rest:= values{ fus };
for i in Irr( tn ) do
scpr:= ScalarProduct( tn, ValuesOfClassFunction( i ), rest ); if scpr <> 0then
# Return info about the constituent.
return rec( isHomogeneous := ( scpr * DegreeOfCharacter( i )
= values[1] ),
comment := "restriction checked",
character := i,
multiplicity := scpr );
fi;
od;
fi; end );
############################################################################# ## #M TestQuasiPrimitive( <chi> ) . . . . . . . . . . . . . . . for a character ## ## This works also for reducible <chi>. ## Note that a representation affording <chi> maps the centre of <chi> ## to scalar matrices. ##
InstallMethod( TestQuasiPrimitive, "for a character",
[ IsCharacter ], function( chi )
local values, # list of character values
t, # character table of `chi'
nsg, # list of normal subgroups of `t'
cen, # centre of `chi'
j, # loop over normal subgroups
testhom, # test of homogeneous restriction
test; # result record
Info( InfoMonomial, 1, "TestQuasiPrimitive called for character ",
CharacterString( chi, "chi" ) );
values:= ValuesOfClassFunction( chi );
# Linear characters are primitive. if values[1] = 1then
test:= rec( isQuasiPrimitive := true,
comment := "linear character" ); else
t:= UnderlyingCharacterTable( chi );
# Compute the normal subgroups of `G' containing the centre of `chi'.
# Note that `chi' restricts homogeneously to all normal subgroups # of `G' if (and only if) it restricts homogeneously to all those # normal subgroups containing the centre of `chi'.
# {\em Proof:} # Let $N \unlhd G$ such that $Z(\chi) \not\leq N$. # We have to show that $\chi$ restricts homogeneously to $N$. # By our assumption $\chi_{N Z(\chi)}$ is homogeneous, # take $\vartheta$ the irreducible constituent. # Let $D$ a representation affording $\vartheta$ such that # the restriction to $N$ consists of block diagonal matrices # corresponding to the irreducible constituents. # $D( Z(\chi) )$ consists of scalar matrices, # thus $D( n^x ) = D( n )$ for $n\in N$, $x\in Z(\chi)$, # i.e., $Z(\chi)$ acts trivially on the irreducible constituents # of $\vartheta_N$, # i.e., every constituent of $\vartheta_N$ is invariant in $N Z(\chi)$, # i.e., $\vartheta$ (and thus $\chi$) restricts homogeneously to $N$.
cen:= ClassPositionsOfCentre( values );
nsg:= ClassPositionsOfNormalSubgroups( t );
nsg:= Filtered( nsg, x -> IsSubsetSet( x, cen ) );
############################################################################# ## #M IsQuasiPrimitive( <chi> ) . . . . . . . . . . . . . . . . for a character ##
InstallMethod( IsQuasiPrimitive, "for a character",
[ IsCharacter ],
chi -> TestQuasiPrimitive( chi ).isQuasiPrimitive );
############################################################################# ## #M IsPrimitiveCharacter( <chi> ) . . . . . . . . . . . . . . for a character ## ## Quasi-primitive irreducible characters of solvable groups are primitive, ## see for example [Isa76, Thm. 11.33]. ##
InstallMethod( IsPrimitiveCharacter, "for a class function",
[ IsClassFunction ], function( chi ) if not ( IsIrreducibleCharacter( chi ) and
IsSolvableGroup( UnderlyingGroup( chi ) ) ) then
TryNextMethod(); fi;
return TestQuasiPrimitive( chi ).isQuasiPrimitive; end );
local sizeN, # size of <N>
sizefactor, # size of $G / <N>$
values, # values list of `chi'
m, # list of all maximal normal subgroups of $G$
test, # intermediate result
tn, # character table of <N>
irr, # irreducibles of `tn'
i, # loop variable
scpr, # one scalar product in <N>
N, # optional second argument
cl, # classes corresponding to `N'
chi; # first argument
# check the arguments if Length( arg ) < 1 or Length( arg ) > 2
or not IsCharacter( arg[1] ) then
Error( "usage: TestInducedFromNormalSubgroup( <chi>[, <N>] )" ); fi;
chi:= arg[1];
Info( InfoMonomial, 1, "TestInducedFromNormalSubgroup called with character ",
CharacterString( chi, "chi" ) );
if Length( arg ) = 1then
# `TestInducedFromNormalSubgroup( <chi> )' if DegreeOfCharacter( chi ) = 1then
# Get all maximal normal subgroups.
m:= ClassPositionsOfMaximalNormalSubgroups(
UnderlyingCharacterTable( chi ) );
for N in m do
test:= TestInducedFromNormalSubgroup( chi, N ); if test.isInduced then
return test; fi;
od;
return rec( isInduced := false,
comment := "all maximal normal subgroups checked" ); fi;
else
# `TestInducedFromNormalSubgroup( <chi>, <N> )'
N:= arg[2];
# 1. If the degree of <chi> is not divisible by the index of <N> in $G$ # then <chi> cannot be induced from <N>. # 2. If <chi> does not vanish outside <N> it cannot be induced from # <N>. # 3. Provided that <chi> vanishes outside <N>, # <chi> is induced from <N> if and only if the restriction of <chi> # to <N> has an irreducible constituent with multiplicity 1. # # Since the scalar product of the restriction with itself has value # $G \: N$, multiplicity 1 means that there are $G \: N$ conjugates # of this constituent, so <chi> is induced from each of them. # # This gives another necessary condition that is easy to check. # Namely, <N> must have more than $G \: <N>$ conjugacy classes if # <chi> is induced from <N>.
if IsList( N ) then
sizeN:= Sum( SizesConjugacyClasses(
UnderlyingCharacterTable( chi ) ){ N }, 0 ); elif IsGroup( N ) then
sizeN:= Size( N ); else
Error( "<N> must be a group or a list" ); fi;
sizefactor:= Size( UnderlyingCharacterTable( chi ) ) / sizeN;
if DegreeOfCharacter( chi ) mod sizefactor <> 0then
return rec( isInduced := false,
comment := "degree not divisible by index" );
elif sizeN <= sizefactor then
return rec( isInduced := false,
comment := "<N> has too few conjugacy classes" );
fi;
values:= ValuesOfClassFunction( chi );
if IsList( N ) then
# Check whether the character vanishes outside <N>. for i in [ 2 .. Length( values ) ] do if not i in N and values[i] <> 0then
return rec( isInduced := false,
comment := "<chi> does not vanish outside <N>" ); fi;
od;
cl:= N;
N:= NormalSubgroupClasses( UnderlyingCharacterTable( chi ), N );
else
# Check whether <N> has less conjugacy classes than its index is. if Length( ConjugacyClasses( N ) ) <= sizefactor then
return rec( isInduced := false,
comment := "<N> has too few conjugacy classes" );
fi;
cl:= ClassPositionsOfNormalSubgroup( UnderlyingCharacterTable( chi ),
N );
# Check whether the character vanishes outside <N>. for i in [ 2 .. Length( values ) ] do if not i in cl and values[i] <> 0then
return rec( isInduced := false,
comment := "<chi> does not vanish outside <N>" ); fi;
od;
fi;
# Compute the restriction to <N>.
chi:= values{ FusionConjugacyClasses( OrdinaryCharacterTable( N ),
UnderlyingCharacterTable( chi ) ) };
# Check possible constituents.
tn:= CharacterTable( N );
irr:= Irr( N ); for i in [ 1 .. NrConjugacyClasses( tn ) - sizefactor + 1 ] do
scpr:= ScalarProduct( tn, ValuesOfClassFunction( irr[i] ), chi );
############################################################################# ## #M TestSubnormallyMonomial( <G> ) . . . . . . . . . . . . . . . for a group ##
InstallMethod( TestSubnormallyMonomial, "for a group",
[ IsGroup ], function( G )
local test, # result record
orbits, # orbits of characters
chi, # loop over `orbits'
found, # decision is found
i; # loop variable
Info( InfoMonomial, 1, "TestSubnormallyMonomial called for group ",
GroupString( G, "G" ) );
if IsNilpotentGroup( G ) then
# Nilpotent groups are subnormally monomial.
test:= rec( isSubnormallyMonomial:= true,
comment := "nilpotent group" );
else
# Check SM character by character, # one representative of each orbit under Galois conjugacy # and multiplication with linear characters only.
orbits:= OrbitRepresentativesCharacters( Irr( G ) );
# For each representative check whether it is SM. # (omit linear characters, i.e., first position)
found:= false;
i:= 2; while ( not found ) and i <= Length( orbits ) do
chi:= orbits[i]; if not TestSubnormallyMonomial( chi ).isSubnormallyMonomial then
# Return the result.
Info( InfoMonomial, 1, "TestSubnormallyMonomial returns with `",
test.isSubnormallyMonomial, "'" );
return test; end );
############################################################################# ## #M TestSubnormallyMonomial( <chi> ) . . . . . . . . . . . . for a character ##
InstallMethod( TestSubnormallyMonomial, "for a character",
[ IsClassFunction ], function( chi )
local test, # result record
testsm; # local function for recursive check
Info( InfoMonomial, 1, "TestSubnormallyMonomial called for character ",
CharacterString( chi, "chi" ) );
if DegreeOfCharacter( chi ) = 1then
# Linear characters are subnormally monomial.
test:= rec( isSubnormallyMonomial := true,
comment := "linear character",
character := chi );
elif HasIsSubnormallyMonomial( UnderlyingGroup( chi ) )
and IsSubnormallyMonomial( UnderlyingGroup( chi ) ) then
# If the group knows that it is subnormally monomial return this.
test:= rec( isSubnormallyMonomial := true,
comment := "subnormally monomial group",
character := chi );
elif IsNilpotentGroup( UnderlyingGroup( chi ) ) then
# Nilpotent groups are subnormally monomial.
test:= rec( isSubnormallyMonomial := true,
comment := "nilpotent group",
character := chi );
else
# We have to check recursively.
# Given a character `chi' of the group $N$, and two classes lists # `forbidden' and `allowed' that describe all maximal normal # subgroups of $N$, where `forbidden' denotes all those normal # subgroups through that `chi' cannot be subnormally induced, # return either a linear character of a subnormal subgroup of $N$ # from that `chi' is induced, or `false' if no such character exists. # If we reach a nilpotent group then we return a character of this # group, so the character is not necessarily linear.
testsm:= function( chi, forbidden, allowed )
local N, # group of `chi'
mns, # max. normal subgroups
forbid, #
n, # one maximal normal subgroup
cl,
len,
nt,
fus,
rest,
deg,
const,
nallowed,
nforbid,
gp,
fusgp,
test;
forbid:= ShallowCopy( forbidden );
N:= UnderlyingGroup( chi );
chi:= ValuesOfClassFunction( chi );
len:= Length( chi );
# Loop over `allowed'. for cl in allowed do
if ForAll( [ 1 .. len ], x -> chi[x] = 0 or x in cl ) then
# `chi' vanishes outside `n', so is induced from `n'.
n:= NormalSubgroupClasses( OrdinaryCharacterTable( N ), cl );
nt:= CharacterTable( n );
# Compute a constituent of the restriction of `chi' to `n'.
fus:= FusionConjugacyClasses( nt, OrdinaryCharacterTable( N ) );
rest:= chi{ fus };
deg:= chi[1] * Size( n ) / Size( N );
const:= First( Irr( n ),
x -> DegreeOfCharacter( x ) = deg
and ScalarProduct( nt, ValuesOfClassFunction( x ),
rest ) <> 0 );
# Check termination. if deg = 1 or IsNilpotentGroup( n ) then
return const; elif Length( allowed ) = 0then
return false; fi;
# Compute allowed and forbidden maximal normal subgroups of `n'.
mns:= ClassPositionsOfMaximalNormalSubgroups( nt );
nallowed:= [];
nforbid:= []; for gp in mns do
# A group is forbidden if it is the intersection of a group # in `forbid' with `n'.
fusgp:= Set( fus{ gp } ); if ForAny( forbid, x -> IsSubsetSet( x, fusgp ) ) then
Add( nforbid, gp ); else
Add( nallowed, gp ); fi;
od;
# Check whether `const' is subnormally induced from `n'.
test:= testsm( const, nforbid, nallowed ); if test <> false then
return test; fi;
fi;
# Add `n' to the forbidden subgroups.
Add( forbid, cl );
od;
# All allowed normal subgroups have been checked.
return false; end;
# Run the recursive search. # Here all maximal normal subgroups are allowed.
test:= testsm( chi, [], ClassPositionsOfMaximalNormalSubgroups(
UnderlyingCharacterTable( chi ) ) );
# Prepare the output. if test = false then
test:= rec( isSubnormallyMonomial := false,
comment := "all subnormal subgroups checked" ); elif DegreeOfCharacter( test ) = 1then
test:= rec( isSubnormallyMonomial := true,
comment := "reduced to linear character",
character := test ); else
test:= rec( isSubnormallyMonomial := true,
comment := "reduced to nilpotent subgroup",
character := test ); fi;
fi;
Info( InfoMonomial, 1, "TestSubnormallyMonomial returns with `",
test.isSubnormallyMonomial, "'" );
return test; end );
############################################################################# ## #M IsSubnormallyMonomial( <G> ) . . . . . . . . . . . . . . . . for a group #M IsSubnormallyMonomial( <chi> ) . . . . . . . . . . . . . for a character ##
InstallMethod( IsSubnormallyMonomial, "for a group",
[ IsGroup ],
G -> TestSubnormallyMonomial( G ).isSubnormallyMonomial );
InstallMethod( IsSubnormallyMonomial, "for a character",
[ IsClassFunction ],
chi -> TestSubnormallyMonomial( chi ).isSubnormallyMonomial );
############################################################################# ## #M IsMonomialNumber( <n> ) . . . . . . . . . . . . . for a positive integer ##
InstallMethod( IsMonomialNumber, "for a positive integer",
[ IsPosInt ], function( n )
local factors, # list of prime factors of `n'
collect, # list of (prime divisor, exponent) pairs
nu2, # $\nu_2(n)$
pair, # loop over `collect'
pair2, # loop over `collect'
ord; # multiplicative order
factors := Factors(Integers, n );
collect := Collected( factors );
# Get $\nu_2(n)$. if2 in factors then
nu2:= collect[1][2]; else
nu2:= 0; fi;
# Check for minimal nonmonomial groups of type 1. if nu2 >= 2then for pair in collect do if pair[1] mod 4 = 3 and pair[2] >= 3then
return false; fi;
od; fi;
# Check for minimal nonmonomial groups of type 2. if nu2 >= 3then for pair in collect do if pair[1] mod 4 = 1 and pair[2] >= 3then
return false; fi;
od; fi;
# Check for minimal nonmonomial groups of type 3. for pair in collect do for pair2 in collect do if pair[1] <> pair2[1] and pair2[1] <> 2then
ord:= OrderMod( pair[1], pair2[1] ); if ord mod 2 = 0 and ord < pair[2] then
return false; fi; fi;
od;
od;
# Check for minimal nonmonomial groups of type 4. if nu2 >= 4then for pair in collect do if pair[1] <> 2 and nu2 >= 2* OrderMod( 2, pair[1] ) + 2then
return false; fi;
od; fi;
# Check for minimal nonmonomial groups of type 5. if nu2 >= 2then for pair in collect do if pair[1] mod 4 = 1 and pair[2] >= 3then for pair2 in collect do if pair2[1] <> 2then
ord:= OrderMod( pair[1], pair2[1] ); if ord mod 2 = 1 and 2 * ord < pair[2] then
return false; fi; fi;
od; fi;
od; fi;
# None of the five cases can occur.
return true; end );
############################################################################# ## #M TestMonomialQuick( <chi> ) . . . . . . . . . . . . . . . for a character ## ## We assume that <chi> is an irreducible character. ##
InstallMethod( TestMonomialQuick, "for a character",
[ IsClassFunction ], function( chi )
local G, # group of `chi'
factsize, # size of the kernel factor of `chi'
codegree, # codegree of `chi'
pi, # prime divisors of a Hall subgroup
hall, # size of `pi' Hall subgroup of kernel factor
ker, # kernel of `chi'
t, # character table of `G'
grouptest; # result of the call to `G / ker'
Info( InfoMonomial, 1, "TestMonomialQuick called for character ",
CharacterString( chi, "chi" ) );
if HasIsMonomialCharacter( chi ) then
# The character knows about being monomial.
Info( InfoMonomial, 1, "TestMonomialQuick returns with `",
IsMonomialCharacter( chi ), "'" );
return rec( isMonomial := IsMonomialCharacter( chi ),
comment := "was already stored" );
elif DegreeOfCharacter( chi ) = 1then
# Linear characters are monomial.
Info( InfoMonomial, 1, "TestMonomialQuick returns with `true'" );
return rec( isMonomial := true,
comment := "linear character" );
fi;
G:= UnderlyingGroup( chi );
if Size( G ) mod DegreeOfCharacter( chi ) <> 0then
Info( InfoMonomial, 1, "TestMonomialQuick returns with `false'" );
return rec( isMonomial := false,
comment := "degree does not divide group order" ); fi;
# The following criteria are applicable only to irreducible characters. # We do *not* check here that 'chi' is really an irreducible character. if TestMonomialQuick( G ).isMonomial = true then
# The whole group is known to be monomial.
Info( InfoMonomial, 1, "TestMonomialQuick returns with `true'" );
return rec( isMonomial := true,
comment := "whole group is monomial" );
fi;
chi := ValuesOfClassFunction( chi );
# Replace `G' by the factor group modulo the kernel.
ker:= ClassPositionsOfKernel( chi ); if1 < Length( ker ) then
t:= CharacterTable( G );
factsize:= Size( G ) / Sum( SizesConjugacyClasses( t ){ ker }, 0 ); else
factsize:= Size( G ); fi;
# Inspect the codegree.
codegree := factsize / chi[1]; if IsPrimePowerInt( codegree ) then
# If the codegree is a prime power then the character is monomial, # by a result of Chillag, Mann, and Manz. # Here is a short proof due to M. I. Isaacs # (communicated by E. Horváth). # # Let $G$ be a finite group, $\chi\in Irr(G)$ with codegree $p^a$ # for a prime $p$, and $P\in Syl_p(G)$. # Then there exists an irreducible character $\psi$ of $P$ # with $\psi^G = \chi$. # # {\it Proof:} # Let $b$ be an integer such that $\chi(1) = [G : P] p^b$, # and consider $\chi_P = \sum_{\psi\in Irr(P)} a_{\psi} \psi$. # There exists $\psi$ with $a_{\psi} \not= 0$ and $\psi(1) \leq p^b$, # as otherwise $\chi(1)$ would be divisible by a larger power of $p$. # On the other hand, $\chi$ must be a constituent of $\psi^G$ and thus # $p^b \leq \psi(1)$. # So there is equality, and thus $\psi^G = \chi$.
Info( InfoMonomial, 1, "TestMonomialQuick returns with `true'" );
return rec( isMonomial := true,
comment := "codegree is prime power" ); fi;
# If $G$ is solvable and $\pi$ is the set of primes dividing the codegree # then the character is induced from a $\pi$ Hall subgroup. # This follows from Theorem~(2D) in~\cite{Fon62}. if IsSolvableGroup( G ) then
pi := PrimeDivisors( codegree );
hall := Product( Filtered( Factors(Integers, factsize ), x -> x in pi ), 1 );
if factsize / hall = chi[1] then
# The character is induced from a *linear* character # of the $\pi$ Hall group.
Info( InfoMonomial, 1, "TestMonomialQuick returns with `true'" );
return rec( isMonomial := true,
comment := "degree is index of Hall subgroup" );
elif IsMonomialNumber( hall ) then
# The *order* of this Hall subgroup is monomial.
Info( InfoMonomial, 1, "TestMonomialQuick returns with `true'" );
return rec( isMonomial := true,
comment := "induced from monomial Hall subgroup" );
fi;
fi;
# Inspect the factor group modulo the kernel. if1 < Length( ker ) then
# For solvable 'G', checking 'factsize' for monomiality does not # help here because the divisor 'hall' has been checked above.
if IsSubsetSet( ker, ClassPositionsOfSupersolvableResiduum(t) ) then
# The factor group modulo the kernel is supersolvable.
Info( InfoMonomial, 1, "TestMonomialQuick returns with `true'" );
return rec( isMonomial:= true,
comment:= "kernel factor group is supersolvable" );
fi;
grouptest:= TestMonomialQuick( FactorGroupNormalSubgroupClasses(
OrdinaryCharacterTable( G ), ker ) ); #T This is not cheap! if grouptest.isMonomial = true then
Info( InfoMonomial, 1, "#I TestMonomialQuick returns with `true'" );
return rec( isMonomial := true,
comment := "kernel factor group is monomial" );
fi;
fi;
# No more cheap tests are available.
Info( InfoMonomial, 1, "TestMonomialQuick returns with `?'" );
return rec( isMonomial := "?",
comment := "no decision by cheap tests" ); end );
############################################################################## ## #M TestMonomialQuick( <G> ) . . . . . . . . . . . . . . . . . . for a group ## ## The following criteria are used for a group <G>. ## ## o Nonsolvable groups are not monomial. ## o If the group order is monomial then <G> is monomial. ## (Note that monomiality of group orders is defined for solvable ## groups only, so solvability has to be checked first.) ## o Nilpotent groups are monomial. ## o Abelian by supersolvable groups are monomial. ## o Sylow abelian by supersolvable groups are monomial. ## (Compute the Sylow subgroups of the supersolvable residuum, ## and check whether they are abelian.) ##
InstallMethod( TestMonomialQuick, "for a group",
[ IsGroup ], function( G )
#T if the table is known then call TestMonomialQuick( G.charTable ) ! #T (and implement this function ...)
local test, # the result record
ssr; # supersolvable residuum of `G'
Info( InfoMonomial, 1, "TestMonomialQuick called for group ",
GroupString( G, "G" ) );
# If the group knows about being monomial return this. if HasIsMonomialGroup( G ) then
# Monomial groups are solvable.
test:= rec( isMonomial := false,
comment := "non-solvable group" );
elif IsMonomialNumber( Size( G ) ) then
# Every solvable group of this order is monomial.
test:= rec( isMonomial := true,
comment := "group order is monomial" );
elif IsNilpotentGroup( G ) then
# Nilpotent groups are monomial.
test:= rec( isMonomial := true,
comment := "nilpotent group" );
else
ssr:= SupersolvableResiduum( G );
if IsTrivial( ssr ) then
# Supersolvable groups are monomial.
test:= rec( isMonomial := true,
comment := "supersolvable group" );
elif IsAbelian( ssr ) then
# Abelian by supersolvable groups are monomial.
test:= rec( isMonomial := true,
comment := "abelian by supersolvable group" );
elif ForAll( PrimeDivisors( Size( ssr ) ),
x -> IsAbelian( SylowSubgroup( ssr, x ) ) ) then
# Sylow abelian by supersolvable groups are monomial.
test:= rec( isMonomial := true,
comment := "Sylow abelian by supersolvable group" );
else
# No more cheap tests are available.
test:= rec( isMonomial := "?",
comment := "no decision by cheap tests" );
fi;
fi;
Info( InfoMonomial, 1, "TestMonomialQuick returns with `", test.isMonomial, "'" );
return test; end );
############################################################################# ## #M TestMonomial( <chi> ) . . . . . . . . . . . . . . . . . . for a character #M TestMonomial( <chi>, <uselattice> ) . . . for a character, and a Boolean ## ## Called with an irreducible character <chi> as argument, ## `TestMonomialQuick( <chi> )' is inspected first; ## if this did not decide the question, ## we test all those normal subgroups of $G$ to which <chi> restricts ## nonhomogeneously whether the interesting character of the ## inertia subgroup is monomial. ## (If <chi> is quasiprimitive then it is nonmonomial.) ## If <chi> is not irreducible, these tests are not applicable. ## ## If <uselattice> is `true' or if the group of <chi> has order at most ## `TestMonomialUseLattice' then the subgroup lattice is used ## to decide the question if necessary. ##
BindGlobal( "TestMonomialFromLattice", function( chi )
local G, H, source;
G:= UnderlyingGroup( chi );
# Loop over representatives of the conjugacy classes of subgroups. for H in List( ConjugacyClassesSubgroups( G ), Representative ) do if IndexNC( G, H ) = chi[1] then
source:= First( LinearCharacters( H ), lambda -> lambda^G = chi ); if source <> fail then
return source; fi; fi;
od;
# Return the negative result.
return fail; end );
InstallMethod( TestMonomial, "for a character",
[ IsClassFunction ],
chi -> TestMonomial( chi, false ) );
InstallMethod( TestMonomial, "for a character, and a Boolean",
[ IsClassFunction, IsBool ], function( chi, uselattice )
local G, # group of `chi'
test, # result record
t, # character table of `G'
nsg, # list of normal subgroups of `G'
ker, # kernel of `chi'
isqp, # is `chi' quasiprimitive
i, # loop over normal subgroups
testhom, # does `chi' restrict homogeneously
theta, # constituent of the restriction
found, # monomial character found
found2, # monomial character found
T, # inertia group of `theta'
fus, # fusion of conjugacy classes `T' in `G'
deg, # degree of `theta'
rest, # restriction of `chi' to `T'
j, # loop over irreducibles of `T'
psi, # character of `T'
testmon; # test for monomiality
Info( InfoMonomial, 1, "TestMonomial called" );
# Start with elementary tests for monomiality. if HasIsMonomialCharacter( chi ) then # The character knows about being monomial.
test:= rec( isMonomial := IsMonomialCharacter( chi ),
comment := "was already stored" ); elif IsIrreducibleCharacter( chi ) then
test:= TestMonomialQuick( chi ); elif DegreeOfCharacter( chi ) = 1then # Linear characters are monomial.
test:= rec( isMonomial := true,
comment := "linear character" ); elif Size( UnderlyingGroup( chi ) ) mod DegreeOfCharacter( chi ) <> 0then
test:= rec( isMonomial := false,
comment := "degree does not divide group order" ); else
test:= rec( isMonomial:= "?" ); fi;
if test.isMonomial = "?"then
G:= UnderlyingGroup( chi );
if not IsSolvableGroup( G ) then
Info( InfoMonomial, 1, "TestMonomial: nonsolvable group" );
test:= rec( isMonomial := "?",
comment := "no criterion for nonsolvable group" ); elif not IsIrreducibleCharacter( chi ) then
Info( InfoMonomial, 1, "TestMonomial: reducible character" );
test:= rec( isMonomial := "?",
comment := "no criterion for reducible character" ); else
# Loop over all normal subgroups of `G' to that <chi> restricts # nonhomogeneously. # (If there are no such normal subgroups then <chi> is # quasiprimitive hence not monomial.)
t:= CharacterTable( G );
ker:= ClassPositionsOfKernel( ValuesOfClassFunction( chi ) );
nsg:= Filtered( ClassPositionsOfNormalSubgroups( t ),
x -> IsSubsetSet( x, ker ) );
isqp:= true;
i:= 1;
found:= false;
while not found and i <= Length( nsg ) do
testhom:= TestHomogeneous( chi, nsg[i] ); if not testhom.isHomogeneous then
isqp:= false;
# Take a constituent `theta' in a nonhomogeneous restriction.
theta:= testhom.character;
# We have $<chi>_N = e \sum_{i=1}^t \theta_i$. # <chi> is induced from an irreducible character of # $'T' = I_G(\theta_1)$ that restricts to $e \theta_1$, # so we have proved monomiality if $e = \theta(1) = 1$. if testhom.multiplicity = 1
and DegreeOfCharacter( theta ) = 1then
found:= true;
test:= rec( isMonomial := true,
comment := "induced from \'character\'",
character := theta );
else
# Compute the inertia group `T'.
T:= InertiaSubgroup( G, theta ); if TestMonomialQuick( T ).isMonomial = true then
# `chi' is induced from `T', and `T' is monomial.
found:= true;
test:= rec( isMonomial := true,
comment := "induced from monomial subgroup",
subgroup := T ); #T example?
else
# Check whether a character of `T' from that <chi> # is induced can be proved to be monomial.
# First get all characters `psi' of `T' # from that <chi> is induced.
t:= Irr( T );
fus:= FusionConjugacyClasses( OrdinaryCharacterTable( T ),
OrdinaryCharacterTable( G ) );
deg:= DegreeOfCharacter( chi ) / Index( G, T );
rest:= ValuesOfClassFunction( chi ){ fus };
j:= 1;
found2:= false; while not found2 and j <= Length(t) do if DegreeOfCharacter( t[j] ) = deg
and ScalarProduct( CharacterTable( T ),
ValuesOfClassFunction( t[j] ),
rest ) <> 0then
psi:= t[j];
testmon:= TestMonomial( psi ); if testmon.isMonomial = true then
found:= true;
found2:= true;
test:= testmon; fi; fi;
j:= j+1;
od;
fi;
fi;
fi;
i:= i+1;
od;
if isqp then
# <chi> is quasiprimitive, for a solvable group this implies # primitivity, # for a nonlinear character this proves nonmonomiality.
test:= rec( isMonomial := false,
comment := "quasiprimitive character" );
elif not found then
# We have tried all suitable normal subgroups and always got # back that the character of the inertia subgroup was # (possibly) nonmonomial.
test:= rec( isMonomial:= "?",
comment:= "all inertia subgroups checked, no result" );
fi;
fi;
if test.isMonomial = "?" and
( uselattice or Size( G ) <= TestMonomialUseLattice ) then # Use explicit computations with the subgroup lattice,
test:= TestMonomialFromLattice( chi ); if test = fail then
test:= rec( isMonomial := false,
comment := "lattice checked" ); else
test:= rec( isMonomial := true,
comment := "induced from \'character\'",
character := test ); fi; fi;
fi;
# Return the result.
Info( InfoMonomial, 1, "TestMonomial returns with `", test.isMonomial, "'" );
return test; end );
############################################################################# ## #M TestMonomial( <G> ) . . . . . . . . . . . . . . . . . . . . . for a group #M TestMonomial( <G>, <uselattice> ) . . . . . . for a group, and a Boolean ## ## Called with a group <G>, the program checks whether all representatives ## of character orbits are monomial. ##
InstallMethod( TestMonomial, "for a group",
[ IsGroup ],
G -> TestMonomial( G, false ) );
InstallMethod( TestMonomial, "for a group, and a Boolean",
[ IsGroup, IsBool ], function( G, uselattice )
local test, # result record
found, # monomial character found
testmon, # test for monomiality
j, # loop over irreducibles of `T'
psi, # character of `T'
orbits, # orbits of irreducibles of `T'
poss; # list of possibly nonmonomial characters
Info( InfoMonomial, 1, "TestMonomial called for a group" );
# elementary test for monomiality
test:= TestMonomialQuick( G );
if test.isMonomial = "?"then
if Size( G ) mod 2 = 0 and ForAny( Delta( G ), x -> 1 < x ) then
# For even order groups it is checked whether # the list `Delta( G )' contains an entry that is bigger # than one. (For monomial groups and for odd order groups # this is always less than one, # according to Taketa's Theorem and Berger's result).
test:= rec( isMonomial := false,
comment := "list Delta( G ) contains entry > 1" );
else
orbits:= OrbitRepresentativesCharacters( Irr( G ) );
found:= false;
j:= 2;
poss:= []; while j <= Length( orbits ) do
psi:= orbits[j];
testmon:= TestMonomial( psi, uselattice ).isMonomial; if testmon = false then
found:= true;
break; elif testmon = "?"then
Add( poss, psi ); fi;
j:= j+1;
od;
if found then
# A nonmonomial character was found.
test:= rec( isMonomial := false,
comment := "nonmonomial character found",
character := psi );
elif IsEmpty( poss ) then
# All checks answered `true'.
test:= rec( isMonomial := true,
comment := "all characters checked" );
else
# We give up.
test:= rec( isMonomial := "?",
comment := "(possibly) nonmon. characters found",
characters := poss );
fi;
fi;
fi;
# Return the result.
Info( InfoMonomial, 1, "TestMonomial returns with `", test.isMonomial, "'" );
return test; end );
############################################################################# ## #M IsMonomialGroup( <G> ) . . . . . . . . . . . . . . . . . . . for a group ##
InstallMethod( IsMonomialGroup, "for a group",
[ IsGroup ],
G -> TestMonomial( G, true ).isMonomial );
############################################################################# ## #M IsMonomialCharacter( <chi> ) . . . . . . . . . . . . . . for a character ##
InstallMethod( IsMonomialCharacter, "for a character",
[ IsClassFunction ],
chi -> TestMonomial( chi, true ).isMonomial );
############################################################################# ## #A TestRelativelySM( <G> ) #A TestRelativelySM( <chi> ) #F TestRelativelySM( <G>, <N> ) #F TestRelativelySM( <chi>, <N> ) ## ## The algorithm for a character <chi> and a normal subgroup <N> ## proceeds as follows. ## If <N> is abelian or has nilpotent factor then <chi> is relatively SM ## with respect to <N>. ## Otherwise we check whether <chi> restricts irreducibly to <N>; in this ## case we also get a positive answer. ## Otherwise a subnormal subgroup from that <chi> is induced must be ## contained in a maximal normal subgroup of <N>. So we get all maximal ## normal subgroups containing <N> from that <chi> can be induced, take a ## character that induces to <chi>, and check recursively whether it is ## relatively subnormally monomial with respect to <N>. ## ## For a group $G$ we consider only representatives of character orbits. ##
BindGlobal( "TestRelativelySMFun", function( arg )
local test, # result record
G, # argument, group
chi, # argument, character of `G'
N, # argument, normal subgroup of `G'
n, # classes in `N'
t, # character table of `G'
nsg, # list of normal subgroups of `G'
newnsg, # filtered list of normal subgroups
orbits, # orbits on `t.irreducibles'
found, # not relatively SM character found?
i, # loop over `nsg'
j, # loop over characters
fus, # fusion of conjugacy classes `N' in `G'
norm, # norm of restriction of `chi' to `N'
isrelSM, # is the constituent relatively SM?
check, #
induced, # is a subnormal subgroup found from where # the actual character can be induced?
k; # loop over `newnsg'
# step 1: # Check the arguments. if Length( arg ) < 1 or 2 < Length( arg )
or not ( IsGroup( arg[1] ) or IsCharacter( arg[1] ) ) then
Error( "first argument must be a group or a character" ); elif HasTestRelativelySM( arg[1] ) then
return TestRelativelySM( arg[1] ); fi;
if IsGroup( arg[1] ) then
G:= arg[1];
Info( InfoMonomial, 1, "TestRelativelySM called with group ", GroupString( G, "G" ) ); elif IsCharacter( arg[1] ) then
G:= UnderlyingGroup( arg[1] );
chi:= ValuesOfClassFunction( arg[1] );
Info( InfoMonomial, 1, "TestRelativelySM called with character ",
CharacterString( arg[1], "chi" ) ); fi;
# step 2: # Get the interesting normal subgroups.
# We want to consider normal subgroups and factor groups. # If this test yields a solution we can avoid to compute # the character table of `G'. # But if the character table of `G' is already known we use it # and store the factor groups.
if Length( arg ) = 1then
# If a normal subgroup <N> is abelian or has nilpotent factor group # then <G> is relatively SM w.r. to <N>, so consider only the other # normal subgroups.
if HasOrdinaryCharacterTable( G ) then
nsg:= ClassPositionsOfNormalSubgroups( CharacterTable( G ) );
newnsg:= []; for n in nsg do if not CharacterTable_IsNilpotentFactor( CharacterTable( G ),
n ) then
N:= NormalSubgroupClasses( CharacterTable( G ), n ); #T geht das? #T if IsSubset( n, centre ) and if not IsAbelian( N ) then
Add( newnsg, N ); fi; fi;
od;
nsg:= newnsg;
else
nsg:= NormalSubgroups( G );
nsg:= Filtered( nsg, x -> not IsAbelian( x ) and
not IsNilpotentGroup( G / x ) );
fi;
elif Length( arg ) = 2then
nsg:= [];
if IsList( arg[2] ) then
if not CharacterTable_IsNilpotentFactor( CharacterTable( G ),
arg[2] ) then
N:= NormalSubgroupClasses( CharacterTable( G ), arg[2] ); if not IsAbelian( N ) then
nsg[1]:= N; fi; fi;
elif IsGroup( arg[2] ) then
N:= arg[2]; if not IsAbelian( N ) and not IsNilpotentGroup( G / N ) then
nsg[1]:= N; fi;
else
Error( "second argument must be normal subgroup or classes list" ); fi;
fi;
# step 3: # Test whether all characters are relatively SM for all interesting # normal subgroups.
if IsEmpty( nsg ) then
test:= rec( isRelativelySM := true,
comment := "normal subgroups are abelian or have nilpotent factor group" );
else
t:= CharacterTable( G ); if IsGroup( arg[1] ) then
# Compute representatives of orbits of characters.
orbits:= OrbitRepresentativesCharacters( Irr( t ) );
orbits:= orbits{ [ 2 .. Length( orbits ) ] };
else
orbits:= [ chi ]; fi;
# Loop over all normal subgroups in `nsg' and all # irreducible characters in `orbits' until a not rel. SM # character is found.
found:= false;
i:= 1; while ( not found ) and i <= Length( nsg ) do
N:= nsg[i];
j:= 1; while ( not found ) and j <= Length( orbits ) do
#T use the kernel or centre here!! #T if N does not contain the centre of chi then we need not test? #T Isn't it sufficient to consider the factor modulo #T the product of `N' and kernel of `chi'?
chi:= orbits[j];
# Is the restriction of `chi' to `N' irreducible? # This means we can choose $H = G$.
n:= ClassPositionsOfNormalSubgroup( OrdinaryCharacterTable( G ),
N );
fus:= FusionConjugacyClasses( OrdinaryCharacterTable( N ),
OrdinaryCharacterTable( G ) );
norm:= Sum( n,
c -> SizesConjugacyClasses( CharacterTable( G ) )[c] * chi[c]
* GaloisCyc( chi[c], -1 ), 0 );
if norm = Size( N ) then
test:= rec( isRelativelySM := true,
comment := "irreducible restriction",
character := Character( G, chi ) );
else
# If there is a subnormal subgroup $H$ from where <chi> is # induced then $H$ is contained in a maximal normal subgroup # of $G$ that contains <N>.
# So compute all maximal subgroups ...
newnsg:= ClassPositionsOfMaximalNormalSubgroups(
CharacterTable( G ) );
# ... containing <N> ...
newnsg:= Filtered( newnsg, x -> IsSubsetSet( x, n ) );
# ... from where <chi> possibly can be induced.
newnsg:= List( newnsg,
x -> TestInducedFromNormalSubgroup(
Character( G, chi ),
NormalSubgroupClasses( CharacterTable( G ),
x ) ) );
induced:= false;
k:= 1; while not induced and k <= Length( newnsg ) do
check:= newnsg[k]; if check.isInduced then
# check whether the constituent is relatively SM w.r. to <N>
isrelSM:= TestRelativelySM( check.character, N ); if isrelSM.isRelativelySM then
induced:= true; fi;
fi;
k:= k+1;
od;
if induced then
test:= rec( isRelativelySM := true,
comment := "suitable character found"
); if IsBound( isrelSM.character ) then
test.character:= isrelSM.character; fi; else
test:= rec( isRelativelySM := false,
comment := "all possibilities checked" ); fi;
# All characters are rel. SM w.r. to all normal subgroups.
test:= rec( isRelativelySM := true,
comment := "all possibilities checked" ); fi;
fi;
Info( InfoMonomial, 1, "TestRelativelySM returns with `", test, "'" );
return test; end );
InstallMethod( TestRelativelySM, "for a character",
[ IsClassFunction ],
TestRelativelySMFun );
InstallMethod( TestRelativelySM, "for a group",
[ IsGroup ],
TestRelativelySMFun );
InstallOtherMethod( TestRelativelySM, "for a character, and an object",
[ IsClassFunction, IsObject ],
TestRelativelySMFun );
InstallOtherMethod( TestRelativelySM, "for a group, and an object",
[ IsGroup, IsObject ],
TestRelativelySMFun );
############################################################################# ## #M IsRelativelySM( <chi> ) #M IsRelativelySM( <G> ) ##
InstallMethod( IsRelativelySM, "for a character",
[ IsClassFunction ],
chi -> TestRelativelySM( chi ).isRelativelySM );
InstallOtherMethod( IsRelativelySM, "for a group",
[ IsGroup ],
G -> TestRelativelySM( G ).isRelativelySM );
############################################################################# ## ## 4. Minimal Nonmonomial Groups ##
############################################################################# ## #M IsMinimalNonmonomial( <G> ) . . . . . . . . . . . for a (solvable) group ## ## We use the classification by van der Waall. ##
InstallMethod( IsMinimalNonmonomial, "for a (solvable) group",
[ IsGroup ], function( K )
local F, # Fitting subgroup
factsize, # index of `F' in `K'
facts, # prime factorization of the order of `F'
p, # prime dividing the order of `F'
m, # `F' is of order $p ^ m $
syl, # Sylow subgroup
sylgen, # one generator of `syl'
gens, # generators list
C, # centre of `K' in dihedral case
fc, # element in $F C$
q; # half of `factsize' in dihedral case
# Check whether `K' is solvable. if not IsSolvableGroup( K ) then
TryNextMethod(); fi;
# Compute the Fitting factor of the group.
F:= FittingSubgroup( K );
factsize:= Index( K, F );
# The Fitting subgroup of a minimal nomonomial group is a $p$-group.
facts:= Factors(Integers, Size( F ) );
p:= Set( facts ); if1 < Length( p ) then
return false; fi;
p:= p[1];
m:= Length( facts );
# Check for the five possible structures. if factsize = 4then
# If $K$ is minimal nonmonomial then # $K / F(K)$ is cyclic of order 4, # $F(K)$ is extraspecial of order $p^3$ and of exponent $p$ # where $p \equiv -1 \pmod{4}$.
if IsPrimeInt( p )
and p >= 3
and ( p + 1 ) mod 4 = 0
and m = 3
and Centre( F ) = FrattiniSubgroup( F )
and Size( Centre( F ) ) = p then
# Check that the factor is cyclic and acts irreducibly. # For that, it is sufficient that the square acts # nontrivially.
syl:= SylowSubgroup( K, 2 ); if IsCyclic( syl )
and ForAny( GeneratorsOfGroup( syl ),
x -> Order( x ) = 4
and ForAny( GeneratorsOfGroup( F ),
y -> not IsOne( Comm( y, x^2 ) ) ) ) then
SetIsMonomialGroup( K, false );
return true; fi;
fi;
elif factsize = 8then
# If $K$ is minimal nonmonomial then # $K / F(K)$ is quaternion of order 8, # $F(K)$ is extraspecial of order $p^3$ and of exponent $p$ # where $p \equiv 1 \pmod{4}$.
if IsPrimeInt( p )
and p >= 5
and ( p - 1 ) mod 4 = 0
and m = 3
and Centre( F ) = FrattiniSubgroup( F )
and Size( Centre( F ) ) = p then
# Check whether $K/F(K)$ is quaternion of order 8, # (i.e., is nonabelian with two *generators* of order 4 that do # not generate the same subgroup) # and that it acts irreducibly on $F$ # For that, it is sufficient to show that the central involution # acts nontrivially.
syl:= SylowSubgroup( K, 2 );
gens:= Filtered( GeneratorsOfGroup( syl ), x -> Order( x ) = 4 ); if not IsAbelian( syl )
and ForAny( gens,
x -> x <> gens[1]
and x <> gens[1]^(-1)
and ForAny( GeneratorsOfGroup( F ),
y -> not IsOne( Comm( y, x^2 ) ) ) ) then
SetIsMonomialGroup( K, false );
return true; fi;
fi;
elif factsize <> 2 and IsPrimeInt( factsize ) then
# If $K$ is minimal nonmonomial then # $K / F(K)$ has order an odd prime $q$. # $F(K)$ is extraspecial of order $p^{2m+1}$ and of exponent $p$ # where $2m$ is the order of $p$ modulo $q$.
if OrderMod( p, factsize ) = m-1
and m mod 2 = 1
and Centre( F ) = FrattiniSubgroup( F )
and Size( Centre( F ) ) = p then
# Furthermore, $F / Z(F)$ is a chief factor. # It is sufficient to show that the Fitting factor acts # trivially on $Z(F)$, and that there is no nontrivial # fixed point under the action on $F / Z(F)$. # These conditions are sufficient for our test.
syl:= SylowSubgroup( K, factsize );
sylgen:= First( GeneratorsOfGroup( syl ), g -> not IsOne( g ) ); if IsCentral( Centre( F ), syl )
and ForAny( GeneratorsOfGroup( F ),
x -> not x in Centre( F )
and not IsOne( Comm( x, sylgen ) ) ) then
SetIsMonomialGroup( K, false );
return true; fi;
fi;
elif factsize mod 2 = 0 and IsPrimeInt( factsize / 2 ) then
# If $K$ is minimal nonmonomial then # $K / F(K)$ is dihedral of order $2 q$ where $q$ is an odd prime. # Let $m$ denote the order of 2 mod $q$. # $F(K)$ is a central product of an extraspecial group $F$ of order # $2^{2m+1}$ (that is purely dihedral) with a cyclic group $C$ # of order $2^{s+1}$. # We have $C = Z(K)$ and $F(K) = C_K( F/Z(F) )$.
q:= factsize / 2;
m:= OrderMod( 2, q );
if m mod 2 = 1then
# Compute a Sylow $q$ subgroup $Q$, with generator $r$.
syl:= SylowSubgroup( K, q );
sylgen:= First( GeneratorsOfGroup( syl ), g -> not IsOne( g ) );
# Show that the Fitting factor is dihedral. if not IsConjugate( K, sylgen, sylgen^-1 ) then
return false; fi;
# The centralizer of $Q$ is $Q \times C$. # Take an element $fc$ in $F(K) \setminus C$ with $f\in F$, # $c\in C$ (exists, since otherwise $Q$ would centralize $F(K)$), # and consider $[r,fc] = [r,f] \in F$. This commutator cannot lie # in $Z = F \cap C$ since this would imply that $r^2$ fixes $f$, # because of odd order this means $r$ fixes $f$, a contradiction. # Thus we find $F$ as the normal closure of $[r,f]$, # of order $2^{2m+1}$.
C:= SylowSubgroup( Centralizer( K, syl ), 2 );
fc:= First( GeneratorsOfGroup( F ), x -> not x in C );
F:= NormalClosure( K, Subgroup( K, [ Comm( sylgen, fc ) ] ) );
if Size( F ) <> 2^(2*m+1)
or IsAbelian( F )
or not IsCentral( K, C )
or not IsCyclic( C )
or Size( Intersection( F, C ) ) <> 2then
return false; fi;
# Now $Q$ acts nontrivially on $F$, and because every nontrivial # irreducible 2-modular representation of $D_{2q}$ has degree # $2m$ we have necessarily $F / Z$ an irreducible module, thus # $F$ must be extraspecial.
SetIsMonomialGroup( K, false );
return true;
fi;
elif factsize mod 4 = 0 and IsPrimeInt( factsize / 4 ) then
# $K / F(K)$ is a central extension of the dihedral group of order # $2 t$ where $t$ is an odd prime, such that all involutions lift to # elements of order 4. $F(K)$ is an extraspecial $p$-group # for an odd prime $p$ with $p \equiv 1 \pmod{4}$. # Let $m$ denote the order of $p$ mod $t$, then $F(K)$ is of order # $p^{2m+1}$, and $m$ is odd.
if m mod 2 <> 0
and ( p - 1 ) mod 4 = 0
and OrderMod( p, factsize / 4 ) = ( m-1 ) / 2
and Centre( F ) = FrattiniSubgroup( F )
and Size( Centre( F ) ) = p then
# Check whether the factor has the required isomorphism type, # i.e., whether it is of order $4t$ where $t$ is an odd prime, # and each element of order 4 inverts a generator of the # Sylow $t$ subgroup (then the presentation is satisfied).
# Check whether the action of the factor on $F$ is irreducible. # Since every faithful representation is of the required # dimension we must only check that the central involution and # the generator of the Sylow $t$ subgroup both act nontrivially.
syl:= SylowSubgroup( K, factsize / 4 );
sylgen:= First( GeneratorsOfGroup( syl ), g -> not IsOne( g ) );
gens:= Filtered( GeneratorsOfGroup( SylowSubgroup( K, 2 ) ),
x -> Order( x ) = 4 );
if not IsEmpty( gens )
and sylgen * gens[1] * sylgen = gens[1]
and ForAny( GeneratorsOfGroup( F ),
x -> not IsOne( Comm( gens[1], x ) ) )
and ForAny( GeneratorsOfGroup( F ),
x -> not IsOne( Comm( sylgen, x ) ) ) then
SetIsMonomialGroup( K, false );
return true;
fi;
fi;
fi;
# None of the structure conditions is satisfied.
return false; end );
InstallMethod( IsMinimalNonmonomial, "for a non-solvable group",
[ IsGroup ], function( K )
local info, q, p, f;
if IsSolvableGroup(K) then
TryNextMethod(); fi;
# Monomial groups are solvable. A minimal-nonmonomial group by # definition has every proper quotient and every proper subgroup # monomial, hence a non-solvable minimal-nonmonomial group must # have every proper subgroup and every proper quotient be solvable. # If [G,G] were proper, it would have to be solvable, and thus G # solvable, hence G is perfect. If G had any proper normal subgroups # then the quotient would have to be both perfect and solvable, so # G must be simple. if not IsSimpleGroup(K) then
return false; fi;
# Indeed, it must be minimal simple as classified by Corollary 1 in # Thompson's 1968 N-Groups paper, doi:10.1090/S0002-9904-1968-11953-6 # * PSL(2,2^f) for f prime, and all such are minimal-non-M groups # * PSL(2,3^f) for f an odd prime, and all such are minimal-non-M groups # * PSL(2,p) for p a prime congruent to 2 or 3 mod 5, and all such are m-n-M # * PSL(3,3) which is NOT a minimal-non-M group (contains SL(2,3)) # * Sz(2^f) for f an odd prime, and all such are minimal-non-M groups # # The minimal-non-M part follows from the fact that metabelian groups # are monomial groups. # * For PSL(2,q) Dickson classified their subgroups; the maximal ones are # either metabelian (hence monomial) or non-solvable; but this latter case # is ruled out here by being minimal simple; hence these groups are minimal # non-monomial. # * For PSL(3,3) a subgroup isomorphic to SL(2,3) is not an M-group # * For Sz(q), Suzuki 1960 shows that maximal subgroups are either the # normalizer H of a Sylow 2-group Q, or one of a few metabelian groups. # The characters of H are calculated in section 11, page 126, and # are all induced from the monomial group Q. # As an induced character can only be irreducible if the original # character was irreducible, and every irreducible of Q is induced # from a linear, and induction from that subgroup of Q and then to # H is the same as induction directly to H, we get that every # character of H is induced from a linear character (q-1 from H itself, # 1 from Q, and 2 from a subgroup of Q). I.e., H is monomial. #
info := IsomorphismTypeInfoFiniteSimpleGroup(K); if info.series = "A"then
return info.parameter = 5; # A5 = PSL(2,4) is minimal non-monomial elif info.series = "L"then if info.parameter[1] = 2then# GAP reports PSL(3,2)=PSL(2,7) as [2,7]
q := info.parameter[2];
p := SmallestRootInt(q);
f := LogInt(q,p); if p = 2 and IsPrimeInt(f) then return true; elif p = 3 and IsOddInt(f) and IsPrimeInt(f) then return true; elif p = q and 0 = (p^2+1) mod 5then return true; fi; fi; elif info.series = "2B"then
q := info.parameter;
f := LogInt(q,2);
return IsPrimeInt(f); fi;
return false; end);
local K, # free group
Kgens, # free generators of `K'
rels, # relators of `K'
name, # name of `K'
t, # number with suitable multiplicative order
form, # matrix of the commutator form
x, # indeterminate
val, # one entry in `form'
i, # loop
j, # loop
v, # coefficient vector
rhs, # right hand side of a relator when viewed as relation
q, # another name for `factsize' 2m, # exponent of size of Frattini factor of group $F$
m, # half of `2m'
facts, # factors of cylotomic polynomial
coeff, # coefficients vector of one factor in `facts'
inv, # inverse of first in `coeff'
f, # `GF(2)'
s, # exponent of centre (minus 1) in dihedral case
W, # part of matrix of an order 2 automorphism
Winv, # part of matrix of an order 2 automorphism
Atr; # transposed of $A$
if factsize = 4then
# $K / F(K)$ is cyclic of order 4, # $F(K)$ is extraspecial of order $p^3$ and of exponent $p$ # where $p \equiv -1 \pmod{4}$.
if not IsPrimeInt( p ) or p < 3 or ( p + 1 ) mod 4 <> 0then
Info( InfoMonomial, 1, "<p> must be a prime congruent 1 mod 4" );
return fail; fi;
K:= FreeGroup(IsSyllableWordsFamily, 5 );
Kgens:= GeneratorsOfGroup( K );
name:= Concatenation( String(p), "^(1+2):4" );
rels:= [ # the relators of the cyclic group
Kgens[1]^2 / Kgens[2], Kgens[2]^2,
# the relators of the extraspecial group
Kgens[3]^p, Kgens[4]^p, Kgens[5]^p,
Kgens[4]^Kgens[3] / ( Kgens[4] * Kgens[5]^-1 ),
# the action of the cyclic group
Kgens[3]^Kgens[1] / Kgens[4],
Kgens[4]^Kgens[1] / Kgens[3]^-1,
Kgens[3]^Kgens[2] / Kgens[3]^-1,
Kgens[4]^Kgens[2] / Kgens[4]^-1 ];
elif factsize = 8then
# $K / F(K)$ is quaternion of order 8, # $F(K)$ is extraspecial of order $p^3$ and of exponent $p$ # where $p \equiv 1 \pmod{4}$.
if not IsPrimeInt( p ) or p < 5 or ( p - 1 ) mod 4 <> 0then
Info( InfoMonomial, 1, "<p> must be a prime congruent 1 mod 4" );
return fail; fi;
# Choose $t$ with $t^2 \equiv -1 \pmod{p}$.
t:= PrimitiveRootMod( p ) ^ ( (p-1)/4 );
K:= FreeGroup(IsSyllableWordsFamily, 6 );
Kgens:= GeneratorsOfGroup( K );
name:= Concatenation( String(p), "^(1+2):Q8" );
rels:= [ # the relators of the quaternion group
Kgens[1]^2 / Kgens[3], Kgens[2]^2 / Kgens[3], Kgens[3]^2,
(Kgens[2]^Kgens[1] ) / ( Kgens[2]^-1 ),
# the relators of the extraspecial group
Kgens[4]^p, Kgens[5]^p, Kgens[6]^p,
Kgens[5]^Kgens[4] / ( Kgens[5]*Kgens[6]^-1 ),
# the action of the quaternion group
Kgens[4]^Kgens[1] / Kgens[4]^t,
Kgens[5]^Kgens[1] / Kgens[5]^( (1/t) mod p ),
Kgens[4]^Kgens[2] / Kgens[5],
Kgens[5]^Kgens[2] / Kgens[4]^-1,
Kgens[4]^Kgens[3] / Kgens[4]^-1,
Kgens[5]^Kgens[3] / Kgens[5]^-1 ];
elif factsize <> 2 and IsPrimeInt( factsize ) then
# $K / F(K)$ has order an odd prime $q$. # $F(K)$ is extraspecial of order $p^{2m+1}$ and of exponent $p$ # where $2m$ is the order of $p$ modulo $q$,
q:= factsize; 2m:= OrderMod( p, q );
if2m = 0 or 2m mod 2 <> 0then
Info( InfoMonomial, 1, "order of <p> mod <factsize> must be nonzero and even" );
return fail; fi;
m:= 2m / 2;
# The `q'-th cyclotomic polynomial splits over the field with # `p' elements into factors of degree `2*m'.
facts:= Factors( CyclotomicPolynomial( GF(p), q ) );
# Take the coefficients i$a_1, a_2, \ldots, a_{2m}, 1$ of a factor.
coeff:= IntVecFFE(
- CoefficientsOfLaurentPolynomial( facts[1] )[1] );
# Compute the vector $\epsilon$.
v:= [];
v[ 2m-1 ]:= 1; for i in [ m .. 2m-2 ] do
v[i]:= 0;
od; for j in [ m-1, m-2 .. 1 ] do
v[j]:= coeff[ j+2 ] - coeff[j]; for i in [ 1 .. m-j-1 ] do
v[j]:= v[j] + v[ m-i ] * coeff[ m+i+j+1 ];
od;
v[j]:= v[j] mod p;
od;
# Write down the presentation,
K:= FreeGroup(IsSyllableWordsFamily, 2m+2 );
Kgens:= GeneratorsOfGroup( K );
name:= Concatenation( String(p), "^(1+", String( 2m ), "):",
String(q) );
# power relators \ldots
rels:= [ Kgens[1]^q ]; if p = 2then for j in [ 2 .. 2m+1 ] do
Add( rels, Kgens[j]^p / Kgens[2m+2] );
od;
Add( rels, Kgens[ 2m+2 ]^p ); else for j in [ 2 .. 2m+2 ] do
Add( rels, Kgens[j]^p );
od; fi;
# \ldots action of the automorphism, \ldots for j in [ 2 .. 2m ] do
Add( rels, Kgens[j]^Kgens[1] / Kgens[j+1] );
od;
rhs:= One( K ); for j in [ 1 .. 2m ] do
rhs:= rhs * Kgens[j+1]^Int( coeff[j] );
od;
Add( rels, Kgens[2m+1]^Kgens[1] / rhs );
# \ldots and commutator relators. for i in [ 3 .. 2m+1 ] do for j in [ 2 .. i-1 ] do
Add( rels, Kgens[i]^Kgens[j]
/ ( Kgens[i] * Kgens[2m+2]^v[ 2m+j-i ] ) );
od;
od;
elif factsize mod 2 = 0 and IsPrimeInt( factsize / 2 ) then
# $K / F(K)$ is dihedral of order $2 q$ where $q$ is an odd prime. # Let $m$ denote the order of 2 mod $q$ (which is odd). # $F(K)$ is a central product of an extraspecial group $F$ of order # $2^{2m+1}$ (that is purely dihedral) with a cyclic group $C$ # of order $2^{s+1}$. Note that in this case the second argument # is $s+1$. # We have $C = Z(K)$ and $F(K) = C_K( F/Z(F) )$.
s:= p-1;
q:= factsize / 2;
m:= OrderMod( 2, q );
if m mod 2 = 0then
Info( InfoMonomial, 1, "order of 2 mod <factsize>/2 must be odd" );
return fail; fi;
# The first generator is $t$, the second is $r$, # generators 3 to $3+s-1$ are the powers of $t$ that are # not contained in $Z(K)$.
K:= FreeGroup(IsSyllableWordsFamily, 2*m + s + 3 );
Kgens:= GeneratorsOfGroup( K );
name:= Concatenation( "2^(1+", String( 2*m ), ")" ); if0 < s then
name:= Concatenation( "(", name, "Y", String( 2^(s+1) ), ")" ); fi;
name:= Concatenation( name, ":D", String( factsize ) );
rels:= [];
# $t^2$ is a generator of $Z(K)$. if s = 0then
# $t$ squares to $z$ or the identity, since for $s = 0$ we have # $Z(K) = \langle z \rangle$. # Here we choose the identity in order to get Dade\'s example.
rels[1]:= Kgens[1]^2 / One( K );
else
# Describe the cyclic group spanned by $t^2$.
rels[1]:= Kgens[1]^2 / Kgens[2]; for i in [ 2 .. s ] do
rels[i]:= Kgens[i]^2 / Kgens[i+1];
od;
rels[ s+1 ]:= Kgens[ s+1 ]^2 / Kgens[ 2*m+s+3 ];
fi;
# The $(s+2)$-nd generator is $r$, that of order $q$.
rels[ s+2 ]:= Kgens[ s+2 ]^q;
# The remaining $2m+1$ generators form the extraspecial group $F$. for i in [ s+3 .. 2*m+s+3 ] do
rels[ i+1 ]:= Kgens[ i ]^2;
od; for i in [ 1 .. m ] do
Add( rels, Kgens[ s+2+m+i ]^Kgens[ s+2+i ]
/ ( Kgens[ s+2+m+i ] / Kgens[ 2*m+s+3 ] ) );
od;
# Describe the actions of $t$ and $r$ on $F$. # First we construct the matrices of the linear actions on the # Frattini factor of $F$. (Note that because of even characteristic # the sign plays no role here.)
f:= GF(2);
facts:= Factors( CyclotomicPolynomial( f, q ) );
coeff:= CoefficientsOfLaurentPolynomial( facts[1] )[1];
Atr:= NullMat( m, m, f ); for i in [ 1 .. m-1 ] do
Atr[i+1][i]:= One( f );
od; for i in [ 1 .. m ] do
Atr[i][m]:= coeff[i];
od;
v:= Zero( f );
v:= List( Atr, x -> v );
v[1]:= One( f );
W:= [ v ]; for i in [ 2 .. m ] do
v:= v * Atr;
W[i]:= v;
od;
Winv:= W^-1;
W := List( W , IntVecFFE );
Winv := List( Winv, IntVecFFE );
coeff := IntVecFFE( coeff );
# The action of $t$ is described by `W' and its inverse. for i in [ s+3 .. s+m+2 ] do
rhs:= One( K ); for j in [ 1 .. m ] do
rhs:= rhs * Kgens[ s+2+m+j ]^W[i-s-2][j];
od;
Add( rels, Kgens[i] ^ Kgens[1] / rhs );
od; for i in [ s+m+3 .. s+2*m+2 ] do
rhs:= One( K ); for j in [ 1 .. m ] do
rhs:= rhs * Kgens[ s+2+j ]^Winv[i-s-m-2][j];
od;
Add( rels, Kgens[i] ^ Kgens[1] / rhs );
od;
# The action of $r$ is described by $A$ and its transposed inverse. # (first half) for i in [ s+3 .. s+m+1 ] do
Add( rels, Kgens[i] ^ Kgens[s+2] / Kgens[i+1] );
od;
rhs:= One( K ); for j in [ 1 .. m ] do
rhs:= rhs * Kgens[ s+2+j ]^coeff[j];
od;
Add( rels, Kgens[ s+m+2 ] ^ Kgens[s+2] / rhs );
# (second half) for i in [ s+m+3 .. s+2*m+1 ] do
Add( rels, Kgens[i] ^ Kgens[s+2]
/ ( Kgens[s+m+3]^coeff[i-s-m-1] * Kgens[i+1] ) );
od;
Add( rels, Kgens[ s+2*m+2 ] ^ Kgens[s+2] / Kgens[s+m+3] );
elif factsize mod 4 = 0 and IsPrimeInt( factsize / 4 ) then
# $K / F(K)$ is a central extension of the dihedral group of order # $2 t$ where $t$ is an odd prime, such that all involutions lift to # elements of order 4. $F(K)$ is an extraspecial $p$-group # for an odd prime $p$ with $p \equiv 1 \pmod{4}$. # Let $m$ denote the order of $p$ mod $t$, then $F(K)$ is of order # $p^{2m+1}$, and $m$ is odd.
t:= factsize / 4;
m:= OrderMod( p, t );
if m mod 2 = 0 or ( p - 1 ) mod 4 <> 0then
Info( InfoMonomial, 1, "order of <p> mod <t> must be odd, <p> congr. 1 mod 4" );
return fail; fi;
# The symplectic form (that will be used to define the # commutator form) is derived from the standard symplectic form # for the 2-dimensional vector space over $GF(p^{2m})$ by first # blowing up to the $2m$ dimensional vector space over $GF(p)$, # and then projecting onto $GF(p)$ (that is, the first component).
# (We need only the lower triangle of the matrix of the form, # and this is nonzero only in the lower left square.)
form:= []; for i in [ 1 .. m ] do
form[i]:= []; for j in [ 1 .. m-i+1 ] do
form[i][j]:= 0;
od;
od;
form[1][1]:= -1;
x:= Indeterminate( GF(p) ); for i in [ 2 .. m ] do
val:= CoefficientsOfLaurentPolynomial(
x^(i+m-2) mod facts[1] );
val:= - Int( ShiftedCoeffs( val[1], val[2] )[1] ); for j in [ i .. m ] do
form[ m+i-j ][j]:= val;
od;
od;
# Write down the presentation.
K:= FreeGroup(IsSyllableWordsFamily, 2*m + 4 );
Kgens:= GeneratorsOfGroup( K );
name:= Concatenation( String(p), "^(1+", String( 2*m), "):2.D",
String( factsize/2 ) );
# power relations,
rels:= [ Kgens[1]^2 / Kgens[3], Kgens[2]^t / Kgens[3], Kgens[3]^2 ]; for i in [ 4 .. 2*m+4 ] do
Add( rels, Kgens[i]^p );
od;
# action of the Frattini factor, # first the order 4 element for i in [ 4 .. m+3 ] do
Add( rels, Kgens[i]^Kgens[1] / Kgens[ i+m ]^-1 );
Add( rels, Kgens[ i+m ]^Kgens[1] / Kgens[i] );
od;
Add( rels, Kgens[2] ^ Kgens[1] / Kgens[2]^-1 );
# (The element of order $2t$ ...) for i in [ 4 .. m+2 ] do
Add( rels, Kgens[i]^Kgens[2] / Kgens[i+1]^-1 );
od;
rhs:= One( K ); for i in [ 1 .. m ] do
rhs:= rhs * Kgens[ i+3 ]^coeff[i];
od;
Add( rels, Kgens[ m+3 ]^Kgens[2] / rhs );
rhs:= One( K ); for i in [ 1 .. m ] do
rhs:= rhs * Kgens[ m+i+3 ]^( coeff[i+1] * inv );
od;
Add( rels, Kgens[ m+4 ]^Kgens[2] / rhs );
for i in [ 5 .. m+3 ] do
Add( rels, Kgens[ m+i ]^Kgens[2] / Kgens[ m+i-1 ]^-1 );
od;
# (The central involution of the Fitting factor inverts.) for i in [ 4 .. m+3 ] do
Add( rels, Kgens[i]^Kgens[3] / Kgens[i]^-1 );
Add( rels, Kgens[ i+m ]^Kgens[3] / Kgens[ i+m ]^-1 );
od;
# The extraspecial group is defined by the commutator form # constructed above. for i in [ m+1 .. 2*m ] do for j in [ 1 .. m ] do
Add( rels, Kgens[i+3]^Kgens[j+3]
/ ( Kgens[i+3] * Kgens[ 2*m + 4 ]^form[i-m][j] ) );
od;
od;
else
return fail; fi;
K:= PolycyclicFactorGroup( K, rels );
ConvertToStringRep( name );
SetName( K, name );
SetIsMinimalNonmonomial( K, true );
return K; end );
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.138Bemerkung:
(vorverarbeitet am 2026-10-12)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.