Skip to content

Commit

Permalink
Merge branch 'bellmanford' of https://github.com/baydrea/Digraphs int…
Browse files Browse the repository at this point in the history
…o bellmanford
  • Loading branch information
baydrea committed Dec 6, 2021
2 parents 07a5cd7 + 6da9d7a commit b76171d
Show file tree
Hide file tree
Showing 17 changed files with 510 additions and 22 deletions.
50 changes: 50 additions & 0 deletions doc/oper.xml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,56 @@ gap> OutNeighbours(D2);
</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 ]"/>
Expand Down
90 changes: 89 additions & 1 deletion doc/prop.xml
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,8 @@ false
<K>false</K> if it is not. A digraph is <E>empty</E> if it has no
edges.<P/>

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

&MUTABLE_RECOMPUTED_PROP;
Expand All @@ -739,6 +740,93 @@ false]]></Example>
</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"/>
Expand Down
6 changes: 6 additions & 0 deletions doc/z-chap5.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<Chapter Label="Properties of digraphs"><Heading>Properties of digraphs</Heading>

<Section><Heading>Vertex properties</Heading>
<#Include Label="DigraphHasAVertex">
<#Include Label="DigraphHasNoVertices">
</Section>

<Section><Heading>Edge properties</Heading>
<#Include Label="DigraphHasLoops">
<#Include Label="IsAntisymmetricDigraph">
Expand All @@ -12,6 +17,7 @@
<#Include Label="IsFunctionalDigraph">
<#Include Label="IsPermutationDigraph">
<#Include Label="IsMultiDigraph">
<#Include Label="IsNonemptyDigraph">
<#Include Label="IsReflexiveDigraph">
<#Include Label="IsSymmetricDigraph">
<#Include Label="IsTournament">
Expand Down
1 change: 1 addition & 0 deletions doc/z-chap6.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ from} $E_a$ \emph{to} $E_b$. In this case we say that $E_a$ and $E_b$ are
<Section><Heading>Acting on digraphs</Heading>
<#Include Label="OnDigraphs">
<#Include Label="OnMultiDigraphs">
<#Include Label="OnTuplesDigraphs">
</Section>

<Section Label="Isomorphisms and canonical labellings">
Expand Down
20 changes: 10 additions & 10 deletions gap/attr.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1128,7 +1128,7 @@ function(D)
# alter the answer for the diameter/girth if necessary. This function is
# called, if appropriate, by DigraphDiameter and DigraphUndirectedGirth.

if DigraphNrVertices(D) = 0 and IsImmutableDigraph(D) then
if DigraphHasNoVertices(D) and IsImmutableDigraph(D) then
SetDigraphDiameter(D, fail);
SetDigraphUndirectedGirth(D, infinity);
return rec(diameter := fail, girth := infinity);
Expand Down Expand Up @@ -1539,10 +1539,10 @@ end);

InstallMethod(DegreeMatrix, "for a digraph", [IsDigraph],
function(D)
if DigraphNrVertices(D) = 0 then
return [];
if DigraphHasAVertex(D) then
return DiagonalMat(OutDegrees(D));
fi;
return DiagonalMat(OutDegrees(D));
return [];
end);

