コード例 #1
0
ファイル: jump_point_search.py プロジェクト: asunathanr/AStar
 def diagonal_forced_neighbors(coord, direction):
     forced_candidates = {Coord(coord.x, coord.y - direction.y)}
     forced = set(
         filter(lambda candidate: candidate in self.grid.obstacles(),
                forced_candidates))
     return set(
         map(lambda cell: Coord(cell.x + direction.x, cell.y), forced))
コード例 #2
0
 def test_start_successors(self):
     """
     Test that a starting node produces all neighbors of it as successors.
     """
     expected = {JPSNode(Coord(0, 3), Coord(0, 1))}
     actual = self.jps.successors(JPSNode(Coord(0, 0), None), Coord(0, 3))
     self.assertEqual(expected, actual)
コード例 #3
0
 def test_diagonal_execute(self):
     goal = Coord(3, 3)
     expected = [Coord(0, 0), goal]
     path = list(
         map(lambda jump_point: jump_point.coord,
             self.jps.execute((Coord(0, 0), goal))))
     self.assertEqual(expected, path)
コード例 #4
0
 def test_forced_diagonal(self):
     obstacle_grid = DiagonalGrid(4, 4, [Coord(2, 1)])
     diag_jps = JumpPointSearch(obstacle_grid, diagonal)
     expected = Coord(3, 1)
     current = JPSNode(Coord(2, 2), Coord(1, 1))
     neighbors = set(
         diag_jps.forced_neighbors(current.coord, current.direction))
     self.assertTrue(expected in neighbors)
コード例 #5
0
ファイル: test_astar.py プロジェクト: asunathanr/AStar
 def test_tricky_path(self):
     tricky_grid = OrthogonalGrid(3, 3, [Coord(0, 1), Coord(2, 1)])
     path = set(
         AStar(tricky_grid, manhattan).execute((Coord(0, 0), Coord(2, 2))))
     expected = {
         Coord(0, 0),
         Coord(1, 0),
         Coord(1, 1),
         Coord(1, 2),
         Coord(2, 2)
     }
     coord_path = set(map(lambda cell: Coord(cell.x, cell.y), path))
     self.assertEqual(expected, coord_path)
コード例 #6
0
 def test_obstacle_execute(self):
     expected = [
         JPSNode(Coord(0, 0), None),
         JPSNode(Coord(1, 1), Coord(1, 1)),
         JPSNode(Coord(1, 2), Coord(0, 1)),
         JPSNode(Coord(0, 3), Coord(-1, 1))
     ]
     obstacle_jps = JumpPointSearch(self.obstacle_grid, diagonal)
     path = obstacle_jps.execute((Coord(0, 0), Coord(0, 3)))
     self.assertEqual(expected, path,
                      coordinate_mismatch_message(expected, path))
コード例 #7
0
ファイル: jump_point_search.py プロジェクト: asunathanr/AStar
 def straight_forced_neighbors(coord, direction):
     orthogonal_direction = Coord(direction.y, direction.x)
     forced_candidates = {
         Coord(coord.x + orthogonal_direction.x,
               coord.y + orthogonal_direction.y),
         Coord(coord.x - orthogonal_direction.x,
               coord.y - orthogonal_direction.y)
     }
     forced = set(
         filter(lambda candidate: candidate in self.grid.obstacles(),
                forced_candidates))
     return set(
         map(
             lambda cell: Coord(cell.x + direction.x, cell.y + direction
                                .y), forced))
コード例 #8
0
ファイル: jump_point_search.py プロジェクト: asunathanr/AStar
 def connect_jump_points(begin, end):
     total_cells = int(self.heuristic_fn(begin.coord, end.coord))
     return list(
         map(
             lambda offset: Coord(
                 begin.coord.x + end.direction.x * offset, begin.coord.y
                 + end.direction.y * offset), range(0, total_cells)))
コード例 #9
0
ファイル: jump_point_search.py プロジェクト: asunathanr/AStar
    def jump(self, parent: Coord, direction: Coord, goal):
        """
        Finds next jump point recursively.
        Base cases:
        1. Next coordinate is out of bounds
        2. Next coordinate is an obstacle
        3. Next coordinate has forced neighbors

        :param parent: Previously considered point (not necessarily a jump point)
        :param direction: Direction to try finding next jump point.
        :param goal: Goal cell.
        :return: Next jump point to consider or None if direction is invalid.
        """
        def straight_moves():
            return {Coord(0, direction.y), Coord(direction.x, 0)}

        def invalid_direction() -> bool:
            return not self.grid.is_valid_coord(
                next_coord) or next_coord in self.grid.obstacles()

        def is_jump_point() -> bool:
            return next_coord == goal or self.has_forced_neighbors(
                next_coord, direction)

        next_coord = Coord(parent.x + direction.x, parent.y + direction.y)
        if invalid_direction():
            return None
        if is_jump_point():
            return next_coord
        if self.is_diagonal(direction):
            for i in straight_moves():
                if self.jump(next_coord, i, goal) is not None:
                    return next_coord
        return self.jump(next_coord, direction, goal)
