【原文翻译】Near Optimal Hierarchical Path-Finding

Near Optimal Hierarchical Path-Finding

近似最优的分层路径搜索

image-20240229160758865

Abstract

商业计算机游戏中的路径搜索问题必须实时解决,而且往往受到内存和 CPU 资源的限制。使用 A* 等搜索算法确定路径所需的计算量会随着搜索空间的增大而增加。因此,在大型地图上寻路会导致严重的性能瓶颈。

本文介绍了 HPA* (Hierarchical Path-Finding A*),一种在网格地图上降低寻路问题复杂性的分层方法。该技术将地图抽象为相互关联的局部群组。在局部层面,预先计算并缓存穿越每个簇的最佳距离。在全局层面上,簇的穿越只需一大步。层次结构可以扩展到两级以上。小的聚类被组合在一起,形成较大的聚类。计算所有聚类的交叉距离时,会使用为包含的较小聚类计算的距离。

我们的方法是自动的,不依赖于特定的拓扑结构。在不使用特定领域知识的情况下,我们成功地处理了随机地图和真实游戏地图。我们的问题分解方法在环境不断变化的领域中效果非常好。该技术还具有简单和易于实现的优点。如果需要,还可以插入更复杂的领域专用算法,以提高性能。

实验结果表明,搜索工作量大大减少。与高度优化的 A* 相比,HPA* 的搜索速度最多可提高 10 倍,同时搜索到的路径与最优路径的差距不超过 1%。

1 Introduction

商业计算机游戏中的路径选择问题必须实时解决,而且往往受到内存和 CPU 资源的限制。分层搜索被认为是降低这一问题复杂性的有效方法。然而,目前还没有关于商业游戏中分层路径搜索的详细研究报告。部分原因是游戏公司通常不会公开他们的想法和源代码。

行业标准是使用 A* [10]或迭代深化 A* ,即 IDA* [3]。A* 通常速度更快,但 IDA* 使用的内存更少。这些算法有许多增强功能,可使其运行更快或探索更小的搜索树。对于许多应用,特别是那些有多个移动 NPC 的应用(如在实时战略游戏中),这些时间和/或空间要求是限制因素。

本文介绍了在网格地图上进行分层路径搜索的新方法 HPA*,并进行了性能测试。我们的技术将地图抽象为相互关联的局部集群。==在局部层面上,我们预先计算并缓存了穿越簇的最佳距离。==在全局层面上,我们的行动是一步跨越一个簇,而不是移动到相邻的原子位置。

我们的方法简单、易于实现,而且通用,因为我们不使用任何应用特殊知识,应用该技术时也不受地图属性的影响。我们可以处理成本可变的地形和各种拓扑类型,如森林、带有任何形状障碍物的开阔区域或建筑物内部,而无需对实施进行任何更改。

对于许多实时路径搜索应用来说,并不需要完整的路径。通常只要知道有效路径的前几段就足够了,这样移动装置就能开始朝正确方向移动。随后发生的事件可能会导致移动装置不得不改变计划,从而不再需要路径的其余部分。A* 返回完整的路径。相比之下,HPA* 返回的是由子问题组成的完整路径。第一个子问题可以求解,让单位沿着路径走几步。根据需要,可以解决后续子问题,提供更多的移动。这样做的好处是,如果单位不得不改变计划,那么就不用浪费精力去计算通往前一个节点的路径,而这是根本不需要的。

分层框架适用于静态和动态变化的环境。在后一种情况下,==首先假设不动的拓扑元素会发生局部变化(例如,a bomb 破坏了 a bridge)。==我们在本地计算从被修改的集群中提取的信息,并保持框架的其他部分不变。其次,假设地图上有多个移动单元,计算出的路径可能会被另一个单元阻塞。我们将以较小的代价计算出一条抽象路径,而无需花费额外的精力将其还原为底层表示。我们会迅速让角色朝好的方向移动,并在角色需要时重新指定抽象路径的部分内容。如果路径受阻,我们会从角色的当前位置重新规划另一条抽象路径。

我们方法的层次结构可以有很多层,因此可以扩展到大型问题空间。当问题地图比较大时,可以通过增加层级数来减少搜索工作量,但代价是需要更多的存储空间和预处理时间。

我们的技术会产生次优解,以最优性换取更高的执行性能。在应用 apath-smoothing 程序后,我们的解决方案与最优方案的差距在 1%以内。

1.1 Motivation

考虑从加利福尼亚州洛杉矶乘车前往安大略省多伦多市的问题。具体来说,从洛杉矶的圣莫尼卡大道 1234 号到多伦多的 Yonge 街 4321 号,开车行驶的最短距离是多少?给定一张详细的北美路线图,上面标注了所有道路的行车距离,A* 实现可以计算出最优(最小距离)行车路线。考虑到路线图的庞大规模,这可能是一项昂贵的计算。

