<!--

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 three situations in mind:
permutation groups, matrix groups and projective groups.
Although the methods used are quite different for those 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
in Section <Ref Sect="techrecog"/>
with a technical description of the recursive procedure
behind our main function <Ref Func="RecogniseGroup"/>.
In Section <Ref Sect="rirecord"/>
we describe the return type of <Ref Func="RecogniseGroup"/>
which we call <Q>recognition nodes</Q>.
The methods to find homomorphisms are described
in Section <Ref Sect="findhomo"/>.
Finally,
we have three sections in which we collect conventions for the
recognition of different types of groups.<P/>

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

At 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 node</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 node.</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
    node 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 image 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 (FIXME: is 20 correct?) 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 image group as a product of the nice
    generators in the image 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 node (see
<Ref Attr="slpforelement"/>).<P/>

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

<#Include Label="RecogniseGeneric">

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

<#Include Label="RecognisePermGroup">
<#Include Label="RecogniseMatrixGroup">
<#Include Label="RecogniseProjectiveGroup">
<#Include Label="RecogniseGroup">

<ManSection>
<Func Name="TryFindHomMethod" Arg="H, method, projective"/>
<Returns><K>fail</K> or <K>false</K> or a recognition node.</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 groups,
set this to <K>false</K>. The result is either <K>fail</K> or
<K>false</K> if the method fails or a recognition node <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 image 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"/>
as the <A>method</A> argument.

<P/>GAP homomorphisms are not required to give a sensible answer when
given a value not in their source, and in practice often enter the break
loop, or return an incorrect answer. This causes problems when checking
if a value is not in the represented group. To avoid this problem,
<Ref Attr="validatehomominput"/> can be set to a function.
This function is used to filter possible group elements,
before they are
passed to <Ref Attr="Homom"/>.
</Description>
</ManSection>

</Section>

<Section Label="rirecord">
    <Heading>Recognition nodes</Heading>

A recognition node is a &GAP; component object. It is a member
of the family

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

and is in the category

<ManSection>
    <Filt Name="IsRecogNode" 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 node always represents a whole binary tree of such
records, see the attributes <Ref Attr="ImageRecogNode"/> and <Ref Attr="KernelRecogNode"/>
below. <P/>

Recognition nodes can be created via:

<#Include Label="RecogNode">

The following filters are defined for recognition nodes:

<#Include Label="IsLeaf">
<#Include Label="IsReady">

The following attributes are defined for recognition nodes:

<#Include Label="Grp">
<#Include Label="Homom">
<#Include Label="NiceGens">
<#Include Label="pregensfac">
<#Include Label="ImageRecogNode">
<#Include Label="KernelRecogNode">
<#Include Label="ParentRecogNode">
<#Include Label="fhmethsel">
<#Include Label="slpforelement">
<#Include Label="SLPforElement">
<#Include Label="StdPresentation">
<#Include Label="methodsforimage">

<ManSection>
<Attr Name="validatehomominput" Arg="ri, x"/>
<Description>

The value of this attribute, if there is any, must be a function with
two arguments: a recognition record <A>ri</A>, and an element <A>x</A>.
The function must return a boolean. If it returns <K>false</K>, then
this means that <A>x</A> is not in the source of the homomorphism
returned by <Ref Attr="Homom"/>. If <K>true</K> is returned, then
either <A>x</A> is in the source of that homomorphism, or passing
<A>x</A> to the homomorphism returns <K>fail</K>.<P/>

For example,
if <A>ri</A> represents a matrix group that preserves a subspace, then
the source of <Ref Attr="Homom"/> will be matrices which preserve that
subspace, and passing matrices which do not preserve this subspace
to <Ref Attr="Homom"/> may produce incorrect answers.
<Ref Attr="validatehomominput"/> can be used to filter out such elements.

The function <Ref Func="ValidateHomomInput"/> provides a simple wrapper
to this attribute, which calls <Ref Attr="validatehomominput"/> unless
it is not defined, in which case <Ref Func="ValidateHomomInput"/>
returns <K>true</K>.
</Description>
</ManSection>


<ManSection>
<Func Name="ValidateHomomInput" Arg="ri, x"/>
<Returns>a boolean.
</Returns>
<Description>
    This is a wrapper function which calls <Ref Attr="validatehomominput"/>
    of <A>ri</A> with <A>x</A>, or returns <K>true</K> if <A>ri</A> does not
    define <Ref Attr="validatehomominput"/>.
