返回顶部
首页 > 资讯 > 后端开发 > Python >python实现A*寻路算法
  • 424
分享到

python实现A*寻路算法

pythonA*寻路算法pythonA*算法 2022-06-02 22:06:29 424人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录A* 算法简介关键代码介绍保存基本信息的地图类搜索到的节点类算法主函数介绍代码的初始化完整代码A* 算法简介 A* 算法需要维护两个数据结构:OPEN 集和 CLOSED 集。OPEN 集包含所有已搜索到的待检测

目录
  • 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 = width
    		self.height = height
    		self.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 = x
    		self.y = y
    		# cost move fORM start entry to this entry
    		self.g_cost = g_cost
    		self.f_cost = f_cost
    		self.pre_entry = pre_entry
    	
    	def 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] = location
    	while True:
    		location = getFastPosition(openlist)
    		if location is None:
    			# not found valid path
    			print("can't find valid path")
    			break;
    		
    		if location.x == dest.x and location.y == dest.y:
    			break
    		
    		closedlist[location.getPos()] = location
    		openlist.pop(location.getPos())
    		addAdjacentPositions(map, location, dest, openlist, closedlist)
    	
    	#mark the found path at the map
    	while location is not None:
    		map.map[location.y][location.x] = 2
    		location = location.pre_entry
    

    我们按照算法主循环的实现来一个个讲解用到的函数。
    下面函数就是从OPEN集中获取一个F值最小的节点,如果OPEN集会空,则返回None。

    
    	# find a least cost position in openlist, return None if openlist is empty
    	def getFastPosition(openlist):
    		fast = None
    		for entry in openlist.values():
    			if fast is None:
    				fast = entry
    			elif fast.f_cost > entry.f_cost:
    				fast = entry
    		return fast
    

    addAdjacentPositions 函数对应算法主函数循环介绍中的尝试添加节点n的所有邻节点n'。

    
    	# add available adjacent positions
    	def addAdjacentPositions(map, location, dest, openlist, closedlist):
    		poslist = getPositions(map, location)
    		for pos in poslist:
    			# if position is already in closedlist, do nothing
    			if 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 openlist
    					openlist[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 position
    					findEntry.g_cost = g_cost
    					findEntry.f_cost = g_cost + h_cost
    					findEntry.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 None
    		return (x, y)
    		
    	def getPositions(map, location):
    		# use four ways or eight ways to move
    		offsets = [(-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 list
    	def isInList(list, pos):
    		if pos in list:
    			return list[pos]
    		return None
    

    calHeuristic 函数简单得使用了曼哈顿距离,这个后续可以进行优化
    getMoveCost 函数根据是否是斜向移动来计算消耗(斜向就是2的开根号,约等于1.4)

    
    	# imporve the heuristic distance more precisely in future
    	def 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.4
    		else:
    			return 1
    

    代码的初始化

    可以调整地图的长度,宽度和不可移动节点的数目。
    可以调整开始节点和目标节点的取值范围。

    
    WIDTH = 10
    HEIGHT = 10
    BLOCK_NUM = 15
    map = 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的节点表示找到的路径。

    在这里插入图片描述

    完整代码

    使用python3.7编译

    
    from random import randint
    
    class SearchEntry():
    	def __init__(self, x, y, g_cost, f_cost=0, pre_entry=None):
    		self.x = x
    		self.y = y
    		# cost move form start entry to this entry
    		self.g_cost = g_cost
    		self.f_cost = f_cost
    		self.pre_entry = pre_entry
    	
    	def getPos(self):
    		return (self.x, self.y)
    
    class Map():
    	def __init__(self, width, height):
    		self.width = width
    		self.height = height
    		self.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] = 1
    	
    	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)
    
    	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 None
    		return (x, y)
    		
    	def getPositions(map, location):
    		# use four ways or eight ways to move
    		offsets = [(-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 future
    	def 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.4
    		else:
    			return 1
    
    	# check if the position is in list
    	def isInList(list, pos):
    		if pos in list:
    			return list[pos]
    		return None
    	
    	# add available adjacent positions
    	def addAdjacentPositions(map, location, dest, openlist, closedlist):
    		poslist = getPositions(map, location)
    		for pos in poslist:
    			# if position is already in closedlist, do nothing
    			if 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 openlist
    					openlist[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 position
    					findEntry.g_cost = g_cost
    					findEntry.f_cost = g_cost + h_cost
    					findEntry.pre_entry = location
    	
    	# find a least cost position in openlist, return None if openlist is empty
    	def getFastPosition(openlist):
    		fast = None
    		for entry in openlist.values():
    			if fast is None:
    				fast = entry
    			elif fast.f_cost > entry.f_cost:
    				fast = entry
    		return fast
    
    	openlist = {}
    	closedlist = {}
    	location = SearchEntry(source[0], source[1], 0.0)
    	dest = SearchEntry(dest[0], dest[1], 0.0)
    	openlist[source] = location
    	while True:
    		location = getFastPosition(openlist)
    		if location is None:
    			# not found valid path
    			print("can't find valid path")
    			break;
    		
    		if location.x == dest.x and location.y == dest.y:
    			break
    		
    		closedlist[location.getPos()] = location
    		openlist.pop(location.getPos())
    		addAdjacentPositions(map, location, dest, openlist, closedlist)
    		
    	#mark the found path at the map
    	while location is not None:
    		map.map[location.y][location.x] = 2
    		location = location.pre_entry	
    
    	
    WIDTH = 10
    HEIGHT = 10
    BLOCK_NUM = 15
    map = 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*寻路算法内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

    --结束END--

    本文标题: python实现A*寻路算法

    本文链接: https://lsjlt.com/news/10923.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • python实现A*寻路算法
      目录A* 算法简介关键代码介绍保存基本信息的地图类搜索到的节点类算法主函数介绍代码的初始化完整代码A* 算法简介 A* 算法需要维护两个数据结构:OPEN 集和 CLOSED 集。OPEN 集包含所有已搜索到的待检测...
      99+
      2022-06-02
      python A*寻路算法 python A*算法
    • 如何用C++实现A*寻路算法
      目录一、A*算法介绍二、A*算法步骤解析三、A*算法优化思路3.1、openList使用优先队列(二叉堆)3.2、障碍物列表,closeList 使用二维表(二维数组)3.3、深度限...
      99+
      2024-04-02
    • java寻路算法怎么实现
      Java中的寻路算法可以使用图的搜索算法来实现。以下是一个简单的示例,使用BFS(广度优先搜索)算法来寻找路径。```javaimp...
      99+
      2023-09-22
      java
    • C#中Astar寻路算法怎么实现
      以下是一种基本的A*寻路算法的实现示例,可以用于C#语言:```csharpusing System;using System.Co...
      99+
      2023-09-22
      C#
    • js中A*寻路算法原理的示例分析
      这篇文章主要为大家展示了“js中A*寻路算法原理的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“js中A*寻路算法原理的示例分析”这篇文章吧。简易地图如...
      99+
      2024-04-02
    • C++ DFS算法实现走迷宫自动寻路
      C++ DFS算法实现走迷宫自动寻路,供大家参考,具体内容如下 深度优先搜索百度百科解释: 事实上,深度优先搜索属于图算法的一种,英文缩写为DFS即Depth First Searc...
      99+
      2024-04-02
    • C# AStar寻路算法详解
      目录概述思路代码示例位置定义方向定义估值函数节点定义算法上下文定义寻路算法初始化获取路径寻路完整代码概述 AStar算法是一种图形搜索算法,常用于寻路。他是以广度优先搜索为基础,集D...
      99+
      2023-05-14
      C# AStar寻路算法 C# A*寻路算法 C# 寻路算法
    • C++ DFS算法如何实现走迷宫自动寻路
      小编给大家分享一下C++ DFS算法如何实现走迷宫自动寻路,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!C++ DFS算法实现走迷宫自动寻路,供大家参考,具体内容...
      99+
      2023-06-15
    • Python实现迷宫自动寻路实例
      目录背景预处理寻路算法测试优化绘制路径结语背景 我打开手机,发现有人在QQ空间里叫嚣。 看他得意的样子,显然是在家里呆久了,已经忘了天有多高。 预处理 设计一个迷宫自动寻路算法并不...
      99+
      2024-04-02
    • C# AStar寻路算法怎么使用
      这篇文章主要讲解了“C# AStar寻路算法怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C# AStar寻路算法怎么使用”吧!概述AStar算法是一种图形搜索算...
      99+
      2023-07-05
    • C++ 基于BFS算法的走迷宫自动寻路的实现
      目录1.效果图2.实现代码1.队列方法类2.地图方法类3.main函数3.思路1.效果图 其中正方形代表障碍物,实心菱形代表移动者(人),空心菱形代表目标位置(都是可以在代码中修改...
      99+
      2024-04-02
    • A*算法求解八数码难题(python实现)
      目录 文章目录 前言 一、八数码难题是什么? 二、算法详解 1.启发函数(曼哈顿距离) 2.状态移动处理 3. A*搜索并返回路径  三、完整代码(注释很详尽) 总结 前言         本文用python实现A*...
      99+
      2023-10-27
      python 算法 人工智能
    • Python实现随机生成迷宫并自动寻路
      目录Python深搜版:Python 广搜版lua版:Python深搜版: 核心在于带随机的深搜(见代码第23到27行,其实也可以用22行代替这几行代码,你可以试着把第24行的数字4改大或者改小,即调整随机程度) ...
      99+
      2022-06-02
      Python随机生成迷宫 Python 迷宫自动寻路
    • 【路径规划】全局路径规划算法——蚁群算法(含python实现)
      文章目录 参考资料1. 简介2. 基本思想3. 算法精讲4. 算法步骤5. python实现 参考资料 路径规划与轨迹跟踪系列算法蚁群算法原理及其实现蚁群算法详解(含例程)图说蚁群算法(A...
      99+
      2023-09-22
      算法 启发式算法 自动驾驶 路径规划
    • Python:实现A*搜索算法(含完整源代码)
      Python:实现A*搜索算法(含完整源代码) A*(也称为A星)搜索算法是一种常用的寻路算法。该算法在解决路径规划问题时表现出色,因为它能够找到最短路径并避免遍历那些不必要的节点。本文将介绍如何使用...
      99+
      2023-10-18
      python
    • 学习Python中A*算法实现的详细步骤
      以此加权图为例,用Python实现A*算法。加权图中的节点用粉红色圆圈表示,并且给出了沿节点的路径的权重。节点上方的数字代表节点的启发式值。 首先为算法创建类。一个用于存储与起始节点的距离,另一个用于存储父节点。并将它们初始化...
      99+
      2024-01-23
    • 【路径规划】局部路径规划算法——DWA算法(动态窗口法)|(含python实现 | c++实现)
      文章目录 参考资料1. DWA算法原理1.1 简介1.2 算法原理1. 速度采样2. 轨迹预测(轨迹推算)3. 轨迹评价 2. Python实现2.1 参数配置2.2 机器人运动学模...
      99+
      2023-08-31
      python 机器人 路径规划 DWA 动态窗口法
    • Java编程如何实现A*算法
      这篇文章主要介绍了Java编程如何实现A*算法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。本文实例代码结构:% % % % %&nb...
      99+
      2023-05-30
      java
    • 【路径规划】(2) A* 算法求解最短路,附python完整代码
      大家好,今天和各位分享一下机器人路径规划中非常经典的 A* 算法,感兴趣的点个关注,文末有 python 代码,那我么开始吧。 1. 算法介绍 A* 算法是 1968 年 P.E.Hart[1]等人所提出的在全局地图环境中所有已知情形下求...
      99+
      2023-10-18
      python A star 路径规划 机器人运动 路径选择
    • 【路径规划】局部路径规划算法——人工势场法(含python实现 | c++实现)
      文章目录 参考资料1. 算法简介2. 算法精讲2.1 引力势场2.2 斥力势场2.3 合力势场 3. 引力斥力推导计算4. 算法缺陷与改进4.1 目标不可达的问题4.2 陷入局部最优的问题...
      99+
      2023-09-01
      算法 自动驾驶 路径规划 人工势场 python
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作