Пример #1
0
def test_greedy_dfs(weights):
    def compare(original, final, moves, row, column, assert_error_message):
        for delta_r, delta_c in moves:
            original.swap(row, column, row + delta_r, column + delta_c)
            row += delta_r
            column += delta_c

        for r in range(original.rows):
            for c in range(original.columns):
                assert isinstance(original.cell(r, c),
                                  type(final.cell(r, c))), assert_error_message

    # solution should contain move list that gets you to the final board state starting from original board state
    original = Board.create_randomized_board(5, 6)
    _, moves, final_board = GreedyDfs(weights).solve(original, 20)
    compare(original, final_board, moves[1:], moves[0][0], moves[0][1],
            "Greedy DFS yielded an incorrect 4-way move list!")

    # same with diagonals enabled
    original = Board.create_randomized_board(5, 6)
    h = GreedyDfs(weights)
    h.diagonals = True
    _, moves, final_board = h.solve(original, 20)
    compare(original, final_board, moves[1:], moves[0][0], moves[0][1],
            "Greedy DFS yielded an incorrect 8-way move list!")
Пример #2
0
def test_cell_swap(board_with_1_chain):
    # swapping a board's cell with another should only affect the source and target cells
    original = board_with_1_chain
    swapped_board = Board.copy_board(original)
    # swap corners where the two pieces are different
    swapped_board.swap(0, 0, 4, 5)

    matching = [
        swapped_board.cell(r, c)
        for c in range(original.columns) for r in range(original.rows)
        if isinstance(original.cell(r, c), type(swapped_board.cell(r, c))) and original.cell(r, c).location == swapped_board.cell(r, c).location
    ]
    assert len(matching) == 28, "Swapping upper left corner with lower right corner of board yielded match counts!"
    assert swapped_board.cell(0, 0).location == (0, 0), "Swapped piece @ 0,0 has invalid location!"
    assert swapped_board.cell(4, 5).location == (4, 5), "Swapped piece @ 4,5 has invalid location!"
    assert isinstance(swapped_board.cell(0, 0), type(original.cell(4, 5))), "Swapped piece @ 0,0 does not match original piece @ 4,5!"
    assert isinstance(swapped_board.cell(4, 5), type(original.cell(0, 0))), "Swapped piece @ 4,5 does not match original piece @ 0,0!"

    # swap multiple times should yield expected results
    original = Board.create_randomized_board(5, 6)
    swapped_board = Board.copy_board(original)
    swapped_board.swap(0, 0, 1, 1)
    swapped_board.swap(1, 1, 2, 2)
    swapped_board.swap(2, 2, 3, 3)
    swapped_board.swap(3, 3, 4, 4)
    assert isinstance(swapped_board.cell(0, 0), type(original.cell(1, 1))), "Swapped piece @ 0,0 does not match original @ 1,1"
    assert isinstance(swapped_board.cell(1, 1), type(original.cell(2, 2))), "Swapped piece @ 1,1 does not match original @ 2,2"
    assert isinstance(swapped_board.cell(2, 2), type(original.cell(3, 3))), "Swapped piece @ 2,2 does not match original @ 3,3"
    assert isinstance(swapped_board.cell(3, 3), type(original.cell(4, 4))), "Swapped piece @ 3,3 does not match original @ 4,4"
    assert isinstance(swapped_board.cell(4, 4), type(original.cell(0, 0))), "Swapped piece @ 4,4 does not match original @ 0,0"
Пример #3
0
    def run(rows, columns, depth, weights):
        def update_board_with_matches(board, matches):
            for piece, clusters in matches:
                for r, c in clusters:
                    board.update(r, c, type(piece))

        b = Board.create_randomized_board(5, 6)
        # b = Board([Fire,  Wood,  Water, Dark,  Light, Light,
        #           Water, Fire, Water, Light, Heart, Light,
        #           Fire,  Water, Dark,  Heart, Heart, Wood,
        #           Light, Water, Light, Fire,  Wood,  Wood,
        #           Dark,  Heart, Dark,  Light, Heart, Light], 5, 6)

        m = Board.create_empty_board(rows, columns)
        update_board_with_matches(m, b.get_matches())

        h = GreedyDfs(weights) if False else PrunedBfs(weights)
        h.diagonals = True
        start = time.time()
        moves = h.solve(b, depth)
        performance = time.time() - start

        print('---------------------------------------------')
        print(b)
        print(m)
        print('run time : ' + str(performance))
        print('best move score : ' + str(moves[0]))
        print('start : ' + str(moves[1][0]))
        print('moves : ' + str(moves[1][1:]))
        print(moves[2])

        m = Board.create_empty_board(rows, columns)
        update_board_with_matches(m, moves[2].get_matches())

        print(m)
