图论BFS(Breath First Search)Algorithm广度优先搜索遍历空间平面网格图路径选择,networkx,Python

x33g5p2x  于2021-11-12 转载在 Go  
字(3.7k)|赞(0)|评价(0)|浏览(486)

(1)在每个节点埋入一个parent指针,指向当前节点的前一个节点,通过串联起来从终点起的父节点,就构成了路径。

(2)图中打X的节点表明当前节点不可通行。

(3)网格中的节点最终被标记为红色且被淡红色粗线描出来的就是选的路。

  1. import random
  2. import networkx as nx
  3. import matplotlib.pyplot as plt
  4. WALKABLE = 'walkable'
  5. PARENT = 'parent'
  6. VISITED = 'visited'
  7. def my_graph():
  8. M = 7
  9. N = 9
  10. G = nx.grid_2d_graph(m=M, n=N)
  11. pos = nx.spring_layout(G, iterations=100)
  12. nx.draw_networkx(G, pos=pos,
  13. # labels=labels, #labels = dict(((i, j), 'Phil') for i, j in G.nodes())
  14. font_size=8,
  15. font_color='white',
  16. node_color='green',
  17. node_size=500,
  18. width=1)
  19. START = (1, 1) # (2, 2)
  20. GOAL = (M - 1 - 1, N - 1 - 1)
  21. # 0,随机生成障碍物点
  22. # 1,精心挑选的障碍物构成陷阱
  23. obstacle_mode = 0
  24. road_closed_nodes = []
  25. if obstacle_mode == 0:
  26. obstacle = 20 # 障碍物(断点、不可达点)数量
  27. road_closed_nodes = obstacle_nodes(G, START, GOAL, obstacle, M, N)
  28. elif obstacle_mode == 1:
  29. road_closed_nodes = dummy_nodes(G)
  30. nx.draw_networkx_nodes(
  31. G, pos,
  32. nodelist=road_closed_nodes,
  33. node_size=500,
  34. node_color="red",
  35. node_shape="x",
  36. # alpha=0.3,
  37. label='x'
  38. )
  39. bfs(G, START, GOAL)
  40. path = find_path_by_parent(G, START, GOAL)
  41. print('path', path)
  42. nx.draw_networkx_nodes(
  43. G, pos,
  44. nodelist=path,
  45. node_size=400,
  46. node_color="red",
  47. node_shape='o',
  48. # alpha=0.3,
  49. # label='NO'
  50. )
  51. # nx.draw_networkx_nodes(
  52. # G, pos,
  53. # nodelist=path,
  54. # node_size=100,
  55. # node_color="yellow",
  56. # node_shape='*',
  57. # # alpha=0.3,
  58. # # label='NO'
  59. # )
  60. path_edges = []
  61. for i in range(len(path)):
  62. if (i + 1) == len(path):
  63. break
  64. path_edges.append((path[i], path[i + 1]))
  65. print('path_edges', path_edges)
  66. # 把path着色加粗重新描边
  67. nx.draw_networkx_edges(G, pos,
  68. edgelist=path_edges,
  69. width=8,
  70. alpha=0.5,
  71. edge_color="r")
  72. plt.axis('off')
  73. plt.show()
  74. # 广度优先遍历搜索路径
  75. def bfs(G, START, GOAL):
  76. for n in G.nodes():
  77. G.nodes[n][VISITED] = False
  78. print('G.nodes(data=True)', G.nodes(data=True))
  79. # 记录搜索路径
  80. search_path = []
  81. open_list = [START]
  82. while True:
  83. if len(open_list) == 0:
  84. break
  85. print('-----')
  86. print('open_list', open_list)
  87. node = open_list[0] # 左边最头部含有上一轮父层次的节点
  88. G.nodes[node][VISITED] = True
  89. search_path.append(node)
  90. print('search_path', len(search_path), search_path)
  91. print('选择', node)
  92. for n in nx.neighbors(G, node):
  93. try:
  94. walkable = G.nodes[n][WALKABLE]
  95. except:
  96. walkable = True
  97. visited = G.nodes[n][VISITED]
  98. # 如果节点已经在队列里面,则不予重复添加。
  99. if (not visited) and walkable and (n not in open_list):
  100. open_list.append(n)
  101. G.nodes[n][PARENT] = node
  102. print('弹出', node)
  103. del (open_list[0])
  104. print('open_list', open_list)
  105. print('nodes', G.nodes(data=True))
  106. if node == GOAL:
  107. print('到达->', GOAL)
  108. break
  109. def find_path_by_parent(G, START, GOAL):
  110. t = GOAL
  111. path = [t]
  112. is_find = False
  113. while not is_find:
  114. for n in G.nodes(data=True):
  115. if n[0] == t:
  116. print('parent', n)
  117. parent = n[1][PARENT]
  118. path.append(parent)
  119. if parent == START:
  120. is_find = True
  121. break
  122. t = parent
  123. list.reverse(path)
  124. return path
  125. # 障碍物点
  126. def obstacle_nodes(G, START, GOAL, obstacle, M, N):
  127. road_closed_nodes = []
  128. for i in range(obstacle):
  129. n = (random.randint(0, M - 1), random.randint(0, N - 1))
  130. if n == START or n == GOAL:
  131. continue
  132. if n in road_closed_nodes:
  133. continue
  134. G.nodes[n][WALKABLE] = False
  135. road_closed_nodes.append(n)
  136. return road_closed_nodes
  137. def dummy_nodes(G):
  138. fun_nodes = []
  139. n0 = (1, 2)
  140. G.nodes[n0][WALKABLE] = False
  141. fun_nodes.append(n0)
  142. n1 = (1, 3)
  143. G.nodes[n1][WALKABLE] = False
  144. fun_nodes.append(n1)
  145. n2 = (1, 4)
  146. G.nodes[n2][WALKABLE] = False
  147. fun_nodes.append(n2)
  148. n3 = (1, 5)
  149. G.nodes[n3][WALKABLE] = False
  150. fun_nodes.append(n3)
  151. n4 = (1, 6)
  152. G.nodes[n4][WALKABLE] = False
  153. fun_nodes.append(n4)
  154. n5 = (2, 6)
  155. G.nodes[n5][WALKABLE] = False
  156. fun_nodes.append(n5)
  157. n6 = (3, 6)
  158. G.nodes[n6][WALKABLE] = False
  159. fun_nodes.append(n6)
  160. n7 = (4, 6)
  161. G.nodes[n7][WALKABLE] = False
  162. fun_nodes.append(n7)
  163. n8 = (5, 6)
  164. G.nodes[n8][WALKABLE] = False
  165. fun_nodes.append(n8)
  166. n9 = (5, 5)
  167. G.nodes[n9][WALKABLE] = False
  168. fun_nodes.append(n9)
  169. n10 = (5, 4)
  170. G.nodes[n10][WALKABLE] = False
  171. fun_nodes.append(n10)
  172. n11 = (5, 3)
  173. G.nodes[n11][WALKABLE] = False
  174. fun_nodes.append(n11)
  175. n12 = (5, 2)
  176. G.nodes[n12][WALKABLE] = False
  177. fun_nodes.append(n12)
  178. return fun_nodes
  179. if __name__ == '__main__':
  180. my_graph()

程序运运行几轮后的选路截图,红色X的点是随机生成的障碍物点,红色X点是说当前这个点不能行走通过:

现在特别的为了挑战算法的智商水平,故意为算法制造一些陷阱出来。具体的实验方法,是做一个凹形的墙,把这个凹形的墙正对着出发点,看看算法的表现,重点考察算法是否能机智的绕过这堵墙, 找到终点。

把程序中的起点修改为(2,2)

  1. START = (2, 2)

修改障碍物模式为1:

  1. obstacle_mode = 1

算法的智商表现:

算法聪明的绕过墙、没有掉进陷阱。

相关文章

最新文章

更多