A * algorithm details

Source: Internet
Author: User

Part 1: A * algorithm Overview
A * algorithm is a typical Heuristic Search Algorithm in artificial intelligence.

I. What is a heuristic search algorithm:

Before you start, you need to search for the status space. Status space search. If it is based on a professional point, the problem solving process is represented by the process of searching for this path from the initial state to the target State. In layman's terms, when solving a problem, the process of finding a problem can start from the problem to the result of the problem (as though not popular ). There are many branches in the process of solving the problem, mainly because of the uncertainty of the solution conditions in the process of solving the problem, which is caused by incompleteness. This makes the solution path a lot, which constitutes a graph, we can say that this figure is an empty state. The problem is actually solved by finding a path in this figure from the beginning to the result. The search process is to search the status space.

Frequently Used status space searches have priority in depth and breadth. Breadth First is to find the target layer by layer until the target is found. Depth first searches for one branch in a certain order, and then finds another branch until the target is found. These two calculation methods are described in the data structure book. You can refer to these books for more detailed explanations.

One major drawback of the breadth and depth preference search mentioned above is that they all work in a given State Space. This is a suitable algorithm when the state space is small, but it is not desirable if the state space is large and unpredictable. His efficiency is too low to be completed. Heuristic Search is required here.

Heuristic Search is to evaluate the position of each search in the state space to obtain the best position, and then search until the target. In this way, a large number of fearless search paths can be omitted, and efficiency is mentioned. In heuristic search, location estimation is very important. Different estimates can have different effects. Let's first look at how the valuation is expressed.

In the inspiration, the valuation is represented by the valuation function, for example:

F (n) = g (n) + H (N)

Where F (n) is the estimated function of node N, the actual cost of g (n) from the initial node to the N node in the real state space, H (N) it is the estimated cost of the optimal path from N to the target node. Here, H (n) mainly reflects the inspiration information of search, because g (n) is known. For details, g (n) indicates the priority of search breadth. However, when H (n)> G (N), g (n) can be omitted to improve efficiency.

Ii. First recognized a * algorithm:

There are actually many heuristic search algorithms, such as local preferred search and best preferred search. Of course, a * is also. These algorithms use heuristic functions, but they have different policies when selecting the best search node. The local preferred search method is to select the "best node" in the search process and discard other sibling nodes. Father's Day points have to be searched continuously. The search results are obvious. Because other nodes are abandoned, the best nodes may also be discarded, because the best node for solving is the best at this stage, not necessarily the global best. It is better to give priority to a more intelligent node. When searching, the node is not discarded (unless the node is a dead node ), in the evaluation of each step, the current node and the previous node are compared to get an "Best node ". This effectively prevents the loss of "best node. So what kind of algorithm is a * algorithm? In fact, the * algorithm is also the best priority algorithm. Only some constraints need to be added. When solving some problems, we hope to be able to solve the Shortest Path of the state space search, that is, to solve the problem using the shortest method. A * is doing this kind of thing! First, let's define it. If an estimate function can find the shortest path, we call it the recoverability. A * algorithm is the best priority algorithm that can be adopted. The evaluation function grams of A * algorithm are represented:

F' (n) = G' (n) + H' (N)

Here, f' (n) is the evaluation function, and G' (n) is the shortest path value from the start point to the end point, H' (N) it is the inspiration value from N to the target's most Broken Circuit. Because f' (n) is actually unknown in advance, we use the evaluate function f (n) to make an approximation. G (n) can replace G' (N), but G (n)> = G' (n) can be used (in most cases, it is satisfied, so you don't have to consider it ), H (n) instead of H '(N), but h (n) <= H' (n) is only available (this is particularly important ). It can be proved that applying such an evaluation function can find the shortest path, that is, it can be adopted. We say the best Priority Algorithm for applying such an evaluation function is the * algorithm. Ha! Do you understand? I certainly don't understand! Next look!

For example, the breadth-first algorithm is a special case of the * algorithm. Where G (n) is the number of layers where the node is located, H (n) = 0, and H (n) is less than H '(N ), therefore, we can see that the breadth-first algorithm is a feasible one. Actually. Of course, it is the most smelly A * algorithm.

Another question is the information about H (N)-inspired functions. H (n) refers to the constraints when estimating the value of a node. If more information or more constraints exist, more nodes will be excluded, the better the evaluate function, or the better the algorithm. This is why the breadth-first algorithm is so smelly. The H (n) of the algorithm is 0, and there is no inspiration at all. However, due to real-time problems in game development, the more information H (n) is, the larger the computing workload and the more time it takes. The information of H (n) should be appropriately reduced, that is, the constraint conditions should be reduced. However, the accuracy of the algorithm is poor, and there is a balance problem here. That's all you need!
To predict the application of a * algorithm, see in-depth A * algorithm.

Part 2: go deep into a * algorithm-analysis on the application of a * Algorithm in searching for the shortest path

I. Preface

Here I will discuss the practical application of the * algorithm, and give an example of the * Algorithm in the shortest path search. It is worth noting that the basic concepts of a * are not introduced here. If you are still not clear about the * algorithm, please refer to the companion article "first understanding a * algorithm".

