<!-- ------------------------------------------------------------------- -->
<!--                                                                     -->
<!--  gpd.xml                Gpd documentation            Chris Wensley  -->
<!--                                                       & Emma Moore  -->
<!--                                                                     -->
<!--  $Id: gpd.xml,v 1.01 2006/04/27 gap Exp $                           -->
<!--                                                                     -->
<!-- ------------------------------------------------------------------- -->

<?xml version="1.0" encoding="ISO-8859-1"?>
  <!-- $Id: gpd.xml,v 1.01  Exp $ -->

<Chapter Label="chap-gpd">
<Heading>Groupoids</Heading>

The &gpd; package provides functions for the computation with
finite groupoids.
The vertex groups will usually be taken to be permutation groups,
but pc-groups and fp-groups are also supported.
For the definition of the standard properties of groupoids
we refer to R. Brown's book ``Topology'' <Cite Key="BrTop" />, 
recently revised and reissued as ``Topology and Groupoids'' 
<Cite Key="BrTopGpd" />.

<Section><Heading>Groupoids: their elements and attributes</Heading>

<ManSection>
   <Oper Name="ConnectedGroupoid"
         Arg="obs, grp" />
   <Oper Name="GroupAsGroupoid"
         Arg="obj, grp" />
   <Oper Name="GroupoidByUnion"
         Arg="comps" />
   <Func Name="Groupoid"
         Arg="args" />
<Description>
A <E>groupoid</E> is a (mathematical) category in which every element
is invertible.
<P/>
A <E>connected groupoid</E> is determined by a set of <E>objects</E> <C>obs</C>
and a <E>vertex group</E> <C>grp</C>. 
Objects are generally chosen to be negative integers, 
but any suitable ordered set will do. 
<P/>
A <E>group</E> is a connected groupoid with one object.
A <E>groupoid</E> is a list of components, 
each of which is a connected groupoid.
There are a variety of constructors for groupoids.
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> d8 := Group( (1,2,3,4), (1,3) );;
gap> SetName( d8, "d8" );
gap> Gd8 := Groupoid( [-9,-8,-7], d8 );
Perm Connected Groupoid:
< [ -9, -8, -7 ], d8 >
gap> c6 := Group( (5,6,7,8,9,10) );;
gap> SetName( c6, "c6" );
gap> Gc6 := Groupoid( -6, c6 );
Perm Connected Groupoid:
< [ -6 ], c6 >
gap> Gd8c6 := Groupoid( [ Gd8, Gc6 ] );;
gap> Display( Gd8c6 );
Perm Groupoid with 2 components:
< objects: [ -9, -8, -7 ]
    group: d8 = <[ (1,2,3,4), (1,3) ]> >
< objects: [ -6 ]
    group: c6 = <[ ( 5, 6, 7, 8, 9,10) ]> >
gap> SetName( Gd8, "Gd8" );
gap> SetName( Gc6, "Gc6" );
gap> SetName( Gd8c6, "Gd8c6" );
]]>
</Example>

<ManSection>
   <Attr Name="ComponentsOfGroupoid"
         Arg="gpd" />
   <Attr Name="ObjectsOfGroupoid"
         Arg="gpd" />
<Description>
The object list of a groupoid is the sorted concatenation of the objects
in the components.
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> ObjectsOfGroupoid( Gd8c6 );
[ -9, -8, -7, -6 ]
]]>
</Example>

<ManSection>
   <Prop Name="IsConnectedGroupoid"
         Arg="gpd" />
   <Prop Name="IsDiscreteGroupoid"
         Arg="gpd" />
<Description>
A groupoid is <E>connected</E> if its underlying graph is a complete digraph.
A groupoid is <E>discrete</E> if it is a union of groups.
<P/>
</Description>
</ManSection>

<ManSection>
   <Prop Name="IsPermGroupoid"
         Arg="gpd" />
   <Prop Name="IsPcGroupoid"
         Arg="gpd" />
   <Prop Name="IsFpGroupoid"
         Arg="gpd" />
