Skip to content

Commit

Permalink
Enhance DirectFactorsOfGroup for faster StructureDescription
Browse files Browse the repository at this point in the history
The default DirectFactorsOfGroup attribute has undergone a serious
enhancement, without having proper documentation, yet.

- The Kayal-Nezhmetdinov algorithm is implemented with some tweaks under the
  attribute DirectFactorsOfGroupKN. From now on, it is referred to as the
  KN method.
  Some parts of the code is reused in the main DirectFactorsOfGroup
  attribute, but there are no direct calls to DirectFactorsOfGroupKN.
- The KN method has an algorithm for computing a direct complement to a
  normal subgroup. This is implemented in the operation
  ComplementNormalSubgroup. This particular operation (in theory) should
  work for infinite groups, as well.
- The main DirectFactorsOfGroup algorithm works as follows:
  - for Abelian groups computes the decomposition to cyclic groups of
    prime-power order,
    (for infinite Abelian groups the output is only a list of the direct
    factors instead of a set, because calling Set on the factors might
    not finish running in reasonable time;
    infinite non-Abelian groups are not handled, at all)
  - for nilpotent groups it calls itself on the Sylow subgroups,
  - checks several sufficient conditions for the group being direct
    indecomposable,
  - looks for Abelian cyclic components from the center of the group,
  - checks for more sufficient conditions for the group being direct
    indecomposable,
  - computes the normal subgroups and the minimal normal subgroups, and
    calls DirectFactorsOfGroupFromList.
- DirectFactorsOfGroupFromList is a more efficient version of the old
  factorization method. It essentially searches through the normal subgroups
  (2nd argument, which is a list) by size and looks for a complement from
  the same list. If it finds a complement then the first factor is direct
  indecomposable, the second is decomposed further using the same list
  filtered from the clearly noncomplemented normal subgroups.
  Trivial intersection is checked by IsTrivialNormalIntersectionInList,
  which checks if any of the minimal subgroups (3rd argument, which is a
  list) is contained in both normal subgroups. This is faster than computing
  the normal intersection and checking if that is trivial.
- IsTrivialNormalIntersection is implemented in cases where one knows more
  about the structure of the group.
- Cases where the group is already a direct product or already has
  NormalSubgroups computed are handled in separate methods.
- Some lines contained a space at their end, these spaces are all removed
  automatically by the text editor.

Tested on SmallGroups of order different than 512, 768, 1024, 1280, 1536,
1792, and on a couple hundred test permutation groups.

More times than not the new method was significantly (>200ms, >10%) faster
than the old method, in many cases because it immediately found the group
is direct indecomposable, rather than spending much time computing the
normal subgroups.

The KN method seems to be drastically slower if the direct factors are
non-Abelian. Computing normal subgrups in such cases is much faster.
However, the implementation is kept for possible future enhancements.
  • Loading branch information
hungaborhorvath committed Nov 28, 2015
1 parent 905b502 commit a73a532
Show file tree
Hide file tree
Showing 2 changed files with 627 additions and 63 deletions.
91 changes: 63 additions & 28 deletions lib/grpnames.gd
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,26 @@
## Markus Püschel and Sebastian Egner.
##

#############################################################################
##
#O IsTrivialNormalIntersection( <G>, <U>, <V> ) . . . . . . . generic method
##
## <ManSection>
## <Oper Name="IsTrivialNormalIntersection" Arg="G, U, V"/>
##
## <Description>
## For normal subgroups U and V of G, IsTrivialNormalIntersection returns
## true if U and V intersect trivially, and false otherwise.
## If U and V are not normal subgroups of G, then it may return true
## even if they have a nontrivial intersection.
## </Description>
## </ManSection>
##
DeclareOperation( "IsTrivialNormalIntersection",[IsGroup, IsGroup, IsGroup]);
# checks if arg2 and arg3 both contain the first generator of any element in
# the given list arg1 of (minimal) normal subgroups
DeclareOperation( "IsTrivialNormalIntersectionInList",[IsList, IsGroup, IsGroup]);

