motoring news
A* search algorithm
A* search algorithm
In computer science, A* (pronounced as “A starlet”) is a computer algorithm that is widely used in pathfinding and graph traversal, the process of plotting an efficiently directed path inbetween numerous points, called knots. It loves widespread use due to its spectacle and accuracy. However, in practical travel-routing systems, it is generally outperformed by algorithms which can pre-process the graph to attain better spectacle, [1] albeit other work has found A* to be superior to other approaches. [Two]
Peter Hart, Nils Nilsson and Bertram Raphael of Stanford Research Institute (now SRI International) very first described the algorithm in 1968. [Trio] It is an extension of Edsger Dijkstra’s one thousand nine hundred fifty nine algorithm. A* achieves better spectacle by using heuristics to guide its search.
Contents
In 1968, AI researcher Nils Nilsson was attempting to improve the path planning done by Shakey the Robot, a prototype robot that could navigate through a room containing obstacles. This path-finding algorithm, which Nilsson called A1, was a swifter version of the then best known method, Dijkstra’s algorithm, for finding shortest paths in graphs. Bertram Raphael suggested some significant improvements upon this algorithm, calling the revised version A2. Then Peter E. Hart introduced an argument that established A2, with only minor switches, to be the best possible algorithm for finding shortest paths. Hart, Nilsson and Raphael then jointly developed a proof that the revised A2 algorithm was optimal for finding shortest paths under certain well-defined conditions.
A* is an informed search algorithm, or a best-first search, meaning that it solves problems by searching among all possible paths to the solution (purpose) for the one that incurs the smallest cost (least distance travelled, shortest time, etc.), and among these paths it very first considers the ones that show up to lead most quickly to the solution. It is formulated in terms of weighted graphs: commencing from a specific knot of a graph, it constructs a tree of paths beginning from that knot, expanding paths one step at a time, until one of its paths finishes at the predetermined objective knot.
At each iteration of its main loop, A* needs to determine which of its partial paths to expand into one or more longer paths. It does so based on an estimate of the cost (total weight) still to go to the aim knot. Specifically, A* selects the path that minimizes
where n is the last knot on the path, g(n) is the cost of the path from the commence knot to n , and h(n) is a heuristic that estimates the cost of the cheapest path from n to the aim. The heuristic is problem-specific. For the algorithm to find the actual shortest path, the heuristic function must be admissible, meaning that it never overestimates the actual cost to get to the nearest aim knot.
Typical implementations of A* use a priority queue to perform the repeated selection of minimum (estimated) cost knots to expand. This priority queue is known as the open set or fringe. At each step of the algorithm, the knot with the lowest f(x) value is liquidated from the queue, the f and g values of its neighbors are updated accordingly, and these neighbors are added to the queue. The algorithm proceeds until a aim knot has a lower f value than any knot in the queue (or until the queue is empty). [a] The f value of the purpose is then the length of the shortest path, since h at the purpose is zero in an admissible heuristic.
The algorithm described so far gives us only the length of the shortest path. To find the actual sequence of steps, the algorithm can be lightly revised so that each knot on the path keeps track of its predecessor. After this algorithm is run, the ending knot will point to its predecessor, and so on, until some knot’s predecessor is the commence knot.
As an example, when searching for the shortest route on a map, h(x) might represent the straight-line distance to the objective, since that is physically the smallest possible distance inbetween any two points.
If the heuristic h pleases the extra condition h(x) ≤ d(x, y) + h(y) for every edge (x, y) of the graph (where d denotes the length of that edge), then h is called monotone, or consistent. In such a case, A* can be implemented more efficiently—roughly speaking, no knot needs to be processed more than once (see closed set below)—and A* is equivalent to running Dijkstra’s algorithm with the diminished cost d’(x, y) = d(x, y) + h(y) − h(x) .
Pseudocode Edit
The following pseudocode describes the algorithm:
Remark: the above pseudocode assumes that the heuristic function is monotonic (or consistent, see below), which is a frequent case in many practical problems, such as the Shortest Distance Path in road networks. However, if the assumption is not true, knots in the closed set may be rediscovered and their cost improved. In other words, the closed set can be omitted (yielding a tree search algorithm) if a solution is assured to exist, or if the algorithm is adapted so that fresh knots are added to the open set only if they have a lower f value than at any previous iteration.
Example Edit
An example of an A* algorithm in activity where knots are cities connected with roads and h(x) is the straight-line distance to target point:
Key: green: embark; blue: purpose; orange: visited
The A* algorithm also has real-world applications. In this example, edges are railroads and h(x) is the great-circle distance (the shortest possible distance on a sphere) to the target. The algorithm is searching for a path inbetween Washington, D.C. and Los Angeles.
If the heuristic function h is admissible, meaning that it never overestimates the actual minimal cost of reaching the aim, then A* is itself admissible (or optimal) if we do not use a closed set. If a closed set is used, then h must also be monotonic (or consistent) for A* to be optimal. This means that for any pair of adjacent knots x and y, where d ( x , y ) <\displaystyle d(x,y)> denotes the length of the edge inbetween them, we must have:
This ensures that for any path X from the initial knot to x:
where L is a function that denotes the length of a path, and Y is the path X extended to include y. In other words, it is unlikely to decrease (total distance so far + estimated remaining distance) by extending a path to include a neighboring knot. (This is analogous to the limitation to nonnegative edge weights in Dijkstra’s algorithm.) Monotonicity implies admissibility when the heuristic estimate at any purpose knot itself is zero, since (letting P = (f,v1,vTwo. vn,g) be a shortest path from any knot f to the nearest objective g):
h ( f ) ≤ d ( f , v one ) + h ( v one ) ≤ d ( f , v one ) + d ( v one , v two ) + h ( v two ) ≤ … ≤ L ( P ) + h ( g ) = L ( P ) <\displaystyle h(f)\leq d(f,v_<1>)+h(v_<1>)\leq d(f,v_<1>)+d(v_<1>,v_<Two>)+h(v_<Two>)\leq \ldots \leq L(P)+h(g)=L(P)>
A* is also optimally efficient for any heuristic h, meaning that no optimal algorithm employing the same heuristic will expand fewer knots than A*, except when there are numerous partial solutions where h exactly predicts the cost of the optimal path. Even in this case, for each graph there exists some order of violating ties in the priority queue such that A* examines the fewest possible knots.
Special cases Edit
Dijkstra’s algorithm, as another example of a uniform-cost search algorithm, can be viewed as a special case of A* where h ( x ) = zero <\displaystyle h(x)=0> for all x. [Four] [Five] General depth-first search can be implemented using A* by considering that there is a global counter C initialized with a very large value. Every time we process a knot we assign C to all of its freshly discovered neighbors. After each single assignment, we decrease the counter C by one. Thus the earlier a knot is discovered, the higher its h ( x ) <\displaystyle h(x)> value. It should be noted, however, that both Dijkstra’s algorithm and depth-first search can be implemented more efficiently without including a h ( x ) <\displaystyle h(x)> value at each knot.
Implementation details Edit
There are a number of ordinary optimizations or implementation details that can significantly affect the spectacle of an A* implementation. The very first detail to note is that the way the priority queue treats ties can have a significant effect on spectacle in some situations. If ties are violated so the queue behaves in a LIFO manner, A* will behave like depth-first search among equal cost paths (avoiding exploring more than one identically optimal solution).
When a path is required at the end of the search, it is common to keep with each knot a reference to that knot’s parent. At the end of the search these references can be used to recover the optimal path. If these references are being kept then it can be significant that the same knot doesn’t show up in the priority queue more than once (each entry corresponding to a different path to the knot, and each with a different cost). A standard treatment here is to check if a knot about to be added already emerges in the priority queue. If it does, then the priority and parent pointers are switched to correspond to the lower cost path. A standard binary heap based priority queue does not directly support the operation of searching for one of its elements, but it can be augmented with a hash table that maps elements to their position in the heap, permitting this decrease-priority operation to be performed in logarithmic time. Alternatively, a Fibonacci heap can perform the same decrease-priority operations in constant amortized time.
A* is admissible and considers fewer knots than any other admissible search algorithm with the same heuristic. This is because A* uses an “optimistic” estimate of the cost of a path through every knot that it considers—optimistic in that the true cost of a path through that knot to the objective will be at least as good as the estimate. But, critically, as far as A* “knows”, that optimistic estimate might be achievable.
To prove the admissibility of A*, the solution path returned by the algorithm is used as goes after:
When A* terminates its search, it has found a path whose actual cost is lower than the estimated cost of any path through any open knot. But since those estimates are optimistic, A* can securely disregard those knots. In other words, A* will never overlook the possibility of a lower-cost path and so is admissible.
Suppose now that some other search algorithm B terminates its search with a path whose actual cost is not less than the estimated cost of a path through some open knot. Based on the heuristic information it has, Algorithm B cannot rule out the possibility that a path through that knot has a lower cost. So while B might consider fewer knots than A*, it cannot be admissible. Accordingly, A* considers the fewest knots of any admissible search algorithm.
This is only true if both:
- A* uses an admissible heuristic. Otherwise, A* is not ensured to expand fewer knots than another search algorithm with the same heuristic. [6]
- A* solves only one search problem rather than a series of similar search problems. Otherwise, A* is not ensured to expand fewer knots than incremental heuristic search algorithms. [7]
Bounded entertainment Edit
While the admissibility criterion assures an optimal solution path, it also means that A* must examine all identically meritorious paths to find the optimal path. To compute approximate shortest paths, it is possible to speed up the search at the expense of optimality by relieving the admissibility criterion. Oftentimes we want to trussed this refreshment, so that we can assure that the solution path is no worse than (1 + ε) times the optimal solution path. This fresh ensure is referred to as ε-admissible.
There are a number of ε-admissible algorithms:
The time complexity of A* depends on the heuristic. In the worst case of an unbounded search space, the number of knots expanded is exponential in the depth of the solution (the shortest path) d : O(b d ) , where b is the branching factor (the average number of successors per state). [15] This assumes that a aim state exists at all, and is reachable from the embark state; if it is not, and the state space is infinite, the algorithm will not terminate.
The heuristic function has a major effect on the practical spectacle of A* search, since a good heuristic permits A* to prune away many of the b d knots that an uninformed search would expand. Its quality can be voiced in terms of the effective branching factor b* , which can be determined empirically for a problem example by measuring the number of knots expanded, N , and the depth of the solution, then solving [16]
Good heuristics are those with low effective branching factor (the optimal being b* = one ).
The time complexity is polynomial when the search space is a tree, there is a single purpose state, and the heuristic function h meets the following condition:
where h * is the optimal heuristic, the exact cost to get from x to the objective. In other words, the error of h will not grow quicker than the logarithm of the “ideal heuristic” h * that comes back the true distance from x to the purpose. [9] [15]
A* is commonly used for the common pathfinding problem in applications such as games, but was originally designed as a general graph traversal algorithm. [Three] It finds applications to diverse problems, including the problem of parsing using stochastic grammars in NLP. [17] Other cases include an Informational search with online learning. [Eighteen]
What sets A* apart from a greedy best-first search algorithm is that it takes the cost/distance already traveled, g(n) , into account.
Some common variants of Dijkstra’s algorithm can be viewed as a special case of A* where the heuristic h ( n ) = zero <\displaystyle h(n)=0> for all knots; [Four] [Five] in turn, both Dijkstra and A* are special cases of dynamic programming. [Nineteen] A* itself is a special case of a generalization of branch and tied [20] and can be derived from the primal-dual algorithm for linear programming. [21]
- Anytime Repairing A* (ARA*) [22]
- Block A*
- D*
- Field D*
- Fringe
- Fringe Saving A* (FSA*)
- Generalized Adaptive A* (GAA*)
- IDA*
- Informational search [Eighteen]
- Hop point search
- Lifelong Planning A* (LPA*)
- Simplified Memory bounded A* (SMA*)
- Theta*
- Anytime A*[23]
- Realtime A* [24]
- Anytime Dynamic A*
- Time-Bounded A* (TBA*) [25]
A* can also be adapted to a bidirectional search algorithm. Special care needs to be taken for the stopping criterion. [26]