Hubbry Logo
Jump point searchJump point searchMain
Open search
Jump point search
Community hub
Jump point search
logo
7 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
Jump point search
Jump point search
from Wikipedia

In computer science, jump point search (JPS) is an optimization to the A* search algorithm for uniform-cost grids. It reduces symmetries in the search procedure by means of graph pruning,[1] eliminating certain nodes in the grid based on assumptions that can be made about the current node's neighbors, as long as certain conditions relating to the grid are satisfied. As a result, the algorithm can consider long "jumps" along straight (horizontal, vertical and diagonal) lines in the grid, rather than the small steps from one grid position to the next that ordinary A* considers.[2]

Jump point search preserves A*'s optimality, while potentially reducing its running time by an order of magnitude.[1]

History

[edit]

Harabor and Grastien's original publication provides algorithms for neighbor pruning and identifying successors.[1] The original algorithm for neighbor pruning allowed corner-cutting to occur, which meant the algorithm could only be used for moving agents with zero width, limiting its application to either real-life agents (e.g., robotics) or simulations (e.g., many games).

The authors presented modified pruning rules for applications where corner-cutting is not allowed the following year.[3] This paper also presents an algorithm for pre-processing a grid in order to minimize online search times.

A number of further optimizations were published by the authors in 2014.[4] These optimizations include exploring columns or rows of nodes instead of individual nodes, pre-computing "jumps" on the grid, and stronger pruning rules.

Future work

[edit]

Although jump point search is limited to uniform cost grids and homogeneously sized agents, the authors are placing future research into applying JPS with existing grid-based speed-up techniques such as hierarchical grids.[4][5]

References