コード例 #10
0
ファイル: jump_point_search.py プロジェクト: asunathanr/AStar
 def natural_neighbors(self, cell: Coord, direction: Coord) -> {}:
     """
     :param cell: A cell inside the current grid.
     :param direction: Direction previously traveled.
     :return: A set containing any natural neighbors of a cell.
     """
     if self.is_diagonal(direction):
         natural_neighbors = {
             Coord(cell.x + direction.x, cell.y),
             Coord(cell.x, cell.y + direction.y),
             Coord(cell.x + direction.x, cell.y + direction.y)
         }
     else:
         natural_neighbors = {
             Coord(cell.x + direction.x, cell.y + direction.y)
         }
     return natural_neighbors
コード例 #11
0
 def test_neighbors(self):
     coord = Coord(1, 1)
     neighbors = set(self.grid.neighbors(coord))
     self.assertEqual(
         {
             Coord(0, 0),
             Coord(0, 1),
             Coord(1, 0),
             Coord(2, 1),
             Coord(2, 2),
             Coord(0, 2),
             Coord(2, 0),
             Coord(1, 2)
         }, neighbors)
コード例 #12
0
ファイル: orthogonal_grid.py プロジェクト: asunathanr/AStar
 def neighbors(self, coord: Coord) -> list:
     """
     :param coord:
     :return: All neighbors of coord in a list. (A coord with no neighbors would return empty list)
     """
     make_neighbor = lambda x, y: Coord(coord.x + x, coord.y + y)
     dist = map(lambda i: make_neighbor(i[0], i[1]), [(0, -1), (0, 1),
                                                      (-1, 0), (1, 0)])
     return list(filter(lambda i: self.is_adjacent(coord, i), dist))
コード例 #13
0
 def test_diagonal_obstacle(self):
     expected = [
         JPSNode(Coord(0, 0), None),
         JPSNode(Coord(2, 2), Coord(1, 1)),
         JPSNode(Coord(3, 3), Coord(1, 1))
     ]
     diagonal_obstacle_grid = DiagonalGrid(4, 4, [Coord(2, 1)])
     obstacle_jps = JumpPointSearch(diagonal_obstacle_grid, diagonal)
     path = obstacle_jps.execute((Coord(0, 0), Coord(3, 3)))
     self.assertEqual(expected, path,
                      coordinate_mismatch_message(expected, path))
コード例 #14
0
ファイル: direction.py プロジェクト: asunathanr/AStar
 def __init__(self):
     self.straight_coordinates = {
         Directions.TOP: Coord(-1, 0),
         Directions.BOTTOM: Coord(1, 0),
         Directions.LEFT: Coord(0, -1),
         Directions.RIGHT: Coord(0, 1),
     }
     self.diagonal_coordinates = {
         Directions.TOP_LEFT: Coord(-1, -1),
         Directions.TOP_RIGHT: Coord(1, 1),
         Directions.BOTTOM_LEFT: Coord(-1, 1),
         Directions.BOTTOM_RIGHT: Coord(-1, 1)
     }
コード例 #15
0
ファイル: jump_point_search.py プロジェクト: asunathanr/AStar
 def successors(self, current: JPSNode, goal: Coord):
     """
     Finds jump point successors of current JPSNode.
     :param current:
     :param goal:
     :return: A set of successors, including empty set if no successors are found.
     """
     succ = set()
     neighbors = self.prune(current)
     parent_x, parent_y = current.coord.x, current.coord.y
     for neighbor in neighbors:
         dir_coord = self.direction(current.coord, neighbor)
         next_jump_point = self.jump(Coord(parent_x, parent_y),
                                     Coord(dir_coord.x, dir_coord.y), goal)
         if next_jump_point is not None:
             next_node = JPSNode(next_jump_point, dir_coord)
             next_node.g = current.g + STRAIGHT_COST
             next_node.f = next_node.g + self.heuristic_fn(
                 next_node.coord, goal)
             succ.add(next_node)
     return succ
コード例 #16
0
 def test_large_obstacle_grid(self):
     large_grid = DiagonalGrid(
         10, 10,
         [Coord(1, 8), Coord(5, 7),
          Coord(6, 0), Coord(7, 7)])
     obstacle_jps = JumpPointSearch(large_grid, diagonal_tie_breaker)
     path = obstacle_jps.execute((Coord(0, 0), Coord(9, 9)))
