<!-- 

recognition.xml        recogbase package documentation
                                                               Max Neunhoeffer
                                                                   Ákos Seress

      Copyright (C) 2005-2008 by the authors.

This chapter covers the recursive, generic recognition procedure.

-->

<Chapter Label="recognition">
<Heading>Group Recognition</Heading>

This chapter describes a generic framework for group recognition.
The basic problem is, we want to solve the constructive membership
problem: given any
<M>g \in G</M>, <M>G = \langle X \rangle</M>, write a straight line
program (SLP) from <M>X</M> to <M>g</M>, for <M>g \notin G</M> (in the 
situation that <M>G</M> is naturally embedded into some bigger group),
the algorithm should fail. This is usually done by constructing
some nice generators (and then writing an SLP from the nice generators
to <M>g</M> and concatenating with an SLP from <M>X</M> to the nice
generators). Often, for efficiency reasons, we will just store the
nice generators and then only be interested in the SLP from those
to <M>g</M>. The framework presented here deals with exactly this
process.<P/>

The generic framework was designed having four situations in mind:
permutation groups, matrix groups, projective groups 
and black box groups. Although the
methods used are quite different for those four cases, there is a common
pattern in the procedure of recognition. Namely, first we have to find
a homomorphism, solve the constructive membership problem
recursively in image and kernel,
then put it together. The recursion ends in groups where we can solve
the constructive membership problem directly. 
The general framework reflects this idea and
separates it from the rest of the recognition methods.<P/>

Solution of the constructive membership problem comes 
in two stages: first a <Q>recognition
phase</Q> and then a <Q>verification phase</Q>. The recognition
phase usually consists of randomised algorithms with certain error
or failure probabilities. The result is some kind of <Q>recognition 
information</Q> that will describe the group already very well, but which 
is not yet proven to be correct. However, one can already write arbitrary
elements in the group as product of the given generators. In the 
verification phase a presentation of the group is calculated, thereby proving
that the group generated by the given generators is in fact isomorphic
to the group described by the recognition information. In many cases
the verification phase will be much more expensive than the recognition phase.
<P/>

In the following sections, we describe the generic framework. We begin
with a technical description of the recursive procedure and describe then
the way methods to find homomorphism have to be implemented. Finally,
we have four sections in which we collect conventions for the
recognition of different types of groups.<P/>

No actual recognition methods are implemented in this package. See the
<Package>recog</Package> package for an implementation and
description of them.

<Section Label="techrecog">
    <Heading>The recursive procedure</Heading>

As explained at the beginning of this section, the heart of the recognition
procedure is a function called <Ref Func="RecogniseGeneric"/> which gets
a &GAP; group object and returns a 
so-called <Q>recognition info record</Q> (see Subsection 
<Ref Subsect="rirecord"/> for details). Success or failure will be indicated
by this record being in the filter <Ref Filt="IsReady"/> or not.<P/>
To know how to find homomorphisms
the function gets as another argument a database of methods (see
Section <Ref Sect="findhomo"/> for a description of the setup for methods 
for finding homomorphisms and Section <Ref Sect="whataremethods"/> 
in Chapter <Ref Chap="methsel"/> for details about method databases).
This database will be different according to the type of group in 
question.<P/>

To describe the algorithm executed by <Ref Func="RecogniseGeneric"/>
we first summarise it in steps:

<Enum>
<Item>Create a new, empty recognition info record.</Item>
<Item>Use the database of <C>FindHomomorphism</C> methods and the method 
    selection procedure described in Chapter <Ref Chap="methsel"/> to
    try to find a homomorphism onto a smaller group or an isomorphism
    onto another known group. Terminate with failure if this does not
    work.</Item>
<Item>If an isomorphism is found or a method somehow else recognises
    the group in question, such that we can write elements as straight
    line programs in the generators from now on, then make the recognition
    info record a leaf of the recognition tree and return success.</Item>
<Item>Otherwise the function sets up all the data for the homomorphism and 
    calls itself with the image of the homomorphism. Note that this
    might use another database of recognition methods because the
    homomorphism might change the representation of the group.</Item>
<Item>After successful recognition of the factor group the procedure has
    to recognise the kernel of the homomorphism. The first step for this
    is to find generators. If they are not already known from the
    <C>FindHomomorphism</C> method, they are created by producing random
    elements in the group, mapping them through the homomorphism, writing them
    as a straight line program in the images of the generators and applying
    this straight line program to the original generators. The quotient of
    the random element and the result of the straight line program lies in
    the kernel of the homomorphism. After creating 20 random generators
    of the kernel we assume for the moment that they generate the kernel.
    </Item>
<Item>The function <Ref Func="RecogniseGeneric"/> can now call itself
    for the kernel. After successful recognition of the kernel all the
    data for the node is completed and success is returned.</Item>
<Item>The function <Ref Func="RecogniseGeneric"/> now acquires preimages
    of the nice generators behind the homomorphism and appends the nice
    generators of the kernel. This list of generators is now the list of
    nice generators for the current node.</Item>
</Enum>

Note that with the collected data one can write arbitrary elements of the
group as a straight line program in the generators as follows:

<Enum>
<Item>Map the element through the homomorphism.</Item>
<Item>Write the element in the factor group as a product of the nice 
    generators in the factor group.</Item>
<Item>Apply the resulting straight line program to the preimages of those
    nice generators and calculate the quotient, which will now lie in
    the kernel.</Item>
<Item>Write the kernel element as a straight line program in the kernel
    generators.</Item>
<Item>Assemble both straight line programs to one bigger straight line program
    (which is now in terms of our own nice generators) and return it.</Item>
</Enum>