<Description>
A groupoid is a permutation groupoid if all its components have 
permutation groups.
Most of the examples in this chapter are permutation groupoids,
but in principle any type of group known to &GAP; may be used.
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> f2 := FreeGroup( 2 );;
gap> Gf2 := Groupoid( [ -22 ], f2 );;
gap> q8 := SmallGroup( 8, 5 );;
gap> Gq8 := Groupoid( [ -28, -18 ], q8 );;
gap> Gf2q8 := Groupoid( [ Gf2, Gq8 ] );;
gap> [ IsFpGroupoid(Gf2), IsPcGroupoid(Gq8), IsPcGroupoid(Gf2q8) ];
[ true, true, false ]
]]>
</Example>

<ManSection>
   <Oper Name="GroupoidElement"
         Arg="gpd, elt, tail, head" />
   <Prop Name="IsElementOfGroupoid"
         Arg="elt" />
   <Attr Name="GroupElement"
         Arg="elt" />
   <Attr Name="Tail"
         Arg="elt" />
   <Attr Name="Head"
         Arg="elt" />
   <Attr Name="Size"
         Arg="gpd" />
<Description>
A <E>groupoid element</E> <C>e</C> is a triple consisting of 
a group element, <C>GroupElement(e)</C> or <C>e![1]</C>; 
the tail (source) object, <C>Tail(e)</C> or <C>e![2]</C>;
and the head (target) object, <C>Head(e)</C> or <C>e![3]</C>.
<P/>
Groupoid elemnts have a <E>partial composition</E>: 
two elements may be multiplied together when the head of the first 
coincides with the tail of the second.
<P/>
</Description>
</ManSection>
<Index>*,\^{} for groupoid elements</Index>
<Example>
<![CDATA[
gap> e1 := GroupoidElement( Gd8, (1,2)(3,4), -9, -8 );
[(1,2)(3,4) : -9 -> -8]
gap> e2 := GroupoidElement( Gd8, (1,3), -8, -7 );
[(1,3) : -8 -> -7]
gap> Print( [ GroupElement( e2 ), Tail( e2 ), Head( e2 ) ], "\n" );
[ (1,3), -8, -7 ]
gap> prod := e1*e2;
[(1,2,3,4) : -9 -> -7]
gap> e3 := GroupoidElement( Gd8, (1,3)(2,4), -7, -9 );
[(1,3)(2,4) : -7 -> -9]
gap> cycle := prod*e3;
[(1,4,3,2) : -9 -> -9]
gap> cycle^2;
[(1,3)(2,4) : -9 -> -9]
gap> Order( cycle );
4
gap> [ Size( Gd8 ), Size( Gc6 ), Size( Gd8c6 ), Size( Gf2q8 ) ];
[ 72, 6, 78, infinity ]
]]>
</Example>
</Section>



<Section><Heading>Subgroupoids</Heading>

<ManSection>
   <Func Name="Subgroupoid"
         Arg="args" />
   <Oper Name="SubgroupoidByComponents"
         Arg="gpd, comps" />
   <Oper Name="FullSubgroupoid"
         Arg="gpd, obs" />
   <Attr Name="MaximalDiscreteSubgroupoid"
         Arg="gpd" />
   <Oper Name="DiscreteSubgroupoid"
         Arg="gpd, obs, sgps" />
   <Attr Name="FullIdentitySubgroupoid"
         Arg="gpd" />
   <Attr Name="DiscreteIdentitySubgroupoid"
         Arg="gpd" />
