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

<#GAPDoc Label="IsMultiDigraph">
<ManSection>
  <Prop Name="IsMultiDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    A <E>multidigraph</E> is one that has at least two
    edges with equal source and range.<P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph(["a", "b", "c"], ["a", "b", "b"], ["b", "c", "a"]);
<immutable digraph with 3 vertices, 3 edges>
gap> IsMultiDigraph(D);
false
gap> D := DigraphFromDigraph6String("&Bug");
<immutable digraph with 3 vertices, 6 edges>
gap> IsDuplicateFree(DigraphEdges(D));
true
gap> IsMultiDigraph(D);
false
gap> D := Digraph([[1, 2, 3, 2], [2, 1], [3]]);
<immutable multidigraph with 3 vertices, 7 edges>
gap> IsDuplicateFree(DigraphEdges(D));
false
gap> IsMultiDigraph(D);
true
gap> D := DigraphMutableCopy(D); 
<mutable multidigraph with 3 vertices, 7 edges>
gap> IsMultiDigraph(D);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphHasLoops">
<ManSection>
  <Prop Name="DigraphHasLoops" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    Returns <K>true</K> if the digraph <A>digraph</A> has loops, and
    <K>false</K> if it does not. A loop is an edge with equal source and range.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[1, 2], [2]]);
<immutable digraph with 2 vertices, 3 edges>
gap> DigraphEdges(D);
[ [ 1, 1 ], [ 1, 2 ], [ 2, 2 ] ]
gap> DigraphHasLoops(D);
true
gap> D := Digraph([[2, 3], [1], [2]]);
<immutable digraph with 3 vertices, 4 edges>
gap> DigraphEdges(D);
[ [ 1, 2 ], [ 1, 3 ], [ 2, 1 ], [ 3, 2 ] ]
gap> DigraphHasLoops(D);
false
gap> D := CompleteDigraph(IsMutableDigraph, 4);
<mutable digraph with 4 vertices, 12 edges>
gap> DigraphHasLoops(D);
false]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsAcyclicDigraph">
<ManSection>
  <Prop Name="IsAcyclicDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if the digraph <A>digraph</A> is acyclic, and
    <K>false</K> if it is not. A digraph is <E>acyclic</E> if every directed
    cycle on the digraph is trivial. See Section <Ref Subsect="Definitions"
      Style="Number" /> for the definition of a directed cycle, and of a trivial
    directed cycle.<P/>

    The method used in this operation has complexity <M>O(m+n)</M> where
    <M>m</M> is the number of edges (counting multiple edges as one) and
    <M>n</M> is the number of vertices in the digraph. <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> Petersen := Graph(SymmetricGroup(5), [[1, 2]], OnSets,
> function(x, y)
>   return IsEmpty(Intersection(x, y));
> end);;
gap> D := Digraph(Petersen);
<immutable digraph with 10 vertices, 30 edges>
gap> IsAcyclicDigraph(D);
false
gap> D := DigraphFromDiSparse6String(
> ".b_OGCIDBaPGkULEbQHCeRIdrHcuZMfRyDAbPhTi|zF");
<immutable digraph with 35 vertices, 34 edges>
gap> IsAcyclicDigraph(D);
true
gap> IsAcyclicDigraph(ChainDigraph(10));
true
gap> D := CompleteDigraph(IsMutableDigraph, 4);
<mutable digraph with 4 vertices, 12 edges>
gap> IsAcyclicDigraph(D);
false
gap> IsAcyclicDigraph(CycleDigraph(10));
false]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsAperiodicDigraph">
<ManSection>
  <Prop Name="IsAperiodicDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if the digraph <A>digraph</A>
    is aperiodic, i.e. if its <Ref Attr = "DigraphPeriod"/> is equal to 1.
    Otherwise, the property is <K>false</K>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[6], [1], [2], [3], [4, 4], [5]]);
<immutable multidigraph with 6 vertices, 7 edges>
gap> IsAperiodicDigraph(D);
false
gap> D := Digraph([[2], [3, 5], [4], [5], [1, 2]]);
<immutable digraph with 5 vertices, 7 edges>
gap> IsAperiodicDigraph(D);
true
gap> D := Digraph(IsMutableDigraph, [[2], [3, 5], [4], [5], [1, 2]]);
<mutable digraph with 5 vertices, 7 edges>
gap> IsAperiodicDigraph(D);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsStronglyConnectedDigraph">
<ManSection>
  <Prop Name="IsStronglyConnectedDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if the digraph <A>digraph</A> is strongly
    connected and <K>false</K> if it is not. <P/>

    A digraph <A>digraph</A> is <E>strongly connected</E> if there is a directed
    path from every vertex to every other vertex.  See Section <Ref
      Subsect="Definitions" Style="Number" /> for the definition of a directed
    path.    <P/>

    The method used in this operation is based on Gabow's Algorithm <Cite
      Key="Gab00"/> and has complexity <M>O(m+n)</M>, where <M>m</M> is
    the number of edges (counting multiple edges as one) and <M>n</M> is the
    number of vertices in the digraph.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := CycleDigraph(250000);
