Advertisement
Guest User

Untitled

a guest
Sep 21st, 2017
419
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.30 KB | None | 0 0
  1. #########################
  2. #   Matthew Callens     #
  3. #   mcallen1@umbc.edu   #
  4. #                       #
  5. #   CS 471 Homework 2   #
  6. #                       #
  7. #   Usage in README.md  #
  8. #########################
  9.  
  10. import random
  11. import sys
  12. import heapq
  13. from timeit import default_timer
  14. from copy import copy, deepcopy
  15. from math import sqrt
  16.  
  17.  
  18. class Node:
  19.     def __init__(self, val, par):
  20.         self.val = val
  21.         self.parent = par
  22.         self.h = 0
  23.         self.g = 0
  24.         self.variant = random.randint(1, 500)
  25.  
  26.     def __find(self, item):
  27.         for i, s in enumerate(self.val):
  28.             try:
  29.                 tmp = s.index(item)
  30.                 return (i, tmp)
  31.             except ValueError:
  32.                 continue
  33.  
  34.     def collect(self):
  35.         print('Collecting solution path...')
  36.         sequence = list()
  37.  
  38.         def backtrack(node):
  39.             if not node.parent == None:
  40.                 backtrack(node.parent)
  41.             sequence.append(node)
  42.  
  43.         backtrack(self)
  44.         return sequence
  45.  
  46.     def __get_moves(self):
  47.         loc = self.__find(' ')
  48.         row, column = loc
  49.         available = list()
  50.  
  51.         bound = len(self.val) - 1
  52.  
  53.         if row > 0:
  54.             available.append((row - 1, column))
  55.         if row < bound:
  56.             available.append((row + 1, column))
  57.         if column > 0:
  58.             available.append((row, column - 1))
  59.         if column < bound:
  60.             available.append((row, column + 1))
  61.  
  62.         return available
  63.  
  64.     def create_children(self):
  65.         legal = self.__get_moves()
  66.         blank = self.__find(' ')
  67.         blank_row, blank_col = blank
  68.  
  69.         def swap_tiles(a, b):
  70.             new_state = deepcopy(self.val)
  71.             new_state[a[0]][a[1]] = self.val[b[0]][b[1]]
  72.             new_state[b[0]][b[1]] = self.val[a[0]][a[1]]
  73.             child = Node(new_state, self)
  74.             child.g = self.g + 1
  75.             return child
  76.  
  77.         return list(map(lambda move: swap_tiles((blank_row, blank_col), move), legal))
  78.  
  79.     def __hash__(self):
  80.         x = self.g + self.h + self.variant
  81.         if not self.parent == None:
  82.             x += self.parent.g + self.parent.h
  83.         return x
  84.  
  85.     def __str__(self):
  86.         display = ''
  87.         for i in range(len(self.val)):
  88.             for j in range(len(self.val[i])):
  89.                 display += '{} '.format(self.val[i][j])
  90.             display += '\n'
  91.         return display
  92.  
  93.     def __lt__(self, other):
  94.         return (self.g + self.h) < (other.g + other.h)
  95.  
  96.     def __eq__(self, other):
  97.         if other == None: return False
  98.  
  99.         for i in range(len(self.val)):
  100.             if not self.val[i] == other.val[i]:
  101.                 return False
  102.         return True
  103.  
  104.  
  105. def create_2d(l, n):
  106.     jump = int(sqrt(n))
  107.     tmp = list()
  108.     i = 0
  109.     while i < n:
  110.         tmp.append(l[i:i + jump])
  111.         i += jump
  112.     return tmp
  113.  
  114.  
  115. def initialize():
  116.     n = int(sys.argv[1])
  117.     random.seed(sys.argv[2])
  118.     state = list(range(1, n)) + [' ']
  119.     goal = copy(state)
  120.     random.shuffle(state)
  121.     return create_2d(state, n), create_2d(goal, n)
  122.  
  123.  
  124. def manhattan(node, goal, size):
  125.     total = 0
  126.     for i in range(len(node.val)):
  127.         for j in range(len(node.val[i])):
  128.             if node.val[i][j] == ' ' or node.val[i][j] == goal.val[i][j]: continue
  129.             goal_row = (node.val[i][j] - 1) // size
  130.             goal_col = (node.val[i][j] - 1) % size
  131.             total += abs(goal_row - i) + abs(goal_col - j)
  132.     return total
  133.  
  134.  
  135. def is_solvable(state):
  136.     n = (len(state) ** 2)
  137.     inversions = 0
  138.     tmp = [j for i in state for j in i]
  139.  
  140.     for i in range(n - 1):
  141.         for j in range(i + 1, n):
  142.             if not tmp[i] == ' ' and not tmp[j] == ' ' and tmp[i] > tmp[j]:
  143.                 inversions += 1
  144.     return inversions % 2 == 0
  145.  
  146.  
  147. def a_star(start, goal, size):
  148.     open_nodes = []
  149.     heapq.heappush(open_nodes, (0, start))
  150.  
  151.     costs = dict()
  152.     costs[start] = 0
  153.  
  154.     while open_nodes:
  155.         curr_tup = heapq.heappop(open_nodes)
  156.         curr = curr_tup[1]
  157.  
  158.         if curr == goal:
  159.             print('Success!')
  160.             return curr.collect()
  161.  
  162.         moves = curr.create_children()
  163.  
  164.         for m in moves:
  165.             new_cost = costs[curr] + m.g
  166.             if m not in costs or new_cost < costs[m]:
  167.                 m.h = manhattan(m, goal, size)
  168.                 costs[m] = new_cost + m.h
  169.                 heapq.heappush(open_nodes, (costs[m], m))
  170.  
  171.     return None
  172.  
  173.  
  174. def main():
  175.     state_list, goal_list = initialize()
  176.  
  177.     start = Node(state_list, None)
  178.     goal = Node(goal_list, None)
  179.  
  180.     print('Start State:\n{}'.format(start))
  181.  
  182.     if not is_solvable(start.val):
  183.         print('Failed!\nThis starting state is not solvable!')
  184.         return
  185.     else:
  186.         print('Initial state is solvable. Calculating...')
  187.  
  188.     size = len(goal.val)
  189.  
  190.     start_timer = default_timer()
  191.     result = a_star(start, goal, size)
  192.     stop_timer = default_timer()
  193.  
  194.     if result == None:
  195.         print('Failed!')
  196.         print("No solution found for this state.")
  197.     else:
  198.         for r in result:
  199.             print('{}\n'.format(r))
  200.         print('{} steps for solution'.format(len(result) - 1))
  201.  
  202.     print('Runtime -> {}'.format(stop_timer - start_timer))
  203.  
  204.  
  205. if __name__ == "__main__":
  206.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement