Skip to content

Commit fd3b5ff

Browse files
committed
feat: add algorithem
1 parent a98308d commit fd3b5ff

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

pydatastructs/graphs/algorithms.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
data structure.
44
"""
55
from collections import deque
6+
from typing import Tuple, Dict
67
from concurrent.futures import ThreadPoolExecutor
78
from pydatastructs.utils.misc_util import (
89
_comp, raise_if_backend_is_not_python, Backend)
@@ -826,6 +827,7 @@ def all_pair_shortest_paths(graph: Graph, algorithm: str,
826827
are implemented,
827828
828829
'floyd_warshall' -> Floyd Warshall algorithm as given in [1].
830+
'floyd_warshall_parallel' -> Parallel Floyd Warshall algorithm as given in [2].
829831
backend: pydatastructs.Backend
830832
The backend to be used.
831833
Optional, by default, the best available
@@ -853,11 +855,17 @@ def all_pair_shortest_paths(graph: Graph, algorithm: str,
853855
21
854856
>>> dist['V3']['V1']
855857
5
858+
>>> dist, _ = all_pair_shortest_paths(G, 'floyd_warshall_parallel')
859+
>>> dist['V1']['V3']
860+
21
861+
>>> dist['V3']['V1']
862+
5
856863
857864
References
858865
==========
859866
860867
.. [1] https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
868+
.. [2] https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm#Parallel_execution
861869
"""
862870
raise_if_backend_is_not_python(
863871
all_pair_shortest_paths, kwargs.get('backend', Backend.PYTHON))
@@ -900,6 +908,44 @@ def _floyd_warshall_adjacency_list(graph: Graph):
900908

901909
_floyd_warshall_adjacency_matrix = _floyd_warshall_adjacency_list
902910

911+
def _floyd_warshall_parallel_adjacency_list(graph: Graph) -> Tuple[Dict, Dict]:
912+
"""
913+
Parallel Floyd-Warshall using ThreadPoolExecutor.
914+
Ensures correct updates of both distance and next_vertex matrices.
915+
916+
:param graph: Graph object with vertices and edge_weights.
917+
:return: Tuple (dist, next_vertex) matrices.
918+
"""
919+
dist, next_vertex = {}, {}
920+
V, E = graph.vertices, graph.edge_weights
921+
922+
# Initialize distance and next vertex matrices
923+
for v in V:
924+
dist[v] = {u: float('inf') for u in V}
925+
next_vertex[v] = {u: None for u in V}
926+
dist[v][v] = 0 # Distance to itself is 0
927+
928+
# Populate initial distances from edges
929+
for name, edge in E.items():
930+
dist[edge.source.name][edge.target.name] = edge.value
931+
next_vertex[edge.source.name][edge.target.name] = edge.target.name
932+
933+
def _update_row(i, k):
934+
"""Update a single row in parallel."""
935+
for j in V:
936+
if dist[i][j] > dist[i][k] + dist[k][j]:
937+
dist[i][j] = dist[i][k] + dist[k][j]
938+
next_vertex[i][j] = next_vertex[i][k] if next_vertex[i][k] else k
939+
940+
# Parallel Floyd-Warshall execution
941+
for k in V:
942+
with ThreadPoolExecutor() as executor:
943+
executor.map(lambda i: _update_row(i, k), V)
944+
945+
return dist, next_vertex
946+
947+
_floyd_warshall_parallel_adjacency_matrix = _floyd_warshall_parallel_adjacency_list
948+
903949
def topological_sort(graph: Graph, algorithm: str,
904950
**kwargs) -> list:
905951
"""

pydatastructs/graphs/tests/test_algorithms.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from pydatastructs import (breadth_first_search, Graph,
22
breadth_first_search_parallel, minimum_spanning_tree,
33
minimum_spanning_tree_parallel, strongly_connected_components,
4-
depth_first_search, shortest_paths, topological_sort,
4+
depth_first_search, shortest_paths, all_pair_shortest_paths, topological_sort,
55
topological_sort_parallel, max_flow)
66
from pydatastructs.utils.raises_util import raises
77

@@ -336,7 +336,7 @@ def _test_shortest_paths_negative_edges(ds, algorithm):
336336
graph.add_edge('2', '3', 3)
337337
graph.add_edge('3', '4', 2)
338338
graph.add_edge('4', '2', -1)
339-
dist, next_v = shortest_paths(graph, algorithm, 's')
339+
dist, next_v = all_pair_shortest_paths(graph, algorithm)
340340
assert dist == {'1': {'3': -2, '1': 0, '4': 0, '2': -1},
341341
'2': {'1': 4, '3': 2, '2': 0, '4': 4},
342342
'3': {'4': 2, '3': 0, '1': 5, '2': 1},
@@ -346,6 +346,11 @@ def _test_shortest_paths_negative_edges(ds, algorithm):
346346
'3': {'4': '3', '3': '3', '1': None, '2': None},
347347
'4': {'2': '4', '4': '4', '1': None, '3': None}}
348348

349+
_test_shortest_paths_negative_edges("List", 'floyd_warshall')
350+
_test_shortest_paths_negative_edges("Matrix", 'floyd_warshall')
351+
_test_shortest_paths_negative_edges("List", 'floyd_warshall_parallel')
352+
_test_shortest_paths_negative_edges("Matrix", 'floyd_warshall_parallel')
353+
349354
def test_topological_sort():
350355

351356
def _test_topological_sort(func, ds, algorithm, threads=None):

0 commit comments

Comments
 (0)