Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
26 views11 pages

Practical 3 - Graphs

The document outlines the implementation of three search algorithms: Breadth-First Search (BFS), Depth-First Search (DFS), and A* algorithm, including their concepts, pseudo code, and Python code examples. BFS uses a queue for level-order traversal, DFS employs a stack for depth-first exploration, and A* utilizes a priority queue with heuristics for optimal pathfinding. Each algorithm is demonstrated with a sample graph and corresponding output for finding paths.

Uploaded by

hiaksharahere
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views11 pages

Practical 3 - Graphs

The document outlines the implementation of three search algorithms: Breadth-First Search (BFS), Depth-First Search (DFS), and A* algorithm, including their concepts, pseudo code, and Python code examples. BFS uses a queue for level-order traversal, DFS employs a stack for depth-first exploration, and A* utilizes a priority queue with heuristics for optimal pathfinding. Each algorithm is demonstrated with a sample graph and corresponding output for finding paths.

Uploaded by

hiaksharahere
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

UID - 2305035 Date:07/07/2025

Practical: 3 Graphs

AIM: A) Implementing Search Algorithms Hands-on coding of search
algorithms (e.g., BFS, DFS, A*)

CONCEPTS:

1.Graph Representation The graph is stored as a dictionary


where keys are nodes and values are
lists of neighbors.

2. Breadth-First Search (BFS) A graph traversal algorithm that


explores all neighbors level by level
using a queue.

3. Queue (deque) A double-ended queue from


collections used to store paths to
be explored in FIFO order.

4. Visited Set A set is used to keep track of visited


nodes to avoid cycles and repeated
work.

5. Path Tracking
Each element in the queue is a list
that represents the path from the start
node to the current node.​

6.Goal Check After popping a path, the code checks


if the last node is the goal. If yes, it
returns the path.

7. Neighbor Expansion If the current node isn’t the goal, all its
unvisited neighbors are added to the
queue with updated paths.
PSEUDO CODE:

Function BFS(graph, start, goal):

Create an empty set called visited


Create a queue and add [start] as the first path

While the queue is not empty:


Remove the first path from the queue
Set node as the last item in the path

If node equals goal:


Return the path

If node is not in visited:


Add node to visited

For each neighbor of node in the graph:


Make a copy of the current path
Add the neighbor to the copied path
Add the new path to the end of the queue

If the goal is not found:


Return None
CODE:

from collections import deque

def bfs(graph, start, goal):

visited = set()
queue = deque([[start]])

while queue:
path = queue.popleft()
node = path[-1]

if node == goal:
return path

if node not in visited:


visited.add(node)
for neighbor in graph.get(node, []):
new_path = list(path)
new_path.append(neighbor)
queue.append(new_path)

return None

graph = {
'A': ['B', 'C', 'D'],
'B': ['E', 'F'],
'C': ['G'],
'D': ['H', 'I'],
'E': ['J', 'K'],
'F': [],
'G': ['L'],
'H': [],
'I': ['M'],
'J': [],
'K': ['N'],
'L': [],
'M': [],
'N': []
}
path = bfs(graph, 'A', 'N')
print("Path to goal:", " → ".join(path))

OUTPUT:
AIM: B)Implementing DFS algorithm

CONCEPTS:

1. Depth First Search (DFS) A graph traversal algorithm that


explores one path completely before
moving to another path.

2. Stack (List of Paths) DFS uses a stack to store and explore


paths. The last path pushed is
explored first (LIFO).

3. Reversed Neighbors Neighbors are reversed before


pushing to the stack so the order
matches diagrams (left-to-right).

4. Path Tracking
Each element in the queue is a list
that represents the path from the start
node to the current node.​

PSEUDO CODE:

Function DFS(graph, start, goal):


Create an empty set called visited
Create a stack and push a list containing the start node

While stack is not empty:


Pop the top path from the stack
Let node be the last element in the path

If node is the goal:


Return path

If node is not in visited:


