Using GA in a GUI

Sorry if this is not clear as I am writing this on a mobile device and I am trying to do it quickly.

I wrote a basic binary-coding (genes) genetic algorithm that builds fitness value and develops through several iterations using tournament selection, mutation and crossover. As a basic command line example, it works.

The problem I am facing is the application of the genetic algorithm in the GUI, as I am writing a program for solving mazes that uses GA to search for a method through the maze. How to turn my random binary encoded genes and fitness function (add all binary values ​​together) into a bot management method around the maze? I created a basic Java GUI consisting of a labyrinth of shortcuts (like grids) where the available routes are in blue and the walls are in black.

We repeat that my GA works well and contains what any typical GA (fitness method, get and set the population, choice, crossover, etc.), but now I need to connect it to the graphical interface to start my maze. What needs to be done to get a bot that can move in different directions depending on what the GA says? A rough pseudo code would be great if possible

According to the request, the Individual is created using a separate class (Indiv), while the main work is performed in the Pop class. When a new individual is created, the ints array represents the genes of the mentioned person, and the genes are randomly selected from 0 to 1. The fitness function simply adds together the value of these genes in the class of descriptors of the class Pop, mutation and crossover of two selected individuals. There is still not much, the command-line program simply shows evolution over n generations with a complete improvement in the performance of each iteration.

EDIT: now this is starting a little more, although there are a few things that are pushing me ...

As Adamsky said, I want to create an “Agent” with the parameters shown below. The problem I came across is that a random bit string is playing here. The agent knows where the walls are and whether it is laid out in a 4-bit line (i.e. 0111), but how does this affect a random 32-bit line? (i.e. 10001011011001001010011011010101) If I have the following maze (x is the starting place, 2 is the target, 1 is the wall):

x 1 1 1 1 0 0 1 0 0 1 0 0 0 2 

If I turn left, I will encounter the wrong way, and the agent will completely move out of the maze if it moves forward. I assume that the first generation of the line will be completely random, and it will develop as fitness grows, but I don’t understand how the line will work in the maze.

So, to get it straight ...

Fitness is the result of when the agent is able to move and is near the wall.

Genes are a 32-bit string broken into 16 sets of 2 bits to show the available actions, and in order for the robot to move two bits, it is necessary to transfer four bits from the agent, displaying its position near the walls. If the movement must go past the wall, the movement is not made, and it is considered invalid, and if the movement is performed, and if a new wall is found, then the fitness rises.

Is it correct?

+4
source share
2 answers

BadHorse's answer is good if you want to solve a specific maze; you simply index your bit string as a sequence of precise instructions to guide the agent through the maze. In this case, your suitability is not the sum of the bit string (as you state in your question), but rather some metric that measures how successful the agent was in solving the problem. For example, your fitness may be defined as "the distance in a straight line from the end of the maze after processing 20 instructions."

Therefore, when evaluating each person, you allow him to process the first 20 commands from your bit string, and then calculate its suitability, perform any crossovers / mutations, and then create the next generation of people.

If you want to develop your agent to solve any maze , you need to encode the rules in your bit string, not a sequence of instructions. You could define rules based on whether the wall was immediately behind, in front, to the left or right of the robot; eg.

 FBLR Action 0000 Move Forward 0001 Move Forward 0010 Turn Right etc 

This gives you a 16-action bit string, each action is encoded as 2 bits (00 = Move Forward, 01 = Turn Right, 10 = Turn Left, 11 = Move Backwards). When evaluating your agent, it simply determines its current state and uses the bit string as a lookup table to determine how it should respond. Then he repeats this a certain number of times, after which you evaluate its suitability.

Given this encoding, the agent can evaluate the rule that people usually use that "continuously follows the left wall." Obviously, this approach will not work if the labyrinth is not fully connected, in which case you will need to encode more states in your rule-based approach (for example, the agent may react differently if iterates over the “old land”) .

Hope this helps.

EDIT

In response to your last change:

The fact that I encoded the "sensors" agent, which detects that it is near the wall or not, is not related to the bit string (your gene), and maybe I messed things up a bit in my example. The gene only encodes actions (moving forward, etc.) not the state of the sensor.

Therefore, you must write code to search for the corresponding part of the bit string, taking into account a specific combination of sensor readings; eg.

 /** * Enumeration describing the four available actions to the agent * and methods for decoding a given action from the "bit" string * (actually represented using booleans). */ public enum Action { MOVE_FORWARD, REVERSE, TURN_LEFT, TURN_RIGHT Action decodeAction(boolean b1, boolean b2) { Action ret; if (b1) { ret = b2 ? Action.MOVE_FORWARD : Action.TURN_LEFT; } else { ret = b2 ? Action.TURN_RIGHT : Action.REVERSE; } return ret; } } /** * Class encapsulating the 32-bit "bit string" represented using booleans. * Given the state of the four agent inputs the gene will provide a specific * action for the agent to perform. */ public class Gene { private final boolean[] values = new boolean[32]; public Action getActionForSensorInputs(boolean wallInFront, boolean wallBehind, boolean wallToLeft, boolean wallToRight) { int i=0; // Encode the four sensor inputs as a single integer value by // bitwise-ORing each sensor value with a power of 2. // The encoded value will be in the range [0, 15]. if (wallToRight) { i |= 0x01; } if (wallToLeft) { i |= 0x02; } if (wallBehind) { i |= 0x04; } if (wallInFront) { i |= 0x08; } // The look-up index is i * 2 because each action is encoded as 2 // booleans. int index = i * 2; // Retrieve the two action bits from the bit string. boolean b1 = this.values[index]; boolean b2 = this.values[index + 1]; // Finally decode the action to perform. return Action.decodeAction(b1, b2); } // TODO: Add method to support crossover and mutation with other Genes. } 

Given this simple definition of a Gene , you can embed this class in the Agent implementation and record how the agent executes the current “installed” gene; eg.

 private enum Direction { NORTH, SOUTH, EAST, WEST }; public class Agent { private final Geneva gene; private final int x; // x position in maze; private final int y; // y position in maze; private Direction currentDirection; public double evaluate() { double fitness; // Perform up to 20 actions and then evaluate fitness. for (int i=0; i<20; ++i) { // TODO Determine sensor inputs. Action action = gene.getActionForSensorInputs(...); // TODO: Now apply action to update agent state. // If agent has reached goal exit loop and return fitness 1.0 (max fitness). // If agent has exited the maze then exit loop and return 0.0 (min fitness). } // Calculate fitness after 100 steps taken. For example could be // calculated as sqrt((goal.x - x) ^ 2 + (goal.y - y) ^ 2). return fitness; } } 
+4
source

If I understand correctly, you need to determine how the actions of your bot in the GUI are represented by the result of your genetic algorithm? I believe that the definition of the view you want to use should be your starting point. Therefore, you need to create a mapping for each (group) of “genes” in your individual for a specific action or a specific change in the algorithm of your bot’s movement.

Once you have chosen a viable view, the implementation will be somewhat more logical.

A very simple representation of the movement would be to give genes a hard-coded route. You can use blocks of four genes to represent different directions, and then 0 means “don't move in that direction,” and 1 represents movement.

Then the view 01001101 could be translated as the following movement pattern:

 stand still go one step east stand still stand still go one step north go one step east stand still go one step west 
0
source

Source: https://habr.com/ru/post/1301686/


All Articles