55from collections import deque
66from concurrent .futures import ThreadPoolExecutor
77from pydatastructs .utils .misc_util import (
8- _comp , raise_if_backend_is_not_python , Backend )
8+ _comp , raise_if_backend_is_not_python , Backend , AdjacencyListGraphNode )
99from pydatastructs .miscellaneous_data_structures import (
1010 DisjointSetForest , PriorityQueue )
1111from pydatastructs .graphs .graph import Graph
@@ -799,7 +799,7 @@ def _dijkstra_adjacency_list(graph: Graph, start: str, target: str):
799799 visited [u ] = True
800800 for v in graph .vertices :
801801 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
803803 visited [v ] is False and dist [v ] > dist [u ] + graph .edge_weights [edge_str ].value ):
804804 dist [v ] = dist [u ] + graph .edge_weights [edge_str ].value
805805 pred [v ] = u
@@ -826,6 +826,7 @@ def all_pair_shortest_paths(graph: Graph, algorithm: str,
826826 are implemented,
827827
828828 'floyd_warshall' -> Floyd Warshall algorithm as given in [1].
829+ 'johnson' -> Johnson's Algorithm as given in [2]
829830 backend: pydatastructs.Backend
830831 The backend to be used.
831832 Optional, by default, the best available
@@ -858,6 +859,7 @@ def all_pair_shortest_paths(graph: Graph, algorithm: str,
858859 ==========
859860
860861 .. [1] https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
862+ .. [2] https://en.wikipedia.org/wiki/Johnson's_algorithm
861863 """
862864 raise_if_backend_is_not_python (
863865 all_pair_shortest_paths , kwargs .get ('backend' , Backend .PYTHON ))
@@ -900,6 +902,51 @@ def _floyd_warshall_adjacency_list(graph: Graph):
900902
901903_floyd_warshall_adjacency_matrix = _floyd_warshall_adjacency_list
902904
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+
903950def topological_sort (graph : Graph , algorithm : str ,
904951 ** kwargs ) -> list :
905952 """
0 commit comments