bi_a_star.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. # -*- coding: utf-8 -*-
  2. import time
  3. from .finder import TIME_LIMIT, MAX_RUNS, BY_START, BY_END
  4. from .a_star import AStarFinder
  5. from pathfinding.core.diagonal_movement import DiagonalMovement
  6. class BiAStarFinder(AStarFinder):
  7. """
  8. Similar to the default A* algorithm from a_star.
  9. """
  10. def __init__(self, heuristic=None, weight=1,
  11. diagonal_movement=DiagonalMovement.never,
  12. time_limit=TIME_LIMIT,
  13. max_runs=MAX_RUNS):
  14. """
  15. find shortest path using Bi-A* algorithm
  16. :param heuristic: heuristic used to calculate distance of 2 points
  17. (defaults to manhatten)
  18. :param weight: weight for the edges
  19. :param diagonal_movement: if diagonal movement is allowed
  20. (see enum in diagonal_movement)
  21. :param time_limit: max. runtime in seconds
  22. :param max_runs: max. amount of tries until we abort the search
  23. (optional, only if we enter huge grids and have time constrains)
  24. <=0 means there are no constrains and the code might run on any
  25. large map.
  26. """
  27. super(BiAStarFinder, self).__init__(
  28. heuristic=heuristic,
  29. weight=weight,
  30. diagonal_movement=diagonal_movement,
  31. time_limit=time_limit,
  32. max_runs=max_runs)
  33. self.weighted = False
  34. def find_path(self, start, end, grid):
  35. """
  36. find a path from start to end node on grid using the A* algorithm
  37. :param start: start node
  38. :param end: end node
  39. :param grid: grid that stores all possible steps/tiles as 2D-list
  40. :return:
  41. """
  42. self.start_time = time.time() # execution time limitation
  43. self.runs = 0 # count number of iterations
  44. start_open_list = [start]
  45. start.g = 0
  46. start.f = 0
  47. start.opened = BY_START
  48. end_open_list = [end]
  49. end.g = 0
  50. end.f = 0
  51. end.opened = BY_END
  52. while len(start_open_list) > 0 and len(end_open_list) > 0:
  53. self.runs += 1
  54. self.keep_running()
  55. path = self.check_neighbors(start, end, grid, start_open_list,
  56. open_value=BY_START,
  57. backtrace_by=BY_END)
  58. if path:
  59. return path, self.runs
  60. self.runs += 1
  61. self.keep_running()
  62. path = self.check_neighbors(end, start, grid, end_open_list,
  63. open_value=BY_END,
  64. backtrace_by=BY_START)
  65. if path:
  66. return path, self.runs
  67. # failed to find path
  68. return [], self.runs