<Chapter Label="Collectors">
<Heading>Collectors</Heading>

Let <M>G</M> be a group defined by a pc-presentation as described in the
Chapter <Ref Chap="Introduction to polycyclic presentations" Style="Text"/>.
<P/>

The process for computing the collected form for an arbitrary word in
the generators of <M>G</M> is called <E>collection</E>.  The basic idea in
collection is the following.  Given a word in the defining generators,
one scans the word for occurrences of adjacent generators (or their
inverses) in the wrong order or occurrences of subwords <M>g_i^{e_i}</M>
with <M>i\in I</M> and <M>e_i</M> not in the range <M>0\ldots r_{i}-1</M>.  In the
first case, the appropriate conjugacy relation is used to move the
generator with the smaller index to the left.  In the second case, one
uses the appropriate power relation to move the exponent of <M>g_i</M> into
the required range.  These steps are repeated until a collected word
is obtained.
<P/>

There exist a number of different strategies for collecting a given
word to collected form.  The strategies implemented in this package
are <E>collection from the left</E> as described by <Cite Key="LGS90"/> and
<Cite Key="Sims94"/> and <E>combinatorial collection from the left</E> by
<Cite Key="MVL90"/>.  In addition, the package provides access to Hall
polynomials computed by Deep Thought for the multiplication in a
nilpotent group, see <Cite Key="WWM97"/> and <Cite Key="LGS98"/>.
<P/>

The first step in defining a pc-presented group is setting up a data
structure that knows the pc-presentation and has routines that perform
the collection algorithm with words in the generators of the
presentation. Such a data structure is called <E>a collector</E>.
<P/>

To describe the right hand sides of the relations in a pc-presentation
we use <E>generator exponent lists</E>; the word
<M>g_{i_1}^{e_1}g_{i_2}^{e_2}\ldots g_{i_k}^{e_k}</M> is represented by the
generator exponent list <M>[i_1,e_1,i_2,e_2,\ldots,i_k,e_k]</M>.
<P/>

<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Constructing a Collector">
<Heading>Constructing a Collector</Heading>

A collector for a group given by a pc-presentation starts by
setting up an empty data structure for the collector.  Then the
relative orders, the power relations and the conjugate relations are
added into the data structure.  The construction is finalised by
calling a routine that completes the data structure for the
collector.  The following functions provide the necessary tools for
setting up a collector.

<ManSection>
<Oper Name="FromTheLeftCollector" Arg="n"/>
<Description>
	returns an empty  data structure for a collector  with <A>n</A> generators.
	No generator  has a relative order,  no right hand sides  of power and
	conjugate relations  are defined.  Two  generators for which  no right
	hand side of a conjugate  relation is defined commute.  Therefore, the
	collector  returned by  this function  can be  used to  define  a free
	abelian group of rank <A>n</A>.

<Example><![CDATA[
gap> ftl := FromTheLeftCollector( 4 );
<<from the left collector with 4 generators>>
gap> PcpGroupByCollector( ftl );
Pcp-group with orders [ 0, 0, 0, 0 ]
gap> IsAbelian(last);
true
]]></Example>

	If the relative order of a generators has been defined (see
	<Ref Func="SetRelativeOrder"/>), but the right hand side of the corresponding
	power relation has not, then the order and the relative order of the
	generator are the same.
</Description>
</ManSection>

<ManSection>
<Oper Name="SetRelativeOrder" Arg="coll, i, ro"/>
<Oper Name="SetRelativeOrderNC" Arg="coll, i, ro"/>
<Description>
	set the relative order in collector  <A>coll</A> for generator <A>i</A> to <A>ro</A>.
	The  parameter <A>coll</A>  is  a  collector as  returned  by the  function
	<Ref Func="FromTheLeftCollector"/>,  <A>i</A>  is a  generator  number  and  <A>ro</A> is  a
	non-negative integer.  The  generator number <A>i</A> is an  integer in the
	range  <M>1,\ldots,n</M> where  <M>n</M>  is  the number  of  generators of  the
	collector.
	<P/>

	If <A>ro</A> is <M>0,</M> then the  generator with number <A>i</A> has infinite order
	and no  power relation  can be  specified.  As a  side effect  in this
	case, a previously defined power relation is deleted.
	<P/>

	If <A>ro</A>  is the relative order of  a generator with number  <A>i</A> and no
	power relation  is set for that  generator, then <A>ro</A> is  the order of
	that generator.
	<P/>

	The NC version of the function bypasses checks on the range of <A>i</A>.

