#############################################################################
##
#W  grp.gd                      GAP library                     Thomas Breuer
#W                                                             & Frank Celler
#W                                                             & Bettina Eick
#W                                                           & Heiko Theissen
##
#H  @(#)$Id: grp.gd,v 4.188.2.6 2008/11/25 09:35:27 gap Exp $
##
#Y  Copyright (C)  1997,  Lehrstuhl D fuer Mathematik,  RWTH Aachen,  Germany
#Y  (C) 1998 School Math and Comp. Sci., University of St.  Andrews, Scotland
#Y  Copyright (C) 2002 The GAP Group
##
##  This file contains the declarations of operations for groups.
##

#1
##  Unless explicitly declared otherwise, all subgroup series are descending.
##  That is they are stored in decreasing order.


#2
##  If a group <U> is created as a subgroup of another group <G>, <G>
##  becomes the parent of <U>. There is no `universal' parent group,
##  parent-child chains can be arbitrary long. {\GAP} stores the result of some
##  operations (such as `Normalizer') with the parent as an attribute.

Revision.grp_gd :=
    "@(#)$Id: grp.gd,v 4.188.2.6 2008/11/25 09:35:27 gap Exp $";


#############################################################################
##
#V  InfoGroup
##
##  is the info class for the generic group theoretic functions
##  (see~"Info Functions").
##
DeclareInfoClass( "InfoGroup" );


#############################################################################
##
#C  IsGroup( <obj> )
##
##  A group is a magma-with-inverses (see~"IsMagmaWithInverses")
##  and associative (see~"IsAssociative") multiplication.
##
##  `IsGroup' tests whether the object <obj> fulfills these conditions,
##  it does *not* test whether <obj> is a set of elements that forms a group
##  under multiplication;
##  use `AsGroup' (see~"AsGroup") if you want to perform such a test.
##  (See~"Categories" for details about categories.)
##
DeclareSynonym( "IsGroup", IsMagmaWithInverses and IsAssociative );

InstallTrueMethod( IsFiniteOrderElementCollection, IsGroup and IsFinite );


#############################################################################
##
#A  GeneratorsOfGroup( <G> )
##
##  returns a list of generators of the group <G>.
##  If <G> has been created by the command `GroupWithGenerators'
##  (see~"GroupWithGenerators"), with argument <gens>, then
##  the list returned by `GeneratorsOfGroup' will be equal to <gens>.
##
DeclareSynonymAttr( "GeneratorsOfGroup", GeneratorsOfMagmaWithInverses );


#############################################################################
##
#O  GroupString( <G>, <name> )
##
##  returns a short string (usually less than one line) with information
##  about the group <G>. <name> is a display name if the group <G> does
##  not have one.
DeclareOperation( "GroupString", [IsGroup,IsString] );


#############################################################################
##
#A  NameIsomorphismClass( <G> ) . . . . . . . . . . . . . . . .  experimental
##
DeclareAttribute( "NameIsomorphismClass", IsGroup );


#############################################################################
##
#P  IsCyclic( <G> )
##
##  A group is *cyclic* if it can be generated by one element.
##  For a cyclic group, one can compute a generating set consisting of only
##  one element using `MinimalGeneratingSet' (see~"MinimalGeneratingSet").
##
DeclareProperty( "IsCyclic", IsGroup );

InstallSubsetMaintenance( IsCyclic, IsGroup and IsCyclic, IsGroup );

InstallFactorMaintenance( IsCyclic,
    IsGroup and IsCyclic, IsObject, IsGroup );

InstallTrueMethod( IsCyclic, IsGroup and IsTrivial );

InstallTrueMethod( IsCommutative, IsGroup and IsCyclic );


#############################################################################
##
#P  IsElementaryAbelian( <G> )
##
##  A group <G> is elementary abelian if it is commutative and if there is a
##  prime $p$ such that the order of each element in <G> divides $p$.
##
DeclareProperty( "IsElementaryAbelian", IsGroup );

InstallSubsetMaintenance( IsElementaryAbelian,
    IsGroup and IsElementaryAbelian, IsGroup );

InstallFactorMaintenance( IsElementaryAbelian,
    IsGroup and IsElementaryAbelian, IsObject, IsGroup );

InstallTrueMethod( IsElementaryAbelian, IsGroup and IsTrivial );


#############################################################################
##
#P  IsFinitelyGeneratedGroup( <G> )
##
##  tests whether the group <G> can be generated by a finite number of
##  generators. (This property is mainly used to obtain finiteness
##  conditions.)
##
##  Note that this is a pure existence statement. Even if a group is known
##  to be generated by a finite number of elements, it can be very hard or
##  even impossible to obtain such a generating set if it is not known.
##
DeclareProperty( "IsFinitelyGeneratedGroup", IsGroup );

InstallFactorMaintenance( IsFinitelyGeneratedGroup,
    IsGroup and IsFinitelyGeneratedGroup, IsObject, IsGroup );

InstallTrueMethod( IsFinitelyGeneratedGroup, IsGroup and IsTrivial );

#############################################################################
##
#P  IsSubsetLocallyFiniteGroup(<U>) . . . . test if a group is locally finite
##
##  A group is called locally finite if every finitely generated subgroup is
##  finite. This property checks whether the group <U> is a subset of a
##  locally finite group. This is used to check whether finite generation
##  will imply finiteness, as it does for example for permutation groups.
##
DeclareProperty( "IsSubsetLocallyFiniteGroup", IsGroup );

# this true method will enforce that many groups are finite, which is needed
# implicitly
InstallTrueMethod( IsFinite, IsFinitelyGeneratedGroup and IsGroup
                             and IsSubsetLocallyFiniteGroup );

InstallTrueMethod( IsSubsetLocallyFiniteGroup, IsFinite and IsGroup );

InstallSubsetMaintenance( IsSubsetLocallyFiniteGroup,
    IsGroup and IsSubsetLocallyFiniteGroup, IsGroup );


#############################################################################
##
#M  IsSubsetLocallyFiniteGroup( <G> ) . . . . . . . . . .  for magmas of FFEs
##
InstallTrueMethod( IsSubsetLocallyFiniteGroup, IsFFECollection and IsMagma );


#############################################################################
#3
##  The following filters and operations indicate capabilities of {\GAP}.
##  They can be used in the method selection or algorithms to check whether
##  it is feasible to compute certain operations for a given group.
##  In general, they return `true' if good algorithms for the given arguments
##  are available in {\GAP}.
##  An answer `false' indicates that no method for this group may exist,
##  or that the existing methods might run into problems.
##
##  Typical examples when this might happen is with finitely presented
##  groups, for which many of the methods cannot be guaranteed to succeed in
##  all situations.
##
##  The willingness of {\GAP} to perform certain operations may change,
##  depending on which further information is known about the arguments.
##  Therefore the filters used are not implemented as properties but as
##  ``other filters'' (see~"Properties" and~"Other Filters").
##


#############################################################################
##
#F  CanEasilyTestMembership( <grp> )
##
##  This filter indicates whether a group can test membership of
##  elements in <grp> (via the operation `in') in reasonable time.
##  It is used by the method selection to decide whether an algorithm
##  that relies on membership tests may be used.
##
DeclareFilter( "CanEasilyTestMembership" );


#############################################################################
##
#F  CanComputeSizeAnySubgroup( <grp> )
##
##  This filter indicates whether <grp> can easily compute the size of any
##  subgroup. (This is for example advantageous if one can test that a
##  stabilizer index equals the length of the orbit computed so far to stop
##  early.)
##
DeclareFilter( "CanComputeSizeAnySubgroup" );

InstallTrueMethod(CanEasilyTestMembership,CanComputeSizeAnySubgroup);
InstallTrueMethod(CanComputeSize,CanComputeSizeAnySubgroup);

InstallTrueMethod( CanComputeSize, IsTrivial );

# these implications can create problems with some fp groups. Therefore we
# are a bit less eager
#InstallTrueMethod( CanComputeSizeAnySubgroup, IsTrivial );
#InstallTrueMethod( CanEasilyTestMembership, IsTrivial );


#############################################################################
##
#F  CanComputeIndex( <G>, <H> )
##
##  This filter indicates whether the index $[G:H]$ (which might
##  be `infinity') can be computed. It assumes that $H\le G$. (see
##  "CanComputeIsSubset")
DeclareOperation( "CanComputeIndex", [IsGroup,IsGroup] );


