A*算法案例

A*算法结合广度优先搜索和启发式搜索,通过启发式函数估计路径成本,使用评估函数指导搜索。文章详细介绍了算法原理、关键步骤如状态扩展和目标检测,以及一个基于网格地图的实际应用示例。
摘要由CSDN通过智能技术生成

A*算法

A算法是一种常用的路径搜索算法,通常用于解决图搜索和图路径问题。它综合了广度优先搜索和启发式搜索的优点,能够在保证最优解的情况下降低搜索空间,从而提高搜索效率。以下是A算法的基本原理:

  1. 启发式函数(Heuristic Function):A*算法使用启发式函数来估计从当前状态到目标状态的代价。启发式函数通常是一个估计函数,它可以根据当前状态的特征来估计到达目标状态的代价。启发式函数通常表示为h(n),其中n是当前状态。
  2. 评估函数(Evaluation Function):A*算法使用评估函数来评估每个候选状态的优先级。评估函数通常表示为f(n),它是从起始状态到目标状态的实际代价的估计值。评估函数通常表示为f(n) = g(n) + h(n),其中g(n)表示从起始状态到当前状态的实际代价,h(n)表示启发式函数的估计值。
  3. 优先队列(Priority Queue):A*算法使用优先队列来存储候选状态,并根据它们的评估函数值(f(n))来选择下一个要扩展的状态。通常情况下,选择评估函数值最小的状态进行扩展。
  4. 状态扩展(State Expansion):A*算法通过扩展当前状态来生成候选状态。对于每个候选状态,算法计算其评估函数值,并将其加入优先队列中。
  5. 目标检测(Goal Detection):当扩展的状态是目标状态时,A*算法结束搜索,并返回找到的路径。

A*算法的关键在于选择合适的启发式函数,它必须能够提供足够的信息来指导搜索朝着目标移动,并且不能过于乐观或过于悲观。如果启发式函数能够准确地估计从当前状态到目标状态的代价,那么A算法就能够在保证最优解的情况下找到最短路径。

  • 以下是一个简单的A*算法案例,用于搜索从起始节点到目标节点的最短路径。在这个案例中,我们假设有一个网格地图,每个节点可以是空地、障碍物或起点/终点。我们的目标是找到从起点到终点的最短路径。
import heapq

# 定义节点类
class Node:
    def __init__(self, row, col, g=0, h=0):
        self.row = row
        self.col = col
        self.g = g  # 从起点到当前节点的实际代价
        self.h = h  # 启发式函数的估计值
        self.f = g + h  # 评估函数的值
        self.parent = None  # 父节点

# 定义A*算法函数
def astar(grid, start, end):
    rows, cols = len(grid), len(grid[0])
    open_set = []  # 开放列表,存放待扩展的节点
    closed_set = set()  # 关闭列表,存放已经扩展过的节点
    heapq.heappush(open_set, (start.f, start))  # 将起始节点放入开放列表
    while open_set:
        current_f, current_node = heapq.heappop(open_set)  # 从开放列表中取出f值最小的节点
        if current_node == end:  # 如果当前节点是目标节点,则返回路径
            path = []
            while current_node:
                path.append((current_node.row, current_node.col))
                current_node = current_node.parent
            return path[::-1]
        closed_set.add(current_node)  # 将当前节点加入关闭列表
        # 扩展当前节点的邻居节点
        for dr, dc in [(1, 0), (-1, 0), (0, 1), (0, -1)]:
            next_row, next_col = current_node.row + dr, current_node.col + dc
            if 0 <= next_row < rows and 0 <= next_col < cols and grid[next_row][next_col] != '#':
                next_node = Node(next_row, next_col)
                if next_node in closed_set:  # 如果邻居节点已经在关闭列表中,则跳过
                    continue
                # 计算邻居节点的g值和h值
                next_node.g = current_node.g + 1
                next_node.h = abs(next_row - end.row) + abs(next_col - end.col)
                next_node.f = next_node.g + next_node.h
                next_node.parent = current_node
                heapq.heappush(open_set, (next_node.f, next_node))  # 将邻居节点放入开放列表
    return None  # 如果开放列表为空且没有找到目标节点,则返回None