Пример #4
0
def test_cell_update():
    # updating a board's cell should update that cell only
    original = Board.create_randomized_board(5, 6)
    updated_board = Board.copy_board(original).update(3, 4, Jammer)
    matching = [
        updated_board.cell(r, c)
        for c in range(original.columns) for r in range(original.rows)
        if isinstance(original.cell(r, c), type(updated_board.cell(r, c))) and original.cell(r, c).location == updated_board.cell(r, c).location
    ]
    assert len(matching) == 29, "Updating board did not yield expected matching cells with original board!"
    assert isinstance(updated_board.cell(3, 4), Jammer), "Piece @ 3,4 was not updated to correct piece!"
Пример #5
0
def test_copy_board():
    # copying a board produces another board with same setup as original
    original = Board.create_randomized_board(5, 6)
    copy = Board.copy_board(original)

    assert original.rows == copy.rows, "Copied board's rows do not match original!"
    assert original.columns == copy.columns, "Copied board's columns do not match original!"
    matching = [copy.cell(r, c)
                for c in range(original.columns) for r in range(original.rows)
                if isinstance(original.cell(r, c), type(copy.cell(r, c))) and original.cell(r, c).location == copy.cell(r, c).location]
    assert len(matching) == 30, "Copied board's board does not match original!"
Пример #6
0
def test_copy_board():
    # copying a board produces another board with same setup as original
    original = Board.create_randomized_board(5, 6)
    copy = Board.copy_board(original)

    assert original.rows == copy.rows, "Copied board's rows do not match original!"
    assert original.columns == copy.columns, "Copied board's columns do not match original!"
    matching = [
        copy.cell(r, c) for c in range(original.columns)
        for r in range(original.rows)
        if isinstance(original.cell(r, c), type(copy.cell(r, c)))
        and original.cell(r, c).location == copy.cell(r, c).location
    ]
    assert len(matching) == 30, "Copied board's board does not match original!"
Пример #7
0
def test_board_setup():
    # as long as length of piece list is equal to row x column, the board yields no error and loads from top left down to bottom right
    b = Board([Fire, Water, Wood, Dark, Light, Heart], 2, 3)
    assert isinstance(b, Board), "Board valid 2x3, but was not instantiated!"
    assert isinstance(b.cell(0, 0), Fire), "Unexpected piece @ 0,0 on 2x3 Board!"
    assert isinstance(b.cell(0, 1), Water), "Unexpected piece @ 0,1 on 2x3 Board!"
    assert isinstance(b.cell(0, 2), Wood), "Unexpected piece @ 0,2 on 2x3 Board!"
    assert isinstance(b.cell(1, 0), Dark), "Unexpected piece @ 1,0 on 2x3 Board!"
    assert isinstance(b.cell(1, 1), Light), "Unexpected piece @ 1,1 on 2x3 Board!"
    assert isinstance(b.cell(1, 2), Heart), "Unexpected piece @ 1,2 on 2x3 Board!"
    assert b.rows == 2, "2x3 board has incorrect rows property!"
    assert b.columns == 3, "2x3 board has incorrect columns property!"
    assert len(b.board) == 2 and len(b.board[0]) == 3, "2x3 board has incorrect board dimensions!"

    b = Board([Fire, Water, Wood, Dark, Light, Heart], 3, 2)
    assert isinstance(b, Board), "Board valid 3x2, but was not instantiated!"
    assert isinstance(b.cell(0, 0), Fire), "Unexpected piece @ 0,0 on 3x2 Board!"
    assert isinstance(b.cell(0, 1), Water), "Unexpected piece @ 0,1 on 3x2 Board!"
    assert isinstance(b.cell(1, 0), Wood), "Unexpected piece @ 1,0 on 3x2 Board!"
    assert isinstance(b.cell(1, 1), Dark), "Unexpected piece @ 1,1 on 3x2 Board!"
    assert isinstance(b.cell(2, 0), Light), "Unexpected piece @ 2,0 on 3x2 Board!"
    assert isinstance(b.cell(2, 1), Heart), "Unexpected piece @ 2,1 on 3x2 Board!"
    assert b.rows == 3, "3x2 board has incorrect rows property!"
    assert b.columns == 2, "3x2 board has incorrect columns property!"
    assert len(b.board) == 3 and len(b.board[0]) == 2, "3x2 board has incorrect board dimensions!"