#############################################################################
##
#P  KnowsHowToDecompose( <G> )
#O  KnowsHowToDecompose( <G>, <gens> )
##
##  Tests whether the group <G> can decompose elements in the generators
##  <gens>. If <gens> is not given it tests, whether it can decompose in the
##  generators given in `GeneratorsOfGroup'.
##
##  This property can be used for example to check whether a
##  `GroupHomomorphismByImages' can be reasonably defined from this group.
DeclareProperty( "KnowsHowToDecompose", IsGroup );
DeclareOperation( "KnowsHowToDecompose", [ IsGroup, IsList ] );


#############################################################################
##
#P  IsPGroup( <G> ) . . . . . . . . . . . . . . . . .  is a group a p-group ?
##
##  A *$p$-group* is a finite group whose order (see~"Size") is of the form
##  $p^n$ for a prime integer $p$ and a nonnegative integer $n$.
##  `IsPGroup' returns `true' if <G> is a $p$-group, and `false' otherwise.
##
DeclareProperty( "IsPGroup", IsGroup );

InstallSubsetMaintenance( IsPGroup,
    IsGroup and IsPGroup, IsGroup );

InstallFactorMaintenance( IsPGroup,
    IsGroup and IsPGroup, IsObject, IsGroup );

InstallTrueMethod( IsPGroup, IsGroup and IsTrivial );
InstallTrueMethod( IsPGroup, IsGroup and IsElementaryAbelian );


#############################################################################
##
#A  PrimePGroup( <G> )
##
##  If <G> is a nontrivial $p$-group (see~"IsPGroup"), `PrimePGroup' returns
##  the prime integer $p$;
##  if <G> is trivial then `PrimePGroup' returns `fail'.
##  Otherwise an error is issued.
##
DeclareAttribute( "PrimePGroup", IsPGroup );


#############################################################################
##
#A  PClassPGroup( <G> )
##
##  The $p$-class of a $p$-group <G> (see~"IsPGroup")
##  is the length of the lower $p$-central series (see~"PCentralSeries")
##  of <G>.
##  If <G> is not a $p$-group then an error is issued.
##
DeclareAttribute( "PClassPGroup", IsPGroup );


#############################################################################
##
#A  RankPGroup( <G> )
##
##  For a $p$-group <G> (see~"IsPGroup"), `RankPGroup' returns the *rank* of
##  <G>, which is defined as the minimal size of a generating system of <G>.
##  If <G> is not a $p$-group then an error is issued.
##
DeclareAttribute( "RankPGroup", IsPGroup );


#############################################################################
##
#P  IsNilpotentGroup( <G> )
##
##  A group is *nilpotent* if the lower central series
##  (see~"LowerCentralSeriesOfGroup" for a definition) reaches the trivial
##  subgroup in a finite number of steps.
##
DeclareProperty( "IsNilpotentGroup", IsGroup );

InstallSubsetMaintenance( IsNilpotentGroup,
    IsGroup and IsNilpotentGroup, IsGroup );

InstallFactorMaintenance( IsNilpotentGroup,
    IsGroup and IsNilpotentGroup, IsObject, IsGroup );

InstallTrueMethod( IsNilpotentGroup, IsGroup and IsCommutative );

InstallTrueMethod( IsNilpotentGroup, IsGroup and IsPGroup );


#############################################################################
##
#P  IsPerfectGroup( <G> )
##
##  A group is *perfect* if it equals its derived subgroup
##  (see~"DerivedSubgroup").
##
DeclareProperty( "IsPerfectGroup", IsGroup );

InstallFactorMaintenance( IsPerfectGroup,
    IsGroup and IsPerfectGroup, IsObject, IsGroup );


#############################################################################
##
#P  IsSporadicSimpleGroup( <G> )
##
##  A group is *sporadic simple* if it is one of the $26$ sporadic simple
##  groups; these are (in {\ATLAS} notation, see~\cite{CCN85}) $M_{11}$,
##  $M_{12}$, $J_1$, $M_{22}$, $J_2$, $M_{23}$, $HS$, $J_3$, $M_{24}$,
##  $M^cL$, $He$, $Ru$, $Suz$, $O^{\prime}N$, $Co_3$, $Co_2$, $Fi_{22}$,
##  $HN$, $Ly$, $Th$, $Fi_{23}$, $Co_1$, $J_4$, $Fi_{24}^{\prime}$, $B$,
##  and $M$.
##
##  This property can be used for example for selecting the character tables
##  of the sporadic simple groups,
##  see the documentation of the {\GAP} package CTblLib.
##
DeclareProperty( "IsSporadicSimpleGroup", IsGroup );

InstallIsomorphismMaintenance( IsSporadicSimpleGroup,
    IsGroup and IsSporadicSimpleGroup, IsGroup );


#############################################################################
##
#P  IsSimpleGroup( <G> )
##
##  A group is *simple* if it is nontrivial and has no nontrivial normal
##  subgroups.
##
DeclareProperty( "IsSimpleGroup", IsGroup );

InstallIsomorphismMaintenance( IsSimpleGroup,
    IsGroup and IsSimpleGroup, IsGroup );

InstallTrueMethod( IsSimpleGroup, IsGroup and IsSporadicSimpleGroup );


#############################################################################
##
#P  IsSupersolvableGroup( <G> )
##
##  A finite group is *supersolvable* if it has a normal series with cyclic
##  factors.
##
DeclareProperty( "IsSupersolvableGroup", IsGroup );

InstallSubsetMaintenance( IsSupersolvableGroup,
    IsGroup and IsSupersolvableGroup, IsGroup );

InstallFactorMaintenance( IsSupersolvableGroup,
    IsGroup and IsSupersolvableGroup, IsObject, IsGroup );

InstallTrueMethod( IsSupersolvableGroup, IsNilpotentGroup );


#############################################################################
##
#P  IsMonomialGroup( <G> )
##
##  A finite group is *monomial* if every irreducible complex character is
##  induced from a linear character of a subgroup.
##
DeclareProperty( "IsMonomialGroup", IsGroup );

InstallFactorMaintenance( IsMonomialGroup,
    IsGroup and IsMonomialGroup, IsObject, IsGroup );

InstallTrueMethod( IsMonomialGroup, IsSupersolvableGroup and IsFinite );


#############################################################################
##
#P  IsSolvableGroup( <G> )
##
##  A group is *solvable* if the derived series (see~"DerivedSeriesOfGroup"
##  for a definition)
##  reaches the trivial subgroup in a finite number of steps.
##
##  For finite groups this is the same as being polycyclic
##  (see~"IsPolycyclicGroup"),
##  and each polycyclic group is solvable,
##  but there are infinite solvable groups that are not polycyclic.
##
DeclareProperty( "IsSolvableGroup", IsGroup );

InstallSubsetMaintenance( IsSolvableGroup,
    IsGroup and IsSolvableGroup, IsGroup );

InstallFactorMaintenance( IsSolvableGroup,
    IsGroup and IsSolvableGroup, IsObject, IsGroup );

InstallTrueMethod( IsSolvableGroup, IsMonomialGroup );
InstallTrueMethod( IsSolvableGroup, IsSupersolvableGroup );


#############################################################################
##
#P  IsPolycyclicGroup( <G> )
##
##  A group is polycyclic if it has a subnormal series with cyclic factors.
##  For finite groups this is the same as if the group is solvable
##  (see~"IsSolvableGroup").
##
DeclareProperty( "IsPolycyclicGroup", IsGroup );
InstallTrueMethod( IsSolvableGroup, IsPolycyclicGroup );
InstallTrueMethod( IsPolycyclicGroup, IsSolvableGroup and IsFinite );
InstallTrueMethod( IsPolycyclicGroup, 
                     IsNilpotentGroup and IsFinitelyGeneratedGroup );

#############################################################################
##
#A  AbelianInvariants( <G> )
##
##  returns the abelian invariants (also sometimes called primary
##  decomposition) of the commutator factor group of the
##  group <G>. These are given as a list of prime-powers or zeroes and
##  describe the
##  structure of $G/G'$ as a direct product of cyclic groups of prime power
##  (or infinite) order.
##  
## (See "IndependentGeneratorsOfAbelianGroup" to obtain actual generators).
##
DeclareAttribute( "AbelianInvariants", IsGroup );