当然,人类旅行规划师绝不会在如此低的细节级别上工作。他们要解决三个问题:

  1. 从圣莫尼卡大道 1234 号前往通往洛杉矶以外的主要高速公路。

  2. 规划从洛杉矶到多伦多的路线。

  3. 从进入多伦多的高速公路行驶到 Yonge 街 4321 号。

第(1)步和第(3)步需要绘制每个城市的详细路线图。第(2)步可以使用高密度地图,用道路连接城市,抽象出城市内部的所有细节。实际上,人类旅行规划师使用抽象方法快速找到从洛杉矶到多伦多的路线。然而,由于将城市视为黑盒子,这种搜索并不能保证找到最短的路线。例如,虽然在高速公路上行驶可能更快,但对于一些高速公路绕城而过的城市来说,离开高速公路穿过城市可能是更短的路线。当然,这也可能不是更快的路线(城市的车速比高速公路慢),但在这个例子中,我们试图尽量缩短旅行距离。

可以将抽象化提升到更高水平:在州/省一级进行规划。一旦路径到达州界,就计算出州与州之间的最佳路线。知道各州的出入口后,再规划州际路线。同样,这样做也行得通,但可能会产生次优解决方案。

更进一步,抽象到国家层面:从美国到加拿大。显然,抽象到一定程度就会变得非常粗糙,以至于实际上毫无用处。

我们希望在计算机游戏路径搜索中采用类似的抽象策略。我们可以在一张完整的 1000 x 1000 地图上使用 A*,但这意味着一个巨大的搜索空间。将地图上的每个 10 x 10 个区块视为一个城市。现在,我们可以在 100 x 100 个城市的地图上进行搜索。对于每个城市,我们都知道城市的入口以及所有入口对的穿越成本。我们还知道如何在城市之间旅行。这样,问题就简化为三个步骤:

  • 起始节点: 在包含起点节点的区块内,找出通往区块边界的最佳路径。
  • 在区块级(100 x100 个区块)搜索从包含起点节点的区块到包含目标节点的区块的最佳路径。
  • 目标节点: 在包含目标节点的区块内,找出从区块边界到目标的最佳路径。

其结果是,搜索速度大大加快,几乎可以得到最优解。此外,这种抽象与拓扑无关;设计人员无需手动将网格分解为高层次特征,也无需在网格上标注航点。

1.2 Contributions

本文的贡献包括:

  1. HPA*,一种新的分层路径搜索算法(包括伪代码和源代码),该算法与领域无关,可很好地用于静态和动态地形拓扑。
  2. 对各种游戏迷宫(来自 BioWare’sB ALDUR’S GATE)进行分层搜索的实验结果表明,速度提高了 10 倍,而路径质量却下降了 1%。
  3. 一些游戏公司似乎正在使用分层搜索思想的变体,尽管它们的大多数算法细节并不公开。据我们所知,这是在商业电脑游戏领域使用分层 A* 的首次科学研究。

第 2 节简要概述了背景文献。第 3 节介绍了我们的分层 A* 新方法,第 4 节对其性能进行了评估。第 5 节是我们的结论和进一步研究的主题。附录 A 提供了我们算法的伪代码。

2 LiteratureRe view

本节第一部分总结了商业游戏中用于路径定位的分层方法。第二部分回顾了更广泛背景下的相关工作,包括在机器人等其他网格领域的应用。

文献[5]描述了使用两级层次结构进行路径标定的方法。作者只提供了该方法的高分辨率演示。问题地图被抽象成一个个群组,如建筑物中的房间或场地上的方形块。一个抽象动作从入口中间穿过一个房间到达另一个房间。首先,这两种方法都将问题地图划分为方形块等群组。其次,抽象行动都是穿越街区(而不是从一个街区中心到另一个街区中心)。第三,两种技术都将区块入口抽象为一个过渡点(事实上,我们允许一个或两个过渡点)。这两种方法之间也存在显著差异。我们将层次结构扩展到多个抽象层,并以独立于领域的方式进行抽象。我们还预先计算并缓存了区块交叉的最佳距离,从而降低了在线计算的成本。

另一种重要的分层方法是利用可见度点(point of visibility)来进行商业游戏的路径定位[6]。对于每个节点,都会为从当前节点可以看到的所有节点添加边(即可以用直线连接的节点)。

