A * astar Algorithm

Source: Internet
Author: User
Tags array definition

I wanted to write something about the * Algorithm for a long time, but it seems that I am busy every day, but there is nothing actually done. It's so impetuous! So let's write a summary tonight!

A * algorithm is a classic algorithm that can only be used as a heuristic search algorithm. The differences between a search algorithm and a general search algorithm (such as DFS and BFS) in terms of language description are as follows, I think it is very well described in a sentence in "code Daquan": "when driving a car to reach someone's house, the algorithm is written as follows: traveling along the 167 expressway to Puyallup south, drive 4.5 miles up the hill from exit XX, turn right at the traffic light next to a grocery store, turn left at the first intersection, and go in from the driveway of the big brown house on the left. The heuristic is: find out the last letter we sent you and drive to the town according to the address on the letter. When you get there, you ask where our house is, and everyone here knows us, someone will be willing to help you. If you cannot find someone, call us at a phone booth and we will pick you up ". It sounds a little abstract. Next let's take a look at the * algorithm!

Note: The figures and ideas in this article are based on http://www.policyalmanac.org/games/astartutorial.htm. thank you very much for the classic article!



If we want to find a path from a green point to a red point, we need to find a path by Heuristic means. In the end, there is no way to find it. We can only try it from the start point! We need to define an Open table. What is put in the Open table? It is the point currently being considered, and the points surrounding it need to be added as possible points on the path. This may be a bit abstract, so let's take a look at the following:

We start searching from the starting point:

 

1: Start from vertex A and store it as a pending vertex into an open table. Your path may pass through the square it contains, or it may not. Basically, this is a list of squares to be checked.
2: Find all the squares that can be reached or passed by (neighbors) around the start point, if there are obstacles. You don't need to consider them, and add them to the Open table for other LVS nodes. These neighboring nodes recognize the current node as the parent node. (The storage of the parent node is required! Because when we find the last vertex, We need to trace back through the parent node to find all vertices until the Start Node! It is a complete path !)
3: delete Vertex a from the Enable list and add it to a close list. The list stores all squares that do not need to be checked again.

At this point, you should form a structure. In the figure, the dark green square is the center of your initial square. It is marked with a light blue stroke to indicate that it is added to the closed list. All adjacent cells are now in the open list, and they are drawn in a light green. Each square has a gray pointer pointing to its parent square, that is, the square of the beginning.



Which of the following points should we continue to consider! I think you should know the so-called heuristic functions, the so-called weights, and so on (here the so-called weights are the length of the path strength ). Yes. We need the point with the smallest value of F in the Open table! Why? Of course, the smaller the weight, the closer it is to the target point!

If we set the weight to F, how does F calculate it! We have two items! G and H,

G = it takes a long time to move the path from start a to the generated path to the specified grid.
H = estimated moving cost of moving the square from the grid to end B. This is often called heuristic. This is because it is just a guess. We cannot know the path length in advance. (But we need to know that, although we only guess, as long as it is based on a unified standard, the trend of relative distance remains unchanged! This is important! )

For example:H valueThe estimation uses the "Manhattan" method, that is, the current point, to the target point, the number of grids in the horizontal and vertical directions is added, that is, the value of H!

(Note: we do not consider skipping obstacles! That is, the obstacle is also a normal grid! This is why H is only used for prediction! The so-called heuristic! )

Then, for the first graph, the H value from the start point to the end point is: 4 grids with horizontal difference and 0 grids with vertical difference, then H = 4 + 0 = 4;