<immutable cycle digraph with 250000 vertices>
gap> IsStronglyConnectedDigraph(D);
true
gap> D := DigraphRemoveEdges(D, [[250000, 1]]);
<immutable digraph with 250000 vertices, 249999 edges>
gap> IsStronglyConnectedDigraph(D);
false
gap> D := CycleDigraph(IsMutableDigraph, 250000);
<mutable digraph with 250000 vertices, 250000 edges>
gap> IsStronglyConnectedDigraph(D);
true
gap> DigraphRemoveEdge(D, [250000, 1]);
<mutable digraph with 250000 vertices, 249999 edges>
gap> IsStronglyConnectedDigraph(D);
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsConnectedDigraph">
<ManSection>
  <Prop Name="IsConnectedDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if the digraph <A>digraph</A>
    is weakly connected and <K>false</K> if it is not.  A digraph
    <A>digraph</A> is <E>weakly connected</E> if it is possible to travel
    from any vertex to any other vertex by traversing edges in either
    direction (possibly against the orientation of some of them). <P/>

    The method used in this function has complexity <M>O(m)</M> if the
    digraph's <Ref Attr="DigraphSource"/> attribute is set, otherwise it has
    complexity <M>O(m+n)</M> (where
    <M>m</M> is the number of edges and
    <M>n</M> is the number of vertices of the digraph).
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[2], [3], []]);;
gap> IsConnectedDigraph(D);
true
gap> D := Digraph([[1, 3], [4], [3], []]);;
gap> IsConnectedDigraph(D);
false
gap> D := Digraph(IsMutableDigraph, [[2], [3], []]);;
gap> IsConnectedDigraph(D);
true
gap> D := Digraph(IsMutableDigraph, [[1, 3], [4], [3], []]);;
gap> IsConnectedDigraph(D);
false]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsBiconnectedDigraph">
<ManSection>
  <Prop Name="IsBiconnectedDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    A connected digraph is <E>biconnected</E> if it is still connected (in the
    sense of <Ref Prop="IsConnectedDigraph"/>) when any vertex is removed. 
      If <A>D</A> has at least 3 vertices, then <C>IsBiconnectedDigraph</C>
      implies <Ref Prop="IsBridgelessDigraph"/>;
    see <Ref Attr="ArticulationPoints"/> or <Ref Attr="Bridges"/> for a more
    detailed explanation.
    <P/>

    <C>IsBiconnectedDigraph</C> returns <K>true</K> if the digraph
    <A>digraph</A> is biconnected, and <K>false</K> if it is not. In
    particular, <C>IsBiconnectedDigraph</C> returns <K>false</K> if
    <A>digraph</A> is not connected. <P/>

    Multiple edges are ignored by this method. <P/>

    The method used in this operation has complexity <M>O(m+n)</M> where
    <M>m</M> is the number of edges and <M>n</M> is the number of vertices in
    the digraph.
    <P/>

    See also <Ref Attr="Bridges"/>, <Ref Attr="ArticulationPoints"/>, and 
    <Ref Prop="IsBridgelessDigraph"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> IsBiconnectedDigraph(Digraph([[1, 3], [2, 3], [3]]));
false
gap> IsBiconnectedDigraph(CycleDigraph(5));
true
gap> D := Digraph([[1, 1], [1, 1, 2], [3], [3, 3, 4, 4]]);;
gap> IsBiconnectedDigraph(D);
false
gap> D := CompleteBipartiteDigraph(IsMutableDigraph, 5, 4);
<mutable digraph with 9 vertices, 40 edges>
gap> IsBiconnectedDigraph(D);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsBipartiteDigraph">
<ManSection>
  <Prop Name="IsBipartiteDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
  This property is <K>true</K> if the digraph <A>digraph</A> is bipartite, and
  <K>false</K> if it is not.  A digraph is bipartite if and only if the
  vertices of <A>digraph</A> can be partitioned into two non-empty sets such
  that the source and range of any edge of <A>digraph</A> lie in distinct sets.
  Equivalently, a digraph is bipartite if and only if it is 2-colorable; see
  <Ref Attr="DigraphGreedyColouring" Label="for a digraph"/>. <P/>

  See also <Ref Attr="DigraphBicomponents"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := ChainDigraph(4);
<immutable chain digraph with 4 vertices>
gap> IsBipartiteDigraph(D);
true
gap> D := CycleDigraph(3);
<immutable cycle digraph with 3 vertices>
gap> IsBipartiteDigraph(D);
false
gap> D := CompleteBipartiteDigraph(IsMutableDigraph, 5, 4);
<mutable digraph with 9 vertices, 40 edges>
gap> IsBipartiteDigraph(D);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsCompleteBipartiteDigraph">
<ManSection>
  <Prop Name="IsCompleteBipartiteDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    Returns <K>true</K> if the digraph <A>digraph</A> is a complete bipartite
    digraph, and <K>false</K> if it is not. <P/>

    A digraph is a <E>complete bipartite digraph</E> if it is bipartite, see
    <Ref Prop="IsBipartiteDigraph"/>, and there exists a unique edge with
    source <C>i</C> and range <C>j</C> if and only if <C>i</C> and <C>j</C> lie
    in different bicomponents of <A>digraph</A>, see <Ref
      Attr="DigraphBicomponents"/>. <P/>

    Equivalently, a bipartite digraph with bicomponents of size <M>m</M> and
    <M>n</M> is complete precisely when it has <M>2mn</M> edges, none of which
    are multiple edges. <P/>

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

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := CycleDigraph(2);
<immutable cycle digraph with 2 vertices>
gap> IsCompleteBipartiteDigraph(D);
true
gap> D := CycleDigraph(4);
<immutable cycle digraph with 4 vertices>
gap> IsBipartiteDigraph(D);
true
gap> IsCompleteBipartiteDigraph(D);
false
gap> D := CompleteBipartiteDigraph(IsMutableDigraph, 5, 4);
<mutable digraph with 9 vertices, 40 edges>
gap> IsCompleteBipartiteDigraph(D);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsCompleteMultipartiteDigraph">
<ManSection>
  <Prop Name="IsCompleteMultipartiteDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property returns <K>true</K> if <A>digraph</A> is a complete
    multipartite digraph, and <K>false</K> if not. <P/>

    A digraph is a <E>complete multipartite digraph</E> if and only if
    its vertices can be partitioned into at least two maximal independent sets,
    where every possible edge between these independent sets occurs in the
    digraph exactly once.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := CompleteMultipartiteDigraph([2, 4, 6]);