当障碍物数量较少且形状为正多边形(如建筑物内部)时,这种方法尤其有用。当障碍物数量较多且/或其形状不是正多边形时,该方法的有效性就会降低。考虑一下包含森林的地图,森林是小尺寸障碍物的密集集合。用可见度点来模拟这种顶部结构,会产生一个具有短边的图形(就节点和边的数量而言)。因此,就无法有效利用在单步中进行长距离行进的关键想法。当问题地图包含凹形或曲面时,该方法要么性能不佳,要么需要复杂的工程设计才能有效地构建图形。相比之下,我们的方法适用于多种类型的地图,并且不需要复杂的领域分析来进行抽象。

导航网格(又名 NavMesh)是一种强大的抽象技术,适用于二维和三维地图。在二维环境中,这种方法用一组(最小的)凸多边形来覆盖地图的无遮挡区域。[11]中介绍了一种构建接近最优 NavMesh 的方法,这种方法放宽了最小多边形集的条件,构建地图覆盖范围的速度更快。

除了商业电脑游戏,路径标定还应用于许多研究领域。在机器人领域探索过的基于拓扑抽象的路径定位方法与本文描述的工作尤其相关。四叉树[8]已被提出作为进行分层地图分解的方法。这种方法将地图分割成不同大小的方形块,使每个块只包含可行走的单元格或只包含阻塞的单元格。问题地图最初被划分为 4 个块。如果块中同时包含障碍单元和可行走单元,则将其进一步分解为 4 个更小的块,依此类推。在这个抽象框架中,行动就是在两个相邻区块的中心点之间行走。由于智能体总是走在两个区块的中间,因此这种方法会产生次优解。

为了提高求解质量,可以将四叉树扩展为有框四叉树 [1,12]。在有框四叉树中,块的边界以最高分辨率的单元增强。一个动作在任意两个边界单元之间穿过一个块。另一方面,框架四叉树比四叉树占用更多内存。

与四叉树相比,框架四叉树与我们的工作更为相似,因为我们也将区块交叉作为抽象动作。不过,我们并不把区块边界上的所有单元格都视为入口点。通过将一个入口抽象为一个或两个入口点,我们减少了区块入口点的数量。此外,我们的方法允许区块包含障碍物。因此,我们必须计算位于同一区块边界上的入口点之间的最优路径。

在马尔可夫决策过程(MarkovDecision Process,MDP)框架下,多目标路径规划的性能已得到提升[4]。所提出的问题是针对所有地图位置对 (x;y) 有效地学习从 x 到 y 的近似最优策略 (x;y)。需要计算和存储的策略数量是地图单元数的二次方。问题地图上的所有位置都是机场,它们被分配到不同的层次结构中。从 x 到 y 的旅行策略与现实世界中的飞机旅行类似。首先,前往越来越大的机场,直到我们到达一个大到足以与目的地所在区域相连的机场。其次,依次前往更小的机场,直到到达目的地。这种方法与第 1.1 节中概述的策略非常相似。

文献[7]对各种框架中路径搜索的性质进行了分析。作者根据所寻求结果的类型、环境类型、可用信息量等对路径搜索问题进行了分类。文中还讨论了每种问题类型所面临的挑战以及解决策略,如重新规划和使用动态数据结构。

[9]分析了与HPA* 相 似 的最短路径算法的层次方法。该方法将初始问题图分解为片段子图集和连接片段子图的全局边界子图。计算并缓存最短路径供将来使用,这与 HPA* 对集群遍历路径执行的缓存类似。作者分析了应缓存哪些最短路径(即来自哪些子图),以及应保留哪些信息(即完整路径或仅成本),以便在内存有限的情况下获得最佳性能。

与 HPA* 相关的另一种技术是分层 A* [2],它也使用空间的分层表示,目的是减少总体搜索工作量。不过,这两种技术使用层次化表示的方式有所不同。我们的方法使用抽象来构造和增强搜索空间的表示,而分层 A* 是一种自动生成与领域无关的启发式状态评估的方法。在单个代理搜索中,一个能评估从状态到目标之间距离的启发式函数被用来指导搜索过程。这种函数的质量在很大程度上影响着整个搜索算法的质量。从初始空间开始,分层 A* 建立抽象空间的分层,直到得到一个抽象的单状态空间。在建立下一个抽象空间时,当前空间中的几个状态会被组合成下一个空间中的一个抽象状态。在这种层次结构中,一个抽象空间用于计算前一个空间的启发式函数。

3 Hierarchical Path-Finding

我们的分层方法实现了 1.1 节中描述的策略。在我们的分层框架中,搜索抽象解的过程分为三步,即在线搜索。其次,搜索从起始邻域边界到目标邻域边界的路径。这是在抽象层面上进行的,搜索更加简单快捷。第三,完成从目标邻域边界到目标位置的路径。