If this procedure fails in the fourth step, this indicates that our random
generators for the kernel did not yet generate the full kernel and makes
further recognition steps necessary. This will not happen after a successful
verification phase.<P/>

The latter procedure to write elements as straight line programs in the
generators is implemented in the function <Ref Func="SLPforElementGeneric"/>
which will be called automatically if one calls the <Ref Func="SLPforElement"/>
function of the resulting recognition info record (see
<Ref Attr="slpforelement"/>).<P/>

It is now high time to give you the calling details of the main recursive
recognition function:

<ManSection>
<Func Name="RecogniseGeneric" Arg="H, methoddb, depth [,knowledge]"/>
<Func Name="RecognizeGeneric" Arg="H, methoddb, depth [,knowledge]"/>
<Returns><C>fail</C> for failure or a recognition info record.</Returns>
<Description>
    <A>H</A> must be a &GAP; group object, <A>methoddb</A> must be a 
    method database in the sense of Section <Ref Sect="whataremethods"/>
    containing <C>FindHomomorphism</C> methods in the sense of Section
    <Ref Sect="findhomo"/>. <A>depth</A> is an integer which measures
    the depth in the recognition tree. It will be increased by one for
    each step we go into the tree. The top level has depth 0.
    <A>knowledge</A> is an optional record the 
    components of which are copied into the new recognition info record
    which is created for the group <A>H</A>. Especially the component
    <C>hints</C> can contain a list of additional find homomorphism
    methods (described by records as in Section <Ref Sect="whataremethods"/>)
    which is prepended to the method database in <A>methoddb</A> before
    the recognition starts. This feature is intended to give hints
    about prior knowledge about which find homomorphism method might succeed.
    <P/>
    The function performs the algorithm described above and returns either
    <C>fail</C> in case of failure or a recognition info record in case
    of success. For the content and definition of recognition info 
    records see Section <Ref Sect="rirecord"/>.
</Description>
</ManSection>

The user will usually not call this function directly, but will use the
following convenience functions:

<ManSection>
<Func Name="RecognisePermGroup" Arg="H"/>
<Func Name="RecognizePermGroup" Arg="H"/>
<Returns><C>fail</C> for failure or a recognition info record.</Returns>
<Description>
<A>H</A> must be a &GAP; permutation group object. This function calls
<Ref Func="RecogniseGeneric"/> with the method database used for
permutation groups, which is stored in the global variable
<Ref Var="FindHomDbPerm"/>, and no prior knowledge.
</Description>
</ManSection>

<ManSection>
<Func Name="RecogniseMatrixGroup" Arg="H"/>
<Func Name="RecognizeMatrixGroup" Arg="H"/>
<Returns><C>fail</C> for failure or a recognition info record.</Returns>
<Description>
<A>H</A> must be a &GAP; matrix group object. This function calls
<Ref Func="RecogniseGeneric"/> with the method database used for
matrix groups, which is stored in the global variable
<Ref Var="FindHomDbMatrix"/>, and no prior knowledge.
</Description>
</ManSection>

<ManSection>
<Func Name="RecogniseProjectiveGroup" Arg="H"/>
<Func Name="RecognizeProjectiveGroup" Arg="H"/>
<Returns><C>fail</C> for failure or a recognition info record.</Returns>
<Description>
<A>H</A> must be a &GAP; matrix group object. Since as of now no
actual projective groups are implemented in the &GAP; library we use
matrix groups instead. The recognition will however view the group as
the projective group, i.e. the matrix group modulo its scalar
matrices. This function calls
<Ref Func="RecogniseGeneric"/> with the method database used for
projective groups, which is stored in the global variable
<Ref Var="FindHomDbProjective"/>, and no prior knowledge.
</Description>
</ManSection>

<ManSection>
<Func Name="RecogniseBBGroup" Arg="H"/>
<Func Name="RecognizeBBGroup" Arg="H"/>
<Returns><C>fail</C> for failure or a recognition info record.</Returns>
<Description>
<A>H</A> must be a &GAP; black box group object. This function calls
<Ref Func="RecogniseGeneric"/> with the method database used for
black box groups, which is stored in the global variable
<Ref Var="FindHomDbBB"/>, and no prior knowledge.
</Description>
</ManSection>

<ManSection>
<Func Name="RecogniseGroup" Arg="H"/>
<Func Name="RecognizeGroup" Arg="H"/>
<Returns><C>fail</C> for failure or a recognition info record.</Returns>
<Description>
    <A>H</A> must be a &GAP; group object. This function automatically 
    dispatches to one of the three previous functions 
    <Ref Func="RecognisePermGroup"/>, <Ref Func="RecogniseMatrixGroup"/>, or
    <Ref Func="RecogniseBBGroup"/>, according to the type of the group <A>H</A>.
    Note that since currently there is no implementation of projective
    groups in the &GAP; library, one cannot recognise a matrix group
    <A>H</A> as a projective group using this function.
</Description>
</ManSection>

<ManSection>
<Var Name="FindHomDbPerm"/>
<Description>
    This list contains the methods for finding homomorphisms
    for permutation group recognition that are stored in the record
    <Ref Var="FindHomMethodsPerm"/>. As described in Section <Ref
    Sect="whataremethods"/> each method is described by a record. The list
    is always sorted with respect to decreasing ranks. The order in this
    list tells in which order the methods should be applied. Use <Ref
    Func="AddMethod"/> to add methods to this database.
</Description>
</ManSection>

<ManSection>
<Var Name="FindHomMethodsPerm"/>
<Description>
    In this global record the functions that are methods for finding 
    homomorphisms for permutation group recognition are stored. We
    collect them all in this record such that we do not use up too many
    global variable names.
</Description> 
</ManSection>