InstallMethod(LaplacianMatrix, "for a digraph", [IsDigraph],
Expand Down Expand Up @@ -1863,7 +1863,7 @@ function(D)
SetDigraphAddAllLoopsAttr(D, C);
SetIsReflexiveDigraph(C, true);
SetIsMultiDigraph(C, ismulti);
SetDigraphHasLoops(C, DigraphNrVertices(C) > 0);
SetDigraphHasLoops(C, DigraphHasAVertex(C));
fi;
return C;
end);
Expand Down Expand Up @@ -2312,7 +2312,7 @@ InstallMethod(UndirectedSpanningForest, "for a digraph by out-neighbours",
[IsDigraphByOutNeighboursRep],
function(D)
local C;
if DigraphNrVertices(D) = 0 then
if DigraphHasNoVertices(D) then
return fail;
fi;
C := MaximalSymmetricSubdigraph(D)!.OutNeighbours;
Expand Down Expand Up @@ -2341,9 +2341,9 @@ InstallMethod(UndirectedSpanningForestAttr, "for an immutable digraph",
InstallMethod(UndirectedSpanningTree, "for a mutable digraph",
[IsMutableDigraph],
function(D)
if DigraphNrVertices(D) = 0
or not IsStronglyConnectedDigraph(D)
or not IsConnectedDigraph(UndirectedSpanningForest(DigraphMutableCopy(D)))
if not (DigraphHasAVertex(D)
and IsStronglyConnectedDigraph(D)
and IsConnectedDigraph(UndirectedSpanningForest(DigraphMutableCopy(D))))
then
return fail;
fi;
Expand All @@ -2357,7 +2357,7 @@ InstallMethod(UndirectedSpanningTreeAttr, "for an immutable digraph",
[IsImmutableDigraph],
function(D)
local out;
if DigraphNrVertices(D) = 0
if DigraphHasNoVertices(D)
or not IsStronglyConnectedDigraph(D)
or (HasMaximalSymmetricSubdigraphAttr(D)
and not IsStronglyConnectedDigraph(MaximalSymmetricSubdigraph(D)))
Expand Down
1 change: 1 addition & 0 deletions gap/digraph.gd
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ DeclareCategory("IsDigraphWithAdjacencyFunction", IsDigraph);
DeclareCategory("IsCayleyDigraph", IsDigraph);
DeclareCategory("IsImmutableDigraph", IsDigraph);
DeclareSynonym("IsMutableDigraph", IsDigraph and IsMutable);
DeclareCategoryCollections("IsDigraph");

DeclareAttribute("DigraphMutabilityFilter", IsDigraph);

Expand Down
2 changes: 1 addition & 1 deletion gap/digraph.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,7 @@ p -> AsDigraph(AsTransformation(p)));
InstallMethod(AsBinaryRelation, "for a digraph", [IsDigraphByOutNeighboursRep],
function(D)
local rel;
if DigraphNrVertices(D) = 0 then
if DigraphHasNoVertices(D) then
ErrorNoReturn("the argument <D> must be a digraph with at least 1 ",
"vertex,");
elif IsMultiDigraph(D) then
Expand Down
4 changes: 2 additions & 2 deletions gap/grahom.gi
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ function(D, n)
fi;
fi;

# Only the null D with 0 vertices can be coloured with 0 colours
# Only the null digraph with 0 vertices can be coloured with 0 colours
if n = 0 then
if DigraphNrVertices(D) = 0 then
if DigraphHasNoVertices(D) then
return IdentityTransformation;
fi;
return fail;
Expand Down
2 changes: 1 addition & 1 deletion gap/isomorph.gi
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ if DIGRAPHS_NautyAvailable then
colors);
colors := NautyColorData(colors);
fi;
if DigraphNrVertices(D) = 0 then
if DigraphHasNoVertices(D) then
# This circumvents Issue #17 in NautyTracesInterface, whereby a graph
# with 0 vertices causes a seg fault.
return [Group(()), ()];
Expand Down
2 changes: 2 additions & 0 deletions gap/oper.gd
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ DeclareOperation("DIGRAPHS_GraphProduct", [IsDigraph, IsDigraph, IsFunction]);
# 4. Actions . . .
DeclareOperation("OnDigraphs", [IsDigraph, IsPerm]);
DeclareOperation("OnDigraphs", [IsDigraph, IsTransformation]);
DeclareOperation("OnTuplesDigraphs", [IsDigraphCollection, IsPerm]);
DeclareOperation("OnSetsDigraphs", [IsDigraphCollection, IsPerm]);
DeclareOperation("OnMultiDigraphs", [IsDigraph, IsPermCollection]);
DeclareOperation("OnMultiDigraphs", [IsDigraph, IsPerm, IsPerm]);

Expand Down
15 changes: 15 additions & 0 deletions gap/oper.gi
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,21 @@ function(D, t)
return MakeImmutable(OnDigraphs(DigraphMutableCopy(D), t));
end);

InstallMethod(OnTuplesDigraphs,
"for list of digraphs and a perm",
[IsDigraphCollection and IsHomogeneousList, IsPerm],
{L, p} -> List(L, D -> OnDigraphs(DigraphMutableCopyIfMutable(D), p)));

InstallMethod(OnSetsDigraphs,
"for a list of digraphs and a perm",
[IsDigraphCollection and IsHomogeneousList, IsPerm],
function(S, p)
if not IsSet(S) then
ErrorNoReturn("the first argument must be a set (a strictly sorted list),");
fi;
return Set(S, D -> OnDigraphs(DigraphMutableCopyIfMutable(D), p));
end);

# Not revising the following because multi-digraphs are being withdrawn in the
# near future.

Expand Down
50 changes: 50 additions & 0 deletions gap/prop.gd
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
# meaning it really has multiple edges!!
DeclareProperty("IsMultiDigraph", IsDigraph);

DeclareProperty("DigraphHasAVertex", IsDigraph);
DeclareProperty("DigraphHasNoVertices", IsDigraph);

DeclareProperty("DigraphHasLoops", IsDigraph);
DeclareProperty("IsAcyclicDigraph", IsDigraph);
DeclareProperty("IsAperiodicDigraph", IsDigraph);
Expand All @@ -32,6 +35,7 @@ DeclareProperty("IsUndirectedForest", IsDigraph);
DeclareProperty("IsEdgeTransitive", IsDigraph);
DeclareProperty("IsVertexTransitive", IsDigraph);
DeclareProperty("IsEmptyDigraph", IsDigraph);
DeclareProperty("IsNonemptyDigraph", IsDigraph);
DeclareProperty("IsEulerianDigraph", IsDigraph);
DeclareProperty("IsFunctionalDigraph", IsDigraph);
DeclareProperty("IsHamiltonianDigraph", IsDigraph);
Expand Down Expand Up @@ -98,3 +102,49 @@ InstallTrueMethod(IsSymmetricDigraph, IsCompleteDigraph);
InstallTrueMethod(IsSymmetricDigraph, IsDigraph and IsUndirectedForest);
InstallTrueMethod(IsTransitiveDigraph, IsTournament and IsAcyclicDigraph);
InstallTrueMethod(IsUndirectedForest, IsDigraph and IsUndirectedTree);

InstallTrueMethod(IsNonemptyDigraph, IsDigraph and DigraphHasLoops);
InstallTrueMethod(DigraphHasLoops, IsReflexiveDigraph and DigraphHasAVertex);
InstallTrueMethod(DigraphHasAVertex, IsDigraph and IsNonemptyDigraph);
InstallTrueMethod(DigraphHasAVertex, IsDigraph and IsDirectedTree);

# Implications that something is false

InstallTrueMethod(HasDigraphHasLoops, IsAcyclicDigraph);
InstallTrueMethod(HasDigraphHasLoops, IsTournament);
InstallTrueMethod(HasDigraphHasLoops, IsUndirectedForest);
InstallTrueMethod(HasDigraphHasLoops, IsDirectedTree);
InstallTrueMethod(HasDigraphHasLoops, IsEmptyDigraph);
InstallTrueMethod(HasDigraphHasLoops, IsCompleteDigraph and IsNonemptyDigraph);
InstallTrueMethod(HasDigraphHasLoops, IsBipartiteDigraph);

InstallTrueMethod(HasIsNonemptyDigraph, IsEmptyDigraph);
InstallTrueMethod(HasIsEmptyDigraph, IsNonemptyDigraph);
InstallTrueMethod(HasDigraphHasAVertex, DigraphHasNoVertices);
InstallTrueMethod(HasDigraphHasNoVertices, DigraphHasAVertex);

InstallTrueMethod(HasIsAcyclicDigraph, IsCompleteDigraph and IsNonemptyDigraph);
InstallTrueMethod(HasIsAcyclicDigraph, IsDigraph and DigraphHasLoops);
InstallTrueMethod(HasIsAcyclicDigraph,
IsStronglyConnectedDigraph and IsNonemptyDigraph);
InstallTrueMethod(HasIsAntisymmetricDigraph,
IsCompleteDigraph and IsNonemptyDigraph);
InstallTrueMethod(HasIsChainDigraph, IsDigraph and DigraphHasLoops);
InstallTrueMethod(HasIsChainDigraph, IsSymmetricDigraph and IsNonemptyDigraph);
InstallTrueMethod(HasIsCompleteDigraph, IsDigraph and DigraphHasLoops);
InstallTrueMethod(HasIsReflexiveDigraph,
IsAcyclicDigraph and DigraphHasAVertex);

InstallTrueMethod(HasIsSymmetricDigraph, IsDirectedTree and IsNonemptyDigraph);
InstallTrueMethod(HasIsSymmetricDigraph, IsTournament and IsNonemptyDigraph);
InstallTrueMethod(HasIsSymmetricDigraph,
IsAcyclicDigraph and IsNonemptyDigraph);

InstallTrueMethod(HasIsMultiDigraph, IsChainDigraph);
InstallTrueMethod(HasIsMultiDigraph, IsCompleteDigraph);
InstallTrueMethod(HasIsMultiDigraph, IsCompleteMultipartiteDigraph);
InstallTrueMethod(HasIsMultiDigraph, IsCycleDigraph);
InstallTrueMethod(HasIsMultiDigraph, IsEmptyDigraph);
InstallTrueMethod(HasIsMultiDigraph, IsFunctionalDigraph);
InstallTrueMethod(HasIsMultiDigraph, IsTournament);
InstallTrueMethod(HasIsMultiDigraph, IsUndirectedForest);
Loading

0 comments on commit b76171d

Please sign in to comment.