跳转点寻路介绍

        有均衡代价的2D网格上寻找最短路径有几种算法。A*算法是一种对宽度优先和深度优先搜索的常见并且简单的优化。对于这样的算法有很多扩展,包括D*、HPA*和Rectangular Symmetry Reduction,每一种都试图减少最优路径节点数量。

        跳转点(Jump Point Search )寻路逻辑是由Daniel Harabor和Alban Grastien提出的,是一种使在矩形网格上寻路更加有效地方法。在这篇文章中,我将不遗余力的介绍它,但是不是研究论文中的底层数学公式。而是尝试通过图表引起你的兴趣。

        我假设你已经很熟悉A*算法,甚至Dijkstra寻路。如果想要了解背景信息和更好地介绍,请查看Amit’s introduction to A*。

对于下面的例子,我假设寻路是在一个常用的方格上,水平和垂直方向的移动代价为1,对角线的移动代价为√2̅。

        尝试一下

你可以演示A*和JPS。通过点击和拖拽任何地方以增加障碍,拖拽绿色(开始)和红色(目标)节点来移动它们,并且点击“Find Path"按钮来寻找最优路径。译者注:由于原文是一个网页演示,所以转载不过来,请直接去原文演示。

减少路径扩展和对称

        在A*每一次迭代期间,我们在已知最好的方向上扩大搜索范围。然而,有一些情况可能会导致低效的情况出现。在大的开放的空间中会出现一种低效的情况。为了展示示例,让我们来看一个矩形网格。

        在一个开放的网格上,有一条从绿点到红点的路径。

        跳转点寻路介绍_第1张图片               

        有许多种等效的路径穿越这个矩形区域。Dijkstra's,做一个广度搜索,是一个不错的例证。你会发现,每一条路的代价是相同的。唯一的不同是我们选择对角还是水平行走。

        在这片研究文章中,Harabor和Grastien把这称作“对称路径”,因为他们是完全相同的效果。理想情况下,我们应该识别这种情况,并忽略其它而保留一种情况。

        更智能

        A*算法是通过最简单的方法扩大搜索:把相邻的下一节点直接加入一个列表中。我们是不是可以想的更远一些,并且跳过那些凭直觉就不可能的一些节点呢?我们可以尝试鉴别一些路径匀称的路径情况,并且忽略忽略某些扩大搜索中的节点。

        展望水平和垂直方向      

        首先,通过扩展的垂直的移动,让我们关注下水平方向。在一个开放的网格上,让我们从考虑从绿色节点开始移向右边。我们把这个节点的邻居作为假设。
        第一步,我们忽略我们来的方向的节点,因为我们已经访问过它了,这个就标记为灰色。
        第二步,我们假设我们已经穿过节点的对角线节点作为下一个节点,因为这些对角线节点比直接穿过会短一些。
        我们前面的这些对角线上的邻居可以通过我们上面和下面的邻居到达。通过这些路径的代价是相同的,所以为了简单起见,我们将假设其他的路径是更可取的,并且忽略这些节点。
        这让我们只有一个节点去检查:当前节点正右边的这个。我们已经假设我们其它的邻居为备用到达路径了,所以我们就能专注于唯一的这个邻居了。
        这就是技巧:只要这条路径是可行的,我们就能跳到右边的下一个节点,并且重复我们的检测而不用加入到open列表里。
        但是,“路径是可行的”意味着什么?当我们的假设不正确的时候,并且当我们需要停止并且需要仔细观察一下的时候?
        我们对右边对角线上节点做了一个假设,任何等价路径将会穿过我们邻居的上方和下方。但是,有一种情况可以为真,那就是如果一个障碍高于或者低于路径块。
        在这里,我们必须停止和重复查找。并不仅仅是要看我们右边的节点,我们也要强制看一下它前面的对角上的节点。在跳转点寻路论文中,这叫做强制邻居,因为当我们不得不忽略它的时候,必须考虑它。
        当我们到达一个强制邻居路径点,我们停止向右跳并且把当前节点加入到open容器中,以备以后检查和扩展。
        一个最终的假设:如果我们右边的节点是不可通过的,我们能安全的忽视全部的节点。我们已经假设路径上方和下方同通过其它节点处理,并且因为强制邻居节点我们没有停止。因为我们只关心如何可以直接到达,一个障碍意味着无处可去了。

        展望对角

当我们在对角线移动的时候,我们可以应用类似的简化了的假设。在这个例子中,我们正向右前行。
跳转点寻路介绍_第2张图片
       首先假设我们到达这是通过我们父母渠道的邻居的左边和下边直接或者水平移动到达这里。
