aiml3-17
aiml3-17
Introduction
AI:-
Artificial Intelligence (AI) refers to the simulation of human intelligence in machines that are
programmed to think, learn, and make decisions like humans. AI encompasses various techniques such as
machine learning, natural language processing, robotics, and computer vision. It powers applications ranging
from virtual assistants and recommendation systems to advanced autonomous vehicles.
Graph Search:-
Graph search is a process of systematically exploring a graph—a data structure made up of nodes
(vertices) connected by edges (links). The goal is to visit nodes in a specific order to solve problems like
finding the shortest path, detecting connectivity, or exploring all possible configurations in a system.
Examples of graph search algorithms include Breadth-First Search (BFS), Depth-First Search (DFS), and
A*.
• Uninformed Search:
o Also called "blind search," it does not use any knowledge about the problem to guide the
search.
o It relies solely on the problem definition and operates without a heuristic function.
o Examples: Breadth-First Search (BFS) and Depth-First Search (DFS).
• Informed Search:
o Also known as "heuristic search," it uses problem-specific knowledge (heuristics) to guide
the search more efficiently.
o These searches prioritize paths that appear to lead closer to the goal.
o Example: A* algorithm, where the heuristic helps estimate the cost to reach the goal.
2.1. Definition
Breadth-First Search (BFS) is a graph traversal algorithm designed to explore a graph in a level-wise
manner. Starting from a source node, it visits all nodes at the current depth level before moving to nodes at
the next level. This systematic approach ensures that BFS identifies the shortest path between the source and
any other node in unweighted graphs, making it highly effective for tasks such as shortest pathfinding and
connectivity detection.
2.2. Theory
The BFS algorithm is built on the concept of breadth-first exploration, where all neighbors of a node are
visited before exploring their descendants. It operates by using a queue, which enforces the First-In-First-
3
Out (FIFO) rule. This ensures that nodes are processed in the exact order in which they are discovered. BFS
avoids revisiting nodes by marking them as visited once they are enqueued.
1. Traversal Process:
o BFS starts with a source node, marking it as visited and adding it to the queue.
o Nodes are dequeued one by one, and their unvisited neighbors are added to the queue and
marked as visited.
o This process continues until all reachable nodes are visited.
2. Handling Different Graph Structures:
o Directed Graphs: Traversal follows the direction of edges.
o Undirected Graphs: Both directions of an edge are considered.
o Cyclic Graphs: BFS avoids infinite loops by maintaining a visited set.
o Disconnected Graphs: BFS must be restarted from another unvisited node to cover all
components.
3. Characteristics:
o Shortest Path: BFS guarantees finding the shortest path (measured in terms of edges) in
unweighted graphs.
o Exhaustive Search: When no specific target node is defined, BFS explores all nodes
systematically.
o Non-Recursive: Unlike Depth-First Search (DFS), BFS is inherently iterative, relying on a
queue for node management.
1. Initialize:
o Create an empty queue and enqueue the starting node.
o Mark the starting node as visited.
2. Exploration:
o While the queue is not empty:
▪ Dequeue a node and process it (e.g., print or store its value).
▪ Retrieve all neighbors of the dequeued node.
▪ For each unvisited neighbor:
▪ Mark it as visited.
▪ Enqueue the neighbor.
3. Termination:
o Continue the process until the queue is empty.
1. Time Complexity:
o BFS runs in O(V+E)O(V + E) time, where:
▪ VV: Number of vertices in the graph.
▪ EE: Number of edges in the graph.
2. Space Complexity:
o The algorithm requires O(V)O(V) space for:
▪ The visited set or array.
▪ The queue to manage nodes.
2.5. Applications
4
1. Shortest Path in Unweighted Graphs: BFS guarantees the shortest path in terms of edges between
two nodes in an unweighted graph.
2. Web Crawling: Search engines use BFS to explore all web pages linked from a given start page.
3. Social Network Analysis: BFS can be used to determine friend recommendations by exploring
connections up to a certain level.
4. Network Broadcast: BFS helps in efficiently broadcasting messages across all nodes in a network.
5. Finding Connected Components: BFS identifies all nodes within the same connected component in
an undirected graph.
6. Solving Mazes and Puzzles: BFS provides the shortest solution to problems like escaping a maze or
solving a puzzle.
Pros:
• Guarantees the shortest path in unweighted graphs.
• Easy to understand and implement.
• Systematic traversal ensures all nodes are visited.
Cons:
• Requires more memory compared to Depth-First Search (DFS), as the queue can grow significantly.
• Inefficient for graphs with very large branching factors or those with deep structures, as it explores all
possible paths.
# Add nodes (A to J)
nodes = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
G.add_nodes_from(nodes)
5
plt.title("Well-Connected Graph with BFS Traversal", fontsize=16)
plt.show()
while queue:
node = queue.popleft()
traversal_order.append(node)
visited.add(neighbor)
queue.append(neighbor)
return traversal_order
For input 1
For input 2
6
Enter the starting node for BFS traversal: A
BFS Traversal Order:
A -> B -> C -> D -> F -> E -> G -> H -> J -> I
2.9. Result
The BFS algorithm systematically explores all nodes in a graph, level by level, using a queue. For
unweighted graphs, BFS guarantees finding the shortest path from the source node to any reachable node. Its
applications in solving real-world problems further highlight its importance in computer science and related
fields.
3.1. Definition
Depth-First Search (DFS) is a graph traversal algorithm that explores as far as possible along each branch
before backtracking. It uses a stack (explicitly or implicitly via recursion) to keep track of the nodes visited.
DFS is particularly suitable for exhaustive exploration of graphs or when searching deep within hierarchical
structures.
3.2. Theory
DFS is based on the principle of exploring one path entirely before moving to the next. It starts at the root or
a specific starting node and traverses as far along a branch as possible until it hits a "dead-end." Once it
reaches a node with no unvisited neighbors, it backtracks to explore other paths.
1. Traversal Process:
o Start at a source node, marking it as visited.
o Move to an unvisited neighbor, marking it as visited, and repeat until there are no more
unvisited neighbors.
o Backtrack to the previous node and resume traversal for any remaining unvisited neighbors.
2. Types of Graphs:
o DFS works on directed, undirected, weighted, and unweighted graphs.
o It avoids infinite loops in cyclic graphs by keeping track of visited nodes.
3. Key Features:
o DFS can be implemented using recursion or an explicit stack.
o Unlike BFS, it doesn’t guarantee the shortest path in an unweighted graph.
1. Initialization:
o Create a visited set to track nodes that have been explored.
o Use a stack (or recursion) for maintaining nodes to visit next.
2. Process:
o Push the starting node onto the stack.
o While the stack is not empty:
▪ Pop a node from the stack and mark it as visited.
▪ Add its unvisited neighbors to the stack.
o Repeat until all reachable nodes are visited.
7
3. Termination:
o The algorithm stops when all reachable nodes from the starting point are visited.
• Time Complexity:
o O(V+E)O(V + E), where VV is the number of vertices and EE is the number of edges.
• Space Complexity:
o O(V)O(V), due to the visited set and the stack (or recursion).
3.5. Applications
1. Pathfinding:
o DFS can be used to find paths in mazes or puzzles.
2. Connected Components:
o Helps identify connected components in undirected graphs.
3. Topological Sorting:
o Used in directed acyclic graphs (DAGs).
4. Cycle Detection:
o Useful for detecting cycles in graphs.
5. Game AI:
o DFS is often used in strategy games to explore move options deeply.
Pros:
• Memory efficient for sparse graphs.
• Simple to implement using recursion.
• Useful for solving puzzles and exploring paths exhaustively.
Cons:
• Does not guarantee the shortest path.
• Can get stuck in deep paths if not carefully managed.
• Requires additional memory for recursive calls or a stack.
# Add 8 nodes
nodes = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
G.add_nodes_from(nodes)
8
]
G.add_edges_from(edges)
visited.add(start_node)
traversal_order = [start_node]
return traversal_order
For input 1
Enter the starting node for DFS traversal: A
DFS Traversal Order:
A -> B -> D -> C -> E -> F -> G -> H
9
For input 2
Enter the starting node for DFS traversal: F
DFS Traversal Order:
F -> E -> C -> A -> B -> D -> G -> H
3.9. Result
Depth-First Search (DFS) effectively explores all possible paths from a given starting node, deeply traversing
one branch before backtracking. For the given graph, DFS starts at node A and F, visiting nodes in a depth-
first order and providing a comprehensive traversal.
4. A* Search Algorithm
4.1. Definition
A* (A-Star) is a graph traversal and pathfinding algorithm widely used for finding the shortest path between
two nodes in a weighted graph. It combines the advantages of Dijkstra’s algorithm (cost evaluation) and
Greedy Best-First Search (heuristics), ensuring both optimality and efficiency.
4.2. Theory
• g(n): The cost of the path from the start node to the current node.
• h(n): A heuristic function estimating the cost from the current node to the goal node.
• f(n) = g(n) + h(n): The total estimated cost to reach the goal node via the current node.
The algorithm prioritizes nodes with the lowest f(n)f(n), ensuring that paths likely leading to the goal are
explored first. If the heuristic function h(n)h(n) is admissible (never overestimates the cost) and consistent,
A* guarantees an optimal solution.
1. Initialization:
o Place the starting node in an open priority queue.
o Set the gg-cost of the start node to 0, and ff-cost to h(start)h(start).
2. Exploration:
o While the open queue is not empty:
▪ Dequeue the node with the lowest ff-cost.
▪ If this node is the goal, reconstruct the path and terminate.
▪ For each neighbor of the current node:
▪ Calculate its tentative gg-cost.
▪ Update its gg-cost, ff-cost, and parent if the tentative gg-cost is better.
3. Path Reconstruction:
o Trace back from the goal to the start node using the parent pointers.
4. Termination:
o Stop if the goal is reached or all reachable nodes have been processed (indicating no path
exists).
10
4.4. Time, Space, and Complexity
• Time Complexity:
o O(E+VlogV)O(E + V \log V) in sparse graphs when using a priority queue, where VV is the
number of vertices and EE is the number of edges.
• Space Complexity:
o O(V)O(V) for maintaining the open and closed lists.
4.5. Applications
1. Pathfinding:
o Navigation systems (e.g., GPS) to compute the shortest route.
2. Game Development:
o AI pathfinding for game characters or entities.
3. Robotics:
o Motion planning and route optimization for robots.
4. Network Routing:
o Optimizing data
transmission paths.
# Add 8 nodes
nodes = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
G.add_nodes_from(nodes)
11
]
G.add_weighted_edges_from(edges)
# A* Algorithm Implementation
def a_star(graph, start, goal):
# Priority queue
queue = []
heapq.heappush(queue, (0, start))
came_from = {}
while queue:
# Get the node with the lowest f-cost
_, current = heapq.heappop(queue)
4.9. Result
The A* algorithm provides the most optimal path from the start to the goal node by balancing cost and
heuristics. For the given graph, A* efficiently computes the shortest path from A to H.
Code:-
import matplotlib.pyplot as plt
import networkx as nx
from collections import deque
import heapq
# Add 8 nodes
nodes = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
G.add_nodes_from(nodes)
13
G.add_weighted_edges_from(edges)
while queue:
node = queue.popleft()
traversal_order.append(node)
return traversal_order
visited.add(start_node)
traversal_order = [start_node]
return traversal_order
while queue:
# Get the node with the lowest f-cost
_, current = heapq.heappop(queue)
if choice == '1':
# BFS
start_node = input("\nEnter the starting node for BFS traversal: ").strip()
if start_node not in nodes:
print(f"Error: Start node '{start_node}' is not in the graph!")
else:
print("\nBFS Traversal Order:")
bfs_result = bfs(G.adj, start_node)
print(" -> ".join(bfs_result))
else:
print("Invalid choice! Please enter 1, 2, or 3.")
Graph:-
Figure 5 Graph for Single-code visualization of the graph search algorithms code
16
Enter your choice (1/2/3): 1
Enter the starting node for BFS traversal: D
BFS Traversal Order:
D -> B -> C -> F -> G -> A -> E -> H
6. Conclusion
BFS ensures shortest paths in unweighted graphs, DFS explores deeply for problem-solving, and A*
combines cost and heuristics to find optimal paths in weighted graphs. These algorithms power navigation,
AI, and network routing, enabling efficient solutions. Their versatility and adaptability make them
indispensable in computer science and real-world applications.
17