<immutable complete multipartite digraph with 12 vertices, 88 edges>
gap> IsCompleteMultipartiteDigraph(D);
true
gap> D := CompleteBipartiteDigraph(IsMutableDigraph, 5, 4);
<mutable digraph with 9 vertices, 40 edges>
gap> IsCompleteMultipartiteDigraph(D);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsCompleteDigraph">
<ManSection>
  <Prop Name="IsCompleteDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    Returns <K>true</K> if the digraph <A>digraph</A> is complete, and
    <K>false</K> if it is not. <P/>

    A digraph is <E>complete</E> if it has no loops, and for all
    <E>distinct</E> vertices <C>i</C> and <C>j</C>,
    there is exactly one edge with source <C>i</C> and range <C>j</C>.

    Equivalently, a digraph with <M>n</M> vertices is complete precisely when
    it has <M>n(n - 1)</M> edges, no loops, and no multiple edges.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[2, 3], [1, 3], [1, 2]]);
<immutable digraph with 3 vertices, 6 edges>
gap> IsCompleteDigraph(D);
true
gap> D := Digraph([[2, 2], [1]]);
<immutable multidigraph with 2 vertices, 3 edges>
gap> IsCompleteDigraph(D);
false
gap> D := CompleteBipartiteDigraph(IsMutableDigraph, 5, 4);
<mutable digraph with 9 vertices, 40 edges>
gap> IsCompleteDigraph(D);
false]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsTournament">
<ManSection>
  <Prop Name="IsTournament" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if the digraph <A>digraph</A> is a tournament,
    and <K>false</K> if it is not. <P/>

    A tournament is an orientation of a complete (undirected) graph.
    Specifically, a tournament is a digraph which has a unique directed edge
    (of some orientation) between any pair of distinct vertices, and no loops.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[2, 3, 4], [3, 4], [4], []]);
<immutable digraph with 4 vertices, 6 edges>
gap> IsTournament(D);
true
gap> D := Digraph([[2], [1], [3]]);
<immutable digraph with 3 vertices, 3 edges>
gap> IsTournament(D);
false
gap> D := CycleDigraph(IsMutableDigraph, 3);
<mutable digraph with 3 vertices, 3 edges>
gap> IsTournament(D);
true
gap> DigraphRemoveEdge(D, 1, 2);
<mutable digraph with 3 vertices, 2 edges>
gap> IsTournament(D);
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsChainDigraph">
<ManSection>
  <Prop Name="IsChainDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    <C>IsChainDigraph</C> returns <K>true</K> if the digraph <A>digraph</A> is
    isomorphic to the chain digraph with the same number of vertices as
    <A>digraph</A>, and <K>false</K> if it is not; see <Ref
      Oper="ChainDigraph"/>.<P/>

    A digraph is a <E>chain</E> if and only if it is a directed tree, in which
    every vertex has out degree at most one; see <Ref Prop="IsDirectedTree"/>
    and <Ref Attr="OutDegrees"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[1, 3], [2, 3], [3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> IsChainDigraph(D);
false
gap> D := ChainDigraph(5);
<immutable chain digraph with 5 vertices>
gap> IsChainDigraph(D);
true
gap> D := DigraphReverse(D);
<immutable digraph with 5 vertices, 4 edges>
gap> IsChainDigraph(D);
true
gap> D := ChainDigraph(IsMutableDigraph, 5);
<mutable digraph with 5 vertices, 4 edges>
gap> IsChainDigraph(D);
true
gap> DigraphReverse(D);
<mutable digraph with 5 vertices, 4 edges>
gap> IsChainDigraph(D);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsCycleDigraph">
<ManSection>
  <Prop Name="IsCycleDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    <C>IsCycleDigraph</C> returns <K>true</K> if the digraph <A>digraph</A> is
    isomorphic to the cycle digraph with the same number of vertices as
    <A>digraph</A>, and <K>false</K> if it is not; see <Ref
      Oper="CycleDigraph"/>.<P/>

    A digraph is a <E>cycle</E> if and only if it is strongly connected and has
    the same number of edges as vertices. 
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[1, 3], [2, 3], [3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> IsCycleDigraph(D);
false
gap> D := CycleDigraph(5);
<immutable cycle digraph with 5 vertices>
gap> IsCycleDigraph(D);
true
gap> D := OnDigraphs(D, (1, 2, 3));
<immutable digraph with 5 vertices, 5 edges>
gap> D = CycleDigraph(5);
false
gap> IsCycleDigraph(D);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsDigraphCore">
<ManSection>
  <Prop Name="IsDigraphCore" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property returns <K>true</K> if <A>digraph</A> is a core,
    and <K>false</K> if it is not.<P/>

    A digraph <C>D</C> is a <E>core</E> if and only if it has no proper
    subdigraphs <C>A</C> such that there exists a homomorphism from <C>D</C>
    to <C>A</C>. In other words, a digraph <C>D</C> is a core if and only if
    every endomorphism on <C>D</C> is an automorphism on <C>D</C>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := CompleteDigraph(6);
<immutable complete digraph with 6 vertices>
gap> IsDigraphCore(D);
true
gap> D := DigraphSymmetricClosure(CycleDigraph(6));
<immutable symmetric digraph with 6 vertices, 12 edges>
gap> DigraphHomomorphism(D, CompleteDigraph(2));
Transformation( [ 1, 2, 1, 2, 1, 2 ] )
gap> IsDigraphCore(D);
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsDirectedTree">
<ManSection>
  <Prop Name="IsDirectedTree" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    Returns <K>true</K> if the digraph <A>digraph</A> is a directed tree, and
    <K>false</K> if it is not. <P/>

    A <E>directed tree</E> is an acyclic digraph with precisely 1 source,
    such that no two vertices share an out-neighbour.
    Note that the empty digraph with zero vertices is not considered
    to be a directed tree, because it has no source. <P/>

    See also <Ref Attr="DigraphSources"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

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

<#GAPDoc Label="IsUndirectedTree">
<ManSection>
  <Prop Name="IsUndirectedTree" Arg="digraph"/>
  <Prop Name="IsUndirectedForest" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    The property <C>IsUndirectedTree</C> returns <K>true</K> if the digraph
    <A>digraph</A> is an undirected tree, and the property
    <C>IsUndirectedForest</C> returns <K>true</K> if <A>digraph</A> is an
    undirected forest; otherwise, these properties return <K>false</K>. <P/>

    An <E>undirected tree</E> is a symmetric digraph without loops, in which for
    any pair of distinct vertices <C>u</C> and <C>v</C>, there is exactly one
    directed path from <C>u</C> to <C>v</C>. See <Ref
      Prop="IsSymmetricDigraph"/> and <Ref Prop="DigraphHasLoops"/>, and see
    Section <Ref Subsect="Definitions" Style="Number" /> for the definition of
    directed path. This definition implies that an undirected tree has
    no multiple edges. <P/>

    An <E>undirected forest</E> is a digraph, each of whose connected components
    is an undirected tree. In other words, an undirected forest is isomorphic to
    a disjoint union of undirected trees. See <Ref
      Attr="DigraphConnectedComponents" /> and <Ref Func="DigraphDisjointUnion"
      Label="for a list of digraphs" />. In particular, every
    undirected tree is an undirected forest. <P/>

    Please note that the digraph with zero vertices is considered to be neither
    an undirected tree nor an undirected forest.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[3], [3], [1, 2]]);