<ManSection>
<Var Name="SLPforElementFuncsPerm"/>
<Description>
    This global record holds the functions that are methods for writing group
    elements as straight line programs (SLPs) in terms of the generators
    after successful permutation group recognition. We collect them all in this
    record such that we do not use up too many global variable names.
</Description>
</ManSection>

<ManSection>
<Var Name="FindHomDbMatrix"/>
<Description>
    This list contains the methods for finding homomorphisms
    for matrix group recognition that are stored in the record
    <Ref Var="FindHomMethodsMatrix"/>. As described in Section <Ref
    Sect="whataremethods"/> each method is described by a record. The list
    is always sorted with respect to decreasing ranks. The order in this
    list tells in which order the methods should be applied. Use <Ref
    Func="AddMethod"/> to add methods to this database.
</Description>
</ManSection>

<ManSection>
<Var Name="FindHomMethodsMatrix"/>
<Description>
    In this global record the functions that are methods for finding 
    homomorphisms for matrix group recognition are stored. We collect
    them all in this record such that we do not use up too many global
    variable names.
</Description> 
</ManSection>

<ManSection>
<Var Name="SLPforElementFuncsMatrix"/>
<Description>
    This global record holds the functions that are methods for writing group
    elements as straight line programs (SLPs) in terms of the generators
    after successful matrix group recognition. We collect them all in this
    record such that we do not use up too many global variable names.
</Description>
</ManSection>

<ManSection>
<Var Name="FindHomDbProjective"/>
<Description>
    This list contains the methods for finding homomorphisms
    for projective group recognition that are stored in the record
    <Ref Var="FindHomMethodsProjective"/>. As described in Section <Ref
    Sect="whataremethods"/> each method is described by a record. The list
    is always sorted with respect to decreasing ranks. The order in this
    list tells in which order the methods should be applied. Use <Ref
    Func="AddMethod"/> to add methods to this database.
</Description>
</ManSection>

<ManSection>
<Var Name="FindHomMethodsProjective"/>
<Description>
    In this global record the functions that are methods for finding 
    homomorphisms for projective group recognition are stored. We collect
    them all in this record such that we do not use up too many global
    variable names.
</Description> 
</ManSection>

<ManSection>
<Var Name="SLPforElementFuncsProjective"/>
<Description>
    This global record holds the functions that are methods for writing group
    elements as straight line programs (SLPs) in terms of the generators
    after successful projective group recognition. We collect them all in this
    record such that we do not use up too many global variable names.
</Description>
</ManSection>

<ManSection>
<Var Name="FindHomDbBB"/>
<Description>
    This list contains the methods for finding homomorphisms
    for black box group recognition that are stored in the record
    <Ref Var="FindHomMethodsBB"/>. As described in Section <Ref
    Sect="whataremethods"/> each method is described by a record. The list
    is always sorted with respect to decreasing ranks. The order in this
    list tells in which order the methods should be applied. Use <Ref
    Func="AddMethod"/> to add methods to this database.
</Description>
</ManSection>

<ManSection>
<Var Name="FindHomMethodsBB"/>
<Description>
    In this global record the functions that are methods for finding 
    homomorphisms for black box group recognition are stored. We collect
    them all in this record such that we do not use up too many global
    variable names.
</Description> 
</ManSection>

<ManSection>
<Var Name="SLPforElementFuncsBB"/>
<Description>
    This global record holds the functions that are methods for writing group
    elements as straight line programs (SLPs) in terms of the generators
    after successful black box group recognition. We collect them all in this
    record such that we do not use up too many global variable names.
</Description>
</ManSection>

<ManSection>
<Func Name="TryFindHomMethod" Arg="H, method, projective"/>
<Returns><C>fail</C> or <C>false</C> or a recognition info record.</Returns>
<Description>
Use this function to try to run a given find homomorphism method
<A>method</A> on a group <A>H</A>. Indicate by the boolean <A>projective</A>
whether or not the method works in projective mode. For permutation and
black box groups give <C>false</C>. The result is either <C>fail</C> or 
<C>false</C> if the method fails or a recognition info record <C>ri</C>.
If the method created a leaf then <C>ri</C> will be a leaf, otherwise
it will have the attribute <Ref Attr="Homom"/> set, but no factor or 
kernel have been created or recognised yet. You can use for example
the methods in <Ref Var="FindHomMethodsPerm"/> or 
<Ref Var="FindHomMethodsMatrix"/> or <Ref Var="FindHomMethodsProjective"/>
or <Ref Var="FindHomMethodsBB"/> as the <A>method</A> argument.
</Description>
</ManSection>

</Section>

<Section Label="rirecord">
    <Heading>Recognition info records</Heading>

A recognition info record is a &GAP; positional object. It is a member 
of the family 

<ManSection>
<Fam Name="RecognitionInfoFamily"/>
</ManSection>

and is in the category 

<ManSection>
    <Filt Name="IsRecognitionInfo" Type="Category"/>
</ManSection>

and is <Ref Filt="IsAttributeStoringRep" BookName="Ref"/>, such that we can
define attributes for it, the values of which are stored once they are 
known. A recognition info record always represents a whole binary tree of such
records, see the attributes <Ref Attr="RIFac"/> and <Ref Attr="RIKer"/>
below. <P/>

The following filters are defined for recognition info records:

<ManSection>
<Filt Name="IsLeaf" Type="Flag"/>
<Description>
This flag indicates, whether or not a recognition info record represents a leaf
in the recognition tree. If it is not set, one finds at least one of
the attributes <Ref Attr="RIFac"/> and <Ref Attr="RIKer"/> set for
the corresponding node. This flag is normally reset and has to be set
by a find homomorphism method to indicate a leaf.
</Description>
</ManSection>