<Example><![CDATA[
gap> ftl := FromTheLeftCollector( 4 );
<<from the left collector with 4 generators>>
gap> for i in [1..4] do SetRelativeOrder( ftl, i, 3 ); od;
gap> G := PcpGroupByCollector( ftl );
Pcp-group with orders [ 3, 3, 3, 3 ]
gap> IsElementaryAbelian( G );
true
]]></Example>
</Description>
</ManSection>


<ManSection>
<Oper Name="SetPower" Arg="coll, i, rhs"/>
<Oper Name="SetPowerNC" Arg="coll, i, rhs"/>
<Description>
	set the  right hand side  of the power  relation for generator  <A>i</A> in
	collector <A>coll</A>  to (a copy of)  <A>rhs</A>.  An attempt to  set the right
	hand  side for  a generator  without a  relative order  results  in an
	error.
	<P/>

	Right hand sides are by default assumed to be trivial.
	<P/>

	The parameter <A>coll</A> is a collector, <A>i</A> is a generator number and
	<A>rhs</A> is a generators exponent list or an element from a free group.
	<P/>

	The no-check (NC) version of the function bypasses checks on the range
	of <A>i</A> and stores <A>rhs</A> (instead of a copy) in the collector.
</Description>
</ManSection>

<ManSection>
<Oper Name="SetConjugate" Arg="coll, j, i, rhs"/>
<Oper Name="SetConjugateNC" Arg="coll, j, i, rhs"/>
<Description>
	set the right  hand side of the conjugate  relation for the generators
	<A>j</A>  and <A>i</A>  with <A>j</A>  larger than  <A>i</A>.  The  parameter <A>coll</A>  is a
	collector, <A>j</A> and <A>i</A> are  generator numbers and <A>rhs</A> is a generator
	exponent list  or an element  from a free group.   Conjugate relations
	are by default assumed to be trivial.
	<P/>

	The  generator  number  <A>i</A>  can   be  negative  in  order  to  define
	conjugation by the inverse of a generator.
	<P/>

	The no-check (NC) version of the function bypasses checks on the range
	of <A>i</A> and <A>j</A> and stores <A>rhs</A> (instead of a copy) in the collector.
</Description>
</ManSection>

<ManSection>
<Oper Name="SetCommutator" Arg="coll, j, i, rhs"/>
<Description>
	set the right  hand side of the conjugate  relation for the generators
	<A>j</A> and <A>i</A>  with <A>j</A> larger than <A>i</A> by  specifying the commutator of
	<A>j</A> and  <A>i</A>.  The parameter  <A>coll</A> is a  collector, <A>j</A> and  <A>i</A> are
	generator numbers and <A>rhs</A> is a generator exponent list or an element
	from a free group.
	<P/>

	The  generator  number  <A>i</A>  can   be  negative  in  order  to  define
	the right hand side of a commutator relation with the second generator
	being the inverse of a generator.
</Description>
</ManSection>

<ManSection>
<Oper Name="UpdatePolycyclicCollector" Arg="coll"/>
<Description>
	completes the data  structures of  a  collector.  This is  usually the
	last step in setting up a collector.  Among the steps performed is the
	completion of the conjugate relations.  For each non-trivial conjugate
	relation  of a generator, the corresponding  conjugate relation of the
	inverse generator is calculated.
	<P/>

	Note that  <C>UpdatePolycyclicCollector</C> is automatically  called by the
	function <C>PcpGroupByCollector</C> (see <Ref Func="PcpGroupByCollector"/>).
</Description>
</ManSection>