#############################################################################
##
#A  AsGroup( <D> )  . . . . . . . . . . . . . collection <D>, viewed as group
##
##  if the elements of the collection <D> form a group the command returns
##  this group, otherwise it returns `fail'.
##
DeclareAttribute( "AsGroup", IsCollection );


#############################################################################
##
#A  ChiefSeries( <G> )
##
##  is a series of normal subgroups of <G> which cannot be refined further.
##  That is there is no normal subgroup $N$ of <G> with $U_i > N > U_{i+1}$.
##  This attribute returns *one* chief series (of potentially many
##  possibilities).
##
DeclareAttribute( "ChiefSeries", IsGroup );


#############################################################################
##
#O  ChiefSeriesUnderAction( <H>, <G> )
##
##  returns a series of normal subgroups of <G> which are invariant under
##  <H> such that the series cannot be refined any further. <G> must be
##  a subgroup of <H>.
##  This attribute returns *one* such series (of potentially many
##  possibilities).
##
DeclareOperation( "ChiefSeriesUnderAction", [ IsGroup, IsGroup ] );


#############################################################################
##
#O  ChiefSeriesThrough( <G>, <l> )
##
##  is a chief series of the group <G> going through the normal subgroups in
##  the list <l>. <l> must be a list of normal subgroups of <G> contained in
##  each other, sorted by descending size.  This attribute returns *one*
##  chief series (of potentially many possibilities).
##
DeclareOperation( "ChiefSeriesThrough", [ IsGroup, IsList ] );


#############################################################################
##
#A  CommutatorFactorGroup( <G> )
##
##  computes the commutator factor group $<G>/<G>^{\prime}$ of the group <G>.
##
DeclareAttribute( "CommutatorFactorGroup", IsGroup );


#############################################################################
##
#A  CompositionSeries( <G> )
##
##  A composition series is a subnormal series which cannot be refined.
##  This attribute returns *one* composition series (of potentially many
##  possibilities).
##
DeclareAttribute( "CompositionSeries", IsGroup );
#T and for module?


#############################################################################
##
#F  DisplayCompositionSeries( <G> )
##
##  Displays a composition series of <G> in a nice way, identifying the
##  simple factors.
##
DeclareGlobalFunction( "DisplayCompositionSeries" );


#############################################################################
##
#A  ConjugacyClasses( <G> )
##
##  returns the conjugacy classes of elements of <G> as a list of
##  `ConjugacyClass'es of <G> (see~`ConjugacyClass'
##  ("ConjugacyClass") for details). It is guaranteed that the class of the
##  identity is in the first position, the further arrangement depends on
##  the method chosen (and might be different for equal but not identical
##  groups).
##
##  For very small groups (of size up to 500) the classes will be computed
##  by the conjugation action of <G> on itself
##  (see~"ConjugacyClassesByOrbits"). This can be deliberately switched off
##  using the ``{`noaction'}'' option shown below.
##
##  For solvable groups, the default method to compute the classes is by
##  homomorphic lift
##  (see section~"Conjugacy Classes in Solvable Groups").
##
##  For other groups the method of \cite{HulpkeClasses} is employed.
##
##  `ConjugacyClasses' supports the following options that can be used to
##  modify this strategy:
##  \beginitems
##  `random'&The classes are computed by  random search. See
##  `ConjugacyClassesByRandomSearch' ("ConjugacyClassesByRandomSearch")
##  below.
##
##  `action'&The classes are computed by action of <G> on itself See
##  `ConjugacyClassesByOrbits' ("ConjugacyClassesByOrbits")
##  below.
##
##  `noaction'&Even for small groups
##  `ConjugacyClassesByOrbits' ("ConjugacyClassesByOrbits")
##  is not used as a default. This can be useful if the elements of the
##  group use a lot of memory.
##  \enditems
##
DeclareAttribute( "ConjugacyClasses", IsGroup );


#############################################################################
##
#A  ConjugacyClassesMaximalSubgroups( <G> )
##
##  returns the conjugacy classes of maximal subgroups of <G>.
##  Representatives of the classes can be computed directly by
##  `MaximalSubgroupClassReps' (see "MaximalSubgroupClassReps").
##
DeclareAttribute( "ConjugacyClassesMaximalSubgroups", IsGroup );


#############################################################################
##
#A  MaximalSubgroups( <G> )
##
##  returns a list of all maximal subgroups of <G>. This may take up much
##  space, therefore the command should be avoided if possible. See
##  "ConjugacyClassesMaximalSubgroups".
##
DeclareAttribute( "MaximalSubgroups", IsGroup );


#############################################################################
##
#A  MaximalSubgroupClassReps( <G> )
##
##  returns a list of conjugacy representatives of the maximal subgroups
##  of <G>.
##
DeclareAttribute("MaximalSubgroupClassReps",IsGroup);


#############################################################################
##
#A  PerfectResiduum( <G> )
##
##  is the smallest normal subgroup of <G> that has a solvable factor group.
##
DeclareAttribute( "PerfectResiduum", IsGroup );


#############################################################################
##
#A  RepresentativesPerfectSubgroups( <G> )
#A  RepresentativesSimpleSubgroups( <G> )
##
##  returns a list of conjugacy representatives of perfect (respectively
##  simple) subgroups of <G>.
##  This uses the library of perfect groups (see "PerfectGroup"), thus it
##  will issue an error if the library is insufficient to determine all
##  perfect subgroups.
##
DeclareAttribute( "RepresentativesPerfectSubgroups", IsGroup );
DeclareAttribute( "RepresentativesSimpleSubgroups", IsGroup );


#############################################################################
##
#A  ConjugacyClassesPerfectSubgroups( <G> )
##
##  returns a list of the conjugacy classes of perfect subgroups of <G>.
##  (see "RepresentativesPerfectSubgroups".)
##
DeclareAttribute( "ConjugacyClassesPerfectSubgroups", IsGroup );


#############################################################################
##
#A  ConjugacyClassesSubgroups( <G> )
##
##  This attribute returns a list of all conjugacy classes of subgroups of
##  the group <G>.
##  It also is applicable for lattices of subgroups (see~"LatticeSubgroups").
##  The order in which the classes are listed depends on the method chosen by
##  {\GAP}.
##  For each class of subgroups, a representative can be accessed using
##  `Representative' (see~"Representative").
##
DeclareAttribute( "ConjugacyClassesSubgroups", IsGroup );


#############################################################################
##
#A  LatticeSubgroups( <G> )
##
##  computes the lattice of subgroups of the group <G>.  This lattice has
##  the conjugacy classes of subgroups as attribute
##  `ConjugacyClassesSubgroups' (see~"ConjugacyClassesSubgroups") and
##  permits one to test maximality/minimality relations.
##
DeclareAttribute( "LatticeSubgroups", IsGroup );


#############################################################################
##
#A  DerivedLength( <G> )
##
##  The derived length of a group is the number of steps in the derived
##  series. (As there is always the group, it is the series length minus 1.)
##
DeclareAttribute( "DerivedLength", IsGroup );

#############################################################################
##
#A  HirschLength( <G> )
##
##  Suppose that <G> is polycyclic-by-finite; that is, there exists a
##  polycyclic normal subgroup N in <G> with [G : N] finite. Then the Hirsch
##  length of <G> is the number of infinite cyclic factors in a polycyclic
##  series of N. This is an invariant of <G>.
##
DeclareAttribute( "HirschLength", IsGroup );
InstallIsomorphismMaintenance( HirschLength, 
                               IsGroup and HasHirschLength,
                               IsGroup );


#############################################################################
##
#A  DerivedSeriesOfGroup( <G> )
##
##  The derived series of a group is obtained by $U_{i+1}=U_i'$. It stops
##  if $U_i$ is perfect.
##
DeclareAttribute( "DerivedSeriesOfGroup", IsGroup );


#############################################################################
##
#A  DerivedSubgroup( <G> )
##
##  The derived subgroup $G'$ of $G$ is the subgroup generated by all
##  commutators of pairs of elements of $G$. It is normal in $G$ and the
##  factor group $G/G'$ is the largest abelian factor group of $G$.
##
DeclareAttribute( "DerivedSubgroup", IsGroup );


#############################################################################
##
#A  MaximalAbelianQuotient(<grp>)  . . . . Max abelian quotient
##
##  returns an epimorphism from <grp> onto the maximal abelian quotient of
##  <grp>. The kernel of this epimorphism is the derived subgroup.
DeclareAttribute( "MaximalAbelianQuotient",IsGroup);


