#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Andrew Solomon and Isabel Araújo.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##
##  This file contains the declarations for finitely
##  presented semigroups.

#############################################################################
##
#C  IsElementOfFpSemigroup(<elm>)
##
##  <#GAPDoc Label="IsElementOfFpSemigroup">
##  <ManSection>
##  <Filt Name="IsElementOfFpSemigroup" Arg='elm' Type='Category'/>
##  <Filt Name="IsElementOfFpMonoid" Arg='elm' Type='Category'/>
##
##  <Description>
##  returns true if <A>elm</A> is an element of a finitely presented
##  semigroup or monoid.
##  <P/>
##  <Example><![CDATA[
##  gap> f := FreeSemigroup( "a", "b" );;
##  gap> IsFpSemigroup( f );
##  false
##  gap> s := f / [ [ f.1^2, f.2^2 ] ];;
##  gap> IsFpSemigroup( s );
##  true
##  gap> t := Semigroup( [ s.1^2 ] );
##  <commutative semigroup with 1 generator>
##  gap> IsSubsemigroupFpSemigroup( t );
##  true
##  gap> IsSubsemigroupFpSemigroup( s );
##  true
##  gap> IsSubsemigroupFpSemigroup( f );
##  false
##  gap> IsElementOfFpSemigroup( t.1^3 );
##  true
##  ]]></Example>
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareCategory( "IsElementOfFpSemigroup",
    IsMultiplicativeElement and IsAssociativeElement );

#############################################################################
##
#O  FpSemigroupOfElementOfFpSemigroup( <elm> )
##
##  <ManSection>
##  <Oper Name="FpSemigroupOfElementOfFpSemigroup" Arg='elm'/>
##
##  <Description>
##  returns the finitely presented semigroup to which <A>elm</A> belongs to
##  </Description>
##  </ManSection>
##
DeclareOperation( "FpSemigroupOfElementOfFpSemigroup",
[IsElementOfFpSemigroup]);

#############################################################################
##
#C  IsElementOfFpSemigroupCollection(<e>)
##
##  <ManSection>
##  <Filt Name="IsElementOfFpSemigroupCollection" Arg='e' Type='Category'/>
##
##  <Description>
##  Created now so that lists of things in the category IsElementOfFpSemigroup
##  are given the category CategoryCollections(IsElementOfFpSemigroup)
##  Otherwise these lists (and other collections) won't create the
##  collections category. See CollectionsCategory in the manual.
##  </Description>
##  </ManSection>
##
DeclareCategoryCollections("IsElementOfFpSemigroup");

#############################################################################
##
#A  IsSubsemigroupFpSemigroup( <t> )
##
##  <#GAPDoc Label="IsSubsemigroupFpSemigroup">
##  <ManSection>
##  <Filt Name="IsSubsemigroupFpSemigroup" Arg='t'/>
##  <Filt Name="IsSubmonoidFpMonoid" Arg='t'/>
##
##  <Description>
##  The first function returns true if <A>t</A> is a finitely presented
##  semigroup or a subsemigroup of a finitely presented semigroup.
##  The second function does the equivalent thing for monoids.
##  (Generally speaking, such a subsemigroup or monoid can be constructed
##  with <C>Semigroup(<A>gens</A>)</C> or <C>Monoid(<A>gens</A>)</C>,
##  where <A>gens</A> is a list of elements
##  of a finitely presented semigroup or monoid.)
##  <P/>
##  A submonoid of a monoid has the same identity as the monoid.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareSynonymAttr( "IsSubsemigroupFpSemigroup",
    IsSemigroup and IsElementOfFpSemigroupCollection );

#############################################################################
##
#C  IsElementOfFpSemigroupFamily
##
##  <ManSection>
##  <Filt Name="IsElementOfFpSemigroupFamily" Arg='obj' Type='Category'/>
##
##  <Description>
##  </Description>
##  </ManSection>
##
DeclareCategoryFamily( "IsElementOfFpSemigroup" );