The example here is a source program on the Amit homepage. You can download it from the Amit website or on my website. When using this source program, you should abide by certain conventions.

Ii. Programming principles of a * Algorithm


A * algorithm is one of the best priority algorithms. There are only some constraints. First, let's see how the best priority algorithm is written. The following State space is available: (the starting position is A, the target position is P, and the number after the letter represents the estimated value of the node ).
The following State space is available: (the starting position is A, the target position is P, and the number after the letter indicates the estimated value of the node)

Figure 1 Status Space

Set two tables: open and closed during the search process. The Open Table stores all the nodes that have been generated but not tested. The closed table records the accessed nodes. One step in the algorithm is to rearrange the Open table based on the evaluation function. In this way, only the nodes with the best status in the Open table are considered for each step in the loop. The specific search process is as follows:

1) initial status:
Open = [A5]; closed = [];
2) estimate A5, search for sub-nodes, and put them in the Open table;
Open = [B4, C4, D6]; closed = [A5]
3) estimate B4, search for subnodes, and put them into the open table;
Open = [C4, E5, F5, D6]; closed = [B4, A5]
4) estimate C4; search for subnodes and put them into the open table;
Open = [H3, G4, E5, F5, D6] closed = [C4, B4, A5]
5) estimate H3, search for sub-nodes, and put them in the Open table;
Open = [O2, P3, G4, E5, F5, D6]; closed = h3c4, B4, A5]
6) estimate O2, search for sub-nodes, and put them into the open table;
Open = [P3, G4, E5, F5, D6]; closed = [O2, H3, C4, B4, A5]
7) estimate P3 and the solution has been obtained;

The pseudo program of the algorithm is as follows:

Best_first_search ()
{
Open = [Start Node];
Closed = [];
While (Open table is not empty)
{
Obtain a node X from open and delete it from the Open table.
If (X is the target node)
{
Obtain the path;
Return path;
}
For (Y of each X subnode)
{
If (Y is not in the Open table or close table)
{
Evaluate the value of Y;
Insert Y to the Open table. // No sorting has been performed.
}
Else if (Y in the Open table)
{
If (the estimated value of Y is smaller than the estimated value of Open table)
Update the valuation value in the Open table;
}
Else // y in the close table
{
If (the estimated value of Y is less than the estimated value of close table)
{
Update the valuation value in the close table;
Remove nodes from the close table and put them in the Open table;
}
}
Insert x nodes into the close table;
Sort the nodes in the Open table according to the estimated value;
} // End
} // End while
} // End func

When the pseudo program comes out, it should not be a problem to write a source program. The program of the * algorithm is the same as that of the algorithm. You only need to pay attention to the H (n) constraints of g (n) In the evaluate function.

