Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions doc/attr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,36 @@ gap> DigraphShortestDistances(D);
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="UnweightedBellmanFord">
<ManSection>
<Attr Name="UnweightedBellmanFord" Arg="digraph","source"/>
<Returns>A list of integers or <K>fail</K>.</Returns>
<Description>
If <A>digraph</A> is a digraph with <M>n</M> vertices, then this
function returns a list with two sublists of <M>n</M> entries, where each entry is
either a non-negative integer, or <K>fail</K>. <P/>

If there is a directed path from <A>source</A> to vertex <C>i</C>, then for each i-th entry the first sublist contains
the length of the shortest directed path to that i-th vertex and second sublist contains the vertex preceding that i-th
vertex. If no such directed path exists, then the value of i is <C>fail</C>.
We use the convention that the distance from every vertex to
itself is <C>0</C> for all vertices <C>i</C>.
<P/>

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

<#GAPDoc Label="DigraphDiameter">
<ManSection>
<Attr Name="DigraphDiameter" Arg="digraph"/>
Expand Down
1 change: 1 addition & 0 deletions gap/attr.gd
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ DeclareAttribute("DigraphDegeneracy", IsDigraph);
DeclareAttribute("DigraphDegeneracyOrdering", IsDigraph);
DeclareAttribute("DIGRAPHS_Degeneracy", IsDigraph);
DeclareAttribute("DigraphShortestDistances", IsDigraph);
DeclareOperation("UnweightedBellmanFord", [IsDigraph, IsPosInt]);
DeclareAttribute("DigraphDiameter", IsDigraph);
DeclareAttribute("DigraphGirth", IsDigraph);
DeclareAttribute("DigraphOddGirth", IsDigraph);
Expand Down
46 changes: 46 additions & 0 deletions gap/attr.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,52 @@ end);
# returns the vertices (i.e. numbers) of <D> ordered so that there are no
# edges from <out[j]> to <out[i]> for all <i> greater than <j>.

InstallMethod(UnweightedBellmanFord, "for a digraph by out-neighbours",
[IsDigraph, IsPosInt],
function(digraph, source)
local distance, n, predecessor, i, inf, u, v, edge, w;
n := DigraphNrVertices(digraph);
# wouldn't work for weighted digraphs
inf := n + 1;
distance := List([1 .. n], x -> 0);
predecessor := List([1 .. n], x -> 0);
for i in DigraphVertices(digraph) do
distance[i] := inf;
predecessor[i] := 0;
od;
distance[source] := 0;
for i in [1 .. n - 1] do
for edge in DigraphEdges(digraph) do
u := edge[1];
v := edge[2];
# only works for unweighted graphs, w needs to be changed into a variable
w := 1;
if distance[u] + w < distance[v] then
distance[v] := distance[u] + w;
predecessor[v] := u;
fi;
od;
od;
for edge in DigraphEdges(digraph) do
u := edge[1];
v := edge[2];
# only works for unweighted graphs, w needs to be changed into a variable
w := 1;
if distance[u] + w < distance[v] then
Print("Graph contains a negative-weight cycle");
fi;
od;
for i in DigraphVertices(digraph) do
if distance[i] >= inf then
distance[i] := fail;
fi;
if predecessor[i] = 0 then
predecessor[i] := fail;
fi;
od;
return [distance, predecessor];
end);

InstallMethod(DigraphTopologicalSort, "for a digraph by out-neighbours",
[IsDigraphByOutNeighboursRep],
D -> DIGRAPH_TOPO_SORT(OutNeighbours(D)));
Expand Down
18 changes: 18 additions & 0 deletions tst/standard/attr.tst
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,24 @@ gap> DIGRAPH_ConnectivityDataForVertex(gr, 2);;
gap> DigraphShortestDistances(gr);
[ [ 0, 1, 1 ], [ 1, 0, 1 ], [ 1, 1, 0 ] ]

# UnweightedBellmanFord
gap> gr := Digraph([[1, 2], [3], [1, 2], [4]]);
<immutable digraph with 4 vertices, 6 edges>
gap> UnweightedBellmanFord(gr, 2);
[ [ 2, 0, 1, fail ], [ 3, fail, 2, fail ] ]
gap> gr := CycleDigraph(IsMutableDigraph, 3);
<mutable digraph with 3 vertices, 3 edges>
gap> UnweightedBellmanFord(gr, 3);
[ [ 1, 2, 0 ], [ 3, 1, fail ] ]
gap> gr := Digraph([[], []]);
<immutable empty digraph with 2 vertices>
gap> UnweightedBellmanFord(gr, 2);
[ [ fail, 0 ], [ fail, fail ] ]
gap> gr := Digraph([[1], [2], [3], [4]]);
<immutable digraph with 4 vertices, 4 edges>
gap> UnweightedBellmanFord(gr, 2);
[ [ fail, 0, fail, fail ], [ fail, fail, fail, fail ] ]

# OutNeighbours and InNeighbours
gap> gr := Digraph(rec(DigraphNrVertices := 10,
> DigraphSource := [1, 1, 5, 5, 7, 10],
Expand Down
Loading