Of course, there are other methods, such as linear distance, SQRT (POW (DES. X-Src. X) + POW (DES. Y-Src. y ~


 

For G value!In this example, the cost of horizontal or vertical movement is 10, and that of diagonal lines is 14. We take these values because the distance along the diagonal line is about 1.414 times the length of root 2 consumed by moving horizontally or vertically. We use 10 and 14 for simplicity. Sometimes simplification is very important ~

(In fact, as long as the distance reflects the basic multiples! )

The G, H, and f values of the starting point and surrounding points are clearly displayed! (F in the upper left corner, G in the lower left corner, and H in the lower right corner)


For the G value, as long as it is a horizontal and vertical neighbor, set it to + 10 and the oblique neighbor + 14 ~ Computation is really easy ~ Haha ~

For the H value, that is, the number lattice ~

F = G + H

Note that the preceding neighbor nodes are added to the Open table ~~~ The start point is deleted from open and added to close ~

Then calculate:

Select the smallest F value from the Open table, and then consider its neighbors for recycling! Until the end point is added to close, the path is found! Or open is empty. The path is not found!

(How do we select the smallest point !? We use heap sorting to quickly select the minimum value ~ )

We can see that the smallest value of F is the point on the right of the starting point. The box below indicates ~


Then consider the neighbors:

There are several possibilities for neighbors.!

1: The neighbor is already in the close table, so you do not need to consider it ~

2: The neighbor is an obstacle and you do not need to consider e.

3: If the neighbor is not in the Open table, add the neighbor to open and assign the parent node of the next neighbor to the current node.

4: When the neighbor is in open, you need to check the size of the G value of the neighbor and the (G value + the distance from the current vertex to the neighbor vertex (10 or 14) of the current vertex, if you are closer to this point (I .e., the G value is smaller), replace the parent node of this point with the current point! (Note: For the same vertex, the value of G must be smaller than that of F! Because H is the same !)

The following is a further illustration:

Then, follow the above ideas to know that the end point is added to the close table! (The ultimate illustration is as follows)

In the end, we can get the path: (as we have said before, it is easy to get the path from the parent node to backend ~ )

I have said so much and I don't know if I can do it. I still need to summarize it!

Summary:

1: add the start point to the Open Table

2: loop until open is null or the end is added to the close table

Otherwise, find the node with the smallest F value in the Open Table (use heap sorting to get a small value point), delete this point from open, and add close!

(If the minimum vertex has been extracted, you need to sort the Open table from the new one. The first vertex is the minimum vertex F !)

Process eight neighbors:

If: 1: The neighbor is already in the close table, you do not need to consider it ~

2: The neighbor is an obstacle and you do not need to consider e.

3: If the neighbor is not in the Open table, add the neighbor to open and assign the parent node of the next neighbor to the current node.

4: When the neighbor is in open, you need to check the G value of the neighbor and the distance between the current vertex (G value + the current vertex and the neighbor vertex ).

(10 or 14). If the node is closer to this vertex (that is, the G value is smaller), replace the parent node of This vertex with the current vertex! (Note: For the same vertex, the value of G must be smaller than that of F! Because H is the same !)

Note: when the parent node changes, the minimum vertex in the Open Table may change, so you need to sort it again to get the most

Smaller!

3: end. You can find the path based on the exit cycle condition! So the following work is easy ~


The basic principle is like this ~

Below is a simple C language DEMO code, just to demonstrate the principle, without paying attention to other issues, so everyone can't blame it ~

Note: In the array, 1 represents the start point, 2 represents the end point, 0 represents the pass, and 3 represents the obstacle.

 

# Include <stdio. h> # include <stdlib. h> # define startnode1 # define endnode2 # define barrier3typedef struct astarnode {int s_x; // coordinates (the final output path is required) int s_y; int s_g; // The distance from the start point to this point (f can be obtained from G and H, F is omitted here, F = G + H) ints_h; // The distance between the start point and the end point of the heuristic function prediction int s_style; // node type: Start Point, end point, obstacle struct astarnode * s_parent; // The parent node int s_is_in_closetable; // whether to close int s_is_in_opentable in the table; // whether it is in the Open Table} astarnode, * pastarnode; astarnode map_maze [10] [10 ]; // Vertex array pastarnode open_table [100]; // Open Table pastarnode close_table [100]; // close table int open_node_count; // number of nodes in the Open Table int close_node_count; // close the number of nodes in the table pastarnode path_stack [100]; // The stack int top of the Save Path =-1; // stack top // exchange two elements // void swap (INT idx1, int idx2) {pastarnode TMP = open_table [idx1]; open_table [idx1] = open_table [idx2]; open_table [idx2] = TMP;} // heap adjustment // void adjust_heap (INT/* I */nindex) {int curr = nind Ex; int child = curr * 2 + 1; // obtain the left child idx (the subscript starts from 0, and all the children are curr * 2 + 1) int parent = (curr-1)/2; // obtain the parent idxif (nindex <0 | nindex> = open_node_count) {return ;} // adjust down (compare left and right children and cuur parent) // while (Child <open_node_count) {// The root Heap has a parent value less than the child value. // If (Child + 1 <open_node_count & open_table [child]-> s_g + open_table [child]-> s_h> open_table [child + 1]-> s_g + open_table [Child + 1]-> s_h) {++ child; // determines the size of the left and right children Small} If (open_table [curr]-> s_g + open_table [curr]-> s_h <= open_table [child]-> s_g + open_table [child]-> s_h) {break;} else {swap (child, curr); // exchange node curr = Child; // judge the current child node child = curr * 2 + 1; // judge the left child} If (curr! = Nindex) {return;} // adjust it upwards (you only need to compare cuur child and parent) // while (curr! = 0) {If (open_table [curr]-> s_g + open_table [curr]-> s_h> = open_table [Parent]-> s_g + open_table [Parent]-> s_h) {break;} else {swap (curr, parent); curr = parent; parent = (curr-1)/2 ;}}} // determine whether the neighbor can enter the Open Table // void insert_to_opentable (int x, int y, pastarnode curr_node, pastarnode end_node, int W) {int I; if (map_maze [x] [Y]. s_style! = Barrier) // not an obstacle {If (! Map_maze [x] [Y]. s_is_in_closetable) // It is not in the closed table {If (map_maze [x] [Y]. s_is_in_opentable) // In the Open table {// determine whether it is a more optimized path // If (map_maze [x] [Y]. s_g> curr_node-> s_g + W) // if it is more optimized, {map_maze [x] [Y]. s_g = curr_node-> s_g + W; map_maze [x] [Y]. s_parent = curr_node; for (I = 0; I <open_node_count; ++ I) {If (open_table [I]-> s_x = map_maze [x] [Y]. s_x & open_table [I]-> s_y = map_maze [x] [Y]. s_y) {break;} adjust_heap (I ); // Below adjustment point} else // not in open {map_maze [x] [Y]. s_g = curr_node-> s_g + W; map_maze [x] [Y]. s_h = ABS (end_node-> s_x-x) + ABS (end_node-> s_y-y); map_maze [x] [Y]. s_parent = curr_node; map_maze [x] [Y]. s_is_in_opentable = 1; open_table [open_node_count ++] = & (map_maze [x] [Y]); }}} // search for neighbors // search for the top and bottom eight neighbors // void get_neighbors (pastarnode curr_node, pastarnode end_node) {int x = curr_node-> s_x; int y = curr_node-> s_y; // Process the eight neighbors below! // If (x + 1)> = 0 & (x + 1) <10 & Y> = 0 & Y <10) {insert_to_opentable (x + 1, y, curr_node, end_node, 10);} If (X-1)> = 0 & (X-1) <10 & Y> = 0 & Y <10) {insert_to_opentable (x-1, Y, curr_node, end_node, 10 );} if (x> = 0 & x <10 & (Y + 1)> = 0 & (Y + 1) <10) {insert_to_opentable (X, Y + 1, curr_node, end_node, 10);} If (x> = 0 & x <10 & (Y-1)> = 0 & (Y-1) <10) {insert_to_opentable (x, Y-1, curr_node, end_node, 10);} If (x + 1)> = 0 & (x + 1) <10 & (Y + 1)> = 0 & (Y + 1) <10) {insert_to_opentable (x + 1, Y + 1, curr_node, end_node, 14);} If (x + 1)> = 0 & (x + 1) <10 & (Y-1)> = 0 & (Y-1) <10) {insert_to_opentable (x + 1, Y-1, curr_node, end_node, 14);} If (X-1)> = 0 & (X-1) <10 & (Y + 1)> = 0 & (Y + 1)) <10) {insert_to_opentable (x-1, Y + 1, curr_node, end_node, 14);} If (X-1)> = 0 & (X-1) <10 & (Y-1)> = 0 & (Y-1) <10) {insert_to_opentable (x-1, Y-1, curr_node, end_node, 14 );}} int main () {// map array definition // astarnode * start_node; // The starting point astarnode * end_node; // The end point astarnode * curr_node; // the current point int is_found; // whether to find the path int maze [] [10] = {// only assign a value to map_maze {,}, {0 ,}, {,}, {, 0, 0, 0, 0,}, {, 0, 0, 0, 0, 0, 0}, {3, 0, 3, 0, 0, 0, 3, 0}, {3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {3, 3, 0,}, {3, 0, 0, 0, 3,},}; int I, j, X; // prepare the following: // for (I = 0; I <10; ++ I) {for (j = 0; j <10; ++ J) {map_maze [I] [J]. s_g = 0; map_maze [I] [J]. s_h = 0; map_maze [I] [J]. s_is_in_closetable = 0; map_maze [I] [J]. s_is_in_opentable = 0; map_maze [I] [J]. s_style = maze [I] [J]; map_maze [I] [J]. s_x = I; map_maze [I] [J]. s_y = J; map_maze [I] [J]. s_parent = NULL; If (map_maze [I] [J]. s_style = startnode) // start point {start_node = & (map_maze [I] [J]);} else if (map_maze [I] [J]. s_style = endnode) // end {end_node = & (map_maze [I] [J]);} printf ("% d", maze [I] [J]);} printf ("\ n");} // use the * algorithm to obtain the path // open_table [open_node_count ++] = start_node; // Add the start point to the Open Table start_no De-> s_is_in_opentable = 1; // Add the Open Table start_node-> s_g = 0; start_node-> s_h = ABS (end_node-> s_x-start_node-> s_x) + ABS (end_node-> s_y-start_node-> s_y); start_node-> s_parent = NULL; if (start_node-> s_x = end_node-> s_x & start_node-> s_y = end_node-> s_y) {printf ("start point = end point! \ N "); Return 0;} is_found = 0; while (1) {// for test // * For (x = 0; x <open_node_count; ++ X) {printf ("(% d, % d): % d", open_table [x]-> s_x, open_table [x]-> s_y, open_table [x]-> s_g + open_table [x]-> s_h);} printf ("\ n"); */curr_node = open_table [0]; // The first vertex of the Open table must be the vertex with the smallest F value (obtained through heap sorting) open_table [0] = open_table [-- open_node_count]; // place the last vertex to the first vertex, and then adjust the heap adjust_heap (0); // adjust the heap close_table [close_node_count ++] = curr _ Node; // Add the current vertex to the close table curr_node-> s_is_in_closetable = 1; // If (curr_node-> s_x = end_node-> s_x & curr_node-> s_y = end_node-> s_y) already exists in the close table // The end point is in close, end {is_found = 1; break;} get_neighbors (curr_node, end_node); // process neighbor if (open_node_count = 0) // No path reaches {is_found = 0; break ;}}if (is_found) {curr_node = end_node; while (curr_node) {path_stack [++ top] = curr_node; curr_node = curr_node-> s_parent ;} While (top> = 0) // The output path is shown below ~ {If (top> 0) {printf ("(% d, % d) -->", path_stack [Top]-> s_x, path_stack [top --]-> s_y);} else {printf ("(% d, % d)", path_stack [Top]-> s_x, path_stack [top --]-> s_y) ;}} else {printf ("") ;}puts (""); Return 0 ;}

 

 




 

 




 

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.