Skip to content

Bi directional dijkstra #7982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Nov 20, 2022
Merged
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1bca1de
Added Bi-Directional Dijkstra
SwayamInSync Nov 13, 2022
c74289b
Added Bi-Directional Dijkstra
SwayamInSync Nov 13, 2022
c369745
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 13, 2022
4de4d62
Added doctest and type hints
SwayamInSync Nov 13, 2022
c689393
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 13, 2022
0ddf115
Rename Bi_directional_Dijkstra.py to bi_directional_dijkstra.py
SwayamInSync Nov 13, 2022
62fc026
Update bi_directional_dijkstra.py
SwayamInSync Nov 13, 2022
12902d7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 13, 2022
a006750
Update bi_directional_dijkstra.py
SwayamInSync Nov 13, 2022
6620798
Update bi_directional_dijkstra.py
SwayamInSync Nov 13, 2022
80396fe
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 13, 2022
baabd64
Update bi_directional_dijkstra.py
SwayamInSync Nov 13, 2022
4ff3b59
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 13, 2022
a22e0d9
Update bi_directional_dijkstra.py
SwayamInSync Nov 14, 2022
91670cc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 14, 2022
35c9e4b
Update bi_directional_dijkstra.py
SwayamInSync Nov 14, 2022
23ac248
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 14, 2022
f3cede3
Update bi_directional_dijkstra.py
SwayamInSync Nov 14, 2022
3adab98
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 14, 2022
9552936
Update bi_directional_dijkstra.py
SwayamInSync Nov 14, 2022
36e68d3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 14, 2022
8a00b3e
Update bi_directional_dijkstra.py
SwayamInSync Nov 15, 2022
d64667e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 15, 2022
10b529a
Update bi_directional_dijkstra.py
SwayamInSync Nov 15, 2022
9425f6f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 15, 2022
c5c4ebe
Update bi_directional_dijkstra.py
SwayamInSync Nov 18, 2022
dc57aae
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions graphs/Bi_directional_Dijkstra.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
from queue import PriorityQueue
import numpy as np

"""
Bi-directional Dijkstra's algorithm.

A bi-directional approach is an efficient and less time consuming optimization for Dijkstra's searching algorithm
Link for reference: https://www.homepages.ucl.ac.uk/~ucahmto/math/2020/05/30/bidirectional-dijkstra.html
"""

# Author: Swayam Singh (https://github.com/practice404)

def bidirectional_dij(source, destination, graph_forward, graph_backward) -> int:
"""
Bi-directional Dijkstra's algorithm.
Link for reference: https://www.homepages.ucl.ac.uk/~ucahmto/math/2020/05/30/bidirectional-dijkstra.html
Args:
source : Source stop id
destination: destination stop id
graph_forward: forward flow of graph
graph_backward: backward flow of graph

Returns:
shortest_path_distance (int): length of the shortest path.

Warnings:
If the destination is not reachable, function returns -1
"""
shortest_path_distance = -1

visited_forward = set()
visited_backward = set()
cost_forward = {source: 0}
cost_backward = {destination: 0}
parent_forward = {source: None}
parent_backward = {destination: None}
queue_forward = PriorityQueue()
queue_backward = PriorityQueue()

shortest_distance = np.inf

queue_forward.put((0, source))
queue_backward.put((0, destination))

if source == destination:
return 0

while queue_forward and queue_backward:
while not queue_forward.empty():
_, vertex_forward = queue_forward.get()

if vertex_forward not in visited_forward:
break
else:
break
visited_forward.add(vertex_forward)

while not queue_backward.empty():
_, vertex_backward = queue_backward.get()

if vertex_backward not in visited_backward:
break
else:
break
visited_backward.add(vertex_backward)

# forward pass and relaxation
for next_forward, d_forward in graph_forward[vertex_forward]:
if next_forward in visited_forward:
continue
old_cost_f = cost_forward.get(next_forward, np.inf)
new_cost_f = cost_forward[vertex_forward] + d_forward
if new_cost_f < old_cost_f:
queue_forward.put((new_cost_f, next_forward))
cost_forward[next_forward] = new_cost_f
parent_forward[next_forward] = vertex_forward
if next_forward in visited_backward and cost_forward[vertex_forward] + d_forward + \
cost_backward[next_forward] < shortest_distance:
shortest_distance = cost_forward[vertex_forward] + d_forward + cost_backward[next_forward]

# backward pass and relaxation
for next_backward, d_backward in graph_backward[vertex_backward]:
if next_backward in visited_backward:
continue
old_cost_b = cost_backward.get(next_backward, np.inf)
new_cost_b = cost_backward[vertex_backward] + d_backward
if new_cost_b < old_cost_b:
queue_backward.put((new_cost_b, next_backward))
cost_backward[next_backward] = new_cost_b
parent_backward[next_backward] = vertex_backward

if next_backward in visited_forward and cost_backward[vertex_backward] + d_backward + \
cost_forward[next_backward] < shortest_distance:
shortest_distance = cost_backward[vertex_backward] + d_backward + cost_forward[next_backward]

if cost_forward[vertex_forward] + cost_backward[vertex_backward] >= shortest_distance:
break

if shortest_distance == np.inf:
return shortest_path_distance
shortest_path_distance = shortest_distance
return shortest_path_distance


if __name__ == "__main__":
r"""
Layout of input Graph:
E -- 1 --> B -- 1 --> C -- 1 --> D -- 1 --> F
\ /\
\ ||
-------- 2 ---------> G ------- 1 ------
"""

graph_fwd = {
"B": [["C", 1]],
"C": [["D", 1]],
"D": [["F", 1]],
"E": [["B", 1], ["G", 2]],
"F": [],
"G": [["F", 1]],
}
graph_bwd = {
"B": [["E", 1]],
"C": [["B", 1]],
"D": [["C", 1]],
"F": [["D", 1], ["G", 1]],
"G": [["E", 2]]
}
print(bidirectional_dij("E", "F", graph_fwd, graph_bwd))
# E -- 2 --> G -- 1 --> F == 3