<Description>
A <E>subgroupoid</E> <C>sgpd</C> of <C>gpd</C> has as objects 
a subset of the objects of <C>gpd</C>.
It is <E>wide</E> if all the objects are included.
It is <E>full</E> if, for any two objects in <C>sgpd</C>, 
the <C>Homset</C> is the same as in <C>gpd</C>.
The elements of <C>sgpd</C> are a subset of those of <C>gpd</C>,
closed under multiplication and
with tail and head in the chosen object set.
<P/>
There are a variety of constructors for a subgroupoids.
The second one listed is the most general, 
in which each component is specified as a list <C>[obs,sgp]</C> where 
<C>obs</C> is a subset of the objects in one of the components of <C>gpd</C>, 
and <C>sgp</C> is a subgroup of the group in that component.
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> Ud8 := Subgroupoid( Gd8, [ [ [-7,-8], c4 ], [ [-9], d8] ] );
Perm Groupoid with components:
< [ -8, -7 ], c4 >
< [ -9 ], d8 >
gap> SetName( Ud8, "Ud8" );
gap> SUd8 := FullSubgroupoid( Ud8, [-9,-7] );
Perm Groupoid with components:
< [ -7 ], c4 >
< [ -9 ], d8 >
gap> SGd8 := FullSubgroupoid( Gd8, [-9,-7] );
Perm Connected Groupoid:
< [ -9, -7 ], d8 >
gap> MUd8 := MaximalDiscreteSubgroupoid( Ud8 );
Perm Groupoid with components:
< [ -9 ], d8 >
< [ -8 ], c4 >
< [ -7 ], c4 >
gap> k4 := Subgroup( d8, [ (1,2)(3,4), (1,3)(2,4) ] );
gap> c3 := Subgroup( c6, [ (5,7,9)(6,8,10)] );;
gap> comp1 := [ [-9,-7], k4 ];;
gap> comp2 := [ [-8], d8 ];;
gap> comp3 := [ [-6], c3 ];;
gap> Ud8c6 := SubgroupoidByComponents( Gd8c6, [comp1,comp2,comp3] );
Perm Groupoid with components:
< [ -9, -7 ], k4 >
< [ -8 ], d8 >
< [ -6 ], c3 >
gap> FUd8 := FullIdentitySubgroupoid( Ud8 );
Perm Connected Groupoid:
< id(d8), [ -8, -7 ] >
gap> DUd8 := DiscreteIdentitySubgroupoid( Ud8 );
Perm Groupoid with components:
< [ -8 ], id(c4) >
< [ -7 ], id(c4) >
< [ -9 ], id(d8) >
]]>
</Example>
</Section>



<Section><Heading>Operations on Groupoids Elements</Heading>

<ManSection>
   <Oper Name="ObjectStar"
         Arg="gpd, obj" />
   <Oper Name="ObjectCostar"
         Arg="gpd, obj" />
   <Oper Name="Homset"
         Arg="gpd, tail, head" />
<Description>
The <E>star</E> at <C>obj</C> is the set of elements 
which have <C>obj</C> as tail,
while the <E>costar</E> is the set of elements which have <C>obj</C> as head.
The <C>Homset</C> from <C>obj1</C> to <C>obj2</C>
is the set of elements with the specified tail and head, 
and so is bijective with the elements of the group. 
In order not to create unneccessary lists, the operations return 
objects of type <C>IsHomsetCosetsRep</C> 
for which an <C>Iterator</C> is provided. 
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> star9 := ObjectStar( Gd8, -9 );
<star at [ -9 ] with group d8>
gap> for e in star9 do
>      if ( Order( e![1] ) = 4 ) then Print( e, "\n" ); fi;
>    od;
[(1,4,3,2) : -9 -> -9]
[(1,4,3,2) : -9 -> -8]
[(1,4,3,2) : -9 -> -7]
[(1,2,3,4) : -9 -> -9]
[(1,2,3,4) : -9 -> -8]
[(1,2,3,4) : -9 -> -7]
gap> hset78 := Homset( Gd8, -7, -8 );
<homset -7 -> -8 with group d8>
gap> for e in hset78 do  Print( e, "\n" );  od;
[() : -7 -> -8]
[(1,3)(2,4) : -7 -> -8]
[(1,4,3,2) : -7 -> -8]
[(1,2,3,4) : -7 -> -8]
[(2,4) : -7 -> -8]
[(1,3) : -7 -> -8]
[(1,4)(2,3) : -7 -> -8]
[(1,2)(3,4) : -7 -> -8]
]]>
</Example>