<ManSection>
<Prop Name="IsConfluent" Arg="coll"/>
<Description>
	tests if the collector <A>coll</A> is confluent.  The function returns true
	or false accordingly.
	<P/>

	Compare Chapter <Ref Chap="Introduction to polycyclic presentations"/> for a
	definition of confluence.
	<P/>

	Note  that  confluence  is   automatically  checked  by  the  function
	<C>PcpGroupByCollector</C> (see <Ref Func="PcpGroupByCollector"/>).
	<P/>

	The following example defines a collector for a semidirect product
	of the cyclic group of order <M>3</M> with the free abelian group of rank
	<M>2</M>.  The action of the cyclic group on the free abelian
	group is given by the matrix

	<Display><![CDATA[\pmatrix{ 0 & 1 \cr -1 & -1}.]]></Display>

	This leads to the following polycyclic presentation:
	<Display>\langle g_1,g_2,g_3 | g_1^3,
                        g_2^{g_1}=g_3,
                        g_3^{g_1}=g_2^{-1}g_3^{-1},
                        g_3^{g_2}=g_3\rangle.</Display>

<Example><![CDATA[
gap> ftl := FromTheLeftCollector( 3 );
<<from the left collector with 3 generators>>
gap> SetRelativeOrder( ftl, 1, 3 );
gap> SetConjugate( ftl, 2, 1, [3,1] );
gap> SetConjugate( ftl, 3, 1, [2,-1,3,-1] );
gap> UpdatePolycyclicCollector( ftl );
gap> IsConfluent( ftl );
true
]]></Example>

	The action of the inverse of <M>g_1</M> on <M>\langle g_2,g_2\rangle</M> is
	given by the matrix <Display><![CDATA[\pmatrix{ -1 & -1 \cr 1 & 0}.]]></Display>  The
	corresponding conjugate relations are automatically computed by
	<C>UpdatePolycyclicCollector</C>.  It is also possible to specify the
	conjugation by inverse generators.  Note that you need to run
	<C>UpdatePolycyclicCollector</C> after one of the set functions has been
	used.

<Example><![CDATA[
gap> SetConjugate( ftl, 2, -1, [2,-1,3,-1] );
gap> SetConjugate( ftl, 3, -1, [2,1] );
gap> IsConfluent( ftl );
Error, Collector is out of date called from
CollectWordOrFail( coll, ev1, [ j, 1, i, 1 ] ); called from
<function>( <arguments> ) called from read-eval-loop
Entering break read-eval-print loop ...
you can 'quit;' to quit to outer loop, or
you can 'return;' to continue
brk>
gap> UpdatePolycyclicCollector( ftl );
gap> IsConfluent( ftl );
true
]]></Example>
</Description>
</ManSection>

</Section>


<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Accessing Parts of a Collector">
<Heading>Accessing Parts of a Collector</Heading>

<ManSection>
<Attr Name="RelativeOrders" Arg="coll"/>
<Description>
	returns (a copy of) the list of relative order stored in the collector
	<A>coll</A>.
</Description>
</ManSection>

<ManSection>
<Oper Name="GetPower" Arg="coll, i"/>
<Oper Name="GetPowerNC" Arg="coll, i"/>
<Description>
	returns a  copy of  the generator exponent  list stored for  the right
	hand side of the power relation  of the generator <A>i</A> in the collector
	<A>coll</A>.
	<P/>

	The no-check (NC) version of the function bypasses checks on the range
	of <A>i</A> and does not create a copy before returning the right hand side
	of the power relation.
</Description>
</ManSection>

<ManSection>
<Oper Name="GetConjugate" Arg="coll, j, i"/>
<Oper Name="GetConjugateNC" Arg="coll, j, i"/>
<Description>
	returns a copy of the right hand side of the conjugate relation stored
	for the generators <A>j</A> and <A>i</A> in the collector <A>coll</A> as generator
	exponent list.  The generator <A>j</A> must be larger than <A>i</A>.
	<P/>

	The no-check (NC) version of the function bypasses checks on the range
	of <A>i</A> and  <A>j</A> and does not create a copy  before returning the right
	hand side of the power relation.
</Description>
</ManSection>

<ManSection>
<Oper Name="NumberOfGenerators" Arg="coll"/>
<Description>
	returns the number of generators of the collector <A>coll</A>.
</Description>
</ManSection>

<ManSection>
<Oper Name="ObjByExponents" Arg="coll, expvec"/>
<Description>
	returns a generator exponent list for the exponent vector <A>expvec</A>.
	This is the inverse operation to <C>ExponentsByObj</C>.  See
	<Ref Func="ExponentsByObj"/> for an example.