#############################################################################
##
#A  CommutatorLength( <G> )
##
##  returns the minimal number $n$ such that each element
##  in the derived subgroup (see~"DerivedSubgroup") of the group <G> can be
##  written as a product of (at most) $n$ commutators of elements in <G>.
##
DeclareAttribute( "CommutatorLength", IsGroup );


#############################################################################
##
#A  DimensionsLoewyFactors( <G> )
##
##  This operation computes the dimensions of the factors of the Loewy
##  series of <G>. (See \cite{Hup82}, p. 157 for the slightly complicated
##  definition of the Loewy Series.)
##
##  The dimensions are computed via the `JenningsSeries' without computing
##  the Loewy series itself.
DeclareAttribute( "DimensionsLoewyFactors", IsGroup );


#############################################################################
##
#A  ElementaryAbelianSeries( <G> )
#A  ElementaryAbelianSeriesLargeSteps( <G> )
#A  ElementaryAbelianSeries( [<G>,<NT1>,<NT2>,...] )
##
##  returns a series of normal subgroups of $G$ such that all factors are
##  elementary abelian. If the group is not solvable (and thus no such series
##  exists) it returns `fail'.
##
##  The variant `ElementaryAbelianSeriesLargeSteps' tries to make the steps
##  in this series large (by eliminating intermediate subgroups if possible)
##  at a small additional cost.
##
##  In the third variant, an elementary abelian series through the given
##  series of normal subgroups is constructed.
##
DeclareAttribute( "ElementaryAbelianSeries", IsGroup );
DeclareAttribute( "ElementaryAbelianSeriesLargeSteps", IsGroup );


#############################################################################
##
#A  Exponent( <G> )
##
##  The exponent $e$ of a group <G> is the lcm of the orders of its
##  elements, that is, $e$ is the smallest integer such that $g^e=1$ for all
##  $g\in G$
##
DeclareAttribute( "Exponent", IsGroup );

InstallIsomorphismMaintenance( Exponent, IsGroup and HasExponent, IsGroup );


#############################################################################
##
#A  FittingSubgroup( <G> )
##
##  The Fitting subgroup of a group <G> is its largest nilpotent normal
##  subgroup.
##
DeclareAttribute( "FittingSubgroup", IsGroup );


#############################################################################
##
#A  PrefrattiniSubgroup( <G> )
##
##  returns a Prefrattini subgroup of the finite solvable group <G>.
##  A factor $M/N$ of $G$ is called a Frattini factor if $M/N \leq
##  \phi(G/N)$ holds.  The group $P$ is a Prefrattini subgroup of $G$ if $P$
##  covers each Frattini chief factor  of $G$, and  if for each  maximal
##  subgroup  of $G$ there exists a conjugate maximal subgroup, which
##  contains $P$.   In a finite solvable group $G$ the Prefrattini subgroups
##  form a characteristic conjugacy class of subgroups and the intersection
##  of all these subgroups is the Frattini subgroup of $G$.
##
DeclareAttribute( "PrefrattiniSubgroup", IsGroup );


#############################################################################
##
#A  FrattiniSubgroup( <G> )
##
##  The Frattini subgroup of a group <G> is the intersection of all maximal
##  subgroups of <G>.
##
DeclareAttribute( "FrattiniSubgroup", IsGroup );


#############################################################################
##
#A  InvariantForm( <D> )
##
DeclareAttribute( "InvariantForm", IsGroup );


#############################################################################
##
#A  JenningsSeries( <G> )
##
##  For a $p$-group <G>, this function returns its Jennings series.
##  This series is defined by setting
##  $G_1=G$ and for $i\geq 0$, $G_{i+1}=[G_i,G]G_j^p$, where $j$ is the
##  smallest integer $\geq i/p$.
##
DeclareAttribute( "JenningsSeries", IsGroup );


#############################################################################
##
#A  LowerCentralSeriesOfGroup( <G> )
##
##  The lower central series of a group <G> is defined as $U_{i+1}:=[G,U_i]$.
##  It is a central series of normal subgroups.
##  The name derives from the fact that $U_i$ is contained in the $i$-th
##  step subgroup of any central series.
##
DeclareAttribute( "LowerCentralSeriesOfGroup", IsGroup );

#############################################################################
##
#A  NilpotencyClassOfGroup( <G> )
##
##  The nilpotency class of a nilpotent group <G> is the number of steps in
##  the lower central series of <G> (see "LowerCentralSeriesOfGroup");
##
##  If <G> is not nilpotent an error is issued.
##
DeclareAttribute( "NilpotencyClassOfGroup", IsGroup );


#############################################################################
##
#A  MaximalNormalSubgroups( <G> )
##
##  is a list containing those proper normal subgroups of the group <G>
##  that are maximal among the proper normal subgroups.
##
DeclareAttribute( "MaximalNormalSubgroups", IsGroup );


#############################################################################
##
#A  NormalMaximalSubgroups( <G> )
##
DeclareAttribute( "NormalMaximalSubgroups", IsGroup );


#############################################################################
##
#A  MinimalNormalSubgroups( <G> )
##
##  is a list containing those nontrivial normal subgroups of the group <G>
##  that are minimal among the nontrivial normal subgroups.
##
DeclareAttribute( "MinimalNormalSubgroups", IsGroup );


#############################################################################
##
#A  NormalSubgroups( <G> )
##
##  returns a list of all normal subgroups of <G>.
##
DeclareAttribute( "NormalSubgroups", IsGroup );


#############################################################################
##
#F  NormalSubgroupsAbove( <G>, <N>, <avoid> )
##
DeclareGlobalFunction("NormalSubgroupsAbove");


############################################################################
##
#A  NrConjugacyClasses( <G> )
##
##  returns the number of conjugacy classes of <G>.
##
DeclareAttribute( "NrConjugacyClasses", IsGroup );


#############################################################################
##
#F  Omega( <G>, <p>[, <n>] )
##
##  For a <p>-group <G>, one defines
##  $\Omega_{<n>}(<G>) = \{ g\in <G> \mid g^{<p>^{<n>}} = 1 \}$.
##  The default value for <n> is `1'.
##
##  *@At the moment methods exist only for abelian <G> and <n>=1.@*
##
DeclareGlobalFunction( "Omega" );
DeclareOperation( "OmegaOp", [ IsGroup, IsPosInt, IsPosInt ] );
DeclareAttribute( "ComputedOmegas", IsGroup, "mutable" );


#############################################################################
##
#F  Agemo( <G>, <p>[, <n>] )
##
##  For a <p>-group <G>, one defines
##  $\mho_{<n>}(G) = \langle g^{<p>^{<n>}} \mid g\in <G> \rangle$.
##  The default value for <n> is `1'.
##
DeclareGlobalFunction( "Agemo" );
DeclareOperation( "AgemoOp", [ IsGroup, IsPosInt, IsPosInt ] );
DeclareAttribute( "ComputedAgemos", IsGroup, "mutable" );


#############################################################################
##
#A  RadicalGroup( <G> )
##
##  is the radical of <G>, i.e., the largest solvable normal subgroup of <G>.
##
DeclareAttribute( "RadicalGroup", IsGroup );


#############################################################################
##
#A  RationalClasses( <G> )
##
##  returns a list of the rational classes of the group <G>. (See
##  "RationalClass".)
##
DeclareAttribute( "RationalClasses", IsGroup );


#############################################################################
##
#A  GeneratorsSmallest( <G> )
##
##  returns a ``smallest'' generating set for the group <G>. This is the
##  lexicographically (using {\GAP}s order of group elements) smallest list
##  $l$ of elements of <G> such that $G=\langle l\rangle$ and
##  $l_i\not\in\langle l_1,\ldots,l_{i-1}\rangle$ (in particular $l_1$ is
##  not the one of the group).  The comparison of two groups via
##  lexicographic comparison of their sorted element lists yields the same
##  relation as lexicographic comparison of their smallest generating sets.
##
DeclareAttribute( "GeneratorsSmallest", IsMagma );


#############################################################################
##
#A  LargestElementGroup( <G> )
##
##  returns the largest element of <G> with respect to the ordering `\<' of
##  the elements family.
##
DeclareAttribute( "LargestElementGroup", IsGroup );


#############################################################################
##
#A  MinimalGeneratingSet( <G> )
##
##  returns a generating set of <G> of minimal possible length.
##
DeclareAttribute( "MinimalGeneratingSet", IsGroup );


