1. 程式人生 > >A*算法的理解與簡單實現

A*算法的理解與簡單實現

update for port 移動 ont 效率 print 估算 net

基本定義

一種尋路算法,特點是:啟發式的,效率高,基本思路比較簡單。

用途

尋路。在指定的地圖上,考慮到地圖上的移動代價,找到最優的路徑。

核心概念

開表,閉表,估值函數。

開表

開表,記錄了當前需要處理的地圖上的點。

1什麽點會加入開表?

1.1 當一個點是起始點時,可以加入;

1.2 當一個點是起始點的鄰接點,且不再閉表裏時,可以進入開表;

2什麽點會離開開表?

2.1開表中的點會按照f(n)進行升序排序,得到最小值的一個點被最先處理;當一個點已經處理後,會離開開表,加入閉表。

閉表

閉表,記錄了當前已經處理的地圖上的點。

1什麽點會加入閉表?

1.1當一個點已經處理後,會加入閉表;

2什麽點會離開閉表?

不會有點離開閉表。

估值函數

估值函數,估算了當前點處於最優路徑上的代價。

估值函數f(n) = g(n) + h(n),其中g(n)表示由起點到當前點的代價;h(n)表示由當前點到終點的代價。A*算法的最核心部分也就是這個估值函數的設計。

在我的實現中,我用簡單的幾何距離作為估值函數的實現。

算法描述

1將起點加入開表

2開表裏如果為空,算法退出;否則,取出f(n)最小的點作為最優路徑上的點;

3針對當前處理的點,計算鄰接點,如果鄰接點不在閉表,且不在開表,加入開表

4重復2,3步驟直到退出