<immutable digraph with 3 vertices, 4 edges>
gap> IsUndirectedTree(D);
true
gap> IsSymmetricDigraph(D) and not DigraphHasLoops(D);
true
gap> D := Digraph([[3], [5], [1, 4], [3], [2]]);
<immutable digraph with 5 vertices, 6 edges>
gap> IsConnectedDigraph(D);
false
gap> IsUndirectedTree(D);
false
gap> IsUndirectedForest(D);
true
gap> D := Digraph([[1, 2], [1], [2]]);
<immutable digraph with 3 vertices, 4 edges>
gap> IsUndirectedTree(D) or IsUndirectedForest(D);
false
gap> IsSymmetricDigraph(D) or not DigraphHasLoops(D);
false]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsEdgeTransitive">
<ManSection>
  <Prop Name="IsEdgeTransitive" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    If <A>digraph</A> is a digraph without multiple edges, then
    <C>IsEdgeTransitive</C> returns <K>true</K> if <A>digraph</A>
    is edge transitive, and <K>false</K> otherwise. A digraph is
    <E>edge transitive</E> if its automorphism group acts
    transitively on its edges (via the action
    <Ref Func="OnPairs" BookName="ref"/>).
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> IsEdgeTransitive(CompleteDigraph(2));
true
gap> IsEdgeTransitive(ChainDigraph(3));
false
gap> IsEdgeTransitive(Digraph([[2], [3, 3, 3], []]));
Error, the argument <D> must be a digraph with no multiple edges,
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsVertexTransitive">
<ManSection>
  <Prop Name="IsVertexTransitive" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    If <A>digraph</A> is a digraph, then <C>IsVertexTransitive</C> returns
    <K>true</K> if <A>digraph</A> is vertex transitive, and <K>false</K>
    otherwise. A digraph is <E>vertex transitive</E> if its automorphism group
    acts transitively on its vertices.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> IsVertexTransitive(CompleteDigraph(2));
true
gap> IsVertexTransitive(ChainDigraph(3));
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsEmptyDigraph">
<ManSection>
  <Prop Name="IsEmptyDigraph" Arg="digraph"/>
  <Prop Name="IsNullDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    Returns <K>true</K> if the digraph <A>digraph</A> is empty, and
    <K>false</K> if it is not. A digraph is <E>empty</E> if it has no
    edges.<P/>

    <Ref Prop="IsNullDigraph"/> is a synonym for <Ref Prop="IsEmptyDigraph"/>.
    See also <Ref Prop="IsNonemptyDigraph"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[], []]);
<immutable empty digraph with 2 vertices>
gap> IsEmptyDigraph(D);
true
gap> IsNullDigraph(D);
true
gap> D := Digraph([[], [1]]);
<immutable digraph with 2 vertices, 1 edge>
gap> IsEmptyDigraph(D);
false
gap> IsNullDigraph(D);
false]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsNonemptyDigraph">
<ManSection>
  <Prop Name="IsNonemptyDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    Returns <K>true</K> if the digraph <A>digraph</A> is nonempty, and
    <K>false</K> if it is not. A digraph is <E>nonempty</E> if it has at
    least one edge.<P/>

    See also <Ref Prop="IsEmptyDigraph"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[], []]);
<immutable empty digraph with 2 vertices>
gap> IsNonemptyDigraph(D);
false
gap> D := Digraph([[], [1]]);
<immutable digraph with 2 vertices, 1 edge>
gap> IsNonemptyDigraph(D);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphHasAVertex">
<ManSection>
  <Prop Name="DigraphHasAVertex" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    Returns <K>true</K> if the digraph <A>digraph</A> has at least one vertex,
    and <K>false</K> if it does not.<P/>

    See also <Ref Prop="DigraphHasNoVertices"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([]);
