%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%A  anupq.tex    ANUPQ documentation - non-interactive f'ns    Eamonn O'Brien
%A                                                             & Frank Celler
%A                                                           & Benedikt Rothe
%%
%A  @(#)$Id: anupq.tex,v 1.54 2004/02/05 17:17:25 gap Exp $
%%
%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\Chapter{Non-interactive ANUPQ functions}

Here we describe  all  the  non-interactive  functions  of  the  {\ANUPQ}
package; i.e.~``one-shot'' functions that invoke the `pq' program in such
a way that once {\GAP} has got what it needs, the `pq' program is allowed
to exit. It is expected that most of the time users will only need  these
functions. The functions interface with three of the four algorithms (see
Chapter~"Introduction") provided by the  ANU  `pq'  C  program,  and  are
mainly grouped according to the algorithm of the `pq' program they relate
to.

In Section~"Computing p-Quotients", we describe the functions  that  give
access to the $p$-quotient algorithm.

Section~"Computing Standard Presentations" describe functions  that  give
access to the standard presentation algorithm.

Section~"Testing  p-Groups  for  Isomorphism"  describe  functions   that
implement  an  isomorphism  test  for  $p$-groups  using   the   standard
presentation algorithm.

In Section~"Computing Descendants of a p-Group",  we  describe  functions
that give access to the $p$-group generation algorithm.

To use any of the functions one must have at some stage previously typed:

\begintt
gap> LoadPackage("anupq");
\endtt

(the response of which we have omitted; see~"Loading the ANUPQ Package").

It is strongly recommended that the user try the  examples  provided.  To
save typing there is a `PqExample' equivalent for each manual example. We
also  suggest  that  to  start  with  you  may  find  the  examples  more
instructive if you set the `InfoANUPQ' level to 2 (see~"InfoANUPQ").

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\Section{Computing  p-Quotients}

\>Pq( <F> : <options> ) F

returns for the fp or pc group <F>, the $p$-quotient of <F> specified  by
<options>, as a pc group. Following the colon, <options> is  a  selection
of the options from the following list, separated by commas  like  record
components (see Section~"ref:function call!with options"  in  the  {\GAP}
Reference Manual). As a minimum the user *must* supply a  value  for  the
`Prime' option. Below  we  list  the  options  recognised  by  `Pq'  (see
Chapter~"ANUPQ options" for detailed descriptions).

\beginlist%unordered