コード例 #17
0
ファイル: orthogonal_grid.py プロジェクト: asunathanr/AStar
def print_grid(grid: OrthogonalGrid, path: []):
    """
    Print a grid with path.
    :param grid: OrthogonalGrid to print
    :param path: Path
    """
    for i in range(0, grid.xsize):
        for j in range(0, grid.ysize):
            coord = Coord(i, j)
            if coord in path:
                val = 'P'
            elif coord in grid.obstacles():
                val = 'X'
            else:
                val = '.'
            print(val, sep=' ', end=' ')
        print()
コード例 #18
0
ファイル: test_astar.py プロジェクト: asunathanr/AStar
 def test_only_path(self):
     """
         Only one path goes through this three by three grid.
         test_path method should give us back this one path.
         It looks like:
         |X|X|E|
         | | | |
         |S|X|X|
     """
     algo = AStar(self.grid, manhattan)
     path = set(algo.execute((Coord(0, 0), Coord(2, 2))))
     expected = {
         Coord(0, 0),
         Coord(1, 0),
         Coord(1, 1),
         Coord(1, 2),
         Coord(2, 2)
     }
     coord_path = set(map(lambda cell: Coord(cell.x, cell.y), path))
     self.assertEqual(expected, coord_path)
コード例 #19
0
 def test_prune_start_node(self):
     expected = {Coord(0, 1)}
     current = JPSNode(Coord(0, 0), Coord(0, 1))
     neighbors = set(self.jps.prune(current))
     self.assertEqual(expected, neighbors)
コード例 #20
0
 def test_not_forced_neighbor(self):
     forced = self.jps.has_forced_neighbors(Coord(0, 0), Coord(0, 1))
     self.assertFalse(
         forced, "Error: forced neighbor occurred in empty grid space.")
コード例 #21
0
 def test_is_forced_neighbor(self):
     forced_neighbor_grid = DiagonalGrid(4, 4, [Coord(1, 2)])
     obstacle_jps = JumpPointSearch(forced_neighbor_grid, diagonal)
     neighbors = obstacle_jps.has_forced_neighbors(Coord(0, 2), Coord(0, 1))
     self.assertTrue(neighbors)
コード例 #22
0
 def test_blocked_jump(self):
     obstacle_jps = JumpPointSearch(self.obstacle_grid, diagonal)
     coord = obstacle_jps.jump(Coord(0, 1), Coord(0, 1), Coord(0, 3))
     self.assertIsNone(coord)
コード例 #23
0
 def test_diagonal_jump(self):
     expected_coord = Coord(3, 3)
     coord = self.jps.jump(Coord(0, 0), Coord(1, 1), expected_coord)
     self.assertEqual(expected_coord, coord)
コード例 #24
0
 def test_obstacle_execute(self):
     obstacle_grid = DiagonalGrid(4, 4, [Coord(0, 2)])
     expected = [Coord(0, 0), Coord(0, 1), Coord(1, 0)]
コード例 #25
0
 def test_full_diagonal_path(self):
     expected = [Coord(0, 0), Coord(1, 1), Coord(2, 2), Coord(3, 3)]
     path = self.jps.execute((Coord(0, 0), Coord(3, 3)))
     self.assertEqual(expected, self.jps.connect_path(path))
コード例 #26
0
 def test_full_horizontal_path(self):
     goal = Coord(0, 3)
     expected = [Coord(0, 0), Coord(0, 1), Coord(0, 2), Coord(0, 3)]
     path = self.jps.execute((Coord(0, 0), goal))
     self.assertEqual(expected, self.jps.connect_path(path))
コード例 #27
0
 def test_prune_horizontal_node(self):
     expected = {Coord(1, 2)}
     current = JPSNode(Coord(1, 1), Coord(0, 1))
     neighbors = set(self.jps.prune(current))
     self.assertEqual(expected, neighbors)
コード例 #28
0
 def test_horizontal_jump(self):
     expected_coord = Coord(0, 3)
     coord = self.jps.jump(Coord(0, 0), Coord(0, 1), expected_coord)
     self.assertEqual(expected_coord, coord)
コード例 #29
0
 def setUp(self):
     self.grid = DiagonalGrid(4, 4, [])
     self.obstacle_grid = DiagonalGrid(4, 4, [Coord(0, 2)])
     self.jps = JumpPointSearch(self.grid, diagonal)
コード例 #30
0
 def test_horizontal_execute(self):
     goal = Coord(0, 3)
     expected = [JPSNode(Coord(0, 0), None), JPSNode(goal, Coord(0, 1))]
     path = self.jps.execute((Coord(0, 0), goal))
     self.assertEqual(expected, path)