#############################################################################
##
#W  oper.xml
#Y  Copyright (C) 2014-19                               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]]);
<immutable digraph with 3 vertices, 5 edges>
gap> h := Digraph([[2, 3], [], [2]]);
<immutable 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]]);
<immutable multidigraph with 2 vertices, 3 edges>
gap> h := Digraph([[2], [1]]);
<immutable 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
      Oper="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
      Oper="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> D := CompleteDigraph(4);
<immutable complete digraph with 4 vertices>
gap> tree := Digraph([[3], [4], [1, 4], [2, 3]]);
<immutable digraph with 4 vertices, 6 edges>
gap> IsSubdigraph(D, tree) and IsUndirectedTree(tree);
true
gap> IsUndirectedSpanningTree(D, tree);
true
gap> forest := EmptyDigraph(4);
<immutable empty digraph with 4 vertices>
gap> IsSubdigraph(D, forest) and IsUndirectedForest(forest);
true
gap> IsUndirectedSpanningForest(D, forest);
false
gap> IsSubdigraph(tree, forest);
true
gap> D := DigraphDisjointUnion(CycleDigraph(2), CycleDigraph(2));
<immutable digraph with 4 vertices, 4 edges>
gap> IsUndirectedTree(D);
false
gap> IsUndirectedForest(D) and IsUndirectedSpanningForest(D, D);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphReverseEdges">
<ManSection>
  <Oper Name="DigraphReverseEdges" Arg="digraph, edges"
    Label="for a digraph and a list of edges"/>
  <Oper Name="DigraphReverseEdge" Arg="digraph, edge"
    Label="for a digraph and an edge"/>
  <Oper Name="DigraphReverseEdge" Arg="digraph, src, ran"
    Label="for a digraph, source, and range"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>digraph</A> is a digraph without multiple edges, and <A>edges</A> is 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),
    then <C>DigraphReverseEdges</C> returns a 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 the second and third
    arguments should be the source and range of an edge respectively. <P/>

    Note that even though <A>digraph</A> cannot have multiple edges, the
    output may have multiple edges. <P/>

    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then the edges
    are reversed in <A>digraph</A>. If <A>digraph</A> belongs to <Ref
      Filt="IsImmutableDigraph"/>, an immutable copy of <A>digraph</A> with the
    specified edges reversed is returned.<P/>
    <Example><![CDATA[
gap> D := DigraphFromDiSparse6String(".Tg?i@s?t_e?_qEsC");
<immutable digraph with 21 vertices, 8 edges>
gap> DigraphEdges(D);
[ [ 1, 2 ], [ 1, 7 ], [ 1, 8 ], [ 5, 21 ], [ 7, 19 ], [ 9, 1 ], 
  [ 11, 2 ], [ 21, 1 ] ]
gap> new := DigraphReverseEdge(D, [7, 19]);
<immutable digraph with 21 vertices, 8 edges>
gap> DigraphEdges(new);
[ [ 1, 2 ], [ 1, 7 ], [ 1, 8 ], [ 5, 21 ], [ 9, 1 ], [ 11, 2 ], 
  [ 19, 7 ], [ 21, 1 ] ]
gap> D2 := DigraphMutableCopy(new);;
gap> new := DigraphReverseEdges(D2, [[19, 7]]);;
gap> D2 = new;
true
gap> D = new;
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/>

    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then
    relabelling of the vertices is performed directly on <A>digraph</A>.
    If <A>digraph</A> belongs to <Ref Filt="IsImmutableDigraph"/>, an immutable
    copy of <A>digraph</A> with the vertices relabelled is returned.<P/>

    <Example><![CDATA[
gap> D := Digraph([[3], [1, 3, 5], [1], [1, 2, 4], [2, 3, 5]]);
<immutable digraph with 5 vertices, 11 edges>
gap> new := OnDigraphs(D, (1, 2));
<immutable digraph with 5 vertices, 11 edges>
gap> OutNeighbours(new);
[ [ 2, 3, 5 ], [ 3 ], [ 2 ], [ 2, 1, 4 ], [ 1, 3, 5 ] ]
gap> D := Digraph([[2], [], [2]]);
<immutable digraph with 3 vertices, 2 edges>
gap> t := Transformation([1, 2, 1]);;
gap> new := OnDigraphs(D, t);
<immutable multidigraph with 3 vertices, 2 edges>
gap> OutNeighbours(new);
[ [ 2, 2 ], [  ], [  ] ]
gap> ForAll(DigraphEdges(D),
>  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>.

    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then
    relabelling of the vertices is performed directly on <A>digraph</A>.
    If <A>digraph</A> belongs to <Ref Filt="IsImmutableDigraph"/>, an immutable
    copy of <A>digraph</A> with the vertices relabelled is returned.<P/>

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

<#GAPDoc Label="OnTuplesDigraphs">
<ManSection>
  <Oper Name="OnTuplesDigraphs" Arg="list, perm"
    Label="for a list of digraphs and a perm"/>
  <Oper Name="OnSetsDigraphs" Arg="list, perm"
    Label="for a set of digraphs and a perm"/>
  <Returns>A list or set of digraphs.</Returns>
  <Description>
    If <A>list</A> is a list of digraphs, and <A>perm</A> is a
    <E>permutation</E> of the vertices of the digraphs in <A>list</A>, then
    <Ref Oper="OnTuplesDigraphs" Label="for a list of digraphs and a perm"/>
    returns a new list constructed by applying <A>perm</A> via
    <Ref Oper="OnDigraphs" Label="for a digraph and a perm"/>
    to a copy (with the same mutability) of each entry of <A>list</A> in turn.
    <P/>

    More precisely, <C>OnTuplesDigraphs(<A>list</A>,<A>perm</A>)</C> is a list
    of length <C>Length(<A>list</A>)</C>, whose <C>i</C>-th entry is
    <C>OnDigraphs(DigraphCopy(<A>list</A>[i]), <A>perm</A>)</C>.
    <P/>

    If <A>list</A> is moreover a &GAP; set (i.e. a duplicate-free sorted list),
    then <Ref Oper="OnSetsDigraphs" Label="for a set of digraphs and a perm"/>
    returns the sorted output of
    <Ref Oper="OnTuplesDigraphs" Label="for a list of digraphs and a perm"/>,
    which is therefore again a set.
    <Example><![CDATA[
gap> list := [CycleDigraph(IsMutableDigraph, 6),
>             DigraphReverse(CycleDigraph(6))];
[ <mutable digraph with 6 vertices, 6 edges>, 
  <immutable digraph with 6 vertices, 6 edges> ]
gap> p := (1, 6)(2, 5)(3, 4);;
gap> result_tuples := OnTuplesDigraphs(list, p);
[ <mutable digraph with 6 vertices, 6 edges>, 
  <immutable digraph with 6 vertices, 6 edges> ]
gap> result_tuples[2] = OnDigraphs(list[2], p);
true
gap> result_tuples = list;
false
gap> result_tuples = Reversed(list);
true
gap> result_sets := OnSetsDigraphs(list, p);
[ <immutable digraph with 6 vertices, 6 edges>, 
  <mutable digraph with 6 vertices, 6 edges> ]
gap> result_sets = list;
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

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

    If the optional second argument <A>label</A> is a &GAP; object,
    then the new vertex will be labelled <A>label</A>.
    <P/>

    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then the
    vertex is added directly to <A>digraph</A>. If <A>digraph</A> belongs to
    <Ref Filt="IsImmutableDigraph"/>, an immutable copy of <A>digraph</A> with
    the additional vertex is returned.<P/>

    <Example><![CDATA[
gap> D := CompleteDigraph(3);
<immutable complete digraph with 3 vertices>
gap> new := DigraphAddVertex(D);
<immutable digraph with 4 vertices, 6 edges>
gap> D = new;
false
gap> DigraphVertices(new);
[ 1 .. 4 ]
gap> new := DigraphAddVertex(D, Group([(1, 2)]));
<immutable digraph with 4 vertices, 6 edges>
gap> DigraphVertexLabels(new);
[ 1, 2, 3, Group([ (1,2) ]) ]
gap> D := CompleteBipartiteDigraph(IsMutableDigraph, 2, 3);
<mutable digraph with 5 vertices, 12 edges>
gap> new := DigraphAddVertex(D);
<mutable digraph with 6 vertices, 12 edges>
gap> D = new;
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphAddVertices">
<ManSection>
  <Oper Name="DigraphAddVertices" Arg="digraph, m"
    Label="for a digraph and an integer"/>
  <Oper Name="DigraphAddVertices" Arg="digraph, labels"
    Label="for a digraph and a list of labels"/>
  <!-- The 3-argument version is deliberately undocumented. It is redundant,
       but it is included for backwards compatibility. -->
  <Returns>A digraph.</Returns>
  <Description>
    For a non-negative integer <A>m</A>, this operation returns a digraph
    constructed from <A>digraph</A> by adding <A>m</A> new vertices.
    <P/>

    Otherwise, if <A>labels</A> is a list
    consisting of <C>k</C> &GAP; objects, then this operation returns a
    digraph constructed from <A>digraph</A> by adding <C>k</C> new vertices,
    which are labelled according to this list.
    <P/>

    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then the
    vertices are added directly to <A>digraph</A>, which is changed in-place.
    If <A>digraph</A> belongs to <Ref Filt="IsImmutableDigraph"/>, then
    <A>digraph</A> itself is returned if no vertices are added
    (i.e. <C><A>m</A>=0</C> or <A>labels</A> is empty), otherwise
    the result is a new immutable digraph.
    <P/>

    <Example><![CDATA[
gap> D := CompleteDigraph(3);
<immutable complete digraph with 3 vertices>
gap> new := DigraphAddVertices(D, 3);
<immutable digraph with 6 vertices, 6 edges>
gap> DigraphVertices(new);
[ 1 .. 6 ]
gap> new := DigraphAddVertices(D, [Group([(1, 2)]), "d"]);
<immutable digraph with 5 vertices, 6 edges>
gap> DigraphVertexLabels(new);
[ 1, 2, 3, Group([ (1,2) ]), "d" ]
gap> DigraphAddVertices(D, 0) = D;
true
gap> D := CompleteBipartiteDigraph(IsMutableDigraph, 2, 3);
<mutable digraph with 5 vertices, 12 edges>
gap> new := DigraphAddVertices(D, 4);
<mutable digraph with 9 vertices, 12 edges>
gap> D = new;
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
    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 returned
    digraph are <C>[1..n-1]</C>, but the original labels can be
    accessed via <Ref Oper="DigraphVertexLabels"/>. <P/>

    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then the
    vertex is removed directly from <A>digraph</A>. If <A>digraph</A> belongs
    to <Ref Filt="IsImmutableDigraph"/>, an immutable copy of <A>digraph</A>
    without the vertex is returned.<P/>

    <Example><![CDATA[
gap> D := Digraph(["a", "b", "c"],
>                  ["a", "a", "b", "c", "c"],
>                  ["b", "c", "a", "a", "c"]);
<immutable digraph with 3 vertices, 5 edges>
gap> DigraphVertexLabels(D);
[ "a", "b", "c" ]
gap> DigraphEdges(D);
[ [ 1, 2 ], [ 1, 3 ], [ 2, 1 ], [ 3, 1 ], [ 3, 3 ] ]
gap> new := DigraphRemoveVertex(D, 2);
<immutable digraph with 2 vertices, 3 edges>
gap> DigraphVertexLabels(new);
[ "a", "c" ]
gap> D := CycleDigraph(IsMutableDigraph, 5);
<mutable digraph with 5 vertices, 5 edges>
gap> new := DigraphRemoveVertex(D, 1);
<mutable digraph with 4 vertices, 3 edges>
gap> DigraphVertexLabels(D);
[ 2, 3, 4, 5 ]
gap> D = new;
true
]]></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 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/>

    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then the
    vertices are removed directly from <A>digraph</A>. If <A>digraph</A> belongs
    to <Ref Filt="IsImmutableDigraph"/>, an immutable copy of <A>digraph</A>
    without the vertices is returned.<P/>

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

<#GAPDoc Label="DigraphAddEdge">
<ManSection>
  <Oper Name="DigraphAddEdge" Arg="digraph, edge"
    Label="for a digraph and an edge"/>
  <Oper Name="DigraphAddEdge" Arg="digraph, src, ran"
    Label="for a digraph, source, and range"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>edge</A> is a pair of vertices of <A>digraph</A>, or <A>src</A> and
    <A>ran</A> are vertices of <A>digraph</A>,
    then this operation returns a digraph constructed from <A>digraph</A>
    by adding a new edge with source <A>edge</A><C>[1]</C> [<A>src</A>] and range
    <A>edge</A><C>[2]</C> [<A>ran</A>].
    <P/>
    
    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then the edge
    is added directly to <A>digraph</A>. If <A>digraph</A> belongs to <Ref
      Filt="IsImmutableDigraph"/>, then an immutable copy of <A>digraph</A> with the
    additional edge is returned.  <P/>

    <Example><![CDATA[
gap> D1 := Digraph([[2], [3], []]);
<immutable digraph with 3 vertices, 2 edges>
gap> DigraphEdges(D1);
[ [ 1, 2 ], [ 2, 3 ] ]
gap> D2 := DigraphAddEdge(D1, [3, 1]);
<immutable digraph with 3 vertices, 3 edges>
gap> DigraphEdges(D2);
[ [ 1, 2 ], [ 2, 3 ], [ 3, 1 ] ]
gap> D3 := DigraphAddEdge(D2, [2, 3]);
<immutable multidigraph with 3 vertices, 4 edges>
gap> DigraphEdges(D3);
[ [ 1, 2 ], [ 2, 3 ], [ 2, 3 ], [ 3, 1 ] ]
gap> D := CycleDigraph(IsMutableDigraph, 4);
<mutable digraph with 4 vertices, 4 edges>
gap> new := DigraphAddEdge(D, [1, 3]);
<mutable digraph with 4 vertices, 5 edges>
gap> DigraphEdges(new);
[ [ 1, 2 ], [ 1, 3 ], [ 2, 3 ], [ 3, 4 ], [ 4, 1 ] ]
gap> D = new;
true
]]></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 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.

    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then the edges
    are added directly to <A>digraph</A>. If <A>digraph</A> belongs to <Ref
      Filt="IsImmutableDigraph"/>, then the result is returned as an immutable
    digraph.
    <P/>

    <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> D := func(1024);
<immutable digraph with 1024 vertices, 1022 edges>
gap> new := DigraphAddEdges(D,
> [[1023, 1024], [1, 1024], [1023, 1024], [1024, 1]]);
<immutable multidigraph with 1024 vertices, 1026 edges>
gap> D = new;
false
gap> D2 := DigraphMutableCopy(func(1024));
<mutable digraph with 1024 vertices, 1022 edges>
gap> new := DigraphAddEdges(D2,
> [[1023, 1024], [1, 1024], [1023, 1024], [1024, 1]]);
<mutable multidigraph with 1024 vertices, 1026 edges>
gap> D2 = new;
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphRemoveEdge">
<ManSection>
  <Oper Name="DigraphRemoveEdge" Arg="digraph, edge"
    Label="for a digraph and an edge"/>
  <Oper Name="DigraphRemoveEdge" Arg="digraph, src, ran"
    Label="for a digraph, source, and range"/>
  <Returns>A digraph.</Returns>
  <Description>
    If <A>digraph</A> is a digraph with no multiple edges and <A>edge</A> is a
    pair of vertices of <A>digraph</A>, or <A>src</A> and <A>ran</A> are
    vertices of <A>digraph</A>, then this operation returns a digraph
    constructed from <A>digraph</A> by removing the edge specified by
    <A>edge</A> or <A>[src, ran]</A>. <P/>  

    If <A>digraph</A> belongs to <Ref
      Filt="IsMutableDigraph"/>, then the edge is removed directly from
    <A>digraph</A>. If <A>digraph</A> belongs to <Ref
      Filt="IsImmutableDigraph"/>, an immutable copy of <A>digraph</A> without
    the edge is returned.
    <P/>

    Note that if <A>digraph</A> belongs to <Ref Filt="IsImmutableDigraph"/>,
    then a new copy of <A>digraph</A> will be returned even if <A>edge</A> or 
    <A>[src, ran]</A> does not define an edge of <A>digraph</A>.<P/>

    <Example><![CDATA[
gap> D := CycleDigraph(250000);
<immutable cycle digraph with 250000 vertices>
gap> D := DigraphRemoveEdge(D, [250000, 1]);
<immutable digraph with 250000 vertices, 249999 edges>
gap> new := DigraphRemoveEdge(D, [25000, 2]);;
gap> new = D;
true
gap> IsIdenticalObj(new, D);
false
gap> D := DigraphMutableCopy(D);;
gap> new := DigraphRemoveEdge(D, 2500, 2);;
gap> IsIdenticalObj(new, D);
true]]>
</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 a digraph and <A>edges</A> is an empty list </Item>
    </List>

    then this operation returns a digraph constructed from <A>digraph</A>
    by removing all of the edges specified by <A>edges</A>
    (see <Ref Oper="DigraphRemoveEdge" Label="for a digraph and an edge"/>).
    <P/>

    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then the edge
    is removed directly from <A>digraph</A>. If <A>digraph</A> belongs to <Ref
      Filt="IsImmutableDigraph"/>, the edge is removed from an immutable copy of
    <A>digraph</A> and this new digraph is returned.<P/>

    Note that if <A>edges</A> is empty, then this operation
    will always return <A>digraph</A> rather than a copy. Also, if any element
    of <A>edges</A> is invalid (i.e. does not define an edge of <A>digraph</A>)
    then that element will simply be ignored.

    <Example><![CDATA[
gap> D := CycleDigraph(250000);
<immutable cycle digraph with 250000 vertices>
gap> D := DigraphRemoveEdges(D, [[250000, 1]]);
<immutable digraph with 250000 vertices, 249999 edges>
gap> D := DigraphMutableCopy(D);
<mutable digraph with 250000 vertices, 249999 edges>
gap> new := DigraphRemoveEdges(D, [[1, 2], [2, 3], [3, 100]]);
<mutable digraph with 250000 vertices, 249997 edges>
gap> new = D;
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/>

    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then
    <A>digraph</A> is modified in place. If <A>digraph</A> belongs to <Ref
      Filt="IsImmutableDigraph"/>, a new immutable digraph containing the
    appropriate
    vertices and edges is returned.<P/>

    <Example><![CDATA[
gap> D := Digraph([[1, 1, 2, 3, 4, 4], [1, 3, 4], [3, 1], [1, 1]]);
<immutable multidigraph with 4 vertices, 13 edges>
gap> InducedSubdigraph(D, [1, 3, 4]);
<immutable multidigraph with 3 vertices, 9 edges>
gap> DigraphVertices(last);
[ 1 .. 3 ]
gap> D := DigraphMutableCopy(D);
<mutable multidigraph with 4 vertices, 13 edges>
gap> new := InducedSubdigraph(D, [1, 3, 4]);
<mutable multidigraph with 3 vertices, 9 edges>
gap> D = new;
true
]]></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> D := Digraph([
> [2, 2, 1], [1, 4], [2, 2, 4, 2], [1, 1, 2, 2, 1, 2, 2]]);
<immutable multidigraph with 4 vertices, 16 edges>
gap> OutDegreeOfVertex(D, 1);
3
gap> OutDegreeOfVertex(D, 2);
2
gap> OutDegreeOfVertex(D, 3);
4
gap> OutDegreeOfVertex(D, 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> D := Digraph([
> [2, 2, 3], [1, 3, 4], [2, 2, 3], [1, 1, 2, 2, 1, 2, 2]]);
<immutable multidigraph with 4 vertices, 16 edges>
gap> OutNeighboursOfVertex(D, 1);
[ 2, 2, 3 ]
gap> OutNeighboursOfVertex(D, 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> D := Digraph([
> [2, 2, 1], [1, 4], [2, 2, 4, 2], [1, 1, 2, 2, 1, 2, 2]]);
<immutable multidigraph with 4 vertices, 16 edges>
gap> InDegreeOfVertex(D, 1);
5
gap> InDegreeOfVertex(D, 2);
9
gap> InDegreeOfVertex(D, 3);
0
gap> InDegreeOfVertex(D, 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> D := Digraph([
> [2, 2, 3], [1, 3, 4], [2, 2, 3], [1, 1, 2, 2, 1, 2, 2]]);
<immutable multidigraph with 4 vertices, 16 edges>
gap> InNeighboursOfVertex(D, 1);
[ 2, 4, 4, 4 ]
gap> InNeighboursOfVertex(D, 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> D := Digraph([[2, 2], [3, 3], [4, 4], [1, 1]]);
<immutable multidigraph with 4 vertices, 8 edges>
gap> DigraphInEdges(D, 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> D := Digraph([[2, 2], [3, 3], [4, 4], [1, 1]]);
<immutable multidigraph with 4 vertices, 8 edges>
gap> DigraphOutEdges(D, 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> D := Digraph([[3], [2], [1, 2], [3]]);
<immutable digraph with 4 vertices, 5 edges>
gap> DigraphStronglyConnectedComponent(D, 3);
[ 1, 3 ]
gap> DigraphStronglyConnectedComponent(D, 2);
[ 2 ]
gap> DigraphStronglyConnectedComponent(D, 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> D := Digraph([[3], [2], [1, 2], [4]]);
<immutable digraph with 4 vertices, 5 edges>
gap> DigraphConnectedComponent(D, 3);
[ 1, 2, 3 ]
gap> DigraphConnectedComponent(D, 2);
[ 1, 2, 3 ]
gap> DigraphConnectedComponent(D, 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 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 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 there exists some edge in <A>digraph</A>
    with source in part <C>i</C> and range in part <C>j</C> if and only if there
    is an edge from <C>i</C> to <C>j</C> in the quotient.
    In particular, this means that the quotient of a digraph has no multiple edges.
    which was a change introduced in version 1.0.0 of the &Digraphs; package.
    <P/>

    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then
    <A>digraph</A> is modified in place. If <A>digraph</A> belongs to <Ref
      Filt="IsImmutableDigraph"/>, a new immutable digraph with the above
    properties is returned.<P/>

    <Example><![CDATA[
gap> D := Digraph([[2, 1], [4], [1], [1, 3, 4]]);
<immutable digraph with 4 vertices, 7 edges>
gap> DigraphVertices(D);
[ 1 .. 4 ]
gap> DigraphEdges(D);
[ [ 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> quo := QuotientDigraph(D, p);
<immutable digraph with 3 vertices, 6 edges>
gap> DigraphVertices(quo);
[ 1 .. 3 ]
gap> DigraphEdges(quo);
[ [ 1, 1 ], [ 1, 2 ], [ 2, 1 ], [ 2, 2 ], [ 2, 3 ], [ 3, 1 ] ]
gap> QuotientDigraph(EmptyDigraph(0), []);
<immutable empty digraph with 0 vertices>
]]></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> D := Digraph([[2, 2], [6], [], [3], [], [1]]);
<immutable multidigraph with 6 vertices, 5 edges>
gap> IsDigraphEdge(D, [1, 1]);
false
gap> IsDigraphEdge(D, [1, 2]);
true
gap> IsDigraphEdge(D, [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> D := DigraphFromDigraph6String("&EAHQeDB");
<immutable 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(D, 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="DigraphEdgeUnion">
<ManSection>
  <Func Name="DigraphEdgeUnion" Arg="D1, D2, ..."
    Label="for a positive 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>D1</A>, <A>D2</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.
    <P/>

    If the first digraph <A>D1</A> [<A>list[1]</A>] belongs to <Ref
    Filt="IsMutableDigraph"/>, then <A>D1</A> [<A>list[1]</A>] is modified in
    place to contain the appropriate vertices and edges. If <A>digraph</A> belongs
    to <Ref Filt="IsImmutableDigraph"/>, a new immutable digraph containing the
    appropriate vertices and edges is returned.
<Example><![CDATA[
gap> D := CycleDigraph(10);
<immutable cycle digraph with 10 vertices>
gap> DigraphEdgeUnion(D, D);
<immutable multidigraph with 10 vertices, 20 edges>
gap> D1 := Digraph([[2], [1]]);
<immutable digraph with 2 vertices, 2 edges>
gap> D2 := Digraph([[2, 3], [2], [1]]);
<immutable digraph with 3 vertices, 4 edges>
gap> union := DigraphEdgeUnion(D1, D2);
<immutable multidigraph with 3 vertices, 6 edges>
gap> OutNeighbours(union);
[ [ 2, 2, 3 ], [ 1, 2 ], [ 1 ] ]
gap> union = DigraphByEdges(
> Concatenation(DigraphEdges(D1), DigraphEdges(D2)));
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphDisjointUnion">
<ManSection>
  <Func Name="DigraphDisjointUnion" Arg="D1, D2, ..." 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>D1</A>, <A>D2</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>D1</A>, <A>D2</A>,
    <C>...</C>, the disjoint union with have
    <C>DigraphNrVertices(</C><A>D1</A><C>)</C> <C>+</C>
    <C>DigraphNrVertices(</C><A>D2</A><C>)</C> <C>+</C> <C>...</C> vertices.
    The edges of <A>D1</A> will remain unchanged, whilst the edges of the
    <C>i</C>th digraph, <A>D</A><C>[i]</C>, will be changed so that they
    belong to the vertices of the disjoint union corresponding to
    <A>D</A><C>[i]</C>.  In particular, the edges of <A>D</A><C>[i]</C> will
    have their source and range increased by
    <C>DigraphNrVertices(</C><A>D1</A><C>)</C> <C>+</C> <C>...</C> <C>+</C>
    <C>DigraphNrVertices(</C><A>D</A><C>[i-1])</C>.

    <P/>

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

    If the first digraph <A>D1</A> [<A>list[1]</A>] belongs to <Ref
    Filt="IsMutableDigraph"/>, then <A>D1</A> [<A>list[1]</A>] is modified in
    place to contain the appropriate vertices and edges. If <A>digraph</A> belongs
    to <Ref Filt="IsImmutableDigraph"/>, a new immutable digraph containing the
    appropriate vertices and edges is returned.
<Example><![CDATA[
gap> D1 := CycleDigraph(3);
<immutable cycle digraph with 3 vertices>
gap> OutNeighbours(D1);
[ [ 2 ], [ 3 ], [ 1 ] ]
gap> D2 := CompleteDigraph(3);
<immutable complete digraph with 3 vertices>
gap> OutNeighbours(D2);
[ [ 2, 3 ], [ 1, 3 ], [ 1, 2 ] ]
gap> union := DigraphDisjointUnion(D1, D2);
<immutable 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="D1, D2, ..."
    Label="for a positive 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>D1</A>, <A>D2</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>D1</A>, <A>D2</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>D</A><C>[i]</C> and
    <A>D</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.
    <P/>

    If the first digraph <A>D1</A> [<A>list[1]</A>] belongs to <Ref
    Filt="IsMutableDigraph"/>, then <A>D1</A> [<A>list[1]</A>] is modified in
    place to contain the appropriate vertices and edges. If <A>digraph</A> belongs
    to <Ref Filt="IsImmutableDigraph"/>, a new immutable digraph containing the
    appropriate vertices and edges is returned.
<Example><![CDATA[
gap> D := CompleteDigraph(3);
<immutable complete digraph with 3 vertices>
gap> IsCompleteDigraph(DigraphJoin(D, D));
true
gap> D2 := CycleDigraph(3);
<immutable cycle digraph with 3 vertices>
gap> DigraphJoin(D, D2);
<immutable digraph with 6 vertices, 27 edges>
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphCartesianProduct">
<ManSection>
  <Func Name="DigraphCartesianProduct" Arg="gr1, gr2, ..."
    Label="for a positive number of digraphs"/>
  <Func Name="DigraphCartesianProduct" 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>DigraphCartesianProduct</C> returns a digraph isomorphic to their
    Cartesian product.
    <P/>

    In the second form, if <A>list</A> is a non-empty list of digraphs,
    then <C>DigraphCartesianProduct</C> returns a digraph isomorphic to the 
    Cartesian product of the digraphs contained in the list.
    <P/>
 
    Mathematically, the Cartesian product of two digraphs <C>G</C>, <C>H</C>
    is a digraph with vertex set <C>Cartesian(DigraphVertices(G),
    DigraphVertices(H))</C> such that there is an edge from <C>[u, u']</C> to
    <C>[v, v']</C> iff <C> u = v </C> and there is an edge from <C>u'</C> to
    <C>v'</C> in <C>H</C> or <C> u' = v'</C> and there is an edge from
    <C>u</C> to <C>v</C> in <C>G</C>.
    <P/>

    Due to technical reasons, the digraph <C>D</C> returned by
    <C>DigraphCartesianProduct</C> has vertex set
    <C>[1 ..  DigraphNrVertices(G)*DigraphNrVertices(H)]</C> instead, and the
     exact
    method of encoding pairs of vertices into integers is implementation
    specific.  The original vertex pair can be somewhat regained by using
    <Ref Attr="DigraphCartesianProductProjections"/>. In addition,
    <Ref Oper="DigraphVertexLabels"/> are preserved: if vertex pair
    <C>[u,u']</C> was encoded as <C>i</C> then the vertex label of <C>i</C>
    will be the pair of vertex labels of <C>u</C> and <C>u'</C> i.e.
    <C>DigraphVertexLabel(D,i) = [DigraphVertexLabel(G,u),
      DigraphVertexLabel(H,u')]</C>.
    <P/>

    As the Cartesian product is associative, the Cartesian product of a collection 
    of digraphs <A>gr1</A>, <A>gr2</A>, <C>...</C> is computed in the obvious 
    fashion. 
    <P/>

<Example><![CDATA[
gap> gr := ChainDigraph(4);
<immutable chain digraph with 4 vertices>
gap> gr2 := CycleDigraph(3);
<immutable cycle digraph with 3 vertices>
gap> gr3 := DigraphCartesianProduct(gr, gr2);
<immutable digraph with 12 vertices, 21 edges>
gap> IsIsomorphicDigraph(gr3, 
> Digraph([[2, 5], [3, 6], [4, 7], [8], 
>          [6, 9], [7, 10], [8, 11], [12],
>          [10, 1], [11, 2], [12, 3], [4]]));
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphDirectProduct">
<ManSection>
  <Func Name="DigraphDirectProduct" Arg="gr1, gr2, ..."
    Label="for a positive number of digraphs"/>
  <Func Name="DigraphDirectProduct" 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>DigraphDirectProduct</C> returns a digraph isomorphic to their direct
    product.
    <P/>

    In the second form, if <A>list</A> is a non-empty list of digraphs, then
    <C>DigraphDirectProduct</C> returns a digraph isomorphic to the direct
    product of the digraphs contained in the list.
    <P/>

    Mathematically, the direct product of two digraphs <C>G</C>, <C>H</C> is a
    digraph with vertex set <C>Cartesian(DigraphVertices(G),
    DigraphVertices(H))</C> such that there is an edge from <C>[u, u']</C>
    to <C>[v, v']</C> iff there is an edge from <C>u</C> to <C>v</C> in
    <C>G</C> and an edge from <C>u'</C> to <C>v'</C> in <C>H</C>. 
    <P/> 

    Due to technical reasons, the digraph <C>D</C> returned by
    <C>DigraphDirectProduct</C> has vertex set
    <C>[1 ..  DigraphNrVertices(G)*DigraphNrVertices(H)]</C> instead, and the
    exact method of encoding pairs of vertices into integers is implementation
    specific.  The original vertex pair can be somewhat regained by using
    <Ref Attr="DigraphDirectProductProjections"/>. In addition
    <Ref Oper="DigraphVertexLabels"/> are preserved: if vertex pair
    <C>[u,u']</C> was encoded as <C>i</C> then the vertex label of <C>i</C>
    will be the pair of vertex labels of <C>u</C> and <C>u'</C> i.e.
    <C>DigraphVertexLabel(D,i) = [DigraphVertexLabel(G,u),
    DigraphVertexLabel(H,u')]</C>.
    <P/>

    As the direct product is associative, the direct product of a collection 
    of digraphs <A>gr1</A>, <A>gr2</A>, <C>...</C> is computed in the obvious 
    fashion. 
    <P/>

<Example><![CDATA[
gap> gr := ChainDigraph(4);
<immutable chain digraph with 4 vertices>
gap> gr2 := CycleDigraph(3);
<immutable cycle digraph with 3 vertices>
gap> gr3 := DigraphDirectProduct(gr, gr2);
<immutable digraph with 12 vertices, 9 edges>
gap> IsIsomorphicDigraph(gr3, 
> Digraph([[6], [7], [8], [], 
>          [10], [11], [12], [],
>          [2], [3], [4], []]));
true
]]></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> D := Digraph([[2], [3], [2, 3]]);
<immutable digraph with 3 vertices, 4 edges>
gap> IsReachable(D, 1, 3);
true
gap> IsReachable(D, 2, 1);
false
gap> IsReachable(D, 3, 3);
true
gap> IsReachable(D, 1, 1);
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="VerticesReachableFrom">
<ManSection>
  <Oper Name="VerticesReachableFrom" Arg="digraph, root"/>
  <Returns>A list.</Returns>
  <Description>
    This operation returns a list of the vertices  <A>v</A>, for which there exists
    a non-trivial directed walk from vertex <A>root</A> to vertex <A>v</A> in the digraph
    <A>digraph</A>. See Section <Ref Subsect="Definitions" Style="Number" />
    for the definition of a non-trivial directed walk.
    <P/>

    The method for <C>VerticesReachableFrom</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> D := CompleteDigraph(5);
<immutable complete digraph with 5 vertices>
gap> VerticesReachableFrom(D, 1);
[ 2, 1, 3, 4, 5 ]
gap> VerticesReachableFrom(D, 3);
[ 1, 2, 3, 4, 5 ]
gap> D := EmptyDigraph(5);
<immutable empty digraph with 5 vertices>
gap> VerticesReachableFrom(D, 1);
[  ]
gap> VerticesReachableFrom(D, 3);
[  ]
gap> D := CycleDigraph(4);
<immutable cycle digraph with 4 vertices>
gap> VerticesReachableFrom(D, 1);
[ 2, 3, 4, 1 ]
gap> VerticesReachableFrom(D, 3);
[ 4, 1, 2, 3 ]
gap> D := ChainDigraph(5);
<immutable chain digraph with 5 vertices>
gap> VerticesReachableFrom(D, 1);
[ 2, 3, 4, 5 ]
gap> VerticesReachableFrom(D, 3);
[ 4, 5 ]
gap> VerticesReachableFrom(D, 5);
[  ]
]]></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 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>.<P/>

      See also <Ref Oper="IsDigraphPath"/>.

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

<#GAPDoc Label="DigraphShortestPathSpanningTree">
<ManSection>
  <Oper Name="DigraphShortestPathSpanningTree" Arg="digraph, v"/>
  <Returns>A digraph, or <K>fail</K>.</Returns>
  <Description>
    If <A>v</A> is a vertex in <A>digraph</A> and every other
    vertex of <A>digraph</A> is reachable from <A>v</A>,
    then this operation returns the shortest path spanning tree of
    <A>digraph</A> rooted at <A>v</A>.
    If there exist vertices in <A>digraph</A> (other than <A>v</A>) that are
    not reachable from <A>v</A>, then <C>DigraphShortestPathSpanningTree</C>
    returns <K>fail</K>.  See <Ref Oper="IsReachable"/>. <P/>

    The <E>shortest path spanning tree of <A>digraph</A> rooted at <A>v</A></E>
    is a subdigraph of <A>digraph</A> that is a directed tree, with unique
    source vertex <A>v</A>, and where for each other vertex <A>u</A> in
    <A>digraph</A>, the unique directed path from <A>v</A> to <A>u</A> in the
    tree is the lexicographically-least shortest directed path from <A>v</A> to
    <A>u</A> in <A>digraph</A>. <P/>

    See <Ref Prop="IsDirectedTree"/>, <Ref Attr="DigraphSources"/>, and
    <Ref Oper="DigraphShortestPath"/>. <P/>
    
    If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then
    <A>digraph</A> is modified in place. If <A>digraph</A> belongs to <Ref
    Filt="IsImmutableDigraph"/>, then the spanning tree is a new immutable
    digraph.

<Example><![CDATA[
gap> D := Digraph([[1, 2], [3], [2, 4], [1], [2, 4]]);
<immutable digraph with 5 vertices, 8 edges>
gap> ForAll([2 .. 5], v -> IsReachable(D, 1, v));
false
gap> DigraphShortestPathSpanningTree(D, 1);
fail
gap> tree := DigraphShortestPathSpanningTree(D, 5);
<immutable directed tree digraph with 5 vertices>
gap> OutNeighbours(tree);
[ [  ], [ 3 ], [  ], [ 1 ], [ 2, 4 ] ]
gap> ForAll(DigraphVertices(D), v ->
> DigraphShortestPath(D, 5, v) = DigraphPath(tree, 5, v));
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<!-- TODO is it *the* lexicographically least shortest path? -->
<#GAPDoc Label="DigraphShortestPath">
<ManSection>
  <Oper Name="DigraphShortestPath" Arg="digraph, u, v"/>
  <Returns>A pair of lists, or <K>fail</K>.</Returns>
  <Description>
    Returns a shortest directed path in the digraph <A>digraph</A> from vertex
    <A>u</A> to vertex <A>v</A>, if such a path exists. If <C><A>u</A> =
    <A>v</A></C>, 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> D := Digraph([[1, 2], [3], [2, 4], [1], [2, 4]]);
<immutable digraph with 5 vertices, 8 edges>
gap> DigraphShortestPath(D, 5, 1);
[ [ 5, 4, 1 ], [ 2, 1 ] ]
gap> DigraphShortestPath(D, 3, 3);
[ [ 3, 2, 3 ], [ 1, 1 ] ]
gap> DigraphShortestPath(D, 5, 5);
fail
gap> DigraphShortestPath(D, 1, 1);
[ [ 1, 1 ], [ 1 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphRandomWalk">
<ManSection>
  <Oper Name="DigraphRandomWalk" Arg="digraph, v, t"/>
  <Returns>A pair of lists.</Returns>
  <Description>
    Returns a directed path corresponding to a <E>random walk</E> in the digraph
    <A>digraph</A>, starting at vertex <A>v</A> and having length no more than
    <A>t</A>.
    <P/>

    A random walk is defined as follows.  The path begins at <A>v</A>, and at
    each step it follows a random edge leaving the current vertex.  It continues
    through the digraph in this way until it has traversed <A>t</A> edges, or
    until it reaches a vertex with no out-edges (a <E>sink</E>) and therefore
    cannot continue.
    <P/>
    
    The output has the same form as that of <Ref Oper="DigraphPath"/>.
    <P/>

<Log><![CDATA[
gap> D := Digraph([[1, 2], [3], [2, 4], [1], [2, 4]]);                
<immutable digraph with 5 vertices, 8 edges>
gap> DigraphRandomWalk(D, 1, 4);
[ [ 1, 2, 3, 2, 3 ], [ 2, 1, 1, 1 ] ]
]]></Log>
  </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> D := Digraph([[1, 4, 4, 2], [3, 5], [2, 3], [1, 2], [4]]);
<immutable multidigraph with 5 vertices, 11 edges>
gap> iter := IteratorOfPaths(D, 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(D, 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> D := Digraph([[2], [3, 4], [], [5], [], [6]]);
<immutable digraph with 6 vertices, 5 edges>
gap> DigraphLongestDistanceFromVertex(D, 1);
3
gap> DigraphLongestDistanceFromVertex(D, 3);
0
gap> 3 in DigraphSinks(D);
true
gap> DigraphLongestDistanceFromVertex(D, 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> D := CompleteDigraph(4);;
gap> DigraphLayers(D, 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> D := Digraph([[2], [3], [1, 4], [1, 3]]);
<immutable digraph with 4 vertices, 6 edges>
gap> DigraphDistanceSet(D, 2, [1, 2]);
[ 3, 1, 4 ]
gap> DigraphDistanceSet(D, 3, 1);
[ 1, 4 ]
gap> DigraphDistanceSet(D, 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> D := Digraph([[2], [3], [1, 4], [1, 3], [5]]);
<immutable digraph with 5 vertices, 7 edges>
gap> DigraphShortestDistance(D, 1, 3);
2
gap> DigraphShortestDistance(D, [3, 3]);
0
gap> DigraphShortestDistance(D, 5, 2);
fail
gap> DigraphShortestDistance(D, [1, 2], [4, 5]);
2
gap> DigraphShortestDistance(D, [1, 3], [3, 5]);
0
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="Dominators">
<ManSection>
  <Oper Name="Dominators" Arg="digraph, root"/>
  <Returns>A list of lists.</Returns>
    <Description>
    <C>Dominators</C> takes a <A>digraph</A> and a root <A>root</A> and returns
    the dominators of each vertex with respect to the root. The output is
    returned as a list of length <C>DigraphNrVertices(<A>Digraph</A>)</C>,
    whose <A>i</A>th entry is a list with the dominators of vertex <A>i</A> of
    the <A>digraph</A>. If there is no path from the root to a specific vertex,
    the output will contain a hole in the corresponding position. The
    <E>dominators</E> of a vertex <M>u</M> are the vertices that are
    contained in every path from the <M>root</M> to <M>u</M>, not including
    <M>u</M> itself.

    The method for this operation is an implementation of an algorithm by
    Thomas Lengauer and Robert Endre Tarjan <Cite Key="LT79"/>. The complexity
    of this algorithm is <M>O(mlog n)</M> where <M>m</M> is the number of edges
    and <M>n</M> is the number of nodes in the subdigraph induced by the nodes
    in <A>digraph</A> reachable from <A>root</A>.
    <Example><![CDATA[
gap> D := Digraph([[2], [3, 6], [2, 4], [1], [], [3]]);
<immutable digraph with 6 vertices, 7 edges>
gap> Dominators(D, 1);
[ , [ 1 ], [ 2, 1 ], [ 3, 2, 1 ],, [ 2, 1 ] ]
gap> Dominators(D, 2);
[ [ 4, 3, 2 ],, [ 2 ], [ 3, 2 ],, [ 2 ] ]
gap> Dominators(D, 3);
[ [ 4, 3 ], [ 3 ],, [ 3 ],, [ 2, 3 ] ]
gap> Dominators(D, 4);
[ [ 4 ], [ 1, 4 ], [ 2, 1, 4 ],,, [ 2, 1, 4 ] ]
gap> Dominators(D, 5);
[  ]
gap> Dominators(D, 6);
[ [ 4, 3, 6 ], [ 3, 6 ], [ 6 ], [ 3, 6 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DominatorTree">
<ManSection>
  <Oper Name="DominatorTree" Arg="digraph, root"/>
  <Returns>A record.</Returns>
  <Description>
    <C>DominatorTree</C> takes a <A>digraph</A> and a
    <A>root</A> vertex and returns a record with the following components: 
    <List>
      <Mark>idom</Mark>
      <Item>
        the immediate dominators of the vertices with respect
        to the root.
      </Item>
      <Mark>preorder</Mark>
      <Item>
        the preorder values of the vertices defined by the depth first search
        executed on the digraph.
      </Item>
    </List>
    The <E>immediate dominator</E> of a vertex <M>u</M> is the unique dominator
    of <M>u</M> that is dominated by all other dominators of <M>u</M>. The
    algorithm is an implementation of the fast algorithm written by Thomas
    Lengauer and Robert Endre Tarjan <Cite Key="LT79"/>.  The complexity of
    this algorithm is <M>O(mlog n)</M> where <M>m</M> is the number of edges
    and <M>n</M> is the number of nodes in the subdigraph induced by the nodes
    in <A>digraph</A> reachable from <A>root</A>.
  <Example><![CDATA[
gap> D := Digraph([[2, 3], [4, 6], [4, 5], [3, 5], [1, 6], [2, 3]]);
<immutable digraph with 6 vertices, 12 edges>
gap> DominatorTree(D, 1);
rec( idom := [ fail, 1, 1, 1, 1, 1 ], 
  preorder := [ 1, 2, 4, 3, 5, 6 ] )
gap> DominatorTree(D, 5);
rec( idom := [ 5, 5, 5, 5, fail, 5 ], 
  preorder := [ 5, 1, 2, 4, 3, 6 ] )
gap> D := CompleteDigraph(5);
<immutable complete digraph with 5 vertices>
gap> DominatorTree(D, 1);
rec( idom := [ fail, 1, 1, 1, 1 ], preorder := [ 1, 2, 3, 4, 5 ] )
gap> DominatorTree(D, 2);
rec( idom := [ 2, fail, 2, 2, 2 ], preorder := [ 2, 1, 3, 4, 5 ] )
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="PartialOrderDigraphMeetOfVertices">
<ManSection>
  <Oper Name="PartialOrderDigraphMeetOfVertices"
    Arg="digraph, u, v"/>
  <Oper Name="PartialOrderDigraphJoinOfVertices"
    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> D := Digraph([[1], [1, 2], [1, 3], [1, 2, 3, 4]]);
<immutable digraph with 4 vertices, 9 edges>
gap> PartialOrderDigraphMeetOfVertices(D, 2, 3);
4
gap> PartialOrderDigraphJoinOfVertices(D, 2, 3);
1
gap> PartialOrderDigraphMeetOfVertices(D, 1, 2);
2
gap> PartialOrderDigraphJoinOfVertices(D, 3, 4);
3
gap> D := Digraph([[1], [2], [1, 2, 3], [1, 2, 4]]);
<immutable digraph with 4 vertices, 8 edges>
gap> PartialOrderDigraphMeetOfVertices(D, 3, 4);
fail
gap> PartialOrderDigraphJoinOfVertices(D, 3, 4);
fail
gap> PartialOrderDigraphMeetOfVertices(D, 1, 2);
fail
gap> PartialOrderDigraphJoinOfVertices(D, 1, 2);
fail
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphClosure">
<ManSection>
  <Oper Name="DigraphClosure" 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> D := CompleteDigraph(6);
<immutable complete digraph with 6 vertices>
gap> D := DigraphRemoveEdges(D, [[1, 2], [2, 1]]);
<immutable digraph with 6 vertices, 28 edges>
gap> closure := DigraphClosure(D, 6);
<immutable 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="IsMaximumMatching" 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 operation
    <C>IsMaximalMatching</C> returns <K>true</K> if <A>list</A> is a maximal 
    matching, <C>IsMaximumMatching</C> returns <K>true</K> if <A>list</A> is a
    maximum matching and <C>IsPerfectMatching</C> returns <K>true</K> if 
    <A>list</A> is a perfect, matching of <A>digraph</A>, respectively.  
    Otherwise, each of 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,
    is <E>maximum</E> if it has the greatest cardinality among all matchings and
    is <E>perfect</E> if every vertex of the digraph is incident to an edge in
    the matching.  Every maximum or perfect matching is maximal. Note, however,
    that not every perfect matching of digraphs with loops is maximum.

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

<#GAPDoc Label="DigraphDijkstra">
<ManSection>
  <Oper Name="DigraphDijkstra" Arg="digraph, source, target" Label="for a source and target"/>
  <Oper Name="DigraphDijkstra" Arg="digraph, source" Label="for a source"/>
  <Returns>Two lists.</Returns>
  <Description>
  If <A>digraph</A> is a digraph and <A>source</A> and <A>target</A>  are
  vertices of <A>digraph</A>, then <C>DigraphDijkstra</C> calculates the
  length of the shortest path from <A>source</A> to <A>target</A> and returns
  two lists. Each element of the first list is the distance of the
  corresponding element from <A>source</A>.  If a vertex was not visited in
  the process of calculating the shortest distance to <A>target</A> or if
  there is no path connecting that vertex with <A>source</A>, then
  the corresponding distance is <K>infinity</K>.  Each element of the
  second list gives the previous vertex in the shortest path
  from <A>source</A> to the corresponding vertex.  For
  <A>source</A> and for any vertices that remained unvisited this
    will be <C>-1</C>.<P/>

    If the optional second argument <A>target</A> is not present, then
    <C>DigraphDijkstra</C> returns the shortest path from <A>source</A> to
    every vertex that is reachable from <A>source</A>.

  <Example><![CDATA[
gap> mat := [[0, 1, 1], [0, 0, 1], [0, 0, 0]];
[ [ 0, 1, 1 ], [ 0, 0, 1 ], [ 0, 0, 0 ] ]
gap> D := DigraphByAdjacencyMatrix(mat);
<immutable digraph with 3 vertices, 3 edges>
gap> DigraphDijkstra(D, 2, 3);
[ [ infinity, 0, 1 ], [ -1, -1, 2 ] ]
gap> DigraphDijkstra(D, 1, 3);
[ [ 0, 1, 1 ], [ -1, 1, 1 ] ]
gap> DigraphDijkstra(D, 1, 2);
[ [ 0, 1, 1 ], [ -1, 1, 1 ] ]
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="ModularProduct">
<ManSection>
  <Oper Name="ModularProduct" Arg="D1, D2"/>
  <Returns>A digraph.</Returns>
  <Description>
  If <A>D1</A> and <A>D2</A> are digraphs without multiple edges, then
  <C>ModularProduct</C> calculates the <E>modular product digraph</E>
  (<C>MPD</C>) of <A>D1</A> and <A>D2</A>.

  <C>MPD</C> has vertex set <C>V1 x V2</C> where <C>V1</C> is the vertex set of
  <A>D1</A> and <C>V2</C> is the vertex set of <A>D2</A> (a vertex
  <C>[a, b]</C> has label <C>(a - 1) * |V2| + b</C> in the  output). There is
  an edge from <C>[a, b]</C> to <C>[c, d]</C> precisely when the following
  two conditions are satisfied:
  <List>
    <Item>
      The vertices <C>a</C> and <C>c</C> of <A>D1</A> are equal if and only if
      the vertices <C>b</C> and <C>d</C> of <A>D2</A> are equal.
    </Item>
    <Item>
      There is an edge from <C>a</C> to <C>c</C> in <A>D1</A> if and only if
      there is an edge from <C>b</C> to <C>d</C> in <A>D2</A>.
    </Item>
  </List>

  Notably, the complete (with loops) subdigraphs of <C>MPD</C> are
  precisely the partial isomorphisms from <A>D1</A> to <A>D2</A>.

  <Example><![CDATA[
gap> ModularProduct(Digraph([[1], [1, 2]]), Digraph([[], [2]]));
<immutable digraph with 4 vertices, 4 edges>
gap> OutNeighbours(last);
[ [ 4 ], [ 2, 3 ], [  ], [ 4 ] ]
gap> ModularProduct(PetersenGraph(),
> DigraphSymmetricClosure(CycleDigraph(5)));
<immutable digraph with 50 vertices, 950 edges>
gap> ModularProduct(NullDigraph(0), CompleteDigraph(10));
<immutable empty digraph with 0 vertices>
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="StrongProduct">
<ManSection>
  <Oper Name="StrongProduct" Arg="D1, D2"/>
  <Returns>A digraph.</Returns>
  <Description>
  If <A>D1</A> and <A>D2</A> are digraphs without multiple edges,
  then <C>StrongProduct</C> calculates the <E>strong product digraph</E>
  (<C>SPD</C>) of <A>D1</A> and <A>D2</A>.

  <C>SPD</C> has vertex set <C>V1 x V2</C> where <C>V1</C> is the vertex set of
  <A>D1</A> and <C>V2</C> is the vertex set of <A>D2</A> (a vertex
  <C>[a, b]</C> has label <C>(a - 1) * |V2| + b</C> in the  output). There is
  an edge from <C>[a, b]</C> to <C>[c, d]</C> when at least one of the
  following three conditions are satisfied:
  <List>
    <Item>
      The vertices <C>a</C> and <C>c</C> of <A>D1</A> are equal and there is
      an edge from <C>b</C> to <C>d</C> in <A>D2</A>.
    </Item>
    <Item>
      The vertices <C>b</C> and <C>d</C> of <A>D2</A> are equal and there is
      an edge from <C>a</C> to <C>c</C> in <A>D1</A>.
    </Item>
    <Item>
      There is an edge from <C>a</C> to <C>c</C> in <A>D1</A> and there is
      an edge from <C>b</C> to <C>d</C> in <A>D2</A>.
    </Item>
  </List>

  The SPD of two paths of lengths <C>m</C> and <C>n</C> is also the king's graph
  for an <C>m</C> by <C>n</C> board. 

  <Example><![CDATA[
gap> D1 := Digraph([[2], [1, 3, 4], [2, 5], [2, 5], [3, 4]]);
<immutable digraph with 5 vertices, 10 edges>
gap> D2 := Digraph([[2], [1, 3, 4], [2], [2]]);
<immutable digraph with 4 vertices, 6 edges>
gap> StrongProduct(D1, D2);
<immutable digraph with 20 vertices, 130 edges>
gap> StrongProduct(DigraphSymmetricClosure(ChainDigraph(3)),
> DigraphSymmetricClosure(ChainDigraph(4)));
<immutable digraph with 12 vertices, 58 edges>
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="ConormalProduct">
<ManSection>
  <Oper Name="ConormalProduct" Arg="D1, D2"/>
  <Returns>A digraph.</Returns>
  <Description>
  If <A>D1</A> and <A>D2</A> are digraphs without multiple edges,
  then <C>ConormalProduct</C> calculates the <E>co-normal product digraph</E>
  (<C>CNPD</C>) of <A>D1</A> and <A>D2</A>.

  <C>CNPD</C> has vertex set <C>V1 x V2</C> where <C>V1</C> is the vertex set of
  <A>D1</A> and <C>V2</C> is the vertex set of <A>D2</A> (a vertex
  <C>[a, b]</C> has label <C>(a - 1) * |V2| + b</C> in the  output). There is
  an edge from <C>[a, b]</C> to <C>[c, d]</C> when at least one of the
  following two conditions are satisfied:
  <List>
    <Item>
      There is an edge from <C>a</C> to <C>c</C> in <A>D1</A>.
    </Item>
    <Item>
      There is an edge from <C>b</C> to <C>d</C> in <A>D2</A>.
    </Item>
  </List>

  <Example><![CDATA[
gap> ConormalProduct(DigraphSymmetricClosure(CycleDigraph(7)),
> DigraphSymmetricClosure(CycleDigraph(4)));
<immutable digraph with 28 vertices, 504 edges>
gap> ConormalProduct(NullDigraph(0), CompleteDigraph(10));
<immutable empty digraph with 0 vertices>
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="HomomorphicProduct">
<ManSection>
  <Oper Name="HomomorphicProduct" Arg="D1, D2"/>
  <Returns>A digraph.</Returns>
  <Description>
  If <A>D1</A> and <A>D2</A> are digraphs without multiple edges,
  then <C>HomomorphicProduct</C> calculates the <E>homomorphic product digraph</E>
  (<C>HPD</C>) of <A>D1</A> and <A>D2</A>.

  <C>HPD</C> has vertex set <C>V1 x V2</C> where <C>V1</C> is the vertex set of
  <A>D1</A> and <C>V2</C> is the vertex set of <A>D2</A> (a vertex
  <C>[a, b]</C> has label <C>(a - 1) * |V2| + b</C> in the  output). There is
  an edge from <C>[a, b]</C> to <C>[c, d]</C> when at least one of the
  following two conditions are satisfied:
  <List>
    <Item>
      The vertices <C>a</C> and <C>c</C> of <A>D1</A> are equal.
    </Item>
    <Item>
      There is an edge from <C>a</C> to <C>c</C> in <A>D1</A> and no edge from
      <C>b</C> to <C>d</C> in <A>D2</A>.
    </Item>
  </List>

  <Example><![CDATA[
gap> HomomorphicProduct(PetersenGraph(),
> DigraphSymmetricClosure(ChainDigraph(4)));
<immutable digraph with 40 vertices, 460 edges>
gap> D1 := Digraph([[2], [1, 3, 4], [2, 5], [2, 5], [3, 4]]);
<immutable digraph with 5 vertices, 10 edges>
gap> D2 := Digraph([[2], [1, 3], [2, 4], [3]]);
<immutable digraph with 4 vertices, 6 edges>
gap> HomomorphicProduct(D1, D2);
<immutable digraph with 20 vertices, 180 edges>
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="LexicographicProduct">
<ManSection>
  <Oper Name="LexicographicProduct" Arg="D1, D2"/>
  <Returns>A digraph.</Returns>
  <Description>
  If <A>D1</A> and <A>D2</A> are digraphs without multiple edges,
  then <C>LexicographicProduct</C> calculates the <E>lexicographic product digraph</E>
  (<C>LPD</C>) of <A>D1</A> and <A>D2</A>.

  <C>LPD</C> has vertex set <C>V1 x V2</C> where <C>V1</C> is the vertex set of
  <A>D1</A> and <C>V2</C> is the vertex set of <A>D2</A> (a vertex
  <C>[a, b]</C> has label <C>(a - 1) * |V2| + b</C> in the  output). There is
  an edge from <C>[a, b]</C> to <C>[c, d]</C> when at least one of the
  following two conditions are satisfied:
  <List>
    <Item>
      There is an edge from <C>a</C> to <C>c</C> in <A>D1</A>.
    </Item>
    <Item>
      The vertices <C>a</C> and <C>c</C> of <A>D1</A> are equal and there is
      an edge from <C>b</C> to <C>d</C> in <A>D2</A>.
    </Item>
  </List>

  <Example><![CDATA[
gap> LexicographicProduct(DigraphSymmetricClosure(CycleDigraph(3)),
> DigraphSymmetricClosure(ChainDigraph(2)));
<immutable digraph with 6 vertices, 30 edges>
gap> OutNeighbours(last);
[ [ 2, 3, 4, 5, 6 ], [ 1, 3, 4, 5, 6 ], [ 1, 2, 4, 5, 6 ], 
  [ 1, 2, 3, 5, 6 ], [ 1, 2, 3, 4, 6 ], [ 1, 2, 3, 4, 5 ] ]
gap> LexicographicProduct(NullDigraph(0), CompleteDigraph(10));
<immutable empty digraph with 0 vertices>
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>  

<#GAPDoc Label="IsDigraphPath">
<ManSection>
  <Oper Name="IsDigraphPath" Arg="D, v, a"/>
  <Oper Name="IsDigraphPath" Arg="D, list" Label="for a digraph and list"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This function returns <K>true</K> if the arguments <A>v</A> and <A>a </A>
    describe a path in the digraph <A>D</A>.

    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>[<A>v</A>, <A>a</A>]</C> as follows:

    <List>
      <Item>
        <A>v</A> is the list <M>[v_1, v_2, ..., v_n]</M>.
      </Item>
      <Item>
        <A>a</A> 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>D</A><C>,</C><M>v_i</M><C>)</C>
        corresponding to the edge <M>e_i</M>.  This can be useful if the
        position of a vertex in a list of out-neighours is significant, for
        example in orbit digraphs.
      </Item>
    </List>

    If the arguments to <C>IsDigraphPath</C> are a digraph <A>D</A> and list
    <A>list</A>, then this is equivalent to calling <C>IsDigraphPath(<A>D</A>,
    <A>list</A>[1], <A>list</A>[2])</C>.

    <Example><![CDATA[
gap> D := Digraph(IsMutableDigraph, Combinations([1 .. 5]), IsSubset);
<mutable digraph with 32 vertices, 243 edges>
gap> DigraphReflexiveTransitiveReduction(D);
<mutable digraph with 32 vertices, 80 edges>
gap> MakeImmutable(D);
<immutable digraph with 32 vertices, 80 edges>
gap> IsDigraphPath(D, [32, 31, 33], [1, 1]);
false
gap> IsDigraphPath(D, [1], []);
true
gap> IsDigraphPath(D, [6, 9, 16, 17], [3, 3, 2]);
true
gap> IsDigraphPath(D, DigraphPath(D, 6, 1));
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>
