The Application of Genetic Algorithm in the maze game, and the genetic algorithm in the maze

Source: Internet
Author: User

The Application of Genetic Algorithm in the maze game, and the genetic algorithm in the maze

My Data Mining Algorithm Library:Https://github.com/linyiqun/DataMiningAlgorithm
My Algorithm Library:Https://github.com/linyiqun/lyq-algorithms-lib

Preface

Genetic (GA) algorithms are very interesting because they use the knowledge of biological evolution theory to solve the problem. The core of an algorithm is to inherit genes with better environmental fitness to the next generation. This is the key selection operation. The overall phase of a genetic algorithm is divided into selection, crossover, and mutation operations, the selection operation and mutation operation are also important steps. This article will not describe the specific details of the GA algorithm. I have previously written a special article about this algorithm. Link:Http://blog.csdn.net/androidlushangderen/article/details/44041499It introduces some basic concepts and principles of algorithms. If you have a good grasp of GA algorithms, it is not difficult to understand the application of genetic algorithms in the maze.

Application of algorithms in maze games

First, let's talk about what the problem is to be solved in a maze game. To put it bluntly, it is to set the starting point, ending point, and a bunch of obstacles in the middle, and then the accessible path, note that this refers to the reachable path, which is not necessarily the optimal path, because the optimal path must have the least number of steps, which is quite different. On the other hand, the genetic algorithm is also used to search for the optimal solution of the problem, so it can just be transferred to this problem. How to use a genetic algorithm to solve practical problems in life is how to use the concepts in genetic algorithms, such as several core concepts in genetic algorithms, gene encoding, and gene length settings, each of the three concepts of a fitness function is important. Okay, the purpose requirement has been clarified gradually. The following problems are solved one by one.

For better understanding, the following is an example ,:


The figure is made by yourself and is relatively simple. It is expressed in the form of the left point. It can be seen that the start point (4, 4) and the left side of the exit are the green area ), if the obstacle area indicated by the X symbol is not allowed to pass through, the problem is converted to searching for the shortest path from the start point to the end point, because the example is not very complex, based on the diagonal line, the total number of steps is 4-1 + 4-0 = 7. As long as the center is not bent, moving every step near the target is the best way. Let's take a look at how to convert it into a conceptual representation in a genetic algorithm.

Individual gene length

First, it is based on the length, because the final screening is an individual that meets the conditions, and its gene encoding is the optimal solution of the problem, therefore, we can think of each step of the role as a genetic code, and seven genetic values are required for a total of seven steps, so the length of the gene is 7 in this example.

Genetic Representation

Each movement step of a role has been converted into a genetic representation. There are four possibilities for each movement. The gene encoding is a standard binary form, so the value can be 00 to indicate up, 01 down, 10 to left, 11 to the right, that is, each genome is represented by two codes, so the total number is 2*7 = 14, two to one.

Fitness Function

The setting of the fitness function should be the most important in the genetic algorithm, so that the setting of the fitness function directly determines the genetic quality, we can calculate the final arrival coordinate through the genome encoding group data. Here we can easily conclude that if the final arrival coordinate is closer to the exit coordinate, the more we want the result, the higher the adaptive value, we can use the following formula as the fitness function:



(X, y) for the calculated adaptive value, the function value fluctuates between 0 and 1, and 1 is the maximum value, that is, when the arrival coordinate is exactly the exit position, of course, the expression of the fitness function is not unique.

Algorithm code implementation

Mapdata.txt:

0 0 0 0 02 0 0 -1 00 0 0 0 0 0 -1 0 0 -10 0 0 0 1

The example shown above.

GATool. java:

