5
5
from collections import deque
6
6
from concurrent .futures import ThreadPoolExecutor
7
7
from pydatastructs .utils .misc_util import (
8
- _comp , raise_if_backend_is_not_python , Backend )
8
+ _comp , raise_if_backend_is_not_python , Backend , AdjacencyListGraphNode )
9
9
from pydatastructs .miscellaneous_data_structures import (
10
10
DisjointSetForest , PriorityQueue )
11
11
from pydatastructs .graphs .graph import Graph
@@ -799,7 +799,7 @@ def _dijkstra_adjacency_list(graph: Graph, start: str, target: str):
799
799
visited [u ] = True
800
800
for v in graph .vertices :
801
801
edge_str = u + '_' + v
802
- if (edge_str in graph .edge_weights and graph .edge_weights [edge_str ].value > 0 and
802
+ if (edge_str in graph .edge_weights and graph .edge_weights [edge_str ].value >= 0 and
803
803
visited [v ] is False and dist [v ] > dist [u ] + graph .edge_weights [edge_str ].value ):
804
804
dist [v ] = dist [u ] + graph .edge_weights [edge_str ].value
805
805
pred [v ] = u
@@ -826,6 +826,7 @@ def all_pair_shortest_paths(graph: Graph, algorithm: str,
826
826
are implemented,
827
827
828
828
'floyd_warshall' -> Floyd Warshall algorithm as given in [1].
829
+ 'johnson' -> Johnson's Algorithm as given in [2]
829
830
backend: pydatastructs.Backend
830
831
The backend to be used.
831
832
Optional, by default, the best available
@@ -858,6 +859,7 @@ def all_pair_shortest_paths(graph: Graph, algorithm: str,
858
859
==========
859
860
860
861
.. [1] https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
862
+ .. [2] https://en.wikipedia.org/wiki/Johnson's_algorithm
861
863
"""
862
864
raise_if_backend_is_not_python (
863
865
all_pair_shortest_paths , kwargs .get ('backend' , Backend .PYTHON ))
@@ -900,6 +902,51 @@ def _floyd_warshall_adjacency_list(graph: Graph):
900
902
901
903
_floyd_warshall_adjacency_matrix = _floyd_warshall_adjacency_list
902
904
905
+ def _johnson_adjacency_list (graph : Graph ):
906
+ new_vertex = AdjacencyListGraphNode ('__q__' )
907
+ graph .add_vertex (new_vertex )
908
+
909
+ for vertex in graph .vertices :
910
+ if vertex != '__q__' :
911
+ graph .add_edge ('__q__' , vertex , 0 )
912
+
913
+ distances , predecessors = shortest_paths (graph , 'bellman_ford' , '__q__' )
914
+
915
+ edges_to_remove = []
916
+ for edge in graph .edge_weights :
917
+ edge_node = graph .edge_weights [edge ]
918
+ if edge_node .source .name == '__q__' :
919
+ edges_to_remove .append ((edge_node .source .name , edge_node .target .name ))
920
+
921
+ for u , v in edges_to_remove :
922
+ graph .remove_edge (u , v )
923
+ graph .remove_vertex ('__q__' )
924
+
925
+ for edge in graph .edge_weights :
926
+ edge_node = graph .edge_weights [edge ]
927
+ u , v = edge_node .source .name , edge_node .target .name
928
+ graph .edge_weights [edge ].value += (distances [u ] - distances [v ])
929
+
930
+ all_distances = {}
931
+ all_next_vertex = {}
932
+
933
+ for vertex in graph .vertices :
934
+ u = vertex
935
+ dijkstra_dist , dijkstra_pred = shortest_paths (graph , 'dijkstra' , u )
936
+ all_distances [u ] = {}
937
+ all_next_vertex [u ] = {}
938
+ for v in graph .vertices :
939
+ if dijkstra_pred [v ] is None or dijkstra_pred [v ] == u :
940
+ all_next_vertex [u ][v ] = u
941
+ else :
942
+ all_next_vertex [u ][v ] = None
943
+ if v in dijkstra_dist :
944
+ all_distances [u ][v ] = dijkstra_dist [v ] - distances [u ] + distances [v ]
945
+ else :
946
+ all_distances [u ][v ] = float ('inf' )
947
+
948
+ return (all_distances , all_next_vertex )
949
+
903
950
def topological_sort (graph : Graph , algorithm : str ,
904
951
** kwargs ) -> list :
905
952
"""
0 commit comments