5
5
from __future__ import annotations
6
6
7
7
import time
8
+ from typing import Optional
9
+
10
+ Path = list [tuple [int , int ]]
8
11
9
12
grid = [
10
13
[0 , 0 , 0 , 0 , 0 , 0 , 0 ],
16
19
[0 , 0 , 0 , 0 , 1 , 0 , 0 ],
17
20
]
18
21
19
- delta = [[- 1 , 0 ], [0 , - 1 ], [1 , 0 ], [0 , 1 ]] # up, left, down, right
22
+ direction = [[- 1 , 0 ], [0 , - 1 ], [1 , 0 ], [0 , 1 ]] # up, left, down, right
20
23
21
24
22
25
class Node :
23
- def __init__ (self , pos_x , pos_y , goal_x , goal_y , parent ):
26
+ def __init__ (
27
+ self , pos_x : int , pos_y : int , goal_x : int , goal_y : int , parent : Optional [Node ]
28
+ ):
24
29
self .pos_x = pos_x
25
30
self .pos_y = pos_y
26
31
self .pos = (pos_y , pos_x )
@@ -32,11 +37,11 @@ def __init__(self, pos_x, pos_y, goal_x, goal_y, parent):
32
37
class BreadthFirstSearch :
33
38
"""
34
39
>>> bfs = BreadthFirstSearch((0, 0), (len(grid) - 1, len(grid[0]) - 1))
35
- >>> (bfs.start.pos_y + delta [3][0], bfs.start.pos_x + delta [3][1])
40
+ >>> (bfs.start.pos_y + direction [3][0], bfs.start.pos_x + direction [3][1])
36
41
(0, 1)
37
42
>>> [x.pos for x in bfs.get_successors(bfs.start)]
38
43
[(1, 0), (0, 1)]
39
- >>> (bfs.start.pos_y + delta [2][0], bfs.start.pos_x + delta [2][1])
44
+ >>> (bfs.start.pos_y + direction [2][0], bfs.start.pos_x + direction [2][1])
40
45
(1, 0)
41
46
>>> bfs.retrace_path(bfs.start)
42
47
[(0, 0)]
@@ -45,14 +50,14 @@ class BreadthFirstSearch:
45
50
(5, 1), (5, 2), (5, 3), (5, 4), (5, 5), (6, 5), (6, 6)]
46
51
"""
47
52
48
- def __init__ (self , start , goal ):
53
+ def __init__ (self , start : tuple [ int , int ], goal : tuple [ int , int ] ):
49
54
self .start = Node (start [1 ], start [0 ], goal [1 ], goal [0 ], None )
50
55
self .target = Node (goal [1 ], goal [0 ], goal [1 ], goal [0 ], None )
51
56
52
57
self .node_queue = [self .start ]
53
58
self .reached = False
54
59
55
- def search (self ) -> list [ tuple [ int ] ]:
60
+ def search (self ) -> Optional [ Path ]:
56
61
while self .node_queue :
57
62
current_node = self .node_queue .pop (0 )
58
63
@@ -65,15 +70,16 @@ def search(self) -> list[tuple[int]]:
65
70
for node in successors :
66
71
self .node_queue .append (node )
67
72
68
- if not (self .reached ):
69
- return [(self .start .pos )]
73
+ if not self .reached :
74
+ return [self .start .pos ]
75
+ return None
70
76
71
77
def get_successors (self , parent : Node ) -> list [Node ]:
72
78
"""
73
79
Returns a list of successors (both in the grid and free spaces)
74
80
"""
75
81
successors = []
76
- for action in delta :
82
+ for action in direction :
77
83
pos_x = parent .pos_x + action [1 ]
78
84
pos_y = parent .pos_y + action [0 ]
79
85
if not (0 <= pos_x <= len (grid [0 ]) - 1 and 0 <= pos_y <= len (grid ) - 1 ):
@@ -87,7 +93,7 @@ def get_successors(self, parent: Node) -> list[Node]:
87
93
)
88
94
return successors
89
95
90
- def retrace_path (self , node : Node ) -> list [ tuple [ int ]] :
96
+ def retrace_path (self , node : Optional [ Node ] ) -> Path :
91
97
"""
92
98
Retrace the path from parents to parents until start node
93
99
"""
@@ -119,7 +125,7 @@ def __init__(self, start, goal):
119
125
self .bwd_bfs = BreadthFirstSearch (goal , start )
120
126
self .reached = False
121
127
122
- def search (self ) -> list [ tuple [ int ] ]:
128
+ def search (self ) -> Optional [ Path ]:
123
129
while self .fwd_bfs .node_queue or self .bwd_bfs .node_queue :
124
130
current_fwd_node = self .fwd_bfs .node_queue .pop (0 )
125
131
current_bwd_node = self .bwd_bfs .node_queue .pop (0 )
@@ -144,10 +150,9 @@ def search(self) -> list[tuple[int]]:
144
150
145
151
if not self .reached :
146
152
return [self .fwd_bfs .start .pos ]
153
+ return None
147
154
148
- def retrace_bidirectional_path (
149
- self , fwd_node : Node , bwd_node : Node
150
- ) -> list [tuple [int ]]:
155
+ def retrace_bidirectional_path (self , fwd_node : Node , bwd_node : Node ) -> Path :
151
156
fwd_path = self .fwd_bfs .retrace_path (fwd_node )
152
157
bwd_path = self .bwd_bfs .retrace_path (bwd_node )
153
158
bwd_path .pop ()
0 commit comments