<ManSection>
<Filt Name="IsReady" Type="Flag"/>
<Description>
This flag indicates during the recognition procedure, whether a node in 
the recognition tree is already completed or not. It is mainly set for
debugging purposes during the recognition. However, if the recognition
fails somewhere in a leaf, this flag is not set and all nodes above will
also not have this flag set. In this way one can see whether the recognition
failed and where the problem was. If a find homomorphism method
uses <C>donotrecurse</C> (see <Ref Subsect="componentsri"/>)
to avoid further recursion it acquires
thereby responsibility to set the <Ref Filt="IsReady"/> flag in the
corresponding subtree upon completion.
</Description>
</ManSection>

The following attributes are defined for recognition info records:

<ManSection>
<Attr Name="Grp" Arg="ri"/>
<Description>
The value of this attribute is the group that is to be recognised by this
recognition info record <A>ri</A>. This attribute is always present during
recognition and after completion. Note that the generators of the group
object stored here always have a memory attached to them, such that
elements that are generated from them remember, how they were acquired.
</Description>
</ManSection>

<ManSection>
<Attr Name="Homom" Arg="ri"/>
<Description>
    The value of this attribute is the homomorphism that was found from the
    group described by the recognition info record <A>ri</A> as a &GAP;
    object. It is set by a find homomorphism method that succeeded to
    find a homomorphism (or isomorphism). It does not have to be set
    in leaf nodes of the recognition tree.
</Description>
</ManSection>

<ManSection>
<Attr Name="NiceGens" Arg="ri"/>
<Description>
    The value of this attribute must be set for all nodes and contains
    the nice generators. The <Ref Func="SLPforElement"/> function of the
    node will write its straight line program in terms of these nice
    generators. For leaf nodes, the find homomorphism method is responsible
    to set the value of <Ref Attr="NiceGens"/>. By default, the original
    generators of the group at this node are taken. For a homomorphism
    (or isomorphism), the <Ref Attr="NiceGens"/> will be the concatenation
    of preimages of the <Ref Attr="NiceGens"/> of the factor group 
    (see <Ref Attr="pregensfac"/>) and
    the <Ref Attr="NiceGens"/> of the kernel. A find homomorphism method
    does not have to set <Ref Attr="NiceGens"/> if it finds a homomorphism.
    Note however, that such a find homomorphism method has to ensure somehow,
    that preimages of the <Ref Attr="NiceGens"/> of the factor group
    can be acquired. See <Ref Attr="calcnicegens"/>, <Ref Func="CalcNiceGens"/>
    and <Ref Attr="slptonice"/>
    for instructions.
</Description>
</ManSection>

<ManSection>
<Attr Name="pregensfac" Arg="ri"/>
<Description>
    The value of this attribute is only set for homomorphism nodes. In that
    case it contains preimages of the nice generators in the factor group.
    This attribute is set automatically by the generic recursive recognition
    function using the mechanism described with the attribute
    <Ref Attr="calcnicegens"/> below. A find homomorphism does not have
    to touch this attribute.
</Description>
</ManSection>

<ManSection>
<Attr Name="RIFac" Arg="ri"/>
<Description>
    The value of this attribute is the recognition info record of the
    image of the homomorphism that was found from the group described by
    the recognition info record <A>ri</A>. It is set by the generic
    recursive procedure after a find homomorphism method has succeeded
    to find a homomorphism (or isomorphism). It does not have to be set
    in leaf nodes of the recognition tree. This attribute value provides
    the link to the <Q>factor</Q> subtree of the recognition tree.
</Description>
</ManSection>

<ManSection>
<Attr Name="RIKer" Arg="ri"/>
<Description>
    The value of this attribute is the recognition info record of the
    kernel of the homomorphism that was found from the group described by
    the recognition info record <A>ri</A>. It is set by the generic
    recursive procedure after a find homomorphism method has succeeded
    to find a homomorphism (or isomorphism). It does not have to be set
    in leaf nodes of the recognition tree or if the homomorphism is known to
    be an isomorphism. In the latter case the value of the attribute is
    set to <C>fail</C>. This attribute value provides the link to the
    <Q>kernel</Q> subtree of the recognition tree.
</Description>
</ManSection>

<ManSection>
<Attr Name="RIParent" Arg="ri"/>
<Description>
    The value of this attribute is the recognition info record of the
    parent of this node in the recognition tree. The top node does not
    have this attribute set.
</Description>
</ManSection>

<ManSection>
<Attr Name="fhmethsel" Arg="ri"/>
<Description>
    The value of this attribute is the record returned by the method
    selection (see Section <Ref Sect="howcalled"/>) after it ran to
    find a homomorphism (or isomorphism). It is there to be able to see
    which methods were tried until the recognition of the node was
    completed.
</Description>
</ManSection>

<ManSection>
<Attr Name="slpforelement" Arg="ri"/>
<Description>
    After the recognition phase is completed for the node <A>ri</A>, we
    are by definition able to write arbitrary elements in the group described
    by this node as a straight line program (SLP) in terms of the nice 
    generators stored in <Ref Attr="NiceGens"/>.
    This attribute value is a function taking the node <A>ri</A> and a
    group element as its arguments and returning the above mentioned
    straight line program. For the case that a find homomorphism method
    succeeds in finding a homomorphism, the generic recursive function
    sets this attribute to the function <Ref Func="SLPforElementGeneric"/>
    which does the job for the generic homomorphism situation. In all other
    cases the successful find homomorphism method has to set this attribute
    to a function doing the job. The find homomorphism method is free to
    store additional data in the recognition info record or the group
    object such that the <Ref Func="SLPforElement"/> function can work.
</Description>
</ManSection>

