Skip to content

Commit 2102a3f

Browse files
SwayamInSyncpre-commit-ci[bot]
authored andcommitted
Bi directional dijkstra (TheAlgorithms#7982)
* Added Bi-Directional Dijkstra * Added Bi-Directional Dijkstra * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added doctest and type hints * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Rename Bi_directional_Dijkstra.py to bi_directional_dijkstra.py * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent bd248b7 commit 2102a3f

File tree

1 file changed

+130
-0
lines changed

1 file changed

+130
-0
lines changed

graphs/bi_directional_dijkstra.py

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
"""
2+
Bi-directional Dijkstra's algorithm.
3+
4+
A bi-directional approach is an efficient and
5+
less time consuming optimization for Dijkstra's
6+
searching algorithm
7+
8+
Reference: shorturl.at/exHM7
9+
"""
10+
11+
# Author: Swayam Singh (https://github.com/practice404)
12+
13+
14+
from queue import PriorityQueue
15+
from typing import Any
16+
17+
import numpy as np
18+
19+
20+
def bidirectional_dij(
21+
source: str, destination: str, graph_forward: dict, graph_backward: dict
22+
) -> int:
23+
"""
24+
Bi-directional Dijkstra's algorithm.
25+
26+
Returns:
27+
shortest_path_distance (int): length of the shortest path.
28+
29+
Warnings:
30+
If the destination is not reachable, function returns -1
31+
32+
>>> bidirectional_dij("E", "F", graph_fwd, graph_bwd)
33+
3
34+
"""
35+
shortest_path_distance = -1
36+
37+
visited_forward = set()
38+
visited_backward = set()
39+
cst_fwd = {source: 0}
40+
cst_bwd = {destination: 0}
41+
parent_forward = {source: None}
42+
parent_backward = {destination: None}
43+
queue_forward: PriorityQueue[Any] = PriorityQueue()
44+
queue_backward: PriorityQueue[Any] = PriorityQueue()
45+
46+
shortest_distance = np.inf
47+
48+
queue_forward.put((0, source))
49+
queue_backward.put((0, destination))
50+
51+
if source == destination:
52+
return 0
53+
54+
while queue_forward and queue_backward:
55+
while not queue_forward.empty():
56+
_, v_fwd = queue_forward.get()
57+
58+
if v_fwd not in visited_forward:
59+
break
60+
else:
61+
break
62+
visited_forward.add(v_fwd)
63+
64+
while not queue_backward.empty():
65+
_, v_bwd = queue_backward.get()
66+
67+
if v_bwd not in visited_backward:
68+
break
69+
else:
70+
break
71+
visited_backward.add(v_bwd)
72+
73+
# forward pass and relaxation
74+
for nxt_fwd, d_forward in graph_forward[v_fwd]:
75+
if nxt_fwd in visited_forward:
76+
continue
77+
old_cost_f = cst_fwd.get(nxt_fwd, np.inf)
78+
new_cost_f = cst_fwd[v_fwd] + d_forward
79+
if new_cost_f < old_cost_f:
80+
queue_forward.put((new_cost_f, nxt_fwd))
81+
cst_fwd[nxt_fwd] = new_cost_f
82+
parent_forward[nxt_fwd] = v_fwd
83+
if nxt_fwd in visited_backward:
84+
if cst_fwd[v_fwd] + d_forward + cst_bwd[nxt_fwd] < shortest_distance:
85+
shortest_distance = cst_fwd[v_fwd] + d_forward + cst_bwd[nxt_fwd]
86+
87+
# backward pass and relaxation
88+
for nxt_bwd, d_backward in graph_backward[v_bwd]:
89+
if nxt_bwd in visited_backward:
90+
continue
91+
old_cost_b = cst_bwd.get(nxt_bwd, np.inf)
92+
new_cost_b = cst_bwd[v_bwd] + d_backward
93+
if new_cost_b < old_cost_b:
94+
queue_backward.put((new_cost_b, nxt_bwd))
95+
cst_bwd[nxt_bwd] = new_cost_b
96+
parent_backward[nxt_bwd] = v_bwd
97+
98+
if nxt_bwd in visited_forward:
99+
if cst_bwd[v_bwd] + d_backward + cst_fwd[nxt_bwd] < shortest_distance:
100+
shortest_distance = cst_bwd[v_bwd] + d_backward + cst_fwd[nxt_bwd]
101+
102+
if cst_fwd[v_fwd] + cst_bwd[v_bwd] >= shortest_distance:
103+
break
104+
105+
if shortest_distance != np.inf:
106+
shortest_path_distance = shortest_distance
107+
return shortest_path_distance
108+
109+
110+
graph_fwd = {
111+
"B": [["C", 1]],
112+
"C": [["D", 1]],
113+
"D": [["F", 1]],
114+
"E": [["B", 1], ["G", 2]],
115+
"F": [],
116+
"G": [["F", 1]],
117+
}
118+
graph_bwd = {
119+
"B": [["E", 1]],
120+
"C": [["B", 1]],
121+
"D": [["C", 1]],
122+
"F": [["D", 1], ["G", 1]],
123+
"E": [[None, np.inf]],
124+
"G": [["E", 2]],
125+
}
126+
127+
if __name__ == "__main__":
128+
import doctest
129+
130+
doctest.testmod()

0 commit comments

Comments
 (0)