Lab 7
Lab 7
(CEL 409)
Lab Journal: 7
Objective
The objective of this report is to explore and analyze the Greedy Best-First Search and A Search*
algorithms. We will discuss their principles, compare their approaches, and understand their
applications in solving pathfinding problems. By the end of this report, readers should have a clear
understanding of these search algorithms and their trade-offs
Software
• Jupyter notebook
Introduction
Greedy Best-First Search
Greedy Best-First Search is an informed search algorithm that aims to find the most promising path
from a given starting point to a goal. It prioritizes paths based on their heuristic values, regardless of
whether they are actually the shortest paths. Process is quiet simple it evaluate the cost of each
possible path using a heuristic function. Expand the path with the lowest heuristic cost. Repeat until
the goal is reached. Greedy Best-First Search is simple and easy to implement, Fast and efficient, and
Requires low memory.
A* Search Algorithm
A* combines features of uniform-cost search and pure heuristic search to efficiently compute optimal
solutions. The cost associated with a node is (f(n) = g(n) + h(n)), where (g(n)) is the cost from the
initial state to node (n) and (h(n)) is the heuristic estimate. A* guarantees optimal solutions if the
heuristic function is admissible (never overestimates actual cost). Among shortest-path algorithms
using the given heuristic, A* expands the fewest nodes.
Applications: Pathfinding, robotics, game AI, and more.
Lab Tasks
Task 1
Implement Greedy Best First Search Algorithm for the given example, if starting node is Arad and
goal node is Bucharest.
Code
def greedy_best_first_search(graph, heuristic_values, start, goal):
visited = set()
current_node = start
path = [current_node]
total_cost = 0
while current_node != goal:
visited.add(current_node)
neighbors = graph[current_node]
next_node = min(neighbors, key=lambda x: heuristic_values[x])
path.append(next_node)
total_cost += graph[current_node][next_node]
print("Visited:", current_node)
current_node = next_node
path.append(goal)
total_cost += heuristic_values[goal]
print("Goal reached:", current_node)
print("Final Path:", path)
print("Total Cost ", total_cost)
graph = {
"Arad": {"Sibiu": 140, "Timisoara": 118, "Zernid": 75},
"Sibiu": {"Arad": 140, "Fagaras": 99, "Oradea": 151, "Rimnicu Vilcea": 80},
"Fagaras": {"Sibiu": 99, "Bucharest": 211},
"Rimnicu Vilcea": {"Craivo": 146, "Pitesti": 97, "Sibiu": 80},
"Pitesti": {"Bucharest": 101, "Craivo": 138, "Rimnicu Vilcea": 97}
}
heuristic_values = {
"Arad": 366, "Bucharest": 0, "Craivo": 160, "Fagaras": 176,
"Oradea": 380, "Pitesti": 10, "Rimnicu Vilcea": 193, "Sibiu": 253,
"Timisoara": 329, "Zernid": 374
}
Task 2
Implement A* Algorithm for the graph given in Task1, if starting node is Arad and goal node is
Bucharest.
Code
from heapq import heappop, heappush
while frontier:
_, current_node = heappop(frontier)
if current_node == goal:
break
visited.add(current_node)
for neighbor, cost in graph[current_node].items():
new_cost = cost_so_far[current_node] + cost
if neighbor not in cost_so_far or new_cost < cost_so_far[neighbor]:
cost_so_far[neighbor] = new_cost
priority = new_cost + heuristic_values[neighbor]
heappush(frontier, (priority, neighbor))
came_from[neighbor] = current_node
path = []
current_node = goal
while current_node != start:
path.append(current_node)
current_node = came_from[current_node]
path.append(start)
path.reverse()
Conclusion
In conclusion, both GBFS and A* Search algorithms offer effective solutions to pathfinding and
optimization problems, each with its advantages and limitations. The choice between these
algorithms depends on factors such as problem constraints, computational resources, and the
importance of finding an optimal solution. Understanding the principles and characteristics of GBFS
and A* enables informed decision-making and efficient problem-solving in various application
domains.