#############################################################################
##
#A  SmallGeneratingSet(<G>) small generating set (hopefully even irredundant)
##
##  returns a generating set of <G> which has few elements. As neither
##  irredundancy, nor minimal length is proven it runs much faster than
##  `MinimalGeneratingSet'. It can be used whenever a short generating set is
##  desired which not necessarily needs to be optimal.
##
DeclareAttribute( "SmallGeneratingSet", IsGroup );


#############################################################################
##
#A  SupersolvableResiduum( <G> )
##
##  is the supersolvable residuum of the group <G>, that is,
##  its smallest normal subgroup $N$ such that the factor group $<G> / N$ is
##  supersolvable.
##
DeclareAttribute( "SupersolvableResiduum", IsGroup );


#############################################################################
##
#F  SupersolvableResiduumDefault( <G> ) . . . . supersolvable residuum of <G>
##
##  For a group <G>, `SupersolvableResiduumDefault' returns a record with the
##  following components.
##  \beginitems
##  `ssr': &
##      the supersolvable residuum of <G>, that is,
##      the largest normal subgroup $N$ of <G> such that the factor group
##      $<G> / N$ is supersolvable,
##
##  `ds': &
##      a chain of normal subgroups of <G>,
##      descending from <G> to the supersolvable residuum,
##      such that any refinement of this chain is a normal series.
##  \enditems
##
DeclareGlobalFunction( "SupersolvableResiduumDefault" );


#############################################################################
##
#A  ComplementSystem( <G> )
##
##  A complement system of a group <G> is a set of Hall-$p'$-subgroups of
##  <G>, where $p'$ runs through the subsets of prime factors of $|<G>|$
##  that omit exactly one prime.
##  Every pair of subgroups from this set commutes as subgroups.
##  Complement systems exist only for solvable groups, therefore
##  `ComplementSystem' returns `fail' if the group <G> is not solvable.
##
DeclareAttribute( "ComplementSystem", IsGroup );


#############################################################################
##
#A  SylowSystem( <G> )
##
##  A Sylow system of a group <G> is a set of Sylow subgroups of <G> such
##  that every pair of Sylow subgroups from this set commutes as subgroups.
##  Sylow systems exist only for solvable groups. The operation returns
##  `fail' if the group <G> is not solvable.
##
DeclareAttribute( "SylowSystem", IsGroup );


#############################################################################
##
#A  HallSystem( <G> )
##
##  returns a list containing one Hall-$P$ subgroup for each set $P$ of primes
##  which occur in the order of <G>.
##  Hall systems exist only for solvable groups. The operation returns
##  `fail' if the group <G> is not solvable.
##
DeclareAttribute( "HallSystem", IsGroup );


#############################################################################
##
#A  TrivialSubgroup( <G> ) . . . . . . . . . .  trivial subgroup of group <G>
##
DeclareSynonymAttr( "TrivialSubgroup", TrivialSubmagmaWithOne );


#############################################################################
##
#A  Socle( <G> ) . . . . . . . . . . . . . . . . . . . . . . . . socle of <G>
##
##  The socle of the group <G> is the subgroup generated by
##  all minimal normal subgroups.
##
DeclareAttribute( "Socle", IsGroup );


#############################################################################
##
#A  UpperCentralSeriesOfGroup( <G> )
##
##  The upper central series of a group <G> is defined as an ending series
##  $U_i/U_{i+1}:=Z(G/U_{i+1})$.
##  It is a central series of normal subgroups.
##  The name derives from the fact that $U_i$ contains every $i$-th step
##  subgroup of a central series.
##
DeclareAttribute( "UpperCentralSeriesOfGroup", IsGroup );


#############################################################################
##
#O  EulerianFunction( <G>, <n> )
##
##  returns the  number  of <n>-tuples $(g_1, g_2,  \ldots g_n)$ of elements
##  of the group <G>  that  generate the  whole group <G>.
##  The elements of an <n>-tuple need not be different. If the Library of 
##  Tables of Marks (see Chapter "Tables of Marks") covers the group <G>,
##  you may also use `EulerianFunctionByTom' (see "EulerianFunctionByTom").
##
DeclareOperation( "EulerianFunction", [ IsGroup, IsPosInt ] );


#############################################################################
##
#F  AgemoAbove( <G>, <C>, <p> )
##
DeclareGlobalFunction( "AgemoAbove" );


#############################################################################
##
#O  AsSubgroup( <G>, <U> )
##
##  creates a subgroup of <G> which contains the same elements as <U>
##
DeclareOperation( "AsSubgroup", [ IsGroup, IsGroup ] );


#############################################################################
##
#O  ClassMultiplicationCoefficient( <G>, <i>, <j>, <k> )
#O  ClassMultiplicationCoefficient( <G>, <C_i>, <C_j>, <C_k> )
##
DeclareOperation( "ClassMultiplicationCoefficient",
    [ IsGroup, IsPosInt, IsPosInt, IsPosInt ] );
DeclareOperation( "ClassMultiplicationCoefficient",
    [ IsGroup, IsCollection, IsCollection, IsCollection ] );


#############################################################################
##
#F  ClosureGroupDefault( <G>, <elm> ) . . . . . closure of group with element
##
##  This functions returns the closure of the group <G> with the element
##  <elm>.
##  If <G> has the attribute `AsSSortedList' then also the result has this
##  attribute.
##  This is used to implement the default method for `Enumerator'
##  (see~"Enumerator") and `EnumeratorSorted' (see~"EnumeratorSorted").
##
DeclareGlobalFunction( "ClosureGroupDefault" );


#############################################################################
##
#O  ClosureGroup( <G>, <obj> )  . . .  closure of group with element or group
##
##  creates the group generated by the elements of <G> and <obj>.
##  <obj> can be either an element or a collection of elements,
##  in particular another group.
##
DeclareOperation( "ClosureGroup", [ IsGroup, IsObject ] );


#############################################################################
##
#F  ClosureGroupAddElm( <G>, <elm> )
#F  ClosureGroupCompare( <G>, <elm> )
#F  ClosureGroupIntest( <G>, <elm> )
##
##  These three functions together with `ClosureGroupDefault' implement the
##  main methods for `ClosureGroup' (see~"ClosureGroup").
##  In the ordering given, they just add <elm> to the generators, remove
##  duplicates and identity elements, and test whether <elm> is already
##  contained in <G>.
##
DeclareGlobalFunction( "ClosureGroupAddElm" );
DeclareGlobalFunction( "ClosureGroupCompare" );
DeclareGlobalFunction( "ClosureGroupIntest" );


#############################################################################
##
#F  ClosureSubgroup( <G>, <obj> )
#F  ClosureSubgroupNC( <G>, <obj> )
##
##  For a group <G> that stores a parent group (see~"Parents"),
##  `ClosureSubgroup' calls `ClosureGroup' (see~"ClosureGroup") with the same
##  arguments;
##  if the result is a subgroup of the parent of <G> then the parent of <G>
##  is set as parent of the result, otherwise an error is raised.
##  The check whether the result is contained in the parent of <G> is omitted
##  by the `NC' version. As a wrong parent might imply wrong properties this
##  version should be used with care.
##
DeclareGlobalFunction( "ClosureSubgroup" );
DeclareGlobalFunction( "ClosureSubgroupNC" );


#############################################################################
##
#O  CommutatorSubgroup( <G>, <H> )
##
##  If <G> and <H> are two groups of elements in the same family, this
##  operation returns the group generated by all commutators
##  $[ g, h ] = g^{-1} h^{-1} g h$ (see~"Comm") of elements $g \in <G>$ and
##  $h \in <H>$, that is the group
##  $\left\langle [ g, h ] \mid g \in <G>, h \in <H> \right\rangle$.
##
DeclareOperation( "CommutatorSubgroup", [ IsGroup, IsGroup ] );


#############################################################################
##
#O  ConjugateGroup( <G>, <obj> )  . . . . . . conjugate of group <G> by <obj>
##
##  returns the conjugate group of <G>, obtained by applying the conjugating
##  element <obj>.
##  To form a conjugate (group) by any object acting via `^', one can use
##  the infix operator `^'.
##
DeclareOperation( "ConjugateGroup", [ IsGroup, IsObject ] );


#############################################################################
##
#O  ConjugateSubgroup( <G>, <g> )
##
DeclareOperation( "ConjugateSubgroup",
    [ IsGroup and HasParent, IsMultiplicativeElementWithInverse ] );