<ManSection>
<Func Name="SLPforElement" Arg="ri, x"/>
<Returns>a straight line program expressing <A>x</A> in the nice generators.
</Returns>
<Description>
    This is a wrapper function which extracts the value of the attribute
    <Ref Attr="slpforelement"/> and calls that function with the arguments
    <A>ri</A> and <A>x</A>.
</Description>
</ManSection>

<ManSection>
<Attr Name="StdPresentation" Arg="ri"/>
<Description>
    After the verification phase, the presentation is stored here. Details
    have still to be decided upon.
</Description>
</ManSection>

<ManSection>
<Attr Name="methodsforfactor" Arg="ri"/>
<Description>
    This attribute is initialised at the beginning of the recursive
    recognition function with the database of find homomorphism methods
    that was used to recognise the group corresponding to the
    recognition info record <A>ri</A>. If the found homomorphism
    changes the representation of the group (going for example from
    a matrix group to a permutation group), the find homomorphism method
    can report this by exchanging the database of find homomorphism methods
    to be used in the recognition of the image of the homomorphism by
    setting the value of this attribute to something different. It lies
    in the responsibility of the find homomorphism method to do so,
    if the representation changes through the homomorphism.
</Description>
</ManSection>

The following two attributes are concerned with the relation between 
the original generators and the nice generators for a node.
They are used to transport this information from a successful find
homomorphism method up to the recursive recognition function:

<ManSection>
<Attr Name="calcnicegens" Arg="ri"/>
<Description>
    To make the recursion work, we have to acquire preimages of the
    nice generators in factor groups under the homomorphism found.
    But we want to keep the information, how the nice generators
    were found, locally at the node where they were found. This
    attribute solves this problem of acquiring preimages in the following
    way: Its value must be a function, taking the recognition info
    record <A>ri</A> as first argument, and a list <A>origgens</A> of 
    preimages of the
    original generators of the current node, and has to
    return corresponding preimages of the nice generators. Usually this
    task can be done by storing a straight line program writing the
    nice generators in terms of the original generators and executing 
    this with inputs <A>origgens</A>. Therefore the default value of
    this attribute is the function <Ref Func="CalcNiceGensGeneric"/>
    described below.
</Description>
</ManSection>

<ManSection>
<Func Name="CalcNiceGensGeneric" Arg="ri, origgens"/>
<Returns>a list of preimages of the nice generators</Returns>
<Description>
    This is the default function for leaf nodes for the attribute <Ref
    Attr="calcnicegens"/> described above. It does the following: If the
    value of the attribute <Ref Attr="slptonice"/> is set, then it must
    be a straight line program expressing the nice generators in terms
    of the original generators of this node. In that case, this straight
    line program is executed with <A>origgens</A> as inputs and the
    result is returned. Otherwise, <A>origgens</A> is returned as is.
    Therefore a leaf node just has to do nothing if the nice generators
    are equal to the original generators, or can simply store the right
    straight line program into the attribute <Ref Attr="slptonice"/> to
    fulfill its duties.
</Description>
</ManSection>

<ManSection>
<Func Name="CalcNiceGensHomNode" Arg="ri, origgens"/>
<Returns>a list of preimages of the nice generators</Returns>
<Description>
    This is the default function for homomorphism node for the attribute 
    <Ref Attr="calcnicegens"/>. It just delegates to factor and kernel of
    the homomorphism, as the nice generators of a homomorphism (or isomorphism)
    node are just the concatenation of the nice generators of the factor
    and the kernel. A find homomorphism method finding a homomorphism
    or isomorphism does not have to do anything with respect to nice
    generators.
</Description>
</ManSection>

<ManSection>
<Func Name="CalcNiceGens" Arg="ri, origgens"/>
<Returns>a list of preimages of the nice generators</Returns>
<Description>
    This is a wrapper function which extracts the value of the attribute
    <Ref Attr="calcnicegens"/> and calls that function with the arguments
    <A>ri</A> and <A>origgens</A>.
</Description>
</ManSection>

<ManSection>
<Attr Name="slptonice" Arg="ri"/>
<Description>
    As described above, the value, if set, must be a straight line program
    expressing the nice generators at this node in terms of the original
    generators. This is for leaf nodes, that choose to use the default
    function <Ref Func="CalcNiceGensGeneric"/> installed in the 
    <Ref Attr="calcnicegens"/> attribute.
</Description>
</ManSection>

The following three attributes are concerned with the administration of the
kernel of a found homomorphism. Find homomorphism methods use them to
report to the main recursive recognition function their knowledge
about the kernel:

<ManSection>
<Attr Name="gensN" Arg="ri"/>
<Description>
    The value of this mutable attribute is a list of generators of the kernel
    of the homomorphism found at the node <A>ri</A>. It is initialised
    as an empty list when the recursive recognition function starts.
    Successful find homomorphism methods may append generators of the
    kernel to this list if they happen to stumble on them. After successful
    recognition of the image of the homomorphism the main recursive
    recognition function will try to create a few more generators
    of the kernel and append them to the list which is the value of 
    the attribute <Ref Attr="gensN"/>. The exact behaviour depends on
    the value of the attribute <Ref Attr="findgensNmeth"/> below.
    The list of generators after that step is used to recognise the
    kernel. Note that the generators in <Ref Attr="gensN"/> have a
    memory attached to them, how they were obtained in terms of the
    original generators of the current node.
</Description>
</ManSection>

