%!TEX root = manual.tex
% !TeX TS-program = pdftex
% !TEX spellcheck =en_GB
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%  grpclass.tex            CRISP documentation              Burkhard Höfling
%%
%%  Copyright © 2000, Burkhard Höfling
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\Chapter{Generic group classes}

In this chapter, we describe how group classes can be defined by assigning
basic attributes and properties, in particular closure properties. 

A class (see "Set theoretical classes") is a *group class* if it consists of
groups, and if it is closed under isomorphisms of groups. Thus if $G$ and
$H$ are isomorphic groups,  then $G$ is in the group class <grpclass> if and
only if
$H$ is. Groups belonging to the same group class may be regarded as sharing
a group theoretical property (a property shared by isomorphic groups), and
groups sharing a group theoretical property form a class of groups. It
not empty, group classes are genuinely infinite objects, so {\GAP} sets can
never form group classes. Some authors require every group class to contain
the trivial groups. Here we do not make this assumption; in particular every
empty class is a group class.


The following sections describe how to create group classes and
declare some of their basic properties. 

Note that,
for common types of group classes, there are additional functions available
to accomplish this task; see the following Chapters 
"Schunck classes and formations" and "Fitting classes and Fitting sets". 
There are also a number of pre-defined group classes; see Chapter~"Examples of
group classes".


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\Section{Creating group classes}\null

\index{group classes!creation of}

Group classes can either be defined by a function deciding membership, or
alternatively by a (finite) list of groups containing at least one
representative of each isomorphism type of groups contained in the class.

\>GroupClass(<rec>) O
\>GroupClass(<func>) O
\>GroupClass(<group-list>) O
\>GroupClass(<group-list>, <iso-func>) O

The function `GroupClass' returns a new group class <class>, specified by its
argument(s).

In the first form, <rec> must be a record which has a component `\\in', and may have
further components `name', and  `char'. `\\in' must be a function having one argument.
When called with a group <G> as its argument, it must return `true' or `false',
depending upon whether <G> is in <class> or not. It is the user's
responsibility to ensure that the function supplied returns the same value
when called with isomorphic groups. If <rec> has components  `name' or 
`char', their values are stored in the attributes `Name' (see "ref:Name")
and `Characteristic' (see "Characteristic") of <class>.

`GroupClass(<func>)' is a shorthand for `GroupClass(rec(\\in := func))'.

In the other cases, `GroupClass' returns the group
class consisting of the isomorphism classes of the groups in the list
<group-list>. If <iso-func> is
given, <iso-func> is used to check whether a given group <G> is isomorphic
with one of the groups in the defining list. <iso-func> must have two
arguments, and must return true if two groups, one of which is in
<group-list>, passed as arguments are isomorphic, and false otherwise. If
<iso-func> is not given, the {\GAP} function `IsomorphismGroups' is used for
the isomorphism test. Note that even for relatively small groups,
`IsomorphismGroups' tends to be very slow. 


\beginexample
gap> GroupClass(IsNilpotent);
GroupClass(in:=<Operation "IsNilpotent">)
gap> GroupClass([CyclicGroup(2), CyclicGroup(3)]);
GroupClass([ <pc group of size 2 with 1 generators>, 
  <pc group of size 3 with 1 generators> ])
gap> AbelianIsomorphismTest := function(A,B)
>     if IsAbelian(A) then
>         if IsAbelian(B) then
>             return AbelianInvariants(A) = AbelianInvariants(B);
>         else
>             return false;
>         fi;
>     elif IsAbelian(B) then
>         return false;
>     else # this will not happen if called from GroupClass
>         Error("At least one of the groups <A> and <B> must be abelian");
>     fi;
> end;
function( A, B ) ... end
gap> cl := GroupClass([AbelianGroup([2,2]), AbelianGroup([3,5])],
> AbelianIsomorphismTest);
GroupClass([ <pc group of size 4 with 2 generators>, 
  <pc group of size 15 with 2 generators> ], function( A, B ) ... end)
gap> Group((1,2),(3,4)) in cl;
true
\endexample


\>Intersection(<list>)!{of group classes} F
\>Intersection(<C_1>, <C_2>, \dots, <C_n>)!{of group classes} F

The intersection of a list <list> of group classes resp. of the group
classes <C_1>, <C_2>, \dots, <C_n> is again
a group class. The intersection automatically has those closure properties
(see "Properties of group classes") which all of the intersected classes
have. 


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\Section{Properties of group classes}\null

\index{closure properties!of group classes}
\index{group classes!closure properties of}

Since nonempty group classes are infinite, {\CRISP} cannot, in
general, decide whether a group class has a certain property. Therefore the
user is required to set the appropriate properties and attributes. 
See Sections "ref:Attributes" and "ref:Properties". To facilitate this task, 
there are special functions available to
create common types of group classes such as formations (see "Creating
formations"), Fitting classes (see "Creating Fitting classes"), and Schunck
classes (see "Creating Schunck classes").

However, {\CRISP}
knows about the implications between the closure properties listed below; for
instance it knows that a group class which has `IsResiduallyClosed' also has
`IsDirectProductClosed', and that a class having `IsSchunckClass' also has
`IsDirectProductClosed' and `IsSaturated'. Moreover, the intersection of
group classes all having one of the closure properties in common also has
that closure property.