Add node to visited
For each neighbor of node in reversed order:
Create a new path by copying current path
Append neighbor to new path
Push new path to the stack
Return None // If goal is not found

CODE:

def dfs(graph, start, goal):

stack = [[start]] # Stack of paths


visited = set()

while stack:
path = stack.pop()
node = path[-1]

if node == goal:
return path

if node not in visited:


visited.add(node)
for neighbor in reversed(graph.get(node, [])): # Reverse to
# match diagram order
new_path = list(path)
new_path.append(neighbor)
stack.append(new_path)
# If the goal is never found, return None.

return None # No path found

graph = {
'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F', 'G'],
'D': [],
'E': [],
'F': [],
'G': []
}

path = dfs(graph, 'A', 'D')


print("DFS Path:", " → ".join(path))

OUTPUT:
Aim : C)Implementing A* algorithm

CONCEPTS:

CONCEPTS:

1.Graph (with weights) The graph is represented using a


dictionary. Each node points to a list of
neighbors and the cost to reach them.

2. Heuristic (h) A dictionary (h) that stores the


estimated cost from each node to the
goal. Helps guide the search faster

3. Priority Queue (heapq) heapq is used to always pick the


node with the lowest estimated total
cost (f = g + h).

4. g_score
Actual cost from the start node to the
current node. Starts with 0 for the start
node and infinity for others.​

5. f_score
Estimated total cost from start →
current → goal. Calculated as f = g
+ h. Used to sort nodes in the queue.

6. Came_from
A dictionary that remembers the best path
(previous node) to each visited node — used
to rebuild the final path.

7. Path Reconstruction
After reaching the goal, the
reconstruct_path() function backtracks
using came_from to print the full path.

PSEUDO CODE:

Create an empty priority queue called open_set


Add (0, start) into open_set

Create an empty dictionary called came_from


Set g_score of all nodes to infinity
Set g_score[start] = 0

Set f_score of all nodes to infinity


Set f_score[start] = heuristic[start]

While open_set is not empty:


Remove the node with the lowest f_score → current

If current equals goal:


Return the path (using reconstruct_path) and the total cost

For each neighbor and its cost of current in the graph:


Calculate tentative_g = g_score[current] + cost

If tentative_g < g_score[neighbor]:


Update came_from[neighbor] = current
Update g_score[neighbor] = tentative_g
Update f_score[neighbor] = tentative_g + heuristic[neighbor]
Add (f_score[neighbor], neighbor) to open_set

If goal is not found:


Return None and infinity as cost

CODE:

import heapq

def a_star(graph, start, goal, h):


open_set = []
heapq.heappush(open_set, (0, start))

came_from = {}
g_score = {node: float('inf') for node in graph}
g_score[start] = 0

f_score = {node: float('inf') for node in graph}


f_score[start] = h[start]

while open_set:
current_f, current = heapq.heappop(open_set)

if current == goal:
return reconstruct_path(came_from, current), g_score[goal]

for neighbor, cost in graph[current]:


tentative_g = g_score[current] + cost

if tentative_g < g_score[neighbor]:


came_from[neighbor] = current
g_score[neighbor] = tentative_g
f_score[neighbor] = tentative_g + h[neighbor]
heapq.heappush(open_set, (f_score[neighbor], neighbor))

return None, float('inf')

def reconstruct_path(came_from, current):


path = [current]
while current in came_from:
current = came_from[current]
path.append(current)
path.reverse()
return path

# Graph and heuristic from your image


graph = {
'A': [('B', 1), ('C', 4)],
'B': [('D', 3)],
'C': [('E', 5)],
'D': [('F', 2)],
'E': [('G', 3)],
'F': [('G', 1)],
'G': []
}

h = {
'A': 5,
'B': 6,
'C': 4,
'D': 3,
'E': 3,
'F': 1,
'G': 0
}

# Run A* from A to G
path, cost = a_star(graph, 'A', 'G', h)
print("Path:", " → ".join(path))
print("Total Cost:", cost)

You might also like