Пример #8
0
def test_cell_update():
    # updating a board's cell should update that cell only
    original = Board.create_randomized_board(5, 6)
    updated_board = Board.copy_board(original).update(3, 4, Jammer)
    matching = [
        updated_board.cell(r, c) for c in range(original.columns)
        for r in range(original.rows)
        if isinstance(original.cell(r, c), type(updated_board.cell(r, c)))
        and original.cell(r, c).location == updated_board.cell(r, c).location
    ]
    assert len(
        matching
    ) == 29, "Updating board did not yield expected matching cells with original board!"
    assert isinstance(updated_board.cell(3, 4),
                      Jammer), "Piece @ 3,4 was not updated to correct piece!"
Пример #9
0
def board():
    return Board([
        Fire, Unknown, Unknown, Unknown, Dark, Dark, Fire, Water, Unknown,
        Heart, Unknown, Dark, Fire, Water, Heart, Heart, Unknown, Unknown,
        Unknown, Water, Unknown, Unknown, Unknown, Unknown, Unknown, Water,
        Unknown, Light, Light, Light
    ], 5, 6)
Пример #10
0
def board_with_0_chain():
    return Board([
        Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown,
        Fire, Unknown, Unknown, Unknown, Unknown, Fire, Unknown, Unknown,
        Unknown, Unknown, Unknown, Fire, Fire, Unknown, Unknown, Unknown,
        Unknown, Unknown, Unknown, Unknown, Unknown, Unknown
    ], 5, 6)
Пример #11
0
def test_empty_board():
    # empty board should contain only Unknown pieces
    b = Board.create_empty_board(5, 6)
    unknown_pieces = [
        b.cell(r, c) for c in range(b.columns) for r in range(b.rows)
        if isinstance(b.cell(r, c), Unknown)
    ]
    assert len(
        unknown_pieces
    ) == 30, "Creating empty board does not contain only Unknown pieces!"
Пример #12
0
def test_randomized_board():
    # randomized board should contain only Fire, Water, Wood, Dark, Light, and Heart pieces
    allowed_pieces = set([Fire, Water, Wood, Dark, Light, Heart])
    b = Board.create_randomized_board(5, 6)
    pieces = [
        b.cell(r, c) for c in range(b.columns) for r in range(b.rows)
        if isinstance(b.cell(r, c), tuple(allowed_pieces))
    ]
    assert len(
        pieces) == 30, "Creating randomized board contains invalid pieces!"
