【问题标题】:Why is my A* implementation slower than floodfill?为什么我的 A* 实现比 Floodfill 慢?
【发布时间】:2014-02-09 01:48:10
【问题描述】:

我有一个由 100、100 个图块组成的空白网格。起点是(0,0),目标是(99,99)。瓷砖是 4 路连接。

我的 Floodfill 算法在 30 毫秒内找到最短路径,但我的 A* 实现慢了大约 10 倍。

注意:无论网格或布局的大小如何,A* 始终比我的填充速度慢 (3 - 10 倍)。因为填充很简单,所以我怀疑我在 A* 中缺少某种优化。

这是函数。我使用 Python 的 heapq 来维护一个 f 排序列表。 “图表”包含所有节点、目标、邻居和 g/f 值。

import heapq

def solve_astar(graph):

    open_q = []

    heapq.heappush(open_q, (0, graph.start_point))

    while open_q:

        current = heapq.heappop(open_q)[1]

        current.seen = True # Equivalent of being in a closed queue

        for n in current.neighbours:
            if n is graph.end_point:
                n.parent = current
                open_q = [] # Clearing the queue stops the process

            # Ignore if previously seen (ie, in the closed queue)
            if n.seen:
                continue

            # Ignore If n already has a parent and the parent is closer
            if n.parent and n.parent.g <= current.g:
                continue

            # Set the parent, or switch parents if it already has one
            if not n.parent:
                n.parent = current
            elif n.parent.g > current.g:
                remove_from_heap(n, n.f, open_q)
                n.parent = current

            # Set the F score (simple, uses Manhattan)
            set_f(n, n.parent, graph.end_point)

            # Push it to queue, prioritised by F score
            heapq.heappush(open_q, (n.f, n))

def set_f(point, parent, goal):
    point.g += parent.g
    h = get_manhattan(point, goal)
    point.f = point.g + h

【问题讨论】:

  • 你能告诉我们remove_from_heap吗?这可能是你的瓶颈。
  • @templatetypedef 是heap.remove((f_value, tile)) - 但即使没有删除,它的运行速度也不会明显加快。
  • 堆删除操作以线性时间运行,这可能会完全耗尽您从智能 A* 搜索中获得的所有效率收益。你确定这不是你的问题吗?
  • @templatetypedef 是的,它仍然慢了约 10 倍,即使该函数从未被调用。
  • 你的set_f函数是什么?也许你的启发式不好?

标签: python path-finding a-star flood-fill


【解决方案1】:

这是一个决胜局的问题。在一个空网格上,从 (0,0) 到 (99,99) 会生成许多具有相同 f 值的图块。

通过向启发式方法添加微小的推动,将首先选择稍微靠近目的地的图块,这意味着可以更快地达到目标并且需要检查的图块更少。

def set_f(point, parent, goal):
    point.g += parent.g
    h = get_manhattan(point, goal) * 1.001
    point.f = point.g + h

这导致了大约 100 倍的改进,比 Floodfill 快得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    • 2011-09-26
    • 2013-02-22
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多