电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

python實現A*尋路算法

瀏覽:27日期:2022-06-17 08:01:25
目錄A* 算法簡介關鍵代碼介紹保存基本信息的地圖類搜索到的節點類算法主函數介紹代碼的初始化完整代碼A* 算法簡介

A* 算法需要維護兩個數據結構:OPEN 集和 CLOSED 集。OPEN 集包含所有已搜索到的待檢測節點。初始狀態,OPEN集僅包含一個元素:開始節點。CLOSED集包含已檢測的節點。初始狀態,CLOSED集為空。每個節點還包含一個指向父節點的指針,以確定追蹤關系。

A* 算法會給每個搜索到的節點計算一個G+H 的和值F:

F = G + H G:是從開始節點到當前節點的移動量。假設開始節點到相鄰節點的移動量為1,該值會隨著離開始點越來越遠而增大。 H:是從當前節點到目標節點的移動量估算值。 如果允許向4鄰域的移動,使用曼哈頓距離。如果允許向8鄰域的移動,使用對角線距離。

算法有一個主循環,重復下面步驟直到到達目標節點:1 每次從OPEN集中取一個最優節點n(即F值最小的節點)來檢測。2 將節點n從OPEN集中移除,然后添加到CLOSED集中。3 如果n是目標節點,那么算法結束。4 否則嘗試添加節點n的所有鄰節點n’。

鄰節點在CLOSED集中,表示它已被檢測過,則無需再添加。 鄰節點在OPEN集中: 如果重新計算的G值比鄰節點保存的G值更小,則需要更新這個鄰節點的G值和F值,以及父節點;否則不做操作 否則將該鄰節點加入OPEN集,設置其父節點為n,并設置它的G值和F值。

有一點需要注意,如果開始節點到目標節點實際是不連通的,即無法從開始節點移動到目標節點,那算法在第1步判斷獲取到的節點n為空,就會退出

關鍵代碼介紹保存基本信息的地圖類

地圖類用于隨機生成一個供尋路算法工作的基礎地圖信息

先創建一個map類, 初始化參數設置地圖的長度和寬度,并設置保存地圖信息的二維數據map的值為0, 值為0表示能移動到該節點。

class Map():def __init__(self, width, height):self.width = widthself.height = heightself.map = [[0 for x in range(self.width)] for y in range(self.height)]

在map類中添加一個創建不能通過節點的函數,節點值為1表示不能移動到該節點。

def createBlock(self, block_num):for i in range(block_num):x, y = (randint(0, self.width-1), randint(0, self.height-1))self.map[y][x] = 1

在map類中添加一個顯示地圖的函數,可以看到,這邊只是簡單的打印出所有節點的值,值為0或1的意思上面已經說明,在后面顯示尋路算法結果時,會使用到值2,表示一條從開始節點到目標節點的路徑。

def showMap(self):print('+' * (3 * self.width + 2))for row in self.map:s = ’+’for entry in row:s += ’ ’ + str(entry) + ’ ’s += ’+’print(s)print('+' * (3 * self.width + 2))

添加一個隨機獲取可移動節點的函數

def generatePos(self, rangeX, rangeY):x, y = (randint(rangeX[0], rangeX[1]), randint(rangeY[0], rangeY[1]))while self.map[y][x] == 1:x, y = (randint(rangeX[0], rangeX[1]), randint(rangeY[0], rangeY[1]))return (x , y)搜索到的節點類

每一個搜索到將到添加到OPEN集的節點,都會創建一個下面的節點類,保存有entry的位置信息(x,y),計算得到的G值和F值,和該節點的父節點(pre_entry)。

class SearchEntry():def __init__(self, x, y, g_cost, f_cost=0, pre_entry=None):self.x = xself.y = y# cost move form start entry to this entryself.g_cost = g_costself.f_cost = f_costself.pre_entry = pre_entrydef getPos(self):return (self.x, self.y)算法主函數介紹

下面就是上面算法主循環介紹的代碼實現,OPEN集和CLOSED集的數據結構使用了字典,在一般情況下,查找,添加和刪除節點的時間復雜度為O(1), 遍歷的時間復雜度為O(n), n為字典中對象數目。