Пример #13
0
def test_cell_swap(board_with_1_chain):
    # swapping a board's cell with another should only affect the source and target cells
    original = board_with_1_chain
    swapped_board = Board.copy_board(original)
    # swap corners where the two pieces are different
    swapped_board.swap(0, 0, 4, 5)

    matching = [
        swapped_board.cell(r, c) for c in range(original.columns)
        for r in range(original.rows)
        if isinstance(original.cell(r, c), type(swapped_board.cell(r, c)))
        and original.cell(r, c).location == swapped_board.cell(r, c).location
    ]
    assert len(
        matching
    ) == 28, "Swapping upper left corner with lower right corner of board yielded match counts!"
    assert swapped_board.cell(
        0, 0).location == (0, 0), "Swapped piece @ 0,0 has invalid location!"
    assert swapped_board.cell(
        4, 5).location == (4, 5), "Swapped piece @ 4,5 has invalid location!"
    assert isinstance(swapped_board.cell(0, 0), type(original.cell(
        4, 5))), "Swapped piece @ 0,0 does not match original piece @ 4,5!"
    assert isinstance(swapped_board.cell(4, 5), type(original.cell(
        0, 0))), "Swapped piece @ 4,5 does not match original piece @ 0,0!"

    # swap multiple times should yield expected results
    original = Board.create_randomized_board(5, 6)
    swapped_board = Board.copy_board(original)
    swapped_board.swap(0, 0, 1, 1)
    swapped_board.swap(1, 1, 2, 2)
    swapped_board.swap(2, 2, 3, 3)
    swapped_board.swap(3, 3, 4, 4)
    assert isinstance(swapped_board.cell(0, 0), type(original.cell(
        1, 1))), "Swapped piece @ 0,0 does not match original @ 1,1"
    assert isinstance(swapped_board.cell(1, 1), type(original.cell(
        2, 2))), "Swapped piece @ 1,1 does not match original @ 2,2"
    assert isinstance(swapped_board.cell(2, 2), type(original.cell(
        3, 3))), "Swapped piece @ 2,2 does not match original @ 3,3"
    assert isinstance(swapped_board.cell(3, 3), type(original.cell(
        4, 4))), "Swapped piece @ 3,3 does not match original @ 4,4"
    assert isinstance(swapped_board.cell(4, 4), type(original.cell(
        0, 0))), "Swapped piece @ 4,4 does not match original @ 0,0"
Пример #14
0
def test_invalid_board():
    # length of list must be equal to row x column for the board to be valid
    with pytest.raises(Exception) as exec_info:
        Board([Fire, Water, Wood, Dark, Light, Heart, Poison, Jammer, Unknown],
              10, 10)
    assert 'Given pieces do not fit specified board dimensions!' in str(exec_info.value), \
        "Board's pieces list was smaller than dimensions, but did not fail initialization!"

    with pytest.raises(Exception) as exec_info:
        Board([Fire, Water, Wood, Dark, Light, Heart, Poison, Jammer, Unknown],
              2, 2)
    assert 'Given pieces do not fit specified board dimensions!' in str(exec_info.value), \
        "Board's pieces list was bigger than dimensions, but did not fail initialization!"

    with pytest.raises(Exception) as exec_info:
        Board([Fire, Water, Wood, Dark, Light, Heart, Poison, Jammer, Unknown],
              0, 3)
    assert 'Given pieces do not fit specified board dimensions!' in str(
        exec_info.value
    ), "Board's row was invalid, but did not fail initialization!"
Пример #15
0
    def _step(self, solutions, depth):
        if depth == 0:
            return solutions
        else:
            next_solutions = []
            for score, moves, board, row, column in solutions:
                for delta_r, delta_c in self._swaps(board, row, column):
                    swapped_board = Board.copy_board(board).swap(row, column, row + delta_r, column + delta_c)
                    next_solutions.append((score + self._score(swapped_board), (moves + ((delta_r, delta_c),)), swapped_board, row + delta_r, column + delta_c))

            # prune solutions down before recursing to next depth
            return self._step(self._prune(next_solutions), depth - 1)
Пример #16
0
def test_greedy_dfs(weights):
    def compare(original, final, moves, row, column, assert_error_message):
        for delta_r, delta_c in moves:
            original.swap(row, column, row + delta_r, column + delta_c)
            row += delta_r
            column += delta_c

        for r in range(original.rows):
            for c in range(original.columns):
                assert isinstance(original.cell(r, c), type(final.cell(r, c))), assert_error_message

    # solution should contain move list that gets you to the final board state starting from original board state
    original = Board.create_randomized_board(5, 6)
    _, moves, final_board = GreedyDfs(weights).solve(original, 20)
    compare(original, final_board, moves[1:], moves[0][0], moves[0][1], "Greedy DFS yielded an incorrect 4-way move list!")

    # same with diagonals enabled
    original = Board.create_randomized_board(5, 6)
    h = GreedyDfs(weights)
    h.diagonals = True
    _, moves, final_board = h.solve(original, 20)
    compare(original, final_board, moves[1:], moves[0][0], moves[0][1], "Greedy DFS yielded an incorrect 8-way move list!")
