0% found this document useful (0 votes)
19 views10 pages

Lab 6

Uploaded by

Alex Siryani
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)
19 views10 pages

Lab 6

Uploaded by

Alex Siryani
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/ 10

🤖

Lab6:BFS
Tree Search vs Graph Search
Tree Search
Definition: A basic search algorithm for exploring possible states in a tree.

Key Characteristics:

Uses a frontier: A list of leaf nodes available for exploration.

Does not keep track of previously visited nodes (no memory of past
states).

Loop:

1. Check if the frontier is empty.

2. Remove a node from the frontier.

3. If it's the goal, return the solution.

4. Otherwise, expand the node and add the new states to the frontier.

Graph Search
Definition: A refined search algorithm for exploring a graph.

Key Characteristics:

Lab6:BFS 1
Maintains an explored set: Keeps track of visited nodes to avoid re-
exploration.

Ensures no state is added to the frontier more than once.

Loop:

1. Check if the frontier is empty.

2. Remove a node from the frontier.

3. If it's the goal, return the solution.

4. Add the node to the explored set.

5. Expand the node and add new states to the frontier if they’re not
already in the explored set or frontier.

Breadth-First Search (BFS) Algorithm


Definition: BFS is a graph traversal algorithm, it explores all nodes at the current
depth before moving to the next depth level.

Key Characteristics:

FIFO queue: Nodes are explored in the order they’re added to the frontier.

Explores shortest paths in unweighted graphs.

Steps:
1. Start with the initial node and add it to the queue.

2. While the queue is not empty:

Dequeue the first node.

Mark it as visited.

Check if it’s the goal; if yes, stop.

Add all unvisited neighbors to the queue.

3. Repeat until the queue is empty or the goal is found.

Lab6:BFS 2
graph = {
'5' : ['3', '7'],
'3' : ['2', '4'],
'7' : ['8'],
'2' : [],
'4' : ['8'],
'8' : []
}

visited = [] # List for visited or explored nodes.


queue = [] # Initialize a queue or frontier.

def bfs(visited, graph, node, goal): # function for BFS


visited.append(node) # Mark the start node as visited.
queue.append(node) # Add the start node to the queue.

while queue: # Loop until the queue is empty.


m = queue.pop(0) # Dequeue a node.
print(m, end=" ") # Print the current node.

# Check if the current node is the goal.


if m == goal:
return m

# Explore neighbors of the current node.


for neighbour in graph[m]:
if neighbour not in visited: # If neighbor is unvisited
visited.append(neighbour) # Mark it as visited.
queue.append(neighbour) # Add it to the queue.

# Call BFS and print the result.


print("Following is the Breadth-First Search:")
bfs(visited, graph, '5', '4') # Start BFS from node '5', goal =

Lab6:BFS 3
Step-by-Step Execution
1. Initialization:

Visited list: Tracks nodes already visited ( visited = [] ).

Queue: Stores nodes to be explored ( queue = [] ).

2. Add Start Node:

Start BFS from node 5 .

Add 5 to the visited list and the queue .

3. Loop Execution:

While the queue is not empty:

Dequeue a Node: Remove the first element from the queue (FIFO).

Print the node to visualize the traversal order.

Check if the node is the goal:

If yes, stop and return the goal.

Explore all neighbors of the current node:

For each unvisited neighbor, add it to the visited list and the queue .

Lab6:BFS 4
1. bfs() :

Inputs:

visited : Tracks visited nodes.

graph : The adjacency list.

node : The start node.

goal : The goal node.

Outputs:

Traversal order and stops when the goal is found.

2. visited.append() :

Marks a node as visited.

3. queue.append() :

Adds a node to the queue.

4. queue.pop(0) :

Removes the first node from the queue.

Lab Solution:
Graph Search and Path Reconstruction using BFS

Exercise 1: Representing the Graph

Objective:
Analyze and represent the given undirected graph.

Problem Description:
The given map contains cities connected by undirected edges. Write a Python
program to represent the graph using an adjacency list or adjacency matrix.

Lab6:BFS 5
Output:
Represent the graph using the selected data structure.

graph = {
'A': ['B', 'C'],
'B': ['A'],
'C': ['A', 'D', 'E', 'F'],
'D': ['C'],
'E': ['C', 'J'],
'F': ['C', 'G'],
'G': ['F', 'L', 'M', 'N'],
'H': [],
'J': ['E', 'K'],
'K': ['J'],
'L': ['G'],
'M': ['G'],

Lab6:BFS 6
'N': ['G']
}

Exercise 2: Pseudocode for BFS Search

Objective:
Write a pseudocode for finding a path from city A to city K using Breadth-First
Search (BFS).

function BFS(graph, start, goal):


Create an empty queue
Add the start node to the queue
Create a set to store visited nodes
Create a dictionary to store the parent of each visited node

while the queue is not empty:


Dequeue the front node and assign it to current_node
If current_node is the goal:
Return the parent dictionary and True (goal reached)

For each neighbor of current_node:


If neighbor is not in visited:
Mark neighbor as visited
Add neighbor to the queue
Set the parent of neighbor to current_node

Return the parent dictionary and False (goal not reached)

Exercise 3: BFS Implementation

Objective:
Implement the BFS function to explore the graph.

Use a queue to store nodes during traversal.

Lab6:BFS 7
Store the parent of each visited node to assist in path reconstruction.

Requirements:
1. Receive the graph, initial state, and goal state as inputs.

2. Use the queue package for managing nodes during BFS.

3. Store the parent of each node in a suitable data structure (e.g., dictionary).

import queue

def BFS(graph, start, goal):


q = queue.Queue()
q.put(start)

visited = set()
visited.add(start)

parent = {}

while not q.empty():


current_node = q.get()

if current_node == goal:
return parent, True

for neighbor in graph[current_node]:


if neighbor not in visited:
visited.add(neighbor)
parent[neighbor] = current_node
q.put(neighbor)

return parent, False

start = 'A'
goal = 'K'

Lab6:BFS 8
parent, goal_reached = BFS(graph, start, goal)

if goal_reached:
print(f"\nThe goal '{goal}' was reached.")
else:
print(f"\nThe goal '{goal}' was NOT reached.")

Exercise 4: Path Reconstruction

Objective:
Implement the pathReconstruction() function to reconstruct the path from the
start to the goal state using the parent dictionary returned by BFS.

function pathReconstruction(parent, goal_reached, goal):


path <- an empty list
if goal_reached:
Add goal to path
node <- parent[goal]
while node is not the initial state:
Add node to path
node <- parent[node]
Reverse the path
Return path

def pathReconstruction(parent, goal_reached, goal):


path = []
if goal_reached:
# Add the goal state to the path
path.append(goal)
node = parent.get(goal, None)

# Traverse back using the parent dictionary


while node is not None:
path.append(node)

Lab6:BFS 9
node = parent.get(node, None)

# Reverse the path to start from the initial state


path.reverse()

return path

start = 'A'
goal = 'K'
parent, goal_reached = BFS(graph, start, goal)

# Reconstruct the path


path = pathReconstruction(parent, goal_reached, goal)

# Print the reconstructed path


if goal_reached:
print(f"Reconstructed Path from {start} to {goal}: {' -> '.j
else:
print(f"No path found from {start} to {goal}.")

Lab6:BFS 10

You might also like