@@ -622,69 +622,124 @@ end);
622622# ############################################################################
623623#
624624# returns an iterator that generates the (possibly empty) sequence of paths
625- # between source and dest
625+ # between source and dest by increasing weight.
626626#
627627# the iterator needs to store
628628# - found paths
629629# - candidates
630- # -
630+ # - reference to the digraph
631631# rec( found_paths := [],
632- InstallGlobalFunction(DIGRAPHS_ShortestPathsIterator,
633- function (digraph, source, dest )
634- local currentIterator, findNextPath;
635-
636- currentIterator := rec (
637- candidates := BinaryHeap(),
638- foundPaths := [
639- EdgeWeightedDigraphShortestPath(digraph, source, dest)
640- ] );
641-
642- findNextPath := function (iter )
643- local currentShortestPath, currentShortestPathLength, spurNode, rootPath,
644- rootPathNode, modifiedGraph, foundPaths, i, p, spurPath, totalPath,
645- nextPath;
646-
647- currentShortestPath := Last(iter.foundPaths);
648- currentShortestPathLength := Length(currentShortestPath[ 1 ] );
649- foundPaths := iter.foundPaths;
650-
651- for i in [ 1 .. currentShortestPathLength] do
652- modifiedGraph := fail ;
653-
654- spurNode := currentShortestPath[ 1 ][ i] ;
655- rootPath := [
656- currentShortestPath[ 1 ]{[ 1 .. i]} ,
657- currentShortestPath[ 2 ]{[ 1 .. i- 1 ]}
658- ] ;
659-
660- for p in foundPaths do
661- if rootPath = p[ 1 ]{[ 1 .. i]} then
662- # remove p[2][i] from Graph;
663- fi ;
664- od ;
665632
666- for rootPathNode in rootPath[ 1 ] do
667- if rootPathNode <> spurNode then
668- # remove rootPathNode from Graph;
669- fi ;
670- od ;
633+ DIGRAPHS_SPI := function (digraph, source, dest )
634+ local iter;
671635
672- spurPath := EdgeWeightedDigraphShortestPath(modifiedGraph, spurNode, dest);
673- totalPath := [ Concatenation(rootPath [ 1 ] , spurPath [ 1 ] ),
674- Concatenation(rootPath [ 2 ] , spurPath [ 2 ] ) ] ;
636+ iter := rec (
637+ NextIterator := function ( iter )
638+ local shortestPath ;
675639
676- Push(iter.candidatePaths, totalPath);
640+ if IsEmpty(iter!. foundPaths) then
641+ shortestPath := EdgeWeightedDigraphShortestPath(iter!. digraph, iter!. source, iter!. dest);
642+ Add(iter!. foundPaths, shortestPath);
643+ else
644+
645+ fi ;
646+ end ,
647+ IsDoneIterator := function (iter )
648+ return IsEmpty(iter!. candidatePaths);
649+ end ,
650+ ShallowCopy := function (iter )
651+ # TODO
652+ return iter;
653+ end ,
654+ PrintObj := function (iter )
655+ Print(" <iterator of shortst paths between vertices>" );
656+ end ,
657+
658+ foundPaths := [] ,
659+ candidatePaths := BinaryHeap(),
660+ digraph := digraph,
661+ source := source,
662+ dest := dest
663+ );
664+ return IteratorByFunctions(iter);
665+ end ;
666+
667+ # FIXME: find out how often paths are used as objects in
668+ # their own right.
669+ DIGRAPHS_ConcatenatePaths := function (a, b )
670+ local a_length;
671+
672+ a_length := Length(a);
673+
674+ if a[ 1 ][ a_length] <> b[ 1 ][ 1 ] then
675+ ErrorNoReturn(" concatenatePaths: last vertex on `a` is not equal to first vertex of `b`" );
676+ fi ;
677+
678+ if a_length = 0 then
679+ return StructuralCopy(b);
680+ else
681+ return [ Concatenation(a[ 1 ]{[ 1 .. a_length- 1 ]} , b[ 1 ] ),
682+ Concatenation(b[ 2 ] , b[ 2 ] ) ] ;
683+ fi ;
684+ end ;
685+
686+ DIGRAPHS_ModifyGraph := function (digraph, root, foundPaths )
687+ mutableWeights := EdgeWeightsMutableCopy(digraph);
688+ for p in foundPaths do
689+ if rootPath = p[ 1 ]{[ 1 .. i]} then
690+ mutableWeights[ p[ 2 ][ i]] := infinity;
691+ fi ;
677692 od ;
678693
679- if IsEmpty(iter.candidatePaths) then
680- return fail ;
694+ rootNodes := currentShortestPath[ 1 ]{[ 1 .. i- 1 ]} ;
695+
696+ o := OutNeighbours(digraph);
697+ for i in [ 1 .. Length(o)] do
698+ for j in [ 1 .. Length(o[ i] )] do
699+ if o[ i][ j] in rootNodes then
700+ mutableWeights[ i][ j] := infinity;
701+ fi ;
702+ od ;
703+ od ;
704+ return EdgeWeightedDigraph(digraph, mutableWeights);
705+ end ;
706+
707+ DIGRAPHS_NextShortestPath := function (iter )
708+ local currentShortestPath, currentShortestPathLength, spurNode, rootPath,
709+ rootPathNode, modifiedGraph, foundPaths, i, p, spurPath, totalPath,
710+ nextPath, mutableWeights, mutableOuts, rootNodes, j, o;
711+
712+ currentShortestPath := Last(iter.foundPaths);
713+ currentShortestPathLength := Length(currentShortestPath[ 1 ] );
714+ foundPaths := iter.foundPaths;
715+
716+ for i in [ 1 .. currentShortestPathLength] do
717+ spurNode := currentShortestPath[ 1 ][ i] ;
718+ rootPath := [
719+ currentShortestPath[ 1 ]{[ 1 .. i]} ,
720+ currentShortestPath[ 2 ]{[ 1 .. i- 1 ]}
721+ ] ;
722+
723+ modifiedGraph := DIGRAPHS_ModifyGraph(digraph, rootPath, iter.foundPaths);
724+ spurPath := EdgeWeightedDigraphShortestPath(modifiedGraph, spurNode, dest);
725+
726+ if spurPath <> fail then
727+ totalPath := DIGRAPHS_ConcatenatePaths(rootPath, spurPath);
728+ Push(iter.candidatePaths, totalPath);
681729 fi ;
730+ od ;
731+
732+ if IsEmpty(iter.candidatePaths) then
733+ return fail ;
734+ fi ;
682735
683- nextPath := Pop(iter.candidatePaths);
684- Push (iter.foundPaths, nextPath);
736+ nextPath := Pop(iter.candidatePaths);
737+ Add (iter.foundPaths, nextPath);
685738
686- return nextPath;
687- end ;
739+ return nextPath;
740+ end ;
688741
689- return findNextPath(currentIterator);
742+ InstallGlobalFunction(DIGRAPHS_ShortestPathsIterator,
743+ function (digraph, source, dest )
744+ ErrorNoReturn(" Not implemented yet" );
690745end );
0 commit comments