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

<#GAPDoc Label="Factorization">
<ManSection>
  <Oper Name = "Factorization" Arg = "S, x"/>
    <Returns>A word in the generators.</Returns>
    <Description>
    <List>
      <Mark>for semigroups</Mark>
      <Item>
        When <A>S</A> is a semigroup and <A>x</A> belongs to <A>S</A>,
        <C>Factorization</C> return a word in the generators of <A>S</A> that
        is equal to <A>x</A>. In this case, a word is a list of positive
        integers where an entry <C>i</C> corresponds to
        <C>GeneratorsOfSemigroups(S)[i]</C>.  More specifically,
      <Log>EvaluateWord(GeneratorsOfSemigroup(S), Factorization(S, x)) = x;</Log>
    </Item>

      <!-- FIXME(later) improve: it not clear to me whether this applies to all
    inverse semigroups or to ones with an inverse op WW -->
      <Mark>for inverse semigroups</Mark>
      <Item>
         When <A>S</A> is an inverse semigroup and <A>x</A> belongs to <A>S</A>,
         <C>Factorization</C> return a word in the generators of <A>S</A> that
         is equal to <A>x</A>. In this case, a word is a list of non-zero
         integers where an entry <C>i</C> corresponds to
         <C>GeneratorsOfSemigroup(S)[i]</C> and <C>-i</C> corresponds to
         <C>GeneratorsOfSemigroup(S)[i] ^ -1</C>.
         As in the previous case,
      <Log>EvaluateWord(GeneratorsOfSemigroup(S), Factorization(S, x)) = x;</Log>
      </Item>
    </List>

    Note that <C>Factorization</C> does not always return a word of minimum length;
    see <Ref Oper = "MinimalFactorization"/>.
    <P/>

    See also <Ref Oper = "EvaluateWord"/> and
    <Ref Func = "GeneratorsOfSemigroup" BookName = "ref"/>.
<Example><![CDATA[
gap> gens := [Transformation([2, 2, 9, 7, 4, 9, 5, 5, 4, 8]),
>             Transformation([4, 10, 5, 6, 4, 1, 2, 7, 1, 2])];;
gap> S := Semigroup(gens);;
gap> x := Transformation([1, 10, 2, 10, 1, 2, 7, 10, 2, 7]);;
gap> word := Factorization(S, x);
[ 2, 2, 1, 2 ]
gap> EvaluateWord(gens, word);
Transformation( [ 1, 10, 2, 10, 1, 2, 7, 10, 2, 7 ] )
gap> S := SymmetricInverseMonoid(8);
<symmetric inverse monoid of degree 8>
gap> x := PartialPerm([1, 2, 3, 4, 5, 8], [7, 1, 4, 3, 2, 6]);
[5,2,1,7][8,6](3,4)
gap> word := Factorization(S, x);
[ -2, -2, -2, -2, -2, -2, 2, 4, 4, 2, 3, 2, -3, -2, -2, 3, 2, -3, -2, 
  -2, 4, -3, -4, 2, 2, 3, -2, -3, 4, -3, -4, 2, 2, 3, -2, -3, 2, 2, 
  3, -2, -3, 2, 2, 3, -2, -3, 4, -3, -4, 3, 2, -3, -2, -2, 3, 2, -3, 
  -2, -2, 4, 3, -4, 3, 2, -3, -2, -2, 3, 2, -3, -2, -2, 3, 2, 2, 3, 
  2, 2, 2, 2 ]
gap> EvaluateWord(GeneratorsOfSemigroup(S), word);
[5,2,1,7][8,6](3,4)
gap> S := DualSymmetricInverseMonoid(6);;
gap> x := S.1 * S.2 * S.3 * S.2 * S.1;
<block bijection: [ 1, 6, -4 ], [ 2, -2, -3 ], [ 3, -5 ], [ 4, -6 ], 
 [ 5, -1 ]>
gap> word := Factorization(S, x);
[ -2, -2, -2, -2, -2, 4, 2 ]
gap> EvaluateWord(GeneratorsOfSemigroup(S), word);
<block bijection: [ 1, 6, -4 ], [ 2, -2, -3 ], [ 3, -5 ], [ 4, -6 ], 
 [ 5, -1 ]>]]></Example>
    </Description>
  </ManSection>