跳转点寻路介绍_第3张图片
我们也可以假设相同的上面节点向左,下面节点向右。这些也可以达到更有效地通过左边的邻居到达左边和下边。
跳转点寻路介绍_第4张图片
这让我们思考三个邻居:上边两个和右边,一个是我们原来方向对角上的。
跳转点寻路介绍_第5张图片
类似于水平移动时的强制邻居,当一个障碍出现在我们左边或者下边的时候,左上角邻居和右下角的邻居不能到达,除了通过当前节点。这就是对角运动的强制邻居节点。
跳转点寻路介绍_第6张图片
当对角移动有3个邻居需要考虑的时候,我们怎么向前?
两个邻居需要水平或者垂直移动,因为我们知道在这些方向中跳到下一个节点,我们来看一下第一个,如果这些方向中找到内核一个节点值得查找,我们就能对角移动一步并且重复它。
例如,这里有几步对角移动。对角线移动前,水平和垂直路径需要考虑一下,直到找到一个需要进一步考虑的节点。这种情况下,障碍边缘被检测,当我们向右跳,因为它有一个强制邻居。
首先,我们扩展水平和垂直方向。两个方向都跳到障碍为止或者地图的边缘为止,否则一直走下去。
跳转点寻路介绍_第7张图片
然后再水平和垂直方向扩展,没有遇到障碍,就一直走下去。然后第三次……
跳转点寻路介绍_第8张图片跳转点寻路介绍_第9张图片
最终,当垂直方向到达地图边缘,向右的跳到一个强制邻居节点。
跳转点寻路介绍_第10张图片
我们把当前节点加入到open容器里,并且接续下一次A*的迭代。

一起试一下

在这个特别的方向行走的时候,我们已经为了一个节点跳过了大部分邻居节点,并且已经制定了一些规则跳往下一格节点。

把这个恢复到A*逻辑,我们将应用这些“jumping ahead”在open容器里的节点。我们将用它的父对象决定移动方向和向前跳到我们能到达的地方。如果我们找到一个感兴趣的节点,我们将忽略所有中间的节点(因为我们已经用我们简单的规则跳过了他们)并且把它们加到open容器里。

在open容器里的每一个节点都是根据父对象的方向扩展的,并随着前面同样地跳点:先向水平和垂直,然后对角移动。

这里是一个扩展序列的例子,在最后标记最终路径。

首先,确定一个目标。

跳转点寻路介绍_第11张图片

从预先设定的节点开始(open容器里的唯一一个),我们水平和垂直方向扩展寻找。

跳转点寻路介绍_第12张图片

水平跳的时候找到一个强制邻居(紫色高亮的节点)。我们把它加入到open容器中。

跳转点寻路介绍_第13张图片

最后,我们沿对角线扩展,除了碰到边缘,并没有找到任何东西。

跳转点寻路介绍_第14张图片

接着,我们检测下一个最优(或者仅仅是这种情况的)的open节点。因为当我们到达这个节点的时候我们正在水平移动,所以我们继续水平移动。

跳转点寻路介绍_第15张图片

因为我们也遇到一个强制邻居,我们也在那个方向扩展。跟着对角线规则,我们也对角线移动,然后水平、垂直方向寻找。

跳转点寻路介绍_第16张图片

没有找到任何东西,继续对角线移动。

跳转点寻路介绍_第17张图片

这一次,当我们水平移动(哪都去不了)和垂直移动时,我们找到了目标节点。用强制邻居找一个节点真是非常有趣,所以我们把这个节点加入到open容器里。

跳转点寻路介绍_第18张图片

最后,我们扩展最后一个open节点,找到目标。跳过算法的最后一次迭代,把目标节点加入到open容器里,我们找到了最有路径。

跳转点寻路介绍_第19张图片 跳转点寻路介绍_第20张图片


备注

1.代码是用于创建这些图表,并且交互式的路径寻找可以在GitHub上的jps-explained project下找到。

2.The original research paper by Daniel Harabor and Alban Grastien 正式介绍了JPS算法,并且可以作为一个优秀的参考去实现自己的算法。几篇其他相关的论文在哥哥

Mr. Harabor’s website.

3.Mr.Harabor's原创博客公布了一系列的Rectangular Symmetry Reduction和Jump Point Search,在这里

4.Amit’s A* Pages是一个优秀的介绍A*和寻路算法的博客。

5.Xueqiao Xu已经创建了一个JavaScript的寻路库,叫做PathFinding.js,其中包含了JPS,并且有一个demo,你可以直接在这里产生可视的图表。

6.我在这 project experimenting with pathfinding and visualization里应用了JPS。

更新,2014.4

1.JPS算法是基于一种假设,用比较少的A*迭代访问网格上德许多节点内容比维护一个优先队列的许多A*迭代要更有效。在这里,是O(1)对抗O(n),虽然有更好地队列实现O(1)对抗O(n long n)。
2.我已经更新了区分不同以检测了的路径的图表对抗建立的open/close容器的A*算法

译者注:
1、JPS解释器(本地运行演示寻路过程):https://github.com/zerowidth/jps-explained
2、JS写的寻路库:https://github.com/qiao/PathFinding.js
3、相关论文(IEEE):http://users.cecs.anu.edu.au/~dharabor/publications.html
4、详细介绍A*:http://theory.stanford.edu/~amitp/GameProgramming/
5、一个各种算法的运行演示网址:http://qiao.github.io/PathFinding.js/visual/







你可能感兴趣的:(翻译)