</Description>
</ManSection>

<ManSection>
<Oper Name="ExponentsByObj" Arg="coll, genexp"/>
<Description>
	returns an exponent vector for the generator exponent list <A>genexp</A>.
	This is the inverse operation to <C>ObjByExponents</C>. The function
	assumes that the generators in <A>genexp</A> are given in the right
	order and that the exponents are in the right range.

<Example><![CDATA[
gap> G := UnitriangularPcpGroup( 4, 0 );
Pcp-group with orders [ 0, 0, 0, 0, 0, 0 ]
gap> coll := Collector ( G );
<<from the left collector with 6 generators>>
gap> ObjByExponents( coll, [6,-5,4,3,-2,1] );
[ 1, 6, 2, -5, 3, 4, 4, 3, 5, -2, 6, 1 ]
gap> ExponentsByObj( coll, last );
[ 6, -5, 4, 3, -2, 1 ]
]]></Example>
</Description>
</ManSection>


</Section>


<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Special Features">
<Heading>Special Features</Heading>

In this section we descibe collectors for nilpotent groups which make
use of the special structure of the given pc-presentation.

<ManSection>
<Prop Name="IsWeightedCollector" Arg="coll"/>
<Description>
	checks if there is a function <M>w</M> from the generators of the collector
	<A>coll</A> into the positive integers  such that <M>w(g) \geq w(x)+w(y)</M> for
	all  generators <M>x</M>, <M>y</M>  and all  generators <M>g</M>  in (the  normal of)
	<M>[x,y]</M>.  If  such a function does  not exist, false  is returned.  If
	such a  function exists, it is  computed and stored in  the collector.
	In addition, the default collection strategy for this collector is set
	to combinatorial collection.
</Description>
</ManSection>

<ManSection>
<Func Name="AddHallPolynomials" Arg="coll"/>
<Description>
	is applicable  to a  collector which passes  <C>IsWeightedCollector</C> and
	computes  the  Hall multiplication  polynomials  for the  presentation
	stored in <A>coll</A>.   The default strategy for this  collector is set to
	evaluating those polynomial when multiplying two elements.
</Description>
</ManSection>

<ManSection>
<Attr Name="String" Arg="coll"/>
<Description>
	converts a collector <A>coll</A> into a string.
</Description>
</ManSection>

<ManSection>
<Func Name="FTLCollectorPrintTo" Arg="file, name, coll"/>
<Description>
	stores a collector <A>coll</A> in the file <A>file</A> such that the file can be
	read back using the function 'Read' into &GAP; and would then be stored
	in the variable <A>name</A>.
</Description>
</ManSection>

<ManSection>
<Func Name="FTLCollectorAppendTo" Arg="file, name, coll"/>
<Description>
	appends a collector  <A>coll</A> in the file <A>file</A> such  that the file can
	be read  back into  &GAP; and  would then be  stored in  the variable
	<A>name</A>.
</Description>
</ManSection>

<ManSection>
<Var Name="UseLibraryCollector"/>
<Description>
	this property can  be set to <K>true</K> for a collector  to force a simple
	from-the-left collection  strategy implemented in  the &GAP; language
	to  be  used.   Its main  purpose  is  to  help debug  the  collection
	routines.
</Description>
</ManSection>

<ManSection>
<Var Name="USE_LIBRARY_COLLECTOR"/>
<Description>
	this global variable  can be set to <K>true</K> to  force all collectors to
	use  a simple  from-the-left  collection strategy  implemented in  the
	&GAP; language  to be used.   Its main purpose  is to help  debug the
	collection routines.
</Description>
</ManSection>

<ManSection>
<Var Name="DEBUG_COMBINATORIAL_COLLECTOR"/>
<Description>
	this  global variable can  be set  to <K>true</K> to force the  comparison of
	results  from  the  combinatorial  collector  with the  result  of  an
	identical collection  performed by  a simple from-the-left  collector.
	Its main purpose is to help debug the collection routines.
</Description>
</ManSection>

<ManSection>
<Var Name="USE_COMBINATORIAL_COLLECTOR"/>
<Description>
	this global  variable can be  set to <K>false</K>  in order to  prevent the
	combinatorial collector to be used.
</Description>
</ManSection>

</Section>
</Chapter>