<#/GAPDoc>

<#GAPDoc Label="MinimalFactorization">
<ManSection>
  <Oper Name = "MinimalFactorization" Arg = "S, x"/>
  <Returns>A minimal word in the generators.</Returns>
  <Description>
    This operation returns a minimal length word in the generators of the
    semigroup <A>S</A> that equals the element <A>x</A>.
    In this case, a word is a list of positive
    integers where an entry <C>i</C> corresponds to
    <C>GeneratorsOfSemigroups(<A>S</A>)[i]</C>.  More specifically,
    <Log>EvaluateWord(GeneratorsOfSemigroup(S), MinimalFactorization(S, x)) = x;</Log>
    <P/>

    <C>MinimalFactorization</C> involves exhaustively enumerating <A>S</A>
    until the element <A>x</A> is found, and so <C>MinimalFactorization</C>
    may be less efficient than <Ref Oper="Factorization"/> for some
    semigroups.
    <P/>

    Unlike <Ref Oper = "Factorization"/> this operation does not distinguish
    between semigroups and inverse semigroups.  See also <Ref
      Oper = "EvaluateWord"/> and <Ref Func = "GeneratorsOfSemigroup"
      BookName="ref"/>.
    <Example><![CDATA[
gap> S := Semigroup(Transformation([2, 2, 9, 7, 4, 9, 5, 5, 4, 8]),
>                   Transformation([4, 10, 5, 6, 4, 1, 2, 7, 1, 2]));
<transformation semigroup of degree 10 with 2 generators>
gap> x := Transformation([8, 8, 2, 2, 9, 2, 8, 8, 9, 9]);
Transformation( [ 8, 8, 2, 2, 9, 2, 8, 8, 9, 9 ] )
gap> Factorization(S, x);
[ 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1 ]
gap> MinimalFactorization(S, x);
[ 1, 2, 1, 1, 1, 1, 2, 2, 1 ]]]></Example>
    </Description>
  </ManSection>
  <#/GAPDoc>

<#GAPDoc Label="NonTrivialFactorization">
<ManSection>
  <Oper Name = "NonTrivialFactorization" Arg = "S, x"/>
  <Returns>A non-trivial word in the generators, or <K>fail</K>.</Returns>
  <Description>
    When <A>S</A> is a semigroup and <A>x</A> belongs to <A>S</A>, this
    operation returns a non-trivial word in the generators of the semigroup
    <A>S</A> that equals <A>x</A>, if one exists. The definition of
    a word in the generators is the same as given in <Ref Oper="Factorization"
      /> for semigroups and inverse semigroups. A word is non-trivial if it
    has length two or more. <P/>

    If no non-trivial word for <A>x</A> exists, then <A>x</A> is an
    indecomposable element of <A>S</A> and this operation returns <K>fail</K>;
    see <Ref Attr="IndecomposableElements" />. <P/>

    When <A>x</A> does not belong to <C>GeneratorsOfSemigroup(<A>S</A>)</C>,
    any factorization of <A>x</A> is non-trivial. In this case,
    <C>NonTrivialFactorization</C> returns the same word as <Ref
      Oper="Factorization" />.  <P/>

    See also <Ref Func = "EvaluateWord"/> and <Ref Func =
      "GeneratorsOfSemigroup" BookName="ref"/>.
    <Example><![CDATA[
gap> x := Transformation([5, 4, 2, 1, 3]);;
gap> y := Transformation([4, 4, 2, 4, 1]);;
gap> S := Semigroup([x, y]);
<transformation semigroup of degree 5 with 2 generators>
gap> NonTrivialFactorization(S, x * y);
[ 1, 2 ]
gap> Factorization(S, x);
[ 1 ]
gap> NonTrivialFactorization(S, x);
[ 1, 1, 1, 1, 1, 1 ]
gap> Factorization(S, y);
[ 2 ]
gap> NonTrivialFactorization(S, y);
[ 2, 1, 1, 1, 1, 1 ]
gap> z := PartialPerm([2]);;
gap> S := Semigroup(z);
<commutative partial perm semigroup of rank 1 with 1 generator>
gap> NonTrivialFactorization(S, z);
fail]]></Example>
  </Description>
  </ManSection>
<#/GAPDoc>