#############################################################################
##
#O  ConjugateSubgroups( <G>, <U> )
##
##  returns a list of all images of the group <U> under conjugation action
##  by <G>.
##
DeclareOperation( "ConjugateSubgroups", [ IsGroup, IsGroup ] );


#############################################################################
##
#O  Core( <S>, <U> )
##
##  If <S> and <U> are groups of elements in the same family, this
##  operation
##  returns the core of <U> in <S>, that is the intersection of all
##  <S>-conjugates of <U>.
##
InParentFOA( "Core", IsGroup, IsGroup, DeclareAttribute );


#############################################################################
##
#O  CosetTable( <G>, <H> )
##
##  returns the coset table of the finitely presented group <G> on the cosets
##  of the subgroup <H>.
##
##  Basically a coset table is the permutation representation of the finitely
##  presented group on the cosets of a subgroup  (which need  not be faithful
##  if the subgroup has a nontrivial  core).  Most  of  the set theoretic and
##  group functions use the regular  representation of <G>, i.e.,  the  coset
##  table of <G> over the trivial subgroup.
##
##  The coset table is returned as a list of lists. For each generator of
##  <G> and its inverse the table contains a generator list. A generator
##  list is simply a list of integers. If <l> is the generator list for the
##  generator <g> and if `<l>[<i>] = <j>' then generator <g> takes the coset
##  <i> to the coset <j> by multiplication from the right. Thus the
##  permutation representation of <G> on the cosets of <H> is obtained by
##  applying `PermList' to each generator list (see "PermList").
##
DeclareOperation( "CosetTable", [ IsGroup, IsGroup ] );


#############################################################################
##
#O  CosetTableNormalClosure( <G>, <H> )
##
##  returns the coset table of the finitely presented group <G> on the cosets
##  of the normal closure of the subgroup <H>.
##
DeclareOperation( "CosetTableNormalClosure", [ IsGroup, IsGroup ] );


#############################################################################
##
#F  FactorGroup( <G>, <N> )
#O  FactorGroupNC( <G>, <N> )
##
##  returns the image of the `NaturalHomomorphismByNormalSubgroup(<G>,<N>)'.
##  The `NC' version does not test whether <N> is normal in <G>.
##
DeclareGlobalFunction( "FactorGroup" );
DeclareOperation( "FactorGroupNC", [ IsGroup, IsGroup ] );


#############################################################################
##
#O  Index( <G>, <U> )
#O  IndexNC( <G>, <U> )
##
##  For a subgroup <U> of the group <G>, `Index' returns the index
##  $[<G>:<U>] = {|<G>| \over |<U>|}$ of <U> in <G>.
##  The `NC' version does not test whether <U> is contained in <G>.
##
InParentFOA( "Index", IsGroup, IsGroup, DeclareAttribute );

DeclareOperation( "IndexNC", [ IsGroup, IsGroup ] );


#############################################################################
##
#A  IndexInWholeGroup( <G> )
##
##  If the family of elements of <G> itself forms a group <P>, this
##  attribute returns the index of <G> in <P>.
DeclareAttribute( "IndexInWholeGroup", IsGroup );


#############################################################################
##
#A  IndependentGeneratorsOfAbelianGroup( <A> )
##
##  returns a set of generators <g> of prime-power order of the abelian
##  group <A> such that <A> is the direct product of the cyclic groups
##  generated by the $g_i$.
##
DeclareAttribute( "IndependentGeneratorsOfAbelianGroup",
  IsGroup and IsAbelian );


#############################################################################
##
#O  IsConjugate( <G>, <x>, <y> )
#O  IsConjugate( <G>, <U>, <V> )
##
##  tests whether the elements <x> and <y> or the subgroups <U> and <V> are
##  conjugate under the action of <G>. (They do not need to be contained in
##  <G>.) This command is only a shortcut to
##  `RepresentativeAction'.
##
DeclareOperation( "IsConjugate", [ IsGroup, IsObject, IsObject ] );


#############################################################################
##
#O  IsNormal( <G>, <U> )
##
##  returns `true' if the group <G> normalizes the group <U>
##  and `false' otherwise.
##
##  A group <G> *normalizes* a group <U> if and only if for every $g \in <G>$
##  and $u \in <U>$ the element $u^g$ is a member of <U>.
##  Note that <U> need not be a subgroup of <G>.
##
InParentFOA( "IsNormal", IsGroup, IsGroup, DeclareProperty );


#############################################################################
##
#O  IsCharacteristicSubgroup(<G>,<N>)
##
##  tests whether <N> is invariant under all automorphisms of <G>.
DeclareOperation( "IsCharacteristicSubgroup", [IsGroup,IsGroup] );


#############################################################################
##
#F  IsPNilpotent( <G>, <p> )
##
##  A group is $p$-nilpotent if it possesses a normal $p$-complement.
##
KeyDependentOperation( "IsPNilpotent", IsGroup, IsPosInt, "prime" );


#############################################################################
##
#F  IsPSolvable( <G>, <p> )
##
##  A group is $p$-solvable if every chief factor is either not divisible
##  by $p$ or solvable.
##
##  *@Currently no method is installed!@*
##
KeyDependentOperation( "IsPSolvable", IsGroup, IsPosInt, "prime" );


#############################################################################
##
#F  IsSubgroup( <G>, <U> )
##
##  `IsSubgroup' returns `true' if <U> is a group that is a subset of the
##  domain <G>.
##  This is actually checked by calling `IsGroup( <U> )' and
##  `IsSubset( <G>, <U> )';
##  note that special methods for `IsSubset' (see~"IsSubset") are available
##  that test only generators of <U> if <G> is closed under the group
##  operations.
##  So in most cases,
##  for example whenever one knows already that <U> is a group,
##  it is better to call only `IsSubset'.
##
DeclareGlobalFunction( "IsSubgroup" );


#############################################################################
##
#O  IsSubnormal( <G>, <U> )
##
##  A subgroup <U> of the group <G> is subnormal if it is contained in a
##  subnormal series of <G>.
##
DeclareOperation( "IsSubnormal", [ IsGroup, IsGroup ] );


#############################################################################
##
#O  NormalClosure( <G>, <U> )
##
##  The normal closure of <U> in <G> is the smallest normal subgroup of <G>
##  which contains <U>.
##
InParentFOA( "NormalClosure", IsGroup, IsGroup, DeclareAttribute );


#############################################################################
##
#O  NormalIntersection( <G>, <U> )
##
##  computes the intersection of <G> and <U>, assuming that <G> is normalized
##  by <U>. This works faster than `Intersection', but will not produce the
##  intersection if <G> is not normalized by <U>.
DeclareOperation( "NormalIntersection", [ IsGroup, IsGroup ] );


#############################################################################
##
#O  Normalizer( <G>, <U> )
#O  Normalizer( <G>, <g> )
##
##  Computes the normalizer $N_G(U)$, that is the stabilizer of $U$ under
##  the conjugation action of $G$.
##  The second form computes $N_G(\langle g\rangle)$.
##
InParentFOA( "Normalizer", IsGroup, IsObject, DeclareAttribute );


#############################################################################
##
#O  CentralizerModulo(<G>,<N>,<elm>)   full preimage of C_(G/N)(elm.N)
##
##  Computes the full preimage of the centralizer $C_{G/N}(elm\cdot N)$ in
##  <G> (without necessarily constructing the factor group).
##
DeclareOperation("CentralizerModulo", [IsGroup,IsGroup,IsObject]);


#############################################################################
##
#F  PCentralSeries( <G>, <p> )
##
##  The $p$-central series of $G$ is defined by $U_1:=G$,
##  $U_i:=[G,U_{i-1}]U_{i-1}^p$.
##
KeyDependentOperation( "PCentralSeries", IsGroup, IsPosInt, "prime" );


#############################################################################
##
#F  PRump( <G>, <p> )
##
##  The *$p$-rump* of a group $G$ is the subgroup $G' G^p$ for a prime $p$.
##
KeyDependentOperation( "PRump", IsGroup, IsPosInt, "prime" );


#############################################################################
##
#F  PCore( <G>, <p> )
##
##  \atindex{O_p(G)!see PCore}{@$O_p(G)$!see \noexpand`PCore'}
##  The *$p$-core* of <G> is the largest normal $p$-subgroup of <G>. It is the
##  core of a $p$-Sylow subgroup of <G>.
##
KeyDependentOperation( "PCore", IsGroup, IsPosInt, "prime" );