def AStarSearch(map, source, dest):...openlist = {}closedlist = {}location = SearchEntry(source[0], source[1], 0.0)dest = SearchEntry(dest[0], dest[1], 0.0)openlist[source] = locationwhile True:location = getFastPosition(openlist)if location is None:# not found valid pathprint('can’t find valid path')break;if location.x == dest.x and location.y == dest.y:breakclosedlist[location.getPos()] = locationopenlist.pop(location.getPos())addAdjacentPositions(map, location, dest, openlist, closedlist)#mark the found path at the mapwhile location is not None:map.map[location.y][location.x] = 2location = location.pre_entry

我們按照算法主循環的實現來一個個講解用到的函數。下面函數就是從OPEN集中獲取一個F值最小的節點,如果OPEN集會空,則返回None。

# find a least cost position in openlist, return None if openlist is emptydef getFastPosition(openlist):fast = Nonefor entry in openlist.values():if fast is None:fast = entryelif fast.f_cost > entry.f_cost:fast = entryreturn fast

addAdjacentPositions 函數對應算法主函數循環介紹中的嘗試添加節點n的所有鄰節點n’。

# add available adjacent positionsdef addAdjacentPositions(map, location, dest, openlist, closedlist):poslist = getPositions(map, location)for pos in poslist:# if position is already in closedlist, do nothingif isInList(closedlist, pos) is None:findEntry = isInList(openlist, pos)h_cost = calHeuristic(pos, dest)g_cost = location.g_cost + getMoveCost(location, pos)if findEntry is None :# if position is not in openlist, add it to openlistopenlist[pos] = SearchEntry(pos[0], pos[1], g_cost, g_cost+h_cost, location)elif findEntry.g_cost > g_cost:# if position is in openlist and cost is larger than current one,# then update cost and previous positionfindEntry.g_cost = g_costfindEntry.f_cost = g_cost + h_costfindEntry.pre_entry = location

getPositions 函數獲取到所有能夠移動的節點,這里提供了2種移動的方式:

允許上,下,左,右 4鄰域的移動 允許上,下,左,右,左上,右上,左下,右下 8鄰域的移動

def getNewPosition(map, locatioin, offset):x,y = (location.x + offset[0], location.y + offset[1])if x < 0 or x >= map.width or y < 0 or y >= map.height or map.map[y][x] == 1:return Nonereturn (x, y)def getPositions(map, location):# use four ways or eight ways to moveoffsets = [(-1,0), (0, -1), (1, 0), (0, 1)]#offsets = [(-1,0), (0, -1), (1, 0), (0, 1), (-1,-1), (1, -1), (-1, 1), (1, 1)]poslist = []for offset in offsets:pos = getNewPosition(map, location, offset)if pos is not None:poslist.append(pos)return poslist

isInList 函數判斷節點是否在OPEN集 或CLOSED集中

# check if the position is in listdef isInList(list, pos):if pos in list:return list[pos]return None

calHeuristic 函數簡單得使用了曼哈頓距離,這個后續可以進行優化。getMoveCost 函數根據是否是斜向移動來計算消耗(斜向就是2的開根號,約等于1.4)

# imporve the heuristic distance more precisely in futuredef calHeuristic(pos, dest):return abs(dest.x - pos[0]) + abs(dest.y - pos[1])def getMoveCost(location, pos):if location.x != pos[0] and location.y != pos[1]:return 1.4else:return 1代碼的初始化

可以調整地圖的長度,寬度和不可移動節點的數目。可以調整開始節點和目標節點的取值范圍。

