Understanding Jump Point Search (JPS) Algorithm
The A* algorithm is a common and straightforward optimization of breadth-first (Dijkstra’s) and depth-first searches. The Jump Point Search algorithm, introduced by Daniel Harabor and Alban Grastien, is one such way of making pathfinding on a rectangular grid more efficient.
The A* algorithm expands its search by doing the simplest thing possible: adding a node’s immediate neighbors to the set of what to examine next. What if we could look ahead a little bit, and skip over some nodes that we can intuit aren’t valuable to look at directly? We can try and identify situations where path symmetries are present, and ignore certain nodes as we expand our search.
But what does “the way is clear” mean? When are our assumptions incorrect, and when do we need to stop and take a closer look?
Here, we have to stop and reexamine. Not only must we look at the node to our right, we’re also forced to look at the one diagonally upward from it. In the Jump Point Search paper, this is called a forced neighbor because we’re forced to consider it when we would have otherwise ignored it.
When we reach a node with a forced neighbor, we stop jumping rightward and add the current node to the open set for further examination and expansion later.
How might we jump ahead when moving diagonally, when there are three neighbors to consider?
Two of our neighbors require vertical or horizontal movement. Since we know how to jump ahead in these directions, we can look there first, and if neither of those directions find any nodes worth looking at, we can move one more step diagonally and do it again.
For example, here are several steps of a diagonal jump. The horizontal and vertical paths are considered before moving diagonally, until one of them finds a node that warrants further consideration. In this case, it’s the edge of the barrier, detected because it has a forced neighbor as we jump to the right.
Tying It Together
We’ve now considered ways of skipping most neighbors for a node when we’re traveling in a particular direction, and have also determined some rules about when we can jump ahead.
To tie this back into the A* algorithm, we’ll apply these “jumping ahead” steps whenever we examine a node in the open set. We’ll use its parent to determine the direction of travel, and skip ahead as far as we can. If we find a node of interest, we’ll ignore all the intermediary steps (since we’ve used our simplifying rules to skip over them) and add that new node to the open set.
Each node in the open set is the expanded based on the direction of its parent, following the same jump point expansion as before: look horizontally and vertically first, then move diagonally.
Here is an example sequence of path expansions, with the final path marked at the end.