diff --git a/doc/oper.xml b/doc/oper.xml
index d150670df..a7f5ba7ad 100644
--- a/doc/oper.xml
+++ b/doc/oper.xml
@@ -1203,6 +1203,41 @@ fail
<#/GAPDoc>
+<#GAPDoc Label="DigraphShortestPath">
+
+
+ A pair of lists, or fail.
+
+ If there exists a non-trivial directed path (or a non-trivial cycle, in the
+ case that u = v) from vertex u to vertex
+ v in the digraph digraph, then this operation returns such a
+ directed path (or directed cycle) of minimum length. Otherwise, this operation returns
+ fail. See Section for the
+ definition of a directed path and a directed cycle.
+
+
+ See for details on the output.
+
+ The method for DigraphShortestPath has worst case complexity of O(m +
+ n) where m is the number of edges and n the number of
+ vertices in digraph.
+
+ gr := Digraph([[1, 2], [3], [2, 4], [1], [2, 4]]);
+
+gap> DigraphShortestPath(gr, 5, 1);
+[ [ 5, 4, 1 ], [ 2, 1 ] ]
+gap> DigraphShortestPath(gr, 3, 3);
+[ [ 3, 2, 3 ], [ 1, 1 ] ]
+gap> DigraphShortestPath(gr, 5, 5);
+fail
+gap> DigraphShortestPath(gr, 1, 1);
+[ [ 1, 1 ], [ 1 ] ]
+]]>
+
+
+<#/GAPDoc>
+
<#GAPDoc Label="IteratorOfPaths">
diff --git a/doc/z-chap4.xml b/doc/z-chap4.xml
index fae693463..02b993e49 100644
--- a/doc/z-chap4.xml
+++ b/doc/z-chap4.xml
@@ -52,6 +52,7 @@
<#Include Label="DigraphFloydWarshall">
<#Include Label="IsReachable">
<#Include Label="DigraphPath">
+ <#Include Label="DigraphShortestPath">
<#Include Label="IteratorOfPaths">
<#Include Label="DigraphAllSimpleCircuits">
<#Include Label="DigraphLongestSimpleCircuit">
diff --git a/gap/oper.gd b/gap/oper.gd
index 99c093604..4754b0f2f 100644
--- a/gap/oper.gd
+++ b/gap/oper.gd
@@ -106,3 +106,4 @@ DeclareOperation("IsMaximalMatching", [IsDigraph, IsHomogeneousList]);
DeclareOperation("AsSemigroup", [IsFunction, IsDigraph]);
DeclareOperation("AsMonoid", [IsFunction, IsDigraph]);
+DeclareOperation("DigraphShortestPath", [IsDigraph, IsPosInt, IsPosInt]);
diff --git a/gap/oper.gi b/gap/oper.gi
index 90858661d..77b699b6a 100644
--- a/gap/oper.gi
+++ b/gap/oper.gi
@@ -1239,6 +1239,67 @@ function(digraph, u, v)
return DIGRAPH_PATH(OutNeighbours(digraph), u, v);
end);
+# DigraphShortestPath
+
+InstallMethod(DigraphShortestPath, "for a digraph and two pos ints",
+[IsDigraph, IsPosInt, IsPosInt],
+function(digraph, u, v)
+ local current, next, parent, distance, falselist, verts, nbs, n, a, b, i, path;
+
+ verts := DigraphVertices(digraph);
+ nbs := OutNeighbors(digraph);
+ distance := [];
+
+ if u = v and v in nbs[v] then # Considers the trivial path from v to v
+ return [[v, v], [Position(nbs[v], v)]];
+ fi;
+
+ # Setting up objects useful in the function.
+ for i in verts do
+ Add(distance, -1);
+ od;
+ parent := [];
+ current := [u];
+ next := [];
+ falselist := [];
+ for i in verts do
+ Add(next, false);
+ Add(falselist, false);
+ od;
+
+ n := 0; # Counts the loops
+ while current <> [] do
+ n := n + 1;
+ for a in current do
+ for b in nbs[a] do
+ if distance[b] = -1 then
+ distance[b] := n;
+ next[b] := true;
+ parent[b] := a;
+ fi;
+
+ if b = v then
+ path := [[], []];
+ # Finds the path
+ for i in [1 .. n] do
+ Add(path[1], b);
+ Add(path[2], Position(nbs[parent[b]], b));
+ b := parent[b];
+ od;
+ Add(path[1], u); # Adds the starting vertex to the list of vertices.
+ return [Reversed(path[1]), Reversed(path[2])];
+ fi;
+
+ od;
+ od;
+
+ current := ListBlist(verts, next);
+ next := IntersectionBlist(next, falselist);
+
+ od;
+ return fail;
+end);
+
# IteratorOfPaths: for a digraph and two pos ints
InstallMethod(IteratorOfPaths, "for a digraph and two pos ints",
diff --git a/tst/standard/oper.tst b/tst/standard/oper.tst
index 8dc76598c..562cf6e9e 100644
--- a/tst/standard/oper.tst
+++ b/tst/standard/oper.tst
@@ -2039,6 +2039,32 @@ gap> S := AsMonoid(IsTransformation, di);;
Error, Digraphs: AsMonoid usage,
the first argument must be IsPartialPermMonoid or IsPartialPermSemigroup,
+#T# DigraphShortestPath
+gap> gr := Digraph([[1], [3, 4], [5, 6], [4, 2, 3], [4, 5], [1]]);;
+gap> DigraphShortestPath(gr, 1, 6);
+fail
+gap> DigraphShortestPath(gr, 2, 5);
+[ [ 2, 3, 5 ], [ 1, 1 ] ]
+gap> DigraphShortestPath(gr, 3, 3);
+[ [ 3, 5, 4, 3 ], [ 1, 1, 3 ] ]
+gap> DigraphShortestPath(gr, 6, 6);
+fail
+gap> DigraphShortestPath(gr, 5, 5);
+[ [ 5, 5 ], [ 2 ] ]
+gap> gr := Digraph([[]]);;
+gap> DigraphShortestPath(gr, 1, 1);
+fail
+gap> gr := Digraph([[], []]);;
+gap> DigraphShortestPath(gr, 2, 1);
+fail
+gap> gr := Digraph([[2], [1], [3]]);;
+gap> DigraphShortestPath(gr, 1, 2);
+[ [ 1, 2 ], [ 1 ] ]
+gap> gr := CayleyDigraph(SymmetricGroup(7));;
+gap> DigraphShortestPath(gr, 12, 5014);
+[ [ 12, 912, 1919, 3595, 4915, 3433, 4153, 3242, 2522, 2886, 23, 743, 238,
+ 1558, 713, 5014 ], [ 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2 ] ]
+
#T# DIGRAPHS_UnbindVariables
gap> Unbind(a);
gap> Unbind(adj);