<immutable empty digraph with 0 vertices>
gap> DigraphHasAVertex(D);
false
gap> D := Digraph([[]]);
<immutable empty digraph with 1 vertex>
gap> DigraphHasAVertex(D);
true
gap> D := Digraph([[], [1]]);
<immutable digraph with 2 vertices, 1 edge>
gap> DigraphHasAVertex(D);
true]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphHasNoVertices">
<ManSection>
  <Prop Name="DigraphHasNoVertices" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    Returns <K>true</K> if the digraph <A>digraph</A> is the unique digraph
    with zero vertices, and <K>false</K> otherwise.<P/>

    See also <Ref Prop="DigraphHasAVertex"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([]);
<immutable empty digraph with 0 vertices>
gap> DigraphHasNoVertices(D);
true
gap> D := Digraph([[]]);
<immutable empty digraph with 1 vertex>
gap> DigraphHasNoVertices(D);
false
gap> D := Digraph([[], [1]]);
<immutable digraph with 2 vertices, 1 edge>
gap> DigraphHasNoVertices(D);
false]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsEulerianDigraph">
<ManSection>
  <Prop Name="IsEulerianDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property returns true if the digraph <A>digraph</A> is Eulerian.
    <P/>

    A connected digraph is called <E>Eulerian</E> if there exists a directed
    circuit on the digraph which includes every edge exactly once.  See
    Section <Ref Subsect="Definitions" Style="Number" /> for the definition of
    a directed circuit. Note that the empty digraph with at most one vertex is
    considered to be Eulerian.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[]]);
<immutable empty digraph with 1 vertex>
gap> IsEulerianDigraph(D);
true
gap> D := Digraph([[2], []]);
<immutable digraph with 2 vertices, 1 edge>
gap> IsEulerianDigraph(D);
false
gap> D := Digraph([[3], [], [2]]);
<immutable digraph with 3 vertices, 2 edges>
gap> IsEulerianDigraph(D);
false
gap> D := Digraph([[2], [3], [1]]);
<immutable digraph with 3 vertices, 3 edges>
gap> IsEulerianDigraph(D);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsFunctionalDigraph">
<ManSection>
  <Prop Name="IsFunctionalDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if the digraph <A>digraph</A> is
    functional. <P/>

    A digraph is <E>functional</E> if every vertex is the source of a
    unique edge.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> gr1 := Digraph([[3], [2], [2], [1], [6], [5]]);
<immutable digraph with 6 vertices, 6 edges>
gap> IsFunctionalDigraph(gr1);
true
gap> gr2 := Digraph([[1, 2], [1]]);
<immutable digraph with 2 vertices, 3 edges>
gap> IsFunctionalDigraph(gr2);
false
gap> gr3 := Digraph(3, [1, 2, 3], [2, 3, 1]);
<immutable digraph with 3 vertices, 3 edges>
gap> IsFunctionalDigraph(gr3);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsPermutationDigraph">
<ManSection>
  <Prop Name="IsPermutationDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if the digraph <A>digraph</A> is
    functional and each node has only one in-neighbour. <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> gr1 := Digraph([[3], [2], [2], [1], [6], [5]]);
<immutable digraph with 6 vertices, 6 edges>
gap> IsPermutationDigraph(gr1);
false
gap> gr2 := Digraph([[1, 2], [1]]);
<immutable digraph with 2 vertices, 3 edges>
gap> IsPermutationDigraph(gr2);
false
gap> gr3 := Digraph(3, [1, 2, 3], [2, 3, 1]);
<immutable digraph with 3 vertices, 3 edges>
gap> IsPermutationDigraph(gr3);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsHamiltonianDigraph">
<ManSection>
  <Prop Name="IsHamiltonianDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    If <A>digraph</A> is Hamiltonian, then this property returns
    <K>true</K>, and <K>false</K> if it is not. <P/>

    A digraph with <C>n</C> vertices is <E>Hamiltonian</E> if it has a
    directed cycle of length <C>n</C>. See Section <Ref Subsect="Definitions"
     Style="Number" /> for the definition of a directed cycle.
    Note the empty digraphs on 0 and 1 vertices are considered to be
    Hamiltonian.<P/>

    The method used in this operation has the worst case complexity as
    <Ref Oper="DigraphMonomorphism"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> g := Digraph([[]]);
<immutable empty digraph with 1 vertex>
gap> IsHamiltonianDigraph(g);
true
gap> g := Digraph([[2], [1]]);
<immutable digraph with 2 vertices, 2 edges>
gap> IsHamiltonianDigraph(g);
true
gap> g := Digraph([[3], [], [2]]);
<immutable digraph with 3 vertices, 2 edges>
gap> IsHamiltonianDigraph(g);
false
gap> g := Digraph([[2], [3], [1]]);
<immutable digraph with 3 vertices, 3 edges>
gap> IsHamiltonianDigraph(g);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsRegularDigraph">
<ManSection>
  <Prop Name="IsRegularDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if there is an integer <C>n</C> such that
    for every vertex <C>v</C> of digraph <A>digraph</A> there are exactly
    <C>n</C> edges starting and terminating at <C>v</C>. In other words,
    the property is <K>true</K> if <A>digraph</A> is both in-regular and
    and out-regular.

    See also <Ref Prop="IsInRegularDigraph"/> and
    <Ref Prop="IsOutRegularDigraph"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> IsRegularDigraph(CompleteDigraph(4));
true
gap> IsRegularDigraph(ChainDigraph(4));
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsInRegularDigraph">
<ManSection>
  <Prop Name="IsInRegularDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if there is an integer <C>n</C> such that
    for every vertex <C>v</C> of digraph <A>digraph</A> there are exactly
    <C>n</C> edges terminating in <C>v</C>.

    See also <Ref Prop="IsOutRegularDigraph"/> and
    <Ref Prop="IsRegularDigraph"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> IsInRegularDigraph(CompleteDigraph(4));
