Advertisement
Guest User

Untitled

a guest
Sep 30th, 2018
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.14 KB | None | 0 0
  1. #!/usr/bin/env python2.7
  2.  
  3. from board import Board
  4.  
  5. import numpy as np
  6. from Queue import PriorityQueue
  7. import sys
  8.  
  9. sys.setrecursionlimit(10000)
  10.  
  11. def solve_A_star(board):
  12.     '''solve_A_star(board) -> list of solution moves
  13.    applies a non recursive variant of the A* algorithm'''
  14.     # setup
  15.     opposite_move = {'UP': 'DOWN', 'DOWN': 'UP',
  16.                      'LEFT': 'RIGHT', 'RIGHT': 'LEFT', None: None}
  17.     depth = 0
  18.     preds = {} # mapping of board configuration to move that leads to previous board
  19.     PQ = PriorityQueue()
  20.     PQ_item = (None, (depth, None, board))
  21.     PQ.put(PQ_item)
  22.  
  23.     # explore boards
  24.     while not PQ.empty():
  25.         # evaluate next board in PQ
  26.         h_plus_depth, (depth, from_move, board) = PQ.get()
  27.         configuration = board.to_tuple_repr()
  28.         if configuration in preds:
  29.             continue
  30.  
  31.         preds[configuration] = opposite_move[from_move]
  32.         if board.is_solved():
  33.             break
  34.  
  35.         # add children of board to PQ
  36.         for from_move, result in board.possible_next_boards():
  37.             new_depth = depth + 1
  38.             h = result.heuristic()
  39.             PQ_item = (h + new_depth, (new_depth, from_move, result))
  40.             PQ.put(PQ_item)
  41.     else:
  42.        # executes if while loop did not break, i.e. PQ is empty -> no solution
  43.        return None
  44.  
  45.     # construct list of moves to backtrack from solved to initial board
  46.     solved_to_initial = []
  47.     move = preds[configuration]
  48.    
  49.     while move is not None:
  50.         solved_to_initial.append(move)
  51.         prev_board = Board.from_tuple_repr(configuration)
  52.         prev_board.apply_move(move)
  53.         configuration = prev_board.to_tuple_repr()
  54.         move = preds[configuration]
  55.  
  56.     # construct solution:
  57.     return [opposite_move[move] for move in reversed(solved_to_initial)]
  58.  
  59. def solve_IDS(board, prints=False):
  60.     '''solve_IDS(board) -> list of solution moves
  61.    applies iterative deepening search by calling solve_DFS iteratively with
  62.    increasing max_depth values; expects solvable board
  63.  
  64.    will find a good solution but can take very long if the
  65.    solution is at a high depth'''
  66.     solution = None
  67.     max_depth = 0
  68.  
  69.     while solution is None:
  70.         if prints:
  71.             print 'max_depth={}'.format(max_depth)
  72.  
  73.         solution = solve_DFS(board, max_depth)
  74.         max_depth += 1
  75.  
  76.     return solution
  77.  
  78. def solve_DFS(board, max_depth=float('inf'), depth=0, seen=None):
  79.     '''solve_DFS(board) -> list of solution moves
  80.    applies DFS, childs are chosen heuristically
  81.  
  82.    tends to find long solutions to relatively simple boards and can take very
  83.    long -> use solve_IDS for shorter solutions
  84.  
  85.    do not touch the default arguments when calling directly, use solve_IDS to
  86.    apply iterative deepening search!'''
  87.     if seen is None:
  88.         seen = set()
  89.  
  90.     # simple case
  91.     if board.is_solved():
  92.         return []
  93.  
  94.     # used to abort when in IDS mode (called via solve_IDS)
  95.     # with max_depth < infinity
  96.     if depth == max_depth:
  97.         return None
  98.  
  99.     # construct copy of seen with the current board added
  100.     seen = seen | {board.to_tuple_repr()}
  101.  
  102.     # put (move, result board) tuples into priority queue
  103.     PQ = PriorityQueue()
  104.  
  105.     for move, result in board.possible_next_boards():
  106.         result_config = result.to_tuple_repr()
  107.         if result_config not in seen:
  108.             h = result.heuristic()
  109.             PQ_item = (h, (move, result))
  110.             PQ.put(PQ_item)
  111.  
  112.     # try moves in order of their position in the PQ
  113.     while not PQ.empty():
  114.         h, (move, result) = PQ.get()
  115.         sub_solution = solve_DFS(result, max_depth, depth + 1, seen)
  116.  
  117.         if sub_solution is not None:
  118.             return [move] + sub_solution
  119.  
  120.     return None
  121.  
  122. # the two hardest boards to play around with (use solve_A_star for these)
  123. hardest1 = Board(np.array([[8, 6, 7], [2, 5, 4], [3, 9, 1]]))
  124. hardest2 = Board(np.array([[6, 4, 7], [8, 5, 9], [3, 2, 1]]))
  125.  
  126. # DEMO SECTION
  127. if __name__ == '__main__':
  128.     strategies = [('solve_IDS', solve_IDS), ('solve_A_star', solve_A_star)]
  129.     TESTS = 20
  130.     boards = [Board.random_solvable_board(num_moves) for num_moves in xrange(TESTS)]
  131.  
  132.     for strategy_name, strategy in strategies:
  133.         print '\n---------- TESTING STRATEGY {} ----------\n'.format(strategy_name)
  134.  
  135.         # generate copy of boards (to later apply the solutions)
  136.         to_solve = [board.copy() for board in boards]
  137.  
  138.         # generate solutions
  139.         solutions = [strategy(board) for board in boards]
  140.  
  141.         # apply solutions
  142.         for solution, board in zip(solutions, to_solve):
  143.             board.apply_moves(solution)
  144.  
  145.         # are all boards solved?
  146.         success = all(board.is_solved() for board in to_solve)
  147.         if success:
  148.             print 'success! all test cases solved!\n'
  149.             solution, board = max(zip(solutions, boards),
  150.                                   key=lambda (solution, board): len(solution))
  151.             print 'longest solution has {} moves:\n{}\n'.format(len(solution), solution)
  152.             print 'and solves the board:\n{}'.format(board)
  153.         else:
  154.             print 'oh no! /o\\'
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement