diff --git a/doc/attr.xml b/doc/attr.xml
index 9c880fdab..f2862fc47 100644
--- a/doc/attr.xml
+++ b/doc/attr.xml
@@ -902,6 +902,37 @@ gap> DigraphShortestDistances(D);
<#/GAPDoc>
+<#GAPDoc Label="UnweightedBellmanFord">
+
+
+ A list of integers or fail.
+
+ If digraph is a digraph with n vertices, then this
+ function returns a list with two sublists of n entries, where each entry is
+ either a non-negative integer, or fail.
+
+ If there is a directed path from source to vertex i, 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 fail.
+ We use the convention that the distance from every vertex to
+ itself is 0 for all vertices i.
+
+
+ D := Digraph([[1, 2], [3], [1, 2], [4]]);
+
+gap> UnweightedBellmanFord(D, 2)
+[ [ 2, 0, 1, fail ], [ 3, fail, 2, fail ] ]
+gap> D := CycleDigraph(IsMutableDigraph, 3);
+
+gap> UnweightedBellmanFord(D, 3);
+[ [ 1, 2, 0 ], [ 3, 1, fail ] ]
+]]>
+
+
+<#/GAPDoc>
+
+
<#GAPDoc Label="DigraphDiameter">
diff --git a/gap/attr.gd b/gap/attr.gd
index bf22fd30d..b67221290 100644
--- a/gap/attr.gd
+++ b/gap/attr.gd
@@ -45,6 +45,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);
diff --git a/gap/attr.gi b/gap/attr.gi
index 2c721ee9d..045e842b8 100644
--- a/gap/attr.gi
+++ b/gap/attr.gi
@@ -700,6 +700,52 @@ end);
# returns the vertices (i.e. numbers) of ordered so that there are no
# edges from to for all greater than .
+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)));
diff --git a/tst/standard/attr.tst b/tst/standard/attr.tst
index ba1ced5d9..919543dfd 100644
--- a/tst/standard/attr.tst
+++ b/tst/standard/attr.tst
@@ -486,6 +486,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]]);
+
+gap> UnweightedBellmanFord(gr, 2);
+[ [ 2, 0, 1, fail ], [ 3, fail, 2, fail ] ]
+gap> gr := CycleDigraph(IsMutableDigraph, 3);
+
+gap> UnweightedBellmanFord(gr, 3);
+[ [ 1, 2, 0 ], [ 3, 1, fail ] ]
+gap> gr := Digraph([[], []]);
+
+gap> UnweightedBellmanFord(gr, 2);
+[ [ fail, 0 ], [ fail, fail ] ]
+gap> gr := Digraph([[1], [2], [3], [4]]);
+
+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],