<ManSection>
   <Oper Name="IdentityElement"
         Arg="gpd, obj" />
<Description>
The identity element <C>1\_{o}</C> of <C>gpd</C> at object <C>o</C> 
is <C>[e,o,o]</C> where <C>e</C> is the identity of the group.  
It is a left identity for the star 
and a right identity for the costar at that object.
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> i7 := IdentityElement( Gd8, -7 );;
gap> i8 := IdentityElement( Gd8, -8 );;
gap> Print( [i7,i8], "\n" );
[ [() : -7 -> -7], [() : -8 -> -8] ]
gap> L := [ ];;
gap> for e in hset78 do  Add( L, i7*e*i8 = e );  od;
gap> L;
[ true, true, true, true, true, true, true, true ]
]]>
</Example>
</Section>



<Section><Heading>Left and right cosets</Heading>

<ManSection>
   <Oper Name="RightCoset"
         Arg="G, U, elt" />
   <Oper Name="RightCosetRepresentatives"
         Arg="G, U" />
   <Oper Name="RightCosetsNC"
         Arg="G, U" />
   <Oper Name="LeftCoset"
         Arg="G, U, elt" />
   <Oper Name="LeftCosetRepresentatives"
         Arg="G, U" />
   <Oper Name="LeftCosetsNC"
         Arg="G, U" />
<Description>
If <C>U</C> is a wide subgroupoid of <M>G</M>, 
the <E>right cosets</E> of <M>U</M> in <M>G</M>
are the equivalence classes of the relation on the elements of <M>G</M>
where  <M>g1</M> is related to <M>g2</M> if and only if <M>g2 = u*g1</M>
for some element <M>u</M> of <M>U</M>.
The right coset containing <M>g</M> is denoted <M>Ug</M>.
These right cosets refine the costars of <M>G</M> and, 
in particular, <M>U1\_{o}</M> is the costar of <M>U</M> at <M>o</M>
so that (unlike groups) <M>U</M> is not itself a coset 
(except when <M>G</M> has only one object).
<P/>
Similarly, the <E>left cosets</E> <M>gU</M> refine the stars of <M>G</M>.
<P/>
As with stars, these cosets are implemented with representation 
<C>IsHomsetCosetsRep</C> and provided with an iterator.
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> e := GroupoidElement( Gd8, (1,3), -7, -8 );
[(1,3) : -7 -> -8]
gap> re := RightCoset( Gd8, Ud8, e );
<right coset c4.[(1,3) : -7 -> -8]>
gap> for x in re do Print( x, "\n" ); od;
[(1,3) : -8 -> -8]
[(1,3) : -7 -> -8]
[(2,4) : -8 -> -8]
[(2,4) : -7 -> -8]
[(1,4)(2,3) : -8 -> -8]
[(1,4)(2,3) : -7 -> -8]
[(1,2)(3,4) : -8 -> -8]
[(1,2)(3,4) : -7 -> -8]
gap> rcrd8 := RightCosetRepresentatives( Gd8, Ud8 );
[ [() : -8 -> -9], [() : -8 -> -8], [() : -8 -> -7], [(2,4) : -8 -> -9],
  [(2,4) : -8 -> -8], [(2,4) : -8 -> -7], [() : -9 -> -9], [() : -9 -> -8],
  [() : -9 -> -7] ]
gap> rcd8 := RightCosetsNC( Gd8, Ud8 );
[ <right coset c4.[() : -8 -> -9]>, <right coset c4.[() : -8 -> -8]>,
  <right coset c4.[() : -8 -> -7]>, <right coset c4.[(2,4) : -8 -> -9]>,
  <right coset c4.[(2,4) : -8 -> -8]>, <right coset c4.[(2,4) : -8 -> -7]>,
  <right coset d8.[() : -9 -> -9]>, <right coset d8.[() : -9 -> -8]>,
  <right coset d8.[() : -9 -> -7]> ]
]]>
</Example>

Note that, when <M>U</M> has more than one component, 
cosets may have differing lengths.
<P/>
</Section>



