#############################################################################
##
#W  grahom.xml
#Y  Copyright (C) 2014-18
##
##  Licensing information can be found in the README file of this package.
##
#############################################################################
##

<#GAPDoc Label="HomomorphismDigraphsFinder">
<ManSection>
  <Func Name="HomomorphismDigraphsFinder" Arg="D1, D2, hook, user_param, max_results, hint, injective, image, partial_map, colors1, colors2[, order, aut_grp]"/>
  <Returns>The argument <A>user_param</A>.</Returns>
  <Description>
    This function finds homomorphisms from the digraph <A>D1</A> to the digraph
    <A>D2</A> subject to the conditions imposed by the other arguments as
    described below.<P/>

    If <C>f</C> and <C>g</C> are homomorphisms found by
    <C>HomomorphismDigraphsFinder</C>, then <C>f</C> cannot be obtained from
    <C>g</C> by right multiplying by an automorphism of <A>D2</A> in
    <A>aut_grp</A>.

    <List>
      <Mark><A>hook</A></Mark>
      <Item>
        This argument should be a function or <K>fail</K>.<P/>

        If <A>hook</A> is a function, then it must have two arguments
        <A>user_param</A> (see below) and a transformation <C>t</C>. The
        function <C><A>hook</A>(<A>user_param</A>, t)</C> is called every time
        a new homomorphism <C>t</C> is found by
        <C>HomomorphismDigraphsFinder</C>. If the function returns <K>true</K>,
        then <C>HomomorphismDigraphsFinder</C> stops and does not find any
        further homomorphisms. This feature might be useful if you are
        searching for a homomorphism that satisfies some condition that you
        cannot specify via the other arguments to
        <C>HomomorphismDigraphsFinder</C>.
        <P/>

        If <A>hook</A> is <K>fail</K>, then a default function is used which
        simply adds every new homomorphism found by
        <C>HomomorphismDigraphsFinder</C> to <A>user_param</A>, which must be a
        mutable list in this case.
      </Item>

      <Mark><A>user_param</A></Mark>
      <Item>
        If <A>hook</A> is a function, then <A>user_param</A> can be any &GAP;
        object. The object <A>user_param</A> is used as the first argument of
        the function <A>hook</A>. For example, <A>user_param</A> might be a
        transformation semigroup, and <C><A>hook</A>(<A>user_param</A>, t)</C>
        might set <A>user_param</A> to be the closure of <A>user_param</A> and
        <C>t</C>. <P/>

        If the value of <A>hook</A> is <K>fail</K>, then the value of
        <A>user_param</A> must be a mutable list.
      </Item>

      <Mark><A>max_results</A></Mark>
      <Item>
        This argument should be a positive integer or <K>infinity</K>.
        <C>HomomorphismDigraphsFinder</C> will return after it has found
        <A>max_results</A> homomorphisms or the search is complete, whichever
        happens first.
      </Item>

      <Mark><A>hint</A></Mark>
      <Item>
        This argument should be a positive integer or <K>fail</K>. <P/>

        If <A>hint</A> is a positive integer, then only homorphisms of rank
        <A>hint</A> are found.<P/>

        If <A>hint</A> is <K>fail</K>, then no restriction is put on the rank
        of homomorphisms found.
      </Item>

      <Mark><A>injective</A></Mark>
      <Item>
        This argument should be <C>0</C>, <C>1</C>, or <C>2</C>.  If it is
        <C>2</C>, then only embeddings are found, if it is <C>1</C>, then only
        injective homomorphisms are found, and if it is <C>0</C> there are no
        restrictions imposed by this argument.
        <P/>

        For backwards compatibility, <A>injective</A> can also be <K>false</K>
        or <K>true</K> which correspond to the values <C>0</C> and <C>1</C>
        described in the previous paragraph, respectively. 
      </Item>

      <Mark><A>image</A></Mark>
      <Item>
        This argument should be a subset of the vertices of the graph <A>D2</A>.
        <C>HomomorphismDigraphsFinder</C> only finds homomorphisms from
        <A>D1</A> to the subgraph of <A>D2</A> induced by the vertices
        <A>image</A>.
      </Item>

      <Mark><A>partial_map</A></Mark>
      <Item>
        This argument should be a partial map from <A>D1</A> to <A>D2</A>,
        that is, a (not necessarily dense) list of vertices of the digraph
        <A>D2</A> of length no greater than the number vertices in the digraph
        <A>D1</A>. <C>HomomorphismDigraphsFinder</C> only finds homomorphisms
        extending <A>partial_map</A> (if any).
      </Item>
      
      <Mark><A>colors1</A></Mark>
      <Item>
        This should be a list representing possible colours of vertices in the
        digraph <A>D1</A>; see 
        <Ref Oper="AutomorphismGroup" 
          Label="for a digraph and a homogeneous list"/> 
        for details of the permissible values for this argument.
      </Item>
      
      <Mark><A>colors2</A></Mark>
      <Item>
        This should be a list representing possible colours of vertices in the
        digraph <A>D2</A>; see 
        <Ref Oper="AutomorphismGroup" 
          Label="for a digraph and a homogeneous list"/> 
        for details of the permissible values for this argument.
      </Item>
      <Mark><A>order</A></Mark>
      <Item>
        The optional argument <A>order</A> specifies the order the
        vertices in <A>D1</A> appear in the search for homomorphisms. 
        The value of this parameter can have a large impact
        on the runtime of the function. It seems in many cases to be a good
        idea for this to be the <Ref Attr="DigraphWelshPowellOrder"/>, i.e.
        vertices ordered from highest to lowest degree.
      </Item>
      <Item>
        The optional argument <A>aut_grp</A> should be a subgroup of the
        automorphism group of <A>D2</A>. This function returns unique
        representatives of the homomorphisms found up to right multiplication
        by <A>aut_grp</A>. If this argument is not specific, it defaults to the
        full automorphism group of <A>D2</A>, which may be costly to calculate.
      </Item>
    </List>

    <Example><![CDATA[
gap> D := ChainDigraph(10);
<immutable chain digraph with 10 vertices>
gap> D := DigraphSymmetricClosure(D);
<immutable symmetric digraph with 10 vertices, 18 edges>
gap> HomomorphismDigraphsFinder(D, D, fail, [], infinity, 2, 0,
> [3, 4], [], fail, fail);
[ Transformation( [ 3, 4, 3, 4, 3, 4, 3, 4, 3, 4 ] ), 
  Transformation( [ 4, 3, 4, 3, 4, 3, 4, 3, 4, 3 ] ) ]
gap> D2 := CompleteDigraph(6);;
gap> HomomorphismDigraphsFinder(D, D2, fail, [], 1, fail, 0,
> [1 .. 6], [1, 2, 1], fail, fail);
[ Transformation( [ 1, 2, 1, 3, 4, 5, 6, 1, 2, 1 ] ) ]
gap> func := function(user_param, t)
> Add(user_param, t * user_param[1]);
> end;;
gap> HomomorphismDigraphsFinder(D, D2, func, [Transformation([2, 2])],
> 3, fail, 0, [1 .. 6], [1, 2, 1], fail, fail);
[ Transformation( [ 2, 2 ] ), 
  Transformation( [ 2, 2, 2, 3, 4, 5, 6, 2, 2, 2 ] ), 
  Transformation( [ 2, 2, 2, 3, 4, 5, 6, 2, 2, 3 ] ), 
  Transformation( [ 2, 2, 2, 3, 4, 5, 6, 2, 2, 4 ] ) ]
gap> HomomorphismDigraphsFinder(NullDigraph(2), NullDigraph(3), fail,
> [], infinity, fail, 1, [1, 2, 3], fail, fail, fail, fail,
> Group(()));
[ IdentityTransformation, Transformation( [ 1, 3, 3 ] ), 
  Transformation( [ 2, 1 ] ), Transformation( [ 2, 3, 3 ] ), 
  Transformation( [ 3, 1, 3 ] ), Transformation( [ 3, 2, 3 ] ) ]
gap> HomomorphismDigraphsFinder(NullDigraph(2), NullDigraph(3), fail,
> [], infinity, fail, 1, [1, 2, 3], fail, fail, fail, fail,
> Group((1, 2)));
[ IdentityTransformation, Transformation( [ 1, 3, 3 ] ), 
  Transformation( [ 3, 1, 3 ] ) ]]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphHomomorphism">
<ManSection>
  <Oper Name="DigraphHomomorphism" Arg="digraph1, digraph2"/>
  <Returns> A transformation, or <K>fail</K>.</Returns>
  <Description>
    A homomorphism from <A>digraph1</A> to <A>digraph2</A> is a mapping from
    the vertex set of <A>digraph1</A> to a subset of the vertices of
    <A>digraph2</A>, such that every pair of vertices <C>[i,j]</C> which has
    an edge <C>i->j</C> is mapped to a pair of vertices <C>[a,b]</C> which
    has an edge <C>a->b</C>.  Note that non-adjacent vertices can still be
    mapped to adjacent vertices. <P/>

    <C>DigraphHomomorphism</C> returns a single homomorphism between
    <A>digraph1</A> and <A>digraph2</A> if it exists, otherwise it returns
    <K>fail</K>.
<Example><![CDATA[
gap> gr1 := ChainDigraph(3);;
gap> gr2 := Digraph([[3, 5], [2], [3, 1], [], [4]]);
<immutable digraph with 5 vertices, 6 edges>
gap> DigraphHomomorphism(gr1, gr1);
IdentityTransformation
gap> map := DigraphHomomorphism(gr1, gr2);
Transformation( [ 3, 1, 5, 4, 5 ] )
gap> IsDigraphHomomorphism(gr1, gr2, map);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="HomomorphismsDigraphs">
<ManSection>
  <Oper Name="HomomorphismsDigraphs" Arg="digraph1, digraph2"/>
  <Oper Name="HomomorphismsDigraphsRepresentatives" Arg="digraph1, digraph2"/>
  <Returns> A list of transformations.</Returns>
  <Description>
    <C>HomomorphismsDigraphsRepresentatives</C> finds every
    <Ref Oper="DigraphHomomorphism"/> between <A>digraph1</A> and
    <A>digraph2</A>, up to right multiplication by an element of the
    <Ref Attr="AutomorphismGroup" Label="for a digraph"/> of <A>digraph2</A>.
    In other words, every homomorphism <C>f</C> between <A>digraph1</A> and
    <A>digraph2</A> can be written as the composition <C>f = g * x</C>,
    where <C>g</C> is one of the <C>HomomorphismsDigraphsRepresentatives</C>
    and <C>x</C> is an automorphism of <A>digraph2</A>.
    <P/>

    <C>HomomorphismsDigraphs</C> returns all homomorphisms between
    <A>digraph1</A> and <A>digraph2</A>.
    <Example><![CDATA[
gap> gr1 := ChainDigraph(3);;
gap> gr2 := Digraph([[3, 5], [2], [3, 1], [], [4]]);
<immutable digraph with 5 vertices, 6 edges>
gap> HomomorphismsDigraphs(gr1, gr2);
[ Transformation( [ 1, 3, 1 ] ), Transformation( [ 1, 3, 3 ] ), 
  Transformation( [ 1, 5, 4, 4, 5 ] ), Transformation( [ 2, 2, 2 ] ), 
  Transformation( [ 3, 1, 3 ] ), Transformation( [ 3, 1, 5, 4, 5 ] ), 
  Transformation( [ 3, 3, 1 ] ), Transformation( [ 3, 3, 3 ] ) ]
gap> HomomorphismsDigraphsRepresentatives(gr1, CompleteDigraph(3));
[ Transformation( [ 2, 1 ] ), Transformation( [ 2, 1, 2 ] ) ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphMonomorphism">
<ManSection>
  <Oper Name="DigraphMonomorphism" Arg="digraph1, digraph2"/>
  <Returns>A transformation, or <K>fail</K>.</Returns>
  <Description>
    <C>DigraphMonomorphism</C> returns a single <E>injective</E> <Ref
      Oper="DigraphHomomorphism"/> between <A>digraph1</A> and <A>digraph2</A>
    if one exists, otherwise it returns <K>fail</K>.
    <Example><![CDATA[
gap> gr1 := ChainDigraph(3);;
gap> gr2 := Digraph([[3, 5], [2], [3, 1], [], [4]]);
<immutable digraph with 5 vertices, 6 edges>
gap> DigraphMonomorphism(gr1, gr1);
IdentityTransformation
gap> DigraphMonomorphism(gr1, gr2);
Transformation( [ 3, 1, 5, 4, 5 ] )
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="MonomorphismsDigraphs">
<ManSection>
  <Oper Name="MonomorphismsDigraphs" Arg="digraph1, digraph2"/>
  <Oper Name="MonomorphismsDigraphsRepresentatives" Arg="digraph1, digraph2"/>
  <Returns>A list of transformations.</Returns>
  <Description>
    These operations behave the same as <Ref Oper="HomomorphismsDigraphs"/> and
    <Ref Oper="HomomorphismsDigraphsRepresentatives"/>, except they only return
    <E>injective</E> homomorphisms.
    <Example><![CDATA[
gap> gr1 := ChainDigraph(3);;
gap> gr2 := Digraph([[3, 5], [2], [3, 1], [], [4]]);
<immutable digraph with 5 vertices, 6 edges>
gap> MonomorphismsDigraphs(gr1, gr2);
[ Transformation( [ 1, 5, 4, 4, 5 ] ), 
  Transformation( [ 3, 1, 5, 4, 5 ] ) ]
gap> MonomorphismsDigraphsRepresentatives(gr1, CompleteDigraph(3));
[ Transformation( [ 2, 1 ] ) ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphEpimorphism">
<ManSection>
  <Oper Name="DigraphEpimorphism" Arg="digraph1, digraph2"/>
  <Returns>A transformation, or <K>fail</K>.</Returns>
  <Description>
    <C>DigraphEpimorphism</C> returns a single <E>surjective</E> <Ref
      Oper="DigraphHomomorphism"/> between <A>digraph1</A> and <A>digraph2</A>
    if one exists, otherwise it returns <K>fail</K>.
    <Example><![CDATA[
gap> gr1 := DigraphReverse(ChainDigraph(4));
<immutable digraph with 4 vertices, 3 edges>
gap> gr2 := DigraphRemoveEdge(CompleteDigraph(3), [1, 2]);
<immutable digraph with 3 vertices, 5 edges>
gap> DigraphEpimorphism(gr2, gr1);
fail
gap> DigraphEpimorphism(gr1, gr2);
Transformation( [ 3, 1, 2, 3 ] )
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="EpimorphismsDigraphs">
<ManSection>
  <Oper Name="EpimorphismsDigraphs" Arg="digraph1, digraph2"/>
  <Oper Name="EpimorphismsDigraphsRepresentatives" Arg="digraph1, digraph2"/>
  <Returns>A list of transformations.</Returns>
  <Description>
    These operations behave the same as <Ref Oper="HomomorphismsDigraphs"/> and
    <Ref Oper="HomomorphismsDigraphsRepresentatives"/>, except they only return
    <E>surjective</E> homomorphisms.
    <Example><![CDATA[
gap> gr1 := DigraphReverse(ChainDigraph(4));
<immutable digraph with 4 vertices, 3 edges>
gap> gr2 := DigraphSymmetricClosure(CycleDigraph(3));
<immutable symmetric digraph with 3 vertices, 6 edges>
gap> EpimorphismsDigraphsRepresentatives(gr1, gr2);
[ Transformation( [ 3, 1, 2, 1 ] ), Transformation( [ 3, 1, 2, 3 ] ), 
  Transformation( [ 2, 1, 2, 3 ] ) ]
gap> EpimorphismsDigraphs(gr1, gr2);
[ Transformation( [ 1, 2, 1, 3 ] ), Transformation( [ 1, 2, 3, 1 ] ), 
  Transformation( [ 1, 2, 3, 2 ] ), Transformation( [ 1, 3, 1, 2 ] ), 
  Transformation( [ 1, 3, 2, 1 ] ), Transformation( [ 1, 3, 2, 3 ] ), 
  Transformation( [ 2, 1, 2, 3 ] ), Transformation( [ 2, 1, 3, 1 ] ), 
  Transformation( [ 2, 1, 3, 2 ] ), Transformation( [ 2, 3, 1, 2 ] ), 
  Transformation( [ 2, 3, 1, 3 ] ), Transformation( [ 2, 3, 2, 1 ] ), 
  Transformation( [ 3, 1, 2, 1 ] ), Transformation( [ 3, 1, 2, 3 ] ), 
  Transformation( [ 3, 1, 3, 2 ] ), Transformation( [ 3, 2, 1, 2 ] ), 
  Transformation( [ 3, 2, 1, 3 ] ), Transformation( [ 3, 2, 3, 1 ] ) ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="GeneratorsOfEndomorphismMonoid">
<ManSection>
  <Func Name="GeneratorsOfEndomorphismMonoid" Arg="digraph[, colors][, limit]"/>
  <Attr Name="GeneratorsOfEndomorphismMonoidAttr" Arg="digraph"/>
  <Returns> A list of transformations.</Returns>
  <Description>
    An endomorphism of <A>digraph</A> is a homomorphism
    <Ref Oper="DigraphHomomorphism"/> from <A>digraph</A> back to itself.

    <C>GeneratorsOfEndomorphismMonoid</C>, called with a single argument,
    returns a generating set for the monoid of all endomorphisms of
    <A>digraph</A>. If <A>digraph</A>  belongs to <Ref
      Filt="IsImmutableDigraph"/>, then the value of
    <C>GeneratorsOfEndomorphismMonoid</C> will not be recomputed on future
    calls.<P/>

    If the <A>colors</A> argument is specified, then
    <C>GeneratorsOfEndomorphismMonoid</C> will return a generating
    set for the monoid of endomorphisms which respect the given colouring.
    The colouring <A>colors</A> can be in one of two forms: <P/>

    <List>
      <Item>
        A list of positive integers of size the number of vertices of
        <A>digraph</A>, where <A>colors</A><C>[i]</C> is the colour of vertex
        <C>i</C>.
      </Item>
      <Item>
        A list of lists, such that <A>colors</A><C>[i]</C> is a list of all
        vertices with colour <C>i</C>.
      </Item>
    </List>

    If the <A>limit</A> argument is specified, then it will return only the
    first <A>limit</A> homomorphisms, where <A>limit</A> must be a positive
    integer or <C>infinity</C>. <P/>

    <Example><![CDATA[
gap> gr := Digraph(List([1 .. 3], x -> [1 .. 3]));;
gap> GeneratorsOfEndomorphismMonoid(gr);
[ Transformation( [ 1, 3, 2 ] ), Transformation( [ 2, 1 ] ), 
  IdentityTransformation, Transformation( [ 1, 2, 1 ] ), 
  Transformation( [ 1, 2, 2 ] ), Transformation( [ 1, 1, 2 ] ), 
  Transformation( [ 1, 1, 1 ] ) ]
gap> GeneratorsOfEndomorphismMonoid(gr, 3);
[ Transformation( [ 1, 3, 2 ] ), Transformation( [ 2, 1 ] ), 
  IdentityTransformation ]
gap> gr := CompleteDigraph(3);;
gap> GeneratorsOfEndomorphismMonoid(gr);
[ Transformation( [ 2, 3, 1 ] ), Transformation( [ 2, 1 ] ), 
  IdentityTransformation ]
gap> GeneratorsOfEndomorphismMonoid(gr, [1, 2, 2]);
[ Transformation( [ 1, 3, 2 ] ), IdentityTransformation ]
gap> GeneratorsOfEndomorphismMonoid(gr, [[1], [2, 3]]);
[ Transformation( [ 1, 3, 2 ] ), IdentityTransformation ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphColouring">
<ManSection>
  <Oper Name="DigraphColouring" Arg="digraph, n"
    Label="for a digraph and a number of colours"/>
  <Returns> A transformation, or <K>fail</K>.</Returns>
  <Description>
    A <E>proper colouring</E> of a digraph is a labelling of its vertices in
    such a way that adjacent vertices have different labels. A <E>proper
      <C>n</C>-colouring</E> is a proper colouring that uses exactly <C>n</C>
    colours.  Equivalently, a proper (<C>n</C>-)colouring of a digraph can be
    defined to be a <Ref Oper="DigraphEpimorphism"/> from a digraph onto the
    complete digraph (with <C>n</C> vertices); see <Ref
      Oper="CompleteDigraph"/>.  Note that a digraph with loops (<Ref
      Prop="DigraphHasLoops"/>) does not have a proper <C>n</C>-colouring for
    any value <C>n</C>.
    <P/>

    If <A>digraph</A> is a digraph and <A>n</A> is a non-negative integer, then
    <C>DigraphColouring(<A>digraph</A>, <A>n</A>)</C> returns an epimorphism
    from <A>digraph</A> onto the complete digraph with <A>n</A> vertices if one
    exists, else it returns <K>fail</K>. <P/>

    See also <Ref Attr="DigraphGreedyColouring" Label="for a digraph"/> and 
    <P/>

    Note that a digraph with at least two vertices has a 2-colouring if and only
    if it is bipartite, see <Ref Prop="IsBipartiteDigraph"/>.

    <Example><![CDATA[
gap> DigraphColouring(CompleteDigraph(5), 4);
fail
gap> DigraphColouring(ChainDigraph(10), 1);
fail
gap> D := ChainDigraph(10);;
gap> t := DigraphColouring(D, 2);
Transformation( [ 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 ] )
gap> IsDigraphColouring(D, t); 
true
gap> DigraphGreedyColouring(D);
Transformation( [ 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 ] )
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphGreedyColouring">
<ManSection>
  <Oper Name="DigraphGreedyColouring" 
        Arg="digraph, order" 
        Label="for a digraph and vertex order"/>
  <Oper Name="DigraphGreedyColouring" 
        Arg="digraph, func" 
        Label="for a digraph and vertex order function"/>
  <Attr Name="DigraphGreedyColouring" 
        Arg="digraph" 
        Label="for a digraph"/>
  <Returns> A transformation, or <K>fail</K>.</Returns>
  <Description>
    A <E>proper colouring</E> of a digraph is a labelling of its vertices in
    such a way that adjacent vertices have different labels. Note that a digraph 
    with loops (<Ref Prop="DigraphHasLoops"/>) does not have any proper 
    colouring.
    <P/>
    
    If <A>digraph</A> is a digraph and <A>order</A> is a dense list consisting 
    of all of the vertices of <A>digraph</A> (in any order), then  
    <C>DigraphGreedyColouring</C>
    uses a greedy algorithm with the specified order to obtain some proper
    colouring of <A>digraph</A>, which may not use the minimal number of
    colours. <P/>
    
    If <A>digraph</A> is a digraph and <A>func</A> is a function whose argument 
    is a digraph, and that returns a dense list <A>order</A>, then 
    <C>DigraphGreedyColouring(<A>digraph</A>, <A>func</A>)</C> returns
    <C>DigraphGreedyColouring(<A>digraph</A>, <A>func</A>(<A>digraph</A>))</C>.
    <P/>

    If the optional second argument (either a list or a function), is not 
    specified, then <Ref Attr="DigraphWelshPowellOrder"/> is used by default. 
    <P/>
    
    See also
    <Ref Oper="DigraphColouring" 
         Label="for a digraph and a number of colours"/>.
    <P/>

    <Example><![CDATA[
gap> DigraphGreedyColouring(ChainDigraph(10));
Transformation( [ 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 ] )
gap> DigraphGreedyColouring(ChainDigraph(10), [1 .. 10]);
Transformation( [ 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 ] )
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphWelshPowellOrder">
<ManSection>
  <Attr Name="DigraphWelshPowellOrder" Arg="digraph"/>
  <Returns> A list of the vertices.</Returns>
  <Description>
    <C>DigraphWelshPowellOrder</C> returns a list of all of the vertices of 
    the digraph <A>digraph</A> ordered according to the sum of the number of 
    out- and in-neighbours, from highest to lowest. 
    <P/>

    <Example><![CDATA[
gap> DigraphWelshPowellOrder(Digraph([[4], [9], [9], [], 
>                                     [4, 6, 9], [1], [], [], 
>                                     [4, 5], [4, 5]]));
[ 5, 9, 4, 1, 6, 10, 2, 3, 7, 8 ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphEmbedding">
<ManSection>
  <Oper Name="DigraphEmbedding" Arg="digraph1, digraph2"/>
  <Returns> A transformation, or <K>fail</K>.</Returns>
  <Description>
    An embedding of a digraph <A>digraph1</A> into another digraph
    <A>digraph2</A> is a <Ref Oper="DigraphMonomorphism"/> from <A>digraph1</A>
    to <A>digraph2</A> which has the additional property that a pair of
    vertices <C>[i, j]</C> which have no edge <C>i -> j</C> in <A>digraph1</A> are

    mapped to a pair of vertices <C>[a, b]</C> which have no edge <C>a->b</C> in
    <A>digraph2</A>.<P/>

    In other words, an embedding <C>t</C> is an isomorphism from
    <A>digraph1</A> to the <Ref Oper="InducedSubdigraph"/> of <A>digraph2</A>
    on the image of <C>t</C>. <P/>

    <C>DigraphEmbedding</C> returns a single embedding if one exists, otherwise
    it returns <K>fail</K>.
    <Example><![CDATA[
gap> gr := ChainDigraph(3);
<immutable chain digraph with 3 vertices>
gap> DigraphEmbedding(gr, CompleteDigraph(4));
fail
gap> DigraphEmbedding(gr, Digraph([[3], [1, 4], [1], [3]]));
Transformation( [ 2, 4, 3, 4 ] )
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="EmbeddingsDigraphs">
<ManSection>
  <Oper Name="EmbeddingsDigraphs" Arg="D1, D2"/>
  <Oper Name="EmbeddingsDigraphsRepresentatives" Arg="D1, D2"/>
  <Returns>A list of transformations.</Returns>
  <Description>
    These operations behave the same as <Ref Oper="HomomorphismsDigraphs"/> and
    <Ref Oper="HomomorphismsDigraphsRepresentatives"/>, except they only return
    embeddings of <A>D1</A> into <A>D2</A>.<P/>

    See also <Ref Oper="IsDigraphEmbedding"/>.
    <Example><![CDATA[
gap> D1 := NullDigraph(2);
<immutable empty digraph with 2 vertices>
gap> D2 := CycleDigraph(5);
<immutable cycle digraph with 5 vertices>
gap> EmbeddingsDigraphsRepresentatives(D1, D2);
[ Transformation( [ 1, 3, 3 ] ), Transformation( [ 1, 4, 3, 4 ] ) ]
gap> EmbeddingsDigraphs(D1, D2);
[ Transformation( [ 1, 3, 3 ] ), Transformation( [ 1, 4, 3, 4 ] ), 
  Transformation( [ 2, 4, 4, 5, 1 ] ), 
  Transformation( [ 2, 5, 4, 5, 1 ] ), 
  Transformation( [ 3, 1, 5, 1, 2 ] ), 
  Transformation( [ 3, 5, 5, 1, 2 ] ), 
  Transformation( [ 4, 1, 1, 2, 3 ] ), 
  Transformation( [ 4, 2, 1, 2, 3 ] ), 
  Transformation( [ 5, 2, 2, 3, 4 ] ), 
  Transformation( [ 5, 3, 2, 3, 4 ] ) ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsDigraphHomomorphism">
<ManSection>
  <Oper Name="IsDigraphHomomorphism" Arg="src, ran, x" 
        Label="for digraphs and a permutation or transformation"/>
  <Oper Name="IsDigraphHomomorphism" Arg="src, ran, x, col1, col2"/>
  <Oper Name="IsDigraphEpimorphism" Arg="src, ran, x"
        Label="for digraphs and a permutation or transformation"/>
  <Oper Name="IsDigraphEpimorphism" Arg="src, ran, x, col1, col2"/>
  <Oper Name="IsDigraphMonomorphism" Arg="src, ran, x"
        Label="for digraphs and a permutation or transformation"/>
  <Oper Name="IsDigraphMonomorphism" Arg="src, ran, x, col1, col2"/>
  <Oper Name="IsDigraphEndomorphism" Arg="digraph, x"
        Label="for digraphs and a permutation or transformation"/>
  <Oper Name="IsDigraphEndomorphism" Arg="digraph, x, col"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    <C>IsDigraphHomomorphism</C> returns <K>true</K> if the permutation
    or transformation <A>x</A> is a homomorphism from the digraph
    <A>src</A> to the digraph <A>ran</A>.
    <P/>

    <C>IsDigraphEpimorphism</C> returns <K>true</K> if the permutation
    or transformation <A>x</A> is a surjective homomorphism from the digraph
    <A>src</A> to the digraph <A>ran</A>.
    <P/>

    <C>IsDigraphMonomorphism</C> returns <K>true</K> if the permutation
    or transformation <A>x</A> is an injective homomorphism from the digraph
    <A>src</A> to the digraph <A>ran</A>.
    <P/>

    <C>IsDigraphEndomorphism</C> returns <K>true</K> if the permutation
    or transformation <A>x</A> is an endomorphism of the digraph
    <A>digraph</A>.
    <P/>

    A permutation or transformation <A>x</A> is a <E>homomorphism</E> from a
    digraph <A>src</A> to a digraph <A>ran</A> if the following hold:
    <List>
      <Item>
        <C>[u ^ <A>x</A>, v ^ <A>x</A>]</C> is an edge of
        <A>ran</A> whenever <C>[u, v]</C> is an
        edge of <A>src</A>; and </Item>
      <Item>
        <A>x</A> fixes every <C>i</C> which is not a vertex of <A>src</A>.
      </Item>
    </List>
    See also <Ref Func="GeneratorsOfEndomorphismMonoid"/>.<P/>


    If <A>col1</A> and <A>col2</A>, or <A>col</A>, are given, then they must
    represent vertex colourings; see 
    <Ref Oper="AutomorphismGroup" Label="for a digraph and a homogeneous list"/> 
    for details of the permissible values for these argument. The
    homomorphism must then also have the property:
  
    <List>
      <Item>
        <C>col[i] = col[i ^ x]</C> for all vertices <C>i</C> of <A>digraph</A>,
        in the case of <C>IsDigraphEndomorphism</C>.</Item>
      <Item>
        <C>col1[i] = col2[i ^ x]</C> for all vertices <C>i</C> of <A>src</A>,
        in the cases of the other operations.</Item>
    </List>

    See also <Ref Oper="DigraphsRespectsColouring"/>.
    
    <Example><![CDATA[
gap> src := Digraph([[1], [1, 2], [1, 3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> ran := Digraph([[1], [1, 2]]);
<immutable digraph with 2 vertices, 3 edges>
gap> IsDigraphHomomorphism(src, ran, Transformation([1, 2, 2]));
true
gap> IsDigraphHomomorphism(src, ran, Transformation([2, 1, 2]));
false
gap> IsDigraphHomomorphism(src, ran, Transformation([3, 3, 3]));
false
gap> IsDigraphHomomorphism(src, src, Transformation([3, 3, 3]));
true
gap> IsDigraphHomomorphism(src, ran, Transformation([1, 2, 2]),
>                          [1, 2, 2], [1, 2]);
true
gap> IsDigraphHomomorphism(src, ran, Transformation([1, 2, 2]),
>                          [2, 1, 1], [1, 2]);
false
gap> IsDigraphEndomorphism(src, Transformation([3, 3, 3]));
true
gap> IsDigraphEndomorphism(src, Transformation([3, 3, 3]), [1, 1, 1]);
true
gap> IsDigraphEndomorphism(src, Transformation([3, 3, 3]), [1, 1, 2]);
false
gap> IsDigraphEpimorphism(src, ran, Transformation([3, 3, 3]));
false
gap> IsDigraphMonomorphism(src, ran, Transformation([1, 2, 2]));
false
gap> IsDigraphEpimorphism(src, ran, Transformation([1, 2, 2]));
true
gap> IsDigraphMonomorphism(ran, src, ());
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsDigraphEmbedding">
<ManSection>
  <Oper Name="IsDigraphEmbedding" Arg="src, ran, x"
        Label="for digraphs and a permutation or transformation"/>
  <Oper Name="IsDigraphEmbedding" Arg="src, ran, x, col1, col2"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    <C>IsDigraphEmbedding</C> returns <K>true</K> if the permutation
    or transformation <A>x</A> is a embedding of the digraph
    <A>src</A> into the digraph <A>ran</A>, while respecting the colourings
    <A>col1</A> and <A>col2</A> if given.
    <P/>

    A permutation or transformation <A>x</A> is a <E>embedding</E> of a digraph
    <A>src</A> into a digraph <A>ran</A> if <A>x</A> is a monomorphism from
    <A>src</A> to <A>ran</A> and the inverse of <A>x</A> is a monomorphism from
    the subdigraph of <A>ran</A> induced by the image of <A>x</A> to
    <A>src</A>.

    See also <Ref Oper="IsDigraphHomomorphism"/>.<P/>

    <Example><![CDATA[
gap> src := Digraph([[1], [1, 2]]);
<immutable digraph with 2 vertices, 3 edges>
gap> ran := Digraph([[1], [1, 2], [1, 3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> IsDigraphMonomorphism(src, ran, ());
true
gap> IsDigraphEmbedding(src, ran, ());
true
gap> IsDigraphEmbedding(src, ran, (), [2, 1], [2, 1, 1]);
true
gap> IsDigraphEmbedding(src, ran, (), [2, 1], [1, 2, 1]);
false
gap> ran := Digraph([[1, 2], [1, 2], [1, 3]]);
<immutable digraph with 3 vertices, 6 edges>
gap> IsDigraphMonomorphism(src, ran, IdentityTransformation);
true
gap> IsDigraphEmbedding(src, ran, IdentityTransformation);
false]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsDigraphColouring">
  <ManSection>
    <Oper Name="IsDigraphColouring" Arg="digraph, list"/>
    <Oper Name="IsDigraphColouring" Arg="digraph, t" 
      Label="for a transformation"/>
    <Returns> <K>true</K> or <K>false</K>. </Returns>
    <Description>
      The operation <C>IsDigraphColouring</C> verifies whether or not 
      the list <A>list</A> describes a proper colouring of the digraph 
      <A>digraph</A>. 
      <P/>

      A list <A>list</A> describes a <E>proper colouring</E> of a digraph
      <A>digraph</A> if <A>list</A> consists of positive integers, the length of
      <A>list</A> equals the number of vertices in <A>digraph</A>, and for any
      vertices <C>u, v</C> of <A>digraph</A> if <C>u</C> and <C>v</C> are adjacent,
      then <C><A>list</A>[u] &gt;&lt; <A>list</A>[v]</C>.
      <P/>

      A transformation <A>t</A> describes a proper colouring of a digraph
      <A>digraph</A>, if <C>ImageListOfTransformation(<A>t</A>,
      DigraphNrVertices(<A>digraph</A>))</C> is a proper colouring of 
      <A>digraph</A>. <P/>

      See also <Ref Oper="IsDigraphHomomorphism"/>.
      
      <Example><![CDATA[
gap> D := JohnsonDigraph(5, 3);
<immutable symmetric digraph with 10 vertices, 60 edges>
gap> IsDigraphColouring(D, [1, 2, 3, 3, 2, 1, 4, 5, 6, 7]);
true
gap> IsDigraphColouring(D, [1, 2, 3, 3, 2, 1, 2, 5, 6, 7]);
false
gap> IsDigraphColouring(D, [1, 2, 3, 3, 2, 1, 2, 5, 6, -1]);
false
gap> IsDigraphColouring(D, [1, 2, 3]);
false
gap> IsDigraphColouring(D, IdentityTransformation);
true
]]></Example>
    </Description>
  </ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphsRespectsColouring">
  <ManSection>
    <Oper Name="DigraphsRespectsColouring" Arg="src, ran, x, col1, col2"/>
    <Returns> <K>true</K> or <K>false</K>. </Returns>
    <Description>
      The operation <C>DigraphsRespectsColouring</C> verifies whether or not 
      the permutation or transformation <A>x</A> respects the vertex colourings
      <A>col1</A> and <A>col2</A> of the digraphs <A>src</A> and <A>range</A>.
      That is, <C>DigraphsRespectsColouring</C> returns <K>true</K> if and only if for
      all vertices <C>i</C> of <A>src</A>, <C>col1[i] = col2[i ^ x]</C>.
      <P/>

      <Example><![CDATA[
gap> src := Digraph([[1], [1, 2]]);
<immutable digraph with 2 vertices, 3 edges>
gap> ran := Digraph([[1], [1, 2], [1, 3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> DigraphsRespectsColouring(src, ran, (1, 2), [2, 1], [1, 2, 1]);
true
gap> DigraphsRespectsColouring(src, ran, (1, 2), [2, 1], [2, 1, 1]);
false
]]></Example>
    </Description>
  </ManSection>
<#/GAPDoc>

<#GAPDoc Label="MaximalCommonSubdigraph">
  <ManSection>
    <Oper Name="MaximalCommonSubdigraph" Arg="D1, D2"/>
    <Returns>A list containing a digraph and two transformations.</Returns>
    <Description>
  If <A>D1</A> and <A>D2</A> are digraphs without multiple edges, then
  <C>MaximalCommonSubdigraph</C> returns a maximal common subgraph <C>M</C> of
  <A>D1</A> and <A>D2</A> with the maximum number of vertices. So <C>M</C> is a
  digraph which embeds into both <A>D1</A> and <A>D2</A> and has the largest
  number of vertices among such digraphs.

  It returns a list <C>[M, t1, t2]</C> where <C>M</C> is the maximal common
  subdigraph and <C>t1, t2</C> are transformations embedding <C>M</C> into
  <A>D1</A> and <A>D2</A> respectively.

<Example><![CDATA[
gap> MaximalCommonSubdigraph(PetersenGraph(), CompleteDigraph(10));
[ <immutable digraph with 2 vertices, 2 edges>, 
  IdentityTransformation, IdentityTransformation ]
gap> MaximalCommonSubdigraph(PetersenGraph(),
> DigraphSymmetricClosure(CycleDigraph(5)));
[ <immutable digraph with 5 vertices, 10 edges>, 
  IdentityTransformation, IdentityTransformation ]
gap> MaximalCommonSubdigraph(NullDigraph(0), CompleteDigraph(10));
[ <immutable empty digraph with 0 vertices>, IdentityTransformation, 
  IdentityTransformation ]
]]></Example>
    </Description>
  </ManSection>
<#/GAPDoc>

<#GAPDoc Label="MinimalCommonSuperdigraph">
  <ManSection>
    <Oper Name="MinimalCommonSuperdigraph" Arg="D1, D2"/>
    <Returns>A list containing a digraph and two transformations.</Returns>
    <Description>
  If <A>D1</A> and <A>D2</A> are digraphs without multiple edges, then
  <C>MinimalCommonSuperdigraph</C> returns a minimal common superdigraph
  <C>M</C> of <A>D1</A> and <A>D2</A> with the minimum number of vertices.
  So <C>M</C> is a digraph into which both <A>D1</A> and <A>D2</A> embed and
  has the smallest number of vertices among such digraphs.
 
  It returns a list <C>[M, t1, t2]</C> where <C>M</C> is the minimal common 
  superdigraph and <C>t1, t2</C> are transformations embedding <A>D1</A> and
  <A>D2</A> respectively into <C>M</C>.
<Example><![CDATA[
gap> MinimalCommonSuperdigraph(PetersenGraph(), CompleteDigraph(10));
[ <immutable digraph with 18 vertices, 118 edges>, 
  IdentityTransformation, 
  Transformation( [ 1, 2, 11, 12, 13, 14, 15, 16, 17, 18, 11, 12, 13,
      14, 15, 16, 17, 18 ] ) ]
gap> MinimalCommonSuperdigraph(PetersenGraph(),
> DigraphSymmetricClosure(CycleDigraph(5)));
[ <immutable digraph with 10 vertices, 30 edges>, 
  IdentityTransformation, IdentityTransformation ]
gap> MinimalCommonSuperdigraph(NullDigraph(0), CompleteDigraph(10));
[ <immutable digraph with 10 vertices, 90 edges>, 
  IdentityTransformation, IdentityTransformation ]
]]></Example>
    </Description>
  </ManSection>
<#/GAPDoc>

<#GAPDoc Label="LatticeDigraphEmbedding">
<ManSection>
  <Oper Name="LatticeDigraphEmbedding" Arg="L1, L2"/>
  <Returns>A transformation, or <K>fail</K>.</Returns>
  <Description>
    If <A>L1</A> and <A>L2</A> are lattice digraphs (<Ref
      Prop="IsLatticeDigraph"/> returns <K>true</K>, then 
    <C>LatticeDigraphEmbedding</C> returns a single <E>injective</E> <Ref
      Oper="DigraphHomomorphism"/> between <A>L1</A> and <A>L2</A>, with
      the property that it is a <E>lattice homomorphism</E>. If no such
      homomorphism exists, <K>fail</K> is returned.<P/>

      A <E>lattice homomorphism</E> is a digraph homomorphism which respects
      meets and joins of every pair of vertices. Note that every injective
      lattice homomorphism <C>map</C> is an embedding, in the sense that
      the inverse of <C>map</C> is a lattice homomorphism also.

    <Example><![CDATA[
gap> D := DigraphReflexiveTransitiveClosure(ChainDigraph(5));
<immutable preorder digraph with 5 vertices, 15 edges>
gap> L1 := DigraphReflexiveTransitiveClosure(ChainDigraph(5));
<immutable preorder digraph with 5 vertices, 15 edges>
gap> L2 := DigraphReflexiveTransitiveClosure(ChainDigraph(6));
<immutable preorder digraph with 6 vertices, 21 edges>
gap> LatticeDigraphEmbedding(L1, L2);
IdentityTransformation
gap> LatticeDigraphEmbedding(L2, L1);
fail
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsLatticeHomomorphism">
<ManSection>
  <Oper Name="IsLatticeHomomorphism" Arg="L1, L2, map" 
        Label="for digraphs and a permutation or transformation"/>
  <Oper Name="IsLatticeEpimorphism" Arg="L1, L2, map"
        Label="for digraphs and a permutation or transformation"/>
  <Oper Name="IsLatticeEmbedding" Arg="L1, L2, map"
        Label="for digraphs and a permutation or transformation"/>
  <Oper Name="IsLatticeMonomorphism" Arg="L1, L2, map"
        Label="for digraphs and a permutation or transformation"/>
  <Oper Name="IsLatticeEndomorphism" Arg="L, map"
        Label="for digraphs and a permutation or transformation"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>

  <Description>
    Each of the function described in this section (except
    <C>IsLatticeEndomorphism</C>) takes a pair of digraphs <A>L1</A> and
    <A>L2</A>, and a transformation <A>map</A>, returning <K>true</K> if
    <A>map</A> is a <E>lattice homomorphism</E> from <A>L1</A> to <A>L2</A>,
      and <K>false</K> otherwise. If <A>L1</A> or <A>L2</A> is not a lattice,
      then <K>false</K> is returned.<P/>

    A transformation or permutation <A>map</A> is a <E>lattice homomorphism</E>
    if <A>map</A> respects meets and joins of every pair of vertices, and
    <A>map</A> fixes every <C>i</C> which is not a vertex of <A>L1</A>.
    <P/>

    <C>IsLatticeHomomorphism</C> returns <K>true</K> if the permutation
    or transformation <A>map</A> is a lattice homomorphism from the lattice digraph
    <A>L1</A> to the lattice digraph <A>L2</A>.
    <P/>

    <C>IsLatticeEpimorphism</C> returns <K>true</K> if the permutation
    or transformation <A>map</A> is a surjective lattice homomorphism from
    the lattice digraph <A>L1</A> to the lattice digraph <A>L2</A>.
    <P/>

    <C>IsLatticeEmbedding</C> returns <K>true</K> if the permutation
    or transformation <A>map</A> is an injective lattice homomorphism from
    the lattice digraph <A>L1</A> to the lattice digraph <A>L2</A>.
    The function <C>IsLatticeMonomorphism</C> is a synonym of 
    <C>IsLatticeEmbedding</C>.
    <P/>

    <C>IsLatticeEndomorphism</C> returns <K>true</K> if the permutation
    or transformation <A>map</A> is an lattice endomorphism of the
    lattice digraph <A>L</A>.

    <Example><![CDATA[
gap> G := Digraph([[2, 4], [3, 7], [6], [5, 7], [6], [], [6]]);
<immutable digraph with 7 vertices, 9 edges>
gap> D := DigraphRemoveVertex(G, 7);
<immutable digraph with 6 vertices, 6 edges>
gap> G := DigraphReflexiveTransitiveClosure(G);
<immutable preorder digraph with 7 vertices, 22 edges>
gap> D := DigraphReflexiveTransitiveClosure(D);
<immutable preorder digraph with 6 vertices, 17 edges>
gap> IsDigraphEmbedding(D, G, IdentityTransformation);
true
gap> IsLatticeHomomorphism(D, G, IdentityTransformation);
false
gap> D := Digraph([[2, 3], [4], [4], []]);
<immutable digraph with 4 vertices, 4 edges>
gap> G := Digraph([[2, 3], [4], [4], [5], []]);
<immutable digraph with 5 vertices, 5 edges>
gap> D := DigraphReflexiveTransitiveClosure(D);
<immutable preorder digraph with 4 vertices, 9 edges>
gap> G := DigraphReflexiveTransitiveClosure(G);
<immutable preorder digraph with 5 vertices, 14 edges>
gap> IsLatticeEmbedding(D, G, IdentityTransformation);
true
gap> IsLatticeMonomorphism(D, G, IdentityTransformation);
true
gap> f := Transformation([1, 2, 3, 4, 4]);
Transformation( [ 1, 2, 3, 4, 4 ] )
gap> IsLatticeEpimorphism(G, D, f);
true
gap> IsLatticeEndomorphism(D, (2, 3));
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>
