Пример #1
0
    def test_check_imperfect_solution(self):
        n = 4
        cols = 10
        rows = 5
        dg = DataGenerator()
        some_instance_np_array = np.array(
            [[1, 10, 1], [2, 10, 2], [1, 10, 3], [5, 10, 4], [1, 10, 1]])

        solution_checker = SolutionChecker(n, cols, rows)
        self.assertEqual(
            solution_checker.get_reward(some_instance_np_array),
            (10 * 5) / (cols * rows)
        )
Пример #2
0
    def test_check_imperfect_solution_count_files_2(self):
        n = 4
        cols = 10
        rows = 5
        dg = DataGenerator()
        some_instance_np_array = np.array(
            [[1, 10, 1], [6, 10, 2], [2, 10, 3], [1, 10, 4], [1, 10, 1]])

        solution_checker = SolutionChecker(n, cols, rows)
        self.assertEqual(
            solution_checker.get_reward(some_instance_np_array, count_tiles=True),
            1 / n
        )
Пример #3
0
    def perform_simulation(self, state):
        '''
        Performs the simulation until legal moves are available.
        If simulation ends by finding a solution, a root state starting from this simulation is returned
        '''

        solution_tiles_order = []
        depth = 0
        simulation_root_state = state  # in case simulation ends in solution; these states are the solution
        if len(state.tiles) == 0:
            print('perform_simulation called with empty tiles')
            return ALL_TILES_USED, simulation_root_state, solution_tiles_order
        val = self.val
        while True:
            val += 1
            if len(state.tiles) == 0:
                print('solution found in simulation')
                return ALL_TILES_USED, simulation_root_state, solution_tiles_order
            valid_moves = SolutionChecker.get_valid_next_moves(state, state.tiles, val=val, colorful_states=self.colorful_states)
            if not valid_moves:
                return depth, simulation_root_state, solution_tiles_order

            next_random_tile_index = random.randint(0, len(valid_moves) -1)
            success, new_board = SolutionChecker.get_next_turn(
                state, valid_moves[next_random_tile_index], val, destroy_state=True, 
                colorful_states=self.colorful_states
            )
            self.n_tiles_placed += 1
            solution_tiles_order.append(valid_moves[next_random_tile_index])

            if success == ALL_TILES_USED:
                print('grid is full')
                # no LFB on grid; probably means grid is full
                solution_tiles_order.append(valid_moves[next_random_tile_index])
                return ALL_TILES_USED, simulation_root_state, solution_tiles_order
            elif success == NO_NEXT_POSITION_TILES_UNUSED:
                print('no next position with unused tiles')
                return depth, simulation_root_state, solution_tiles_order
            elif success == TILE_CANNOT_BE_PLACED:
                # cannot place the tile. return depth reached
                return depth, simulation_root_state, solution_tiles_order
            else:
                new_tiles = SolutionChecker.eliminate_pair_tiles(state.tiles, valid_moves[next_random_tile_index])
                new_state = State(board=new_board, tiles=new_tiles, parent=state)

                new_state.score = -1  #  because no choice is performed for sequent actions
                state.children.append(new_state)
                state = new_state
            depth += 1
        return depth, simulation_root_state, solution_tiles_order
Пример #4
0
    def test_check_perfect_solution(self):
        n = 20
        w = 40
        h = 40
        dg = DataGenerator()
        some_instance_visual = dg.gen_instance_visual(n, w, h)
        perfect_bin_configuration = sorted(some_instance_visual, key=lambda x: (x[2][0], x[2][1]))
        some_instance_np_array = dg._transform_instance_visual_to_np_array(some_instance_visual)

        solution_checker = SolutionChecker(n, h, w)
        self.assertEqual(
            solution_checker.get_reward(np.array(perfect_bin_configuration)),
            0
        )
Пример #5
0
    def test_check_imperfect_solution_count_tiles(self):
        n = 4
        cols = 10
        rows = 5
        dg = DataGenerator()
        some_instance_visual = dg.gen_instance_visual(n, cols, rows)
        # NOTE: first bin always repeated
        some_instance_np_array = np.array(
            [[1, 10, 1], [2, 10, 2], [1, 10, 3], [5, 10, 4], [1, 10, 1]])

        solution_checker = SolutionChecker(n, cols, rows)
        self.assertEqual(
            solution_checker.get_reward(some_instance_np_array, count_tiles=True),
            1 / n
        )
Пример #6
0
    def test_get_next_turn_only_success(self):

        success, new_board,  = SolutionChecker.get_next_turn(
            self.state, self.tile, val=1, get_only_success=True, destroy_state=True
        )

        # assert board is destroyed i.e. equal to new_board
        self.assertIsNone(new_board)