#############################################################################
##
#F  FactorFreeSemigroupByRelations( <f>, <rels> )
#F  FactorFreeMonoidByRelations( <f>, <rels> )
##
##  <#GAPDoc Label="FactorFreeSemigroupByRelations">
##  <ManSection>
##  <Func Name="FactorFreeSemigroupByRelations" Arg='f, rels'/>
##  <Func Name="FactorFreeMonoidByRelations" Arg='f, rels'/>
##
##  <Description>
##  for a free semigroup or free monoid <A>f</A>
##  and a list <A>rels</A> of pairs of elements of <A>f</A>.
##  Returns the finitely presented semigroup or monoid
##  which is the quotient of <A>f</A> by the least congruence on <A>f</A>
##  generated by the pairs in <A>rels</A>.
##  <P/>
##  Users should be aware that much of the code described in this chapter
##  is in need of substantial revision.
##  In particular, the two functions described here are <E>not</E>
##  called by the operation <C>\/</C> of the previous subsection,
##  and so are liable to be removed in due course.
##  <P/>
##  <Example><![CDATA[
##  gap> fm := FreeMonoid( 3 );;
##  gap> y := GeneratorsOfMonoid( fm );;
##  gap> m := FactorFreeMonoidByRelations( fm,
##  >           [ [ y[1] * y[2] * y[1], y[1] ],[ y[2]^4, y[1] ] ] );
##  <fp monoid on the generators [ m1, m2, m3 ]>
##  ]]></Example>
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareGlobalFunction("FactorFreeSemigroupByRelations");

#############################################################################
##
#O  ElementOfFpSemigroup( <fam>, <word> )
#O  ElementOfFpMonoid( <fam>, <word> )
##
##  <#GAPDoc Label="ElementOfFpSemigroup">
##  <ManSection>
##  <Oper Name="ElementOfFpSemigroup" Arg='fam, word'/>
##  <Oper Name="ElementOfFpMonoid" Arg='fam, word'/>
##
##  <Description>
##  for a family <A>fam</A> of elements of a finitely presented semigroup
##  or monoid and a word <A>word</A> in the free generators underlying this
##  finitely presented semigroup or monoid.
##  Returns the element of the finitely presented semigroup or monoid
##  with the representative <A>word</A> in the free semigroup or free monoid.
##  These operations are inverse to <C>UnderlyingElement</C>.
##  <P/>
##  <Example><![CDATA[
##  gap> fam := FamilyObj( genm[1] );;
##  gap> w := y[1]^3 * y[2]^4 * y[3]^5;
##  m1^3*m2^4*m3^5
##  gap> ew := ElementOfFpMonoid( fam, w );
##  m1^3*m2^4*m3^5
##  gap> ew in fm;
##  false
##  gap> ew in m;
##  true
##  gap> w = UnderlyingElement( ew );
##  true
##  ]]></Example>
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareOperation( "ElementOfFpSemigroup",
    [ IsElementOfFpSemigroupFamily, IsAssocWord ] );

#############################################################################
##
#P  IsFpSemigroup(<s>)
##
##  <#GAPDoc Label="IsFpSemigroup">
##  <ManSection>
##  <Filt Name="IsFpSemigroup" Arg='s'/>
##  <Filt Name="IsFpMonoid" Arg='m'/>
##
##  <Description>
##  The first function is a synonym for
##  <C>IsSubsemigroupFpSemigroup(<A>s</A>)</C> and
##  <C>IsWholeFamily(<A>s</A>)</C> (this is because a subsemigroup
##  of a finitely presented semigroup is not necessarily finitely presented).
##  <P/>
##  Similarly, the second function is a synonym for
##  <C>IsSubmonoidFpMonoid(<A>m</A>)</C> and <C>IsWholeFamily(<A>m</A>)</C>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareSynonym( "IsFpSemigroup",IsSubsemigroupFpSemigroup and IsWholeFamily);

#############################################################################
##
#A  FreeGeneratorsOfFpSemigroup( <s> )
#A  FreeGeneratorsOfFpMonoid( <m> )
##
##  <#GAPDoc Label="FreeGeneratorsOfFpSemigroup">
##  <ManSection>
##  <Attr Name="FreeGeneratorsOfFpSemigroup" Arg='s'/>
##  <Attr Name="FreeGeneratorsOfFpMonoid" Arg='m'/>
##
##  <Description>
##  returns the underlying free generators corresponding to the generators of
##  the finitely presented semigroup <A>s</A> or monoid <A>m</A>.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareAttribute("FreeGeneratorsOfFpSemigroup",  IsFpSemigroup );