2. Use the * algorithm to search for the shortest path
In game design, the shortest path search is often involved. Now, a better method is to use the * Algorithm for design.
Note that the following are all modeled based on the classastar program, which is a complete project. Contains an EXE file. You can check it out first.
The core of a * algorithm is the evaluation function f (n), which consists of g (N) and H (n. G (n) is the price that has passed, and H (n) is the estimated price of N to the target. In this example, g (n) indicates the depth from the starting node to N nodes in the state space, and H (n) indicates the straight line distance from the position of the map where n nodes are located to the target position. One is the state space and the other is the actual map. Do not make a mistake. In detail, there is an object A. The coordinates on the map are (XA, ya), and the coordinates of the target B to which a will arrive are (XB, Yb ). When you start searching, set a Start Node 1 to generate eight child nodes 2-9 because there are eight directions.

Figure 2 node chart
First look at the search main function:
Void astarpathfinder: findpath (INT Sx, int Sy, int dx, int Dy) <br/>{< br/> node * node, * bestnode; <br/> int tilenumdest; </P> <p> // obtain the target location for determination. <br/> tilenumdest = tilenum (sx, Sy ); </P> <p> // generate open and closed tables <br/> open = (node *) calloc (1, sizeof (node )); <br/> closed = (node *) calloc (1, sizeof (node); </P> <p> // generate the Start Node, and put it in the Open Table <br/> node = (node *) calloc (1, sizeof (node); <br/> node-> G = 0; </P> <p> // This is the calculated H value <br/> node-> H = (DX-SX) * (DX-SX) + (dy-sy) * (dy-sy); // shocould really use SQRT (). </P> <p> // This is the calculated F value, that is, the estimated value <br/> node-> F = node-> G + node-> h; <br/> node-> nodenum = tilenum (dx, Dy); <br/> node-> X = DX; <br/> node-> Y = Dy; </P> <p> open-> nextnode = node; // make open list point to first node <br/> (;;) <br/>{< br/> // obtain a node with the best valuation value from the Open Table <br/> bestnode = returnbestnode (); </P> <p> // exit if the node is the target node <br/> If (bestnode-> nodenum = tilenumdest) // if we 've found the end, break and finish <br/> break; <br/> // otherwise, a subnode is generated. <br/> generatesuccessors (bestnode, Sx, sy); <br/>}< br/> Path = bestnode; <br/>}

Let's take a look at generatesuccessors:

  Void astarpathfinder: generatesuccessors (node * bestnode, int dx, int Dy) <br/>{< br/> int X, Y; </P> <p> // generate child nodes in eight directions in sequence, which is simple! <Br/> // upper-left <br/> If (freetile (x = bestnode-> X-tilesize, y = bestnode-> Y-tilesize )) <br/> generatesucc (bestnode, X, Y, dx, Dy); <br/> // upper <br/> If (freetile (x = bestnode-> X, y = bestnode-> Y-tilesize) <br/> generatesucc (bestnode, X, Y, dx, Dy ); <br/> // upper-right <br/> If (freetile (x = bestnode-> X + tilesize, y = bestnode-> Y-tilesize )) <br/> generatesucc (bestnode, X, Y, dx, Dy ); <br/> // right <br/> If (freetile (x = bestnode-> X + tilesize, y = bestnode-> Y) <br/> generatesucc (bestnode, x, Y, dx, Dy); <br/> // lower-right <br/> If (freetile (x = bestnode-> X + tilesize, y = bestnode-> Y + tilesize) <br/> generatesucc (bestnode, X, Y, dx, Dy ); <br/> // lower <br/> If (freetile (x = bestnode-> X, Y = bestnode-> Y + tilesize) <br/> generatesucc (bestnode, x, Y, dx, Dy); <br/> // lower-left <br/> If (freetile (x = bestnode-> X-tilesize, y = bestnode-> Y + tilesize) <br/> generatesucc (bestnode, X, Y, dx, Dy ); <br/> // left <br/> If (freetile (x = bestnode-> X-tilesize, y = bestnode-> Y) <br/> generatesucc (bestnode, x, Y, dx, Dy); <br/>}

Look at the most important function generatesucc:

  Void astarpathfinder: generatesucc (node * bestnode, int X, int y, int dx, int Dy) <br/>{< br/> int g, tilenums, c = 0; <br/> node * Old, * successor; </P> <p> // calculate the G value of the subnode <br/> G = bestnode-> G + 1; // G (successor) = g (bestnode) + cost of getting from bestnode to successor <br/> tilenums = tilenum (x, y ); // identification purposes </P> <p> // do subnodes need to open the table again? <Br/> If (old = checkopen (tilenums ))! = NULL) // if equal to null then not in open list, <br/> // else it returns the node in old <br/> {<br/> // If the node is in <br/> for (C = 0; C <8; c ++) <br/> If (bestnode-> child [c] = NULL) // Add old to the list of bestnode's children <br/> // (or successors ). <br/> break; <br/> bestnode-> child [c] = old; <br/> // compare the values in the Open table with the current values (as long as the G value is compared) <br/> If (g) // if our new G value is parent = bestnode; <br /> Old-> G = g; <br/> old-> F = G + Old-> h; <br/>}< br/> else // in the closed table? <Br/> If (old = checkclosed (tilenums ))! = NULL) // if equal to null then not in open list <br/> // else it returns the node in old <br/>{< br/> // If/> for (C = 0; c <8; C ++) <br/> If (bestnode-> child [c] = NULL) // Add old to the list of bestnode's <br/> // children (or successors ). break; <br/> bestnode-> child [c] = old; <br/> // compare the estimated value in the closed table with the current estimated value (as long as the G value is compared) <br/> If (g) // if our new G value is parent = bestnode; <br/> ol D-> G = g; <br/> old-> F = G + Old-> h; // update the estimated values of all old subnodes in sequence <br/> propagatedown (old); // since we changed the G value of old, we need <br/> // to propagate this new value downwards, I. e. <br/> // do a depth-first traversal of the tree! <Br/>}< br/> else // not in the Open table or in the close table <br/>{< br/> // generate a new node <br/> br/> successor = (node *) calloc (1, sizeof (node); <br/> successor-> parent = bestnode; <br/> successor-> G = g; <br/> successor-> H = (X-dx) * (X-dx) + (Y-dy) * (Y-dy ); // shocould do SQRT (), but since we <br/> don't really <br/> successor-> F = G + successor-> h; // care about the distance but just which branch <br/> looks successor-> X = X; // better this shoshould suffice. anyayz it's faster. <br/> successor-> Y = y; <br/> successor-> nodenum = tilenums; <br/> // Insert the data into the Open table and sort the data at the same time. <Br/> insert (successor); // insert successor on open list wrt f <br/> for (C = 0; C <8; C ++) <br/> If (bestnode-> child [c] = NULL) // Add old to the list of bestnode's <br/> children (or successors ). <br/> break; <br/> bestnode-> child [c] = successor; <br/>}< br/>}

Take a closer look at this program and you will find that this program is different from the pseudo program mentioned above. In the generatesucc function, when the subnode is in the closed table, the child node is not deleted from the closed table and put into the Open table. Instead, it directly recalculates the estimated values of all the subnodes of the node (using the propagatedown function ). This is faster. In addition, when the subnode is in an Open table or a closed table, after the estimated value is re-calculated, the nodes in the Open table are not re-ordered.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.