Você está na página 1de 6

Algorithm Study: A* Search

Sophors Khut Melissa Marshall Banteaymolu Alebachew Eric Biggers November 21, 2011

Background

A* Search is a graph search algorithm that is able to nd the shortest path between two vertices in a graph. It is based on Dijkstras algorithm, which also solves this problem (and optionally also the more general problem of nding the shortest distance from a vertex to all other vertices). Finding the shortest path between two points has applications in areas such as digitized maps and robot motion planning. We can think of A* search as Dijkstras algorithm with slight modications that can allow it to run faster on graphs in which it is possible to estimate the distance to the goal for example, graphs where the vertices are actual points in space, which typically is the case for pathnding problems in the real world. Before explaining the A* search algorithm itself, we should examine Dijkstras algorithm, which A* search is based on.

Dijkstras Algorithm

As mentioned, Dijkstras algorithm solves the single-source shortest path problem for a graph. It works on any graph that has all edges with non-negative weights. Dijkstras algorithm works by visiting vertices in the graph starting with the starting vertex in the path. Of the vertices that can be reached from only the set of vertices that have been visited so far, we can take the vertex that is the smallest distance from the start. The path that has been discovered to this vertex is guaranteed to be the shortest path to this vertex because it must be at least as great a distance to reach this vertex via a non-yet-visited vertex. After we have decided on this vertex, the algorithm must examine the vertexs neighbors and update the distances from the start vertex to each of them so that in the next iteration, the closest not-yet-visited vertex can be identied once again. The algorithm continues until the closest not-yet-visited vertex is the goal vertex (if there is a goal vertex), or, it continues until the shortest paths to all vertices have been found. If there is no path to the goal vertex, the algorithm will examine all vertices and edges before nishing with the indication that there is no path to the goal. One way that that Dijkstras algorithm can return the physical shortest path that it found between two vertices is that every vertex can be assigned an attribute that points to the previous vertex in the path going to that vertex. Then, if these attributes are continuously updated as vertices are visited, when the algorithm nally terminates the

path from the start to the end can be recovered by following the references from the end all the way back to the start vertex. Dijkstras algorithm is guaranteed to nd a shortest path from the starting point to the goal, unless no path exists. In the following diagram, the pink square is the starting point, the blue square is the goal, and the teal areas show what areas Dijkstras algorithm scanned.

Improving Dijkstras Algorithm: A* Search

Dijkstras algorithm can be made more ecient by choosing good data structures, such as an adjacency list to represent the graph so that vertices neighbors can be found quickly, and a minheap to hold unvisited vertices so that the closest vertex to the start is always on top and can be retrieved quickly. But even with these optimizations, it is apparent that Dijkstras algorithm can be fairly inecient. Imagine that the structure of the graph is not arbitrary with an edge of any length between any two vertices in the graph, but rather that the graph is used to represent something in real space. This could be something like roads on a 2-dimensional map, or it could be a division of a 2-dimensional grid into cells (vertices), with edges representing whether movement between two cells is possible or not. If we wanted to nd the shortest path from a point on the left side of a map to a point on the right side of the map, wouldnt we want to search for paths to the right, towards the goal, rather than towards the left, away from the goal? But Dijkstras algorithm will not search in this rather obvious way; instead, it will search outwards from the start vertex in all directions, without any sense of directionality, and it will only reach the goal vertex after it has already searched every vertex closer to the start than the goal vertex, even vertices in a completely dierent direction from the goal vertex. The reason that we are able to think of this possible optimization is because as a result of the structure of the graph, we can estimate the distance from any vertex to the end

vertex based on their positions in 2-dimensional space. This estimate could be done by taking the straight-line diagonal distance between the two vertices using the Pythagorean Theorem. We call this the heuristic function. A* Search uses the idea of this heuristic function to search vertices that are closer to the goal before it searches vertices that are farther away from the goal. Instead of always examining the closest vertex to the start, as in Dijkstras Algorithm, A* Search computes a priority for a vertex by adding together the distance to the start and the value of the heuristic function, which approximates the distance to the goal from that vertex. Mathematically, we always examine the unvisited vertex that has the smallest value of the function F , where F is a function given by F =G+H where G is the shortest path that has been found so far from the start to the vertex under consideration, and H is the heurically estimated distance from the vertex under consideration to the goal vertex. Vertices that are closer to the goal in space will have lower values of H and therefore will tend to have lower values of F , so they will be examined rst, possibly even before vertices that are closer to the start (both distancewise and the actual path to them). In the following diagram, the pink square is the starting point, the blue square is the goal, and the colored areas show what areas A* algorithm scanned.

Care needs to be taken to choose an appropriate heuristic function. If a heuristic function that can overestimate the distance to the goal is used, then it is possible that A* Search will return a path to the goal that is not the shortest path. This will happen because the overestimating heuristic can prevent the vertices that lie on the actual shortest path from ever being visited. However, this problem is not seen if the heuristic is chosen so that it never overestimates the distance to the goal; if this is the case, then A* Search is guaranteed to return the shortest path from the start to the goal. Note that in the case of vertices in space, the straight-line distance between vertices will never overestimate the distance between them, so this typically is a good heuristic function. 3

Pseudocode for A* Search