在线搜索的抽象图是利用从问题迷宫中提取的信息构建的。我们将更详细地讨论如何构建分层搜索框架(预处理)以及如何用于路径遴选(在线搜索)。起初,我们专注于构建两个层次的层次结构:一个低层次和一个抽象层次。本节末尾将讨论如何添加更多的层次。我们将在图 1(a) 所示的 40 40 小地图上演示我们的方法是如何工作的。

image-20240229162103866

3.1 Pre-processing a Grid

构建分层搜索框架的第一步是对迷宫进行顶层抽象。我们利用这种迷宫抽象来构建分层搜索的抽象图。

图 1(b)中的粗线表示用于拓扑抽象的抽象簇。在本例中,40 x 40 个网格被划分为 16 个大小为 10 x 10 的簇。请注意,这种抽象没有使用任何领域知识(除了调整簇的大小)。

对于两个相邻集群之间的每条边界线,我们都要确定一组(可能为空)连接它们的入口。==入口是沿两个相邻集群 c1 和 c2 的共同边界的最大无障碍线段,==其形式表示如下:考虑瓦片 l1 和 l2 的两条相邻线(每个集群一条),它们决定了 c1 和 c2 之间的边界边缘。 对于 t i l e t ∈ l 1 ∪ l 2 tile t \in l1 \cup l2 tiletl1l2,我们将 symm(t)定义为 t 相对于 c1 和 c2 之间边界的对称瓦片。请注意,t 和 symm(t) 是相邻的,绝不属于同一个簇:

  • 边界限制条件: e ∈ l 1 ∪ l 2 e\in l1 \cup l2 el1l2.该条件规定,入口沿相邻两个集群之间的边界分布,且不能超过这两个集群之间的边界。
  • 对称条件:$\forall t \in l_1 \cup l_2: t \in e \Leftrightarrow symm(t) \in e $。
  • 无障碍条件:入口处没有任何障碍物。
  • 最大化条件:只要前面的条件保持不变,入口就会向两个方向延伸。

image-20240301105641344

图 2 是样本地图左上角的缩放图片。图中显示了我们如何识别入口并利用它们构建抽象问题图的细节。在这个例子中,左侧的两个集群分别由宽度为 3 和 6 的两个入口连接。如果入口的宽度小于预设常数(在我们的例子中为 6),那么我们就在入口中间设置一个转换。否则,我们在入口两端各设置一个过渡段。

我们使用过渡来构建抽象问题图。对于抽象图中的每一个过渡,我们都会指定两个节点和一条连接它们的边。对于簇内的每对节点,我们都会找到一条连接它们的边,称为内边。我们通过搜索簇区域内的最优路径来计算内边的长度。

image-20240301111739537

图 2 显示了所有节点(浅灰色方块)、所有边间(浅灰色线条)和部分边内(右上角集群)。图 3 显示了图 2 右上角集群的抽象内部拓扑细节。数据结构包含节点集以及节点之间的距离。直线转换时,距离为 1;对角线转换时,距离为 1:42。我们只缓存节点之间的距离,而舍弃与这些距离相对应的实际最优路径。如果需要,也可以存储路径,但代价是占用更多内存。详见第 3.2.2 节的讨论。

image-20240301111848771

图 4(a) 显示了运行示例的抽象图。图中包括将起点节点 S 和目标节点 G 插入图中的结果(虚线),下一小节将对此进行描述。图中有 68 个节点,包括 S 和 G,每次搜索时它们都会发生变化。在此抽象层次上,有 16 个群组,其中 43 个相互连接,88 个内部连接。还有 2 条额外的边将 S 和 G 与图的其他部分连接起来。为了便于比较,低层次(非抽象)图包含 1; 463 个节点(每个未阻塞瓦片一个节点)和 2; 714 条边。

一旦构建了抽象图形并计算了边内距离,就可以在分层搜索中使用网格了。这些信息可以预先计算(在游戏启动前),存储在磁盘上,并在游戏运行时加载到内存中。这对于静态(不变化的)网格非常有用。对于动态变化的网格,必须在运行时修改预先计算的数据。当网格拓扑结构发生变化时(如桥被炸毁),受影响的本地群组的内边和间边需要重新计算。

3.2 On-line Search

在线搜索的第一阶段是将起始位置 S 与包含 S 的簇边界连接起来,这一步是通过将 S 临时插入抽象图来完成的。同样,将目标位置 G 连接到其群集边界也是通过将 G 插入抽象图来完成的。

添加 S 和 G 后,我们使用 A* [10]在抽象图中搜索 S 和 G 之间的路径。这是在线搜索中最重要的部分。它提供了一条抽象路径、从 S 到 S 簇边界的实际移动、到 G 簇的抽象路径以及从 G 簇边界到 G 的实际移动。

