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

<#GAPDoc Label="IsSubdigraph">
<ManSection>
  <Oper Name="IsSubdigraph" Arg="super, sub"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    If <A>super</A> and <A>sub</A> are digraphs, then this operation returns
    <K>true</K> if <A>sub</A> is a subdigraph of <A>super</A>, and <K>false</K>
    if it is not. <P/>

    A digraph <A>sub</A> is a <E>subdigraph</E> of a digraph <A>super</A> if
    <A>sub</A> and <A>super</A> share the same number of vertices, and the
    collection of edges of <A>super</A> (including repeats) contains the
    collection of edges of <A>sub</A> (including repeats).  <P/>

    In other words, <A>sub</A> is a subdigraph of <A>super</A> if and only if
    <C>DigraphNrVertices(<A>sub</A>) = DigraphNrVertices(<A>super</A>)</C>, and
    for each pair of vertices <C>i</C> and <C>j</C>, there are at least as many
    edges of the form <C>[i, j]</C> in <A>super</A> as there are in <A>sub</A>.
    <P/>

    <Example><![CDATA[
gap> g := Digraph([[2, 3], [1], [2, 3]]);
<digraph with 3 vertices, 5 edges>
gap> h := Digraph([[2, 3], [], [2]]);
<digraph with 3 vertices, 3 edges>
gap> IsSubdigraph(g, h);
true
gap> IsSubdigraph(h, g);
false
gap> IsSubdigraph(CompleteDigraph(4), CycleDigraph(4));
true
gap> IsSubdigraph(CycleDigraph(4), ChainDigraph(4));
true
gap> g := Digraph([[2, 2], [1]]);
<multidigraph with 2 vertices, 3 edges>
gap> h := Digraph([[2], [1]]);
<digraph with 2 vertices, 2 edges>
gap> IsSubdigraph(g, h);
true
gap> IsSubdigraph(h, g);
false]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsUndirectedSpanningTree">
<ManSection>
  <Oper Name="IsUndirectedSpanningTree" Arg="super, sub"/>
  <Oper Name="IsUndirectedSpanningForest" Arg="super, sub"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    The operation <C>IsUndirectedSpanningTree</C> returns <K>true</K> if the
    digraph <A>sub</A> is an undirected spanning tree of the digraph
    <A>super</A>, and the operation <C>IsUndirectedSpanningForest</C> returns
    <K>true</K> if the digraph <A>sub</A> is an undirected spanning forest of
    the digraph <A>super</A>. <P/>

    An <E>undirected spanning tree</E> of a digraph <A>super</A> is a subdigraph
    of <A>super</A> that is an undirected tree (see <Ref Oper="IsSubdigraph" />
    and <Ref Prop="IsUndirectedTree" />). Note that a digraph whose <Ref
      Attr="MaximalSymmetricSubdigraph"/> is not connected has no undirected
    spanning trees (see <Ref Prop="IsConnectedDigraph"/>). <P/>

    An <E>undirected spanning forest</E> of a digraph <A>super</A> is a
    subdigraph of <A>super</A> that is an undirected forest (see <Ref
      Oper="IsSubdigraph"/> and <Ref Prop="IsUndirectedForest"/>), and is not
    contained in any larger such subdigraph of <A>super</A>.  Equivalently, an
    undirected spanning forest is a subdigraph of <A>super</A> whose connected
    components coincide with those of the <Ref
      Attr="MaximalSymmetricSubdigraph"/> of <A>super</A> (see <Ref
      Attr="DigraphConnectedComponents"/>). <P/>

    Note that an undirected spanning tree is an undirected spanning forest that
    is connected.

    <Example><![CDATA[
gap> gr := CompleteDigraph(4);
<digraph with 4 vertices, 12 edges>
gap> tree := Digraph([[3], [4], [1, 4], [2, 3]]);
<digraph with 4 vertices, 6 edges>
gap> IsSubdigraph(gr, tree) and IsUndirectedTree(tree);
true
gap> IsUndirectedSpanningTree(gr, tree);
true
gap> forest := EmptyDigraph(4);
<digraph with 4 vertices, 0 edges>
gap> IsSubdigraph(gr, forest) and IsUndirectedForest(forest);
true
gap> IsUndirectedSpanningForest(gr, forest);
false
gap> IsSubdigraph(tree, forest);
true
gap> gr := DigraphDisjointUnion(CycleDigraph(2), CycleDigraph(2));
<digraph with 4 vertices, 4 edges>
gap> IsUndirectedTree(gr);
false
gap> IsUndirectedForest(gr) and IsUndirectedSpanningForest(gr, gr);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphReverse">
<ManSection>
  <Oper Name="DigraphReverse" Arg="digraph"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>digraph</A> is a digraph, then this operation returns a digraph
    constructed from <A>digraph</A> by reversing the orientation of every edge.
    <Example><![CDATA[
gap> gr := Digraph([[3], [1, 3, 5], [1], [1, 2, 4], [2, 3, 5]]);
<digraph with 5 vertices, 11 edges>
gap> DigraphReverse(gr);
<digraph with 5 vertices, 11 edges>
gap> OutNeighbours(last);
[ [ 2, 3, 4 ], [ 4, 5 ], [ 1, 2, 5 ], [ 4 ], [ 2, 5 ] ]
gap> gr := Digraph([[2, 4], [1], [4], [3, 4]]);
<digraph with 4 vertices, 6 edges>
gap> DigraphEdges(gr);
[ [ 1, 2 ], [ 1, 4 ], [ 2, 1 ], [ 3, 4 ], [ 4, 3 ], [ 4, 4 ] ]
gap> DigraphEdges(DigraphReverse(gr));
[ [ 1, 2 ], [ 2, 1 ], [ 3, 4 ], [ 4, 1 ], [ 4, 3 ], [ 4, 4 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphReverseEdges">
<ManSection>
  <Oper Name="DigraphReverseEdges" Arg="digraph, edges"/>
  <Oper Name="DigraphReverseEdge" Arg="digraph, edge"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>digraph</A> is a digraph without multiple edges,
    and <A>edges</A> is either:

    <List>
      <Item>
        a list of pairs of vertices of <A>digraph</A>
        (the entries of each pair corresponding to
        the source and the range of an edge, respectively),
      </Item>
      <Item>
        a list of positions of elements in the list <Ref Attr="DigraphEdges"/>,
      </Item>
    </List>

    then <C>DigraphReverseEdges</C> returns a new digraph constructed from
    <A>digraph</A> by reversing the orientation of every edge specified by
    <A>edges</A>.  If only one edge is to be reversed, then
    <C>DigraphReverseEdge</C> can be used instead.  In this case, the second
    argument should just be a single vertex-pair or a single position. <P/>

    Note that even though <A>digraph</A> cannot have multiple edges, the
    output may have multiple edges. <P/>
    <Example><![CDATA[
gap> gr := DigraphFromDiSparse6String(".Tg?i@s?t_e?_qEsC");
<digraph with 21 vertices, 8 edges>
gap> DigraphEdges(gr);
[ [ 1, 2 ], [ 1, 7 ], [ 1, 8 ], [ 5, 21 ], [ 7, 19 ], [ 9, 1 ], 
  [ 11, 2 ], [ 21, 1 ] ]
gap> gr2 := DigraphReverseEdges(gr, [1, 2, 4]);
<digraph with 21 vertices, 8 edges>
gap> gr = DigraphReverseEdges(gr2, [[7, 1], [2, 1], [21, 5]]);
true
gap> gr2 := DigraphReverseEdge(gr, 5);
<digraph with 21 vertices, 8 edges>
gap> gr2 = DigraphReverseEdge(gr, [7, 19]);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="OnDigraphs">
<ManSection>
  <Oper Name="OnDigraphs" Arg="digraph, perm"
    Label="for a digraph and a perm"/>
  <Oper Name="OnDigraphs" Arg="digraph, trans"
    Label="for a digraph and a transformation"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>digraph</A> is a digraph, and the second argument <A>perm</A> is a
    <E>permutation</E> of the vertices of <A>digraph</A>, then this operation
    returns a digraph constructed by relabelling the vertices of
    <A>digraph</A> according to <A>perm</A>.  Note that for an automorphism
    <C>f</C> of a digraph, we have <C>OnDigraphs(<A>digraph</A>, f) =
    </C><A>digraph</A>.
    <P/>

    If the second argument is a <E>transformation</E> <A>trans</A> of the
    vertices of <A>digraph</A>, then this operation returns a digraph
    constructed by transforming the source and range of each edge according to
    <A>trans</A>. Thus a vertex which does not appear in the image of
    <A>trans</A> will be isolated in the returned digraph, and the returned
    digraph may contain multiple edges, even if <A>digraph</A> does not.
    If <A>trans</A> is mathematically a permutation, then the result coincides
    with <C>OnDigraphs(<A>digraph</A>, AsPermutation(<A>trans</A>))</C>.
    <P/>

    The <Ref Oper="DigraphVertexLabels"/> of <A>digraph</A> will not be retained
    in the returned digraph. <P/>

    <Example><![CDATA[
gap> gr := Digraph([[3], [1, 3, 5], [1], [1, 2, 4], [2, 3, 5]]);
<digraph with 5 vertices, 11 edges>
gap> new := OnDigraphs(gr, (1, 2));
<digraph with 5 vertices, 11 edges>
gap> OutNeighbours(new);
[ [ 2, 3, 5 ], [ 3 ], [ 2 ], [ 2, 1, 4 ], [ 1, 3, 5 ] ]
gap> gr := Digraph([[2], [], [2]]);
<digraph with 3 vertices, 2 edges>
gap> t := Transformation([1, 2, 1]);;
gap> new := OnDigraphs(gr, t);
<multidigraph with 3 vertices, 2 edges>
gap> OutNeighbours(new);
[ [ 2, 2 ], [  ], [  ] ]
gap> ForAll(DigraphEdges(gr),
>  e -> IsDigraphEdge(new, [e[1] ^ t, e[2] ^ t]));
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="OnMultiDigraphs">
<ManSection>
  <Oper Name="OnMultiDigraphs" Arg="digraph, pair"/>
  <Oper Name="OnMultiDigraphs" Arg="digraph, perm1, perm2" Label="for a digraph, perm, and perm"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>digraph</A> is a digraph, and <A>pair</A> is a pair consisting of a
    permutation of the vertices and a permutation of the edges of
    <A>digraph</A>, then this operation returns a digraph
    constructed by relabelling the vertices and edges of <A>digraph</A> according to
    <A>perm[1]</A> and <A>perm[2]</A>, respectively. <P/>

    In its second form, <C>OnMultiDigraphs</C> returns a digraph with vertices
    and edges permuted by <A>perm1</A> and <A>perm2</A>, respectively. <P/>

    Note that <C>OnDigraphs(<A>digraph</A>,
      perm)=OnMultiDigraphs(<A>digraph</A>, [perm, ()])</C> where <C>perm</C> is
    a permutation of the vertices of <A>digraph</A>. If you are only interested
    in the action of a permutation on the vertices of a digraph, then you can
    use <C>OnDigraphs</C> instead of <C>OnMultiDigraphs</C>.

    <Example><![CDATA[
gap> gr1 := Digraph([
> [3, 6, 3], [], [3], [9, 10], [9], [],  [], [10, 4, 10], [], []]);
<multidigraph with 10 vertices, 10 edges>
gap> p := BlissCanonicalLabelling(gr1);
[ (1,9,5,3,10,6,4,7), (1,7,9,5,2,8,4,10,3,6) ]
gap> gr2 := OnMultiDigraphs(gr1, p);
<multidigraph with 10 vertices, 10 edges>
gap> OutNeighbours(gr2);
[ [  ], [  ], [ 5 ], [  ], [  ], [  ], [ 5, 6 ], [ 6, 7, 6 ], 
  [ 10, 4, 10 ], [ 10 ] ]]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphRemoveLoops">
<ManSection>
  <Oper Name="DigraphRemoveLoops" Arg="digraph"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>digraph</A> is a digraph, then this operation returns a new
    digraph  constructed from <A>digraph</A> by removing every loop. A loop
    is an edge with equal source and range.
    <Example><![CDATA[
gap> gr := Digraph([[1, 2, 4], [1, 4], [3, 4], [1, 4, 5], [1, 5]]);
<digraph with 5 vertices, 12 edges>
gap> DigraphRemoveLoops(gr);
<digraph with 5 vertices, 8 edges>
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphRemoveAllMultipleEdges">
<ManSection>
  <Oper Name="DigraphRemoveAllMultipleEdges" Arg="digraph"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>digraph</A> is a digraph, then this operation returns a new
    digraph  constructed from <A>digraph</A> by removing all multiple edges.
    The result is the largest subdigraph of <A>digraph</A> which does not
    contain multiple edges. <P/>

    <Example><![CDATA[
gap> gr1 := Digraph([[1, 2, 3, 2], [1, 1, 3], [2, 2, 2]]);
<multidigraph with 3 vertices, 10 edges>
gap> gr2 := DigraphRemoveAllMultipleEdges(gr1);
<digraph with 3 vertices, 6 edges>
gap> OutNeighbours(gr2);
[ [ 1, 2, 3 ], [ 1, 3 ], [ 2 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphAddVertex">
<ManSection>
  <Oper Name="DigraphAddVertex" Arg="digraph[, label ]"/>
  <Returns>A digraph.</Returns>
  <Description>
    The operation returns a new digraph constructed from <A>digraph</A> by
    adding a single new vertex. <P/>

    If the optional second argument <A>label</A> is a &GAP; object,
    then the new vertex will be labelled <A>label</A>.
    <P/>
    <Example><![CDATA[
gap> gr := CompleteDigraph(3);
<digraph with 3 vertices, 6 edges>
gap> new := DigraphAddVertex(gr);
<digraph with 4 vertices, 6 edges>
gap> DigraphVertices(new);
[ 1 .. 4 ]
gap> new := DigraphAddVertex(gr, Group([(1, 2)]));
<digraph with 4 vertices, 6 edges>
gap> DigraphVertexLabels(new);
[ 1, 2, 3, Group([ (1,2) ]) ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphAddVertices">
<ManSection>
  <Oper Name="DigraphAddVertices" Arg="digraph, m[, labels ]"/>
  <Returns>A digraph.</Returns>
  <Description>
    For a non-negative integer <A>m</A>, this operation returns a new digraph
    constructed from <A>digraph</A> by adding <A>m</A> new vertices. <P/>

    If the optional third argument <A>labels</A> is a list of length <A>m</A>
    consisting of &GAP; objects, then the new vertices will be
    labelled according to this list. <P/>
    <Example><![CDATA[
gap> gr := CompleteDigraph(3);
<digraph with 3 vertices, 6 edges>
gap> new := DigraphAddVertices(gr, 3);
<digraph with 6 vertices, 6 edges>
gap> DigraphVertices(new);
[ 1 .. 6 ]
gap> new := DigraphAddVertices(gr, 2, [Group([(1, 2)]), "d"]);
<digraph with 5 vertices, 6 edges>
gap> DigraphVertexLabels(new);
[ 1, 2, 3, Group([ (1,2) ]), "d" ]
gap> DigraphAddVertices(gr, 0) = gr;
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphRemoveVertex">
<ManSection>
  <Oper Name="DigraphRemoveVertex" Arg="digraph, v"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>v</A> is a vertex of <A>digraph</A>, then this operation returns a
    new digraph constructed from <A>digraph</A> by removing vertex <A>v</A>,
    along with any edge whose source or range vertex is <A>v</A>. <P/>

    If <A>digraph</A> has <C>n</C> vertices, then the vertices of the new
    digraph are <C>[1..n-1]</C>, but the original labels can be
    accessed via <Ref Oper="DigraphVertexLabels"/>. <P/>

    <Example><![CDATA[
gap> gr := Digraph(["a", "b", "c"],
>                  ["a", "a", "b", "c", "c"],
>                  ["b", "c", "a", "a", "c"]);
<digraph with 3 vertices, 5 edges>
gap> DigraphVertexLabels(gr);
[ "a", "b", "c" ]
gap> DigraphEdges(gr);
[ [ 1, 2 ], [ 1, 3 ], [ 2, 1 ], [ 3, 1 ], [ 3, 3 ] ]
gap> new := DigraphRemoveVertex(gr, 2);
<digraph with 2 vertices, 3 edges>
gap> DigraphVertexLabels(new);
[ "a", "c" ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphRemoveVertices">
<ManSection>
  <Oper Name="DigraphRemoveVertices " Arg="digraph, verts"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>verts</A> is a (possibly empty) duplicate-free list of vertices of
    <A>digraph</A>, then this operation returns a new digraph constructed from
    <A>digraph</A> by removing every vertex in <A>verts</A>, along with any edge
    whose source or range vertex is in <A>verts</A>. <P/>

    If <A>digraph</A> has <C>n</C> vertices, then the vertices of the new
    digraph are <C>[1 .. n-Length(<A>verts</A>)]</C>, but the
    original labels can be accessed via <Ref Oper="DigraphVertexLabels"/>. <P/>

    <Example><![CDATA[
gap> gr := Digraph([[3], [1, 3, 5], [1], [1, 2, 4], [2, 3, 5]]);
<digraph with 5 vertices, 11 edges>
gap> SetDigraphVertexLabels(gr, ["a", "b", "c", "d", "e"]);
gap> new := DigraphRemoveVertices(gr, [2, 4]);
<digraph with 3 vertices, 4 edges>
gap> DigraphVertexLabels(new);
[ "a", "c", "e" ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphAddEdge">
<ManSection>
  <Oper Name="DigraphAddEdge" Arg="digraph, edge"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>edge</A> is a pairs of vertices of <A>digraph</A>,
    then this operation returns a new digraph constructed from <A>digraph</A>
    by adding a new edge with source <A>edge</A><C>[1]</C> and range
    <A>edge</A><C>[2]</C>. <P/>

    <Example><![CDATA[
gap> gr1 := Digraph([[2], [3], []]);
<digraph with 3 vertices, 2 edges>
gap> DigraphEdges(gr1);
[ [ 1, 2 ], [ 2, 3 ] ]
gap> gr2 := DigraphAddEdge(gr1, [3, 1]);
<digraph with 3 vertices, 3 edges>
gap> DigraphEdges(gr2);
[ [ 1, 2 ], [ 2, 3 ], [ 3, 1 ] ]
gap> gr3 := DigraphAddEdge(gr2, [2, 3]);
<multidigraph with 3 vertices, 4 edges>
gap> DigraphEdges(gr3);
[ [ 1, 2 ], [ 2, 3 ], [ 2, 3 ], [ 3, 1 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphAddEdges">
<ManSection>
  <Oper Name="DigraphAddEdges" Arg="digraph, edges"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>edges</A> is a (possibly empty) list of pairs of vertices of
    <A>digraph</A>, then this operation returns a new digraph constructed from
    <A>digraph</A> by adding the edges specified by <A>edges</A>.  More
    precisely, for every <C>edge</C> in <A>edges</A>, a new edge
    will be added with source <C>edge[1]</C> and range <C>edges[2]</C>.
    <P/>

    If an edge is included in <A>edges</A> with multiplicity <C>k</C>,
    then it will be added <C>k</C> times.

    <Example><![CDATA[
gap> func := function(n)
>  local source, range, i;
>  source := [];
>  range  := [];
>  for i in [1 .. n - 2] do
>    Add(source, i);
>    Add(range, i + 1);
>  od;
>  return Digraph(n, source, range);
> end;;
gap> gr := func(1024);
<digraph with 1024 vertices, 1022 edges>
gap> gr := DigraphAddEdges(gr,
> [[1023, 1024], [1, 1024], [1023, 1024], [1024, 1]]);
<multidigraph with 1024 vertices, 1026 edges>]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphRemoveEdges">
<ManSection>
  <Oper Name="DigraphRemoveEdges" Arg="digraph, edges"/>
  <Returns>A digraph.</Returns>
  <Description>
    If one of the following holds:
    <List>
      <Item>
        <A>digraph</A> is a digraph with no multiple edges, and
        <A>edges</A> is a list of pairs of vertices of <A>digraph</A>, or
      </Item>
      <Item>
        <A>digraph</A> is any digraph and <A>edges</A> is a list of
        indices of edges of <A>digraph</A>,
      </Item>
    </List>

    then this operation returns a new digraph constructed from <A>digraph</A>
    by removing all of the edges specified by <A>edges</A>
    [see <Ref Oper="DigraphRemoveEdge"/>]. <P/>

    <Example><![CDATA[
gap> gr := CycleDigraph(250000);
<digraph with 250000 vertices, 250000 edges>
gap> gr := DigraphRemoveEdges(gr, [[250000, 1]]);
<digraph with 250000 vertices, 249999 edges>
gap> gr := DigraphRemoveEdges(gr, [10]);
<digraph with 250000 vertices, 249998 edges>]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphRemoveEdge">
<ManSection>
  <Oper Name="DigraphRemoveEdge" Arg="digraph, edge"/>
  <Returns>A digraph.</Returns>
  <Description>
    If one of the following holds:
    <List>
      <Item>
        <A>digraph</A> is a digraph with no multiple edges, and
        <A>edge</A> is a pair of vertices of <A>digraph</A>, or
      </Item>
      <Item>
        <A>digraph</A> is any digraph and <A>edge</A> is the index of
        an edge of <A>digraph</A>,
      </Item>
    </List>

    then this operation returns a new digraph constructed from <A>digraph</A>
    by removing the edges specified by <A>edges</A>. If, in the first case,
    the pair of vertices <A>edge</A> does not specify an edge of <A>digraph</A>,
    then a new copy of <A>digraph</A> will be returned.<P/>

    <Example><![CDATA[
gap> gr := CycleDigraph(250000);
<digraph with 250000 vertices, 250000 edges>
gap> gr := DigraphRemoveEdge(gr, [250000, 1]);
<digraph with 250000 vertices, 249999 edges>
gap> gr := DigraphRemoveEdge(gr, 10);
<digraph with 250000 vertices, 249998 edges>]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphReflexiveTransitiveReduction">
<ManSection>
  <Oper Name="DigraphReflexiveTransitiveReduction" Arg="digraph"/>
  <Oper Name="DigraphTransitiveReduction" Arg="digraph"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>digraph</A> is a topologically sortable digraph
    [see <Ref Attr="DigraphTopologicalSort"/>]
    with no multiple edges, then these  operations return the
    (reflexive) transitive reduction of <A>digraph</A>.
    <P/>

    The (reflexive) transitive reduction of such a digraph is the unique
    least subgraph such that the (reflexive) transitive closure of the
    subgraph is equal to the (reflexive) transitive closure of <A>digraph</A>
    [see <Ref Attr="DigraphReflexiveTransitiveClosure"/>].
    In order words, it is the least subgraph of <A>digraph</A> which
    retains the same reachability as <A>digraph</A>. <P/>

    Let <M>n</M> be the number of vertices of an arbitrary digraph, and let
        <M>m</M> be the number of edges.
    Then these operations
    use methods with complexity <M>O(m + n + m \cdot n)</M>.
    <P/>
    <Example><![CDATA[
gap> gr := Digraph([[1, 2, 3], [3], [3]]);;
gap> DigraphHasLoops(gr);
true
gap> gr1 := DigraphReflexiveTransitiveReduction(gr);
<digraph with 3 vertices, 2 edges>
gap> DigraphHasLoops(gr1);
false
gap> OutNeighbours(gr1);
[ [ 2 ], [ 3 ], [  ] ]
gap> gr2 := DigraphTransitiveReduction(gr);
<digraph with 3 vertices, 4 edges>
gap> DigraphHasLoops(gr2);
true
gap> OutNeighbours(gr2);
[ [ 2, 1 ], [ 3 ], [ 3 ] ]
gap> DigraphReflexiveTransitiveClosure(gr)
>  = DigraphReflexiveTransitiveClosure(gr1);
true
gap> DigraphTransitiveClosure(gr)
>  = DigraphTransitiveClosure(gr2);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="InducedSubdigraph">
<ManSection>
  <Oper Name="InducedSubdigraph" Arg="digraph, verts"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>digraph</A> is a digraph, and <A>verts</A> is a subset of the
    vertices of <A>digraph</A>, then this operation returns a digraph
    constructed from <A>digraph</A> by retaining precisely those vertices in
    <A>verts</A>, and those edges whose source and range vertices are both
    contained in <A>verts</A>. <P/>

    The vertices of the induced subdigraph are
    <C>[1..Length(verts)]</C> but the original vertex labels can be
    accessed via <Ref Oper="DigraphVertexLabels"/>. <P/>

    <Example><![CDATA[
gap> gr := Digraph([[1, 1, 2, 3, 4, 4], [1, 3, 4], [3, 1], [1, 1]]);
<multidigraph with 4 vertices, 13 edges>
gap> InducedSubdigraph(gr, [1, 3, 4]);
<multidigraph with 3 vertices, 9 edges>
gap> DigraphVertices(last);
[ 1 .. 3 ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="OutDegreeOfVertex">
<ManSection>
  <Oper Name="OutDegreeOfVertex" Arg="digraph, vertex"/>
  <Returns>The non-negative integer.</Returns>
  <Description>
    This operation returns the out-degree of the vertex <A>vertex</A> in the
    digraph <A>digraph</A>.
    The out-degree of <A>vertex</A> is the number of edges in <A>digraph</A>
    whose source is <A>vertex</A>.
    <P/>
    <Example><![CDATA[
gap> gr := Digraph([
> [2, 2, 1], [1, 4], [2, 2, 4, 2], [1, 1, 2, 2, 1, 2, 2]]);
<multidigraph with 4 vertices, 16 edges>
gap> OutDegreeOfVertex(gr, 1);
3
gap> OutDegreeOfVertex(gr, 2);
2
gap> OutDegreeOfVertex(gr, 3);
4
gap> OutDegreeOfVertex(gr, 4);
7
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="OutNeighboursOfVertex">
<ManSection>
  <Oper Name="OutNeighboursOfVertex" Arg="digraph, vertex"/>
  <Oper Name="OutNeighborsOfVertex" Arg="digraph, vertex"/>
  <Returns>A list of vertices.</Returns>
  <Description>

    This operation returns the list <C>out</C> of vertices of the digraph
    <A>digraph</A>.
    A vertex <C>i</C> appears in the list <C>out</C> each time there exists an
    edge  with source <A>vertex</A> and range <C>i</C> in <A>digraph</A>; in
    particular, this means that <C>out</C> may contain duplicates.<P/>
    <Example><![CDATA[
gap> gr := Digraph([
> [2, 2, 3], [1, 3, 4], [2, 2, 3], [1, 1, 2, 2, 1, 2, 2]]);
<multidigraph with 4 vertices, 16 edges>
gap> OutNeighboursOfVertex(gr, 1);
[ 2, 2, 3 ]
gap> OutNeighboursOfVertex(gr, 3);
[ 2, 2, 3 ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="InDegreeOfVertex">
<ManSection>
  <Oper Name="InDegreeOfVertex" Arg="digraph, vertex"/>
  <Returns>A non-negative integer.</Returns>
  <Description>
    This operation returns the in-degree of the vertex <A>vertex</A> in the
    digraph <A>digraph</A>.
    The in-degree of <A>vertex</A> is the number of edges in <A>digraph</A>
    whose range is <A>vertex</A>.
    <Example><![CDATA[
gap> gr := Digraph([
> [2, 2, 1], [1, 4], [2, 2, 4, 2], [1, 1, 2, 2, 1, 2, 2]]);
<multidigraph with 4 vertices, 16 edges>
gap> InDegreeOfVertex(gr, 1);
5
gap> InDegreeOfVertex(gr, 2);
9
gap> InDegreeOfVertex(gr, 3);
0
gap> InDegreeOfVertex(gr, 4);
2
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="InNeighboursOfVertex">
<ManSection>
  <Oper Name="InNeighboursOfVertex" Arg="digraph, vertex"/>
  <Oper Name="InNeighborsOfVertex" Arg="digraph, vertex"/>
  <Returns>A list of postitive vertices.</Returns>
  <Description>

    This operation returns the list <C>inn</C> of vertices of the digraph
    <A>digraph</A>.
    A vertex <C>i</C> appears in the list <C>inn</C> each time there exists an
    edge  with source <C>i</C> and range <A>vertex</A> in <A>digraph</A>; in
    particular, this means that <C>inn</C> may contain duplicates. <P/>

    <Example><![CDATA[
gap> gr := Digraph([
> [2, 2, 3], [1, 3, 4], [2, 2, 3], [1, 1, 2, 2, 1, 2, 2]]);
<multidigraph with 4 vertices, 16 edges>
gap> InNeighboursOfVertex(gr, 1);
[ 2, 4, 4, 4 ]
gap> InNeighboursOfVertex(gr, 2);
[ 1, 1, 3, 3, 4, 4, 4, 4 ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphInEdges">
<ManSection>
  <Oper Name="DigraphInEdges" Arg="digraph, vertex"/>
  <Returns>A list of edges.</Returns>
  <Description>
    <C>DigraphInEdges</C> returns the list of all edges of <A>digraph</A>
    which have <A>vertex</A> as their range.
    <Example><![CDATA[
gap> gr := Digraph([[2, 2], [3, 3], [4, 4], [1, 1]]);
<multidigraph with 4 vertices, 8 edges>
gap> DigraphInEdges(gr, 2);
[ [ 1, 2 ], [ 1, 2 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphOutEdges">
<ManSection>
  <Oper Name="DigraphOutEdges" Arg="digraph, vertex"/>
  <Returns>A list of edges.</Returns>
  <Description>
    <C>DigraphOutEdges</C> returns the list of all edges of <A>digraph</A>
    which have <A>vertex</A> as their source.
    <Example><![CDATA[
gap> gr := Digraph([[2, 2], [3, 3], [4, 4], [1, 1]]);
<multidigraph with 4 vertices, 8 edges>
gap> DigraphOutEdges(gr, 2);
[ [ 2, 3 ], [ 2, 3 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphStronglyConnectedComponent">
<ManSection>
  <Oper Name="DigraphStronglyConnectedComponent" Arg="digraph, vertex"/>
  <Returns>A list of vertices.</Returns>
  <Description>
    If <A>vertex</A> is a vertex in the digraph <A>digraph</A>, then
    this operation returns the strongly connected component of <A>vertex</A>
    in <A>digraph</A>.
    See <Ref Attr="DigraphStronglyConnectedComponents"/> for more information.
    <Example><![CDATA[
gap> gr := Digraph([[3], [2], [1, 2], [3]]);
<digraph with 4 vertices, 5 edges>
gap> DigraphStronglyConnectedComponent(gr, 3);
[ 1, 3 ]
gap> DigraphStronglyConnectedComponent(gr, 2);
[ 2 ]
gap> DigraphStronglyConnectedComponent(gr, 4);
[ 4 ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphConnectedComponent">
<ManSection>
  <Oper Name="DigraphConnectedComponent" Arg="digraph, vertex"/>
  <Returns>A list of vertices.</Returns>
  <Description>
    If <A>vertex</A> is a vertex in the digraph <A>digraph</A>, then
    this operation returns the connected component of <A>vertex</A>
    in <A>digraph</A>.
    See <Ref Attr="DigraphConnectedComponents"/> for more information.
    <Example><![CDATA[
gap> gr := Digraph([[3], [2], [1, 2], [4]]);
<digraph with 4 vertices, 5 edges>
gap> DigraphConnectedComponent(gr, 3);
[ 1, 2, 3 ]
gap> DigraphConnectedComponent(gr, 2);
[ 1, 2, 3 ]
gap> DigraphConnectedComponent(gr, 4);
[ 4 ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="QuotientDigraph">
<ManSection>
  <Oper Name="QuotientDigraph" Arg="digraph, p"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>digraph</A> is a digraph, and <A>p</A> is a partition of the vertices
    of <A>digraph</A>, then this operation returns a new digraph constructed by
    amalgamating all vertices of <A>digraph</A> which lie in the same part of
    <A>p</A>.
    <P/>

    A partition of the vertices of <A>digraph</A> is a list of non-empty
    disjoint lists, such that the union of all the sub-lists is equal
    to the vertex set of <A>digraph</A>. In particular, each vertex must appear
    in precisely one sub-list.
    <P/>

    The vertices of <A>digraph</A> in part <C>i</C> of <A>p</A> will become
    vertex <C>i</C> in the quotient, and every edge of <A>digraph</A>
    with source in part <C>i</C> and range in part <C>j</C> becomes an edge
    from <C>i</C> to <C>j</C> in the quotient. In particular, this means that
    the quotient of a digraph without multiple edges can have multiple edges.
    <P/>

    <Example><![CDATA[
gap> gr := Digraph([[2, 1], [4], [1], [1, 3, 4]]);
<digraph with 4 vertices, 7 edges>
gap> DigraphVertices(gr);
[ 1 .. 4 ]
gap> DigraphEdges(gr);
[ [ 1, 2 ], [ 1, 1 ], [ 2, 4 ], [ 3, 1 ], [ 4, 1 ], [ 4, 3 ], 
  [ 4, 4 ] ]
gap> p := [[1], [2, 4], [3]];
[ [ 1 ], [ 2, 4 ], [ 3 ] ]
gap> qr := QuotientDigraph(gr, p);
<multidigraph with 3 vertices, 7 edges>
gap> DigraphVertices(qr);
[ 1 .. 3 ]
gap> DigraphEdges(qr);
[ [ 1, 2 ], [ 1, 1 ], [ 2, 2 ], [ 2, 1 ], [ 2, 3 ], [ 2, 2 ], 
  [ 3, 1 ] ]
gap> QuotientDigraph(EmptyDigraph(0), []);
<digraph with 0 vertices, 0 edges>
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsDigraphEdge">
<ManSection>
  <Oper Name="IsDigraphEdge" Arg="digraph, list"
        Label="for digraph and list"/>
  <Oper Name="IsDigraphEdge" Arg="digraph, u, v"
        Label="for digraph and two pos ints"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    In the first form, this function returns <K>true</K> if and only if the list
    <A>list</A> specifies an edge in the digraph <A>digraph</A>.  Specifically,
    this operation returns <K>true</K> if <A>list</A> is a pair of positive
    integers where <A>list</A><C>[1]</C> is the source and <A>list</A><C>[2]</C>
    is the range of an edge in <A>digraph</A>, and <K>false</K> otherwise. <P/>

    The second form simply returns <K>true</K> if <C>[<A>u</A>, <A>v</A>]</C> is
    an edge in <A>digraph</A>, and <K>false</K> otherwise.

<Example><![CDATA[
gap> gr := Digraph([[2, 2], [6], [], [3], [], [1]]);
<multidigraph with 6 vertices, 5 edges>
gap> IsDigraphEdge(gr, [1, 1]);
false
gap> IsDigraphEdge(gr, [1, 2]);
true
gap> IsDigraphEdge(gr, [1, 8]);
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphFloydWarshall">
<ManSection>
  <Oper Name="DigraphFloydWarshall" Arg="digraph, func, nopath, edge"/>
  <Returns>A matrix.</Returns>
  <Description>
    If <A>digraph</A> is a digraph with <M>n</M> vertices, then
    this operation returns an <M>n \times n</M> matrix <C>mat</C> containing
    the output of a generalised version of the Floyd-Warshall algorithm,
    applied to <A>digraph</A>. <P/>

    The operation <C>DigraphFloydWarshall</C> is customised by the arguments
    <A>func</A>, <A>nopath</A>, and <A>edge</A>.
    The arguments <A>nopath</A> and <A>edge</A> can be arbitrary &GAP; objects.
    The argument <A>func</A> must be a function which accepts 4 arguments:
    the matrix <C>mat</C>, followed by 3 postive integers. The function
    <A>func</A> is where the work to calculate the desired outcome must be
    performed. <P/>

    This method initialises the matrix <C>mat</C> by setting entry
    <C>mat[i][j]</C> to equal <A>edge</A> if there is an edge with source
    <C>i</C> and range <C>j</C>, and by setting entry <C>mat[i][j]</C> to equal
    <A>nopath</A> otherwise.
    The final part of <C>DigraphFloydWarshall</C> then calls the function
    <A>func</A> inside three nested for loops, over the vertices of
    <A>digraph</A>: <P/>

<Listing><![CDATA[
for i in DigraphsVertices(digraph) do
  for j in DigraphsVertices(digraph) do
    for k in DigraphsVertices(digraph) do
      func(mat, i, j, k);
    od;
  od;
od;
]]></Listing>

    The matrix <C>mat</C> is then returned as the result. An example of using
    <C>DigraphFloydWarshall</C> to calculate the shortest (non-zero) distances
    between the vertices of a digraph is shown below: <P/>

    <Example><![CDATA[
gap> gr := DigraphFromDigraph6String("&EAHQeDB");
<digraph with 6 vertices, 12 edges>
gap> func := function(mat, i, j, k)
>   if mat[i][k] <> -1 and mat[k][j] <> -1 then
>     if (mat[i][j] = -1) or (mat[i][j] > mat[i][k] + mat[k][j]) then
>       mat[i][j] := mat[i][k] + mat[k][j];
>     fi;
>   fi;
> end;
function( mat, i, j, k ) ... end
gap> shortest_distances := DigraphFloydWarshall(gr, func, -1, 1);;
gap> Display(shortest_distances);
[ [   3,  -1,  -1,   2,   1,   2 ],
  [   4,   2,   1,   3,   2,   1 ],
  [   3,   1,   2,   2,   1,   2 ],
  [   1,  -1,  -1,   1,   1,   2 ],
  [   2,  -1,  -1,   1,   2,   1 ],
  [   3,  -1,  -1,   2,   1,   1 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="AsBinaryRelation">
<ManSection>
  <Oper Name="AsBinaryRelation" Arg="digraph"/>
  <Returns>A binary relation.</Returns>
  <Description>
    If <A>digraph</A> is a digraph with a positive number of vertices
    <M>n</M>, and no multiple edges, then this operation returns a binary
    relation on the points <C>[1..n]</C>.
    The pair <C>[i,j]</C> is in the binary relation if and only if
    <C>[i,j]</C> is an edge in <A>digraph</A>.
    <P/>
<Example><![CDATA[
gap> gr := Digraph([[3, 2], [1, 2], [2], [3, 4]]);
<digraph with 4 vertices, 7 edges>
gap> AsBinaryRelation(gr);
Binary Relation on 4 points
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphEdgeUnion">
<ManSection>
  <Func Name="DigraphEdgeUnion" Arg="gr1, gr2, ..." Label="for an arbitrary
    number of digraphs"/>
  <Func Name="DigraphEdgeUnion" Arg="list" Label="for a list of digraphs"/>
  <Returns>A digraph.</Returns>
  <Description>
    In the first form, if <A>gr1</A>, <A>gr2</A>, etc. are digraphs, then
    <C>DigraphEdgeUnion</C> returns their edge union.

    In the second form, if <A>list</A> is a non-empty list of digraphs, then
    <C>DigraphEdgeUnion</C> returns the edge union of the digraphs contained
    in the list.  <P/>

    The vertex set of the edge union of a collection of digraphs is the
    <E>union</E> of the vertex sets, whilst the edge list of the edge union is
    the <E>concatenation</E> of the edge lists.  The number of vertices of the
    edge union is equal to the <E>maximum</E> number of vertices of one of the
    digraphs, whilst the number of edges of the edge union will equal the
    <E>sum</E> of the number of edges of each digraph. <P/>

    Note that previously set <Ref Oper="DigraphVertexLabels"/> will be lost.

<Example><![CDATA[
gap> gr := CycleDigraph(10);
<digraph with 10 vertices, 10 edges>
gap> DigraphEdgeUnion(gr, gr);
<multidigraph with 10 vertices, 20 edges>
gap> gr1 := Digraph([[2], [1]]);
<digraph with 2 vertices, 2 edges>
gap> gr2 := Digraph([[2, 3], [2], [1]]);
<digraph with 3 vertices, 4 edges>
gap> union := DigraphEdgeUnion(gr1, gr2);
<multidigraph with 3 vertices, 6 edges>
gap> OutNeighbours(union);
[ [ 2, 2, 3 ], [ 1, 2 ], [ 1 ] ]
gap> union = DigraphByEdges(
> Concatenation(DigraphEdges(gr1), DigraphEdges(gr2)));
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphDisjointUnion">
<ManSection>
  <Func Name="DigraphDisjointUnion" Arg="gr1, gr2, ..." Label="for an
    arbitrary number of digraphs"/>
  <Func Name="DigraphDisjointUnion" Arg="list" Label="for a list of digraphs"/>
  <Returns>A digraph.</Returns>
  <Description>
    In the first form, if <A>gr1</A>, <A>gr2</A>, etc. are digraphs, then
    <C>DigraphDisjointUnion</C> returns their disjoint union.

    In the second form, if <A>list</A> is a non-empty list of digraphs, then
    <C>DigraphDisjointUnion</C> returns the disjoint union of the digraphs
    contained in the list.  <P/>

    For a disjoint union of digraphs, the vertex set is the disjoint union of
    the vertex sets, and the edge list is the disjoint union of the edge lists.
    <P/>

    More specifically, for a collection of digraphs <A>gr1</A>, <A>gr2</A>,
    <C>...</C>, the disjoint union with have
    <C>DigraphNrVertices(</C><A>gr1</A><C>)</C> <C>+</C>
    <C>DigraphNrVertices(</C><A>gr2</A><C>)</C> <C>+</C> <C>...</C> vertices.
    The edges of <A>gr1</A> will remain unchanged, whilst the edges of the
    <C>i</C>th digraph, <A>gr</A><C>[i]</C>, will be changed so that they
    belong to the vertices of the disjoint union corresponding to
    <A>gr</A><C>[i]</C>.  In particular, the edges of <A>gr</A><C>[i]</C> will
    have their source and range increased by
    <C>DigraphNrVertices(</C><A>gr1</A><C>)</C> <C>+</C> <C>...</C> <C>+</C>
    <C>DigraphNrVertices(</C><A>gr</A><C>[i-1])</C>.

    <P/>

    Note that previously set <Ref Oper="DigraphVertexLabels"/> will be lost.

<Example><![CDATA[
gap> gr1 := CycleDigraph(3);
<digraph with 3 vertices, 3 edges>
gap> OutNeighbours(gr1);
[ [ 2 ], [ 3 ], [ 1 ] ]
gap> gr2 := CompleteDigraph(3);
<digraph with 3 vertices, 6 edges>
gap> OutNeighbours(gr2);
[ [ 2, 3 ], [ 1, 3 ], [ 1, 2 ] ]
gap> union := DigraphDisjointUnion(gr1, gr2);
<digraph with 6 vertices, 9 edges>
gap> OutNeighbours(union);
[ [ 2 ], [ 3 ], [ 1 ], [ 5, 6 ], [ 4, 6 ], [ 4, 5 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphJoin">
<ManSection>
  <Func Name="DigraphJoin" Arg="gr1, gr2, ..." Label="for an arbitrary number
    of digraphs"/>
  <Func Name="DigraphJoin" Arg="list" Label="for a list of digraphs"/>
  <Returns>A digraph.</Returns>
  <Description>
    In the first form, if <A>gr1</A>, <A>gr2</A>, etc. are digraphs, then
    <C>DigraphJoin</C> returns their join.

    In the second form, if <A>list</A> is a non-empty list of digraphs,
    then <C>DigraphJoin</C> returns the join of the digraphs contained in the
    list. <P/>

    The join of a collection of digraphs <A>gr1</A>, <A>gr2</A>, <C>...</C> is
    formed by first taking the <Ref Func="DigraphDisjointUnion"
      Label="for a list of digraphs"/> of the collection.

    In the disjoint union, if <M>i \neq j</M> then there are no edges between
    vertices corresponding to digraphs <A>gr</A><C>[i]</C> and
    <A>gr</A><C>[j]</C> in the collection; the join is created by including
    all such edges.

    <P/>

    For example, the join of two empty digraphs is a complete bipartite
    digraph.

    <P/>

    Note that previously set <Ref Oper="DigraphVertexLabels"/> will be lost.

<Example><![CDATA[
gap> gr := CompleteDigraph(3);
<digraph with 3 vertices, 6 edges>
gap> IsCompleteDigraph(DigraphJoin(gr, gr));
true
gap> gr2 := CycleDigraph(3);
<digraph with 3 vertices, 3 edges>
gap> DigraphJoin(gr, gr2);
<digraph with 6 vertices, 27 edges>
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsReachable">
<ManSection>
  <Oper Name="IsReachable" Arg="digraph, u, v"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This operation returns <K>true</K> if there exists a non-trivial directed
    walk from vertex <A>u</A> to vertex <A>v</A> in the digraph <A>digraph</A>,
    and <K>false</K> if there does not exist such a directed walk.  See section
    <Ref Subsect="Definitions" Style="Number" /> for the definition of a
    non-trivial directed walk.
    <P/>

    The method for <C>IsReachable</C> has worst case complexity of <M>O(m +
      n)</M> where <M>m</M> is the number of edges and <M>n</M> the number of
    vertices in <A>digraph</A>.

<Example><![CDATA[
gap> gr := Digraph([[2], [3], [2, 3]]);
<digraph with 3 vertices, 4 edges>
gap> IsReachable(gr, 1, 3);
true
gap> IsReachable(gr, 2, 1);
false
gap> IsReachable(gr, 3, 3);
true
gap> IsReachable(gr, 1, 1);
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphPath">
<ManSection>
  <Oper Name="DigraphPath" Arg="digraph, u, v"/>
  <Returns>A pair of lists, or <K>fail</K>.</Returns>
  <Description>
    If there exists a non-trivial directed path (or a non-trivial cycle, in the
    case that <A>u</A> <C>=</C> <A>v</A>) from vertex <A>u</A> to vertex
    <A>v</A> in the digraph <A>digraph</A>, then this operation returns such a
    directed path (or directed cycle). Otherwise, this operation returns
    <K>fail</K>.  See Section <Ref Subsect="Definitions" Style="Text"/> for the
    definition of a directed path and a directed cycle.
    <P/>

    A directed path (or directed cycle) of non-zero length <C>n-1</C>,
    <M>(v_1, e_1, v_2, e_2, ..., e_{n-1}, v_n)</M>,
    is represented by a pair of lists <C>[v,a]</C> as follows:

    <List>
      <Item>
        <C>v</C> is the list <M>[v_1, v_2, ..., v_n]</M>.
      </Item>
      <Item>
        <C>a</C> is the list of positive integers <M>[a_1, a_2, ..., a_{n-1}]</M>
        where for each each <M>i &lt; n</M>, <M>a_i</M> is the position of
        <M>v_{i+1}</M> in
        <C>OutNeighboursOfVertex(</C><A>digraph</A><C>,</C><M>v_i</M><C>)</C>
        corresponding to the edge <M>e_i</M>.  This is can be useful if the
        position of a vertex in a list of out-neighours is significant, for
        example in orbit digraphs.
      </Item>
    </List>

    The method for <C>DigraphPath</C> has worst case complexity of <M>O(m +
      n)</M> where <M>m</M> is the number of edges and <M>n</M> the number of
    vertices in <A>digraph</A>.

<Example><![CDATA[
gap> gr := Digraph([[2], [3], [2, 3]]);
<digraph with 3 vertices, 4 edges>
gap> DigraphPath(gr, 1, 3);
[ [ 1, 2, 3 ], [ 1, 1 ] ]
gap> DigraphPath(gr, 2, 1);
fail
gap> DigraphPath(gr, 3, 3);
[ [ 3, 3 ], [ 2 ] ]
gap> DigraphPath(gr, 1, 1);
fail
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphShortestPath">
<ManSection>
  <Oper Name="DigraphShortestPath" Arg="digraph, u, v"/>
  <Returns>A pair of lists, or <K>fail</K>.</Returns>
  <Description>
    Returns the shortest directed path in the digraph digraph from the vertex u to the vertex v, if such a path exists. If u = v, then the shortest non-trivial cycle is returned, again, if it exists. Otherwise, this operation returns
    <K>fail</K>.  See Section <Ref Subsect="Definitions" Style="Text"/> for the
    definition of a directed path and a directed cycle.
    <P/>

    See <Ref Oper="DigraphPath"/> for details on the output.

    The method for <C>DigraphShortestPath</C> has worst case complexity of <M>O(m +
      n)</M> where <M>m</M> is the number of edges and <M>n</M> the number of
    vertices in <A>digraph</A>.

<Example><![CDATA[
gap> gr := Digraph([[1, 2], [3], [2, 4], [1], [2, 4]]);
<digraph with 5 vertices, 8 edges>
gap> DigraphShortestPath(gr, 5, 1);
[ [ 5, 4, 1 ], [ 2, 1 ] ]
gap> DigraphShortestPath(gr, 3, 3);
[ [ 3, 2, 3 ], [ 1, 1 ] ]
gap> DigraphShortestPath(gr, 5, 5);
fail
gap> DigraphShortestPath(gr, 1, 1);
[ [ 1, 1 ], [ 1 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IteratorOfPaths">
<ManSection>
  <Oper Name="IteratorOfPaths" Arg="digraph, u, v"/>
  <Returns>An iterator.</Returns>
  <Description>
    If <A>digraph</A> is a digraph or a list of adjacencies which defines a
    digraph - see <Ref Attr="OutNeighbours"/> - then this operation returns an
    iterator of the non-trivial directed paths (or directed cycles, in the case
    that <A>u</A> <C>=</C> <A>v</A>) in <A>digraph</A> from the vertex <A>u</A>
    to the vertex <A>v</A>.
    <P/>

    See <Ref Oper="DigraphPath"/> for more information about the repesentation
    of a directed path or directed cycle which is used, and see <Ref
      Sect="Iterators" BookName="ref"/> for more information about iterators.
    See Section <Ref Subsect="Definitions" Style="Text"/> for the definition of
    a directed path and a directed cycle.
    <P/>

<Example><![CDATA[
gap> gr := Digraph([[1, 4, 4, 2], [3, 5], [2, 3], [1, 2], [4]]);
<multidigraph with 5 vertices, 11 edges>
gap> iter := IteratorOfPaths(gr, 1, 4);
<iterator>
gap> NextIterator(iter);
[ [ 1, 4 ], [ 2 ] ]
gap> NextIterator(iter);
[ [ 1, 4 ], [ 3 ] ]
gap> NextIterator(iter);
[ [ 1, 2, 5, 4 ], [ 4, 2, 1 ] ]
gap> IsDoneIterator(iter);
true
gap> iter := IteratorOfPaths(gr, 4, 3);
<iterator>
gap> NextIterator(iter);
[ [ 4, 1, 2, 3 ], [ 1, 4, 1 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphLongestDistanceFromVertex">
<ManSection>
  <Oper Name="DigraphLongestDistanceFromVertex" Arg="digraph, v"/>
  <Returns>An integer, or <K>infinity</K>.</Returns>
  <Description>
    If <A>digraph</A> is a digraph and <A>v</A> is a vertex in <A>digraph</A>,
    then this operation returns the length of the longest directed walk in
    <A>digraph</A> which begins at vertex <A>v</A>.  See section <Ref
      Subsect="Definitions" Style="Number" /> for the definitions of directed
    walk, directed cycle, and loop.
    <P/>

    <List>
      <Item>
        If there exists a directed walk starting at vertex <A>v</A>
        which traverses a loop or a directed cycle,
        then we consider there to be a walk of infinite length from <A>v</A>
        (realised by repeatedly traversing the loop/directed cycle),
        and so the result is <K>infinity</K>.
        To disallow walks using loops, try using
        <Ref Oper="DigraphRemoveLoops"/>:<P/>

        <C>DigraphLongestDistanceFromVertex(DigraphRemoveLoops(<A>digraph</A>,<A>v</A>))</C>.
      </Item>

      <Item>
        Otherwise, if all directed walks
        starting at vertex <A>v</A> have finite length,
        then the length of the longest such walk is returned.
      </Item>
    </List>

    Note that the result is <C>0</C> if and only if <A>v</A> is a sink of
    <A>digraph</A>.  See <Ref Attr="DigraphSinks"/>.

<Example><![CDATA[
gap> gr := Digraph([[2], [3, 4], [], [5], [], [6]]);
<digraph with 6 vertices, 5 edges>
gap> DigraphLongestDistanceFromVertex(gr, 1);
3
gap> DigraphLongestDistanceFromVertex(gr, 3);
0
gap> 3 in DigraphSinks(gr);
true
gap> DigraphLongestDistanceFromVertex(gr, 6);
infinity
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphLayers">
<ManSection>
  <Oper Name="DigraphLayers" Arg="digraph, vertex"/>
  <Returns>A list.</Returns>
  <Description>
    This operation returns a list <K>list</K> such that <K>list[i]</K> is the
    list of vertices whose minimum distance from the vertex <A>vertex</A> in
    <A>digraph</A> is <K>i - 1</K>. Vertex <A>vertex</A> is
    assumed to be at distance <K>0</K> from itself.
    <Example><![CDATA[
gap> gr := CompleteDigraph(4);;
gap> DigraphLayers(gr, 1);
[ [ 1 ], [ 2, 3, 4 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphDistanceSet">
<ManSection>
  <Oper Name="DigraphDistanceSet" Label="for a digraph, a pos int, and an int" Arg="digraph, vertex, distance"/>
  <Oper Name="DigraphDistanceSet" Label="for a digraph, a pos int, and a list" Arg="digraph, vertex, distances"/>
  <Returns>A list of vertices</Returns>
  <Description>
    This operation returns the list of all vertices in digraph <A>digraph</A>
    such that the shortest distance to a vertex <A>vertex</A> is
    <A>distance</A> or is in the list <A>distances</A>. <P/>

    <A>digraph</A> should be a digraph, <A>vertex</A> should be a positive
    integer, <A>distance</A> should be a non-negative integer, and
    <A>distances</A> should be a list of non-negative integers.

    <Example><![CDATA[
gap> gr := Digraph([[2], [3], [1, 4], [1, 3]]);
<digraph with 4 vertices, 6 edges>
gap> DigraphDistanceSet(gr, 2, [1, 2]);
[ 3, 1, 4 ]
gap> DigraphDistanceSet(gr, 3, 1);
[ 1, 4 ]
gap> DigraphDistanceSet(gr, 2, 0);
[ 2 ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphShortestDistance">
<ManSection>
  <Oper Name="DigraphShortestDistance" Label="for a digraph and two vertices"
        Arg="digraph, u, v"/>
  <Oper Name="DigraphShortestDistance" Label="for a digraph and a list"
        Arg="digraph, list"/>
  <Oper Name="DigraphShortestDistance" Label="for a digraph, a list, and a list"
        Arg="digraph, list1, list2"/>
  <Returns>An integer or <K>fail</K></Returns>
  <Description>
    If there is a directed path in the digraph <A>digraph</A> between vertex
    <A>u</A> and vertex <A>v</A>, then this operation returns the length of the
    shortest such directed path.  If no such directed path exists, then this
    operation returns <K>fail</K>. See section <Ref Subsect="Definitions"
      Style="Number" /> for the definition of a directed path. <P/>

    If the second form is used, then <A>list</A> should be a list of length two,
    containing two positive integers which correspond to the vertices <A>u</A>
    and <A>v</A>. <P/>

    Note that as usual, a vertex is considered to be at distance 0 from
    itself .<P/>

    If the third form is used, then <A>list1</A> and <A>list2</A> are both lists
    of vertices. The shortest directed path between <A>list1</A> and
    <A>list2</A> is then the length of the shortest directed path which starts
    with a vertex in <A>list1</A> and terminates at a vertex in <A>list2</A>, if
    such directed path exists. If <A>list1</A> and <A>list2</A> have non-empty
    intersection, the operation returns <C>0</C>.<P/>
    <Example><![CDATA[
gap> gr := Digraph([[2], [3], [1, 4], [1, 3], [5]]);
<digraph with 5 vertices, 7 edges>
gap> DigraphShortestDistance(gr, 1, 3);
2
gap> DigraphShortestDistance(gr, [3, 3]);
0
gap> DigraphShortestDistance(gr, 5, 2);
fail
gap> DigraphShortestDistance(gr, [1, 2], [4, 5]);
2
gap> DigraphShortestDistance(gr, [1, 3], [3, 5]);
0
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="PartialOrderDigraphMeetOfVertices">
<ManSection>
  <Oper Name="PartialOrderDigraphMeetOfVertices" Label="for a digraph and two vertices"
        Arg="digraph, u, v"/>
  <Oper Name="PartialOrderDigraphJoinOfVertices" Label="for a digraph and two vertices"
        Arg="digraph, u, v"/>
  <Returns>A positive integer or <K>fail</K></Returns>
    <Description>
    If the first argument is a partial order digraph <Ref Prop="IsPartialOrderDigraph"/>
    then these operations return the meet, or the join, of the two input vertices. If
    the meet (or join) is does not exist then <K>fail</K> is returned. The meet (or
    join) is guaranteed to exist when the first argument satisfies 
    <Ref Prop="IsMeetSemilatticeDigraph"/>  (or <Ref Prop="IsJoinSemilatticeDigraph"/>)
    - see the documentation for these properties for the definition of the meet (or
    the join).

    <Example><![CDATA[
gap> gr := Digraph([[1], [1, 2], [1, 3], [1, 2, 3, 4]]);
<digraph with 4 vertices, 9 edges>
gap> PartialOrderDigraphMeetOfVertices(gr, 2, 3);
4
gap> PartialOrderDigraphJoinOfVertices(gr, 2, 3);
1
gap> PartialOrderDigraphMeetOfVertices(gr, 1, 2);
2
gap> PartialOrderDigraphJoinOfVertices(gr, 3, 4);
3
gap> gr := Digraph([[1], [2], [1, 2, 3], [1, 2, 4]]);
<digraph with 4 vertices, 8 edges>
gap> PartialOrderDigraphMeetOfVertices(gr, 3, 4);
fail
gap> PartialOrderDigraphJoinOfVertices(gr, 3, 4);
fail
gap> PartialOrderDigraphMeetOfVertices(gr, 1, 2);
fail
gap> PartialOrderDigraphJoinOfVertices(gr, 1, 2);
fail
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphClosure">
<ManSection>
  <Oper Name="DigraphClosure" Label="for a digraph and positive integer"
        Arg="digraph, k"/>
  <Returns>A digraph</Returns>
  <Description>
    Given a symmetric loopless digraph with no multiple edges <A>digraph</A>,
    the <E><A>k</A>-closure of <A>digraph</A></E> is defined to be the unique
    smallest symmetric loopless digraph <C>C</C> with no multiple edges on the
    vertices of <A>digraph</A> that contains all the edges of <A>digraph</A>
    and satsifies the property that the sum of the degrees of every two
    non-adjacenct vertices in <C>C</C> is less than <A>k</A>. See <Ref
    Prop="IsSymmetricDigraph"/>, <Ref Prop="DigraphHasLoops"/>, <Ref
    Prop="IsMultiDigraph"/>, and <Ref Oper="OutDegreeOfVertex"/>. <P/>

    The operation <C>DigraphClosure</C> returns the <A>k</A>-closure of <A>digraph</A>.
    <Example><![CDATA[
gap> gr := CompleteDigraph(6);;
gap> DigraphRemoveEdges(gr, [[1, 2], [2, 1]]);;
gap> closure := DigraphClosure(gr, 6);
<digraph with 6 vertices, 30 edges>
gap> IsCompleteDigraph(closure);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsMatching">
<ManSection>
  <Oper Name="IsMatching" Arg="digraph, list"/>
  <Oper Name="IsMaximalMatching" Arg="digraph, list"/>
  <Oper Name="IsPerfectMatching" Arg="digraph, list"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    If <A>digraph</A> is a digraph and <A>list</A> is a list of pairs of
    vertices of <A>digraph</A>, then <C>IsMatching</C> returns <K>true</K> if
    <A>list</A> is a matching of <A>digraph</A>.  The operations
    <C>IsMaximalMatching</C> and <C>IsPerfectMatching</C> return <K>true</K> if
    <A>list</A> is a maximal, or perfect, matching of <A>digraph</A>,
    respectively.  Otherwise, these operations return <K>false</K>. <P/>

    A <E>matching</E> <C>M</C> of a digraph <A>digraph</A> is a subset of the
    edges of <A>digraph</A>, i.e. <C>DigraphEdges(<A>digraph</A>)</C>, such
    that no pair of distinct edges in <C>M</C> are incident to the same vertex
    of <A>digraph</A>.  Note that this definition allows a matching to contain
    loops.  See <Ref Prop="DigraphHasLoops" />.  The matching <C>M</C> is
    <E>maximal</E> if it is contained in no larger matching of the digraph, and
    is <E>perfect</E> if every vertex of the digraph is incident to an edge in
    the matching.  Every perfect matching is maximal.

    <Example><![CDATA[
gap> gr := Digraph([[2], [1], [2, 3, 4], [3, 5], [1]]);
<digraph with 5 vertices, 8 edges>
gap> IsMatching(gr, [[2, 1], [3, 2]]);
false
gap> edges := [[3, 2]];;
gap> IsMatching(gr, edges);
true
gap> IsMaximalMatching(gr, edges);
false
gap> edges := [[5, 1], [3, 3]];;
gap> IsMaximalMatching(gr, edges);
true
gap> IsPerfectMatching(gr, edges);
false
gap> edges := [[1, 2], [3, 3], [4, 5]];;
gap> IsPerfectMatching(gr, edges);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="AsSemigroup">
  <ManSection>
    <Oper Name="AsSemigroup" Arg="filt, digraph"/>
    <Oper Name="AsMonoid" Arg="filt, digraph"/>
    <Returns>A semilattice of partial perms.</Returns>
    <Description>
      The operation <C>AsSemigroup</C> requires that <A>filt</A> be equal to
      <Ref Filt="IsPartialPermSemigroup" BookName="ref"/>.
      If <A>digraph</A> is a
      <Ref Prop="IsJoinSemilatticeDigraph"/> or <Ref Prop="IsLatticeDigraph"/>
      then <C>AsSemigroup</C> returns a semigroup of partial perms which is
      isomorphic to the semigroup whose elements are the vertices of
      <A>digraph</A> with the binary operation
      <Ref Oper="PartialOrderDigraphJoinOfVertices"
        Label="for a digraph and two vertices"/>. If <A>digraph</A>
      satisfies  <Ref Prop="IsMeetSemilatticeDigraph"/> but not
      <Ref Prop="IsJoinSemilatticeDigraph"/> then
      <C>AsSemigroup</C> returns a semigroup of partial perms which is
      isomorphic to the semigroup whose elements are the vertices of
      <A>digraph</A> with the binary operation
      <Ref Oper="PartialOrderDigraphMeetOfVertices"
        Label="for a digraph and two vertices"/>. <P/>

      The operation <C>AsMonoid</C> behaves similarly to <C>AsSemigroup</C>
      except that <A>filt</A> may also be equal to
      <Ref Filt="IsPartialPermMonoid" BookName="ref"/>,
      <A>digraph</A> must satisfy <Ref Prop="IsLatticeDigraph"/>, and the
      output satisfies <Ref Filt="IsMonoid" BookName="ref"/>. <P/>

      The output of both of these operations is guaranteed to be of minimal
      degree (see <Ref Attr="DegreeOfPartialPermSemigroup" BookName="ref"/>).
      Furthermore the <Ref Attr="GeneratorsOfSemigroup" BookName="ref"/> of
      the output is guaranteed to be the unique generating set of minimal size.
      <Example><![CDATA[
gap> di := Digraph([[1], [1, 2], [1, 3], [1, 4], [1, 2, 3, 5]]);
<digraph with 5 vertices, 11 edges>
gap> S := AsSemigroup(IsPartialPermSemigroup, di);
<partial perm semigroup of rank 3 with 4 generators>
gap> ForAll(Elements(S), IsIdempotent);
true
gap> IsInverseSemigroup(S);
true
gap> Size(S);
5
gap> di := Digraph([[1], [1, 2], [1, 2, 3]]);
<digraph with 3 vertices, 6 edges>
gap> M := AsMonoid(IsPartialPermMonoid, di);
<partial perm monoid of rank 2 with 3 generators>
gap> Size(M);
3]]></Example>
    </Description>
  </ManSection>
<#/GAPDoc>