Package GA_Maze; import java. io. bufferedReader; import java. io. file; import java. io. fileReader; import java. io. IOException; import java. text. messageFormat; import java. util. arrayList; import java. util. random; /*** Application of Genetic Algorithm in a maze game-genetic algorithm tool ** @ author lyq **/public class GATool {// public static final int MAZE_ENTRANCE_POS = 1; public static final int MAZE_EXIT_POS = 2; // the corresponding encoding array public static final I Nt [] [] MAZE_DIRECTION_CODE = new int [] [] {0, 0}, {0, 1}, {1, 0}, {1, 1 },}; // change the public static final int [] [] MAZE_DIRECTION_CHANGE = new int [] [] {-1, 0}, {1, 0}, {0, {0, -1 },{ 0, 1 },}; // description of the public static final String [] MAZE_DIRECTION_LABEL = new String [] {"upper", "lower ", "Left", "right"}; // map data file address: private String filePath; // The shortest steps of the Maze: private int stepNum; // The number of initial individuals: private int initSetsNum; // The Maze entrance location is private int [] startPos; // The Maze exit location is private int [] endPos; // The Maze map data is private int [] [] mazeData; // initial collection private ArrayList <int []> initSets; // Random number generator private random Random; public GATool (String filePath, int initSetsNum) {this. filePath = filePath; this. initSetsNum = initSetsNum; readDataFile () ;}/ *** read data from the File */public void readDataFile () {file File = new file (filePath ); arrayList <String []> dataArray = ne W ArrayList <String []> (); try {BufferedReader in = new BufferedReader (new FileReader (file); String str; String [] tempArray; while (str = in. readLine ())! = Null) {tempArray = str. split (""); dataArray. add (tempArray);} in. close ();} catch (IOException e) {e. getStackTrace ();} int rowNum = dataArray. size (); mazeData = new int [rowNum] [rowNum]; for (int I = 0; I <rowNum; I ++) {String [] data = dataArray. get (I); for (int j = 0; j <data. length; j ++) {mazeData [I] [j] = Integer. parseInt (data [j]); // value the entry and exit locations. if (mazeData [I] [j] = MAZE_ENTRANCE_POS) {startPos = new I Nt [2]; startPos [0] = I; startPos [1] = j;} else if (mazeData [I] [j] = MAZE_EXIT_POS) {endPos = new int [2]; endPos [0] = I; endPos [1] = j ;}}// calculate the shortest step out of the maze stepNum = Math. abs (startPos [0]-endPos [0]) + Math. abs (startPos [1]-endPos [1]);}/*** generate the initial dataset */private void produceInitSet () {// int direcode code = 0; random = new Random (); initSets = new ArrayList <> (); // for each step, use two digits to represent int [] codeNum; for (int I = 0; I <initSetsNum; I ++) {codeNum = new int [stepNum * 2]; for (int j = 0; j <stepNum; j ++) {direcode code = random. nextInt (4); codeNum [2 * j] = MAZE_DIRECTION_CODE [direcode Code] [0]; codeNum [2 * j + 1] = MAZE_DIRECTION_CODE [direcode Code] [1];} initSets. add (codeNum) ;}}/*** select operation, the next generation of highly adaptive individuals is preferentially inherited ** @ param initCodes * initial individual code * @ return */private ArrayList <int []> selectOperate (ArrayList <int []> initCode S) {double randomNum = 0; double sumFitness = 0; ArrayList <int []> resultCodes = new ArrayList <> (); double [] adaptiveValue = new double [initSetsNum]; for (int I = 0; I <initSetsNum; I ++) {adaptiveValue [I] = calFitness (initCodes. get (I); sumFitness + = adaptiveValue [I];} // convert to a probability form and perform the normalization operation for (int I = 0; I <initSetsNum; I ++) {adaptiveValue [I] = adaptiveValue [I]/sumFitness;} for (int I = 0; I <initSetsNu M; I ++) {randomNum = random. nextInt (100) + 1; randomNum = randomNum/100; // unable to judge because 1.0 ,, the sum is infinitely close to 1.0 and the value is 0.99. Make a judgment if (randomNum = 1) {randomNum = randomNum-0.01;} sumFitness = 0; // determine the range for (int j = 0; j <initSetsNum; j ++) {if (randomNum> sumFitness & randomNum <= sumFitness + adaptiveValue [j]) {// use the copy method to avoid repeated references to resultCodes. add (initCodes. get (j ). clone (); break;} else {sumFitness + = adaptiveValue [j] ;}} re Turn resultCodes ;} /* ** crossover operation ** @ param selectedCodes * @ return */private ArrayList <int []> crossOperate (ArrayList <int []> selectedCodes) {int randomNum = 0; // intersection int crossPoint = 0; ArrayList <int []> resultCodes = new ArrayList <> (); // random encoding queue, perform random cross-match ArrayList <int []> randomCodeSeqs = new ArrayList <> (); // perform random sorting while (selectedCodes. size ()> 0) {randomNum = random. nextInt (selectedCodes. size (); RandomCodeSeqs. add (selectedCodes. get (randomNum); selectedCodes. remove (randomNum);} int temp = 0; int [] array1; int [] array2; // performs a crossover operation for (int I = 1; I <randomCodeSeqs. size (); I ++) {if (I % 2 = 1) {array1 = randomCodeSeqs. get (I-1); array2 = randomCodeSeqs. get (I); crossPoint = random. nextInt (stepNum-1) + 1; // convert the encoding after the intersection position for (int j = 0; j <2 * stepNum; j ++) {if (j> = 2 * crossPoint) {temp = Array1 [j]; array1 [j] = array2 [j]; array2 [j] = temp ;}// add it to the cross operation result resultCodes. add (array1); resultCodes. add (array2) ;}} return resultCodes ;} /*** mutating operation *** @ param crossCodes * result of crossover operation * @ return */private ArrayList <int []> variationOperate (ArrayList <int []> crossCodes) {// variant int variationPoint = 0; ArrayList <int []> resultCodes = new ArrayList <> (); for (int [] array: crossCodes) {variationPoint = random. nex TInt (stepNum); for (int I = 0; I <array. length; I + = 2) {// mutations if (I % 2 = 0 & I/2 = variationPoint) {array [I] = (array [I] = 0? 1: 0); array [I + 1] = (array [I + 1] = 0? 1: 0); break;} resultCodes. add (array);} return resultCodes ;} /*** calculate the adapt value based on the encoding ** @ param code * Current encoding * @ return */public double calFitness (int [] code) {double fintness = 0; // The X-axis int endX = 0 from the end point calculated by the encoding; // the x-axis int endY = 0 from the end point calculated by the encoding; // int ction = 0 based on the walking direction represented by the segment; // The temporary coordinate int tempX = 0; // The temporary coordinate int tempY = 0; endX = startPos [0]; endY = startPos [1]; for (int I = 0; I <stepNum; I ++) {direction = binary ArrayToNum (new int [] {code [2 * I], code [2 * I + 1]}); // modify the coordinates of the array according to the direction. tempX = endX + MAZE_DIRECTION_CHANGE [direction] [0]; tempY = endY + MAZE_DIRECTION_CHANGE [direction] [1]; // determine whether the coordinate point is out of bounds if (tempX> = 0 & tempX <mazeData. length & tempY> = 0 & tempY <mazeData [0]. length) {// determines whether the coordinate point is reached. if (mazeData [tempX] [tempY]! =-1) {endX = tempX; endY = tempY ;}}// calculate the fintness = 1.0/(Math. abs (endX-endPos [0]) + Math. abs (endY-endPos [1]) + 1); return fintness ;} /*** determine whether the exit location has been found based on the current code ** @ param code * after several genetic codes * @ return */private boolean ifArriveEndPos (int [] code) {boolean isArrived = false; // the x-axis int endpoint calculated by the code = 0; // The end point ordinate int endY = 0 calculated by the Code; // int ction = 0 based on the walking direction represented by the segment; // The temporary coordinate int tempX = 0 ;// Temporary coordinate point: int tempY = 0; endX = startPos [0]; endY = startPos [1]; for (int I = 0; I <stepNum; I ++) {direction = binaryArrayToNum (new int [] {code [2 * I], code [2 * I + 1]}); // modify the coordinates of the array according to the direction. tempX = endX + MAZE_DIRECTION_CHANGE [direction] [0]; tempY = endY + MAZE_DIRECTION_CHANGE [direction] [1]; // determine whether the coordinate point is out of bounds if (tempX> = 0 & tempX <mazeData. length & tempY> = 0 & tempY <mazeData [0]. length) {// determines whether the coordinate point is blocked. Block if (mazeData [tempX] [tempY]! =-1) {endX = tempX; endY = tempY ;}}if (endX = endPos [0] & endY = endPos [1]) {isArrived = true;} return isArrived;}/*** convert a binary array to a number ** @ param binaryArray * binary array to be converted */private int binaryArrayToNum (int [] binaryArray) {int result = 0; for (int I = binaryArray. length-1, k = 0; I> = 0; I --, k ++) {if (binaryArray [I] = 1) {result + = Math. pow (2, k) ;}} return result;}/*** genetic algorithm out of the maze */public void goOutMaze () {// number of iterations int loopCount = 0; boolean canExit = false; // result path int [] resultCode = null; ArrayList <int []> initCodes; ArrayList <int []> selectedCodes; ArrayList <int []> crossedCodes; arrayList <int []> variationCodes; // generate the initial dataset produceInitSet (); initCodes = initSets; while (true) {for (int [] array: initCodes) {// The termination condition of the genetic iteration is whether the exit position is found. if (ifArriveEndPos (array) {resultCode = array; canExit = true; break ;}} if (canExit) {break;} selectedCodes = selectOperate (initCodes); crossedCodes = crossOperate (selectedCodes); variationCodes = variationOperate (centers); initCodes = variationCodes; loopCount ++; // if the genetic frequency exceeds 100, exit if (loopCount> = 100) {break;} System. out. println ("total genetic evolution" + loopCount + "times"); printFindedRoute (resultCode );} /*** output path ** @ param code */private void printFindedRoute (int [] code) {if (code = null) {System. out. println ("the optimal path is not found within a limited number of genetic evolution times"); return;} int tempX = startPos [0]; int tempY = startPos [1]; int direction = 0; System. out. println (MessageFormat. format ("starting point ({0}, {1}), exit point ({2}, {3})", tempX, tempY, endPos [0], endPos [1]); System. out. print ("searched result encoding:"); for (int value: code) {System. out. print ("" + value);} System. out. println (); for (int I = 0, k = 1; I <code. length; I + = 2, k ++) {direction = binaryArrayToNum (new int [] {code [I], code [I + 1]}); tempX + = MAZE_DIRECTION_CHANGE [direction] [0]; tempY + = MAZE_DIRECTION_CHANGE [direction] [1]; System. out. println (MessageFormat. format ("Step {0}, code: {1} {2}, move to {3}, move to ({4}, {5})", k, code [I], code [I + 1], MAZE_DIRECTION_LABEL [direction], tempX, tempY ));}}}
Client. java:

Package GA_Maze;/*** Application of Genetic Algorithm in a maze game * @ author lyq **/public class Client {public static void main (String [] args) {// The data address of the Maze map file String filePath = "C :\\ Users \ lyq \ Desktop \ icon \ mapData.txt "; // initial number of individuals int initSetsNum = 4; GATool tool = new GATool (filePath, initSetsNum); tool. goOutMaze ();}}

Algorithm output:

I tested the data many times, because it may fail to be searched at half past one, and I set the maximum genetic count to 100.

A total of 2 genetic evolution of the starting point location (10100000100010), exit point location (1, 0) found the result code: 1st step, code as 10, move to the left, move to (2nd) Step 3rd, code as 10, move to left, move to () Step, code as 00, move up, move) step 5: code 00, move up, move to (4th) Step 2, code 10, move left, move to (5th) Step 2, code 00, move up, move to Step 1 (7th), Code 10, move to left, move to Step 1 (), and then inherit and evolve eight starting points () in total ), result code found at the exit point (1, 0): Step 1, code 10, move to the left, move to Step 4 (3), code 00, move up, move to (3, 3) Step 3rd, code as 10, move to left, move to (3, 2) Step 4th, code as 00, move up, move to step 2 (2), Code 10, move to left, move to step 2 (2, 1), Code 10, move to left, move to (2, 0) step 1, code 00, move up, and then reach (7th). A total of 100 genetic evolution times within a limited number of genetic evolution times, no Optimal Path found

Algorithm Summary

The Application of Genetic Algorithms in the maze is very interesting in general. If you have a serious understanding, at least let me have a deeper understanding of the GA algorithm, if you want to implement this algorithm in person, I would like to give some suggestions. The first is the difficulty of the maze and the number of initial individuals. Why do you need to pay attention to these two points, one is the number of genetic iterations. Sometimes the genetic algorithm cannot be found in a period of time. If it cannot be found, the CPU of the PC will continue to calculate at high speed, therefore, do not limit the number of vertices. It may be that my current configuration is too bad .. In algorithm debugging, a bug that was not found before was fixed. In the selection phase, the random number judgment was rarely considered. When the random number reaches 1.0, in fact, it cannot be determined, because the concept is infinitely close to 1 and it does not know which region to be divided.

Related Article

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.