Пример #7
0
 def test_get_next_lfb_on_grid_5(self):
     state = np.array([
             [1, 1, 1, 1],
             [1, 1, 1, 1],
             [0, 0, 0, 1]
         ])
     res = SolutionChecker.get_next_lfb_on_grid(state)
     self.assertEqual(res, (2, 0)) 
Пример #8
0
    def get_next_turn(self, state, tile, val=1):
        new_board = np.copy(state.board)
        next_position = SolutionChecker.get_next_lfb_on_grid(new_board)
        # one without the other should not be possible
        if not next_position and len(state.tiles) == 0:
            print('solution found!')
            return ALL_TILES_USED, None
        elif not next_position:
            return NO_NEXT_POSITION_TILES_UNUSED, None

        success, new_board = SolutionChecker.place_element_on_grid_given_grid(
            tile, SolutionChecker.get_next_lfb_on_grid(new_board), val,
            new_board, get_cols(new_board), get_rows(new_board))

        if not success:
            # cannot place the tile. this branch will not be considered
            return TILE_CANNOT_BE_PLACED, None
        return True, new_board
Пример #9
0
    def test_get_possible_tile_actions_given_grid(self):
        grid = np.array([
            [1, 1, 1, 0, 0],
            [1, 1, 1, 0, 0],
            [1, 1, 1, 0, 0],
        ])
        tiles = [[1, 2], [2, 1], [4, 5], [1, 1], [1, 1], [3, 2], [3, 3], [2, 3]]
        possible_tiles_to_place = SolutionChecker.get_possible_tile_actions_given_grid(grid, tiles)

        self.assertEqual(possible_tiles_to_place, [[1, 2], [2, 1], [1, 1], [1, 1], [3, 2]])
Пример #10
0
 def test_get_valid_next_moves_1(self):
     self.board = np.array([
         [1, 1, 1, 1],
         [1, 1, 1, 0],
         [0, 0, 0, 0]
     ])
     self.tiles = [(2, 1), (1, 2)]
     self.state = State(self.board, self.tiles)
     next_moves = SolutionChecker.get_valid_next_moves(self.state, self.tiles)
     self.assertEqual(next_moves, [(2, 1)])
Пример #11
0
    def __init__(self, tiles, board, strategy='max_depth'):

        self.initial_tiles, self.initial_board = tiles, board
        self.state = State(self.initial_board, self.initial_tiles)
        self.solution_checker = SolutionChecker(len(tiles), get_rows(board), get_cols(board))
        self.strategy=strategy
        self.n_tiles_placed = 0
        self.solution_tiles_order = []

        # for MCTS vis purposes
        self.colorful_states = True
Пример #12
0
    def test_get_next_turn_destroy_board(self):

        success, new_board,  = SolutionChecker.get_next_turn(
            self.state, self.tile, val=1, get_only_success=False, destroy_state=True
        )
        self.assertEqual(success, True)

        # assert board is destroyed i.e. equal to new_board
        np.testing.assert_array_equal(
            self.state.board,
            new_board
        )
Пример #13
0
    def test_get_valid_actions_indexed_given_grid(self):

        grid = np.array([
            [1, 1, 1, 0, 0],
            [1, 1, 1, 0, 0],
            [1, 1, 1, 0, 0],
        ])
        tiles = [[1, 2], [2, 1], [0, 0], [4, 5], [1, 1], [1, 1], [3, 2], [3, 3], [2, 3]]
        possible_tiles_indexes = SolutionChecker.get_valid_tile_actions_indexes_given_grid(
            grid, tiles)

        self.assertEqual(possible_tiles_indexes, [1, 1, 0, 0, 1, 1, 1, 0, 0])
Пример #14
0
    def test_get_valid_next_moves_2(self):
        self.board = np.array([
            [1, 1, 1, 1],
            [1, 1, 1, 0],
            [0, 0, 0, 0]
        ])
        tiles_list = [(2, 1), (1, 2), (3, 3), (4, 4), (1, 1)]

        self.tiles = sorted(tiles_list, key=lambda x: (x[1], x[0]))
        self.state = State(self.board, self.tiles)
        next_moves = SolutionChecker.get_valid_next_moves(self.state, self.tiles)
        self.assertEqual(next_moves, [(1, 1), (2, 1)])
Пример #15
0
    def initialize(self, height, width, n_tiles):
        Game.__init__(self)

        self.height = height
        self.width = width
        self.n_tiles = n_tiles

        dg = DataGenerator()
        self.tiles, solution = dg.gen_instance(n_tiles, width, height)
        # print(self.tiles)

        _tiles_ints = SolutionChecker.get_tiles_with_orientation(self.tiles)
        self._base_board = Board(height, width, _tiles_ints, n_tiles)
