diff --git a/doc/oper.xml b/doc/oper.xml
index 11ffbcebc..2edeee307 100644
--- a/doc/oper.xml
+++ b/doc/oper.xml
@@ -989,17 +989,6 @@ gap> Display(shortest_distances);
<#/GAPDoc>
-<#GAPDoc Label="DigraphDijkstraS">
-
-
-
-
-
-
-
-
-<#/GAPDoc>
-
<#GAPDoc Label="DigraphEdgeUnion">
<#/GAPDoc>
-<#GAPDoc Label="DigraphDijkstraST">
+<#GAPDoc Label="DigraphDijkstra">
-
- Two lists.
-
- If digraph is a digraph and source and target are vertices of digraph,
- then DigraphDijkstraST calculates the shortest distance from source and returns two lists. Each element of the first list
- is the distance of the corresponding element from source.
- If a vertex was not visited in the process of calculating the shortest distance to target or if there is no path connecting that vertex
- with source then the corresponding distance is infinity.
- Each element of the second list gives the previous vertex in the shortest pahth from source to the corresponding vertex.
- For source and for any vertices that remained unvisited this will be -1.
-
- mat:= [ [0, 1, 1], [0, 0, 1], [0, 0, 0]];
- [ [ 0, 1, 1 ], [ 0, 0, 1 ], [ 0, 0, 0 ] ]
- gap> gr:=DigraphByAdjacencyMatrix(mat);
-
- gap> DigraphDijkstraST(gr,2,3);
- [ [ infinity, 0, 1 ], [ -1, -1, 2 ] ]
- gap> DigraphDijkstraST(gr,1,3);
- [ [ 0, 1, 1 ], [ -1, 1, 1 ] ]
- gap> DigraphDijkstraST(gr,1,2);
- [ [ 0, 1, 1 ], [ -1, 1, 1 ] ] ]]>
-
-
- <#/GAPDoc>
+
+
+ Two lists.
+
+ If digraph is a digraph and source and target are
+ vertices of digraph, then DigraphDijkstra calculates the
+ length of the shortest path from source to target and returns
+ two lists. Each element of the first list is the distance of the
+ corresponding element from source. If a vertex was not visited in
+ the process of calculating the shortest distance to target or if
+ there is no path connecting that vertex with source, then
+ the corresponding distance is infinity. Each element of the
+ second list gives the previous vertex in the shortest path
+ from source to the corresponding vertex. For
+ source and for any vertices that remained unvisited this
+ will be -1.
+
+ If the optional second argument target is not present, then
+ DigraphDijkstra returns the shortest path from source to
+ every vertex that is reachable from source.
+
+ mat := [[0, 1, 1], [0, 0, 1], [0, 0, 0]];
+[ [ 0, 1, 1 ], [ 0, 0, 1 ], [ 0, 0, 0 ] ]
+gap> D := DigraphByAdjacencyMatrix(mat);
+
+gap> DigraphDijkstra(D, 2, 3);
+[ [ infinity, 0, 1 ], [ -1, -1, 2 ] ]
+gap> DigraphDijkstra(D, 1, 3);
+[ [ 0, 1, 1 ], [ -1, 1, 1 ] ]
+gap> DigraphDijkstra(D, 1, 2);
+[ [ 0, 1, 1 ], [ -1, 1, 1 ] ]
+]]>
+
+
+<#/GAPDoc>
diff --git a/doc/z-chap4.xml b/doc/z-chap4.xml
index 3a4daedec..c8c7327db 100644
--- a/doc/z-chap4.xml
+++ b/doc/z-chap4.xml
@@ -67,6 +67,7 @@
<#Include Label="DigraphDegeneracyOrdering">
<#Include Label="HamiltonianPath">
<#Include Label="NrSpanningTrees">
+ <#Include Label="DigraphDijkstra">
Cayley graphs of groups
diff --git a/gap/oper.gd b/gap/oper.gd
index 88d90b6b0..a773d4e67 100644
--- a/gap/oper.gd
+++ b/gap/oper.gd
@@ -94,9 +94,9 @@ DeclareOperation("IsPerfectMatching", [IsDigraph, IsHomogeneousList]);
# 9. Connectivity . . .
DeclareOperation("DigraphFloydWarshall",
[IsDigraph, IsFunction, IsObject, IsObject]);
-DeclareOperation("DigraphDijkstraS",
+DeclareOperation("DigraphDijkstra",
[IsDigraph, IsPosInt]);
-DeclareOperation("DigraphDijkstraST",
+DeclareOperation("DigraphDijkstra",
[IsDigraph, IsPosInt, IsPosInt]);
DeclareOperation("DigraphConnectedComponent", [IsDigraph, IsPosInt]);
diff --git a/gap/oper.gi b/gap/oper.gi
index 20380da6e..87b1d0f72 100644
--- a/gap/oper.gi
+++ b/gap/oper.gi
@@ -1314,47 +1314,57 @@ function(D, u, v)
return fail;
end);
-InstallMethod(DigraphDijkstraS, "for a digraph, and a vertex",
-[IsDigraph, IsPosInt],
-{digraph, source} -> DigraphDijkstraST(digraph, source, fail));
-
-InstallMethod(DigraphDijkstraST, "for a digraph, a vertex, and a vertex",
-[IsDigraph, IsPosInt, IsPosInt],
+BindGlobal("DIGRAPHS_DijkstraST",
function(digraph, source, target)
- local dist, prev, queue, u, v, alt;
+ local dist, prev, queue, u, v, alt;
- dist := [];
- prev := [];
- queue := BinaryHeap({x, y} -> x[1] < y[1]);
+ if not source in DigraphVertices(digraph) then
+ ErrorNoReturn("the 2nd argument must be a vertex of the ",
+ "1st argument ");
+ elif target <> fail and not target in DigraphVertices(digraph) then
+ ErrorNoReturn("the 3rd argument must be a vertex of the ",
+ "1st argument ");
+ fi;
- for v in DigraphVertices(digraph) do
- dist[v] := infinity;
- prev[v] := -1;
- od;
+ dist := [];
+ prev := [];
+ queue := BinaryHeap({x, y} -> x[1] < y[1]);
- dist[source] := 0;
- Push(queue, [0, source]);
+ for v in DigraphVertices(digraph) do
+ dist[v] := infinity;
+ prev[v] := -1;
+ od;
- while not IsEmpty(queue) do
- u := Pop(queue);
- u := u[2];
- # TODO: this has a small performance impact for DigraphDijkstraS,
- # but do we care?
- if u = target then
- return [dist, prev];
- fi;
- for v in OutNeighbours(digraph)[u] do
- alt := dist[u] + DigraphEdgeLabel(digraph, u, v);
- if alt < dist[v] then
- dist[v] := alt;
- prev[v] := u;
- Push(queue, [dist[v], v]);
- fi;
- od;
+ dist[source] := 0;
+ Push(queue, [0, source]);
+
+ while not IsEmpty(queue) do
+ u := Pop(queue);
+ u := u[2];
+ # TODO: this has a small performance impact for DigraphDijkstraS,
+ # but do we care?
+ if u = target then
+ return [dist, prev];
+ fi;
+ for v in OutNeighbours(digraph)[u] do
+ alt := dist[u] + DigraphEdgeLabel(digraph, u, v);
+ if alt < dist[v] then
+ dist[v] := alt;
+ prev[v] := u;
+ Push(queue, [dist[v], v]);
+ fi;
od;
- return [dist, prev];
+ od;
+ return [dist, prev];
end);
+InstallMethod(DigraphDijkstra, "for a digraph, a vertex, and a vertex",
+[IsDigraph, IsPosInt, IsPosInt], DIGRAPHS_DijkstraST);
+
+InstallMethod(DigraphDijkstra, "for a digraph, and a vertex",
+[IsDigraph, IsPosInt],
+{digraph, source} -> DIGRAPHS_DijkstraST(digraph, source, fail));
+
InstallMethod(IteratorOfPaths,
"for a digraph by out-neighbours and two pos ints",
[IsDigraphByOutNeighboursRep, IsPosInt, IsPosInt],
diff --git a/tst/standard/oper.tst b/tst/standard/oper.tst
index ce25eb6ce..3fc7f5efb 100644
--- a/tst/standard/oper.tst
+++ b/tst/standard/oper.tst
@@ -2010,7 +2010,7 @@ gap> OutNeighbours(C);
[ [ 5, 6, 7 ], [ 7 ], [ 7 ], [ 7 ], [ 1, 6, 7 ], [ 1, 5, 7 ],
[ 3, 2, 1, 6, 5, 4 ] ]
-#DigraphDijkstraST
+#DigraphDijkstra
# When there is one path to target
gap> mat := [[0, 1, 1], [0, 0, 1], [0, 0, 0]];
[ [ 0, 1, 1 ], [ 0, 0, 1 ], [ 0, 0, 0 ] ]
@@ -2018,11 +2018,11 @@ gap> gr := DigraphByAdjacencyMatrix(mat);
gap> DigraphShortestDistance(gr, 2, 3);
1
-gap> DigraphDijkstraST(gr, 2, 3);
+gap> DigraphDijkstra(gr, 2, 3);
[ [ infinity, 0, 1 ], [ -1, -1, 2 ] ]
-gap> DigraphDijkstraST(gr, 1, 3);
+gap> DigraphDijkstra(gr, 1, 3);
[ [ 0, 1, 1 ], [ -1, 1, 1 ] ]
-gap> DigraphDijkstraST(gr, 1, 2);
+gap> DigraphDijkstra(gr, 1, 2);
[ [ 0, 1, 1 ], [ -1, 1, 1 ] ]
gap> DigraphShortestDistance(gr, 1, 3);
1
@@ -2034,21 +2034,21 @@ gap> gr := DigraphByAdjacencyMatrix(mat);
gap> DigraphShortestDistance(gr, 2, 3);
fail
-gap> DigraphDijkstraST(gr, 2, 3);
+gap> DigraphDijkstra(gr, 2, 3);
[ [ infinity, 0, infinity ], [ -1, -1, -1 ] ]
gap> mat := [[0, 1, 1, 1], [0, 0, 1, 1], [0, 1, 0, 0], [1, 0, 0, 0]];
[ [ 0, 1, 1, 1 ], [ 0, 0, 1, 1 ], [ 0, 1, 0, 0 ], [ 1, 0, 0, 0 ] ]
gap> gr := DigraphByAdjacencyMatrix(mat);
-gap> DigraphDijkstraST(gr, 1, 4);
+gap> DigraphDijkstra(gr, 1, 4);
[ [ 0, 1, 1, 1 ], [ -1, 1, 1, 1 ] ]
gap> mat := [[0, 1, 1, 1], [0, 0, 1, 1], [0, 1, 0, 0], [1, 0, 0, 0]];
[ [ 0, 1, 1, 1 ], [ 0, 0, 1, 1 ], [ 0, 1, 0, 0 ], [ 1, 0, 0, 0 ] ]
gap> gr := DigraphByAdjacencyMatrix(mat);
-gap> DigraphDijkstraST(gr, 1, 2);
+gap> DigraphDijkstra(gr, 1, 2);
[ [ 0, 1, 1, 1 ], [ -1, 1, 1, 1 ] ]
-gap> DigraphDijkstraST(gr, 1, 3);
+gap> DigraphDijkstra(gr, 1, 3);
[ [ 0, 1, 1, 1 ], [ -1, 1, 1, 1 ] ]
#DIGRAPHS_UnbindVariables