Experiment – 7
AIM : To Write a python program to implements A* and A*
algorithms(Example :find the shortest path)
Description :
This program uses the A* search algorithm to find the shortest path between a
start and a goal position in a grid. The grid is represented as a 2D list where 0
indicates a traversable cell and 1 indicates an obstacle.
Key Components:
1. Node Class: Represents each cell in the grid with attributes:
o position: Coordinates (x, y) of the node.
o parent: Pointer to the previous node in the path.
o g: Cost from the start node to the current node.
o h: Heuristic cost estimate to the goal (using Euclidean distance).
o f: Total cost (f = g + h).
2. Heuristic Function: The heuristic function (heuristic(current, goal))
computes the estimated cost from the current node to the goal using the
Euclidean distance formula:
3. A Algorithm (astar function):*
o Initialization: Sets up the open list (priority queue) and closed set.
o Main Loop:
Picks the node with the lowest f value.
Checks if the goal is reached. If so, it reconstructs the path
by tracing back through parent nodes.
Explores neighboring nodes (up, down, left, right).
Calculates the g, h, and f values for neighbors.
Adds neighbors to the open list if they are not in the closed
set and not blocked by obstacles.
4. Grid Example:
grid = [[0, 1, 0, 0, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 1, 0]]
0 = open cell, 1 = obstacle.
Start position: (0, 0), Goal position: (4, 4).
Output:
If a path is found, it prints the shortest path as a list of coordinates. Otherwise,
it indicates that no path is available.
Algorithm for A Search Algorithm:*
Step 1 : Start
Step 2 : Initialization:
Create two lists:
o Open List: Priority queue of nodes to be evaluated (starting with
the start node).
o Closed Set: Set of nodes already evaluated.
Initialize the start node with:
o g = 0: Cost from start to start is 0.
o h = heuristic(start, goal): Heuristic estimate from start to goal.
o f = g + h: Total cost.
Step 3 : Main Loop:
While the open list is not empty:
1. Get Current Node:
o Pop the node with the lowest f value from the open list.
2. Goal Check:
o If the current node is the goal, reconstruct the path:
Initialize an empty path list.
Trace back from the goal node to the start node using
parent pointers.
Return the reversed path list.
3. Add Current Node to Closed Set:
o Mark the current node as evaluated by adding it to the closed set.
Step 4 : Generate Neighbors:
For each possible move (up, down, left, right):
Calculate Neighbor Position: (dx, dy) offsets are applied to the current
node's position.
Boundary Check: Ensure the neighbor is within grid bounds.
Obstacle Check: Skip if the neighbor is an obstacle or in the closed set.
Step 5 : Calculate Costs:
For each valid neighbor:
G Cost (g): current_node.g + 1 (assuming uniform cost for movement).
Heuristic Cost (h): heuristic(neighbor_pos, goal).
Total Cost (f): g + h.
Step 6 : Check Open List:
If a node with the same position and a lower f value is already in the
open list, skip this neighbor.
Otherwise, add the neighbor to the open list.
Step 7 : Failure Handling:
If the open list is exhausted without finding the goal, return None to
indicate no path exists.
Heuristic Function:
The heuristic function uses the Euclidean distance formula to estimate
the cost from the current node to the goal.
This algorithm ensures the shortest path is found if one exists, thanks to the
admissible heuristic and the A* algorithm's optimal nature. Let me know if you
need more details or further explanations!
Step 8 : Stop
Source Code :
import heapq
import math
class Node:
def __init__(self, position, parent=None, g=0, h=0, f=0):
[Link] = position
[Link] = parent
self.g = g # Cost from start to node
self.h = h # Heuristic cost to goal
self.f = f # Total cost
def __lt__(self, other):
return self.f < other.f
def heuristic(current, goal):
# Using Euclidean distance as the heuristic
return [Link]((current[0] - goal[0]) ** 2 + (current[1] - goal[1])
** 2)
def astar(start, goal, grid):
open_list = []
closed_set = set()
start_node = Node(start, None, 0, heuristic(start, goal),
heuristic(start, goal))
[Link](open_list, start_node)
while open_list:
current_node = [Link](open_list)
if current_node.position == goal:
path = []
while current_node:
[Link](current_node.position)
current_node = current_node.parent
return path[::-1] # Return reversed path
closed_set.add(current_node.position)
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
neighbor_pos = (current_node.position[0] + dx,
current_node.position[1] + dy)
if not (0 <= neighbor_pos[0] < len(grid) and 0 <=
neighbor_pos[1] < len(grid[0])):
continue
if grid[neighbor_pos[0]][neighbor_pos[1]] == 1 or
neighbor_pos in closed_set:
continue
g = current_node.g + 1
h = heuristic(neighbor_pos, goal)
f=g+h
neighbor_node = Node(neighbor_pos, current_node, g, h, f)
if any(open_node.position == neighbor_pos and open_node.f
<= f for open_node in open_list):
continue
[Link](open_list, neighbor_node)
return None # No path found
if __name__ == '__main__':
grid = [
[0, 1, 0, 0, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 1, 0]
]
start = (0, 0)
goal = (4, 4)
path = astar(start, goal, grid)
if path:
print('Shortest path:', path)
else:
print('No path found!')
Output :
Shortest path: [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2), (3, 2), (4, 2), (4, 3), (4, 4)]
Explanation of the Path:
1. Start at (0, 0).
2. Move down to (1, 0).
3. Move down to (2, 0).
4. Move right to (2, 1).
5. Move right to (2, 2).
6. Move down to (3, 2).
7. Move down to (4, 2).
8. Move right to (4, 3).
9. Move right to (4, 4) (Goal Reached).
When No Path Exists:
If the goal is not reachable, the output will be:
No path found!
Result : The above program A* and A* algorithms(Example :find the shortest path)
Successfully executed.