Пример #17
0
    def _step(self, score, moves, board, row, column, depth):
        if depth == 0:
            return (score, moves, board)
        else:
            # get possible swaps from current row, column position
            swaps = self._swaps(board, row, column)

            solutions = []
            for delta_r, delta_c in swaps:
                swapped_board = Board.copy_board(board).swap(row, column, row + delta_r, column + delta_c)
                solutions.append((self._score(swapped_board), swapped_board, (delta_r, delta_c)))

            # calculate score on all possible swaps and order them from highest to lowest. recurse into the highest one
            best = max(solutions, key=lambda x: x[0])
            return self._step(score + best[0], (moves + (best[2],)), best[1], row + best[2][0], column + best[2][1], depth - 1)
Пример #18
0
    def _step(self, score, moves, board, row, column, depth):
        if depth == 0:
            return (score, moves, board)
        else:
            # get possible swaps from current row, column position
            swaps = self._swaps(board, row, column)

            solutions = []
            for delta_r, delta_c in swaps:
                swapped_board = Board.copy_board(board).swap(row, column, row + delta_r, column + delta_c)
                if self._remember(swapped_board):
                    # only add move to solutions if it is a board layout that has not been seen before
                    solutions.append((self._score(swapped_board), swapped_board, (delta_r, delta_c)))

            if solutions:
                # calculate score on all possible swaps and order them from highest to lowest. recurse into the highest one
                best = max(solutions, key=lambda x: x[0])
                return self._step(score + best[0], (moves + (best[2],)), best[1], row + best[2][0], column + best[2][1], depth - 1)
            else:
                return (score, moves, board)
Пример #19
0
    def _step(self, solutions, depth):
        if depth == 0:
            return solutions
        else:
            next_solutions = []
            for score, moves, board, row, column in solutions:
                for delta_r, delta_c in self._swaps(board, row, column):
                    swapped_board = Board.copy_board(board).swap(
                        row, column, row + delta_r, column + delta_c)
                    if self._remember(swapped_board):
                        # only add move to solutions if it is a board layout that has not been seen before
                        next_solutions.append(
                            (score + self._score(swapped_board),
                             (moves + ((delta_r, delta_c), )), swapped_board,
                             row + delta_r, column + delta_c))

            if next_solutions:
                # prune solutions down before recursing to next depth
                return self._step(self._prune(next_solutions), depth - 1)
            else:
                return solutions
Пример #20
0
    Heart.symbol: 1.0,
    Poison.symbol: 0.5,
    Jammer.symbol: 0.5,
    Unknown.symbol: 0.0
}

#board = Board.create_randomized_board(5, 6)

piece_list = [
    Fire, Wood, Water, Dark, Light, Heart, Fire, Water, Dark, Light, Heart,
    Fire, Fire, Water, Dark, Heart, Heart, Wood, Light, Water, Light, Fire,
    Wood, Wood, Dark, Water, Dark, Light, Light, Light
]
number_of_rows = 5
number_of_columns = 6
board = Board(piece_list, number_of_rows, number_of_columns)
matches = board.get_matches()

print(board)
print(matches)

solver1 = GreedyDfs(weights)
solution = solver1.solve(board, 100)

print(solution)

solver2 = PrunedBfs(weights)
solution = solver2.solve(board, 100)

print(solution)
Пример #21
0
def test_randomized_board():
    # randomized board should contain only Fire, Water, Wood, Dark, Light, and Heart pieces
    allowed_pieces = set([Fire, Water, Wood, Dark, Light, Heart])
    b = Board.create_randomized_board(5, 6)
    pieces = [b.cell(r, c) for c in range(b.columns) for r in range(b.rows) if isinstance(b.cell(r, c), tuple(allowed_pieces))]
    assert len(pieces) == 30, "Creating randomized board contains invalid pieces!"
Пример #22
0
def test_empty_board():
    # empty board should contain only Unknown pieces
    b = Board.create_empty_board(5, 6)
    unknown_pieces = [b.cell(r, c) for c in range(b.columns) for r in range(b.rows) if isinstance(b.cell(r, c), Unknown)]
    assert len(unknown_pieces) == 30, "Creating empty board does not contain only Unknown pieces!"
