A Star using the Algorithm in the book
Begin at the start node
While destination node is not visited
For each node connected to the current node
Add it to the list of open nodes
Add the distance from the start (g) to the heuristic estimate of the
distance to the end (h) to make f
Assign this value f to the node
Next node
Make the unvisited node with the lowest value of (f) the current node
https://colab.research.google.com/drive/1IPD51AOJxlLna3yWBXedvzVmOGXP8K9T?usp=sharing
Okay, let's go through the code line by line, using examples from the sample graph provided:
import heapq
● Expla nation: Imports the heapq module, which provides functions for working with priority queues.
● Example: Imagine heapq as a tool to manage a priority list of cities to visit, where the priority is based on
their estimated distance to the goal ('D' in this case).
def a_star(start, goal, graph, heuristic):
● Explanation: Defines a function named a_star that takes the starting node (start), the goal node (goal),
the graph structure (graph), and a heuristic function (heuristic) as input.
● Example: This function is like a navigation system that takes your starting city ('A'), your destination city ('D'),
a map of the cities and roads (graph), and estimated distances to the destination (heuristic) as input to
calculate the shortest route.
open_list = []
● Explanation: Initializes an empty list called open_list to store the nodes that need to be explored.
● Example: Think of this as an empty to-do list of cities you need to consider during your journey from 'A' to 'D'.
heapq.heappush(open_list, (0, start)) # Priority queue based on f = g + h
● Explanation: Adds the starting node (start) to the open_list with an initial cost of 0. The open_list acts
as a priority queue, where nodes with lower estimated total costs (f = g + h) have higher priority.
● Example: You add your starting city 'A' to your to-do list with an initial cost of 0, as you are already there.
g_scores = {node: float('inf') for node in graph}
● Explanation: Creates a dictionary called g_scores to store the cost to reach each node from the starting
node. Initially, all nodes are assigned an infinite cost, except for the starting node.
● Example: You assume it takes an infinite amount of time to reach any city initially, except for 'A' where you
start, which has a cost of 0.
g_scores[start] = 0
● Explanation: Sets the cost to reach the starting node to 0.
● Example: You are already at city 'A', so the cost to reach it is 0.
came_from = {}
● Explanation: Creates an empty dictionary called came_from to store the path by keeping track of the
preceding node for each node in the path.
● Example: This dictionary will help you remember how you reached each city on your route, so you can
retrace your steps later.
while open_list:
● Explanation: Enters a loop that continues as long as there are nodes in the open_list to explore.
● Example: You will keep planning your trip as long as there are cities on your to-do list.
current_f, current = heapq.heappop(open_list)
● Explanation: Retrieves and removes the node with the lowest estimated total cost (current_f) from the
open_list and assigns it to current.
● Example: You pick the city from your to-do list that has the lowest estimated total distance to 'D' and mark it
as your current city. Let's say 'A' is picked first.
if current == goal:
● Explanation: Checks if the current node is the goal node.
● Example: You check if your current city is 'D', your destination.
path = []
● Explanation: If the current node is the goal node, initializes an empty list called path to store the final path.
● Example: If you have reached 'D', you start a new list to write down your final route.
while current in came_from:
● Explanation: Enters a loop that backtracks from the goal node to the starting node using the came_from
dictionary.
● Example: You trace your steps back from 'D' to 'A' using the notes you made in the came_from dictionary.
path.append(current)
● Explanation: Adds the current node to the path list.
● Example: You write down the current city on your route list.
current = came_from[current]
● Explanation: Moves to the preceding node in the path using the came_from dictionary.
● Example: You go back to the city you came from to continue tracing your route.
path.append(start)
● Explanation: Adds the starting node to the path list.
● Example: You write down your starting city 'A' at the beginning of your route list.
return path[::-1] # Return the path in the correct order
● Explanation: Reverses the path list to get the correct order from start to goal and returns it.
● Example: You flip your route list to get the correct order from 'A' to 'D'.
for neighbor, cost in graph[current]:
● Explanation: Iterates through the neighbors of the current node and their associated costs.
● Example: If your current city is 'A', you look at its neighbors 'B' (with a cost of 1) and 'C' (with a cost of 4).
tentative_g = g_scores[current] + cost
● explanation: Calculates the tentative cost to reach a neighbor from the current node.
● Example: You calculate the cost to reach 'B' from 'A' as g_scores['A'] + 1 = 0 + 1 = 1.
if tentative_g < g_scores[neighbor]:
● Explanation: Checks if the tentative cost is lower than the current known cost to reach the neighbor.
● Example: You compare the calculated cost to reach 'B' (1) with the current cost to reach 'B' (which was
initially infinity).
g_scores[neighbor] = tentative_g
● Explanation: If the tentative cost is lower, updates the cost to reach the neighbor in the g_scores dictionary.
● Example: Since 1 is less than infinity, you update the cost to reach 'B' to 1.
f_score = tentative_g + heuristic[neighbor]
● Explanation: Calculates the estimated total cost (f = g + h) to reach the goal through the neighbor.
● Example: You calculate the estimated total cost to reach 'D' through 'B' as 1 + heuristic['B'] = 1 + 6
= 7.
heapq.heappush(open_list, (f_score, neighbor))
● Explanation: Adds the neighbor to the open_list with its estimated total cost as priority.
● Example: You add 'B' to your to-do list with a priority of 7.
came_from[neighbor] = current
● Explanation: Records that you reached the neighbor from the current node in the came_from dictionary.
● Example: You make a note that you reached 'B' from 'A'.
return None # No path found
● Explanation: If the open_list becomes empty before reaching the goal node, it means there is no path, and
the function returns None.
● Example: If there were no connections between cities in the graph, and you couldn't reach 'D' from 'A', the
function would return None.
graph = {
'A': [('B', 1), ('C', 4)],
'B': [('C', 2), ('D', 5)],
'C': [('D', 1)],
'D': []
● Explanation: Defines the graph structure as a dictionary where keys are nodes and values are lists of
connected nodes with their associated costs.
● Example: This represents the map of cities and roads. City 'A' is connected to 'B' with a cost of 1 and to 'C'
with a cost of 4.
heuristic = {'A': 7, 'B': 6, 'C': 2, 'D': 0} # Estimated distances to goal 'D'
● Explanation: Defines the heuristic function as a dictionary containing estimated distances from each node
to the goal node.
● Example: This represents the estimated distances from each city to 'D'. The heuristic for 'A' is 7, meaning it's
estimated to be 7 units away from 'D'.
path = a_star('A', 'D', graph, heuristic)
● Explanation: Calls the a_star function with the starting node 'A', the goal node 'D', the graph structure, and
the heuristic function to find the shortest path.
● Example: You use the navigation system (a_star function) to calculate the shortest route from 'A' to 'D'
based on the provided map and estimated distances.
print("Shortest Path:", path)
● Explanation: Prints the shortest path found by the a_star function.
● Example: The navigation system outputs the shortest route, which might be ['A', 'B', 'C', 'D'] in this case.