true
gap> IsInRegularDigraph(ChainDigraph(4));
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsOutRegularDigraph">
<ManSection>
  <Prop Name="IsOutRegularDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if there is an integer <C>n</C> such that
    for every vertex <C>v</C> of digraph <A>digraph</A> there are exactly
    <C>n</C> edges starting at <C>v</C>.
    <P/>

    See also <Ref Prop="IsInRegularDigraph"/> and
    <Ref Prop="IsRegularDigraph"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> IsOutRegularDigraph(CompleteDigraph(4));
true
gap> IsOutRegularDigraph(ChainDigraph(4));
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsDistanceRegularDigraph">
<ManSection>
  <Prop Name="IsDistanceRegularDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    If <A>digraph</A> is a connected symmetric graph, this property returns
    <K>true</K> if for any two vertices <C>u</C> and <C>v</C> of <A>digraph</A>
    and any two integers <C>i</C> and <C>j</C> between <C>0</C> and the
    diameter of <A>digraph</A>, the number of vertices at distance <C>i</C>
    from <C>u</C> and distance <C>j</C> from <C>v</C> depends only on
    <C>i</C>, <C>j</C>, and the distance between vertices <C>u</C> and
    <C>v</C>.<P/>

    Alternatively, a distance regular graph is a graph for which there exist
    integers <C>b_i</C>, <C>c_i</C>, and <C>i</C> such that for any two
    vertices <C>u</C>, <C>v</C> in <A>digraph</A> which are distance <C>i</C>
    apart, there are exactly <C>b_i</C> neighbors of <C>v</C> which are at
    distance <C>i - 1</C> away from <C>u</C>, and <C>c_i</C> neighbors of
    <C>v</C> which are at distance <C>i + 1</C> away from <C>u</C>. This
    definition is used to check whether <A>digraph</A> is distance regular.<P/>

    In the case where <A>digraph</A> is not symmetric or not connected, the
    property is <K>false</K>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := DigraphSymmetricClosure(ChainDigraph(5));;
gap> IsDistanceRegularDigraph(D);
false
gap> D := Digraph([[2, 3, 4], [1, 3, 4], [1, 2, 4], [1, 2, 3]]);
<immutable digraph with 4 vertices, 12 edges>
gap> IsDistanceRegularDigraph(D);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsReflexiveDigraph">
<ManSection>
  <Prop Name="IsReflexiveDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if the digraph <A>digraph</A> is
    reflexive, and <K>false</K> if it is not.
    A digraph is <E>reflexive</E> if it has a loop at every vertex. <P/>
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

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

