分享

<font style="vertical-align: inherit;"><font style="vertical-align: inherit;

 羊玉wngbx 2021-08-13

波束搜索#

在主 A* 循环中,OPEN 集存储可能需要搜索以找到路径的所有节点。束搜索是A的变化*这就使开集的大小有限制。如果该集合变得太大,则具有最坏机会提供良好路径的节点将被丢弃。一个缺点是你必须保持你的集合排序才能做到这一点,这限制了你选择的数据结构的种类。

迭代深化#

迭代深化是许多 AI 算法中使用的一种方法,从近似答案开始,然后使其更准确。这个名字来自博弈树搜索,在那里你可以向前看一些移动(例如,在国际象棋中)。您可以尝试通过向前看更多动作来加深树。一旦你的答案没有太大变化或改进,你就认为你有一个很好的答案,当你再次尝试使它更准确时,它也不会改进。在 IDA* 中,“深度”是f的临界值。f值太大时,节点甚至不会被考虑(即,它不会被添加到 OPEN 集)。第一次通过您处理很少的节点。每次后续传递,您都会增加访问的节点数。如果你发现路径有所改善,那么你继续增加截止;否则,您可以停止。有关更多详细信息,请阅读IDA* 上的这些讲座节点

我个人认为 IDA* 不需要在游戏地图上寻找路径。ID 算法往往会增加计算时间,同时减少内存需求。然而,在地图寻路中,“节点”非常小——它们只是坐标。我不认为不存储这些节点有什么大的好处。

加权 A*#

在游戏中,我们经常将启发式乘以某个常数因子以使 A* 运行得更快。这就是所谓的在文献中。我们可以使用一些权重w> 1(例如,1.5 或 2.0)来增加启发式的效果:

f(p) = g(p) + w * h(p)

在大多数情况下,这在实践似乎运作良好Wilt 和 Ruml 的 AAAI 2012 论文何时加权 A* 失败?显示了一些没有的情况。

另一种思考方式是 Dijsktra's Algorithm 仅使用 ,g而 Greedy Best First Search 仅使用h权重是在这两种算法之间平滑插值的一种方式,其中权重为 0 表示 Dijkstra 算法,权重为 ∞ 表示贪婪最佳优先搜索。权重 1.0 介于两个极端之间,给出 A*。加权 A* 介于 A* 和贪婪最佳优先搜索之间。

如果仅在路径的某些部分或地图的某些部分启发式太低,我们可以使用动态加权

f(p) = g(p) + w(p) * h(p)

有很多方法可以改变权重,但我在 1997 年写这些页面时并没有探索这个主题。当时我的直觉让我相信在接近开始时使用更高的权重会更好路径和接近终点的较低权重。那是因为我认为权重补偿了启发式太低,并且通常在路径开始时太低并且在路径末尾附近相当准确。然而,研究表明我的直觉是错误的。最好在路径的尽头附近施加重量。

Chen 和 Sturvetant 的 AAAI 2021 论文Necessary and Suffient Conditions for avoiding Reopenings in Best First Suboptimal Search with General Bounding Functions提出了两种方法pxWU,当您接近目标时,它会降低权重:

f(p) = g(p) < (2*w - 1) * h(p) ? g(p) / (2*w - 1) + h(p) : (g(p) + h(p)) / w

pxWD,当您接近目标时会增加重量:

f(p) = g(p) < h(p) ? g(p) + h(p) : (g(p) + (2*w - 1) * h(p)) / w}

他们发现增加重量效果更好。他们还有一个交互式演示,您可以在其中尝试不同的加权方案。

带宽搜索#

有些人可能会发现有关带宽搜索的两个属性很有用。这种变化假设这h是一个高估,但它不会高估超过某个数字e如果您的搜索是这种情况,那么您获得的路径的成本不会超过最佳路径的成本多于e再一次,你的启发式方法越好,你的解决方案就会越好。

您获得的另一个属性是,如果您可以删除 OPEN 集中的某些节点。只要h+d大于路径的真实成本(对于某些d),您就可以删除其f值至少e+d高于fOPEN 中最佳节点值的任何节点。这是一个奇怪的属性。你有一个良好价值的“带” f该频带之外的所有内容都可以丢弃,因为可以保证它不会在最佳路径上。

奇怪的是,您可以对这两个属性使用不同的启发式方法,结果仍然有效。您可以使用一种启发式方法来保证您的路径不会太糟糕,而另一种方法来确定要在 OPEN 集中删除什么。

