python 实现双向A*算法

双向A*算法介绍

双向A算法(Bidirectional A)是A算法的一种改进,它旨在通过同时从起点和终点两个方向进行搜索来减少搜索空间,从而提高搜索效率。以下是对双向A算法的详细解释:

基本原理

双向A*算法在搜索过程中,从起点开始,使用启发式函数(如曼哈顿距离或欧几里得距离)来评估节点,并朝着终点方向进行搜索;同时,从终点开始,也以起点为目标,使用相同的启发式函数进行搜索。两个方向的搜索同时进行,直到它们在某个节点相交,从而找到一条从起点到终点的路径。

算法步骤

1、初始化:

设定起点和终点。
为起点和终点分别初始化启发式函数值(即估计从起点到终点的距离)。
初始化两个优先级队列(通常使用最小堆实现),一个用于存放从起点开始搜索的节点,另一个用于存放从终点开始搜索的节点。

2、搜索过程:

在每一步中,从两个优先级队列中分别选择f值(f = g + h,其中g是从起点或终点到当前节点的实际代价,h是当前节点到目标节点的估计代价)最小的节点进行扩展。
对于每个被扩展的节点,计算其g值、h值和f值,并更新其邻居节点的信息(如果邻居节点的f值或g值得到改进)。
检查两个搜索方向是否有节点相交,即检查是否有节点同时出现在两个搜索队列中。如果相交,则找到了一条从起点到终点的路径,算法结束。

3、回溯路径:

一旦找到相交节点,从该节点开始,分别向起点和终点回溯,收集路径上的节点,直到达到起点和终点。

4、终止条件:

如果两个搜索队列都为空,且没有找到相交节点,则表明起点和终点之间不存在可达路径。

优势

减少搜索空间:通过同时从起点和终点搜索,双向A算法能够显著减少需要搜索的节点数量,特别是在图的规模较大时。
提高搜索效率:由于减少了搜索空间,双向A
算法通常能够更快地找到最短路径。

应用场景

双向A*算法特别适用于需要高效解决大规模图搜索问题的场景,如地图导航、游戏路径规划等。

注意事项

在实现双向A*算法时,需要特别注意处理节点相交的情况,以避免重复计算或遗漏路径。
启发式函数的选择对算法的性能有很大影响,因此需要根据具体问题选择合适的启发式函数。

双向A*算法python实现样例

下面是一个简单的Python实现双向A*算法的示例代码:

import heapq

# 定义节点类
class Node:
    def __init__(self, x, y, parent=None, g=float('inf'), f=float('inf')):
        self.x = x
        self.y = y
        self.parent = parent
        self.g = g
        self.f = f

    def __lt__(self, other):
        return self.f < other.f

# 定义启发函数
def heuristic(node, target):
    return abs(node.x - target.x) + abs(node.y - target.y)

# 定义双向A*算法函数
def bidirectional_a_star(start, end, obstacles, grid_size):
    open_list_start = [start]
    open_list_end = [end]
    closed_list_start = {}
    closed_list_end = {}

    while open_list_start and open_list_end:
        # 从起点开始搜索
        current_start = heapq.heappop(open_list_start)
        closed_list_start[(current_start.x, current_start.y)] = current_start

        # 判断搜索是否完成
        if (current_start.x, current_start.y) in closed_list_end:
            path = []
            node = current_start
            while node:
                path.append((node.x, node.y))
                node = node.parent
            node = closed_list_end[(current_start.x, current_start.y)]
            while node:
                path.insert(0, (node.x, node.y))
                node = node.parent
            return path

        # 扩展搜索
        for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            nx = current_start.x + dx
            ny = current_start.y + dy

            if nx < 0 or nx >= grid_size[0] or ny < 0 or ny >= grid_size[1] or (nx, ny) in closed_list_start or (nx, ny) in obstacles:
                continue

            g = current_start.g + 1
            f = g + heuristic(Node(nx, ny), end)
            node = Node(nx, ny, current_start, g, f)
            
            if node in open_list_start:
                if g < node.g:
                    open_list_start.remove(node)
                else:
                    continue

            heapq.heappush(open_list_start, node)

        # 从终点开始搜索
        current_end = heapq.heappop(open_list_end)
        closed_list_end[(current_end.x, current_end.y)] = current_end

        # 判断搜索是否完成
        if (current_end.x, current_end.y) in closed_list_start:
            path = []
            node = closed_list_start[(current_end.x, current_end.y)]
            while node:
                path.append((node.x, node.y))
                node = node.parent
            node = current_end
            while node:
                path.insert(0, (node.x, node.y))
                node = node.parent
            return path

        # 扩展搜索
        for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            nx = current_end.x + dx
            ny = current_end.y + dy

            if nx < 0 or nx >= grid_size[0] or ny < 0 or ny >= grid_size[1] or (nx, ny) in closed_list_end or (nx, ny) in obstacles:
                continue

            g = current_end.g + 1
            f = g + heuristic(Node(nx, ny), start)
            node = Node(nx, ny, current_end, g, f)
            
            if node in open_list_end:
                if g < node.g:
                    open_list_end.remove(node)
                else:
                    continue

            heapq.heappush(open_list_end, node)

    return None

# 测试代码
start = Node(0, 0)
end = Node(4, 4)

obstacles = set([(1, 2), (2, 2), (3, 2)])

path = bidirectional_a_star(start, end, obstacles, (5, 5))
print(path)

这是一个简单的双向A*算法实现,其中使用了优先队列来实现open列表,并通过字典来实现closed列表。在搜索过程中,通过启发函数(这里使用的是曼哈顿距离)来计算每个节点的f值,并选择f值最小的节点进行扩展。算法通过两个方向同时进行搜索,当两个搜索方向的节点相遇时,即找到了最短路径。最后返回路径。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luthane

您的鼓励将是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值