At its core, a pathfinding method searches a
graph by starting at one
vertex and exploring adjacent
nodes until the destination node is reached, generally with the intent of finding the cheapest route. Although graph searching methods such as a
breadth-first search would find a route if given enough time, other methods, which "explore" the graph, would tend to reach the destination sooner. An analogy would be a person walking across a room; rather than examining every possible route in advance, the person would generally walk in the direction of the destination and only deviate from the path to avoid an obstruction, and make deviations as minor as possible. Two primary problems of pathfinding are (1) to find a path between two nodes in a
graph; and (2) the
shortest path problem—to find the
optimal shortest path. Basic algorithms such as
breadth-first and
depth-first search address the first problem by
exhausting all possibilities; starting from the given node, they iterate over all potential paths until they reach the destination node. These algorithms run in O(|V|+|E|), or linear time, where V is the number of vertices, and E is the number of
edges between vertices. The more complicated problem is finding the optimal path. The exhaustive approach in this case is known as the
Bellman–Ford algorithm, which yields a time complexity of O(|V||E|), or quadratic time. However, it is not necessary to examine all possible paths to find the optimal one. Algorithms such as
A* and
Dijkstra's algorithm strategically eliminate paths, either through
heuristics or through
dynamic programming. By eliminating impossible paths, these algorithms can achieve time complexities as low as O(|E|\log(|V|)). The above algorithms are among the best general algorithms which operate on a graph without preprocessing. However, in practical travel-routing systems, even better time complexities can be attained by algorithms which can pre-process the graph to attain better performance. One such algorithm is
contraction hierarchies.
Dijkstra's algorithm A common example of a graph-based pathfinding algorithm is
Dijkstra's algorithm. This algorithm begins with a start node and an "open set" of candidate nodes. At each step, the node in the open set with the lowest distance from the start is examined. The node is marked "closed", and all nodes adjacent to it are added to the open set if they have not already been examined. This process repeats until a path to the destination has been found. Since the lowest distance nodes are examined first, the first time the destination is found, the path to it will be the shortest path. Dijkstra's algorithm fails if there is a negative
edge weight. In the hypothetical situation where Nodes A, B, and C form a connected undirected graph with edges AB = 3, AC = 4, and BC = −2, the optimal path from A to C costs 1, and the optimal path from A to B costs 2. Dijkstra's Algorithm starting from A will first examine B, as that is the closest. It will assign a cost of 3 to it, and mark it closed, meaning that its cost will never be reevaluated. Therefore, Dijkstra's cannot evaluate negative edge weights. However, since for many practical purposes there will never be a negative edgeweight, Dijkstra's algorithm is largely suitable for the purpose of pathfinding.
A* algorithm A* is a variant of Dijkstra's algorithm with a wide variety of use cases. A* assigns a weight to each open node equal to the weight of the edge to that node plus the approximate distance between that node and the finish. This approximate distance is found by the
heuristic, and represents a minimum possible distance between that node and the end. This allows it to eliminate longer paths once an initial path is found. If there is a path of length x between the start and finish, and the minimum distance between a node and the finish is greater than x, that node need not be examined. A* uses this heuristic to improve on the behavior relative to Dijkstra's algorithm. When the heuristic evaluates to zero, A* is equivalent to Dijkstra's algorithm. As the heuristic estimate increases and gets closer to the true distance, A* continues to find optimal paths, but runs faster (by virtue of examining fewer nodes). When the value of the heuristic is exactly the true distance, A* examines the fewest nodes. (However, it is generally impractical to write a heuristic function that always computes the true distance, as the same comparison result can often be reached using simpler calculations – for example, using
Chebyshev distance over
Euclidean distance in
two-dimensional space.) As the value of the heuristic increases, A* examines fewer nodes but no longer guarantees an optimal path. In many applications (such as video games) this is acceptable and even desirable, in order to keep the algorithm running quickly. == In video games ==