The following
basic properties are defined for group classes.

\>IsGroupClass(<grpclass>) P

A generic class (see Chapter "Set theoretical classes") is considered a group
class if it has the property `IsGroupClass'. There is no way for {\CRISP} to
*know* that a given class defined by a membership function is a group class,
i.~e., consists of groups and is closed under group isomorphisms.

\> ContainsTrivialGroup(<grpclass>) P

This property, if bound, indicates whether <grpclass> contains the trivial group
or not.

\> IsSubgroupClosed(<grpclass>) P

if true, then for every $G$ in <grpclass>, the subgroups of <G> likewise
belong to <grpclass>.

\> IsNormalSubgroupClosed(<grpclass>) P

if true, then for every $G$ in <grpclass>, the (sub)normal subgroups of <G>
likewise belong to <grpclass>.

\> IsQuotientClosed(<grpclass>) P

if true, then for every $G$ in <grpclass>, the factor groups of <G>
likewise belong to <grpclass>.

\> IsResiduallyClosed(<grpclass>) P

if true and $G$ is a group such that $G/N_1$ and $G/N_2$ belong to
<grpclass> for two normal subgroups $N_1$ and $N_2$ of $G$ *which intersect
trivially*, then $G$ belongs to <grpclass>.

\> IsNormalProductClosed(<grpclass>) P

if true and $G$ is a group which is generated by subnormal subgroups in <grpclass>,
then $G$ belongs to <grpclass>.

\> IsDirectProductClosed(<grpclass>) P

if true and the group $G$ is the direct product of $N_1$ and
$N_2$ belonging to <grpclass>, then $G$ likewise belongs to
<grpclass>.

\> IsSchunckClass(<grpclass>) P

if true, then $G$ belongs to <grpclass> if and only if its primitive
factor groups lie in <grpclass>. A (finite) group is primitive if it has a
faithful primitive permutation representation, or equivalently, if it has a
maximal subgroup with trivial core. A Schunck class contains every trivial
group. 

\>IsSaturated(<grpclass>) P

if true, <G> belongs to <X> whenever <G>/`FrattiniSubgroup(<G>)' belongs to
<X>.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\Section{Additional properties of group classes}\null

\index{group classes!properties of}
\index{properties!of group classes}

Note that the following ``properties'' are not properties but only filters in
the {\GAP} sense (cf. "ref:Properties" and "ref:Filters" in the {\GAP}
reference manual).

\>HasIsFittingClass(<obj>) F

is true if <obj> *knows* if it is a Fitting class, that is, if it lies in the
filters  `HasIsGroupClass', `HasContainsTrivialGroup',
`HasIsNormalSubgroupClosed'  and `HasIsNormalProductClosed'.

\>IsFittingClass(<obj>) F