#############################################################################
##
#O  SubnormalSeries( <G>, <U> )
##
##  If <U> is a subgroup of <G> this operation returns a subnormal series
##  that descends from <G> to a subnormal subgroup <V>$\ge$<U>. If <U> is
##  subnormal, <V>=<U>.
InParentFOA( "SubnormalSeries", IsGroup, IsGroup, DeclareAttribute );


#############################################################################
##
#F  SylowSubgroup( <G>, <p> )
##
##  returns a Sylow $p$ subgroup of the finite group <G>.
##  This is a $p$-subgroup of <G> whose index in <G> is coprime to $p$.
##  `SylowSubgroup' computes Sylow subgroups via the operation
##  `SylowSubgroupOp'.
##
KeyDependentOperation( "SylowSubgroup", IsGroup, IsPosInt, "prime" );


#############################################################################
##
#F  SylowComplement( <G>, <p> )
##
##  returns a $p$-Sylow complement of the finite group <G>. This is a
##  subgroup <U> of order coprime to $p$ such that the index $[G:U]$ is a
##  $p$-power.
##  At the moment methods exist only if <G> is solvable and {\GAP} will
##  issue an error if <G> is not solvable.
##
KeyDependentOperation( "SylowComplement", IsGroup, IsPosInt, "prime" );


#############################################################################
##
#F  HallSubgroup( <G>, <P> )
##
##  computes a $P$-Hall subgroup for a set $P$ of primes.
##  This is a subgroup the order of which is only divisible by primes in $P$
##  and whose index is coprime to all primes in $P$.
##  The function computes Hall subgroups via the operation `HallSubgroupOp'.
##  At the moment methods exist only if <G> is solvable and {\GAP} will
##  issue an error if <G> is not solvable.
##
KeyDependentOperation( "HallSubgroup", IsGroup, IsList, ReturnTrue );


#############################################################################
##
#O  NrConjugacyClassesInSupergroup( <U>, <G> )
##
DeclareOperation( "NrConjugacyClassesInSupergroup", [ IsGroup, IsGroup ] );


#############################################################################
##
#F  Factorization( <G>, <elm> )
##
##  returns a factorization of <elm> as word in the generators of <G> given in
##  the attribute `GeneratorsOfGroup'. The component `<G>!.factFreeMap'
##  will contain a map <map> from the group <G> to the free group in which
##  the word is expressed. The attribute `MappingGeneratorsImages' of this
##  map gives a list of generators and corresponding letters.
##
##  The algorithm used computes all elements of the group to ensure a short
##  word is found. Therefore this function should *not* be used when the
##  group <G> has more than a few thousand elements. Because of this, one
##  should not call this function within algorithms, but use
##  homomorphisms instead.
DeclareGlobalFunction("Factorization");


#############################################################################
##
#O  GroupByGenerators( <gens> ) . . . . . . . . . . . . . group by generators
#O  GroupByGenerators( <gens>, <id> ) . . . . . . . . . . group by generators
##
##  `GroupByGenerators' returns the group $G$ generated by the list <gens>.
##  If a second argument <id> is present then this is stored as the identity
##  element of the group.
##
##  The value of the attribute `GeneratorsOfGroup' of $G$ need not be equal
##  to <gens>.
##  `GroupByGenerators' is called by `Group'.
##
DeclareOperation( "GroupByGenerators", [ IsCollection ] );
DeclareOperation( "GroupByGenerators",
    [ IsCollection, IsMultiplicativeElementWithInverse ] );


#############################################################################
##
#O  GroupWithGenerators( <gens> ) . . . . . . . . group with given generators
#O  GroupWithGenerators( <gens>, <id> ) . . . . . group with given generators
##
##  `GroupWithGenerators' returns the group $G$ generated by the list <gens>.
##  If a second argument <id> is present then this is stored as the identity
##  element of the group.
##  The value of the attribute `GeneratorsOfGroup' of $G$ is equal to <gens>.
##
DeclareOperation( "GroupWithGenerators", [ IsCollection ] );
DeclareOperation( "GroupWithGenerators",
    [ IsCollection, IsMultiplicativeElementWithInverse ] );


#############################################################################
##
#F  Group( <gen>, ... )
#F  Group( <gens> )
#F  Group( <gens>, <id> )
##
##  `Group( <gen>, ... )' is the group generated by the arguments <gen>, ...
##
##  If the only  argument <gens> is a list  that is not  a matrix then
##  `Group( <gens> )' is the group generated by the elements of that list.
##
##  If there  are two arguments,   a list <gens>  and  an element <id>, then
##  `Group( <gens>, <id> )'  is the group generated  by the elements of
##  <gens>, with identity <id>.
##
##  Note that the value of the attribute `GeneratorsOfGroup' need not be
##  equal to the list <gens> of generators entered as argument.
##  Use `GroupWithGenerators' (see~"GroupWithGenerators") if you want to be
##  sure that the argument <gens> is stored as value of `GeneratorsOfGroup'.
##
DeclareGlobalFunction( "Group" );


#############################################################################
##
#F  Subgroup( <G>, <gens> ) . . . . . . . subgroup of <G> generated by <gens>
#F  SubgroupNC( <G>, <gens> )
##
##  creates the subgroup <U> of <G> generated by <gens>. The `Parent' of <U>
##  will be <G>.
##  The `NC' version does not check, whether the elements in <gens> actually
##  lie in <G>.
##
DeclareSynonym( "Subgroup", SubmagmaWithInverses );

DeclareSynonym( "SubgroupNC", SubmagmaWithInversesNC );

#############################################################################
##
#F  SubgroupByProperty( <G>, <prop> )
##
##  creates a subgroup of <G> consisting of those elements fulfilling
##  <prop> (which is a tester function).
##  No test is done whether the property actually defines a subgroup.
##
##  Note that currently very little functionality beyond an element test
##  exists for groups created this way.
##
DeclareGlobalFunction( "SubgroupByProperty" );

#############################################################################
##
#A  ElementTestFunction( <G> )
##
##  This attribute contains a function that provides an element test for the
##  group <G>.
##
DeclareAttribute( "ElementTestFunction", IsGroup );

#############################################################################
##
#F  SubgroupShell( <G> )
##
##  creates a subgroup of <G> which at this point is not yet specified
##  further (but will be later, for example by assigning a generating set).
##
DeclareGlobalFunction( "SubgroupShell" );


#############################################################################
##
#C  IsRightTransversal( <obj> )
##
DeclareCategory("IsRightTransversal",IsCollection);
DeclareCategoryCollections("IsRightTransversal");

#############################################################################
##
#O  RightTransversal( <G>, <U> )
##
##  A right transversal $t$ is a list of representatives for the set
##  $<U> {\setminus} <G>$ of right
##  cosets (consisting of cosets $Ug$) of $U$ in $G$.
##
##  The object returned by `RightTransversal' is not a plain list, but an
##  object that behaves like an immutable list of length $[<G>{:}<U>]$,
##  except if <U> is the trivial subgroup of <G>
##  in which case `RightTransversal' may return the sorted plain list of
##  coset representatives.
##
##  The operation `PositionCanonical(<t>,<g>)', called for a transversal <t>
##  and an element <g> of <G>, will return the position of the
##  representative in <t> that lies in the same coset of <U> as the element
##  <g> does. (In comparison, `Position' will return `fail' if the element
##  is not equal to the representative.) Functions that implement group
##  actions such as `Action' or `Permutation' (see Chapter~"Group
##  Actions") use `PositionCanonical', therefore it is possible to
##  ``act'' on a right transversal to implement the action on the cosets.
##  This is often much more efficient than acting on cosets.
##
InParentFOA( "RightTransversal", IsGroup, IsGroup, DeclareAttribute );


#############################################################################
##
#O  IntermediateSubgroups( <G>, <U> )
##
##  returns a list of all subgroups of <G> that properly contain <U>; that
##  is all subgroups between <G> and <U>. It returns a record with
##  components `subgroups' which is a list of these subgroups as well as a
##  component `inclusions' which lists all maximality inclusions among these
##  subgroups.
##  A maximality inclusion is given as a list `[<i>,<j>]' indicating that
##  subgroup number <i> is a maximal subgroup of subgroup number <j>, the
##  numbers 0 and 1+length(`subgroups') are used to denote <U> and <G>
##  respectively.
##
DeclareOperation( "IntermediateSubgroups", [IsGroup, IsGroup] );


