目的
JPS算法核心思想:找到搜索图的对称性并打破
如图所示,A*7可会搜索很多对称的路径,造成计算资源的浪费,JPS算法可以智能地忽略掉路径中地对称性,有倾向性地进行搜索。
前向性(Look Ahead)准则
如果其他节点可以通过父节点到达,且路径的cost小于等于从当前节点到达的累计cost,那么该节点不需要被搜索。
无障碍物
- 灰色节点:inferior neighbors 劣性节点。拓展时直接放弃
- 白色节点:natural neighbors 自然节点,搜索时拓展的节点。
如图所示左图中除5之外,其他节点如2从父节点4到达所需要的cost为
2
\sqrt{2}
2,小于从x节点到达的累计cost为2,所以不需要被搜索。而到达节点3从父节点4经过节点2和经过节点x所需要的累计cost相同,也不需要被搜索,其余节点同理。
在斜对角拓展时,准则中要变为小于累计cost的节点才会放弃,这是因为如果考虑小于等于的情况,节点2和节点5会被放弃,在之后的搜索过程中,无论如何都搜索不到这两个节点。
详情可见:http://users.cecs.anu.edu.au/~dharabor/data/papers/harabor-grastien-aaai11.pdf
有障碍物
- 红色节点:forced neighbors 强迫节点,由于障碍物的出现使得该节点也要被强制进行考察。
如图所示左图中节点2变为障碍物,此时父节点4到达节点3的最短路径只有通过4->x->3这一条,所以在路径搜索中节点3也要被考虑。
跳点规则
![]() | ![]() |
---|
节点迭代进行拓展,开始时父节点p(x)可以向没有障碍物的各个方向拓展。
左图中向右直线拓展节点x,由于前向性规则,只能继续向该方向拓展,直到y节点附近遇到障碍物,可以右上拓展到节点z,此时y节点为特殊节点,将y节点放入队列中。
右图按右上对角线拓展节点x,之后节点x可以向上方,右方和右上角对角线继续拓展,之后的每个对角线节点也会向这三个方向拓展,直到拓展到节点z时发现其存在forced节点,z节点比较特殊,z节点无法从x节点直接拓展,其父节点y时x的直接拓展节点,所以把y节点放入open list,而x节点也有一个forced节点w,把w节点放入open list,至此,x的所有特殊节点搜索完成,把x弹出到close list,搜索过程可以看下图。
![]() | ![]() |
---|---|
![]() | ![]() |
![]() |
JPS 伪代码
- 维护一个优先级队列以存储要扩展的所有节点
- 初始化所有节点的启发式函数 h ( n ) h(n) h(n)
- 优先级队列初始化并加入初始状态 X s X_s Xs
- 对图中的所有节点初始化 g ( X s ) = 0 g(X_s)=0 g(Xs)=0, g ( n ) = i n f g(n)=inf g(n)=inf
- 开始循环
- 如果队列为空,说明没有找到路径,return FALSE; break;
- 把队列中 f ( n ) f(n) f(n)最小的节点n弹出
- 标记节点n为已扩展
- 如果节点n是目标点, return TRUE; break;
- 寻找节点n的所有未拓展节点m
- If g(m) = inf 更新节点累积成本
- g(m)= g(n) + Cnm
- 将节点m塞入队列
- If g(m) > g(n) + Cnm 保证节点从启动状态起具有最小的成本
- g(m)= g(n) + Cnm
- end
- End Loop
可以看出JPS伪代码与A*完全一致,不一样的地方是如何寻找节点n的所有未拓展邻居节点m