Пример #23
0
def board_with_1_chain():
    return Board([
        Fire, Wood, Water, Dark, Light, Poison, Water, Water, Water, Light,
        Heart, Jammer, Fire, Water, Dark, Heart, Heart, Wood, Light, Water,
        Light, Fire, Wood, Wood, Dark, Heart, Dark, Light, Heart, Light
    ], 5, 6)
Пример #24
0
from pazudorasolver.heuristics.greedy_dfs import GreedyDfs
from pazudorasolver.heuristics.pruned_bfs import PrunedBfs

weights = {
    Fire.symbol: 1.0,
    Wood.symbol: 1.0,
    Water.symbol: 1.0,
    Dark.symbol: 1.0,
    Light.symbol: 1.0,
    Heart.symbol: 1.0,
    Poison.symbol: 0.5,
    Jammer.symbol: 0.5,
    Unknown.symbol: 0.0
}

board = Board.create_randomized_board(5, 6)
matches = board.get_matches()

print(board)
print(matches)

# try GreedyDfs heuristic
solver1 = GreedyDfs(weights)
solution = solver1.solve(board, 50)

print(solution)

# try PrunedBfs heuristic
solver2 = PrunedBfs(weights)
solution = solver2.solve(board, 50)
Пример #25
0
def test_board_setup():
    # as long as length of piece list is equal to row x column, the board yields no error and loads from top left down to bottom right
    b = Board([Fire, Water, Wood, Dark, Light, Heart], 2, 3)
    assert isinstance(b, Board), "Board valid 2x3, but was not instantiated!"
    assert isinstance(b.cell(0, 0),
                      Fire), "Unexpected piece @ 0,0 on 2x3 Board!"
    assert isinstance(b.cell(0, 1),
                      Water), "Unexpected piece @ 0,1 on 2x3 Board!"
    assert isinstance(b.cell(0, 2),
                      Wood), "Unexpected piece @ 0,2 on 2x3 Board!"
    assert isinstance(b.cell(1, 0),
                      Dark), "Unexpected piece @ 1,0 on 2x3 Board!"
    assert isinstance(b.cell(1, 1),
                      Light), "Unexpected piece @ 1,1 on 2x3 Board!"
    assert isinstance(b.cell(1, 2),
                      Heart), "Unexpected piece @ 1,2 on 2x3 Board!"
    assert b.rows == 2, "2x3 board has incorrect rows property!"
    assert b.columns == 3, "2x3 board has incorrect columns property!"
    assert len(b.board) == 2 and len(
        b.board[0]) == 3, "2x3 board has incorrect board dimensions!"

    b = Board([Fire, Water, Wood, Dark, Light, Heart], 3, 2)
    assert isinstance(b, Board), "Board valid 3x2, but was not instantiated!"
    assert isinstance(b.cell(0, 0),
                      Fire), "Unexpected piece @ 0,0 on 3x2 Board!"
    assert isinstance(b.cell(0, 1),
                      Water), "Unexpected piece @ 0,1 on 3x2 Board!"
    assert isinstance(b.cell(1, 0),
                      Wood), "Unexpected piece @ 1,0 on 3x2 Board!"
    assert isinstance(b.cell(1, 1),
                      Dark), "Unexpected piece @ 1,1 on 3x2 Board!"
    assert isinstance(b.cell(2, 0),
                      Light), "Unexpected piece @ 2,0 on 3x2 Board!"
    assert isinstance(b.cell(2, 1),
                      Heart), "Unexpected piece @ 2,1 on 3x2 Board!"
    assert b.rows == 3, "3x2 board has incorrect rows property!"
    assert b.columns == 2, "3x2 board has incorrect columns property!"
    assert len(b.board) == 3 and len(
        b.board[0]) == 2, "3x2 board has incorrect board dimensions!"
Пример #26
0
def board_with_3_chain():
    return Board([
        Fire, Wood, Water, Dark, Light, Heart, Fire, Water, Dark, Light, Heart,
        Fire, Fire, Water, Dark, Heart, Heart, Wood, Light, Water, Light, Fire,
        Wood, Wood, Dark, Water, Dark, Light, Light, Light
    ], 5, 6)