#############################################################################
##
#W  semigroups.xml
#Y  Copyright (C) 2011-14                                James D. Mitchell
##
##  Licensing information can be found in the README file of this package.
##
#############################################################################
##

<#GAPDoc Label="InverseMonoidByGenerators">
  <ManSection>
    <Oper Name = "InverseMonoidByGenerators" Arg = "coll[, opts]"/>
    <Oper Name = "InverseSemigroupByGenerators"  Arg = "coll[, opts]"/>
    <Returns>An inverse monoid or semigroup.</Returns>
    <Description>
      If <A>coll</A> is a collection satisfying
      <C>IsGeneratorsOfInverseSemigroup</C>, then
      <C>InverseMonoidByGenerators</C> and
      <C>InverseSemigroupByGenerators</C>
      return the inverse monoid and semigroup generated by <A>coll</A>,
      respectively. <P/>

      If present, the optional second argument <A>opts</A> should be a record
      containing the values of the options for the semigroup being created, as
      described in Section <Ref Sect = "Options when creating semigroups"/>.<P/>
    </Description>
  </ManSection>
<#/GAPDoc>

<#GAPDoc Label="Generators">
  <ManSection>
    <Attr Name = "Generators" Arg = "S"/>
    <Returns>A list of generators.</Returns>
    <Description>
      <C>Generators</C> returns a generating set that can be used to define the
      semigroup <A>S</A>.  The generators of a monoid or inverse semigroup
      <A>S</A>, say, can be defined in several ways, for example, including or
      excluding the identity element, including or not the inverses of the
      generators.  <C>Generators</C> uses the definition that returns the least
      number of generators. If no generating set for <A>S</A> is known, then
      <C>GeneratorsOfSemigroup</C> is used by default.<P/>
 
      <List>
        <Mark>for a group</Mark>
        <Item><C>Generators(<A>S</A>)</C> is a synonym for
          <Ref Attr = "GeneratorsOfGroup" BookName = "ref"/>.
        </Item>
        <Mark>for an ideal of semigroup</Mark>
        <Item><C>Generators(<A>S</A>)</C> is a synonym for
          <Ref Attr = "GeneratorsOfSemigroupIdeal"/>.
        </Item>
        <Mark>for a semigroup</Mark>
        <Item><C>Generators(<A>S</A>)</C> is a synonym for
          <Ref Attr = "GeneratorsOfSemigroup" BookName = "ref"/>.
        </Item>
        <Mark>for a monoid</Mark>
        <Item><C>Generators(<A>S</A>)</C> is a synonym for
          <Ref Attr = "GeneratorsOfMonoid" BookName = "ref"/>.
        </Item>
        <Mark>for an inverse semigroup</Mark>
        <Item><C>Generators(<A>S</A>)</C> is a synonym for
          <Ref Attr = "GeneratorsOfInverseSemigroup" BookName = "ref"/>.
        </Item>
        <Mark>for an inverse monoid</Mark>
        <Item><C>Generators(<A>S</A>)</C> is a synonym for
          <Ref Attr = "GeneratorsOfInverseMonoid" BookName = "ref"/>.
        </Item>
      </List>
<Example><![CDATA[
gap> M := Monoid([
> Transformation([1, 4, 6, 2, 5, 3, 7, 8, 9, 9]),
> Transformation([6, 3, 2, 7, 5, 1, 8, 8, 9, 9])]);;
gap> GeneratorsOfSemigroup(M);
[ IdentityTransformation, 
  Transformation( [ 1, 4, 6, 2, 5, 3, 7, 8, 9, 9 ] ), 
  Transformation( [ 6, 3, 2, 7, 5, 1, 8, 8, 9, 9 ] ) ]
gap> GeneratorsOfMonoid(M);
[ Transformation( [ 1, 4, 6, 2, 5, 3, 7, 8, 9, 9 ] ), 
  Transformation( [ 6, 3, 2, 7, 5, 1, 8, 8, 9, 9 ] ) ]
gap> Generators(M);
[ Transformation( [ 1, 4, 6, 2, 5, 3, 7, 8, 9, 9 ] ), 
  Transformation( [ 6, 3, 2, 7, 5, 1, 8, 8, 9, 9 ] ) ]
gap> S := Semigroup(Generators(M));;
gap> Generators(S);
[ Transformation( [ 1, 4, 6, 2, 5, 3, 7, 8, 9, 9 ] ), 
  Transformation( [ 6, 3, 2, 7, 5, 1, 8, 8, 9, 9 ] ) ]
gap> GeneratorsOfSemigroup(S);
[ Transformation( [ 1, 4, 6, 2, 5, 3, 7, 8, 9, 9 ] ), 
  Transformation( [ 6, 3, 2, 7, 5, 1, 8, 8, 9, 9 ] ) ]]]></Example>
   </Description>
  </ManSection>
