Posted by admin on 2025-09-17 20:05:20 | Last Updated by admin on 2025-10-16 04:49:47
Share: Facebook | Twitter | Whatsapp | Linkedin Visits: 27
Last Updated : 21 Aug, 2025
Informed search algorithms in AI are search methods that use extra knowledge, called heuristics, to prioritize which paths to explore. By estimating how close each possible step is to the goal, these algorithms can find solutions more quickly and efficiently than uninformed or "blind," search. They are widely used in AI for tasks like pathfinding and puzzle solving because they help navigate large, complex search spaces.
Let's see some popular informed search algorithm,
We will use this maze example to show the working of All Algorithms.
maze = [
[0, 0, 0, 0, 1],
[0, 1, 1, 0, 1],
[0, 0, 0, 0, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 0, 0],
]
start = (0, 0)
end = (4, 4)
Greedy Best-First Search always picks the next step that looks closest to the goal, using a guess (heuristic) about which choice is best. It tries to reach the goal as quickly as possible but isn't guaranteed to find the shortest path.
Advantage: Efficient at quickly finding a solution by following the most promising paths. Limitation: Can get stuck in local optima; does not guarantee finding the shortest (optimal) path.
In the code:
A priority queue (min-heap) is used to always pick the cell that looks closest to the goal (based only on heuristic distance). It tracks where each cell came from (came_from) to reconstruct the path at the end. It expands neighbors only if they are valid, not walls and not visited before. When the goal is reached, the path is reconstructed backwards.
import heapq
def heuristic(a, b):
return abs(a[0] - b[0]) + abs(a[1] - b[1])
def greedy_best_first_search(maze, start, end):
open_list = []
heapq.heappush(open_list, (heuristic(start, end), start))
came_from = {start: None}
visited = set()
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
while open_list:
_, current = heapq.heappop(open_list)
if current == end:
path = []
while current:
path.append(current)
current = came_from[current]
return path[::-1]
visited.add(current)
for dx, dy in directions:
neighbor = (current[0] + dx, current[1] + dy)
if (0 <= neighbor[0] < len(maze) and 0 <= neighbor[1] < len(maze[0]) and
maze[neighbor[0]][neighbor[1]] == 0 and neighbor not in visited):
visited.add(neighbor)
came_from[neighbor] = current
heapq.heappush(open_list, (heuristic(neighbor, end), neighbor))
return None
path = greedy_best_first_search(maze, start, end)
print("Greedy Best-First path:", path)
Output:
Greedy Best-First path: [(0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (2, 4), (3, 4), (4, 4)]
A* Search finds the shortest path by combining two things: how far we have already gone and a guess of how far is left to go. It checks both actual progress and potential, so it's very reliable if our guess (heuristic) is good. It uses a combined cost function f(n)=g(n)+h(n) actual path cost so far g(n) plus heuristic estimate h(n) to the goal. Finds both shortest and most cost-effective path with an admissible heuristic.
Advantage: Complete and optimal (when using an admissible heuristic); widely applicable. Limitation: Can consume high memory for large graphs or spaces
In the code:
def a_star_search(maze, start, end):
open_list = []
heapq.heappush(open_list, (0 + heuristic(start, end), 0, start))
came_from = {start: None}
cost_so_far = {start: 0}
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
while open_list:
_, cost, current = heapq.heappop(open_list)
if current == end:
path = []
while current:
path.append(current)
current = came_from[current]
return path[::-1]
for dx, dy in directions:
neighbor = (current[0] + dx, current[1] + dy)
if (0 <= neighbor[0] < len(maze) and 0 <= neighbor[1] < len(maze[0])
and maze[neighbor[0]][neighbor[1]] == 0):
new_cost = cost + 1
if neighbor not in cost_so_far or new_cost < cost_so_far[neighbor]:
cost_so_far[neighbor] = new_cost
priority = new_cost + heuristic(neighbor, end)
heapq.heappush(open_list, (priority, new_cost, neighbor))
came_from[neighbor] = current
return None
path = a_star_search(maze, start, end)
print("A* Search path:", path)
Output:
A* Search path: [(0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (2, 4), (3, 4), (4, 4)]
IDA* blends A*'s optimality and memory-efficient depth-first search. Performs iterative deepening using increasing cost thresholds computed from f(n).
Advantage: Uses far less memory than A*, suitable for huge search spaces (like puzzle solving). Limitation: Repeats a lot of work; can be slower than A* due to repeated traversal.
In the code:
def ida_star_search(maze, start, end):
def search(path, g, threshold):
node = path[-1]
f = g + heuristic(node, end)
if f > threshold:
return f
if node == end:
return path
min_threshold = float('inf')
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
for dx, dy in directions:
neighbor = (node[0] + dx, node[1] + dy)
if (0 <= neighbor[0] < len(maze) and 0 <= neighbor[1] < len(maze[0])
and maze[neighbor[0]][neighbor[1]] == 0 and neighbor not in path):
res = search(path + [neighbor], g + 1, threshold)
if isinstance(res, list):
return res
if res < min_threshold:
min_threshold = res
return min_threshold
threshold = heuristic(start, end)
path = [start]
while True:
res = search(path, 0, threshold)
if isinstance(res, list):
return res
if res == float('inf'):
return None
threshold = res
path = ida_star_search(maze, start, end)
print("IDA* path:", path)
Output:
IDA* path: [(0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (2, 4), (3, 4), (4, 4)]
Beam Search keeps track of only a set number of the best-looking options at each step (instead of everything). It moves forward with "the best few" options and ignores the rest, making it faster and lighter on memory, but it might miss the absolute best path.
Advantage: Reduces memory usage; effective in large or combinatorial search spaces. Limitation: May miss the optimal solution; solution quality depends on beam width.
In the code:
Instead of exploring all possible paths, it only keeps the best few (beam_width) paths at each level.
At every step:
Continues until goal is found or no paths left.
from collections import deque
def beam_search(maze, start, end, beam_width=2):
queue = deque([[start]])
while queue:
all_paths = []
while queue:
path = queue.popleft()
node = path[-1]
if node == end:
return path
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
for dx, dy in directions:
neighbor = (node[0] + dx, node[1] + dy)
if (0 <= neighbor[0] < len(maze) and 0 <= neighbor[1] < len(maze[0])
and maze[neighbor[0]][neighbor[1]] == 0 and neighbor not in path):
all_paths.append(path + [neighbor])
all_paths = sorted(
all_paths, key=lambda p: heuristic(p[-1], end))[:beam_width]
queue.extend(all_paths)
return None
path = beam_search(maze, start, end, beam_width=2)
print("Beam Search path:", path)
Output:
Beam Search path: [(0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (2, 4), (3, 4), (4, 4)]
informed-search-algo Visual Representation of Path Finding
Informed search algorithms are extensively used in various applications, such as: