Skip to content

Commit a3b4f73

Browse files
baydreawilfwilson
authored andcommitted
Implementing an unweighted version of the Bellman-Ford Algorithm
1 parent 9266652 commit a3b4f73

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed

doc/attr.xml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,36 @@ gap> DigraphShortestDistances(D);
944944
</ManSection>
945945
<#/GAPDoc>
946946

947+
<#GAPDoc Label="UnweightedBellmanFord">
948+
<ManSection>
949+
<Attr Name="UnweightedBellmanFord" Arg="digraph","source"/>
950+
<Returns>A list of integers or <K>fail</K>.</Returns>
951+
<Description>
952+
If <A>digraph</A> is a digraph with <M>n</M> vertices, then this
953+
function returns a list with two sublists of <M>n</M> entries, where each entry is
954+
either a non-negative integer, or <K>fail</K>. <P/>
955+
956+
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
957+
the length of the shortest directed path to that i-th vertex and second sublist contains the vertex preceding that i-th
958+
vertex. If no such directed path exists, then the value of i is <C>fail</C>.
959+
We use the convention that the distance from every vertex to
960+
itself is <C>0</C> for all vertices <C>i</C>.
961+
<P/>
962+
963+
<Example><![CDATA[
964+
gap> D := Digraph([[1, 2], [3], [1, 2], [4]]);
965+
<immutable digraph with 4 vertices, 6 edges>
966+
gap> UnweightedBellmanFord(D, 2)
967+
[ [ 2, 0, 1, fail ], [ 3, fail, 2, fail ] ]
968+
gap> D := CycleDigraph(IsMutableDigraph, 3);
969+
<mutable digraph with 3 vertices, 3 edges>
970+
gap> UnweightedBellmanFord(D, 3);
971+
[ [ 1, 2, 0 ], [ 3, 1, fail ] ]
972+
]]></Example>
973+
</Description>
974+
</ManSection>
975+
<#/GAPDoc>
976+
947977
<#GAPDoc Label="DigraphDiameter">
948978
<ManSection>
949979
<Attr Name="DigraphDiameter" Arg="digraph"/>

gap/attr.gd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ DeclareAttribute("DigraphDegeneracy", IsDigraph);
4848
DeclareAttribute("DigraphDegeneracyOrdering", IsDigraph);
4949
DeclareAttribute("DIGRAPHS_Degeneracy", IsDigraph);
5050
DeclareAttribute("DigraphShortestDistances", IsDigraph);
51+
DeclareOperation("UnweightedBellmanFord", [IsDigraph, IsPosInt]);
5152
DeclareAttribute("DigraphDiameter", IsDigraph);
5253
DeclareAttribute("DigraphGirth", IsDigraph);
5354
DeclareAttribute("DigraphOddGirth", IsDigraph);

gap/attr.gi

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,52 @@ end);
10651065
# returns the vertices (i.e. numbers) of <D> ordered so that there are no
10661066
# edges from <out[j]> to <out[i]> for all <i> greater than <j>.
10671067

1068+
InstallMethod(UnweightedBellmanFord, "for a digraph by out-neighbours",
1069+
[IsDigraph, IsPosInt],
1070+
function(digraph, source)
1071+
local distance, n, predecessor, i, inf, u, v, edge, w;
1072+
n := DigraphNrVertices(digraph);
1073+
# wouldn't work for weighted digraphs
1074+
inf := n + 1;
1075+
distance := List([1 .. n], x -> 0);
1076+
predecessor := List([1 .. n], x -> 0);
1077+
for i in DigraphVertices(digraph) do
1078+
distance[i] := inf;
1079+
predecessor[i] := 0;
1080+
od;
1081+
distance[source] := 0;
1082+
for i in [1 .. n - 1] do
1083+
for edge in DigraphEdges(digraph) do
1084+
u := edge[1];
1085+
v := edge[2];
1086+
# only works for unweighted graphs, w needs to be changed into a variable
1087+
w := 1;
1088+
if distance[u] + w < distance[v] then
1089+
distance[v] := distance[u] + w;
1090+
predecessor[v] := u;
1091+
fi;
1092+
od;
1093+
od;
1094+
for edge in DigraphEdges(digraph) do
1095+
u := edge[1];
1096+
v := edge[2];
1097+
# only works for unweighted graphs, w needs to be changed into a variable
1098+
w := 1;
1099+
if distance[u] + w < distance[v] then
1100+
Print("Graph contains a negative-weight cycle");
1101+
fi;
1102+
od;
1103+
for i in DigraphVertices(digraph) do
1104+
if distance[i] >= inf then
1105+
distance[i] := fail;
1106+
fi;
1107+
if predecessor[i] = 0 then
1108+
predecessor[i] := fail;
1109+
fi;
1110+
od;
1111+
return [distance, predecessor];
1112+
end);
1113+
10681114
InstallMethod(DigraphTopologicalSort, "for a digraph by out-neighbours",
10691115
[IsDigraphByOutNeighboursRep],
10701116
D -> DIGRAPH_TOPO_SORT(OutNeighbours(D)));

tst/standard/attr.tst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,24 @@ gap> DIGRAPH_ConnectivityDataForVertex(gr, 2);;
549549
gap> DigraphShortestDistances(gr);
550550
[ [ 0, 1, 1 ], [ 1, 0, 1 ], [ 1, 1, 0 ] ]
551551

552+
# UnweightedBellmanFord
553+
gap> gr := Digraph([[1, 2], [3], [1, 2], [4]]);
554+
<immutable digraph with 4 vertices, 6 edges>
555+
gap> UnweightedBellmanFord(gr, 2);
556+
[ [ 2, 0, 1, fail ], [ 3, fail, 2, fail ] ]
557+
gap> gr := CycleDigraph(IsMutableDigraph, 3);
558+
<mutable digraph with 3 vertices, 3 edges>
559+
gap> UnweightedBellmanFord(gr, 3);
560+
[ [ 1, 2, 0 ], [ 3, 1, fail ] ]
561+
gap> gr := Digraph([[], []]);
562+
<immutable empty digraph with 2 vertices>
563+
gap> UnweightedBellmanFord(gr, 2);
564+
[ [ fail, 0 ], [ fail, fail ] ]
565+
gap> gr := Digraph([[1], [2], [3], [4]]);
566+
<immutable digraph with 4 vertices, 4 edges>
567+
gap> UnweightedBellmanFord(gr, 2);
568+
[ [ fail, 0, fail, fail ], [ fail, fail, fail, fail ] ]
569+
552570
# OutNeighbours and InNeighbours
553571
gap> gr := Digraph(rec(DigraphNrVertices := 10,
554572
> DigraphSource := [1, 1, 5, 5, 7, 10],

0 commit comments

Comments
 (0)