The following is pseudocode for the A* Search algorithm. Note that while distance, previous, heuristic, and priority are suggested to be arrays, they could also be attributes of the vertices (implemented as structures or objects). It is also implicit that the neighbors of a given vertex can be determined somehow; in actual code we may want to make the graph be represented as an adjacency list. AStarSearch (V [1 . . . n], startVertex, endVertex) // V is graph of n vertices. startVertex and endVertex // are the indices of the start and end vertices. // The output is an array from which the path // from the start to end can be constructed. 1. declare distance[1 . . . n] 2. declare previous[1 . . . n] 3. declare heuristic[1 . . . n] 4. declare priority[1 . . . n] 5. for i = 1 to n do 6. distance[i] 7. heuristic[i] H(Vi , VendV ertex ) 8. priority[i] distance[i] + heuristic[i] 9. previous[i] None 10. endfor 11. declare q = MakePriorityQueue (V1 . . . Vn , priority[1 . . . n]) 12. distance[startVertex] 0 13. priority[startVertex] heuristic[startVertex] 14. ChangePriority (q, startVertex) 15. while q is not empty do 16. v RemoveLowestPriority(q) 17. if distance[v] = then 18. break 19. end if 20. if v = VendVertex then 21. break 22. end if 23. for neighbor N of V [v] do 24. newDistance = distance[v] + EdgeWeight (V [v], V [N ]) 25. if newDistance < distance[N ] and V [N ] is in q then 26. distance[N ] = newDistance 27. priority[N ] = newDistance + heuristic[N ] 28. ChangePriority (q, N ) 29. previous[N ] = v 30. end if 31. done 32. done 33. return previous[1 . . . n]

Running Time of A* Search

Using a specic type of data structure is not required for either Dijkstras algorithm or A* Search, but the eciency of both can be improved by using data structures well-suited for the operations that the algorithms require. As mentioned earlier, we can have the graph be represented as an adjacency list so that we can quickly nd the neighbors of a vertex. This will be done in time proportional to the number of neighbors of that vertex. If we instead opt for a matrix representation of the graph, this operation would take time linear with the total number of vertices in the graph, which usually is much worse. There is also the operation of nding the lowest priority vertex of those that have not yet been visited. With a linear search, this will take time proportional to the number of vertices. This can be made much faster by having the vertices arranged in a heap. The highest vertex can then be found and removed in time proportional to the logarithm base 2 of the number of vertices in the heap. At minimum, the running time of A* Search is (V ), where V is the number of vertices in the graph, because no matter what, all the vertices have to have their distances from the start vertex initialized to innity, and this operation is linear with the number of vertices. In the best case, the path to the end is found immediately, giving an overall running time in the eciency class (V ). However, in the worst case, every edge in the graph is searched before nding a path to the end; the running time in this case would be on the order of (E log V ) in the case of the well-suited adjacency list and minheap structures.

Implementation

The code accompanying this writeup contains an ecient implementation of Dijkstras Algorithm and A* Search and a visualization of it in action. It is written in the C programming language with graphics using Xlib and OpenGL (the graphics are not 3D). A makele is provided. The code is compiled into two executables, run-A star for the A* Search algorithm, and run-dijkstra for Dijkstras algorithm. Run them with the --help option to see all command line arguments. The code is fairly modular and is divided into the following les: dijkstra.c, the actual implementation of the algorithms and their data structures; graphics.c, which contains the code for creating the window and redrawing the screen; input.c, which contains the code for reading in graph les given as a 2D grid of 0s (free spaces) and 1s (obstacles), and turning them into graph data structures; main.c, which processes command line arguments and performs the operation requested. For the most part, the implementation in dijkstra.c follows the pseudocode given above. The graph is represented as an adjacency list, and the vertices are put into a priority queue implemented as a minheap. The actual vertex structures are in the adjacency list, while the minheap, as well as the lists of neighboring vertices, contain only the memory addresses of the actual vertices. 5

One operation that is very important, but may not seem so from the pseudocode, is the lowering of a vertexs priority when a new path is found to it. It is not a standard priority queue operation to change the priority of an arbitrary vertex in the priority queue, as is required by this operation. This can be done by swapping vertices, going up the heap, until the vertex has reached its new place. However, this requires knowing the exact location of the vertex in the heap, which would degenerate into a linear time (with V, the number of vertices) operation if we had to linearly search the heap to nd the vertex that we want to decrease the priority of (note that this vertex is originally found in a dierent way, via the adjacency list, so thats why it still needs to be found in the priority queue). We can instead make this a constant time operation by having the vertices carry an attribute that indicates their current index in the priority queue (index in the array that holds the minheap). Whenever vertices are moved in the heap, this index will be updated; and when a vertex is found via the adjacency list, its position in the priority queue can be found immediately by reading this index. Note that a similar explicitly stored index is not necessarily needed for the vertices position in the adjacency list as well; this is because if the physical vertex structures are located in an array in the adjacency list, the index of a vertex in the adjacency list can be computed by subtracting the memory address of that vertex from the memory address of the start of the array of vertices and dividing by the number of bytes per vertex.

Conclusion

The problem of determining the shortest or lowest-cost path between two vertices in a graph is seen in applications such as route planning on digitized maps and the planning of movement of computer-controlled entities. A* Search, which is an algorithm to solve this problem, is based on Dijkstras algorithm, which is a more general, but typically less ecient, solution to this problem. A* Search uses a heuristic function to search vertices that are more likely to lead to the goal before it searches vertices that are less likely to lead to the goal.

References
A* Pathnding Algorithm to Understand the Specic Process. Unknown Error. N.p., 21 May 2011. Retrieved 9 Oct. 2011. <http://unknownerror.net/201105/35571-a-pathfinding-algorithm-to-understand-the-specific-process.html>. Levitin, Anany. Dijkstras Algorithm. Introduction to the Design and Analysis of Algorithms. 2nd ed. 2007. pp. 323-328. A* Search Algorithm. Wikipedia- the Free Encyclopedia. Retrieved 9 Oct. 2011. http://en.wikipedia.org/wiki/A* search algorithm. Introduction to A*. Stanford University. http://theory.stanford.edu/ amitp/GameProgramming/AStarComparison.html #dijkstras-algorithm-and-best-first-search.

Você também pode gostar