# 测试
grid = [
    ['#', '#', '#', '#', '#', '#', '#', '#', '#'],
    ['#', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '#'],
    ['#', ' ', '#', '#', '#', '#', '#', ' ', '#'],
    ['#', ' ', '#', ' ', '#', ' ', ' ', ' ', '#'],
    ['#', ' ', '#', ' ', '#', ' ', '#', ' ', '#'],
    ['#', ' ', '#', ' ', '#', ' ', '#', ' ', '#'],
    ['#', ' ', '#', ' ', '#', ' ', '#', ' ', '#'],
    ['#', ' ', '#', '#', '#', '#', '#', ' ', '#'],
    ['#', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '#'],
    ['#', '#', '#', '#', '#', '#', '#', '#', '#']
]
start = Node(1, 1)
end = Node(8, 7)
path = astar(grid, start, end)
if path:
    print("最短路径为:", path)
else:
    print("无法到达目标节点")

在这个案例中,我们首先定义了一个节点类 Node,表示网格地图上的一个节点,包括节点的行、列、实际代价g、启发式函数估计值h、评估函数值f和父节点。然后,我们定义了A算法函数 astar,通过在开放列表中选择f值最小的节点来进行状态扩展,并计算每个邻居节点的g值和h值。最后,我们测试了A算法函数,并输出了最短路径。

  • 16
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
A*算法是一种常用的启发式搜索算法,它可以用于求解最短路径问题、迷宫问题等。本文将介绍A*算法的原理、步骤以及实现过程,并给出一个基于A*算法的迷宫问题的实例。 一、A*算法原理 A*算法是一种启发式搜索算法,它通过估计从起点到终点的最小代价来搜索最短路径。在搜索过程中,A*算法不仅考虑当前节点到起点的代价,还考虑当前节点到终点的估计代价。具体来说,A*算法将每个节点的f值定义为: f(n) = g(n) + h(n) 其中,g(n)表示从起点到节点n的实际代价,h(n)表示从节点n到终点的估计代价。A*算法选择f(n)值最小的节点进行扩展,直到找到终点或者所有可达节点都被扩展完毕。 A*算法的优点是能够快速找到最短路径,而且在估计代价函数h(n)正确的情况下,搜索过程相对较快。缺点是需要预先知道终点的位置,并且估计代价函数h(n)的准确性对搜索效率有很大影响。 二、A*算法步骤 1.定义节点类及估价函数 定义一个节点类,包含节点坐标、g值、f值、父节点等属性。同时,需要定义一个估价函数h(n),用于估计从节点n到终点的代价。估价函数需要满足以下条件: - h(n) >= 0 - h(n) = 0 当且仅当 n 是终点 - h(n) 是可行的,即 h(n)<=从n到终点的实际代价 2.初始化起点和终点 将起点和终点加入open表中,起点的g值为0,f值为h(起点)。 3.循环搜索 重复以下步骤,直到找到终点或者open表为空: - 从open表中选择f值最小的节点n,将其从open表中删除,并将其加入close表中。 - 如果n是终点,则搜索结束,返回路径。 - 否则,扩展节点n的邻居节点m。 - 对于每个邻居节点m,计算其g值和f值,更新其父节点为n。 - 如果m在open表中,则比较m原来的f值和新计算的f值,选择较小的更新到open表中。 - 如果m在close表中,则忽略。 - 如果m既不在open表中也不在close表中,则将其加入open表中,并设置其g值和f值。 4.返回路径 如果搜索到终点,则从终点开始,沿着父节点一直走到起点,得到路径。 三、A*算法实例 以迷宫问题为例,介绍A*算法的实现过程。 1.定义节点类及估价函数 定义节点类Node,包含节点坐标x、y,g值g,f值f,父节点parent等属性。 ```python class Node: def __init__(self, x, y): self.x = x self.y = y self.g = 0 self.f = 0 self.parent = None def h(node, end): return abs(node.x - end.x) + abs(node.y - end.y) ``` 估价函数h(node, end)采用曼哈顿距离,即从节点node到终点end的水平距离和竖直距离之和。 2.初始化起点和终点 假设迷宫大小为10x10,起点为(1, 1),终点为(8, 8)。 ```python start = Node(1, 1) end = Node(8, 8) ``` 3.循环搜索 A*算法的核心是循环搜索,需要不断从open表中选取f值最小的节点进行扩展。在本例中,可以使用列表来实现open表和close表。 ```python open_list = [start] close_list = [] while len(open_list) > 0: # 选取f值最小的节点进行扩展 curr_node = open_list[0] curr_index = 0 for index, node in enumerate(open_list): if node.f < curr_node.f: curr_node = node curr_index = index # 将当前节点从open表中删除,并加入close表中 open_list.pop(curr_index) close_list.append(curr_node) # 到达终点,搜索结束 if curr_node.x == end.x and curr_node.y == end.y: path = [] node = curr_node while node is not None: path.append((node.x, node.y)) node = node.parent return path[::-1] # 反转路径,得到从起点到终点的路径 # 扩展当前节点的邻居节点 neighbors = [] for i, j in [(0, -1), (0, 1), (-1, 0), (1, 0)]: x = curr_node.x + i y = curr_node.y + j if x < 0 or x >= 10 or y < 0 or y >= 10: continue if maze[x][y] == 1: continue node = Node(x, y) neighbors.append(node) # 对于每个邻居节点,计算g值和f值,更新其父节点为当前节点 for neighbor in neighbors: if neighbor in close_list: continue neighbor.g = curr_node.g + 1 neighbor.f = neighbor.g + h(neighbor, end) neighbor.parent = curr_node # 如果邻居节点在open表中,则比较原来的f值和新计算的f值,选择较小的更新到open表中 for open_node in open_list: if neighbor == open_node and neighbor.g > open_node.g: continue open_list.append(neighbor) ``` 4.返回路径 如果搜索到终点,则从终点开始,沿着父节点一直走到起点,得到路径。 ```python path = A_star(maze, start, end) print(path) ``` 完整代码如下: ```python class Node: def __init__(self, x, y): self.x = x self.y = y self.g = 0 self.f = 0 self.parent = None def h(node, end): return abs(node.x - end.x) + abs(node.y - end.y) def A_star(maze, start, end): open_list = [start] close_list = [] while len(open_list) > 0: # 选取f值最小的节点进行扩展 curr_node = open_list[0] curr_index = 0 for index, node in enumerate(open_list): if node.f < curr_node.f: curr_node = node curr_index = index # 将当前节点从open表中删除,并加入close表中 open_list.pop(curr_index) close_list.append(curr_node) # 到达终点,搜索结束 if curr_node.x == end.x and curr_node.y == end.y: path = [] node = curr_node while node is not None: path.append((node.x, node.y)) node = node.parent return path[::-1] # 反转路径,得到从起点到终点的路径 # 扩展当前节点的邻居节点 neighbors = [] for i, j in [(0, -1), (0, 1), (-1, 0), (1, 0)]: x = curr_node.x + i y = curr_node.y + j if x < 0 or x >= 10 or y < 0 or y >= 10: continue if maze[x][y] == 1: continue node = Node(x, y) neighbors.append(node) # 对于每个邻居节点,计算g值和f值,更新其父节点为当前节点 for neighbor in neighbors: if neighbor in close_list: continue neighbor.g = curr_node.g + 1 neighbor.f = neighbor.g + h(neighbor, end) neighbor.parent = curr_node # 如果邻居节点在open表中,则比较原来的f值和新计算的f值,选择较小的更新到open表中 for open_node in open_list: if neighbor == open_node and neighbor.g > open_node.g: continue open_list.append(neighbor) return None # 迷宫问题实例 maze = [ [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 1, 1, 0, 1, 1, 0], [0, 1, 0, 1, 0, 0, 0, 0, 1, 0], [0, 1, 0, 1, 0, 1, 1, 1, 1, 0], [0, 1, 0, 1, 0, 0, 0, 0, 1, 0], [0, 1, 0, 1, 1, 1, 0, 1, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], ] start = Node(1, 1) end = Node(8, 8) path = A_star(maze, start, end) print(path) ``` 输出结果为: ``` [(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (6, 2), (7, 2), (8, 2), (8, 3), (8, 4), (8, 5), (8, 6), (8, 7), (8, 8)] ``` 表示从起点(1, 1)到终点(8, 8)的最短路径为[(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (6, 2), (7, 2), (8, 2), (8, 3), (8, 4), (8, 5), (8, 6), (8, 7), (8, 8)]。 四、总结 A*算法是一种常用的启发式搜索算法,可以用于求解最短路径问题、迷宫问题等。A*算法通过估计从起点到终点的最小代价来搜索最短路径,具有快速找到最短路径的优点。在实现A*算法时,需要定义节点类及估价函数,同时使用open表和close表来辅助搜索。在估价函数h(n)正确的情况下,A*算法的搜索过程相对较快,但需要预先知道终点的位置,并且估计代价函数h(n)的准确性对搜索效率有很大影响。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值