注意:当我在 1997 年写这篇文章时,带宽搜索看起来可能很有用,但我从未使用过它,而且我在游戏行业也没有看到太多关于它的文章,所以我可能会删除这一部分。您可以在Google搜索更多信息,尤其是从教科书中搜索。

双向搜索#

您可以并行开始两次搜索,而不是从头到尾搜索——一次从头到尾,一次从头到尾。当他们相遇时,你应该有一个好的路径。

这是一个好主意,在某些情况下会有所帮助。双向搜索背后的想法是搜索结果在地图上呈扇形散开的“树”。一棵大树比两棵小树差很多,所以最好有两棵小搜索树。

前到前变化的两个搜索链接在一起。该算法不是选择最佳的前向搜索节点g(start,x) + h(x,goal)——或者最佳的反向搜索节点g(y,goal) + h(start,y)——而是选择具有最佳的一对节点g(start,x) + h(x,y) + g(y,goal)

重新定位方法在退让向前和向后方向上同时搜索。相反,它执行短时间的前向搜索,选择最佳的前向候选者,然后执行后向搜索——不是到起点,而是到那个候选者。一段时间后,它会选择一个最佳的后向候选,并执行从最佳前向候选到最佳后向候选的前向搜索。这个过程一直持续到两个候选人是同一点。

Holte、Felner、Sharon、Sturtevant 的 2016 年论文Front-to-End Bidirectional Heuristic Search with Near-Optimal Node Expansions是最近的结果,其中包含 A* 的近乎最优的双向变体。Pijls 和 Post 的 2009 年论文最短路径的另一种双向算法提出了一种不平衡的双向 A*,它比平衡的双向搜索运行得更快。

动态 A* 和终身规划 A*#

有 A* 的变体允许在计算初始路径后改变世界。D* 旨在在您没有完整信息时使用。如果您没有所有信息,A* 可能会出错;D* 的贡献在于它可以在不花费太多时间的情况下纠正这些错误。LPA* 旨在在成本发生变化时使用。使用 A*,路径可能因地图更改而失效;LPA* 可以重用之前的 A* 计算来生成新路径。

然而,D* 和 LPA* 都需要大量空间——本质上你运行 A* 并保留它的内部信息(OPEN/CLOSED集合、路径树、g值),然后当映射发生变化时,D* 或 LPA* 会告诉你您需要调整路径以将地图更改考虑在内。

对于具有大量移动单位的游戏,您通常不想保留所有这些信息,因此 D* 和 LPA* 不适用。它们是为只有一个机器人的机器人设计的——你不需要为其他机器人的路径重用内存。如果您的游戏只有一个或少量单位,您可能需要调查 D* 或 LPA*。

跳转点搜索#

许多加速 A* 的技术实际上都是关于减少节点数量。在具有统一成本的方形网格中,一次查看所有单个网格空间是一种浪费。一种方法是构建关键点(例如角点)的图形并将其用于寻路。但是,您不想预先计算航点图,请查看 Jump Point Search,这是 A* 的一种变体,可以在方形网格上向前跳过。当考虑当前节点的子节点可能包含在 OPEN 集中时,跳转点搜索会向前跳到从当前节点可见的远处节点。每一步都更昂贵,但它们的数量更少,从而减少了 OPEN 集中的节点数量。有关详细信息,请参阅此博客文章此博客文章以获得很好的视觉解释,以及这个关于利弊的讨论

另请参阅Rectangular Symmetry Reduction,它分析地图并将跳转嵌入到图形本身中这两种技术都是为方形网格开发的。这是为六边形网格扩展的算法

θ*#

有时网格用于寻路是因为地图是在网格上制作的,而不是因为您实际上想要在网格上移动。如果给定关键点(例如角)图而不是网格,A* 会运行得更快并产生更好的路径。但是,如果您不想预先计算角点图,则可以使用 Theta*(在方形网格上运行的 A* 的变体)来查找不严格遵循网格的路径。在构建指针时,如果有到该节点的视线,Theta* 将直接指向祖先,并跳过其间的节点。路径平滑不同,它在 A* 找到路径后将路径弄直,Theta* 可以将这些路径分析为 A* 过程的一部分。这可能导致比将网格路径后处理为任意角度路径更短的路径。这篇文章是对算法的合理介绍;另请参阅Lazy Theta*

Theta* 的想法也可能适用于导航网格。

另请参阅Block A*,它声称通过使用分层方法比 Theta* 快得多。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多