#############################################################################
##
#A DirectFactorsOfGroup( <G> ) . . . . . decomposition into a direct product
Expand All @@ -36,7 +56,7 @@
## (4) <G> = <G1> * .. * <Gr> as the complex product.
## (5) $Gi \cap (G1 * .. * G_{i-1} * G_{i+1} * .. * Gr) = 1$.
##
## Factorization of a permutation group into a direct product
## Factorization of a permutation group into a direct product
## ==========================================================
##
## Def.: Seien G1, .., Gr endliche Gruppen, dann ist
Expand Down Expand Up @@ -73,24 +93,24 @@
## Remark:
## The normal subgroup lattice of G does not contain
## all the information needed for the normal subgroup lattice
## of G2 for a decomposition G = G1 x G2. However let
## of G2 for a decomposition G = G1 x G2. However let
## G = G1 x .. x Gr be finest direct product decomposition
## then all Gi are normal subgroups in G. Thus all Gi occur in
## the set NormalSubgroups(G) and we may split G recursively
## the set NormalSubgroups(G) and we may split G recursively
## without recomputing normal subgroup lattices for factors.
##
## Method to enumerate factorizations given the divisors:
## Consider a strictly increasing chain
## 1 < a1 < a2 < .. < a_n < A
## of positive divisors of an integer A.
## of positive divisors of an integer A.
## The task is to enumerate all pairs 1 <= i <= j <= n
## such that a_i*a_j = A. This is done by
##
## i := 1;
## i := 1;
## j := n;
## while i <= j do
## while j > i and a_i*a_j > A do
## j := j-1;
## while i <= j do
## while j > i and a_i*a_j > A do
## j := j-1;
## end while;
## if a_i*a_j = A then
## "found i <= j with a_i*a_j = A"
Expand All @@ -100,11 +120,11 @@
##
## which is based on the following fact:
## Lemma:
## Let i1 <= j1, i2 <= j2 be such that
## Let i1 <= j1, i2 <= j2 be such that
## a_i1*a_j1 = a_i2*a_j2 = A, then
## i2 > i1 ==> j2 < j1.
## Proof:
## i2 > i1
## i2 > i1
## ==> a_i2 > a_i1 by strictly increasing a's
## ==> a_i1*a_j1 = A = a_i2*a_j2 > a_i1*a_j2 by *a_j2
## ==> a_j1 > a_j2 by /a_i1
Expand All @@ -122,6 +142,21 @@
## and where it is in the b-sequence if any. The the
## linear algorithm above may be used.
##

## The Kayal-Nezhmetdinov algorithm is described in
## Neeraj Kayal and Timur Nezhmetdinov, Factoring Groups Efficiently, in
## International Colloquium on Automata, Languages and Programming (ICALP) ,
## Springer Verlag, 2009.
# Gives a normal complement to the second argument if exists, fail otherwise.
# In theory it finds the normal complement for infinite groups, as well,
# but has an infinite loop if g/N is Abelian for infinite N.
DeclareOperation( "ComplementNormalSubgroup", [IsGroup, IsGroup]);
DeclareOperation( "ComplementNormalSubgroupNC", [IsGroup, IsGroup]);
# Kayal-Nezhmetdinov algorithm with only a few tweaks
DeclareAttribute( "DirectFactorsOfGroupKN", IsGroup );
# checks if there are factors from first list
# trivial intersection is checked if both contain anyone from second list
DeclareGlobalFunction( "DirectFactorsOfGroupFromList", [IsGroup, IsList, IsList]);
DeclareAttribute( "DirectFactorsOfGroup", IsGroup );