WIDTH = 10HEIGHT = 10BLOCK_NUM = 15map = Map(WIDTH, HEIGHT)map.createBlock(BLOCK_NUM)map.showMap()source = map.generatePos((0,WIDTH//3),(0,HEIGHT//3))dest = map.generatePos((WIDTH//2,WIDTH-1),(HEIGHT//2,HEIGHT-1))print('source:', source)print('dest:', dest)AStarSearch(map, source, dest)map.showMap()

執行的效果圖如下,第一個表示隨機生成的地圖,值為1的節點表示不能移動到該節點。第二個圖中值為2的節點表示找到的路徑。

python實現A*尋路算法

完整代碼

使用python3.7編譯

from random import randintclass SearchEntry():def __init__(self, x, y, g_cost, f_cost=0, pre_entry=None):self.x = xself.y = y# cost move form start entry to this entryself.g_cost = g_costself.f_cost = f_costself.pre_entry = pre_entrydef getPos(self):return (self.x, self.y)class Map():def __init__(self, width, height):self.width = widthself.height = heightself.map = [[0 for x in range(self.width)] for y in range(self.height)]def createBlock(self, block_num):for i in range(block_num):x, y = (randint(0, self.width-1), randint(0, self.height-1))self.map[y][x] = 1def generatePos(self, rangeX, rangeY):x, y = (randint(rangeX[0], rangeX[1]), randint(rangeY[0], rangeY[1]))while self.map[y][x] == 1:x, y = (randint(rangeX[0], rangeX[1]), randint(rangeY[0], rangeY[1]))return (x , y)def showMap(self):print('+' * (3 * self.width + 2))for row in self.map:s = ’+’for entry in row:s += ’ ’ + str(entry) + ’ ’s += ’+’print(s)print('+' * (3 * self.width + 2))def AStarSearch(map, source, dest):def getNewPosition(map, locatioin, offset):x,y = (location.x + offset[0], location.y + offset[1])if x < 0 or x >= map.width or y < 0 or y >= map.height or map.map[y][x] == 1:return Nonereturn (x, y)def getPositions(map, location):# use four ways or eight ways to moveoffsets = [(-1,0), (0, -1), (1, 0), (0, 1)]#offsets = [(-1,0), (0, -1), (1, 0), (0, 1), (-1,-1), (1, -1), (-1, 1), (1, 1)]poslist = []for offset in offsets:pos = getNewPosition(map, location, offset)if pos is not None:poslist.append(pos)return poslist# imporve the heuristic distance more precisely in futuredef calHeuristic(pos, dest):return abs(dest.x - pos[0]) + abs(dest.y - pos[1])def getMoveCost(location, pos):if location.x != pos[0] and location.y != pos[1]:return 1.4else:return 1# check if the position is in listdef isInList(list, pos):if pos in list:return list[pos]return None# add available adjacent positionsdef addAdjacentPositions(map, location, dest, openlist, closedlist):poslist = getPositions(map, location)for pos in poslist:# if position is already in closedlist, do nothingif isInList(closedlist, pos) is None:findEntry = isInList(openlist, pos)h_cost = calHeuristic(pos, dest)g_cost = location.g_cost + getMoveCost(location, pos)if findEntry is None :# if position is not in openlist, add it to openlistopenlist[pos] = SearchEntry(pos[0], pos[1], g_cost, g_cost+h_cost, location)elif findEntry.g_cost > g_cost:# if position is in openlist and cost is larger than current one,# then update cost and previous positionfindEntry.g_cost = g_costfindEntry.f_cost = g_cost + h_costfindEntry.pre_entry = location# find a least cost position in openlist, return None if openlist is emptydef getFastPosition(openlist):fast = Nonefor entry in openlist.values():if fast is None:fast = entryelif fast.f_cost > entry.f_cost:fast = entryreturn fastopenlist = {}closedlist = {}location = SearchEntry(source[0], source[1], 0.0)dest = SearchEntry(dest[0], dest[1], 0.0)openlist[source] = locationwhile True:location = getFastPosition(openlist)if location is None:# not found valid pathprint('can’t find valid path')break;if location.x == dest.x and location.y == dest.y:breakclosedlist[location.getPos()] = locationopenlist.pop(location.getPos())addAdjacentPositions(map, location, dest, openlist, closedlist)#mark the found path at the mapwhile location is not None:map.map[location.y][location.x] = 2location = location.pre_entryWIDTH = 10HEIGHT = 10BLOCK_NUM = 15map = Map(WIDTH, HEIGHT)map.createBlock(BLOCK_NUM)map.showMap()source = map.generatePos((0,WIDTH//3),(0,HEIGHT//3))dest = map.generatePos((WIDTH//2,WIDTH-1),(HEIGHT//2,HEIGHT-1))print('source:', source)print('dest:', dest)AStarSearch(map, source, dest)map.showMap()

到此這篇關于python實現A*尋路算法的文章就介紹到這了,更多相關python A*尋路算法內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Python 編程
相關文章:
主站蜘蛛池模板: 除甲醛公司-甲醛检测治理-杭州创绿家环保科技有限公司-室内空气净化十大品牌 | 胃口福饺子加盟官网_新鲜现包饺子云吞加盟 - 【胃口福唯一官网】 | PC构件-PC预制构件-构件设计-建筑预制构件-PC构件厂-锦萧新材料科技(浙江)股份有限公司 | 跨境物流_美国卡派_中大件运输_尾程派送_海外仓一件代发 - 广州环至美供应链平台 | 防弹玻璃厂家_防爆炸玻璃_电磁屏蔽玻璃-四川大硅特玻科技有限公司 | 无菌实验室规划装修设计-一体化实验室承包-北京洁净净化工程建设施工-北京航天科恩实验室装备工程技术有限公司 | 可程式恒温恒湿试验箱|恒温恒湿箱|恒温恒湿试验箱|恒温恒湿老化试验箱|高低温试验箱价格报价-广东德瑞检测设备有限公司 | 无菌实验室规划装修设计-一体化实验室承包-北京洁净净化工程建设施工-北京航天科恩实验室装备工程技术有限公司 | 北京发电车出租-发电机租赁公司-柴油发电机厂家 - 北京明旺盛安机电设备有限公司 | 剪刃_纵剪机刀片_分条机刀片-南京雷德机械有限公司 | 工业CT-无锡璟能智能仪器有限公司 | 宿舍管理系统_智慧园区系统_房屋/房产管理系统_公寓管理系统 | 油缸定制-液压油缸厂家-无锡大鸿液压气动成套有限公司 | 二次元影像仪|二次元测量仪|拉力机|全自动影像测量仪厂家_苏州牧象仪器 | 皮带机_移动皮带机_大倾角皮带机_皮带机厂家 - 新乡市国盛机械设备有限公司 | 西宁装修_西宁装修公司-西宁业之峰装饰-青海业之峰墅级装饰设计公司【官网】 | 屏蔽泵厂家,化工屏蔽泵_维修-淄博泵业| 二手Sciex液质联用仪-岛津气质联用仪-二手安捷伦气质联用仪-上海隐智科学仪器有限公司 | 电杆荷载挠度测试仪-电杆荷载位移-管桩测试仪-北京绿野创能机电设备有限公司 | 湖州织里童装_女童男童中大童装_款式多尺码全_织里儿童网【官网】-嘉兴嘉乐网络科技有限公司 | 制样机-密封锤式破碎机-粉碎机-智能马弗炉-南昌科鑫制样 | 杭州货架订做_组合货架公司_货位式货架_贯通式_重型仓储_工厂货架_货架销售厂家_杭州永诚货架有限公司 | 卷筒电缆-拖链电缆-特种柔性扁平电缆定制厂家「上海缆胜」 | 非小号行情 - 专业的区块链、数字藏品行情APP、金色财经官网 | 免联考国际MBA_在职MBA报考条件/科目/排名-MBA信息网 | 环讯传媒,永康网络公司,永康网站建设,永康小程序开发制作,永康网站制作,武义网页设计,金华地区网站SEO优化推广 - 永康市环讯电子商务有限公司 | 数显恒温油浴-电砂浴-高温油浴振荡器-常州迈科诺仪器有限公司 | 智能风向风速仪,风速告警仪,数字温湿仪,综合气象仪(气象五要素)-上海风云气象仪器有限公司 | 光谱仪_积分球_分布光度计_灯具检测生产厂家_杭州松朗光电【官网】 | 曙光腾达官网-天津脚手架租赁-木板架出租-移动门式脚手架租赁「免费搭设」 | 深圳希玛林顺潮眼科医院(官网)│深圳眼科医院│医保定点│香港希玛林顺潮眼科中心连锁品牌 | 环境模拟实验室_液体-气体控温机_气体控温箱_无锡双润冷却科技有限公司 | 一体化净水器_一体化净水设备_一体化水处理设备-江苏旭浩鑫环保科技有限公司 | 网架支座@球铰支座@钢结构支座@成品支座厂家@万向滑动支座_桥兴工程橡胶有限公司 | 自恢复保险丝_贴片保险丝_力特保险丝_Littelfuse_可恢复保险丝供应商-秦晋电子 | 车间除尘设备,VOCs废气处理,工业涂装流水线,伸缩式喷漆房,自动喷砂房,沸石转轮浓缩吸附,机器人喷粉线-山东创杰智慧 | 玻璃钢格栅盖板|玻璃钢盖板|玻璃钢格栅板|树篦子-长沙川皖玻璃钢制品有限公司 | 培训中心-海南香蕉蛋糕加盟店技术翰香原中心官网总部 | CPSE安博会| 粒米特测控技术(上海)有限公司-测功机_减速机测试台_电机测试台 | 设定时间记录电子秤-自动累计储存电子秤-昆山巨天仪器设备有限公司 |