<#/GAPDoc>

<#GAPDoc Label="ClosureSemigroup">
  <ManSection>
    <Oper Name = "ClosureSemigroup" Arg = "S, coll [, opts]"/>
    <Oper Name = "ClosureMonoid" Arg = "S, coll [, opts]"/>
    <Oper Name = "ClosureInverseSemigroup" Arg = "S, coll [, opts]"/>
    <Oper Name = "ClosureInverseMonoid" Arg = "S, coll [, opts]"/>
    <Returns>A semigroup, monoid, inverse semigroup, or inverse
      monoid.</Returns>
    <Description>
      These operations return the semigroup, monoid, inverse semigroup or
      inverse monoid generated by the argument <A>S</A> and the collection of
      elements <A>coll</A> after removing duplicates and elements from
      <A>coll</A> that are already in <A>S</A>. In most cases, the new
      semigroup knows at least as much information about its structure as was
      already known about that of <A>S</A>. <P/>
      
      When <C>X</C> is any of
      <Ref Func="Semigroup" BookName="ref"/>,
      <Ref Func="Monoid" BookName="ref"/>,
      <Ref Func="InverseSemigroup" BookName="ref"/>, or
      <Ref Func="InverseMonoid" BookName="ref"/>, 
      the argument <A>S</A> of the operation <C>ClosureX</C> must belong to the
      category <C>IsX</C>, and <C>ClosureX(<A>S</A>, <A>coll</A>)</C> returns
      an object in the category <C>IsX</C> such that 
      <Log>
        ClosureX(S, coll) = X(S, coll);</Log>
      but may have fewer generators, if for example,
      <A>coll</A> contains a duplicates or elements already known to belong to
      <A>S</A>.<P/>
      
      For example, the argument <A>S</A> of <C>ClosureInverseSemigroup</C> must
      be an inverse semigroup in the category <Ref Filt="IsInverseSemigroup"
        BookName="ref"/>.  <C>ClosureInverseSemigroup(<A>S</A>,
        <A>coll</A>)</C> returns an inverse semigroup which is equal to
      <C>InverseSemigroup(<A>S</A>, <A>coll</A>)</C>.
      <P/>

      If present, the optional third argument <A>opts</A> should be a record
      containing the values of the options for the semigroup being created as
      described in Section <Ref Sect = "Options when creating semigroups"/>.<P/>
      <Example><![CDATA[
gap> gens := [Transformation([2, 6, 7, 2, 6, 1, 1, 5]),
>             Transformation([3, 8, 1, 4, 5, 6, 7, 1]),
>             Transformation([4, 3, 2, 7, 7, 6, 6, 5]),
>             Transformation([7, 1, 7, 4, 2, 5, 6, 3])];;
gap> S := Monoid(gens[1]);;
gap> for x in gens do 
>      S := ClosureSemigroup(S, x); 
>    od;
gap> S;
<transformation monoid of degree 8 with 4 generators>
gap> Size(S);
233606
gap> S := Monoid(PartialPerm([1]));
<trivial partial perm group of rank 1 with 1 generator>
gap> T := ClosureMonoid(S, [PartialPerm([2 .. 5])]);
<partial perm monoid of rank 5 with 2 generators>
gap> One(T);
<identity partial perm on [ 1, 2, 3, 4, 5 ]>
gap> T := ClosureSemigroup(S, [PartialPerm([2 .. 5])]);
<partial perm semigroup of rank 4 with 2 generators>
gap> One(T);
fail
gap> ClosureInverseMonoid(DualSymmetricInverseMonoid(3),
>                         DClass(DualSymmetricInverseMonoid(3),
>                                IdentityBipartition(3)));
<inverse block bijection monoid of degree 3 with 3 generators>
gap> S := InverseSemigroup(Bipartition([[1, -1, -3], [2, 3, -2]]),
>                          Bipartition([[1, -3], [2, -2], [3, -1]]));;
gap> T := ClosureInverseSemigroup(S, DClass(PartitionMonoid(3),
> IdentityBipartition(3)));
<inverse block bijection semigroup of degree 3 with 3 generators>
gap> T := ClosureInverseSemigroup(T, [T.1, T.1, T.1]);
<inverse block bijection semigroup of degree 3 with 3 generators>
gap> S := InverseMonoid([
> PartialPerm([5, 9, 10, 0, 6, 3, 8, 4, 0]),
> PartialPerm([10, 7, 0, 8, 0, 0, 5, 9, 1])]);;
gap> x := PartialPerm([
> 5, 1, 7, 3, 10, 0, 2, 12, 0, 14, 11, 0, 16, 0, 0, 0, 0, 6, 9, 15]);
[4,3,7,2,1,5,10,14][8,12][13,16][18,6][19,9][20,15](11)
gap> S := ClosureInverseSemigroup(S, x);
<inverse partial perm semigroup of rank 19 with 4 generators>
gap> Size(S);
9744
gap> T := Idempotents(SymmetricInverseSemigroup(10));;
gap> S := ClosureInverseSemigroup(S, T);
<inverse partial perm semigroup of rank 19 with 14 generators>]]></Example>
    </Description>
  </ManSection>