Пример #16
0
    def __init__(self, tiles, board):
        self.Qsa = {}  # stores Q values for s,a (as defined in the paper)
        self.Nsa = {}  # stores #times edge s,a was visited
        self.Ns = {}  # stores #times board s was visited
        self.Ps = {}  # stores initial policy (returned by neural net)

        self.Es = {}  # stores game.getGameEnded ended for board s
        self.Vs = {}  # stores game.getValidMoves for board s

        self.initial_tiles, self.initial_board = tiles, board
        self.state = State(self.initial_board, self.initial_tiles)
        self.solution_checker = SolutionChecker(len(tiles), get_rows(board),
                                                get_cols(board))
Пример #17
0
    def test_bin_outside_border(self):

        n = 20
        h = 50
        w = 50

        solution_checker = SolutionChecker(n, h, w)
        #
        # 11  -------------
        #     |           |
        #     |           |          |
        #     |           |          |
        #     -----------------------|
        #                40

        solution_checker.LFBs = SortedKeyList([], key=lambda x: (x[1], x[0]))
        solution_checker.LFBs.add((40, 11))

        _bin = (10, 10)
        self.assertFalse(solution_checker.is_bin_outside_borders(_bin))

        _bin = (12, 10)
        self.assertTrue(solution_checker.is_bin_outside_borders(_bin))
Пример #18
0
    def build_reward(self): # reorder input % tour and return tour length (euclidean distance)
        self.permutations = tf.stack(  # this just creates a vectors with repeating idxs so we can gather later
            [
                tf.tile(tf.expand_dims(tf.range(self.batch_size,dtype=tf.int32), 1), [1, self.n+1]),
                self.tour
            ], 2
        )
        if self.is_training==True:
            self.ordered_input_ = tf.gather_nd(self.input_,self.permutations)
        else:
            self.ordered_input_ = tf.gather_nd(tf.tile(self.input_,[self.batch_size,1,1]),self.permutations)

        solution_checker = SolutionChecker(self.n, self.w, self.h)
        sess = tf.Session()
        rewards = tf.py_func(
            solution_checker.get_rewards, [self.ordered_input_, self.count_non_placed_tiles, self.combinatorial_reward], tf.float32)
        
        self.reward = rewards
        tf.summary.scalar('reward_mean', tf.reduce_mean(rewards))
Пример #19
0
def get_only_random_predictions(examples):
    total_random_correct = 0
    with open("tensorboard/random_predictions.csv", 'w') as f:
        for i in range(2755):
            total_count = 0
            total_random_correct = 0
            for example in examples:
                expected = np.argmax(example[2])
                expected_tile = example[1][expected]
                random_prediction = random.randint(
                    0,
                    SolutionChecker.get_n_nonplaced_tiles(example[1]) - 1)
                if np.array_equal(expected_tile,
                                  example[1][random_prediction]):
                    total_random_correct += 1
                total_count += 1

            accuracy = (total_random_correct / total_count) * 100
            f.write(f'{accuracy}\n')
            print(accuracy)
    return
Пример #20
0
    def test_get_next_turn(self):

        success, new_board,  = SolutionChecker.get_next_turn(
            self.state, self.tile, val=1, get_only_success=False, destroy_state=False
        )

        self.assertEqual(success, True)
        np.testing.assert_array_equal(
            new_board,
            np.array([
                [1, 1, 1, 1],
                [1, 1, 1, 1],
                [0, 0, 0, 1]
            ])
        )
        # assert board is not destroyed
        np.testing.assert_array_equal(
            self.state.board,
            np.array([
                [1, 1, 1, 1],
                [1, 1, 1, 0],
                [0, 0, 0, 0]
            ])
        )