#############################################################################
##
#A  FreeSemigroupOfFpSemigroup( <s> )
#A  FreeMonoidOfFpMonoid( <m> )
##
##  <#GAPDoc Label="FreeSemigroupOfFpSemigroup">
##  <ManSection>
##  <Attr Name="FreeSemigroupOfFpSemigroup" Arg='s'/>
##  <Attr Name="FreeMonoidOfFpMonoid" Arg='m'/>
##
##  <Description>
##  returns the underlying free semigroup or free monoid
##  for the finitely presented semigroup <A>s</A> or monoid <A>m</A>,
##  i.e. the free semigroup or free monoid over which <A>s</A> or <A>m</A>
##  is defined as a quotient.
##  (This is the free semigroup or free monoid generated by the free generators
##  provided by <C>FreeGeneratorsOfFpSemigroup(<A>s</A>)</C>
##  or <C>FreeGeneratorsOfFpMonoid(<A>m</A>)</C>).
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareAttribute("FreeSemigroupOfFpSemigroup", IsFpSemigroup);

############################################################################
##
#A  RelationsOfFpSemigroup(<s>)
#A  RelationsOfFpMonoid(<m>)
##
##  <#GAPDoc Label="RelationsOfFpSemigroup">
##  <ManSection>
##  <Attr Name="RelationsOfFpSemigroup" Arg='s'/>
##  <Attr Name="RelationsOfFpMonoid" Arg='m'/>
##
##  <Description>
##  returns the relations of the finitely presented semigroup <A>s</A>
##  or monoid <A>m</A> as pairs of words in the free generators provided by
##  <C>FreeGeneratorsOfFpSemigroup(<A>s</A>)</C> or
##  <C>FreeGeneratorsOfFpMonoid(<A>m</A>)</C>.
##  <P/>
##  <Example><![CDATA[
##  gap> fs = FreeSemigroupOfFpSemigroup( s );
##  true
##  gap> FreeGeneratorsOfFpMonoid( m );
##  [ m1, m2, m3 ]
##  gap> RelationsOfFpSemigroup( s );
##  [ [ s1*s2*s1, s1 ], [ s2^4, s1 ] ]
##  ]]></Example>
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareAttribute("RelationsOfFpSemigroup",IsFpSemigroup);

############################################################################
##
#A  IsomorphismFpSemigroup( <m> )
#A  IsomorphismFpMonoid( <g> )
##
##  <#GAPDoc Label="IsomorphismFpSemigroup">
##  <ManSection>
##  <Attr Name="IsomorphismFpSemigroup" Arg='m'/>
##  <Attr Name="IsomorphismFpMonoid" Arg='g'/>
##
##  <Description>
##  for a finitely presented monoid <A>m</A>
##  or a finitely presented group <A>g</A>.
##  Returns an isomorphism from <A>m</A> or <A>g</A>
##  to a finitely presented semigroup or monoid.
##  <P/>
##  <Example><![CDATA[
##  gap> phis := IsomorphismFpSemigroup( m );
##  MappingByFunction( <fp monoid on the generators
##  [ m1, m2, m3 ]>, <fp semigroup on the generators [ <identity ...>, m1, m2, m3
##   ]>, function( x ) ... end, function( x ) ... end )
##  gap> fg := FreeGroup( 2 );;
##  gap> g := fg / [ fg.1^4, fg.2^5 ];
##  <fp group on the generators [ f1, f2 ]>
##  gap> phim := IsomorphismFpMonoid( g );
##  MappingByFunction( <fp group on the generators
##  [ f1, f2 ]>, <fp monoid on the generators [ f1, f1^-1, f2, f2^-1
##   ]>, function( x ) ... end, function( x ) ... end )
##  ]]></Example>
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareAttribute("IsomorphismFpSemigroup",IsSemigroup);

############################################################################
##
#O  FpGrpMonSmgOfFpGrpMonSmgElement( <elm> )
##
##  <#GAPDoc Label="FpGrpMonSmgOfFpGrpMonSmgElement">
##  <ManSection>
##  <Oper Name="FpGrpMonSmgOfFpGrpMonSmgElement" Arg='elm'/>
##
##  <Description>
##  returns the finitely presented group, monoid or semigroup to which
##  <A>elm</A> belongs.
##  <P/>
##  <Example><![CDATA[
##  gap> s = FpGrpMonSmgOfFpGrpMonSmgElement( s.1 );
##  true
##  gap> s = FpGrpMonSmgOfFpGrpMonSmgElement( t.1 );
##  true
##  gap> f := FreeMonoid( 2 );;
##  gap> m := f / [ [ f.1^2, f.2^2 ] ];
##  <fp monoid on the generators [ m1, m2 ]>
##  gap> m = FpGrpMonSmgOfFpGrpMonSmgElement( m.1 * m.2 );
##  true
##  ]]></Example>
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareOperation("FpGrpMonSmgOfFpGrpMonSmgElement",[IsMultiplicativeElement]);
