In: Computer Science
Write a program in a language of your choice to perform a search using the A* algorithm for the eight puzzle problem, in which numbers may be shifted one space at a time to transform the initial state into the goal state (see p. 103 – 3rd Ed., pp. 105-106 – 2nd Ed. of the text).
2. a)
Use the start state-goal state combination given in pp. 103, Figure 3.28 (3rd Ed.), [pp. 105,
Figure 4.7 (2rd Ed.)], as (start_1, goal_1) (see page 2).
b) Use a new start state, which is given in page 2, the same goal state (start_2, goal_1).
c) Use a different goal state (the blank is now at the bottom right corner - see page 2),
and the same start state as part a (start_1, goal_2).
d) Use a the same start state as part b, and the same goal state as part c
(start_2, goal_2) (see page 2).
e) Also use { (start_3, goal_1), (start_3, goal_2), (start_3, goal_3), (start_1, goal_3),
(start_2, goal_3) } pairs given in page 2.
Use two different set of heuristic functions to estimate
distance from the goal
(See pp. 103 – 3rd Ed, p. 106 – 2nd Ed.)
h1: the number of misplaced tiles
h2: the sum of the distances of tiles from their goal positions
(Manhattan distance)
Write a report comparing the performance of the two heuristics on the nine different sets of (start_x, goal_x) combinations of part 2.
Performance measure: the length of the solution path (from the start state to the goal), and the actual time it takes to find the solution (i.e., to reach the goal state).
from copy import deepcopy class puzzle: def __init__ (self, starting, parent): self.board = starting self.parent = parent self.f = 0 self.g = 0 self.h = 0
def manhattan(self): h = 0 for i in range(3): for j in range(3): x, y = divmod(self.board[i][j], 3) h += abs(x-i) + abs(y-j) return h def goal(self): inc = 0 for i in range(3): for j in range(3): if self.board[i][j] != inc: return False inc += 1 return True def __eq__(self, other): return self.board == other.board def move_function(curr): curr = curr.board for i in range(3): for j in range(3): if curr[i][j] == 0: x, y = i, j break q = [] if x-1 >= 0: b = deepcopy(curr) b[x][y]=b[x-1][y] b[x-1][y]=0 succ = puzzle(b, curr) q.append(succ) if x+1 < 3: b = deepcopy(curr) b[x][y]=b[x+1][y] b[x+1][y]=0 succ = puzzle(b, curr) q.append(succ) if y-1 >= 0: b = deepcopy(curr) b[x][y]=b[x][y-1] b[x][y-1]=0 succ = puzzle(b, curr) q.append(succ) if y+1 < 3: b = deepcopy(curr) b[x][y]=b[x][y+1] b[x][y+1]=0 succ = puzzle(b, curr) q.append(succ) return q def best_fvalue(openList): f = openList[0].f index = 0 for i, item in enumerate(openList): if i == 0: continue if(item.f < f): f = item.f index = i return openList[index], index def AStar(start): openList = [] closedList = [] openList.append(start) while openList: current, index = best_fvalue(openList) if current.goal(): return current openList.pop(index) closedList.append(current) X = move_function(current) for move in X: ok = False #checking in closedList for i, item in enumerate(closedList): if item == move: ok = True break if not ok: #not in closed list newG = current.g + 1 present = False #openList includes move for j, item in enumerate(openList): if item == move: present = True if newG < openList[j].g: openList[j].g = newG openList[j].f = openList[j].g + openList[j].h openList[j].parent = current if not present: move.g = newG move.h = move.manhattan() move.f = move.g + move.h move.parent = current openList.append(move) return None #start = puzzle([[2,3,6],[0,1,8],[4,5,7]], None) start = puzzle([[5,2,8],[4,1,7],[0,3,6]], None) # start = puzzle([[0,1,2],[3,4,5],[6,7,8]], None) #start = puzzle([[1,2,0],[3,4,5],[6,7,8]], None) result = AStar(start) noofMoves = 0 if(not result): print ("No solution") else: print(result.board) t=result.parent while t: noofMoves += 1 print(t.board) t=t.parent print ("Length: " + str(noofMoves))