diff --git a/doc/oper.xml b/doc/oper.xml
index a7f5ba7ad..f0650d219 100644
--- a/doc/oper.xml
+++ b/doc/oper.xml
@@ -1208,10 +1208,7 @@ fail
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
+ Returns the shortest directed path in the digraph digraph from the vertex u to the vertex v, if such a path exists. If u = v, then the shortest non-trivial cycle is returned, again, if it exists. Otherwise, this operation returns
fail. See Section for the
definition of a directed path and a directed cycle.
diff --git a/gap/oper.gi b/gap/oper.gi
index 77b699b6a..5975008ec 100644
--- a/gap/oper.gi
+++ b/gap/oper.gi
@@ -1244,38 +1244,49 @@ end);
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;
+ local current, next, parent, distance, falselist, verts, nbs, path, edge,
+ n, a, b, i;
- verts := DigraphVertices(digraph);
- nbs := OutNeighbors(digraph);
- distance := [];
+ verts := DigraphVertices(digraph);
+ if not (u in verts and v in verts) then
+ ErrorNoReturn("Digraphs: DigraphPath: usage,\n",
+ "the second and third arguments and must be\n",
+ "vertices of the first argument ,");
+ fi;
- if u = v and v in nbs[v] then # Considers the trivial path from v to v
- return [[v, v], [Position(nbs[v], v)]];
+ if IsDigraphEdge(digraph, [u, v]) then
+ return [[u, v], [Position(OutNeighboursOfVertex(digraph, u), v)]];
+ elif HasIsTransitiveDigraph(digraph) and IsTransitiveDigraph(digraph) then
+ # If it's a known transitive digraph, just check whether the edge exists
+ return fail;
+ # Glean information from WCC if we have it
+ elif HasDigraphConnectedComponents(digraph)
+ and DigraphConnectedComponents(digraph).id[u] <>
+ DigraphConnectedComponents(digraph).id[v] then
+ return fail;
fi;
+ nbs := OutNeighbors(digraph);
+ distance := ListWithIdenticalEntries(Length(verts), -1);
+
# 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;
+ parent := [];
+ current := [u];
+ edge := [];
+ next := BlistList([1 .. Length(verts)], []);
+ falselist := BlistList([1 .. Length(verts)], []);
- n := 0; # Counts the loops
+ n := 0;
while current <> [] do
- n := n + 1;
+ n := n + 1;
for a in current do
- for b in nbs[a] do
+ for i in [1 .. Length(nbs[a])] do
+ b := nbs[a][i];
if distance[b] = -1 then
distance[b] := n;
next[b] := true;
parent[b] := a;
+ edge[b] := i;
fi;
if b = v then
@@ -1283,21 +1294,18 @@ function(digraph, u, v)
# Finds the path
for i in [1 .. n] do
Add(path[1], b);
- Add(path[2], Position(nbs[parent[b]], b));
+ Add(path[2], edge[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);
-
+ IntersectBlist(next, falselist);
od;
- return fail;
+ return fail;
end);
# IteratorOfPaths: for a digraph and two pos ints