Skip to content

Commit

Permalink
Add iterator for K-Shortest-Paths in a weighted graph
Browse files Browse the repository at this point in the history
  • Loading branch information
markuspf committed Aug 28, 2024
1 parent 96103f8 commit f6e9006
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 1 deletion.
1 change: 1 addition & 0 deletions gap/weights.gd
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ DeclareGlobalFunction("DIGRAPHS_Edge_Weighted_Johnson");
DeclareGlobalFunction("DIGRAPHS_Edge_Weighted_FloydWarshall");
DeclareGlobalFunction("DIGRAPHS_Edge_Weighted_Bellman_Ford");
DeclareGlobalFunction("DIGRAPHS_Edge_Weighted_Dijkstra");
DeclareGlobalFunction("DIGRAPHS_ShortestPathsIterator");
72 changes: 72 additions & 0 deletions gap/weights.gi
Original file line number Diff line number Diff line change
Expand Up @@ -616,3 +616,75 @@ function(digraph, source)

return rec(distances := distances, parents := parents, edges := edges);
end);

#############################################################################
# 4. Shortest Paths Iterator
#############################################################################
#
# returns an iterator that generates the (possibly empty) sequence of paths
# between source and dest
#
# the iterator needs to store
# - found paths
# - candidates
# -
# rec( found_paths := [],
InstallGlobalFunction(DIGRAPHS_ShortestPathsIterator,
function(digraph, source, dest)
local currentIterator, findNextPath;

currentIterator := rec(
candidates := BinaryHeap(),
foundPaths := [
EdgeWeightedDigraphShortestPath(digraph, source, dest)
]);

findNextPath := function(iter)
local currentShortestPath, currentShortestPathLength, spurNode, rootPath,
rootPathNode, modifiedGraph, foundPaths, i, p, spurPath, totalPath,
nextPath;

currentShortestPath := Last(iter.foundPaths);
currentShortestPathLength := Length(currentShortestPath[1]);
foundPaths := iter.foundPaths;

for i in [1 .. currentShortestPathLength] do
modifiedGraph := fail;

spurNode := currentShortestPath[1][i];
rootPath := [
currentShortestPath[1]{[1..i]},
currentShortestPath[2]{[1..i-1]}
];

for p in foundPaths do
if rootPath = p[1]{[1..i]} then
# remove p[2][i] from Graph;
fi;
od;

for rootPathNode in rootPath[1] do
if rootPathNode <> spurNode then
# remove rootPathNode from Graph;
fi;
od;

spurPath := EdgeWeightedDigraphShortestPath(modifiedGraph, spurNode, dest);
totalPath := [ Concatenation(rootPath[1], spurPath[1]),
Concatenation(rootPath[2], spurPath[2]) ];

Push(iter.candidatePaths, totalPath);
od;

if IsEmpty(iter.candidatePaths) then
return fail;
fi;

nextPath := Pop(iter.candidatePaths);
Push(iter.foundPaths, nextPath);

return nextPath;
end;

return findNextPath(currentIterator);
end);
8 changes: 7 additions & 1 deletion tst/standard/weights.tst
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,16 @@ t is the 1st argument,
gap> EdgeWeightedDigraphShortestPath(d, 1, 3);
[ [ 1, 2, 3 ], [ 1, 1 ] ]
# K Shortest Paths
gap> d := EdgeWeightedDigraph([[2], [3], [4], []], [[1], [1], [1], []]);
gap> shortest_path := EdgeWeightedDigraphShortestPath(d, 1, 4);
[ [ 1, 2, 3, 4 ], [ 1, 1, 1 ] ]
gap> iter := DIGRAPHS_ShortestPathsIterator(d, 1, 4);
# DIGRAPHS_UnbindVariables
gap> Unbind(d);
gap> Unbind(tree);
#
gap> DIGRAPHS_StopTest();
gap> STOP_TEST("Digraphs package: standard/weights.tst", 0);
gap> STOP_TEST("Digraphs package: standard/weights.tst", 0);

0 comments on commit f6e9006

Please sign in to comment.