示例實現

  1 #coding=utf8
  2 """
  3     a* algorithm
4 """ 5 import math 6 7 AB_MAP = [ 8 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 9 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 10 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 11 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
12 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 13 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 14 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 15 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 16 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 17 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 18 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 19 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 20 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 21 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 22 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 23 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 24 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 25 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 26 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 27 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], 28 ] 29 POS_UP = 1 30 POS_LEFT = 2 31 POS_DOWN = 3 32 POS_RIGHT = 4 33 34 35 def mod_map(m_map, pos_x, pos_y, val): 36 """ 37 修改地圖的某個點位的值 38 """ 39 m_map[pos_x][pos_y] = val 40 41 42 def print_map(m_map): 43 """ 44 打印地圖 45 """ 46 rows = len(m_map) 47 for i in range(0, rows - 1): 48 cols = len(m_map[i]) 49 for j in range(0, cols - 1): 50 print str(m_map[i][j]) + "\t", 51 j = j + 1 52 print 53 i = i + 1 54 55 56 class Node(object): 57 """ 58 記錄一個節點的信息 59 """ 60 def __init__(self, x, y, h_n=0, g_n=0): 61 self.pos_x = x 62 self.pos_y = y 63 self.parent = None 64 self.h_n = h_n 65 self.g_n = g_n 66 self.f_n = self.h_n + self.g_n 67 68 def update_h_n(self, target): 69 """ 70 計算h(n) 71 """ 72 self.h_n = int(math.sqrt((target.pos_x - self.pos_x)**2 + (target.pos_y - self.pos_y)**2)) 73 return self.h_n 74 75 def update_g_n(self, source): 76 """ 77 計算g(n) 78 """ 79 self.g_n = int(math.sqrt((source.pos_x - self.pos_x)**2 + (source.pos_y - self.pos_y)**2)) 80 return self.g_n 81 82 def update_f_n(self, source, target): 83 """ 84 計算f(n) 85 """ 86 self.f_n = self.update_g_n(source) + self.update_h_n(target) 87 return self.f_n 88 89 def update_parent(self, par): 90 """ 91 更新父節點 92 """ 93 self.parent = par 94 95 def get_adj_node(self, flag, source, target): 96 """ 97 計算鄰近的節點 98 """ 99 if flag == POS_UP: 100 cur_node = Node(self.pos_x, self.pos_y - 1) 101 cur_node.update_f_n(source, target) 102 cur_node.parent = self 103 return cur_node 104 elif flag == POS_LEFT: 105 cur_node = Node(self.pos_x - 1, self.pos_y) 106 cur_node.update_f_n(source, target) 107 cur_node.parent = self 108 return cur_node 109 elif flag == POS_DOWN: 110 cur_node = Node(self.pos_x, self.pos_y + 1) 111 cur_node.update_f_n(source, target) 112 cur_node.parent = self 113 return cur_node 114 elif flag == POS_RIGHT: 115 cur_node = Node(self.pos_x + 1, self.pos_y) 116 cur_node.update_f_n(source, target) 117 cur_node.parent = self 118 return cur_node 119 else: 120 return None 121 122 123 def node_addible(node, open_list, close_list): 124 """ 125 判斷一個點是否在open和close表 126 """ 127 index = str(node.pos_x) + _ + str(node.pos_y) 128 if index not in open_list and index not in close_list: 129 open_list[index] = node 130 131 132 def reach_end(node, target): 133 """ 134 判斷一個點是否到達終點 135 """ 136 if node and target and node.pos_x == target.pos_x and node.pos_y == target.pos_y: 137 return True 138 else: 139 return False 140 141 142 def handle_reach_end(node, mmap, modval, print_path=False): 143 """ 144 當一個點到達終點時的處理方法 145 """ 146 if node and mmap: 147 while node: 148 if print_path: 149 print "x: %s, y: %s" % (node.pos_x, node.pos_y) 150 mod_map(mmap, node.pos_x, node.pos_y, modval) 151 node = node.parent 152 153 def main(source, target, open_list, close_list, mmap): 154 """ 155 主函數 156 """ 157 open_list[str(source.pos_x) + _ + str(source.pos_y)] = source 158 while open_list: 159 tmp_dict = sorted(open_list.iteritems(), key=lambda d: d[1].f_n) 160 first_key = tmp_dict[0][0] 161 first_node = open_list[first_key] 162 del open_list[first_key] 163 164 up_node = first_node.get_adj_node(POS_UP, source, target) 165 if reach_end(up_node, target): 166 handle_reach_end(up_node, mmap, 2) 167 break 168 169 left_node = first_node.get_adj_node(POS_LEFT, source, target) 170 if reach_end(left_node, target): 171 handle_reach_end(left_node, mmap, 2) 172 break 173 174 down_node = first_node.get_adj_node(POS_DOWN, source, target) 175 if reach_end(down_node, target): 176 handle_reach_end(down_node, mmap, 2) 177 break 178 179 right_node = first_node.get_adj_node(POS_RIGHT, source, target) 180 if reach_end(right_node, target): 181 handle_reach_end(right_node, mmap, 2) 182 break 183 184 if first_key not in close_list: 185 close_list[first_key] = first_node 186 187 node_addible(up_node, open_list, close_list) 188 node_addible(down_node, open_list, close_list) 189 node_addible(left_node, open_list, close_list) 190 node_addible(right_node, open_list, close_list) 191 192 193 if __name__ == __main__: 194 print "******************************* before *******************************" 195 print_map(AB_MAP) 196 OPEN_LIST = {} 197 CLOSE_LIST = {} 198 199 SOURCE = Node(3, 4) 200 TARGET = Node(13, 9) 201 main(SOURCE, TARGET, OPEN_LIST, CLOSE_LIST, AB_MAP) 202 203 print "******************************** after ********************************" 204 mod_map(AB_MAP, SOURCE.pos_x, SOURCE.pos_y, 0) 205 mod_map(AB_MAP, TARGET.pos_x, TARGET.pos_y, 0) 206 print_map(AB_MAP)

參考文章

http://www.cnblogs.com/technology/archive/2011/05/26/2058842.html
http://blog.sciencenet.cn/blog-5422-538894.html
https://segmentfault.com/a/1190000004462060
http://blog.csdn.net/v_JULY_v/article/details/6093380
http://blog.csdn.net/zhuangxiaobin/article/details/38755447
http://www.cnblogs.com/tongy0/p/5671545.html

A*算法的理解與簡單實現