#############################################################################
##
#F  IsomorphismTypeInfoFiniteSimpleGroup( <G> )
##
##  For a finite simple group <G>, `IsomorphismTypeInfoFiniteSimpleGroup'
##  returns a record with components `series', `name' and possibly `parameter',
##  describing the isomorphism type of <G>.
##  The component `name' is a string that gives name(s) for <G>,
##  and `series' is a string that describes the following series.
##
##  (If different characterizations of <G> are possible only one is given by
##  `series' and `parameter', while `name' may give several names.)
##  \beginlist
##  \item{`"A"'} Alternating groups, `parameter' gives the natural degree.
##
##  \item{`"L"'} Linear groups (Chevalley type $A$),
##               `parameter' is a list [<n>,<q>] that indicates $L(n,q)$.
##
##  \item{`"2A"'} Twisted Chevalley type ${}^2A$,
##                `parameter' is a list [<n>,<q>] that indicates ${}^2A(n,q)$.
##
##  \item{`"B"'} Chevalley type $B$,
##               `parameter' is a list [<n>,<q>] that indicates $B(n,q)$.
##
##  \item{`"2B"'} Twisted Chevalley type ${}^2B$,
##                `parameter' is a value <q> that indicates ${}^2B(2,q)$.
##
##  \item{`"C"'} Chevalley type $C$,
##               `parameter' is a list [<n>,<q>] that indicates $C(n,q)$.
##
##  \item{`"D"'} Chevalley type $D$,
##               `parameter' is a list [<n>,<q>] that indicates $D(n,q)$.
##
##  \item{`"2D"'} Twisted Chevalley type ${}^2D$,
##                `parameter' is a list [<n>,<q>] that indicates ${}^2D(n,q)$.
##
##  \item{`"3D"'} Twisted Chevalley type ${}^3D$,
##                `parameter' is a value <q> that indicates ${}^3D(4,q)$.
##
##  \item{`"E"'} Exceptional Chevalley type $E$,
##               `parameter' is a list [<n>,<q>] that indicates $E_n(q)$.
##               The value of <n> is 6,7 or 8.
##
##  \item{`"2E"'} Twisted exceptional Chevalley type $E_6$,
##                `parameter' is a value <q> that indicates ${}^2E_6(q)$.
##
##  \item{`"F"'} Exceptional Chevalley type $F$,
##               `parameter' is a value <q> that indicates $F(4,q)$.
##
##  \item{`"2F"'} Twisted exceptional Chevalley type ${}^2F$ (Ree groups),
##                `parameter' is a value <q> that indicates ${}^2F(4,q)$.
##
##  \item{`"G"'} Exceptional Chevalley type $G$,
##               `parameter' is a value <q> that indicates $G(2,q)$.
##
##  \item{`"2G"'} Twisted exceptional Chevalley type ${}^2G$ (Ree groups),
##                `parameter' is a value <q> that indicates ${}^2G(2,q)$.
##
##  \item{`"Spor"'} Sporadic groups, `name' gives the name.
##
##  \item{`"Z"'} Cyclic groups of prime size, `parameter' gives the size.
##  \endlist
##
##  An equal sign in the name denotes different naming schemes for the same
##  group, a tilde sign abstract isomorphisms between groups constructed in a
##  different way.
##
DeclareGlobalFunction( "IsomorphismTypeInfoFiniteSimpleGroup" );


#############################################################################
##
#A  IsomorphismPcGroup( <G> )
##
##  \index{isomorphic!pc group}
##  returns an isomorphism from <G> onto an isomorphic PC group.
##  The series chosen for this PC representation depends on
##  the method chosen.
##  <G> must be a polycyclic group of any kind, for example a solvable
##  permutation group.
DeclareAttribute( "IsomorphismPcGroup", IsGroup );


#############################################################################
##
#A  IsomorphismSpecialPcGroup( <G> )
##
##  returns an isomorphism from <G> onto an isomorphic PC group whose family
##  pcgs is a special pcgs. (This can be beneficial to the runtime of
##  calculations.)
##  <G> may be a polycyclic group of any kind, for example a solvable
##  permutation group.
DeclareAttribute( "IsomorphismSpecialPcGroup", IsGroup );


#############################################################################
##
#A  IsomorphismPermGroup( <G> )
##
##  returns an isomorphism $\varphi$ from the group <G> onto
##  a permutation group <P> which is isomorphic to <G>.
##  The method will select a suitable permutation representation.
##
DeclareAttribute("IsomorphismPermGroup",IsGroup);


#############################################################################
##
#A  IsomorphismFpGroup( <G> )
##
##  returns an isomorphism from the given finite group <G> to a finitely
##  presented group isomorphic to <G>. The function first *chooses a set of
##  generators of <G>* and then computes a presentation in terms of these
##  generators.
##
DeclareAttribute( "IsomorphismFpGroup", IsGroup );


#############################################################################
##
#A  IsomorphismFpGroupByGenerators( <G>,<gens>[,<string>] )
#A  IsomorphismFpGroupByGeneratorsNC( <G>,<gens>,<string> )
##
##  returns an isomorphism from a finite group <G> to a finitely presented
##  group <F> isomorphic to <G>.  The generators of <F> correspond to the
##  *generators of <G> given in the list <gens>*.  If <string> is given it
##  is used to name the generators of the finitely presented group.
##
##  The NC version will avoid testing whether the elements in <gens>
##  generate <G>.
##
DeclareGlobalFunction("IsomorphismFpGroupByGenerators");
DeclareOperation( "IsomorphismFpGroupByGeneratorsNC",
    [ IsGroup, IsList, IsString ] );

DeclareOperation(
    "IsomorphismFpGroupBySubnormalSeries", [IsGroup, IsList, IsString] );

DeclareOperation(
    "IsomorphismFpGroupByCompositionSeries", [IsGroup, IsString] );

DeclareGlobalFunction( "IsomorphismFpGroupByPcgs" );


#############################################################################
##
#A  PrimePowerComponents( <g> )
##
DeclareAttribute( "PrimePowerComponents", IsMultiplicativeElement );


#############################################################################
##
#O  PrimePowerComponent( <g>, <p> )
##
DeclareOperation( "PrimePowerComponent",
    [ IsMultiplicativeElement, IsPosInt ] );


#############################################################################
##
#O  PowerMapOfGroup( <G>, <n>, <ccl> )
##
##  is a list of positions, at position $i$ the position of the conjugacy
##  class containing the <n>-th powers of the elements in the $i$-th class
##  of the list <ccl> of conjugacy classes.
##
DeclareOperation( "PowerMapOfGroup", [ IsGroup, IsInt, IsHomogeneousList ] );


#############################################################################
##
#F  PowerMapOfGroupWithInvariants( <G>, <n>, <ccl>, <invariants> )
##
##  is a list of integers, at position $i$ the position of the conjugacy
##  class containimg the <n>-th powers of elements in class $i$ of <ccl>.
##  The list <invariants> contains all invariants besides element order
##  that shall be used before membership tests.
##
##  Element orders are tested first in any case since they may allow a
##  decision without forming the <n>-th powers of elements.
##
DeclareGlobalFunction( "PowerMapOfGroupWithInvariants" );


#############################################################################
##
#O  HasAbelianFactorGroup(<G>,<N>)
##
##  tests whether $G/N$ is abelian (without explicitly
##  constructing the factor group).
##
DeclareGlobalFunction("HasAbelianFactorGroup");


#############################################################################
##
#O  HasElementaryAbelianFactorGroup(<G>,<N>)
##
##  tests whether $G/N$ is elementary abelian (without explicitly
##  constructing the factor group).
##
DeclareGlobalFunction("HasElementaryAbelianFactorGroup");


#############################################################################
##
#F  IsGroupOfFamily(<G>)
##
##  This filter indicates that the group <G> is the group which is stored in
##  the family <fam> of its elements as `<fam>!.wholeGroup'.
##
DeclareFilter("IsGroupOfFamily");


#############################################################################
##
#F  Group_PseudoRandom(<G>)
##
##  Computes a pseudo-random element of <G> by product replacement.
##  (This is installed as a method for `PseudoRandom' under the condition
##  that generators are known.)
##
DeclareGlobalFunction("Group_PseudoRandom");


#############################################################################
##
#E


