diff --git a/Path Finding/8 Puzzle Solver.py b/Path Finding/8 Puzzle Solver.py new file mode 100644 index 00000000..d69c52bf --- /dev/null +++ b/Path Finding/8 Puzzle Solver.py @@ -0,0 +1,147 @@ +position_of = {1:(0,0), 2:(0,1), 3:(0,2), + 4:(1,0), 5:(1,1), 6:(1,2), + 7:(2,0), 8:(2,1)} + +goal = [[1,2,3], + [4,5,6], + [7,8,0]] + +class Node: + def __init__(self, data, level, f): + self.data = data + self.f = f + self.level = 0 + self.N = len(data) + self.prev = None + + def neighbors(self): + neighbors = [] + N = self.N + + moves, (x,y) = self.find_moves() + + for i,j in moves: + state = self.copy(self.data) + state[x][y], state[i][j] = state[i][j], state[x][y] + neighbors.append(Node(state, self.level+1, 0)) + + return neighbors + + def copy(self, data): + temp = [] + + for i in data: + t = [] + for j in i: + t.append(j) + temp.append(t) + return temp + + + def find_blank(self, data): + N = self.N + + for i in range(N): + for j in range(N): + if data[i][j] == 0: + return (i,j) + + def find_moves(self): + x,y = self.find_blank(self.data) + moves = [] + + if (x != 0): + moves.append((x-1,y)) + if (y != 0): + moves.append((x,y-1)) + if (y != 2): + moves.append((x,y+1)) + if (x != 2): + moves.append((x+1,y)) + + return moves, (x,y) + +def heuristic(board, goal, heuristic_func): + count = 0 + + # Hamming Priority + if heuristic_func=='hamming': + for i in range(3): + for j in range(3): + if board[i][j] and board[i][j] != goal[i][j]: + count += 1 + + # Manhattan Distance + elif heuristic_func=='manhattan': + for i in range(3): + for j in range(3): + if board[i][j]: + x,y = position_of[board[i][j]] + manhattan = abs(x-i) + abs(y-j) + count += manhattan + + return count + +def getPath(): + path = [] + temp = curr + + while temp.prev: + path.insert(0, temp.data) + temp = temp.prev + + path.insert(0, temp.data) + + return path + +curr = None +def solve(start, heuristic_func): + global curr + + openSet = [] + closedSet = [] + + start = Node(start, 0, 0) + start.f = heuristic(start.data, goal, heuristic_func) + start.level + openSet.append(start) + + while len(openSet) > 0: + low = 0 + for i in range(len(openSet)): + if openSet[i].f < openSet[low].f: + low = i + + curr = openSet[low] + + if heuristic(curr.data, goal, heuristic_func) == 0: + break + + closedSet.append(curr.data) + openSet.remove(curr) + + for neighbor in curr.neighbors(): + if neighbor.data not in closedSet: + # f(x) = g(x) + h(x) + h_x = heuristic(neighbor.data, goal, heuristic_func) + g_x = neighbor.level + neighbor.f = g_x + h_x + openSet.append(neighbor) + neighbor.prev = curr + + + return getPath() + +def print_solution(board): + for step in solution: + for row in step: + print(row) + print() + + print("Total Steps:",len(solution)) + + +board = [[2,0,3], + [5,8,1], + [6,7,4]] +solution = solve(board, heuristic_func='manhattan') +print_solution(solution) diff --git a/Path Finding/README.md b/Path Finding/README.md index 8b137891..423aebfd 100644 --- a/Path Finding/README.md +++ b/Path Finding/README.md @@ -1 +1,30 @@ +# Solving 8-puzzle problem using A* algorithm + +The 8-puzzle consists of an area divided into 3x3 (3 by 3) grid. Each grid with in the puzzle +is known as tile and each tile contains a number ranged between 1 to 8, so that they can be +uniquely identified. Tile adjacent to the empty grid can be moved to the empty space leaving +its previous position empty until reaching the goal. + +# PROBLEM FORMULATION +- Goal: Goal State is initially given. +- State: Instance of Puzzle. +- Actions: Move the blank tile in left, up, down and right positions +- Performance: Number of total moves in the solution + +# A* ALGORITHM + +A* is an informed search algorithm used in path findings and graph traversals. It is a +combination of uniform cost search and best first search, which avoids expanding expensive +paths. A* star uses admissible heuristics which is optimal as it never over-estimates the path +to goal. The evaluation function A* star uses for calculating distance is + +- f(n) = g(n) + h(n) +- g(n) = cost so far to reach n +- h(n) = estimated cost from n to goal +- f(n) = estimated total cost of path through n to goal + +# Heuristic Functions +The heuristic function is a way to inform the search regarding the direction to a goal. It provides +an information to estimate which neighboring node will lead to the goal. The two heuristic +functions that we considered for solving 8-puzzle problem are