</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:

<#Include Label="calcnicegens">
<#Include Label="CalcNiceGensGeneric">
<#Include Label="CalcNiceGensHomNode">
<#Include Label="CalcNiceGens">
<#Include Label="slptonice">

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 node
    to the list of arguments in <C>args</C>. That is, the following
    code is used to call the method:
<Listing>
    gensNmeth := findgensNmeth(ri);
    CallFuncList(gensNmeth.method,Concatenation([ri],gensNmeth.args));
</Listing>
The record is initialised upon creation of the recognition node
to calling <Ref Func="FindKernelFastNormalClosure"/> with arguments
<C>[6, 3]</C> (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><K>true</K> or <K>false</K>.</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"/>. Returns <K>false</K> if the generation of the 
    straight line program for some element fails.
</Description>
</ManSection>

<ManSection>
<Func Name="FindKernelDoNothing" Arg="ri, n1, n2"/>
<Returns><K>true</K>.</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, n1, n2"/>
<Returns><K>true</K> or <K>false</K>.</Returns>
<Description>
    <A>n1</A> random elements of the kernel are generated by calling
    FindKernelRandom. Then this function computes a probable generating
    set of the normal closure in <A>G</A> of the group generated by the
    random elements. The integer <A>n2</A> indicates how hard it should try.
    Returns <K>false</K> if the call to
    <Ref Func="FindKernelRandom" Style="Text"/> returns <K>false</K>.
</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 <K>false</K> can be set to <K>true</K>.
    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 node to the image or
kernel of the found homomorphism:

<ManSection>
<Attr Name="InitialDataForKernelRecogNode" 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 node 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="InitialDataForImageRecogNode" 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 node for the image. Thus,
    information is transported down to the recognition process for the
    image. 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
    image, because often during the finding of a homomorphism knowledge
    is acquired which might help the recognition of the image.
</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 <K>true</K> 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>

<ManSection>
<Attr Name="OrderFunc" Arg="ri"/>
<Description>
This attribute returns a function that computes the order of an element
of the group being recognised. Usually this is just the operation
<Ref Oper="Order" BookName="Ref"/> but for projective groups it is a
special function. In generic code, one should always use the result of
this attribute to compute the order of an element 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 nodes</Heading>

    In this subsection we describe a few more components of
    recognition nodes 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 node.

<List>

<Mark><C>leavegensNuntouched</C></Mark>
<Item>If this component is bound to <K>true</K> 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 <K>Success</K>, <K>NeverApplicable</K>,
        <K>TemporaryFailure</K>, or <K>NotEnoughInformation</K>.</Returns>
    <Description>
        Find homomorphism methods take two arguments <A>ri</A> and <A>G</A>,
        of which <A>ri</A> is a recognition node 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 node <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 node <A>ri</A>. However, it can
collect information and store it either in the group object or in the
recognition node. 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/>
    A method finding a homomorphism which is not an isomorphism indicates
    so by not touching the flags.
    <E>FIXME: What does that mean? Which flags? The IsLeaf filter? But then
    this sounds as if isomorphisms require settings some flag.. but which?!?
    perhaps remove that sentence?</E>
</Item>
<Mark>for leaves: <Ref Func="SLPforElement"/> function</Mark>
<Item>
    If a find homomorphism method has produced a leaf in the recognition tree,
    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 node
    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="methodsforimage"/> accordingly. Also,
    <Ref Attr="ValidateHomomInput"/> may be set to a function which returns
    <K>false</K> for values which may cause <Ref Attr="Homom"/> to
    produce the wrong answer, or error.
</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 (FIXME: is 20 correct?) 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="InitialDataForKernelRecogNode"/> and <Ref Attr="InitialDataForImageRecogNode"/>, which both are
    records. Components in these
    record that are bound during the recognition will be copied into
    the recognition node of the kernel and image respectively
    of a found homomorphism
    upon creation and thus are available to all find homomorphism
    methods called for the kernel and image. This feature might be
    interesting to transport information that is relevant for the
    recognition of the kernel or image 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 image. <P/>
    In addition, a find homomorphism method might set the attribute
    <Ref Attr="immediateverification"/> to <K>true</K>, 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 node <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>

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

</Chapter>
