An Introduction to The A* Algorithm Introduction The A* (A-Star) algorithm depicts one of the most popular AI methods used to identify the shortest path between 2 locations in a mapped area. The A* algorithm was developed around 1968 to combine heuristic approaches such as the Best-First-Search (BFS) with more formal algorithms such as Dijsktra. The algorithm basically depicts a state space search method. Many problems can be solved by representing the world in an initial state and for each action to be taken, new states can be generated that reflect what the world would be like if taken. This process is basically repeated until the world is in the state that is specified as a solution, and the route from the initial to the goal state reflects the solution to the problem. Identifying the shortest path between 2 points is also referred to in the literature as pathfinding. In this primer, the popular 8-puzzle game (see Figure 1) is used as the discussion baseline. Terminology With the A* algorithm, a node is referred to as a state that the problem's world can be in. In a pathfinding scenario, a node would just reflect a 2D coordinate of where the system is at any given time. For the 8-puzzle, the nodes represent the positions of all the individual tiles. All the nodes are arranged in a graph where the links among the nodes represent valid steps (that can be considered) to solve the problem. These links are referred to as edges. In the 8-puzzle diagram (see Figure 2), the edges are depict as black arrows. Figure 1: 8-Puzzle Game - Start/Initial & Goal State The actual state space search commences with the initial state and then for each node the nodes below in the graph are expanded by applying all the possible moves that can be made at each point. Generalizes, an actual heuristic (a good enough algorithm that provides an answer quickly) is used at that point to solve this rather large search problem. The heuristic is applied at each node to estimate how far from the goal state the system is. With a pathfinding exercise, this is rather straight forward as it is known how far the system can travel in each step and the actual distance to the goal can easily be calculated. The 8-puzzle scenario is a bit more difficult though and hence various heuristics such as BFS, the Nilsson score, or the A* algorithm may be used to solve the problem.
While evaluating each node in the graph, the heuristic allows the system to estimate how close the state is to the goal. Another aspect that is considered is the actual cost of getting to this point. With pathfinding, an actual movement cost is normally assigned to each square. If the cost is the same, then the cost of each square equals to 1. In scenarios where the system differentiates among different types of terrain (such as moving over grass, water, concrete, sand, rocks, or mud) each type can be associated with a different cost. When analyzing a node, the cost is added up to determine what it took to get to this state. The math is simple as it reflects the sum of the cost of the current node plus all the nodes above it in the graph. Figure 2: 8 Puzzle Game - Edges & State Space generated by 'moving the blank' A* Algorithm - A Brief Discussion Figure 3 is used as the starting point to briefly discuss some of the features of the A* algorithm. One of the major characteristics of the A* algorithm is the maintenance of 2 entities that are labeled as the closed and the fringe lists, respectively. The closed list reflects a record of all the locations that have already been explored/evaluated by the algorithm. The fringe list (sometimes referred to as the open list) records the areas adjacent to those already evaluated locations plus the calculation of the distances traveled from the start with estimated distances to get to the goal. Figure 3: A* Starting Scenario In Figure 3, it is assumed that the current location is referenced via the bright yellow square. So at this point, the bright yellow square is part of the closed list. The light orange squares (8) that are surrounding the yellow one are part of the fringe list as they depict possible options that the algorithm can
experiment with. As the path progresses, the closed and the fringe list grow. Figure 4 depicts a GRID with a wall (represented by the gray squares). In this scenario (Figure 4), the path scratches the wall twice. As the gray area depicts a wall, this path is invalid and the route depicted in Figure 5 has to be taken (move around the wall). Figure 4: A* GRID with Wall - Invalid Path Figure 5: A* with Wall - Valid Path The actual heuristic used to evaluate distances via the A* algorithm can be expressed as: f(n) = g(n) + h(n) [Formula 1] In Formula 1, g(n) represents the cost (distance) of the path from the starting point to any vertex n while h(n) reflects the estimated cost from vertex n to the goal. It is common to use methods such as the Euclidean or the Manhattan distance to quantify h(n). Further, the following definitions are normally being made: x 2 = x coordinate of the goal location x 1 = x coordinate of the current location y 2 = y coordinate of the goal location y 1 = y coordinate of current location dx = x 2 - x 1 dy = y 2 - y 1 The actual (Euclidean) distance equals to sqrt(dx 2 + dy 2 ). It has to be pointed out that the A* algorithm is actually fairly simple. As already discussed, the A* algorithm traditionally operates on 2 sets labeled fringe and closed. To reiterate, the fringe set contains the nodes that are candidates to be
examined. Initially, the fringe set holds only 1 element, the starting position. The closed set contains the nodes that have already been examined and initially, the closed set is empty. From a graphical perspective, the fringe set represents the frontier while the closed set represents the interior of the visited areas. Each node further holds a pointer to its parent node so that the system can keep track of how the node was found. In the actual code for the algorithm, there is a main loop that repeatedly pulls the best node n from the fringe set (aka the node with the lowest f value) and examines it. If n reflects the goal, the algorithm finishes processing. Otherwise, the node n is removed from the fringe set and added to the closed set. Then, its neighbors n' are scrutinized. A neighbor that is in the closed set has already been evaluated and hence will not be re-examined. A neighbor that is in the fringe set will be scrutinized next if and only if its f value becomes the lowest in the fringe set. Otherwise, the neighbor is added to the fringe set (with its parent set to n). The actual path cost to n' (labeled as g(n') in this example) is set to g(n) + movement-cost(n, n'). 8-Puzzle Game To further discuss the A* algorithm, the 8 puzzle game is revisited. The game was popularized by Sam Loyd in the 1870s. It is played on a 3-by-3 GRID with 8 square blocks labeled 1 through 8 and a blank square (see Figure 1). The blank tile is open so that one can move the other tiles into the gap until the puzzle reaches the goal position (state). There are 362,880 different states that the puzzle can be in and in order to find a solution, the search process has to identify a route through them. From most search positions, the number of edges equals to 2. That implies that the number of nodes in each level of the search (think of a tree structure) equals to 2 d (where d represents the depth). Hence, if the number of steps to solve a particular state equals to 18, a whopping 262,144 nodes are possible just at this level. Simplified, the game state is as simple as representing a list of the 9 squares and what they hold. The rules applied to the game are simple as well. If there is a blank tile either above, below, to the left, or to the right of a given tile, then one can move that tile into the space (see Figure 2). To solve the puzzle, one has to find the path from the start state through the graph down to the goal state. In other words, the goal is to rearrange the blocks so that they are in order. One is only permitted to slide the blocks horizontally or vertically into the blank square. The following diagram shows a sequence of legal moves from an initial board position (left) to the goal position (right). 0 1 3 1 0 3 1 2 3 1 2 3 1 2 3 4 2 5 => 4 2 5 => 4 0 5 => 4 5 0 => 4 5 6 7 8 6 7 8 6 7 8 6 7 8 6 7 8 0 initial move1 move2 move3 goal As already discussed, the 8 puzzle game is a bit more difficult to solve than the pathfinding example already described in this primer. Anyhow, an A* algorithm based solution to solve the puzzle is presented here. The solution elaborated on in this primer is based on an actual priority queue. In this solution, a state of the game is defined to be (1) the board position, (2) the number of moves made to reach the position, and (3) the previous state. First, insert the initial state (the initial board, 0 moves, and a null previous state) into a priority queue. Then, (1) delete from the priority queue the state with the minimum priority and (2) insert into the priority queue all the neighboring states (those that can be reached in 1 move). Repeat this procedure until the current state reflects the goal state. The success of this approach is tightly coupled to the appropriate choice of a distance/priority function. In this primer, 2 (priority) distance functions are discussed:
1. The Hamming function. A function for a given state is represented by the number of blocks in the wrong position plus the number of moves made so far to get to this state. Instinctively, states with a small number of blocks in the wrong position are close to the goal state and states that have been reached using a small number of moves are preferred. 2. The Manhattan function. The distance function for a given state is reflected by the sum of the distances (sum of the vertical and horizontal distance) from the blocks to their goal positions, plus the number of moves made so far to get to this state. To illustrate, the Hamming and the Manhattan function values of the initial state (for the example depicted below) can be expressed as being 5 and 10, respectively. 8 1 3 1 2 3 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 4 0 2 4 5 6 ---------------------- ---------------------- 7 6 5 7 8 0 1 1 0 0 1 1 0 1 1 2 0 0 2 2 0 3 initial goal Hamming = 5 Manhattan = 10 One observation that can be made is that in order to solve the puzzle based on a given state on the priority queue, the total number of moves (including those already made) equals to at least its function value (using either the Hamming or Manhattan function). This statement holds true for the Hamming function as each block that is out of place has to move at least once to reach its goal position. In regards to the Manhattan function, the statement is true as each block has to move its Manhattan distance from its goal position. It has to be pointed out that the that the blank tile is omitted when computing the Hamming or Manhattan function values. As a result, as soon as a state is taken out of the queue, the application has not only discovered a sequence of moves from the initial board to the board associated with this state, but actually one that provides the fewest number of moves. While implementing this procedure straight forward, one has to be aware of the fact that states that are corresponding to the same board position may be queued onto the priority queue n times. To prevent the unnecessary exploration of these useless states, when considering the neighbors of a state, the suggestion made is to not insert the neighbor if its board position is the same as the previous state (see diagram below). 8 1 3 8 1 3 8 1 3 4 0 2 4 2 0 4 0 2 7 6 5 7 6 5 7 6 5 previous current disallow A* Implementation & Benchmark For this primer, an A* algorithm was implemented in C++ to solve the X-Puzzle game. The implementation supports larger than 8-tile games hence the name X-Puzzle. The solution is capable of using either the Manhattan or Hamming distance to solve the puzzle. The following sequence below shows the moves made to solve a simple 15-puzzle (via the Manhattan distance). When the Manhattan distance was used, the implemented code solved the puzzle in 23 moves and it took 0.098 seconds to get to the goal state (on an Intel 4core system configured with 8GB RAM). The benchmark was executed 10 times and the reported response time equals to the average over all 10 runs. The CV across the 10 test
runs was less than 4% and hence the results are reproducible. On the other hand, executing the same puzzle (same initial state) via the Hamming method also resulted in 23 moves but the execution time increased to 0.556 seconds. Researching the performance delta revealed that the Manhattan distance visited only a fraction of the vertices that were evaluated while executing the Hamming function. initial move1 move2 move3 2 3 4 8 2 3 4 8 2 3 4 8 2 3 4 8 1 6 7 12 1 6 0 12 1 6 7 12 1 6 7 12 5 10 0 11 5 10 7 11 5 10 0 11 5 10 11 0 9 14 15 13 9 14 15 13 9 14 15 13 9 14 15 13 move4 move5 move6 move7 2 3 4 8 2 3 4 8 2 3 4 8 2 3 4 8 1 6 7 12 1 6 7 12 1 6 7 12 1 6 7 12 5 10 11 13 5 10 11 13 5 10 0 13 5 10 13 0 9 14 15 0 9 14 0 15 9 14 11 15 9 14 11 15 move8 move9 move10 move11 2 3 4 8 2 3 4 0 2 3 0 4 2 0 3 4 1 6 7 0 1 6 7 8 1 6 7 8 1 6 7 8 5 10 13 12 5 10 13 12 5 10 13 12 5 10 13 12 9 14 11 15 9 14 11 15 9 14 11 15 9 14 11 15 move12 move13 move14 move15 0 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 6 7 8 0 6 7 8 5 6 7 8 5 6 7 8 5 10 13 12 5 10 13 12 0 10 13 12 10 0 13 12 9 14 11 15 9 14 11 15 9 14 11 15 9 14 11 15 move16 move17 move18 move19 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8 10 13 0 12 10 13 11 12 10 13 11 12 10 0 11 12 9 14 11 15 9 14 0 15 9 0 14 15 9 13 14 15 move20 move21 move22 move23 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8 0 10 11 12 9 10 11 12 9 10 11 12 9 10 11 12 9 13 14 15 0 13 14 15 13 0 14 15 13 14 0 15 goal 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 References 1. Zeng, Church, "Finding shortest paths on real road networks: the case for A*". Geo Science, 2009 2. Dechter, Judea, "Generalized best-first search strategies and the optimality of A*", 1985 3. Malik; Allard, "Aε an efficient near admissible heuristic search algorithm", AI Conference, 1983 4. Goldberg et al, "Efficient Point-to-Point Shortest Path Algorithms", Princeton University, 2015 5. Harder, 8 and 15 Puzzles, University of Waterloo, 2015 6. A* Wiki, 2015 7. A* Online Blogs, 2015