Skip to content

Commit 851975e

Browse files
A* Searching Algorithm Added with README file
1 parent 40f65e8 commit 851975e

File tree

2 files changed

+457
-0
lines changed

2 files changed

+457
-0
lines changed
+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
# Python program for A* Search Algorithm
2+
import math
3+
import heapq
4+
5+
# Define the Cell class
6+
7+
8+
class Cell:
9+
def __init__(self):
10+
# Parent cell's row index
11+
self.parent_i = 0
12+
# Parent cell's column index
13+
self.parent_j = 0
14+
# Total cost of the cell (g + h)
15+
self.f = float('inf')
16+
# Cost from start to this cell
17+
self.g = float('inf')
18+
# Heuristic cost from this cell to destination
19+
self.h = 0
20+
21+
22+
# Define the size of the grid
23+
ROW = 9
24+
COL = 10
25+
26+
# Check if a cell is valid (within the grid)
27+
28+
29+
def is_valid(row, col):
30+
return (row >= 0) and (row < ROW) and (col >= 0) and (col < COL)
31+
32+
# Check if a cell is unblocked
33+
34+
35+
def is_unblocked(grid, row, col):
36+
return grid[row][col] == 1
37+
38+
# Check if a cell is the destination
39+
40+
41+
def is_destination(row, col, dest):
42+
return row == dest[0] and col == dest[1]
43+
44+
# Calculate the heuristic value of a cell (Euclidean distance to destination)
45+
46+
47+
def calculate_h_value(row, col, dest):
48+
return ((row - dest[0]) ** 2 + (col - dest[1]) ** 2) ** 0.5
49+
50+
# Trace the path from source to destination
51+
52+
53+
def trace_path(cell_details, dest):
54+
print("The Path is ")
55+
path = []
56+
row = dest[0]
57+
col = dest[1]
58+
59+
# Trace the path from destination to source using parent cells
60+
while not (cell_details[row][col].parent_i == row and cell_details[row][col].parent_j == col):
61+
path.append((row, col))
62+
temp_row = cell_details[row][col].parent_i
63+
temp_col = cell_details[row][col].parent_j
64+
row = temp_row
65+
col = temp_col
66+
67+
# Add the source cell to the path
68+
path.append((row, col))
69+
# Reverse the path to get the path from source to destination
70+
path.reverse()
71+
72+
# Print the path
73+
for i in path:
74+
print("->", i, end=" ")
75+
print()
76+
77+
# Implement the A* search algorithm
78+
79+
80+
def a_star_search(grid, src, dest):
81+
# Check if the source and destination are valid
82+
if not is_valid(src[0], src[1]) or not is_valid(dest[0], dest[1]):
83+
print("Source or destination is invalid")
84+
return
85+
86+
# Check if the source and destination are unblocked
87+
if not is_unblocked(grid, src[0], src[1]) or not is_unblocked(grid, dest[0], dest[1]):
88+
print("Source or the destination is blocked")
89+
return
90+
91+
# Check if we are already at the destination
92+
if is_destination(src[0], src[1], dest):
93+
print("We are already at the destination")
94+
return
95+
96+
# Initialize the closed list (visited cells)
97+
closed_list = [[False for _ in range(COL)] for _ in range(ROW)]
98+
# Initialize the details of each cell
99+
cell_details = [[Cell() for _ in range(COL)] for _ in range(ROW)]
100+
101+
# Initialize the start cell details
102+
i = src[0]
103+
j = src[1]
104+
cell_details[i][j].f = 0
105+
cell_details[i][j].g = 0
106+
cell_details[i][j].h = 0
107+
cell_details[i][j].parent_i = i
108+
cell_details[i][j].parent_j = j
109+
110+
# Initialize the open list (cells to be visited) with the start cell
111+
open_list = []
112+
heapq.heappush(open_list, (0.0, i, j))
113+
114+
# Initialize the flag for whether destination is found
115+
found_dest = False
116+
117+
# Main loop of A* search algorithm
118+
while len(open_list) > 0:
119+
# Pop the cell with the smallest f value from the open list
120+
p = heapq.heappop(open_list)
121+
122+
# Mark the cell as visited
123+
i = p[1]
124+
j = p[2]
125+
closed_list[i][j] = True
126+
127+
# For each direction, check the successors
128+
directions = [(0, 1), (0, -1), (1, 0), (-1, 0),
129+
(1, 1), (1, -1), (-1, 1), (-1, -1)]
130+
for dir in directions:
131+
new_i = i + dir[0]
132+
new_j = j + dir[1]
133+
134+
# If the successor is valid, unblocked, and not visited
135+
if is_valid(new_i, new_j) and is_unblocked(grid, new_i, new_j) and not closed_list[new_i][new_j]:
136+
# If the successor is the destination
137+
if is_destination(new_i, new_j, dest):
138+
# Set the parent of the destination cell
139+
cell_details[new_i][new_j].parent_i = i
140+
cell_details[new_i][new_j].parent_j = j
141+
print("The destination cell is found")
142+
# Trace and print the path from source to destination
143+
trace_path(cell_details, dest)
144+
found_dest = True
145+
return
146+
else:
147+
# Calculate the new f, g, and h values
148+
g_new = cell_details[i][j].g + 1.0
149+
h_new = calculate_h_value(new_i, new_j, dest)
150+
f_new = g_new + h_new
151+
152+
# If the cell is not in the open list or the new f value is smaller
153+
if cell_details[new_i][new_j].f == float('inf') or cell_details[new_i][new_j].f > f_new:
154+
# Add the cell to the open list
155+
heapq.heappush(open_list, (f_new, new_i, new_j))
156+
# Update the cell details
157+
cell_details[new_i][new_j].f = f_new
158+
cell_details[new_i][new_j].g = g_new
159+
cell_details[new_i][new_j].h = h_new
160+
cell_details[new_i][new_j].parent_i = i
161+
cell_details[new_i][new_j].parent_j = j
162+
163+
# If the destination is not found after visiting all cells
164+
if not found_dest:
165+
print("Failed to find the destination cell")
166+
167+
# Driver Code
168+
169+
170+
def main():
171+
# Define the grid (1 for unblocked, 0 for blocked)
172+
grid = [
173+
[1, 0, 1, 1, 1, 1, 0, 1, 1, 1],
174+
[1, 1, 1, 0, 1, 1, 1, 0, 1, 1],
175+
[1, 1, 1, 0, 1, 1, 0, 1, 0, 1],
176+
[0, 0, 1, 0, 1, 0, 0, 0, 0, 1],
177+
[1, 1, 1, 0, 1, 1, 1, 0, 1, 0],
178+
[1, 0, 1, 1, 1, 1, 0, 1, 0, 0],
179+
[1, 0, 0, 0, 0, 1, 0, 0, 0, 1],
180+
[1, 0, 1, 1, 1, 1, 0, 1, 1, 1],
181+
[1, 1, 1, 0, 0, 0, 1, 0, 0, 1]
182+
]
183+
184+
# Define the source and destination
185+
src = [8, 0]
186+
dest = [0, 0]
187+
188+
# Run the A* search algorithm
189+
a_star_search(grid, src, dest)
190+
191+
192+
if __name__ == "__main__":
193+
main()

0 commit comments

Comments
 (0)