Пример #21
0
def main(options):
    #N_TILES = 8
    #HEIGHT = 8
    #WIDTH = 8
    HEIGHT = 25
    WIDTH = 25
    N_TILES = 50
    for (WIDTH, HEIGHT) in [(30, 30)]:
        #for N_TILES in [50]:
        SCALAR_TILES = True
        predict_move_index = True
        g = Game(HEIGHT, WIDTH, N_TILES)

        dg = DataGenerator(WIDTH, HEIGHT)

        # from alpha.binpack.tensorflow.NNet import NNetWrapper as nn
        from alpha.binpack.keras.NNet import NNetWrapper as nn
        nnet = nn(g, scalar_tiles=SCALAR_TILES)

        n_tiles, height, width = N_TILES, HEIGHT, WIDTH

        if options['load_model']:
            nnet.load_checkpoint()
        else:
            # place tiles one by one
            # generate pair x and y where x is stack of state + tiles
            print('Preparing examples')
            N_EXAMPLES = 1000

            examples = get_n_examples(N_EXAMPLES,
                                      width,
                                      height,
                                      n_tiles,
                                      dg,
                                      scalar_tiles=SCALAR_TILES)
            if options['load_examples']:
                with open(
                        f'models/train_examples_{N_TILES}_{HEIGHT}_{WIDTH}.pickle',
                        'rb') as f:
                    train_examples = pickle.load(f)
            else:
                train_examples = get_examples(examples,
                                              N_TILES,
                                              height,
                                              width,
                                              dg,
                                              return_binary_mask=True,
                                              predict_move_index=True,
                                              scalar_tiles=SCALAR_TILES)
                with open(
                        f'models/train_examples_{N_TILES}_{HEIGHT}_{WIDTH}.pickle',
                        'wb') as f:
                    pickle.dump(train_examples, f)

        if options['load_val_examples']:
            with open(
                    f'models/validation_examples_{N_TILES}_{HEIGHT}_{WIDTH}.pickle',
                    'rb') as f:
                validation_examples = pickle.load(f)
        else:
            N_EXAMPLES = 100
            validation_examples = get_n_examples(N_EXAMPLES,
                                                 width,
                                                 height,
                                                 n_tiles,
                                                 dg,
                                                 scalar_tiles=SCALAR_TILES)
            validation_examples = get_examples(validation_examples,
                                               N_TILES,
                                               height,
                                               width,
                                               dg,
                                               from_file=False,
                                               return_binary_mask=True,
                                               predict_move_index=True,
                                               scalar_tiles=SCALAR_TILES,
                                               shuffle_tiles_times=1)
            validation_examples = get_val_examples_not_in_overlap(
                train_examples, validation_examples)
            with open(
                    f'models/validation_examples_{N_TILES}_{HEIGHT}_{WIDTH}.pickle',
                    'wb') as f:
                pickle.dump(validation_examples, f)

        if not options['load_model']:
            print(f'In total: {len(train_examples)} train examples')
            print(f'In total: {len(validation_examples)} validation examples')

        if options['load_model']:
            nnet.load_checkpoint()
        else:
            nnet.train(train_examples, validation_examples)
            nnet.save_checkpoint()
        np.set_printoptions(
            formatter={'float': lambda x: "{0:0.2f}".format(x)}, linewidth=115)

        total_correct = 0
        total_random_correct = 0
        total_max_col_correct = 0
        total_max_row_correct = 0
        total_biggest_tile_correct = 0
        total_smallest_tile_correct = 0
        total_most_common_tile_correct = 0
        total_count = 0

        n_empty_tiles_with_fails = [0] * (N_TILES + 1)
        if False:
            # overlap was 39/1868 between val and train
            get_overlap_between_examples(train_examples, validation_examples)
            return

        if False:
            get_only_random_predictions(validation_examples)
            return

        for example in validation_examples:
            prediction = nnet.predict([example[0], example[1]])
            random_prediction = random.randint(
                0,
                SolutionChecker.get_n_nonplaced_tiles(example[1]) - 1)
            output_str = ''
            if VISUALIZE_PREDICTIONS:
                output_str += f'----------------------------------------------------------'
                output_str += '\n'
            if predict_move_index:
                _prediction = prediction
                if VISUALIZE_PREDICTIONS:
                    output_str += f'{prediction}\n'
                max_index = np.argmax(prediction)
                _prediction_index = max_index
                if SCALAR_TILES:
                    expected = np.argmax(example[2])
                else:
                    expected = np.argmax(example[1])

                # if not scalar_tiles:
                # print('grid state')
                # print(example[0][:, :, 0])
                # print(state_to_tiles_dims(example[0], dg))
                # print('expected')
                if SCALAR_TILES:
                    expected_tile = example[1][expected]
                    prediction_tile = example[1][_prediction_index]
                    if VISUALIZE_PREDICTIONS:
                        output_str += f'{example[1].tolist()}\n'
                else:
                    expected_tile = dg.get_matrix_tile_dims(
                        example[0][:, :, expected + 1])
                    prediction_tile = dg.get_matrix_tile_dims(
                        example[0][:, :, _prediction_index + 1])
                # print(expected, expected_tile)
                #print('prediction')
                # print(_prediction)
                #print(_prediction_index, prediction_tile)
                if VISUALIZE_PREDICTIONS:
                    output_str += f'{example[0]}\n'
                    output_str += f'expected: {expected_tile}, got: {prediction_tile}'
                    output_str += f'random: {example[1][random_prediction]}'
                if SCALAR_TILES:
                    widest_tile = example[1][0]
                    highest_tile = example[1][0]
                    biggest_tile = example[1][0]
                    smallest_tile = example[1][0]
                    counter = Counter()
                    for i, tile in enumerate(example[1]):
                        if tile[1] > widest_tile[1]:
                            widest_tile = tile
                        elif tile[1] == widest_tile[1]:
                            if tile[0] > widest_tile[0]:
                                widest_tile = tile

                        if tile[0] > highest_tile[0]:
                            highest_tile = tile
                        elif tile[0] == highest_tile[0]:
                            if tile[1] > highest_tile[1]:
                                highest_tile = tile

                        if tile[1] * tile[0] > (biggest_tile[1] *
                                                biggest_tile[0]):
                            biggest_tile = tile

                        if tile[1] * tile[0] < (smallest_tile[1] *
                                                smallest_tile[0]):
                            smallest_tile = tile

                        counter[tuple(tile.tolist())] += 1

                    if np.array_equal(expected_tile, widest_tile):
                        total_max_col_correct += 1

                    if np.array_equal(expected_tile, highest_tile):
                        total_max_row_correct += 1

                    if np.array_equal(expected_tile, biggest_tile):
                        total_biggest_tile_correct += 1

                    if np.array_equal(expected_tile, smallest_tile):
                        total_smallest_tile_correct += 1

                    most_common_tile = np.array(counter.most_common(1)[0][0])
                    if np.array_equal(most_common_tile, np.array([0, 0])):
                        most_common_tile = np.array(
                            counter.most_common(2)[1][0])

                    if np.array_equal(expected_tile, most_common_tile):
                        total_most_common_tile_correct += 1

                    if VISUALIZE_PREDICTIONS:
                        output_str += f'max_tile: {widest_tile}\n'

                    if np.array_equal(expected_tile, prediction_tile):
                        total_correct += 1
                        # visualize predictions
                        #if not np.array_equal(expected_tile, widest_tile) and VISUALIZE_PREDICTIONS:
                        #   print(output_str)
                        if VISUALIZE_PREDICTIONS:
                            print(output_str)
                    else:
                        n_empty_tiles_with_fails[count_n_of_non_placed_tiles(
                            example[1]) // 2] += 1
                    # print(example[1][random_prediction])
                    if np.array_equal(expected_tile,
                                      example[1][random_prediction]):
                        total_random_correct += 1
                else:
                    if expected_tile == prediction_tile:
                        total_correct += 1

                    else:
                        n_empty_tiles_with_fails[count_n_of_non_placed_tiles(
                            state_to_tiles_dims(example[0], dg)) // 2] += 1
                total_count += 1
            else:
                _prediction = np.reshape(prediction, (width, height))
                _prediction = get_prediction_masked(_prediction,
                                                    example[0][:, :, 0])
                expected = np.reshape(example[1], (width, height))

                if VISUALIZE_PREDICTIONS:
                    # visualize predictions
                    # print('-' * 50)
                    # print('grid state')
                    # print(example[0][:, :, 0])
                    # print('expected')
                    # print(expected)
                    # print('prediction')
                    # print(_prediction)
                    pass

        if predict_move_index:
            with open(f"nn_results/custom_{N_TILES}_{width}_{height}.csv",
                      'w') as f:
                output_str = (
                    f'{width}-{height}\n'
                    f'In total guessed;{100*(total_correct/ total_count)}; {total_correct}/{total_count}\n'
                    f'Random baseline; {100*(total_random_correct/total_count)}\n'
                    f'Max col tile baseline; {100*(total_max_col_correct/total_count)}\n'
                    f'Max row tile baseline; {100*(total_max_row_correct/total_count)}\n'
                    f'Most common tile baseline; {100*(total_most_common_tile_correct/total_count)}\n'
                    f'Max area tile baseline; {100*(total_biggest_tile_correct/total_count)}\n'
                    f'Min area tile baseline; {100*(total_smallest_tile_correct/total_count)}'
                )
                f.write(output_str)

            print(output_str)
            print(n_empty_tiles_with_fails)

            print('-' * 100)

        if not PREDICT_FULL_EXAMPLES:
            # return
            continue
        tiles_left = []
        for example in examples:
            if SCALAR_TILES:
                state, tiles, _ = example
                tiles = get_tiles_with_orientation(tiles.tolist())
            else:
                tiles, _ = example
            # tiles = dg.get_matrix_tile_dims(tiles)
            grid = np.zeros((width, height))
            tiles_left.append(
                play_using_prediction(nnet,
                                      width,
                                      height,
                                      tiles,
                                      grid,
                                      N_TILES,
                                      dg,
                                      predict_move_index,
                                      scalar_tiles=SCALAR_TILES))
            # [0, 6, 4, 2, 2, 2, 0, 4, 4, 8, 6, 2, 2, 6, 6, 8, 6, 4, 4, 4]
        print(tiles_left)
        print(np.sum(tiles_left) / len(tiles_left))
Пример #22
0
def play_using_prediction(nnet,
                          width,
                          height,
                          tiles,
                          grid,
                          n_tiles,
                          dg,
                          predict_move_index=False,
                          verbose=False,
                          scalar_tiles=False):
    if scalar_tiles:
        tiles = tiles
    else:
        tiles = state_to_tiles_dims(tiles, dg)
    while True:
        tiles_left = len(tiles)
        if tiles_left == 0:
            print(
                f"Success: game ended with {tiles_left / ORIENTATIONS} tiles left unplaced."
            )
            return 0

        _tiles_ints = SolutionChecker.get_possible_tile_actions_given_grid(
            grid, tiles)
        if len(_tiles_ints) == 0 and tiles_left:
            print(
                f"game ended with {tiles_left / ORIENTATIONS} tiles left unplaced."
            )
            return tiles_left / ORIENTATIONS
        np.random.shuffle(_tiles_ints)
        if scalar_tiles:
            _tiles = tiles_to_np_array(
                SolutionChecker.pad_tiles_with_zero_scalars(
                    _tiles_ints, ORIENTATIONS * n_tiles - len(_tiles_ints)))
            # state = state.squeeze()

            prediction = nnet.predict([grid, tiles_to_np_array(_tiles)])
        else:
            tiles_in_matrix_shape = dg._transform_instance_to_matrix(
                _tiles_ints, only_one_orientation=True)
            tiles_in_matrix_shape = pad_tiles_with_zero_matrices(
                tiles_in_matrix_shape,
                n_tiles * ORIENTATIONS - tiles_in_matrix_shape.shape[2], width,
                height)

            state = np.dstack((np.expand_dims(grid,
                                              axis=2), tiles_in_matrix_shape))
            prediction = nnet.predict(state)

        if not predict_move_index:
            if len(prediction) == 2:  # if we are also predicting v
                prediction, v = prediction

            prediction = np.reshape(prediction, (width, height))

            # get the  probability matrix
            prediction = get_prediction_masked(prediction, state[:, :, 0])

        if verbose:
            print('-' * 50)
            print(grid, prediction)
            print(tiles)
        if scalar_tiles:
            _ttiles = tiles
        else:
            _ttiles = state_to_tiles_dims(state, dg)
        solution_tile = get_best_tile_by_prediction(
            grid,
            _ttiles,
            prediction,
            dg,
            predict_move_index=predict_move_index)
        if verbose:
            print(solution_tile)
        if solution_tile is None:
            print(
                f"game ended with {tiles_left / ORIENTATIONS} tiles left unplaced."
            )
            return tiles_left / ORIENTATIONS

        success, grid = SolutionChecker.place_element_on_grid_given_grid(
            solution_tile[0],
            solution_tile[1],
            val=1,
            grid=grid,
            cols=width,
            rows=height)

        if not success:
            print(
                f"game ended with {tiles_left / ORIENTATIONS} tiles left unplaced."
            )
            return tiles_left / ORIENTATIONS

        if scalar_tiles:
            tiles = [tuple(x) for x in tiles]
        tiles = SolutionChecker.eliminate_pair_tiles(tiles, solution_tile[0])
    return 0
Пример #23
0
def get_best_tile_by_prediction(grid,
                                tiles,
                                prediction,
                                dg,
                                predict_move_index=True):
    '''
    1. mask invalid moves
    2. renormalize the probability distribution
    3. for each tile sum up which would be the probability of placing that tile in LFB
    4. return the new grid 

    Returns the tile which is the best in format [(rows, cols), position_to_place]
    '''
    next_lfb = SolutionChecker.get_next_lfb_on_grid(grid)
    max_probability = -math.inf
    max_index = 0
    best_tile = None
    rows, cols = grid.shape

    tile_probabilities = defaultdict(int)
    tile_counts = defaultdict(int)
    tiles_to_iterate_on = tiles

    SOFTMAX = False
    best_tile_individual = None
    best_prediction = 0

    for i, tile in enumerate(tiles_to_iterate_on):
        tile = tuple(tile)
        success, _ = SolutionChecker.place_element_on_grid_given_grid(
            tile,
            next_lfb,
            val=1,
            grid=grid,
            cols=cols,
            rows=rows,
            get_only_success=True)
        if not success:
            continue

        if predict_move_index and SOFTMAX:
            '''
            The best tile is predicted by taking the sum of the tiles
            with the same (width, height)
            '''
            if tuple(tile) == (0, 0):
                continue
            tile_probabilities[tile] += prediction[i]
            tile_counts[tile] += 1
        elif predict_move_index:
            if tuple(tile) == (0, 0):
                continue
            if prediction[i] > best_prediction:
                best_tile_individual = tile
                best_prediction = prediction[i]

            # if tile[0] * tile[1] > best_prediction:
            #     best_tile_individual = tile
            #     best_prediction = tile[0] * tile[1]
        else:
            probability = np.sum(prediction[next_lfb[0]:next_lfb[0] + tile[0],
                                            next_lfb[1]:next_lfb[1] + tile[1]])

            # scale with area
            # probability = probability / (tile[0] * tile[1])

            if probability > max_probability:
                max_index = i
                max_probability = probability
                best_tile = [tile, next_lfb]

    if predict_move_index and SOFTMAX:
        max_tile = None
        max_val = -math.inf
        for k in tile_probabilities.keys():
            v = tile_probabilities[k] / tile_counts[k]
            if True:
                if v > max_val:
                    max_tile = k
                    max_val = v
            else:
                if k[0] * k[1] > max_val:
                    max_tile = k
                    max_val = k[0] * k[1]
        if max_tile:
            best_tile = [max_tile, next_lfb]
    elif predict_move_index:
        best_tile = [best_tile_individual, next_lfb]

    # print(tile_probabilities)
    # print(tile_counts)
    if not best_tile:
        print('No valid tile placement found')
    return best_tile
Пример #24
0
    def predict(self, temp=1, N=3000):
        initial_state = self.state
        state = self.state
        available_tiles = state.tiles
        prev_state = state
        solution_found = False

        depth = 0
        self.val = 1
        while len(state.tiles):
            tile_placed = False
            states = []
            print(len(state.tiles))
            best_score = 0
            for i, tile in enumerate(state.tiles):
                success, new_board = SolutionChecker.get_next_turn(state, tile, self.val, destroy_state=False)
                self.n_tiles_placed += 1

                if success == ALL_TILES_USED:
                    print('solution found!')
                    solution_found = True
                    return initial_state, depth, solution_found
                if success == TILE_CANNOT_BE_PLACED:
                    # cannot place the tile.  this branch will not be considered
                    states.append(None)
                    continue
                else:
                    tile_placed = True
                    new_tiles = SolutionChecker.eliminate_pair_tiles(state.tiles, tile)
                    new_state = State(
                        board=new_board, tiles=new_tiles, parent=state)
                    state.children.append(new_state)
                    simulation_result, solution_tiles_order = self.perform_simulations(new_state, N=N, record_simulations=False)
                    if simulation_result == ALL_TILES_USED:
                        print('solution found in simulation!')
                        print(tile)
                        solution_found = True

                        # update scores of states found in simulation
                        new_state.score = len(state.tiles) / ORIENTATIONS - 1
                        _state = new_state.children[0]
                        while _state.children:
                            _state.score = (len(_state.tiles) / ORIENTATIONS) - 1
                            _state = _state.children[0]

                        if state.tile_placed:
                            self.solution_tiles_order.extend([state.tile_placed] + [tile] + solution_tiles_order)
                        else:
                            self.solution_tiles_order.extend([tile] + solution_tiles_order)
                        return initial_state, depth, solution_found
                    new_state.score = simulation_result
                    if new_state.score > best_score:
                        best_tile = tile
                        best_score = new_state.score
                    new_state.tile_placed = tile
                    state.solution_tiles_order.append(tile)
                    states.append(new_state)
            if not tile_placed:
                # no tile was placed, it's a dead end; end game
                return initial_state, depth, solution_found

            # PERFORMANCE:
            # for visualization this can be changed
            # all tiles will be 1 inside the frame for performance reasons
            self.val += 1

            depth += 1
            best_action = get_max_index(states) 
            prev_state = state
            new_state = states[best_action]
            print(best_tile, prev_state.tile_placed)
            if prev_state.tile_placed:
                self.solution_tiles_order.append(prev_state.tile_placed)


            state = new_state

        print('Solution found!')
        solution_found = True
        return initial_state, depth, solution_found
Пример #25
0
    def test_eliminate_pair_tiles_3(self):
        tiles_list = [(1, 1), (2, 1), (1, 1), (1, 1), (2, 1), (1, 1)]

        new_tiles = SolutionChecker.eliminate_pair_tiles(tiles_list, tile_to_remove=(1, 1))
        self.assertEqual(new_tiles, [(2, 1), (1, 1), (2, 1), (1, 1)])
Пример #26
0
    def test_eliminate_pair_tiles_when_pair_is_not_present(self):
        tiles_list = [(1, 8), (2, 1), (1, 1), (1, 1), (2, 1), (1, 1)]

        with self.assertRaises(ValueError):
            SolutionChecker.eliminate_pair_tiles(tiles_list, tile_to_remove=(1, 8))
Пример #27
0
    def test_pad(self):
        tiles = [[1, 2], [2, 1], [4, 5]]
        padded_tiles = SolutionChecker.pad_tiles_with_zero_scalars(tiles, 2)

        self.assertEqual(len(padded_tiles), 5)
        self.assertEqual([[1, 2], [2, 1], [4, 5], [0, 0], [0, 0]], padded_tiles)
Пример #28
0
    for i in tqdm(range(10)): # test instance
        seed_ = 1+random.randint(0, 10000)
        dg =  DataGenerator() # Create Data Generator
        input_batch = dg.train_batch(
            1, actor.n, actor.w, actor.h, actor.dimension,
            seed=i,
            freeze_first_batch=config.freeze_first_batch
        )
        feed = {actor.input_: input_batch} # Get feed dict
        tour, reward = sess.run([actor.tour, actor.reward], feed_dict=feed) # sample tours

        j = np.argmin(reward) # find best solution
        best_permutation = tour[j][:-1]
        predictions_length.append(reward[j])

        solution_checker = SolutionChecker(actor.n, actor.w, actor.h)
        # TODO: find how this is called in numpy (sort by index)
        bins = []
        for el in best_permutation:
            bins.append(input_batch[0][el])

        solution_checker.get_reward(bins)
        grid = solution_checker.grid
        print('reward',reward[j])
        solution_checker.visualize_grid()

        #dataset.visualize_2D_trip(input_batch[0][best_permutation])
        #dataset.visualize_sampling(tour)
        
        # dataset.visualize_2D_trip(opt_tour)
        
Пример #29
0
def get_examples(given_examples,
                 n_tiles,
                 height,
                 width,
                 dg,
                 from_file=False,
                 return_binary_mask=False,
                 predict_v=False,
                 predict_move_index=True,
                 scalar_tiles=False,
                 shuffle_tiles_times=20):
    examples = []
    for i, _example in enumerate(given_examples):
        # print(f'{i}/{len(given_examples)}')
        if scalar_tiles:
            state, tiles, solution = _example
            state = state.squeeze()
        else:
            state, solution = _example
        grid = np.zeros([height, width])
        for solution_index, solution_tile in enumerate(solution):
            solution_copy = np.copy(solution)
            solution_order = np.array(solution_copy[solution_index:])
            solution_tile_dims = solution_tile[:2]
            orig_solution_order = solution_order

            for i in range(shuffle_tiles_times):  # tile permutations
                solution_order = np.copy(orig_solution_order)
                _tiles_ints = [x[:ORIENTATIONS] for x in solution_order]
                _tiles_ints = get_tiles_with_orientation(_tiles_ints)
                _tiles_ints = SolutionChecker.get_possible_tile_actions_given_grid(
                    grid, _tiles_ints)
                np.random.shuffle(_tiles_ints)
                if scalar_tiles:
                    tiles = tiles_to_np_array(
                        SolutionChecker.pad_tiles_with_zero_scalars(
                            _tiles_ints,
                            ORIENTATIONS * n_tiles - len(_tiles_ints)))
                else:
                    tiles = dg._transform_instance_to_matrix(
                        _tiles_ints, only_one_orientation=True)
                    tiles = pad_tiles_with_zero_matrices(
                        tiles, ORIENTATIONS * n_tiles - tiles.shape[2], width,
                        height)
                    state = np.dstack((np.expand_dims(grid, axis=2), tiles))
                pi = solution_to_solution_matrix(
                    solution_tile,
                    cols=width,
                    rows=height,
                    return_binary_mask=False).flatten()

                # v = N_TILES - solution_index
                v = 1
                if solution_index == len(solution) - 1:
                    continue

                if predict_move_index:
                    n_possible_tiles = SolutionChecker.get_n_nonplaced_tiles(
                        _tiles_ints)
                    if n_possible_tiles == 1:  # if only one action-tile placement is possible
                        pass
                    else:
                        _tiles_ints = SolutionChecker.np_array_to_tiles(
                            _tiles_ints)
                        solution_index = _tiles_ints.index(solution_tile_dims)
                        if scalar_tiles:
                            if INDIVIDUAL_TILES:
                                split_tiles = np.array(tiles)
                                split_tiles = np.split(split_tiles,
                                                       split_tiles.shape[0])
                            else:
                                split_tiles = tiles
                            example = [
                                grid.copy(), split_tiles,
                                one_hot_encode(_tiles_ints, solution_tile_dims,
                                               len(tiles))
                            ]
                        else:
                            example = [
                                state,
                                one_hot_encode(_tiles_ints, solution_tile_dims,
                                               state.shape[2] - 1)
                            ]
                        examples.append(example)
                        # print(_tiles_ints, solution_tile_dims, one_hot_encode(_tiles_ints, solution_tile_dims, state))
                else:
                    example = [state, pi]
                    if predict_v:
                        example.append(v)

                    examples.append(example)

            success, grid = SolutionChecker.place_element_on_grid_given_grid(
                solution_tile[:ORIENTATIONS],
                solution_tile[2],
                val=1,
                grid=grid,
                cols=width,
                rows=height)

    return examples
Пример #30
0
 def test_get_next_lfb_on_grid_3(self):
     state = np.array([[1, 1, 1], [1, 1, 1]])
     res = SolutionChecker.get_next_lfb_on_grid(state)
     self.assertIsNone(res)