在线搜索的最后两个步骤是可选的:

  1. 路径重整可用于将抽象路径转换为原始网格上的移动序列。
    2. 路径平滑可用于提高路径重整解决方案的质量。

抽象路径可在后续处理步骤中进行重整,以获得从 S 到 G 的详细路径。对于许多实时路径搜索应用来说,并不需要完整的路径,只需要前几段路径即可。这些信息可以让角色开始朝着目标的正确方向移动。相比之下,A* 必须完成搜索并生成从 S 到 G 的完整路径,然后才能确定角色的最初步骤。

考虑一个经常发生动态变化的领域(例如,有许多移动装置在周围穿梭)。在这种情况下,找到一条抽象路径后,我们可以在角色向目标导航的过程中逐步重新定义它。如果当前的抽象路径变得无效,智能体就会丢弃它,寻找另一条抽象路径。没有必要事先重新定义整条抽象路径。

3.2.1 Searching for an Abstract Path

要在抽象图中搜索路径,S 和 G 必须是图的一部分。我们将 S 连接到包含它的集群 c 的边界。我们将 S 添加到抽象图中,并在本地搜索 S 和 c 的每个抽象节点之间的最优路径。如果存在这样的路径,我们就在抽象图中添加一条边,并将其权重设置为路径的长度。在图 4 中,我们用虚线表示这些边。

在我们的实验中,我们假设每次新的搜索都会改变 S 和 G。因此,插入 S 和 G 的成本会被添加到找到解决方案的总成本中。找到路径后,我们会从图中移除 S 和 G。然而,在实际操作中,这种计算方法可以更加高效。在这种情况下,我们插入 G 一次,然后重复使用。插入 G 的成本会在多次搜索中摊销。一般来说,缓存可以用来存储热门起始节点和目标节点的连接信息。

插入 S 和 G 后,抽象图可用来搜索 S 和 G 之间的抽象路径。

3.2.2 Path Refinement

路径重构将抽象路径转化为低级路径。抽象路径中的每个集群交叉都会被等效的低级移动序列所取代。

如果簇预处理缓存了这些附着在内侧边上的移动序列,那么重新定位就只需简单地查找即可。否则,我们将在每个簇内沿着抽象路径进行小规模搜索,以重新发现最优局部路径。有两个因素限制了重新定位搜索的复杂性。首先,只要在找到抽象路径后环境不发生变化,抽象解就能保证正确。这意味着我们永远不必为修正抽象解而回溯和重新规划。其次,初始搜索问题已被分解成几个非常小的搜索(抽象路径上的每个群组一个),搜索复杂度很低。

3.2.3 Path Smoothing

拓扑抽象阶段每个入口只有一个转换点。虽然这样做很不科学,但却放弃了计算解决方案的最优性。解决方案在抽象图中是最优的,但在初始问题图中不一定。

为了提高解决方案的质量(即长度和美观度),我们进行了路径平滑的后处理阶段。我们的路径平滑技术很简单,但效果很好。其主要思路是用直线取代解的局部次优部分。从解法的一端开始。对于解中的每个节点,我们都要检查是否能以直线到达路径中的下一个节点。如果可以,那么这两个节点之间的直线路径就取代了这些节点之间的初始次优序列。

3.3 Experimental Results for Example

表 1 的前两行总结了运行示例的实验结果。L-0 表示在低层图上运行 A*(我们称之为第 0 层),L-1 使用两个层次(即第 0 层和第 1 层),L-2 使用三个层次(即第 0 层、第 1 层和第 2 层)。最后一行 L-2 的含义将在第 3.5 节中说明。

使用曼哈顿距离作为启发式的低层(原始网格)搜索性能较差。我们选择这个例子是为了展示最糟糕的情况。在没有抽象的情况下,A* 将访问迷宫中所有未封锁的位置。搜索会扩展 1 462 个节点。限制搜索复杂度的唯一因素是迷宫的大小。具有相似拓扑结构的 Alar ger 地图对 A* 来说是一个难题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用分层搜索可以大大提高性能。将 S 插入抽象图时,它只能与起始簇边界上的一个节点相连。因此,我们添加了一个节点(对应 S)和一条边,将 S 与簇中唯一可访问的节点相连。将 G 插入图中是相同的。

在抽象图上使用 A* 搜索 S 和 G 之间的路径。在第 1 层搜索也会扩展抽象图的所有节点。不过,这次搜索的工作量大大减少。

主搜索扩展了 67 个节点。此外,插入 S 和 G 会扩展 16 个节点。找到一条抽象路径总共需要扩展 83 个节点。如果需要,抽象路径可以部分或全部重写,但需要额外费用。最糟糕的情况是,我们必须完全重写路径,而且没有缓存内边的实际路径。对于路径中的每一条内边(即簇交叉),我们都要执行一次搜索,以计算出相应的低水平作用序列。这样的小规模搜索共有 12 次,共扩展了 145 个节点。