<ManSection>
<Attr Name="findgensNmeth" Arg="ri"/>
<Description>
    This attribute decides about how generators of the kernel of a found
    homomorphism are produced. Its value has to be a record with at least
    two components bound. The first is <C>method</C> which holds a function
    taking at least one argument <A>ri</A> and possibly more, and does
    not return anything. The second is <C>args</C> which holds a list
    of arguments for the above mentioned function. The real list of
    arguments is derived by prepending the recognition info record
    to the list of arguments in <C>args</C>. That is, the following
    code is used to call the method:
<Listing>
    methgensN := findmethgensN(ri);
    CallFuncList(methgensN(ri).method,Concatenation([ri],methgensN.args));
</Listing>
The record is initialised upon creation of the recognition info record
to calling <Ref Func="FindKernelRandom"/> with one argument of 20 (in addition
to the first argument <A>ri</A>). See below for a choice of possible
find kernel methods.
</Description>
</ManSection>

<ManSection>
<Func Name="FindKernelRandom" Arg="ri, n"/>
<Returns>nothing</Returns>
<Description>
    <A>n</A> random elements are generated, mapped through the homomorphism,
    written as a straight line program in the generators. Then the straight
    line program is executed with the original generators thereby producing
    elements in the same coset. The quotients are then elements of the
    kernel. The kernel elements created are stored in the attribute
    <Ref Attr="gensN"/>.
</Description>
</ManSection>

<ManSection>
<Func Name="FindKernelDoNothing" Arg="ri, n"/>
<Returns>nothing</Returns>
<Description>
    Does nothing. This function is intended to be set as method for producing
    kernel elements if the kernel is known to be trivial or if one knows,
    that the attribute <Ref Attr="gensN"/> already contains a complete
    set of generators for the kernel.
</Description>
</ManSection>

<ManSection>
<Func Name="FindKernelFastNormalClosure" Arg="ri, nr"/>
<Returns>a probable generating set for the normal closure</Returns>
<Description>
    This function takes the group <M>G</M> in the <Ref Attr="Grp"/> attribute
    in <A>ri</A> and the list of generators <M>gens</M> of the kernel in
    <Ref Attr="gensN"/> and the positive integer <A>nr</A>.
    This function computes a probable generating
    set of the normal closure in <A>G</A> of the group generated by the
    generators in <A>gens</A>. The integer <A>nr</A> indicates how hard
    it should try.
</Description>
</ManSection>

<ManSection>
<Attr Name="gensNslp" Arg="ri"/>
<Description>
    The recursive recognition function calculates a straight line program
    that computes the generators of the kernel stored in <Ref Attr="gensN"/>
    in terms of the generators of the group recognised by <A>ri</A>.
    This straight line program is stored in the value of this mutable
    attribute. It is used by the generic function 
    <Ref Func="SLPforElementGeneric"/>.
</Description>
</ManSection>

<ManSection>
<Attr Name="immediateverification" Arg="ri"/>
<Description>
    Sometimes a find homomorphism has information that it will be difficult
    to create generators for the kernel, for example if it is known that
    the kernel will need lots of generators. In that case this attribute
    with the default boolean value <C>false</C> can be set to <C>true</C>.
    In that case, the generic recursive recognition function will perform
    an immediate verification phase after the kernel has been recognised.
    This is done as follows: A few random elements are created, mapped
    through the homomorphism and written as an SLP in the nice generators
    there. Then this SLP is executed with preimages of those nice generators.
    The quotient lies then in the kernel and is written as an SLP in terms
    of the nice generators of the would be kernel. If this is not possible,
    then probably the creation of kernel generators was not complete and 
    a few more kernel elements are produced and recognition in the kernel
    starts all over again. This is for example done in case of the
    <Q>Imprimitive</Q> method which maps onto the action on a block system.
    In that case, the kernel often needs lots of generators.
</Description>
</ManSection>

The following attributes are used to give a successful find homomorphism
method further possibilities to transport knowledge about the group
recognised by the current recognition info record to the factor or
kernel of the found homomorphism:

<ManSection>
<Attr Name="forkernel" Arg="ri"/>
<Description>
    This attribute is initialised to a record with only the component
    <C>hints</C> bound to an empty list at the beginning of the 
    recursive recognition function. Find homomorphism methods can
    put acquired knowledge about the group to be recognised (like for
    example an invariant subspace of a matrix group) into this record.
    When a homomorphism is found and recognition goes on in its 
    kernel, the value of this attribute is taken as initialisation data
    for the newly created recognition info record for the kernel. Thus,
    information is transported down to the recognition process for the
    kernel. The component <C>hints</C> is special insofar as it has to
    contain records describing find homomorphism methods which might be
    particularly successful. They are prepended to the find homomorphism
    method database such that they are called before any other methods.
    This is a means to give hints to the recognition procedure in the 
    kernel, because often during the finding of a homomorphism knowledge
    is acquired which might help the recognition of the kernel.
</Description>
</ManSection>

<ManSection>
<Attr Name="forfactor" Arg="ri"/>
<Description>
    This attribute is initialised to a record with only the component
    <C>hints</C> bound to an empty list at the beginning of the 
    recursive recognition function. Find homomorphism methods can
    put acquired knowledge about the group to be recognised (like for
    example an invariant subspace of a matrix group) into this record.
    When a homomorphism is found and recognition goes on in its 
    image, the value of this attribute is taken as initialisation data
    for the newly created recognition info record for the factor. Thus,
    information is transported down to the recognition process for the
    factor. The component <C>hints</C> is special insofar as it has to
    contain records describing find homomorphism methods which might be
    particularly successful. They are prepended to the find homomorphism
    method database such that they are called before any other methods.
    This is a means to give hints to the recognition procedure in the 
    factor, because often during the finding of a homomorphism knowledge
    is acquired which might help the recognition of the factor.
</Description>
</ManSection>