<#/GAPDoc>

<#GAPDoc Label="InverseSubsemigroupByProperty">
  <ManSection>
    <Oper Name = "InverseSubsemigroupByProperty" Arg = "S, func"/>
    <Returns>An inverse semigroup.</Returns>
    <Description>
    <C>InverseSubsemigroupByProperty</C> returns the inverse subsemigroup of the
    inverse semigroup <A>S</A> generated by those elements of <A>S</A>
    fulfilling <A>func</A> (which should be a function returning <K>true</K> or
    <K>false</K>).<P/>

    If no elements of <A>S</A> fulfil <A>func</A>, then <K>fail</K> is
    returned.<P/>
 
    If the optional third argument <A>limit</A> is present and a positive
    integer, then once the subsemigroup has at least <A>limit</A> elements the
    computation stops.
    <Example><![CDATA[
gap> IsIsometry := function(f)
> local n, i, j, k, l;
>  n := RankOfPartialPerm(f);
>  for i in [1 .. n - 1] do
>    k := DomainOfPartialPerm(f)[i];
>    for j in [i + 1 .. n] do
>      l := DomainOfPartialPerm(f)[j];
>      if not AbsInt(k ^ f - l ^ f) = AbsInt(k - l) then
>        return false;
>      fi;
>    od;
>  od;
>  return true;
> end;;
gap> S := InverseSubsemigroupByProperty(SymmetricInverseSemigroup(5),
> IsIsometry);;
gap> Size(S);
142]]></Example>
    </Description>
  </ManSection>
<#/GAPDoc>

<#GAPDoc Label="SubsemigroupByProperty">
<ManSection>
  <Oper Name = "SubsemigroupByProperty" Arg = "S, func"
    Label = "for a semigroup and function"/>
  <Oper Name = "SubsemigroupByProperty" Arg = "S, func, limit"
  Label = "for a semigroup, function, and limit on the size of the subsemigroup"/>
  <Returns>A semigroup.</Returns>
  <Description>
    <C>SubsemigroupByProperty</C> returns the subsemigroup of the semigroup
    <A>S</A> generated by those elements of <A>S</A> fulfilling <A>func</A>
    (which should be a function returning <K>true</K> or <K>false</K>).<P/>

    If no elements of <A>S</A> fulfil <A>func</A>, then <K>fail</K> is
    returned.<P/>

    If the optional third argument <A>limit</A> is present and a positive
    integer, then once the subsemigroup has at least <A>limit</A> elements the
    computation stops.
    <Example><![CDATA[
gap> func := function(x)
>      local n;
>      n := DegreeOfTransformation(x);
>      return 1 ^ x <> 1 and ForAll([1 .. n], y -> y = 1 or y ^ x = y);
>    end;
function( x ) ... end
gap> T := SubsemigroupByProperty(FullTransformationSemigroup(3), func);
<transformation semigroup of size 2, degree 3 with 2 generators>
gap> T := SubsemigroupByProperty(FullTransformationSemigroup(4), func);
<transformation semigroup of size 3, degree 4 with 3 generators>
gap> T := SubsemigroupByProperty(FullTransformationSemigroup(5), func);
<transformation semigroup of size 4, degree 5 with 4 generators>]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="Random">
  <ManSection>
    <Meth Name = "Random" Arg = "S" Label = "for a semigroup"/>
    <Returns>A random element.</Returns>
    <Description>

      This function returns a random element of the semigroup <A>S</A>.
      If the elements of <A>S</A> have been calculated, then one of these
      is chosen randomly.

      Otherwise, if the data  structure for <A>S</A> is known,
      then a random element of a randomly chosen &R;-class is returned. 
 
      If the data structure for <A>S</A> has not been calculated, then a short
      product (at most <C>2 * Length(GeneratorsOfSemigroup(<A>S</A>))</C>) of
      generators is returned. 
 
    </Description>
  </ManSection>
<#/GAPDoc>
