Skip to content

Commit

Permalink
Separate code into testable functions
Browse files Browse the repository at this point in the history
  • Loading branch information
markuspf committed Aug 29, 2024
1 parent f6e9006 commit acaea65
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 51 deletions.
157 changes: 106 additions & 51 deletions gap/weights.gi
Original file line number Diff line number Diff line change
Expand Up @@ -622,69 +622,124 @@ end);
#############################################################################
#
# returns an iterator that generates the (possibly empty) sequence of paths
# between source and dest
# between source and dest by increasing weight.
#
# the iterator needs to store
# - found paths
# - candidates
# -
# - reference to the digraph
# 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;
DIGRAPHS_SPI := function(digraph, source, dest)
local iter;

spurPath := EdgeWeightedDigraphShortestPath(modifiedGraph, spurNode, dest);
totalPath := [ Concatenation(rootPath[1], spurPath[1]),
Concatenation(rootPath[2], spurPath[2]) ];
iter := rec(
NextIterator := function(iter)
local shortestPath;

Push(iter.candidatePaths, totalPath);
if IsEmpty(iter!.foundPaths) then
shortestPath := EdgeWeightedDigraphShortestPath(iter!.digraph, iter!.source, iter!.dest);
Add(iter!.foundPaths, shortestPath);
else

fi;
end,
IsDoneIterator := function(iter)
return IsEmpty(iter!.candidatePaths);
end,
ShallowCopy := function(iter)
# TODO
return iter;
end,
PrintObj := function(iter)
Print("<iterator of shortst paths between vertices>");
end,

foundPaths := [],
candidatePaths := BinaryHeap(),
digraph := digraph,
source := source,
dest := dest
);
return IteratorByFunctions(iter);
end;

# FIXME: find out how often paths are used as objects in
# their own right.
DIGRAPHS_ConcatenatePaths := function(a, b)
local a_length;

a_length := Length(a);

if a[1][a_length] <> b[1][1] then
ErrorNoReturn("concatenatePaths: last vertex on `a` is not equal to first vertex of `b`");
fi;

if a_length = 0 then
return StructuralCopy(b);
else
return [ Concatenation(a[1]{[1..a_length-1]}, b[1]),
Concatenation(b[2], b[2]) ];
fi;
end;

DIGRAPHS_ModifyGraph := function(digraph, root, foundPaths)
mutableWeights := EdgeWeightsMutableCopy(digraph);
for p in foundPaths do
if rootPath = p[1]{[1..i]} then
mutableWeights[p[2][i]] := infinity;
fi;
od;

if IsEmpty(iter.candidatePaths) then
return fail;
rootNodes := currentShortestPath[1]{[1..i-1]};

o := OutNeighbours(digraph);
for i in [1..Length(o)] do
for j in [1..Length(o[i])] do
if o[i][j] in rootNodes then
mutableWeights[i][j] := infinity;
fi;
od;
od;
return EdgeWeightedDigraph(digraph, mutableWeights);
end;

DIGRAPHS_NextShortestPath := function(iter)
local currentShortestPath, currentShortestPathLength, spurNode, rootPath,
rootPathNode, modifiedGraph, foundPaths, i, p, spurPath, totalPath,
nextPath, mutableWeights, mutableOuts, rootNodes, j, o;

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

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

modifiedGraph := DIGRAPHS_ModifyGraph(digraph, rootPath, iter.foundPaths);
spurPath := EdgeWeightedDigraphShortestPath(modifiedGraph, spurNode, dest);

if spurPath <> fail then
totalPath := DIGRAPHS_ConcatenatePaths(rootPath, spurPath);
Push(iter.candidatePaths, totalPath);
fi;
od;

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

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

return nextPath;
end;
return nextPath;
end;

return findNextPath(currentIterator);
InstallGlobalFunction(DIGRAPHS_ShortestPathsIterator,
function(digraph, source, dest)
ErrorNoReturn("Not implemented yet");
end);
1 change: 1 addition & 0 deletions tst/standard/weights.tst
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ gap> EdgeWeightedDigraphShortestPath(d, 1, 3);
# K Shortest Paths
gap> d := EdgeWeightedDigraph([[2], [3], [4], []], [[1], [1], [1], []]);
<immutable digraph with 4 vertices, 3 edges>
gap> shortest_path := EdgeWeightedDigraphShortestPath(d, 1, 4);
[ [ 1, 2, 3, 4 ], [ 1, 1, 1 ] ]
gap> iter := DIGRAPHS_ShortestPathsIterator(d, 1, 4);
Expand Down

0 comments on commit acaea65

Please sign in to comment.