\atindex{option Prime}{@option \noexpand`Prime'}
\item{}`Prime := <p>'

\atindex{option ClassBound}{@option \noexpand`ClassBound'}
\item{}`ClassBound := <n>'

\atindex{option Exponent}{@option \noexpand`Exponent'}
\item{}`Exponent := <n>'

\atindex{option Relators}{@option \noexpand`Relators'}
\item{}`Relators := <rels>'

\atindex{option Metabelian}{@option \noexpand`Metabelian'}
\item{}`Metabelian'

\atindex{option Identities}{@option \noexpand`Identities'}
\item{}`Identities := <funcs>'

\atindex{option GroupName}{@option \noexpand`GroupName'}
\item{}`GroupName := <name>'

\atindex{option OutputLevel}{@option \noexpand`OutputLevel'}
\item{}`OutputLevel := <n>'

\atindex{option SetupFile}{@option \noexpand`SetupFile'}
\item{}`SetupFile := <filename>'

\atindex{option PqWorkspace}{@option \noexpand`PqWorkspace'}
\item{}`PqWorkspace := <workspace>'

\endlist

*Notes:* `Pq' may also  be  called  with  no  arguments  or  one  integer
argument,   in   which   case   it   is    being    used    interactively
(see~"Pq!interactive");  the  same  options  may  be  used,  except  that
`SetupFile'  and  `PqWorkspace'  are  ignored  by  the  interactive  `Pq'
function.

See Section~"Attributes and a Property for fp and pc  p-groups"  for  the
attributes   and   property   `NuclearRank',   `MultiplicatorRank'    and
`IsCapable' which may be applied to the group returned by `Pq'.

See also `PqEpimorphism' ("PqEpimorphism").

We now give a few examples of the use of `Pq'. Except for the addition of
a few comments and the non-suppression of output (by not using duplicated
semicolons) the next 3 examples may be run by  typing:  `PqExample(  "Pq"
);' (see~"PqExample").

\beginexample
gap> LoadPackage("anupq");; # does nothing if ANUPQ is already loaded
gap> # First we get a p-quotient of a free group of rank 2
gap> F := FreeGroup("a", "b");; a := F.1;; b := F.2;;
gap> Pq( F : Prime := 2, ClassBound := 3 ); 
<pc group of size 1024 with 10 generators>
gap> # Now let us get a p-quotient of an fp group
gap> G := F / [a^4, b^4];
<fp group on the generators [ a, b ]>
gap> Pq( G : Prime := 2, ClassBound := 3 ); 
<pc group of size 256 with 8 generators>
gap> # Now let's get a different p-quotient of the same group
gap> Pq( G : Prime := 2, ClassBound := 3, Exponent := 4 ); 
<pc group of size 128 with 7 generators>
gap> # Now we'll get a p-quotient of another fp group
gap> # which we will redo using the `Relators' option
gap> R := [ a^25, Comm(Comm(b, a), a), b^5 ];
[ a^25, a^-1*b^-1*a*b*a^-1*b^-1*a^-1*b*a^2, b^5 ]
gap> H := F / R;
<fp group on the generators [ a, b ]>
gap> Pq( H : Prime := 5, ClassBound := 5, Metabelian );
<pc group of size 78125 with 7 generators>
\endexample

\atindex{option Relators!example of usage}%
{@option \noexpand`Relators'!example of usage}
Now we redo the last example to show  how  one  may  use  the  `Relators'
option. Observe that `Comm(Comm(b, a), a)' is a  left  normed  commutator
which must be written in square bracket notation for the `pq' program and
embedded in  a  pair  of  double  quotes.  The  function  `PqGAPRelators'
(see~"PqGAPRelators") can be used to translate a list of strings prepared
for the `Relators' option into {\GAP} format. Below we  use  it.  Observe
that the value of `R' is the same as before.

\beginexample
gap> F := FreeGroup("a", "b");;
gap> # `F' was defined for `Relators'. We use the same strings that GAP uses
gap> # for printing the free group generators. It is *not* necessary to
gap> # predefine: a := F.1; etc. (as it was above).
gap> rels := [ "a^25", "[b, a, a]", "b^5" ];
[ "a^25", "[b, a, a]", "b^5" ]
gap> R := PqGAPRelators(F, rels);
[ a^25, a^-1*b^-1*a*b*a^-1*b^-1*a^-1*b*a^2, b^5 ]
gap> H := F / R;
<fp group on the generators [ a, b ]>
gap> Pq( H : Prime := 5, ClassBound := 5, Metabelian, 
>            Relators := rels );
<pc group of size 78125 with 7 generators>
\endexample

In fact, above we could have just passed `F' (rather than  `H'),  i.e.~we
could have done:

\beginexample
gap> F := FreeGroup("a", "b");;
gap> rels := [ "a^25", "[b, a, a]", "b^5" ];
[ "a^25", "[b, a, a]", "b^5" ]
gap> Pq( F : Prime := 5, ClassBound := 5, Metabelian, 
>            Relators := rels );
<pc group of size 78125 with 7 generators>
\endexample

The non-interactive `Pq' function also allows the options to be passed in
two other ways; these alternatives have been included for those  familiar
with the {\GAP}~3 version of the {\ANUPQ} package; the  preferred  method
of passing options is the one already described.  Firstly,  they  may  be
passed in a record as a second argument; note that  any  boolean  options
must be set explicitly e.g.

\beginexample
gap> Pq( H, rec( Prime := 5, ClassBound := 5, Metabelian := true ) );
<pc group of size 78125 with 7 generators>
\endexample

It is also possible to pass them as extra arguments,  where  each  option
name appears as a string followed immediately by  its  value  (if  not  a
boolean option) e.g.

\beginexample
gap> Pq( H, "Prime", 5, "ClassBound", 5, "Metabelian" );             
<pc group of size 78125 with 7 generators>
\endexample

The preceding two examples can be run from {\GAP} via `PqExample( "Pq-ni"
);' (see~"PqExample").

This method of passing options permits abbreviation; the only restriction
is that the abbreviation must be  unique.  So  `"Pr"'  may  be  used  for
`"Prime"', `"Class"' or even just `"C"' for `"ClassBound"', etc.

\atindex{option Identities!example of usage}%
{@option \noexpand`Identities'!example of usage}
The following example illustrates the use of the option `Identities'.  We
compute the largest finite Burnside  group  of  exponent  $5$  that  also
satisfies the $3$-Engel identity. Each identity is defined by a  function
whose arguments correspond to the variables of the identity.  The  return
value of each of  those  functions  is  the  identity  evaluated  on  the
arguments of the function.

\beginexample
gap> F := FreeGroup(2);
<free group on the generators [ f1, f2 ]>
gap> Burnside5 := x->x^5;
function( x ) ... end
gap> Engel3 := function( x,y ) return PqLeftNormComm( [x,y,y,y] ); end;
function( x, y ) ... end
gap> Pq( F : Prime := 5, Identities := [ Burnside5, Engel3 ] );
#I  Class 1 with 2 generators.
#I  Class 2 with 3 generators.
#I  Class 3 with 5 generators.
#I  Class 3 with 5 generators.
<pc group of size 3125 with 5 generators>
\endexample

The above example can be run from {\GAP} via `PqExample( "B5-5-Engel3-Id"
);' (see~"PqExample").

\>PqEpimorphism( <F> : <options> ) F

returns for the fp or pc group <F>  an  epimorphism  from  <F>  onto  the
$p$-quotient  of  <F>  specified  by  <options>;  the  possible   options
<options> and *required* option (`"Prime"') are as for  `Pq'  (see~"Pq").
`PqEpimorphism' only differs from `Pq' in  what  it  outputs;  everything
about what must/may be passed as input to `PqEpimorphism' is the same  as
for `Pq'.  The  same  alternative  methods  of  passing  options  to  the
non-interactive  `Pq'  function  are  available  to  the  non-interactive
version of `PqEpimorphism'.

*Notes:* `PqEpimorphism' may also be called  with  no  arguments  or  one
integer  argument,  in  which  case  it  is  being   used   interactively
(see~"PqEpimorphism!interactive"),  and  the  options   `SetupFile'   and
`PqWorkspace' are ignored by the interactive `PqEpimorphism' function.

See Section~"Attributes and a Property for fp and pc  p-groups"  for  the
attributes   and   property   `NuclearRank',   `MultiplicatorRank'    and
`IsCapable' which may be applied to the image group  of  the  epimorphism
returned by `PqEpimorphism'.

\beginexample
gap> F := FreeGroup (2, "F");
<free group on the generators [ F1, F2 ]>
gap> phi := PqEpimorphism( F : Prime := 5, ClassBound := 2 );
[ F1, F2 ] -> [ f1, f2 ]
gap> Image( phi );
<pc group of size 3125 with 5 generators>
\endexample

Typing: `PqExample( "PqEpimorphism" );' runs the above example in  {\GAP}
(see~"PqExample").

\>PqPCover( <F> : <options> ) F

returns for the fp or  pc  group  <F>,  the  $p$-covering  group  of  the
$p$-quotient of <F> specified by  <options>,  as  a  pc  group,  i.e.~the
$p$-covering group of the $p$-quotient `Pq( <F> : <options> )'. Thus  the
options that `PqPCover' accepts are exactly those expected for `Pq'  (and
hence as a minimum the user *must* supply a value for the `Prime' option;
see~"Pq" for more details), except in the following special case.

If <F> is already a $p$-group, in the sense  that  `HasIsPGroup(<F>)  and
IsPGroup(<F>)' is `true', then

\beginitems

`Prime'& 
defaults to `PrimePGroup(<F>)', if not supplied and  `HasPrimePGroup(<F>)
= true'; and

`ClassBound'&
defaults to `PClassPGroup(<F>)' if `HasPClassPGroup(<F>) =  true'  if  not
supplied, or to the usual default of 63, otherwise.

\enditems

The same alternative methods of passing options  to  the  non-interactive
`Pq' function are available to the non-interactive version of `PqPCover'.

We now give a few examples of the use of `PqPCover'. These  examples  are
just a subset of the ones we gave for `Pq'  (see~"Pq"),  except  that  in
each instance  the  command  `Pq'  has  been  replaced  with  `PqPCover'.
Essentially  the  same  examples  may  be  run  by  typing:   `PqExample(
"PqPCover" );' (see~"PqExample").

\beginexample
gap> F := FreeGroup("a", "b");; a := F.1;; b := F.2;;
gap> PqPCover( F : Prime := 2, ClassBound := 3 );
<pc group of size 262144 with 18 generators>
gap> 
gap> # Now let's get a p-cover of a p-quotient of an fp group
gap> G := F / [a^4, b^4];
<fp group on the generators [ a, b ]>
gap> PqPCover( G : Prime := 2, ClassBound := 3 );
<pc group of size 16384 with 14 generators>
gap> 
gap> # Now let's get a p-cover of a different p-quotient of the same group
gap> PqPCover( G : Prime := 2, ClassBound := 3, Exponent := 4 );
<pc group of size 8192 with 13 generators>
gap> 
gap> # Now we'll get a p-cover of a p-quotient of another fp group
gap> # which we will redo using the `Relators' option
gap> R := [ a^25, Comm(Comm(b, a), a), b^5 ];
[ a^25, a^-1*b^-1*a*b*a^-1*b^-1*a^-1*b*a^2, b^5 ]
gap> H := F / R;
<fp group on the generators [ a, b ]>
gap> PqPCover( H : Prime := 5, ClassBound := 5, Metabelian );
<pc group of size 48828125 with 11 generators>
gap> 
gap> # Now we redo the previous example using the `Relators' option
gap> F := FreeGroup("a", "b");;
gap> rels := [ "a^25", "[b, a, a]", "b^5" ];
[ "a^25", "[b, a, a]", "b^5" ]
gap> PqPCover( F : Prime := 5, ClassBound := 5, Metabelian, 
>                  Relators := rels );
<pc group of size 48828125 with 11 generators>
\endexample

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\Section{Computing Standard Presentations}

\index{automorphisms!of $p$-groups}
\>PqStandardPresentation( <F> : <options> ) F
\>StandardPresentation( <F> : <options> ) M

return the <p>-quotient specified by  <options> of the fp or pc $p$-group
<F>, as an *fp group*  which has a standard presentation.  Here <options>
is a selection of the options from the following list (see Chapter~"ANUPQ
options"  for   detailed  descriptions).   Section~"Hints   and  Warnings
regarding the  use of  Options" gives some  important hints  and warnings
regarding option  usage, and Section~"ref:function  call!with options" in
the {\GAP} Reference Manual describes their ``record''-like syntax.

\beginlist%unordered

\atindex{option Prime}{@option \noexpand`Prime'}
\item{}`Prime := <p>'

\atindex{option pQuotient}{@option \noexpand`pQuotient'}
\item{}`pQuotient := <Q>'

\atindex{option ClassBound}{@option \noexpand`ClassBound'}
\item{}`ClassBound := <n>'

\atindex{option Exponent}{@option \noexpand`Exponent'}
\item{}`Exponent := <n>'

\atindex{option Metabelian}{@option \noexpand`Metabelian'}
\item{}`Metabelian'

\atindex{option GroupName}{@option \noexpand`GroupName'}
\item{}`GroupName := <name>'

\atindex{option OutputLevel}{@option \noexpand`OutputLevel'}
\item{}`OutputLevel := <n>'

\atindex{option StandardPresentationFile}%
{@option \noexpand`StandardPresentationFile'}
\item{}`StandardPresentationFile := <filename>'

\atindex{option SetupFile}{@option \noexpand`SetupFile'}
\item{}`SetupFile := <filename>'

\atindex{option PqWorkspace}{@option \noexpand`PqWorkspace'}
\item{}`PqWorkspace := <workspace>'

\endlist

Unless <F> is a pc <p>-group, the user *must* supply  either  the  option
`Prime' or the option `pQuotient' (if both `Prime'  and  `pQuotient'  are
supplied,  the  prime  <p>  is  determined  by   applying   `PrimePGroup'
(see~"ref:PrimePGroup"  in  the  Reference  Manual)  to  the   value   of
`pQuotient').

The options for `PqStandardPresentation' may also be passed  in  the  two
alternative ways described for  `Pq'  (see~"Pq").  `StandardPresentation'
does not provide these alternative ways of passing options.

*Notes:*
In contrast  to the  function `Pq' (see~"Pq")  which returns a  pc group,
`PqStandardPresentation' or `StandardPresentation' returns an  fp  group.
This is because the output is mainly used  for  isomorphism  testing  for
which an fp group is enough. However, the presentation  is  a  polycyclic
presentation and if you need to do  any  further  computation  with  this
group (e.g.~to find the order) you can use the function  `PcGroupFpGroup'
(see~"ref:PcGroupFpGroup" in the {\GAP} Reference Manual) to  form  a  pc
group.

If the user does not supply a <p>-quotient <Q> via the `pQuotient' option
and the prime <p> is either supplied or <F> is a  pc  <p>-group,  then  a
<p>-quotient <Q> is computed. If the user does supply a <p>-quotient  <Q>
via the `pQuotient' option, the package {\AutPGrp} is called  to  compute
the automorphism group of <Q>; an error will occur that asks the user  to
install the package  {\AutPGrp}  if  the  automorphism  group  cannot  be
computed.

The  attributes  and  property  `NuclearRank',  `MultiplicatorRank'   and
`IsCapable' are set for the group returned by `PqStandardPresentation' or
`StandardPresentation' (see Section~"Attributes and a Property for fp and
pc p-groups").

We illustrate the method with the following examples.

\beginexample
gap> F := FreeGroup( "a", "b" );; a := F.1;; b := F.2;;
gap> G := F / [a^25, Comm(Comm(b, a), a), b^5];
<fp group on the generators [ a, b ]>
gap> S := StandardPresentation( G : Prime := 5, ClassBound := 10 );
<fp group on the generators [ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, 
  f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26 ]>
gap> IsPcGroup( S );
false
gap> # if we need to compute with S we should convert it to a pc group
gap> Spc := PcGroupFpGroup( S );
<pc group of size 1490116119384765625 with 26 generators>
gap> 
gap> H := F / [ a^625, Comm(Comm(Comm(Comm(b, a), a), a), a)/Comm(b, a)^5,
>               Comm(Comm(b, a), b), b^625 ];;                     
gap> StandardPresentation( H : Prime := 5, ClassBound := 15, Metabelian );
<fp group on the generators [ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, 
  f12, f13, f14, f15, f16, f17, f18, f19, f20 ]>
gap> 
gap> F4 := FreeGroup( "a", "b", "c", "d" );;                        
gap> a := F4.1;; b := F4.2;; c := F4.3;; d := F4.4;;
gap> G4 := F4 / [ b^4, b^2 / Comm(Comm (b, a), a), d^16,                
>                 a^16 / (c * d), b^8 / (d * c^4) ];
<fp group on the generators [ a, b, c, d ]>
gap> K := Pq( G4 : Prime := 2, ClassBound := 1 );
<pc group of size 4 with 2 generators>
gap> StandardPresentation( G4 : pQuotient := K, ClassBound := 14 );
<fp group with 53 generators>
\endexample

Typing: `PqExample( "StandardPresentation" );' runs the above example  in
{\GAP} (see~"PqExample").

\>EpimorphismPqStandardPresentation( <F> : <options> ) F
\>EpimorphismStandardPresentation( <F> : <options> ) M

Each of the above functions accepts the same arguments and options as the
function `StandardPresentation' (see~"StandardPresentation") and  returns
an epimorphism from the fp or pc group <F> onto  the  finitely  presented
group given by a standard  presentation,  i.e.~if  <S>  is  the  standard
presentation    computed    for    the    $p$-quotient    of    <F>    by
`StandardPresentation' then `EpimorphismStandardPresentation' returns the
epimorphism from <F> to the group with presentation <S>.

*Note:*
The  attributes  and  property  `NuclearRank',  `MultiplicatorRank'   and
`IsCapable' are set for the image group of the  epimorphism  returned  by
`EpimorphismPqStandardPresentation' or  `EpimorphismStandardPresentation'
(see Section~"Attributes and a Property for fp and pc p-groups").

We illustrate the function with the following example.

\beginexample
gap> F := FreeGroup(6, "F");
<free group on the generators [ F1, F2, F3, F4, F5, F6 ]>
gap> # For printing GAP uses the symbols F1, ... for the generators of F
gap> x := F.1;; y := F.2;; z := F.3;; w := F.4;; a := F.5;; b := F.6;;
gap> R := [x^3 / w, y^3 / w * a^2 * b^2, w^3 / b,
>          Comm (y, x) / z, Comm (z, x), Comm (z, y) / a, z^3 ];;
gap> Q := F / R;
<fp group on the generators [ F1, F2, F3, F4, F5, F6 ]>
gap> # For printing GAP also uses the symbols F1, ... for the generators of Q
gap> # (the same as used for F) ... but the gen'rs of Q and F are different:
gap> GeneratorsOfGroup(F) = GeneratorsOfGroup(Q);
false
gap> G := Pq( Q : Prime := 3, ClassBound := 3 );
<pc group of size 729 with 6 generators>
gap> phi := EpimorphismStandardPresentation( Q : Prime := 3,
>                                                ClassBound := 3 );
[ F1, F2, F3, F4, F5, F6 ] -> [ f1*f2^2*f3*f4^2*f5^2, f1*f2*f3*f5, f3^2, 
  f4*f6^2, f5, f6 ]
gap> NamesOfComponents(phi);
[ "Source", "Range", "MappingGeneratorsImages" ]
gap> phi!.Source; # This is the group Q (GAP uses F1, ... for gen'r symbols)
<fp group of size infinity on the generators [ F1, F2, F3, F4, F5, F6 ]>
gap> phi!.Range;  # This is the group G (GAP uses f1, ... for gen'r symbols)
<fp group on the generators [ f1, f2, f3, f4, f5, f6 ]>
gap> AssignGeneratorVariables(G);
#I  Assigned the global variables [ f1, f2, f3, f4, f5, f6 ]
gap> # Just to see that the images of [F1, ..., F6] do generate G
gap> Group([ f1*f2^2*f3, f1*f2*f3*f4*f5^2*f6^2, f3^2, f4, f5, f6 ]) = G;
true
gap> Size( Image(phi) );
729
\endexample

Typing: `PqExample( "EpimorphismStandardPresentation" );' runs the  above
example in {\GAP} (see~"PqExample"). Note that `AssignGeneratorVariables'
(see~"ref:AssignGeneratorVariables")  has  only  been   available   since
{\GAP}~4.3.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\Section{Testing p-Groups for Isomorphism}

\>IsPqIsomorphicPGroup( <G>, <H> ) F
\>IsIsomorphicPGroup( <G>, <H> ) M

each return true if <G> is isomorphic to <H>, where both <G> and <H> must
be pc groups of prime power order. These functions  compute  and  compare
in {\GAP} the fp groups given by standard presentations for <G>  and  <H>
(see "StandardPresentation").

\beginexample
gap> G := Group( (1,2,3,4), (1,3) );
Group([ (1,2,3,4), (1,3) ])
gap> P1 := Image( IsomorphismPcGroup( G ) );
Group([ f1, f2, f3 ])
gap> P2 := SmallGroup( 8, 5 );
<pc group of size 8 with 3 generators>
gap> IsIsomorphicPGroup( P1, P2 );
false
gap> P3 := SmallGroup( 8, 4 );
<pc group of size 8 with 3 generators>
gap> IsIsomorphicPGroup( P1, P3 );
false
gap> P4 := SmallGroup( 8, 3 );
<pc group of size 8 with 3 generators>
gap> IsIsomorphicPGroup( P1, P4 );
true
\endexample

Typing: `PqExample( "IsIsomorphicPGroup" );' runs the  above  example  in
{\GAP} (see~"PqExample").

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\Section{Computing Descendants of a p-Group}

\>PqDescendants( <G> : <options> ) F

returns, for the pc group <G> which must be of prime power order  with  a
confluent pc presentation (see~"ref:IsConfluent!for  pc  groups"  in  the
{\GAP} Reference Manual), a list  of  descendants  (pc  groups)  of  <G>.
Following the colon <options> a selection of  the  options  listed  below
should  be  given,  separated  by  commas  like  record  components  (see
Section~"ref:function call!with options" in the {\GAP} Reference Manual).
See Chapter~"ANUPQ options" for detailed descriptions of the options.

The automorphism group of each descendant <D> is also computed via a call
to the `AutomorphismGroupPGroup' function of the {\AutPGrp} package.
%For each descendant <D>, a subgroup of the automorphism group  of <D>  is
%computed which is  a supplement to the inner automorphisms  of <D> in the
%whole automorphism group  of <D>.  This subgroup can  be accessed via the
%function                                 `PqSupplementInnerAutomorphisms'
%(see~"PqSupplementInnerAutomorphisms").

\beginlist%unordered

\atindex{option ClassBound}{@option \noexpand`ClassBound'}
\item{}`ClassBound := <n>'

\atindex{option Relators}{@option \noexpand`Relators'}
\item{}`Relators := <rels>'

\atindex{option OrderBound}{@option \noexpand`OrderBound'}
\item{}`OrderBound := <n>'

\atindex{option StepSize}{@option \noexpand`StepSize'}
\item{}`StepSize := <n>', `StepSize := <list>'

\atindex{option RankInitialSegmentSubgroups}%
{@option \noexpand`RankInitialSegmentSubgroups'}
\item{}`RankInitialSegmentSubgroups := <n>'

\atindex{option SpaceEfficient}{@option \noexpand`SpaceEfficient'}
\item{}`SpaceEfficient'

\atindex{option CapableDescendants}{@option \noexpand`CapableDescendants'}
\item{}`CapableDescendants'

\atindex{option AllDescendants}{@option \noexpand`AllDescendants'}
\item{}`AllDescendants := false'

\atindex{option Exponent}{@option \noexpand`Exponent'}
\item{}`Exponent := <n>'

\atindex{option Metabelian}{@option \noexpand`Metabelian'}
\item{}`Metabelian'

\atindex{option GroupName}{@option \noexpand`GroupName'}
\item{}`GroupName := <name>'

\atindex{option SubList}{@option \noexpand`SubList'}
\item{}`SubList := <sub>'

\atindex{option BasicAlgorithm}{@option \noexpand`BasicAlgorithm'}
\item{}`BasicAlgorithm'

\atindex{option CustomiseOutput}{@option \noexpand`CustomiseOutput'}
\item{}`CustomiseOutput := <rec>'

\atindex{option SetupFile}{@option \noexpand`SetupFile'}
\item{}`SetupFile := <filename>'

\atindex{option PqWorkspace}{@option \noexpand`PqWorkspace'}
\item{}`PqWorkspace := <workspace>'

\endlist

*Notes:*
The function `PqDescendants' uses the  automorphism group of <G> which it
computes via the package {\AutPGrp}.  If this package is not installed an
error may be  raised. If the automorphism group of  <G> is insoluble, the
`pq' program  will call {\GAP}  together with the {\AutPGrp}  package for
certain  orbit-stabilizer calculations.   (So,  in any  case, one  should
ensure the {\AutPGrp} package is installed.)

The  attributes  and  property  `NuclearRank',  `MultiplicatorRank'   and
`IsCapable'  are  set  for  each  group   of   the   list   returned   by
`PqDescendants' (see Section~"Attributes and a Property  for  fp  and  pc
p-groups").

The options <options> for `PqDescendants' may be passed in an alternative
manner to that already described, namely you can pass  `PqDescendants'  a
record as an argument, which contains as entries some  (or  all)  of  the
above mentioned. Those parameters which do not occur in  the  record  are
set to their default values.

Note that you cannot set both `OrderBound' and `StepSize'.

In the first example  we  compute all descendants of the Klein four group
which have exponent-2 class at most 5 and order at most $2^6$.

\beginexample
gap> F := FreeGroup( "a", "b" );; a := F.1;; b := F.2;;         
gap> G := PcGroupFpGroup( F / [ a^2, b^2, Comm(b, a) ] );
<pc group of size 4 with 2 generators>
gap> des := PqDescendants( G : OrderBound := 6, ClassBound := 5 );;
gap> Length(des);
83
gap> List(des, Size); 
[ 8, 8, 8, 16, 16, 16, 32, 16, 16, 16, 16, 16, 32, 32, 64, 64, 32, 32, 32, 
  32, 32, 32, 32, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 32, 32, 32, 32, 
  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 32, 32, 32, 32, 32, 64, 64, 64, 
  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
  64, 64, 64, 64, 64, 64, 64 ]
gap> List(des, d -> Length( PCentralSeries( d, 2 ) ) - 1 );
[ 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 
  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
  4, 4, 4, 5, 5, 5, 5, 5 ]
\endexample

Below, we compute all capable descendants of order 27 of  the  elementary
abelian group of order 9.

\beginexample
gap> F := FreeGroup( 2, "g" );
<free group on the generators [ g1, g2 ]>
gap> G := PcGroupFpGroup( F / [ F.1^3, F.2^3, Comm(F.1, F.2) ] );
<pc group of size 9 with 2 generators>
gap> des := PqDescendants( G : OrderBound := 3, ClassBound := 2,
>                              CapableDescendants );
[ <pc group of size 27 with 3 generators>, 
  <pc group of size 27 with 3 generators> ]
gap> List(des, d -> Length( PCentralSeries( d, 3 ) ) - 1 );
[ 2, 2 ]
gap> # For comparison let us now compute all descendants
gap> PqDescendants( G : OrderBound := 3, ClassBound := 2);
[ <pc group of size 27 with 3 generators>, 
  <pc group of size 27 with 3 generators>, 
  <pc group of size 27 with 3 generators> ]
\endexample

In  the  third  example,  we  compute  all  capable  descendants  of  the
elementary abelian group of order  $5^2$ which have exponent-$5$ class at
most $3$, exponent $5$, and are metabelian.

\beginexample
gap> F := FreeGroup( 2, "g" );;                                  
gap> G := PcGroupFpGroup( F / [ F.1^5, F.2^5, Comm(F.2, F.1) ] );
<pc group of size 25 with 2 generators>
gap> des := PqDescendants( G : Metabelian, ClassBound := 3,
>                              Exponent := 5, CapableDescendants );
[ <pc group of size 125 with 3 generators>, 
  <pc group of size 625 with 4 generators>, 
  <pc group of size 3125 with 5 generators> ]
gap> List(des, d -> Length( PCentralSeries( d, 5 ) ) - 1 );
[ 2, 3, 3 ]
gap> List(des, d -> Length( DerivedSeries( d ) ) );
[ 3, 3, 3 ]
gap> List(des, d -> Maximum( List( Elements(d), Order ) ) );     
[ 5, 5, 5 ]
\endexample

The     examples     `"PqDescendants-1"',     `"PqDescendants-2"'     and
`"PqDescendants-3"' (in order) are essentially  the  same  as  the  above
three examples (see~"PqExample").

\>PqSupplementInnerAutomorphisms( <D> ) F

returns a generating set for a supplement to the inner  automorphisms  of
<D>, in the form  of  a  record  with  fields  `agAutos',  `agOrder'  and
`glAutos', as provided by the `pq' program. One should be very careful in
using these automorphisms for a descendant calculation.
%The automorphisms generate a subgroup of the automorphism group of the pc
%group <D> that supplements the inner automorphism group  of  <D>  in  the
%whole automorphism group of <D>. The group of automorphisms returned  may
%be a proper subgroup of the full automorphism group. The  descendant  <D>
%must   have   been   computed    by    the    function    `PqDescendants'
%(see~"PqDescendants").

*Note:*
In principle there must be a way to use those automorphisms in  order  to
compute descendants but there does not seem to be  a  way  to  hand  back
these automorphisms properly to the `pq' program.

\beginexample
gap> Q := Pq( FreeGroup(2) : Prime := 3, ClassBound := 1 );
<pc group of size 9 with 2 generators>
gap> des := PqDescendants( Q : StepSize := 1 );
[ <pc group of size 27 with 3 generators>, 
  <pc group of size 27 with 3 generators>, 
  <pc group of size 27 with 3 generators> ]
gap> S := PqSupplementInnerAutomorphisms( des[3] );
rec( agAutos := [  ], agOrder := [ 3, 2, 2, 2 ], 
  glAutos := [ Pcgs([ f1, f2, f3 ]) -> [ f1*f2^2, f2, f3 ], 
      Pcgs([ f1, f2, f3 ]) -> [ f1^2, f2, f3^2 ], 
      Pcgs([ f1, f2, f3 ]) -> [ f1^2, f2, f3^2 ] ] )
gap> A := AutomorphismGroupPGroup( des[3] );
rec( glAutos := [  ], glOrder := 1, 
  agAutos := [ Pcgs([ f1, f2, f3 ]) -> [ f1^2, f2, f3^2 ], 
      Pcgs([ f1, f2, f3 ]) -> [ f1*f2^2, f2, f3 ], 
      Pcgs([ f1, f2, f3 ]) -> [ f1*f3, f2, f3 ], 
      Pcgs([ f1, f2, f3 ]) -> [ f1, f2*f3, f3 ] ], agOrder := [ 2, 3, 3, 3 ], 
  one := IdentityMapping( <pc group of size 27 with 3 generators> ), 
  group := <pc group of size 27 with 3 generators>, size := 54, 
  glOper := [  ]
\endexample

The   above   example   may   be   executed   on-line   via   `PqExample(
"PqSupplementInnerAutomorphisms" );' (see~"PqExample"). 

Note that by also including `PqStart' as a second argument to `PqExample'
one can see how it is possible, with the aid  of  `PqSetPQuotientToGroup'
(see~"PqSetPQuotientToGroup"), to do the equivalent computations with the
interactive versions of  `Pq'  and  `PqDescendants'  and  a  single  `pq'
process (recall `pq' is the name of the external C program).

\>PqList( <filename> [: SubList := <sub> ]) F

reads a file with name <filename> (a string) and returns the list <L>  of
pc groups (or with option `SubList' a sublist of <L> or a single pc group
in <L>) defined in that file. If the option `SubList' is passed  and  has
the value <sub>, then it has the same  meaning  as  for  `PqDescendants',
i.e.~if  <sub>  is  an  integer  then  `PqList'   returns   `<L>[<sub>]';
otherwise, if <sub> is a list of integers `PqList' returns  `Sublist(<L>,
<sub> )'.

Both `PqList' and `SavePqList' (see "SavePqList") can be used to save and
restore a list of descendants (see "PqDescendants").

\>SavePqList( <filename>, <list> ) F

writes a list of descendants <list> to a file  with  name  <filename>  (a
string).

`SavePqList' and `PqList' (see "PqList") can be used to save and restore,
respectively, the results of `PqDescendants' (see "PqDescendants").

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