<Section><Heading>Morphisms of Groupoids</Heading>

<ManSection>
   <Oper Name="ChangeGroupoidRoot"
         Arg="gpd, obj" />
   <Oper Name="ChangeConnectedGroupoidRoot"
         Arg="gpd, obj" />
<Description>
These functions are used to change the root in a component of a groupoid.
</Description>
</ManSection>
<Example>
<![CDATA[
gap> Gd8b := ChangeConnectedGroupoidRoot( Gd8, -6 );
Perm Connected Groupoid:
< Group( [ (2,3,4,5), (3,5) ] ), [ -6, -5, -9 ], [ (), (1,5), (1,5,6) ] >
gap> SetName( Gd8b, "Gd8b" );
]]>
</Example>

<ManSection>
   <Func Name="GroupoidMorphism"
         Arg="args" />
   <Func Name="ConnectedGroupoidMorphism"
         Arg="G, H, obs, hom, rays" />
<Description>
A <E>morphism</E> <M>m</M> from a groupoid <M>G</M> to a groupoid <M>H</M>
consists of a map from the objects of <M>G</M> to those of <M>H</M>
together with a map from the elements of <M>G</M> to those of <M>H</M>
which is compatible with tail and head and which preserves multiplication: 
<Display>
m(g1 : o1 -> o2)*m(g2 : o2 -> o3) = m(g1*g2 : o1 -> o3).
</Display>
As usual, there are a variety of morphism constructors.
Currently, we require a morphism to map root objects to root objects, 
but this is no real restriction since we can use 
<C>ChangeGroupoidRoot</C> to select an alternative root.
So, for a morphism <M>G \to H</M> with <M>G,H</M> connected, we require:
<List>
<Item>
a list of the images of the objects of <M>G</M>, mapping the root to the root;
</Item>
<Item>
a homomorphism from the root group of <M>G</M> to the root group of <M>H</M>.
</Item>
</List>
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> og6 := ObjectGroup( Gd8, -6 );;
gap> gd8 := GeneratorsOfGroup( d8 );;
gap> hd8 := GroupHomomorphismByImages( d8, og6, gd8, [ (2,3,4,5), (3,5) ] );;
gap> md8 := GroupoidMorphism( Gd8, Gd8b, [-6,-9,-5], hd8 );
Groupoid morphism : Gd8 -> Gd8b
gap> Display( md8 );
Connected groupoid morphism:
[ Gd8 ] -> [ Gd8b ]
object images = [ -6, -9, -5 ]
 root mapping = [ [ (1,2,3,4), (1,3) ], [ (2,3,4,5), (3,5) ] ]
   ray images = [ (), (1,5,6), (1,5) ]
]]>
</Example>

<ManSection>
   <Attr Name="IdentityMapping"
         Arg="G" />
   <Oper Name="MappingToIdentityGroupoid"
         Arg="src, rng" />
   <Oper Name="InclusionMappingGroupoids"
         Arg="G, U" />
   <Oper Name="RestrictionMappingGroupoids"
         Arg="hom, src, rng" />
<Description>
The functions <C>IdentityMapping</C> and <C>MappingToOne</C> are already
provided for groups, and are implemented for groupoids.
The latter requires the two groupoids to have the same object set.
The function <C>MappingToIdentityGroupoid</C> maps <C>G</C> to 
<C>FullIdentitySubgroupoid( G )</C>.
We have added functions <C>InclusionMappingGroupoids</C> and 
<C>RestrictionMappingGroupoids</C> for groupoids, corresponding to 
<C>InclusionMappingGroups</C> and <C>RestrictionMappingGroups</C> for groups.
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> idmap := MappingToIdentityGroupoid( Gd8, Gd8 );
Groupoid morphism: [ Gd8 ] -> [ Gd8 ]
]]>
</Example>