3.4 Adding Levels of Hierarchy 添加层次结构级别

层次结构可以扩展到多个层次,从而将抽象图转化为多层次图。在多层次图中,节点和边都有标签,显示其在抽象层次结构中的层级。层级结构中的附加层级可以减少搜索工作量,尤其是在大型迷宫中。有关在多线索图中进行高效搜索的详情,请参阅附录 A.2.2。为了构建多层迷宫图,我们将迷宫抽象为多个层次。层级越高,迷宫分解中的簇就越大。第 l 层的簇称为 l 簇。在现有结构的基础上建立每个新的层级。第 3.1 节介绍了第 1 个簇的构建。对于第 2 层,将 n x n 个相邻的(第 1 层)簇组合在一起就得到了第 l 层簇,其中 n 是参数。

位于新创建的 l 簇边界上的节点会将其等级更新为 l(我们称之为 l 节点)。在第 l 个簇之间进行转换的边际节点也会将其等级提升至第 l 级(我们称之为 l-边际节点)。

我们为位于同一 l 簇边界上的 l 个通信节点对添加了级别为 l 的内部边(即 l-intra-edges),该边的权重是仅使用(l 1)个节点和边连接簇内两个节点的最短路径的长度。更多细节见第 A.2.2 节。

image-20240301134357121

将 S 插入图中会反复连接 S 和包含它的 l 簇边界上的节点,l从 1 到最大抽象层级递增。搜索 S 和 l 节点之间的路径仅限于 l 1 层和包含 S 的当前 l 簇的区域。

==我们构建抽象图的方式确保了无论我们使用多少抽象层级,都能找到相同的解。==特别是,在图中添加新的第 l 2 层并不会降低解的质量。在此,我们将提供简要的直观解释,而不是形式上的证明。在第 l 层添加的新边对应于第 l 1 层的现有最短路径。在第 l 层搜索得到的解与在第 l 1 层搜索得到的解相同,只是速度更快。

image-20240301135115029

在我们的示例中,增加一个 n =2 的额外层级会产生 4 个大的簇,地图的每个四分之一都有一个。图 2 中的整个图是一个 2 簇的例子。这个簇包含 2 个大小为 10 x 10 的 2-1 簇。除了 S,这个簇中唯一的 2 节点是左下角的那个。第 2 层是进行主要搜索的地方,共有 14 个节点(包括 S 和 G)。图 4(b) 显示了抽象图的第 2 层。图中虚线所示的边将 S 和 G 与第 2 层的图连接起来。

抽象层 2 很好地说明了预处理如何解决局部限制并降低抽象图的搜索复杂度。在第 2 层,我们避免在这个 "房间 "中进行任何无用的搜索,而是直接从 S 到左下角的出口。

插入 S 和 G 后,我们就可以搜索 S 和 G 之间的路径了。由于起点和目标的抽象层级最高,因此假设存在解决方案,我们将始终找到解决方案。搜索结果就是最高抽象层次的节点序列。如果需要,抽象路径可以反复重演,直到获得低层次的解决方案。

3.5 Experimental Results for Example with 3-LevelHierar chy

表 1 的第三行列出了我们的运行示例的数字数据,该示例采用 3 级层次结构(即三个层次:L 0、L 1 和 L 2)。

如第 3.3 节所示,将 S 和 G 连接到它们的 1 簇边界共扩展了 16 个节点。同样,我们现在将 S 和 G 连接到它们的 2 簇边界。这些第 1 级搜索为 S 扩展了 3 个节点,为 G 扩展了 22 个节点。

第 2 层的主搜索只扩展了 7 个节点。除了抽象路径中的节点外,没有其他节点被扩展。如果我们考虑到在第 1 层图中的搜索扩展了图中的所有节点,那么这是一个重要的改进。在扩展层次中找到抽象解总共需要 48 个节点。

值得注意的是,在增加了一个新的抽象层后,插入 S 和 G 的成本就占了主搜索成本的绝大部分。这说明了该方法的一般特点,即插入 S 和 G 的成本随着层次数的增加而增加,而主搜索则变得更简单。

表 1 还显示了完整解决方案重构的成本。将解决方案从第 2 层重置到第 1 层会扩展 16 个节点,从第 1 层重置到第 0 层会扩展 145 个节点,总计 161 个节点。

3.6 Storage Analysis

除了计算速度之外,分层方法用于路径标定的存储量也是另一个重要的性能指标。影响分层方法内存使用量的有两个因素:问题图的大小和 A* 使用的开放列表的大小。我们将在本节的其余部分详细讨论这两个因素。对于图的存储,我们既有经验分析,也有最坏情况的理论讨论。