#############################################################################
Expand All @@ -142,7 +177,7 @@ DeclareAttribute( "DirectFactorsOfGroup", IsGroup );
##
## Literatur:
## [1] Huppert Bd. I, Springer 1983.
## [2] M. Hall: Theory of Groups. 2nd ed.,
## [2] M. Hall: Theory of Groups. 2nd ed.,
## Chelsea Publ. Co., 1979 NY.
##
## Zerlegung eines semidirekten Produkts, Grundlagen
Expand All @@ -160,7 +195,7 @@ DeclareAttribute( "DirectFactorsOfGroup", IsGroup );
## (1) |H| * |N| = |G| und
## (2) |H meet N| = 1.
## Dann gibt es ein f mit G = H semidirect[f] N.
## Bew.: [2], Th. 6.5.3.
## Bew.: [2], Th. 6.5.3.
##
## Lemma2:
## Sei G = H semidirect[phi] N und h in H, n in N, dann ist auch
Expand Down Expand Up @@ -193,7 +228,7 @@ DeclareAttribute( "SemidirectFactorsOfGroup", IsGroup );
## A <E>decomposition type</E> <A>type</A> is denoted by a specification
## of the form
## <Log><![CDATA[
## <type> ::=
## <type> ::=
## <integer> ; cyclic group of prime power order
## | ["non-split", <integer>] ; non-split extension; size annotated
## | ["x", <type>, .., <type>] ; non-trivial direct product (ass., comm.)
Expand Down Expand Up @@ -235,7 +270,7 @@ DeclareAttribute( "DihedralGenerators", IsGroup );
## <Attr Name="QuaternionGenerators" Arg="G"/>
##
## <Description>
## Indicates whether the group <A>G</A> is a generalized quaternion group
## Indicates whether the group <A>G</A> is a generalized quaternion group
## of size <M>N = 2^(k+1)</M>, <M>k >= 2</M>. If it is, methods may set
## the attribute <C>QuaternionGenerators</C> to [<A>t</A>,<A>s</A>],
## where <A>t</A> and <A>s</A> are two elements such that <A>G</A> =
Expand All @@ -256,7 +291,7 @@ DeclareAttribute( "QuaternionGenerators", IsGroup );
## <Attr Name="QuasiDihedralGenerators" Arg="G"/>
##
## <Description>
## Indicates whether the group <A>G</A> is a quasidihedral group
## Indicates whether the group <A>G</A> is a quasidihedral group
## of size <M>N = 2^(k+1)</M>, <M>k >= 2</M>. If it is, methods may set
## the attribute <C>QuasiDihedralGenerators</C> to [<A>t</A>,<A>s</A>],
## where <A>t</A> and <A>s</A> are two elements such that <A>G</A> =
Expand Down Expand Up @@ -286,11 +321,11 @@ DeclareProperty( "IsPSL", IsGroup );