<ManSection>
<Attr Name="isone" Arg="ri"/>
<Description>
This attribute returns a function that tests, whether or not an
element of the group is equal to the identity or not. Usually this is
just the operation <Ref Oper="IsOne" BookName="Ref"/> but for projective
groups it is a special function returning <C>true</C> for scalar matrices. In
generic code, one should always use the result of this attribute to
compare an element to the identity such that the code works also for
projective groups. Find homomorphism methods usually do not have to
set this attribute.
</Description>
</ManSection>

<ManSection>
<Attr Name="isequal" Arg="ri"/>
<Description>
This attribute returns a function that compares two elements of the
group being recognised.  Usually this is
just the operation <Ref Oper="EQ" BookName="Ref"/> but for projective
groups it is a special function checking for equality up to a scalar
factor. In
generic code, one should always use the result of this attribute to
compare two elements such that the code works also for
projective groups. Find homomorphism methods usually do not have to
set this attribute.
</Description>
</ManSection>

<Subsection Label="componentsri">
<Heading>Other components of recognition info records</Heading>

    In this subsection we describe a few more components of
    recognition info records that can be queried or set by find
    homomorphism methods. Not all of these components are bound in all
    cases. See the individual descriptions about the conventions.
    Remember to use the <C>!.</C> notation to access these components
    of a recognition info record.

<List>
    <Mark><C>donotrecurse</C></Mark>
<Item>
    This component can be set to <C>true</C> 
    by a find homomorphism method to indicate that the
    generic recursive procedure should not recurse further down, even if
    the corresponding node is not a leaf. It is then the responsibility of 
    the find homomorphism method to complete the tree below.
</Item>

<Mark><C>leavegensNuntouched</C></Mark>
<Item>If this component is bound to <C>true</C> by a find homomorphism
    method or a find kernel generators method, the generic mechanism
    to remove duplicates and identities in the generator for the
    kernel is not used. This is important if your methods rely on the
    generating set of the kernel being exactly as it was when found.
</Item>

<!-- the following are currently not officially documented:

<Mark><C>genswithmem</C></Mark>
<Item>Contains the generators with memory.</Item>

<Mark><C>groupmem</C></Mark>
<Item>Contains the group with memory.</Item>

-->

</List>

</Subsection>

</Section>

<Section Label="findhomo">
    <Heading>Methods to find homomorphisms</Heading>

A <Q>find homomorphism method</Q> has the objective to, given a
group <M>G</M>, either find a homomorphism from <M>G</M> onto a group, or 
to find an isomorphism, or to solve the constructive membership
problem directly for <M>G</M>, or to fail. <P/>
In case a homomorphism is found, it has to report that homomorphism
back to the calling recursive recognition function together with as
much information about the kernel as possible.<P/>

If a find homomorphism method determines that the node is a leaf in the
recognition tree (by solving the constructive membership problem
directly), then it has to ensure, that
arbitrary elements can be written in terms of the nice generators of <M>G</M>.
It does so by returning a function together
with possible extra data, that can perform this job.<P/>
Of course, the find homomorphism method also has to report, how
the nice generators were acquired in terms of the original generators.<P/>
If the find homomorphism method fails, it has to report, whether it has failed
forever or if it possibly makes sense to try to call this method again later.
<P/>
Find homomorphism methods have to fit into the framework for method selection
described in Chapter <Ref Chap="methsel"/>. We now begin to describe the
technical details of how a find homomorphism method has to look like
and what it has to do and what it is not allowed to do. We first explain
the calling convention by means of a hypothetical function:

<ManSection>
    <Func Name="FindHomomorphism" Arg="ri, G"/>
    <Returns>One of the values <C>true</C>, <C>false</C>, <C>fail</C>, or
        <C>NotApplicable</C>.</Returns>
    <Description>
        Find homomorphism methods take two arguments <A>ri</A> and <A>G</A>,
        of which <A>ri</A> is a recognition info record and <A>G</A> is
        a &GAP; group object. The return value is one of the four possible
        values in the framework for method selection described in Chapter
        <Ref Chap="methsel"/> indicating success, failure, or (temporary)
        non-applicability. The above mentioned additional information
        in case of success are all returned by changing the recognition
        info record <A>ri</A>. For the conventions about what a find
        homomorphism method has to do and return see below.
    </Description>
</ManSection>

A failed or not applicable find homomorphism method does not have to report
or do anything in the recognition info record <A>ri</A>. However, it can
collect information and store it either in the group object or in the
recognition info record. Note that for example it might be that
a failed find homomorphism method acquires additional information that
allows another find homomorphism method to become applicable. <P/>

A not applicable find homomorphism method should find out so relatively
quickly, because otherwise the whole process might be slowed down, because
a find homomorphism method repeatedly ponders about its applicability. Usually
no big calculations should be triggered just to decide applicability.<P/>

A successful find homomorphism method has the following duties:

<List>
<Mark>for leaves:</Mark>
<Item>First it has to report whether the current node is a leaf or not
    in the recognition tree. That is,
    in case a leaf was found the method has to do
    <C>SetFilterObj(ri,IsLeaf);</C> thereby setting the <Ref Filt="IsLeaf"/>
    flag. <P/>
    If the method for some reason chooses to finish the tree
    below the current node on its own, it can set the component
    <C>donotrecurse</C> to <C>true</C> (see <Ref
    Subsect="componentsri"/>) to indicate that no further action is required
    by the generic recognition function. The method is then responsible 
    for correctly setting the <Ref Filt="IsLeaf"/> and <Ref Filt="IsReady"/>
    flags in the whole subtree. <P/>
    A method finding a homomorphism which is not an isomorphism indicates
    so by not touching the flags.