3.6.1 Graph Storage Requirements

表 2 显示了 BALDUR’S GATE 测试套件的问题图平均大小。有关该数据集和设置(如群组大小或原始问题图中的边定义)的详细信息,请参见第 4 节。我们将原始低级图与抽象图进行了比较,抽象图的抽象层级有一个、两个和三个(不包括第 0 层)。表中显示了节点数 N、边间数 E1 和边内数 E2。对于多层次图,我们同时显示了总数量和各层次的数量 L i , i ∈ 1 , 2 , 3 L_i, i \in {1, 2, 3} Li,i1,2,3

数据显示,与原始问题图的大小相比,抽象图的存储开销很小。添加新的图级别会更新一些现有节点和边间的级别,而不会创建任何这些类型的新对象。唯一的开销就是新增的内边。在我们的数据集中,我们在一个有 4469 个节点和 16420 条边的初始图中添加了至少 1846 条内边(当有三个抽象层时)。假设节点和边占用的内存量大致相同,我们得到的开销为 8.83%。

以内存字节数表示的开销很大程度上取决于实现、编译器优化或问题图大小等因素。例如,如果图的大小至少为 256 x 256,那么存储图节点的坐标就需要两个字节。更大的地图需要更多内存。

由于抽象节点和边是按级别标记的,因此在抽象图中存储元素所需的内存可能比在初始图中更大。由于大多数编译器会将对象的比特大小四舍五入为 8 的倍数,因此实际上可能不存在比特开销。

通过在内存(如缓存)中只保留当前搜索所需的图部分,可以优化存储利用率。在分层框架中,我们只需要与当前搜索所在层级和区域相对应的子图。例如,在进行主抽象搜索时,我们可以放弃低层次的问题图,从而大大减少该搜索的内存需求。

一个簇的最坏情况是边界上交替出现阻塞地砖和空闲地砖,并且任何两个边界节点都可以相互连接。假设问题迷宫的大小为 m x m,迷宫被分解为 c x c 个簇,一个簇的大小为 n x n。在最坏的情况下,我们得到每个簇有 4n=2=2 n 个节点。由于每对节点表示一条内边,因此一个簇的内边数量为 2n(2n 1)=2= n(2n 1)。迷宫边缘没有抽象节点,因此边缘集群的抽象节点数量较少。对于位于迷宫角落的簇,节点数为 n,边缘内的节点数为 n(n 1)=2. 对于位于迷宫边缘的簇,节点数为 1:5n,边缘内的节点数为 1:5n(1:5n 1)=2. 因此,抽象节点总数为 2m(c 1)。内边总数为 n(c 2)2(2n 1)+2( n 1)+3( c 2)(1:5n 1)。

3.6.2 Storage for the A* Open List

由于分层路径搜索将问题分解为若干个小搜索,因此分层搜索中 A* 的平均打开长度比低层搜索小。表 3 比较了低层搜索和分层搜索中开放列表的平均长度。表 3 比较了低层搜索和分层搜索中开放列表的平均长度,该平均值是对第 4.1 节中描述的所有搜索的平均值,而不是在求解长度之后的结果。数据显示,在抽象框架中,低层搜索和主搜索的列表长度减少了三倍。

4 Experimental Results

4.1 Experimental Setup

实验对象是从 BioWare 的游戏《BALDUR’S GATE》中提取的 120 幅地图,地图大小从 50 x 50 到 320 x 320 不等。对于每幅地图,我们使用随机生成的 S 和 G 对进行了 100 次搜索,搜索结果显示这两个位置之间存在有效路径。

八边形是指在 4 个直线方向和 4 个对角线方向上具有邻接关系的图块。垂直和水平转换的成本均为 1,对角线转换的成本设定为 1:42。宽度小于 6 的入口只有一个过渡。对于较大的入口,我们会生成两个过渡。