<ManSection>
   <Prop Name="IsGroupoidMorphism"
         Arg="mor" />
   <Prop Name="IsInjectiveOnObjects"
         Arg="mor" />
   <Prop Name="IsSurjectiveOnObjects"
         Arg="mor" />
   <Prop Name="IsBijectiveOnObjects"
         Arg="mor" />
   <Attr Name="RootHom"
         Arg="mor" />
   <Attr Name="ObjectImages"
         Arg="mor" />
   <Attr Name="RayImages"
         Arg="mor" />
<Description>
Here are some of the basic properties and attributes of groupoid morphisms:
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> IsGroupoidMorphism( md8 );
true
gap> IsBijectiveOnObjects( md8 );
true
gap> RootHom( md8);
GroupHomomorphismByImages( d8, Group( [ (1,4), (3,4) ] ), [ (1,2), (2,3) ], 
[ (3,4), (1,4) ] )
gap> ObjectImages( md8 );
[ -6, -9, -5 ]
gap> RayImages( md8 );
[ (), (2,4)(3,5), (2,4) ]
]]>
</Example>

<ManSection>
   <Oper Name="GroupoidMorphismByComponentsNC"
         Arg="G, H, comps" />
<Description>
When <M>G</M> is not connected, we require <C>comps</C> to be a list
of morphisms of connected groupoids.
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> hc4 := GroupHomomorphismByImages( c4, c4, [(7,8,9,10)], [(7,10,9,8)] );;
gap> mc4 := GroupoidMorphism( Gc4, Gc4, [3], hc4 );;
gap> mG := GroupoidMorphism( G, G, [ md8, mc4 ] );
Groupoid morphism : G -> G
gap> Display( mG );
Groupoid morphism with components:
[ Gd8 ] -> [ Gd8b ]
object images = [ -6, -9, -5 ]
 root mapping = [ [ (1,2,3,4), (1,3) ], [ (2,3,4,5), (3,5) ] ]
   ray images = [ (), (1,5,6), (1,5) ]
[ Gc4 ] -> [ Gc4 ]
object images = [ -3 ]
 root mapping = [ [ ( 7, 8, 9,10) ], [ ( 7,10, 9, 8) ] ]
   ray images = [ () ]
]]>
</Example>

<ManSection>
   <Attr Name="Order"
         Arg="mor" />
<Description>
Morphisms <M>m_1, m_2</M> can be composed if the image of <M>m_1</M> 
is contained in the domain of <M>m_2</M>.
Currently composition is only defined for morphisms of connected groupoids.
The order of an automorphism is the smallest power which returns the
identity morphism of <M>G</M>.
<P/>
</Description>
</ManSection>
<Index>*,\^{} for groupoid morphisms</Index>
<Example>
<![CDATA[
gap> gog6 := GeneratorsOfGroup( og6 );;
gap> hd8b := GroupHomomorphismByImages( og6, d8, gog6, [(1,2,3,4),(2,4)] );;
gap> md8b := GroupoidMorphism( Gd8b, Gd8, [-5,-6,-9], hd8b );
Groupoid morphism : Gd8b -> Gd8
gap> comp := md8*md8b;
Connected groupoid morphism:
[ Gd8 ] -> [ Gd8 ]
gap> Display( comp );
object images = [ -5, -9, -6 ]
 root mapping = [ [ (1,2,3,4), (1,3) ], [ (1,2,3,4), (2,4) ] ]
   ray images = [ (), (1,6), (1,5) ]
gap> Print( Order( comp ), "\n" );
2
]]>
</Example>

<ManSection>
   <Attr Name="InverseMorphism"
         Arg="mor" />
<Description>
The inverse of a morphism <M>m</M> is defined when <M>m</M> 
is bijective on objects and on elements.
<P/>
</Description>
</ManSection>
<Example>
<![CDATA[
gap> imd8 := InverseMorphism( md8 );;
gap> Display( imd8 );
Connected groupoid morphism:
[ Gd8b ] -> [ Gd8 ]
object images = [ -5, -9, -6 ]
 root mapping = [ [ (2,3,4,5), (3,5) ], [ (1,2,3,4), (1,3) ] ]
   ray images = [ (), (1,6), (1,5) ]
]]>
</Example>
</Section>
</Chapter>
