first_search.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. # ----------
  2. # User Instructions:
  3. #
  4. # Define a function, search() that returns a list
  5. # in the form of [optimal path length, row, col]. For
  6. # the grid shown below, your function should output
  7. # [11, 4, 5].
  8. #
  9. # If there is no valid path from the start point
  10. # to the goal, your function should return the string
  11. # 'fail'
  12. # ----------
  13. # Grid format:
  14. # 0 = Navigable space
  15. # 1 = Occupied space
  16. from collections import deque
  17. import numpy as np
  18. from icecream import ic
  19. grid = np.array([[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
  20. [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
  21. [0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0],
  22. [0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0],
  23. [0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
  24. [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
  25. [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
  26. [0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0],
  27. [0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0],
  28. [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]])
  29. init = np.array([0, 0])
  30. # goal = np.array([len(grid)-1, len(grid[0])-1])
  31. goal = np.array([7, 10])
  32. cost = 1
  33. delta = np.array([[-1, 0], # go up
  34. [0, -1], # go left
  35. [1, 0], # go down
  36. [0, 1]]) # go right
  37. delta_name = ['^', '<', 'v', '>']
  38. def check_navigable(grid, goal) -> bool:
  39. if all(goal >= np.array([0, 0])) and all(goal <= np.array([len(grid)-1, len(grid[0])-1])):
  40. if not grid[goal[0], goal[1]]:
  41. return True
  42. return False
  43. def search(grid: np.ndarray, init: list, goal: list, cost: list):
  44. # ----------------------------------------
  45. # insert code here
  46. # ----------------------------------------
  47. next_check = deque()
  48. next_check.append(init)
  49. already_checked = dict()
  50. already_checked[tuple(init)] = 0
  51. cost_map = np.zeros([len(grid), len(grid[0])]) + float('INF')
  52. cost_map[init[0], init[1]] = 0
  53. expand_map = np.zeros([len(grid), len(grid[0])]) - 1
  54. expand_now = 0
  55. expand_map[init[0], init[1]] = expand_now
  56. while next_check:
  57. checking = next_check.popleft()
  58. if check_navigable(grid, checking):
  59. for move_num in range(len(delta)):
  60. next = checking+delta[move_num] # type: np.ndarray
  61. if check_navigable(grid, next) and tuple(next) not in already_checked:
  62. expand_now += 1
  63. next_check.append(next)
  64. cost_now = already_checked[checking[0], checking[1]]+cost
  65. already_checked[tuple(next)] = cost_now
  66. cost_map[next[0], next[1]] = cost_now
  67. expand_map[next[0], next[1]] = expand_now
  68. if all(next == goal):
  69. ic(cost_map)
  70. ic(expand_map)
  71. # return [cost_now, next[0], next[1]]
  72. return cost_map
  73. # ic(cost_map)
  74. # ic(expand_map)
  75. return "fail"
  76. def show_path(grid, init, goal, cost):
  77. cost_map = search(grid, init, goal, cost)
  78. motion_map = np.array([[' ' for x in range(len(grid[0]))]
  79. for y in range(len(grid))])
  80. motion_map[goal[0], goal[1]] = '*'
  81. if type(cost_map) == np.ndarray:
  82. print('success')
  83. now_position = goal
  84. while any(now_position != init):
  85. dlt_opst = deque(['v', '>', '^', '<'])
  86. neighbor_grid = np.array([now_position for _ in range(4)])+delta
  87. neighbor_grid = map(lambda pos: pos if check_navigable(
  88. grid, pos) else False, neighbor_grid)
  89. neighbor_cost = {cost_map[pos[0], pos[1]] if type(pos) == np.ndarray else float(
  90. 'INF'): [dlt_opst.popleft(), pos] for pos in neighbor_grid}
  91. next_move, now_position = neighbor_cost[min(neighbor_cost.keys())]
  92. motion_map[now_position[0], now_position[1]] = next_move
  93. return motion_map
  94. elif cost_map == 'fail':
  95. print('Fail to generate a feasible path.')
  96. return motion_map
  97. ic(show_path(grid, init, goal, cost))