<#GAPDoc Label="IsSymmetricDigraph">
<ManSection>
  <Prop Name="IsSymmetricDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if the digraph <A>digraph</A>
    is symmetric, and <K>false</K> if it is not.<P/>

    A <E>symmetric digraph</E> is one where for each non-loop edge, having
    source <C>u</C> and range <C>v</C>, there is a corresponding edge with
    source <C>v</C> and range <C>u</C>.  If there are <C>n</C> edges with
    source <C>u</C> and range <C>v</C>, then there must be precisely <C>n</C>
    edges with source <C>v</C> and range <C>u</C>.  In other words, a symmetric
    digraph has a symmetric adjacency matrix <Ref Attr="AdjacencyMatrix"/>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> gr1 := Digraph([[2], [1, 3], [2, 3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> IsSymmetricDigraph(gr1);
true
gap> adj1 := AdjacencyMatrix(gr1);;
gap> Display(adj1);
[ [  0,  1,  0 ],
  [  1,  0,  1 ],
  [  0,  1,  1 ] ]
gap> adj1 = TransposedMat(adj1);
true
gap> gr1 = DigraphReverse(gr1);
true
gap> gr2 := Digraph([[2, 3], [1, 3], [2, 3]]);
<immutable digraph with 3 vertices, 6 edges>
gap> IsSymmetricDigraph(gr2);
false
gap> adj2 := AdjacencyMatrix(gr2);;
gap> Display(adj2);
[ [  0,  1,  1 ],
  [  1,  0,  1 ],
  [  0,  1,  1 ] ]
gap> adj2 = TransposedMat(adj2);
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsAntisymmetricDigraph">
<ManSection>
  <Prop Name="IsAntiSymmetricDigraph" Arg="digraph"/>
  <Prop Name="IsAntisymmetricDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if the digraph <A>digraph</A>
    is antisymmetric, and <K>false</K> if it is not.
    <P/>

    A digraph is <E>antisymmetric</E> if whenever there is an edge with source
    <C>u</C> and range <C>v</C>, and an edge with source <C>v</C> and range
    <C>u</C>, then the vertices <C>u</C> and <C>v</C> are equal.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> gr1 := Digraph([[2], [1, 3], [2, 3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> IsAntisymmetricDigraph(gr1);
false
gap> DigraphEdges(gr1){[1, 2]};
[ [ 1, 2 ], [ 2, 1 ] ]
gap> gr2 := Digraph([[1, 2], [3, 3], [1]]);
<immutable multidigraph with 3 vertices, 5 edges>
gap> IsAntisymmetricDigraph(gr2);
true
gap> DigraphEdges(gr2);
[ [ 1, 1 ], [ 1, 2 ], [ 2, 3 ], [ 2, 3 ], [ 3, 1 ] ]
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsTransitiveDigraph">
<ManSection>
  <Prop Name="IsTransitiveDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    This property is <K>true</K> if the digraph <A>digraph</A>
    is transitive, and <K>false</K> if it is not.

    A digraph is <E>transitive</E> if whenever <C>[ i, j ]</C> and
    <C>[ j, k ]</C> are edges of the digraph, then <C>[ i, k ]</C> is also an
    edge of the digraph. <P/>

    Let <M>n</M> be the number of vertices of an arbitrary digraph, and let
        <M>m</M> be the number of edges.
    For general digraphs, the methods used for this property use a version
    of the Floyd-Warshall algorithm, and have complexity <M>O(n^3)</M>.

    However for digraphs which are topologically sortable
    [<Ref Attr="DigraphTopologicalSort"/>], then methods with
    complexity <M>O(m + n + m \cdot n)</M> will be used when appropriate.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[1, 2], [3], [3]]);
<immutable digraph with 3 vertices, 4 edges>
gap> IsTransitiveDigraph(D);
false
gap> gr2 := Digraph([[1, 2, 3], [3], [3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> IsTransitiveDigraph(gr2);
true
gap> gr2 = DigraphTransitiveClosure(D);
true
gap> gr3 := Digraph([[1, 2, 2, 3], [3, 3], [3]]);
<immutable multidigraph with 3 vertices, 7 edges>
gap> IsTransitiveDigraph(gr3);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsMeetSemilatticeDigraph">
<ManSection>
  <Prop Name="IsMeetSemilatticeDigraph" Arg="digraph"/>
  <Prop Name="IsJoinSemilatticeDigraph" Arg="digraph"/>
  <Prop Name="IsLatticeDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    <C>IsMeetSemilatticeDigraph</C> returns <K>true</K> if the digraph
    <A>digraph</A> is a meet semilattice; <C>IsJoinSemilatticeDigraph</C>
    returns <K>true</K> if the digraph <A>digraph</A> is a join semilattice;
    and  <C>IsLatticeDigraph</C> returns <K>true</K> if the digraph
    <A>digraph</A> is both a meet and a join semilattice.
    <P/>

    For a partial order digraph <Ref Prop="IsPartialOrderDigraph"/> the
    corresponding partial order is the relation <M>\leq</M>, defined by
    <M>x \leq y</M> if and only if <C>[x, y]</C> is an edge.
    A digraph is a <E>meet semilattice</E> if it is a partial order and every
    pair of vertices has a greatest lower bound (meet) with respect to the
    aforementioned relation. A <E>join semilattice</E> is a partial order where
    every pair of vertices has a least upper bound (join) with respect to
    the relation.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[1, 3], [2, 3], [3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> IsMeetSemilatticeDigraph(D);
false
gap> IsJoinSemilatticeDigraph(D);
true
gap> IsLatticeDigraph(D);
false
gap> D := Digraph([[1], [2], [1 .. 3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> IsJoinSemilatticeDigraph(D);
false
gap> IsMeetSemilatticeDigraph(D);
true
gap> IsLatticeDigraph(D);
false
gap> D := Digraph([[1 .. 4], [2, 4], [3, 4], [4]]);
<immutable digraph with 4 vertices, 9 edges>
gap> IsMeetSemilatticeDigraph(D);
true
gap> IsJoinSemilatticeDigraph(D);
true
gap> IsLatticeDigraph(D);
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsDistributiveLatticeDigraph">
<ManSection>
  <Prop Name="IsDistributiveLatticeDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    <C>IsDistributiveLatticeDigraph</C> returns <K>true</K> if the digraph
    <A>digraph</A> is a <E>distributive lattice digraph</E>.<P/>

    A <E>distributive lattice digraph</E> is a <E>lattice digraph</E>
    (<Ref Prop="IsLatticeDigraph"/>) which is distributive. That is to say,
    the functions <Ref Oper="PartialOrderDigraphMeetOfVertices"/> and
    <Ref Oper="PartialOrderDigraphJoinOfVertices"/> distribute over each other.<P/>
    
    Equivalently, a <E>distributive lattice digraph</E> is a <E>lattice digraph</E>
    in which the <E>lattice digraphs</E> representing <M>M3</M> and <M>N5</M> are
    not embeddable as lattices
    (see <URL>https://en.wikipedia.org/wiki/Distributive_lattice</URL> and
    <Ref Prop="IsLatticeEmbedding" 
    Label="for digraphs and a permutation or transformation"/>).<P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[2, 3], [4], [4], []]);
<immutable digraph with 4 vertices, 4 edges>
gap> D := DigraphReflexiveTransitiveClosure(D);
<immutable preorder digraph with 4 vertices, 9 edges>
gap> IsDistributiveLatticeDigraph(D);
true
gap> N5 := Digraph([[2, 4], [3], [5], [5], []]);
<immutable digraph with 5 vertices, 5 edges>
gap> N5 := DigraphReflexiveTransitiveClosure(N5);
<immutable preorder digraph with 5 vertices, 13 edges>
gap> IsDistributiveLatticeDigraph(N5);
false]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>


<#GAPDoc Label="IsPreorderDigraph">
<ManSection>
  <Prop Name="IsPreorderDigraph" Arg="digraph"/>
  <Prop Name="IsQuasiorderDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    A digraph is a preorder digraph if and only if the digraph satisfies both
    <Ref Prop="IsReflexiveDigraph"/> and <Ref Prop="IsTransitiveDigraph"/>.
    A preorder digraph (or quasiorder digraph) <A>digraph</A> corresponds to
    the preorder relation <M>\leq</M> defined by <M>x \leq y</M> if and only
    if <C>[x, y]</C> is an edge of <A>digraph</A>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := Digraph([[1], [2, 3], [2, 3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> IsPreorderDigraph(D);
true
gap> D := Digraph([[1 .. 4], [1 .. 4], [1 .. 4], [1 .. 4]]);
<immutable digraph with 4 vertices, 16 edges>
gap> IsPreorderDigraph(D);
true
gap> D := Digraph([[2], [3], [4], [5], [1]]);
<immutable digraph with 5 vertices, 5 edges>
gap> IsPreorderDigraph(D);
false
gap> D := Digraph([[1], [1, 2], [2, 3]]);
<immutable digraph with 3 vertices, 5 edges>
gap> IsQuasiorderDigraph(D);
false
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsPartialOrderDigraph">
<ManSection>
  <Prop Name="IsPartialOrderDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    A digraph is a partial order digraph if and only if the digraph satisfies
    all of <Ref Prop="IsReflexiveDigraph"/>,
    <Ref Prop="IsAntisymmetricDigraph"/> and <Ref Prop="IsTransitiveDigraph"/>.
    A partial order <A>digraph</A> corresponds
    to the partial order relation <M>\leq</M> defined by <M>x \leq y</M> if and
    only if <C>[x, y]</C> is an edge of <A>digraph</A>.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

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

<#GAPDoc Label="IsEquivalenceDigraph">
<ManSection>
  <Prop Name="IsEquivalenceDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    A digraph is an equivalence digraph if and only if the digraph satisfies
    all of <Ref Prop="IsReflexiveDigraph"/>,
    <Ref Prop="IsSymmetricDigraph"/> and <Ref Prop="IsTransitiveDigraph"/>.
    A partial order <A>digraph</A> corresponds to an equivalence relation.
    <P/>

    &MUTABLE_RECOMPUTED_PROP;

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

<#GAPDoc Label="IsBridgelessDigraph">
<ManSection>
  <Prop Name="IsBridgelessDigraph" Arg="digraph"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    A connected digraph is <E>bridgeless</E> if it is still connected (in the
    sense of <Ref Prop="IsConnectedDigraph"/>) when any edge is removed. 
    If <A>digraph</A> has at least 3 vertices, then <Ref
    Prop="IsBiconnectedDigraph"/> implies <C>IsBridgelessDigraph</C>;
    see <Ref Attr="ArticulationPoints"/> or <Ref Attr="Bridges"/> for a more
    detailed explanation.
    <P/>

    <C>IsBridgelessDigraph</C> returns <K>true</K> if the digraph
    <A>digraph</A> is bridgeless, and <K>false</K> if it is not. In
    particular, <C>IsBridgelessDigraph</C> returns <K>false</K> if
    <A>digraph</A> is not connected. <P/>

    Multiple edges are ignored by this method. <P/>

    The method used in this operation has complexity <M>O(m+n)</M> where
    <M>m</M> is the number of edges and <M>n</M> is the number of vertices in
    the digraph.
    <P/>

    See also <Ref Attr="Bridges"/>, <Ref Attr="ArticulationPoints"/>, and 
    <Ref Prop="IsBiconnectedDigraph"/>. <P/>

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> IsBridgelessDigraph(Digraph([[1, 3], [2, 3], [3]]));
false
gap> IsBridgelessDigraph(CycleDigraph(5));
true
gap> D := Digraph([[1, 1], [1, 1, 2], [3], [3, 3, 4, 4]]);;
gap> IsBridgelessDigraph(D);
false
gap> D := CompleteBipartiteDigraph(IsMutableDigraph, 5, 4);
<mutable digraph with 9 vertices, 40 edges>
gap> IsBridgelessDigraph(D);
true
gap> D := Digraph([[2, 5], [1, 3, 4, 5], [2, 4], [2, 3], [1, 2]]);
<immutable digraph with 5 vertices, 12 edges>
gap> IsBridgelessDigraph(D);
true
gap> IsBiconnectedDigraph(D);
false
gap> D := Digraph([[2], [3], [4], [2]]);
<immutable digraph with 4 vertices, 4 edges>
gap> IsBridgelessDigraph(D);
false
gap> IsBiconnectedDigraph(D);
false
gap> IsBridgelessDigraph(ChainDigraph(2));
false
gap> IsBiconnectedDigraph(ChainDigraph(2));
true
]]></Example>
  </Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsUpperSemimodularDigraph">
<ManSection>
  <Prop Name="IsUpperSemimodularDigraph" Arg="D"/>
  <Prop Name="IsLowerSemimodularDigraph" Arg="D"/>
  <Returns><K>true</K> or <K>false</K>.</Returns>
  <Description>
    <C>IsUpperSemimodularDigraph</C> returns <K>true</K> if the digraph
    <A>D</A> represents an upper semimodular lattice and <K>false</K> if it
    does not.  Similarly, <C>IsLowerSemimodularDigraph</C> returns <K>true</K>
    if <A>D</A> represents a lower semimodular lattice and <K>false</K> if
    it does not. <P/>

    In a lattice we say that a vertex <C>a</C> <E>covers</E> a vertex <C>b</C>
    if <C>a</C> is greater than <C>b</C>, and there are no further vertices
    between <C>a</C> and <C>b</C>.  A lattice is <E>upper semimodular</E> if
    whenever the meet of <C>a</C> and <C>b</C> is covered by <C>a</C>, the join
    of <C>a</C> and <C>b</C> covers <C>b</C>.  <E>Lower semimodularity</E> is
    defined analogously. <P/>

    See also <Ref Prop="IsLatticeDigraph"/>, <Ref Oper="NonUpperSemimodularPair"/>, 
    and <Ref Oper="NonLowerSemimodularPair"/>.

    &MUTABLE_RECOMPUTED_PROP;

    <Example><![CDATA[
gap> D := DigraphFromDigraph6String(
> "&M~~sc`lYUZO__KIBboC_@h?U_?_GL?A_?c");
<immutable digraph with 14 vertices, 66 edges>
gap> IsUpperSemimodularDigraph(D);
true
gap> IsLowerSemimodularDigraph(D);
false]]></Example>
</Description>
</ManSection>
<#/GAPDoc>