</Item>
<Mark>for leaves: <Ref Func="SLPforElement"/> function</Mark>
<Item>
    If a find homomorphism method has
    produced a leaf in the recognition tree or has set the
    <C>donotrecurse</C> component to <C>true</C> (see
    <Ref Subsect="componentsri"/>), then it has to set the attribute
    <Ref Attr="slpforelement"/> to a function like 
    <Ref Func="SLPforElementGeneric"/> that can write an arbitrary element
    in <A>G</A> as a straight line program in the nice generators of <A>G</A>.
    The method may store additional data into the recognition info record
    for this to work. It does not have to set any other value in <A>ri</A>.
</Item>
<Mark>for leaves: information about nice generators</Mark>
<Item>
    If a find homomorphism method has produced a leaf in the recognition
    tree, then it has to report what are the nice generators of the group
    described by the leaf. To this end, it has three possibilities: Firstly
    to do nothing, which means, that the original generators are the nice
    generators. Secondly to store a straight line program expressing the
    nice generators in terms of the original generators into the attribute
    <Ref Attr="slptonice"/>. In that case, the generic frame work takes
    care of the rest. The third possibility is to store a function 
    into the value of the attribute <Ref Attr="calcnicegens"/> which
    can calculate preimages of the nice generators in terms of preimages
    of the original generators. See the function 
    <Ref Func="CalcNiceGensGeneric"/> for an example of such a function.
</Item>
<Mark>for non-leaves: the homomorphism itself</Mark>
<Item>
    If a find homomorphism method has found a homomorphism, it has to
    store it as a &GAP; homomorphism object from <A>G</A> to the image
    group in the attribute <Ref Attr="Homom"/>. Note that if your homomorphism
    changes the representation (for example going from matrix groups to 
    permutation groups), you will have to set the attribute
    <Ref Attr="methodsforfactor"/> accordingly.
</Item>
<Mark>for non-leaves: kernel generators</Mark>
<Item>
    If a find homomorphism method has found a homomorphism, it has to 
    provide information about already known generators of the kernel.
    This is done firstly by appending known generators of the kernel
    to the attribute value of <Ref Attr="gensN"/> and secondly by 
    leaving or changing the attribute <Ref Attr="findgensNmeth"/> to 
    a record describing the method that should be used (for details
    see <Ref Attr="findgensNmeth"/>).
    If one does not change the default value,
    the recursive recognition function will generate
    20 random elements in <A>G</A> and produce random generators of the
    kernel by dividing by a preimage of an image under the homomorphism.
    Note that generators in <Ref Attr="gensN"/> have to have a
    memory attached to them that stores, how they were acquired from the
    generators of <A>G</A>.
</Item>
<Mark>additional information</Mark>
<Item>
    A find homomorphism method may store any data into the attributes
    <Ref Attr="forkernel"/> and <Ref Attr="forfactor"/>, which both are 
    records. Components in these
    record that are bound during the recognition will be copied into
    the recognition info record of the kernel and factor respectively 
    of a found homomorphism
    upon creation and thus are available to all find homomorphism
    methods called for the kernel and factor. This feature might be
    interesting to transport information that is relevant for the
    recognition of the kernel or factor and was acquired during the recognition
    of <A>G</A> itself.<P/> A special role is played by the component
    <C>hints</C> in both of the above records, 
    which can hold a list of records describing find
    homomorphism methods that shall be tried first when recognising the
    kernel or factor. <P/>
    In addition, a find homomorphism method might set the attribute
    <Ref Attr="immediateverification"/> to true, if it considers the problem
    of finding kernel generators particularly difficult.
</Item>
</List>

To explain the calling conventions for <Ref Func="SLPforElement"/>
functions and for the sake of completeness we present now the
function <Ref Func="SLPforElementGeneric"/> which is used for the
case of a <Q>homomorphism node</Q>:

<ManSection>
<Func Name="SLPforElementGeneric" Arg="ri, x"/>
<Returns>a &GAP; straight line program</Returns>
<Description>
This function takes as arguments a recognition info record <A>ri</A> 
and a group element <A>x</A>. It returns a &GAP; straight line program
that expresses the element <A>x</A> in terms of the nice generators of the
group <M>G</M> recognised by <A>ri</A>.<P/>
This generic function here does exactly this job for the generic
situation that we found a homomorphism from <M>G</M> to some other
group say <M>H</M> with kernel <M>N</M>. It first maps <A>x</A> via
the homomorphism to <M>H</M> and uses the recognition information there
to write it as a straight line program in terms of the nice generators of
<M>H</M>. Then it applies this straight line program to the preimages 
of those nice generators (see <Ref Attr="pregensfac"/>)
thereby finding an element <M>y</M> of <M>G</M> with <M>x \cdot y^{-1}</M>
lying in the kernel <M>N</M>. <P/>
Then the function writes this element
as a straight line program in the nice generators of <M>N</M> again using the
recursively acquired recognition info about <M>N</M>. In the end a
concatenated straight line program for <M>x</M> is built, which is in terms
of the nice generators of the current node.
</Description>
</ManSection>

</Section>

<Section Label="convperm">
    <Heading>Conventions for the recognition of permutation groups</Heading>

No conventions so far.
</Section>

<Section Label="convmat">
    <Heading>Conventions for the recognition of matrix groups</Heading>

We are considering only the case of matrix groups over finite fields.<P/>

No conventions so far.
</Section>

<Section Label="convproj">
    <Heading>Conventions for the recognition of projective groups</Heading>

We are considering only the case of projective groups over finite fields.<P/>

No conventions so far.
</Section>

<Section Label="convbb">
    <Heading>Conventions for the recognition of black box groups</Heading>

No conventions so far.
</Section>



<!-- ############################################################ -->

</Chapter>