代码使用阿尔伯塔大学路径定位代码库 (http://www.cs.ualberta.ca/ògames/pathfind) 实现。该库被用作搜索工具,可使用不同的网格表示快速实现不同的搜索算法。由于其通用性,使用该库会产生一些开销。本文中报告的所有时间应被视为自定义实现的宽松上限。

定时在 800 MHz 奔腾 III 处理器和 3GB 内存上进行。程序使用 gcc 2.96 版本编译,并在 Red Hat Linux 7.2 版本下运行。

4.2 分析

图 5 比较了在最大层级设置为 1、2 和 3 的层次结构上进行低层 A* 抽象搜索的情况。对于分层搜索,我们显示的是总工作量,其中包括在图中插入 S 和 G、在最高层搜索以及重新生成路径。实际花费可能更少,因为插入 S 或 G 的成本可以在多次搜索中摊销,而且路径重定并非总是必要的。从图中可以看出,当需要进行完整处理时,第一抽象层对于我们在本实验中使用的地图大小来说已经足够好了。我们认为,对于更大的地图,更多层次的好处会更显著。复杂度的降低可能会大于增加层级的开销。正如我们接下来所展示的,当不需要路径重构,并且 S 或 G 可用于多次搜索时,更多层次也是有用的。

尽管报告的时间是针对通用实现的,但值得注意的是,对于任何长度的解决方案,适当的抽象层次都能在平均不到 10 毫秒的时间内提供答案。在长度为 400 的情况下,在 800 MHz 的机器上每次搜索的平均时间不到 5 毫秒。

当解题长度很小时,A* 略优于 HPA*。解长小通常表示搜索问题简单,A* 只需付出较少的努力就能解决。在这种情况下,HPA* 的开销(例如插入 S 和 G 的开销)大于算法可能节省的费用。在这种情况下,使用欧几里得距离作为启发式提供了完美的信息,而 A* 除了那些属于解决方案的节点外,不会扩展其他节点。

图 6 显示了分层搜索的总耗费是如何由抽象耗费、插入 S 和 G 的耗费以及解决方案再改进的耗费组成的。查找抽象路径的成本是主要成本与插入 S 和 G 的成本之和。当 S 或 G 在多次搜索中重复使用时,只有部分成本计入问题的抽象成本。考虑到这些因素,图中显示,在层级较多的层次结构中,寻找抽象路径变得更加容易。

图 7 显示了解决方案的质量。我们将分层路径平滑得到的解决方案与低层 A* 计算出的最优解决方案进行了比较。我们绘制了路径平滑前后的误差。误差用百分比来衡量开销,计算公式如下:
e = h l − o l o l × 100 e = \frac{hl - ol}{ol} \times 100 e=olhlol×100

其中,hl 是用 HPA* 求得的解的长度,ol 是用 A* 求得的最优解的长度。误差与层次数量无关。唯一导致次优的因素是没有考虑入口的所有可能转换。

聚类大小是一个可以调整的参数。我们在性能测试中使用了大小为 10 10 的 1 个集群。该图显示了抽象搜索的平均扩展节点数是如何随着簇大小的变化而变化的。虽然主搜索随着簇大小的增加而减少,但插入 S 和 G 的成本增加得更快。

对于更高层次,一个 l 簇包含 22( l 1)个簇。我们使用这个较小的值,是因为当使用较大的值时,插入 S 和 G 的成本增加速度要快于主搜索的减少速度。这种趋势在相对较小的地图上尤为明显,在这种地图上,较小的簇就能实现良好的性能,而使用较大簇所增加的成本可能无法摊销。插入 S 和 G 的开销来自于必须将 S 和 G 连接到位于簇边界上的节点,簇边界越长,需要连接的节点就越多。我们对随机生成的地图进行了类似测试。主要结论类似,但由于篇幅有限,本文不再讨论细节。

5 Conclusions and FutureWork

尽管分层路径定位非常重要,也做了大量工作,但有关商业游戏中分层路径定位的详细出版物并不多。

在本文中,我们提出了一种高效近优路径定位的分层技术。我们的方法与领域无关,易于应用,并且适用于不同类型的地图拓扑结构。该方法能适应动态变化的环境。层次结构可以扩展到多个抽象层次,因此可以扩展到大型问题空间。我们使用从areal game中提取的地图测试了我们的程序,获得接近最优解的速度明显快于低层次的A*。

我们为分层路径搜索的未来工作提出了一些想法。我们计划优化将 S 和 G 插入抽象图的方式。如图 6 所示,增加新的抽象层后,这些成本会显著增加。提高性能的一种策略是只将 S 连接到边界上的稀疏节点子集,以保持抽象图的完整性。例如,如果抽象图中的每个 "未连接 "节点(即我们没有尝试连接 S 的边界上的节点)都可以从 "已连接 "节点(即我们连接了 S 的边界上的节点)到达,那么就可以保持抽象图的完整性。另一种方法是只考虑连接在 G 方向上的边界节点。然而,最后一种方法并不能保证完备性,而且很难事先评估其优点。如果由于图的不完整性导致搜索失败,我们就必须重新进行搜索,并逐渐扩大边界节点的子集。

我们目前使用的聚类方法很简单,效果也不错。不过,我们还想探索更复杂的聚类方法。一种与应用无关的策略是自动最小化一些聚类参数,如抽象聚类的数量、聚类相互作用和聚类复杂性(如内部障碍物的百分比)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值