The 8-Puzzle is a captivating sliding tile game, with the 15-Puzzle being its more common counterpart.
The 8-Puzzle
This puzzle comprises a 3x3 grid filled with numbered tiles, except for one missing tile, often denoted by an empty space or a period. The ultimate objective is to rearrange the tiles in a specific order while adhering to the rule of sliding only one tile into the empty space at a time.
In our exploration of this puzzle, we will aim to reach the following configuration as our target:
In this post, we will explore different approaches to solving the classic 8-Puzzle using uninformed search and informed search. We will also delve into specific search techniques, such as Breadth-First Search, Depth-Limited Search, Iterative Deepening, and Informed Search using Heuristics and A* Search.
State Representation and Problem Setup
In the provided code below, we will define a class called Node which serves as the state representation for the 8-Puzzle problem.
Initialization: The Node class is initialized with a 3x3 NumPy array, representing the current state of the 8-Puzzle.
State Visualization: The vis method is used to display the current state of the 8-Puzzle.
Child Node Generation: The child_node method generates a new child node by simulating a move in a specified direction (“Left,” “Right,” “Up,” or “Down”). It creates a copy of the current state and swaps the position of the empty cell (0) with the adjacent cell in the chosen direction.
Available Actions: The avail_actions method determines the available actions (moves) that can be made from the current state. It returns a list of valid actions by considering the current position of the empty cell (0) and excluding actions that would move the empty cell out of bounds.
Uninformed Search: Breadth-First
Uninformed Search, as the name suggests, operates without any prior knowledge of the problem domain. For the 8-Puzzle, this means shuffling the tiles around until you reach the desired state. Let’s start with Breadth-First Search, which is a systematic approach that explores all possible paths, level by level.
Uninformed Search: Depth-Limited Search and Iterative Deepening
If we want to search for the deepest level first, it becomes a Depth-First Search. To make it more efficient, we can implement Depth-Limited Search, a variation of Depth-First Search with a depth limit. This avoids getting stuck in infinite paths.
Iterative Deepening performs a series of Depth-Limited Searches with increasing depth limits. It combines the benefits of Breadth-First Search and Depth-First Search. This ensures optimal solutions without a huge memory used.
Informed Search: Heuristics and A* Search
A* Search is a powerful and widely used algorithm in the field of artificial intelligence and computer science. It is particularly notable for its efficiency and optimality in finding the shortest path or solution in a search space.
A* Search leverages a heuristic, which provides an informed estimate of the cost from the current state to the goal. By incorporating this heuristic, A* Search intelligently explores the most promising paths while systematically examining the search space.
In this post, we’ll explore the key concepts behind A* Search and employ A* Search for solving 8-Puzzle. We will use two types of Heuristics: the Number of Wrong Tiles, and the Manhattan Distance.
Manhattan Distance =
x_current - x_target
+
y_current - y_target
, where we calculate the sum of the horizontal and vertical distances it is away from its desired goal position.
Heuristics
A* Search
Comparing the Efficiency
A* Search is typically more efficient than Uninformed Search algorithms, such as Iterative Deepening, while Breadth-First Search is usually the most time-consuming. We will estimate the time they take to solve the 8-Puzzle below.