is true if <obj> is a Fitting class, that is, if it has the properties
`IsGroupClass', `ContainsTrivialGroup', `IsNormalSubgroupClosed' and
`IsNormalProductClosed'.

\>SetIsFittingClass(<group class>, <bool>) F

If <bool> is `true', this fake setter function sets the properties
`IsNormalSubgroupClosed' and `IsNormalProductClosed' of <group class> to
<true>. It is the user's responsibility  to ensure that <group class> is
indeed a Fitting class.

\beginexample
gap> nilp := GroupClass(IsNilpotent);
GroupClass(in:=<Operation "IsNilpotent">)
gap> SetIsFittingClass(nilp, true);
gap> nilp;
FittingClass(in:=<Operation "IsNilpotent">)
\endexample

\>HasIsOrdinaryFormation(<obj>) F

\indextt{HasIsFormation}\relax
is true if <obj> *knows* if it is a formation, that is, if it lies in the filters
`HasIsGroupClass', `HasContainsTrivialGroup', `HasIsQuotientClosed' and 
`HasIsResiduallyClosed'.

\>IsOrdinaryFormation(<obj>) F

\indextt{IsFormation}\relax
is true if <obj> is a formation, that is, if it has the properties
`IsGroupClass', `ContainsTrivialGroup', `IsQuotientClosed' and `IsResiduallyClosed'.

\>SetIsOrdinaryFormation(<class>, <bool>) F

\indextt{SetIsFormation}\relax
If <bool> is `true', this sets the attributes `IsQuotientClosed',
`ContainsTrivialGroup', and `IsResiduallyClosed' of <class>, making it a formation.

\>HasIsSaturatedFormation(<obj>) F

returns true if <obj> *knows* if it is a saturated formation, that is, if it
lies in the filters `HasIsOrdinaryFormation' and `HasIsSaturated'.

\>IsSaturatedFormation(<obj>) F

returns true if <obj> is a saturated formation, that is, if it has the
properties `IsOrdinaryFormation' and `IsSaturated'

\>SetIsSaturatedFormation(<class>, <bool>) F

If <bool> is `true', this sets the attributes `IsQuotientClosed',
`ContainsTrivialGroup', and `IsResiduallyClosed' and `IsSaturated'
of <class>, making it a saturated formation.

\>HasIsFittingFormation(<obj>) F

returns true if <obj> *knows* whether it is a Fitting formation, that is, if it lies in the
filters `HasIsOrdinaryFormation' and  `HasIsFittingClass' (see "HasIsOrdinaryFormation" and
"HasIsFittingClass").


\>IsFittingFormation(<obj>) F

returns true if <obj> is both a formation and a Fitting class.

\>SetIsFittingFormation(<class>, <bool>) F

If <bool> is `true', this function sets the attributes of <class> to indicate
that it is a Fitting formation.

\>HasIsSaturatedFittingFormation(<obj>)  F

returns true if <obj>  *knows* whether it is a saturated Fitting formation, that is, if it lies
in the filters `HasIsSaturatedFormation' and  `HasIsFittingClass' (see "HasIsSaturatedFormation"
and "HasIsFittingClass").

\>IsSaturatedFittingFormation(<obj>) F

returns true if <obj> is both a saturated formation and a Fitting class, that is, if it lies 
in the filters `IsSaturatedFormation' and  `IsFittingClass' (see "IsSaturatedFormation"
and "IsFittingClass").

\>SetIsSaturatedFittingFormation(<class>, <bool>) F

If <bool> is `true', this sets the attributes of <class> to indicate that it
is a saturated Fitting formation.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\Section{Attributes of group classes}\null

\index{group classes!attributes for}
\index{attributes!of group classes}

In addition to the attribute `MemberFunction' which has the same meaning as
for generic classes, a group class may have the following attribute.

\>Characteristic(<grpclass>) A

This attribute, if present, stores a class containing all primes $p$ such
that <grpclass> contains a cyclic group of order~$p$. There is a pre-defined
class `AllPrimes' which should be assigned to `Characteristic' if <grpclass>
contains a cyclic group of order $p$ for every prime~$p$.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%E
%%
