Professional Documents
Culture Documents
AStar Program of 8 Puzzle
AStar Program of 8 Puzzle
In an 8 puzzle problem :
Eight (positive integer) tiles are given in a matrix.
The size(number of rows and columns) of the matrix depends on the number of tiles.
The number of rows in a matrix is equal to the square root of the number of tiles plus
one (square root(Number plus one)).
The number of columns in a matrix is equal to the square root of the number of tiles
plus one (square root(Number plus one)).
After the above calculations, the number of rows and columns are 3 in a matrix.
In this problem:
A start matrix and goal matrix is given (both the matrix contain 8 elements and a
blank space).
The task of the program is to take the input as a start matrix and convert it into a goal
matrix by use of various algorithms available such as uninformed and informed search
methods.
Uninformed means algorithms do not know where to search and search for what but
informed methods have this capability.
Uninformed methods:
Breadth-first search
Depth-first search
Linear search
Binary search
Informed methods:
A* Algorithms
A* Algorithm:
Is a type of informed search technique.
For search optimization, cost value or heuristic value is used.
A function is created to store and keep track of the node level and cost return the sum
of two.
A matrix containing the lowest function value will be processed in the next step.
This process is repeated until the function value is lowest with a heuristic value equal
to zero.
Run the code at the link given in the question to verify the output and code explanation.
Note: Examples of the 8-Puzzle problem and its solution using the A* algorithm,
detailed explanation of the code, and output snips are given in the explanation part.
Step-by-step explanation
Example of the 8-Puzzle problem and its solution using A* algorithm:
The complete code is divided into two classes:
I used these notations to explain the code so that plagiarism can be avoided.
Code explanation:
Methods in the class eight_puzzle_node (same as Node in reference)
[1]
def __init__(self,node_data,node_level,f_value):
self.node_data = node_data
self.node_level = node_level
self.f_value = f_value
Init method initializes the variables when the object is created and an instance of the
class is represented by a self keyword.
The variables:
node_data is the same as the start matrix as shown in the example above.
node_level is the same as the level in the above diagram which is used to keep
track of the position of the transformed matrix. Later it can be used to visualize
the working of the algorithm.
f_value is the sum of node_level and heuristic or cost. (Matrix with minimum
f_value is selected as the answer.
[2]Method for child generation:
def child_generation(self):
x,y = self.find_blank_space(self.node_data,'_')
cord_list = [[x,y-1],[x,y+1],[x-1,y],[x+1,y]]
n_children = []
for i in cord_list:
child = self.shuffle(self.node_data,x,y,i[0],i[1])
# if the blank space does not have any position value to move, it will
return None but if #position is not out of limit swapping of coordinates is
done in order to move the blank spaces in
# the given direction
if child is not None:
child_node = eight_puzzle_node(child,self.node_level+1,0)
# In the case the child is none, class is called with the level increment.
n_children.append(child_node)
# n_children is the list
return n_children
The blank space "_" moved in directions (left, right, down and up) to create the child
node.
(in the example above, blank space is at the centre and it moved left, right, up and down
to create 4 matrices in the next level)
x , y = self.find_blank_space(self.node_data, '_')
This line uses the function described below to find the x and y coordinates of the blank
space.
Initial blank space position:
The coordinate x and y-1 for the movement above of initial blank space position.
The coordinate x and y+1 for the movement to one step down.
The coordinate x-1 and y for the left movement.
The coordinate x+1 and y for the movement one step right.
def shuffle_method(self,puzzle,x1,y1,x2,y2):
if x2 >= 0 and x2 < len(self.node_data) and y2 >= 0 and y2 <
len(self.node_data):
temp_puzzle = []
temp_puzzle = self.copy_matrix(puzzle)
# copy the of the puzzle created
#swapping
temp = temp_puzzle[x2][y2]
temp_puzzle[x2][y2] = temp_puzzle[x1][y1]
temp_puzzle[x1][y1] = temp
return temp_puzzle
else:
return None
Parameters:
Puzzle: is the matrix to be transformed to the goal state
x1, x2, y1 and y2 are coordinates of blank spaces.
if x2 >= 0 and x2 < len(self.node_data) and y2 >= 0 and y2 < len(self.node_data)
To check if the positions are out of limits or not.
temp_puzzle = []
temp_puzzle = self.copy_matrix(puzzle)
The copy of the puzzle or matrix is created and stored in the list temp_puzzle. The copy
is created to avoid the modification of the original matrix.
If copying is not added, the system can lose the existence of the original values of the
matrix or puzzle.
At the last line of code, it returns None if there are no positions to move blank space.
[4] The method copy matrix:
[5] The method to find blank spaces:
Second class methods:
[1] init method
Parameters:
The puzzle is the matrix (start matrix)
Puzzle_size is the size of the start matrix
Two empty lists open_matrix and cloased_matrix are initialized to store the start matrix
and goal matrix.
[2] method to input from the user
def accept_user_puzzle(self):
#empty list to store user entry
puzzle = []
for k in range(0,self.n_size):
# split methos is used to split input string
# example "1 2 3 4".split() gives ["1", "2", "3", "4"]
tem = input().split(" ")
puzzle.append(tem)
return puzzle
This method is created to take input from the user.
The input provided by the user is string and split() method is used to convert the input
string to the list.
[3] Method to calculate the f value
def calc_fvalue(self,start_matrix,goal_matrix):
return self.hueristic(start_matrix.node_data,goal_matrix)
+start_matrix.node_level
Parameters:
Strat_matrix is the matrix given by the user
Goal_matrx is the final matrix that is obtained from the algorithm
F value is the sum of the cost and level of the node
[4] Method to calculate the cost which is also called heuristics.
This method calculates the cost at different levels.
Parameters:
Start_matrix
Goal_matrix
This condition is checking that the start_matrix and goal_matrix are equal or not, and
start_matrix element is blank space or not.
If the above condition holds, the cost is incremented by one.
This process will stop if the algorithm is able to convert start_matrix to goal_matrix
[5] The final method to combine all the processes
def final_process(self):
# take input from user
print("Input the start puzzle \n")
start_matrix = self.accept_user_puzzle()
# the function accepts the input from user and converts it into list.
print("input the goal_puzzle \n")
goal_matrix = self.accept_user_puzzle()
start_matrix = eight_puzzle_node(start_matrix,0,0)
# call the class with parameters as start_matrix entered by the user
# calculate the f value
start_matrix.f_value = self.calc_fvalue(start_matrix,goal_matrix)
# append the start_matrix to the open_matrix
self.open_matrix.append(start_matrix)
while True:
cur = self.open[0]
print("")
print(" | ")
print(" | ")
print(" \\\'/ \n")
# above three lines are used to print arrows in the output.
for p in cur.node_data:
for q in p:
print(q,end=" ")
print("")
# code will stop if algorithm produced or transformed start_matrix to
goal matrix
# given if block compares start_matrix and goal_matrix in order to
check if they are equal #to stop the code execution.
if(self.hueristic(cur.node_data,goal_matrix) == 0):
break
# if above condition does not hold , next lines will be executed.
for i in cur.child_generation():
i.f_value = self.calc_fvalue(i,goal_matrix)
self.open.append(i)
self.closed.append(cur)
del self.open[0]
# the list is sorted using f value (level plus cost)
self.open.sort(key = lambda x:x.f_value,reverse=False)
[6] driver code
puzzle = Eight_Puzzle(3)
puzzle.final_process()
The object of the class Eight_Puzzle is created.
Output snip:
[1]
[2]