[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
Jump Point Search (JPS) is a pathfinding algorithm that optimizes the A* search method for uniform-cost grid maps by selectively expanding only specific nodes known as "jump points," thereby pruning symmetric paths on the fly to achieve optimal solutions without preprocessing or additional memory overhead. Developed by Daniel Harabor and Alban Grastien, it was introduced in as an online symmetry-breaking technique specifically designed for grids supporting cardinal and diagonal movements with costs of 1 and √2, respectively. The core mechanism of JPS involves a macro-step operator that allows the search to "jump" from a node in a fixed direction—either straight or diagonal—until it reaches a jump point or encounters an , skipping intermediate nodes that would inevitably lie on any optimal path. Jump points are identified through local rules based on forced neighbors ( that constrain movement) or proximity to the , ensuring that no optimal path is overlooked. This approach guarantees optimality, as proven in the original formulation, while reducing the search space dramatically compared to standard A*. In empirical evaluations on benchmark grid maps such as those from the Moving AI Lab (including Adaptive Depth, Baldur’s Gate, , and Rooms datasets), JPS demonstrated speedups over A* ranging from 20.37 times on Adaptive Depth to 215.36 times on Baldur’s Gate, with corresponding reductions in node expansions. It also outperformed other symmetry-exploiting methods like Swamps (up to 20.37x vs. 1.89x speedup) and was competitive with hierarchical techniques such as HPA* (e.g., 35.95x vs. 9.63x on ). Subsequent improvements, including online and offline optimizations, have further enhanced its efficiency for applications in , video games, and planning.

Overview

Definition and purpose

Jump Point Search (JPS) is an optimized designed for uniform-cost grid environments, serving as a symmetry-reducing enhancement to the by expanding only specific nodes known as "jump points" rather than all neighboring cells. This approach identifies and prunes redundant paths that arise due to the symmetric structure of grids, where multiple equivalent routes exist between points, thereby focusing the search on directionally significant nodes that could lead to optimal paths. The primary purpose of JPS is to efficiently compute optimal paths in obstacle-filled rectangular grids, minimizing computational overhead while preserving the optimality and completeness guarantees of A*. By exploiting the inherent symmetries in grid maps—such as straight-line traversals where intermediate nodes offer no unique routing advantages—JPS skips over these redundant expansions, potentially accelerating searches by an in large, open spaces compared to standard A*. It assumes a uniform-cost model where cardinal movements (up, down, left, right) cost 1 unit and diagonal movements cost √2 units, operating on undirected grids with cells designated as either traversable or obstacles, and allowing up to eight possible neighbors per cell. For instance, consider a simple 2D grid scenario with no obstacles, where the start point is at the bottom-left and the goal is at the top-right, forming a straight diagonal line. In standard A*, the algorithm would expand every intermediate cell along this path. JPS, however, identifies the direction of travel and "jumps" directly to the next jump point—such as the goal itself or a point where a deviation becomes possible—bypassing the in-between nodes and adding only the jump point as a successor. This illustrates how JPS reduces the search space in symmetric, linear traversals without missing the optimal route. Jump point search (JPS) is an optimized variant of the A* specifically designed for uniform-cost grid maps, retaining A*'s core framework, including the use of open and closed sets to manage explored nodes and an such as the Euclidean or to guide the search toward the goal. This integration allows JPS to inherit A*'s guarantees of optimality and completeness when the heuristic is consistent, without altering the fundamental f(n)=g(n)+h(n)f(n) = g(n) + h(n), where g(n)g(n) is the path cost from the start to node nn and h(n)h(n) is the estimated cost from nn to the goal. The primary modification in JPS lies in the successor generation phase, where instead of expanding all neighboring nodes (typically up to 8 in a grid), the algorithm applies symmetry-breaking pruning rules to identify only "jumpable" directions and advances directly to the next relevant node, known as a jump point, thereby skipping intermediate symmetric nodes that would not lead to optimal paths. This jumping mechanism dramatically reduces the number of node expansions compared to standard A*, often achieving speedups of an or more in open terrains by eliminating redundant searches along straight-line or diagonal paths. consistency is preserved in JPS by ensuring that the remains unchanged and that pruned nodes do not affect the monotonicity required for optimality, allowing the algorithm to find the shortest path without relaxation or . At a high level, JPS integrates with A* by replacing the standard with a specialized one that incorporates pruning and jumping, as illustrated in the following outline:

function JPS(start, goal): open_set = PriorityQueue() // prioritized by f(n) = g(n) + h(n) closed_set = Set() g_scores = {start: 0} open_set.insert(start, h(start)) while open_set is not empty: current = open_set.extract_min() if current == goal: return reconstruct_path(current) closed_set.add(current) for successor in identify_successors(current, goal): // JPS-modified: prunes and jumps tentative_g = g_scores[current] + distance(current, successor) if successor in closed_set or tentative_g >= g_scores[successor]: continue came_from[successor] = current g_scores[successor] = tentative_g f_score = tentative_g + h(successor) open_set.insert_or_update(successor, f_score) function identify_successors(node, [goal](/page/Goal)): // Key JPS modification successors = [] for direction in possible_directions(node): if is_jumpable(direction): jump_point = jump(node, direction, [goal](/page/Goal)) if jump_point is valid: successors.append(jump_point) return successors

function JPS(start, goal): open_set = PriorityQueue() // prioritized by f(n) = g(n) + h(n) closed_set = Set() g_scores = {start: 0} open_set.insert(start, h(start)) while open_set is not empty: current = open_set.extract_min() if current == goal: return reconstruct_path(current) closed_set.add(current) for successor in identify_successors(current, goal): // JPS-modified: prunes and jumps tentative_g = g_scores[current] + distance(current, successor) if successor in closed_set or tentative_g >= g_scores[successor]: continue came_from[successor] = current g_scores[successor] = tentative_g f_score = tentative_g + h(successor) open_set.insert_or_update(successor, f_score) function identify_successors(node, [goal](/page/Goal)): // Key JPS modification successors = [] for direction in possible_directions(node): if is_jumpable(direction): jump_point = jump(node, direction, [goal](/page/Goal)) if jump_point is valid: successors.append(jump_point) return successors

This structure maintains A*'s efficiency while leveraging grid-specific optimizations, ensuring that only nodes where paths can deviate or encounter obstacles are fully expanded.

Background

Grid-based pathfinding

Grid-based pathfinding refers to the process of finding the shortest path between two points in a discrete 2D lattice composed of cells, where certain cells are designated as obstacles that cannot be traversed. This approach models the environment as a graph, with each free cell (or grid point) serving as a node and possible movements between adjacent cells as edges. It is commonly applied in domains such as , video games, and simulations to enable around barriers while minimizing path length or cost. Movement in grid-based pathfinding is governed by specific models that define allowable directions and associated costs. The cardinal (or 4-neighbor) model permits movement only in four orthogonal directions—north, , east, and west—resulting in uniform costs for horizontal and vertical steps. The 8-directional (or octile) model extends this by including four diagonal directions, allowing for more natural, shorter paths in open spaces, with costs of 1 for orthogonal moves and √2 for diagonal moves. These models assume a regular lattice structure where each cell connects to its immediate neighbors based on the chosen connectivity. Grids are typically represented using 2D arrays to store cell states, with free spaces marked as traversable and obstacles as impassable to prevent expansion into blocked areas. Adjacency can be implicitly defined through array indexing for efficiency, or explicitly via lists that enumerate neighbors according to the movement model, facilitating graph search operations. This representation simplifies implementation but requires careful handling of boundary conditions and obstacle integration. A key challenge in grid-based arises from the potentially high node count in large environments, such as expansive maps with thousands of cells, which can generate spaces during exploration without targeted optimizations. Obstacles further complicate this by fragmenting the space and increasing the , demanding efficient pruning or heuristic guidance to maintain computational feasibility. A* search serves as a standard informed method for addressing these issues in grid environments.

Limitations of standard A* on grids

In uniform-cost grid maps, the standard A* algorithm encounters substantial inefficiencies stemming from the inherent of the grid structure. Numerous paths between the start and goal nodes are equivalent in cost but differ merely in the sequence of moves, prompting A* to generate and evaluate a large number of redundant states. This symmetry arises because uniform edge weights make detours and alternative routings indistinguishable in terms of path length until later in the search, causing the algorithm to explore unnecessary branches that do not contribute to the optimal solution. A key manifestation of this issue occurs during straight-line pathfinding, where A* expands intermediate nodes along the route while checking all possible symmetric continuations, such as diagonal or orthogonal deviations that could be pruned if grid topology were better exploited. In an empty grid without obstacles, for instance, A* generates a diamond-shaped expansion front (under distance) or approximately elliptical front (under octile ), evaluating every node within the bounding defined by the goal's initial f-value and wasting effort on or circuitous paths that renders suboptimal. This leads to excessive node generations, as dominated states—those reachable via multiple equivalent routes—are not inherently identified and discarded. The expansion overhead exacerbates these problems, with A* routinely examining up to 8 neighbors per node in 8-connected grids, resulting in a worst-case of O(bd)O(b^d), where b=8b = 8 is the and dd is the solution depth. Even when employing consistent and admissible like the octile distance—which computes max(x2x1,y2y1)+(21)min(x2x1,y2y1)\max(|x_2 - x_1|, |y_2 - y_1|) + (\sqrt{2} - 1) \min(|x_2 - x_1|, |y_2 - y_1|)
Add your contribution
Related Hubs
User Avatar
No comments yet.