#############################################################################
##
#A ParametersOfGroupViewedAsPSL
#A ParametersOfGroupViewedAsSL
#A ParametersOfGroupViewedAsPSL
#A ParametersOfGroupViewedAsSL
#A ParametersOfGroupViewedAsGL
##
## triples (n,p,e) such that the group is isomorphic to PSL(n,p^e), SL(n,p^e)
## triples (n,p,e) such that the group is isomorphic to PSL(n,p^e), SL(n,p^e)
## and GL(n,p^e) respectively
##
## <ManSection>
Expand Down Expand Up @@ -362,7 +397,7 @@ DeclareAttribute( "GLUnderlyingField", IsGroup );
## |GL(n, p, e)| = Product(p^(e n) - p^(e k) : k in [0..n-1])
## |SL(n, p, e)| = |GL(n, p, e)| / (p^e - 1)
## |PSL(n, p, e)| = |SL(n, p, e)| / gcd(p^e - 1, n)
##
##
DeclareGlobalFunction( "SizeGL" );
DeclareGlobalFunction( "SizeSL" );
DeclareGlobalFunction( "SizePSL" );
Expand All @@ -386,7 +421,7 @@ DeclareGlobalFunction( "SizePSL" );
## </ManSection>
##
## Lemma (o.B.):
## Es bezeichne
## Es bezeichne
##
## gl(n, p, e) = Product(p^(e n) - p^(e k) : k in [0..n-1])
## sl(n, p, e) = gl(n, p, e) / (p^e - 1)
Expand All @@ -402,15 +437,15 @@ DeclareGlobalFunction( "SizePSL" );
## und in diesen F"allen sind die dazugeh"origen Gruppen auch
## isomorph. Dar"uberhinaus existieren genau die folgenden
## sporadischen "Ubereinstimmungen
##
##
## psl(2, 2, 2) = psl(2, 5, 1) = 60 ; PSL(2, 4) ~= PSL(2, 5) ~= A5
## psl(2, 7, 1) = psl(3, 2, 1) = 168 ; PSL(2, 7) ~= PSL(3, 2)
## psl(4, 2, 1) = psl(3, 2, 2) = 20160 ; PSL(4, 2) not~= PSL(3, 4)
##
## wobei in den ersten beiden F"allen die dazugeh"origen Gruppen
##
## wobei in den ersten beiden F"allen die dazugeh"origen Gruppen
## isomorph sind, im letzten Fall aber nicht! Die Gruppen PSL(4, 2)
## und PSL(3, 4) sind "uber das Zentrum ihrer 2-Sylowgruppen
## unterscheidbar (Huppert: S.185).
## unterscheidbar (Huppert: S.185).
## Es bezeichne Z1, Z2 die Zentren der 2-Sylowgruppen von PSL(4, 2)
## bzw. PSL(3, 4). Dann ist |Z1| = 2 und |Z2| = 4.
##
Expand Down Expand Up @@ -447,7 +482,7 @@ DeclareGlobalFunction( "LinearGroupParameters" );
## the following form: <P/>
## <Listing><![CDATA[
## StructureDescription(<G>) ::=
## 1 ; trivial group
## 1 ; trivial group
## | C<size> ; cyclic group
## | A<degree> ; alternating group
## | S<degree> ; symmetric group
Expand Down Expand Up @@ -552,7 +587,7 @@ DeclareGlobalFunction( "LinearGroupParameters" );
## </Item>
## <Mark>4.</Mark>
## <Item>
## <M>\phi: H \rightarrow</M> Aut(<M>N</M>),
## <M>\phi: H \rightarrow</M> Aut(<M>N</M>),
## <M>h \mapsto (n \mapsto n^h)</M> is injective.
## </Item>
## </List>
Expand Down Expand Up @@ -599,11 +634,11 @@ DeclareGlobalFunction( "LinearGroupParameters" );
## gap> List(l,StructureDescription);; l;
## [ C3 : C4, C12, A4, D12, C6 x C2 ]
## gap> List(AllSmallGroups(40),G->StructureDescription(G:short));
## [ "5:8", "40", "5:8", "5:Q8", "4xD10", "D40", "2x(5:4)", "(10x2):2",
## [ "5:8", "40", "5:8", "5:Q8", "4xD10", "D40", "2x(5:4)", "(10x2):2",
## "20x2", "5xD8", "5xQ8", "2x(5:4)", "2^2xD10", "10x2^2" ]
## gap> List(AllTransitiveGroups(DegreeAction,6),
## > G->StructureDescription(G:short));
## [ "6", "S3", "D12", "A4", "3xS3", "2xA4", "S4", "S4", "S3xS3",
## [ "6", "S3", "D12", "A4", "3xS3", "2xA4", "S4", "S4", "S3xS3",
## "(3^2):4", "2xS4", "A5", "(S3xS3):2", "S5", "A6", "S6" ]
## gap> StructureDescription(PSL(4,2));
## "A8"
Expand Down
Loading

0 comments on commit a73a532

Please sign in to comment.