HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Where equations are born and mutants are buried

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
equationsaremutantswherebornburiedand

Problem

I've read up on genetic programming yesterday so I figured I'd try to implement something myself. I would like the main focus to be on whether or not I've implemented the idea behind it correctly.

The thought behind it is simple: given a number and a few parameters, generate an equation that yields that number as solution. I have implemented the *, /, +, - and ^ operators.

The world gets populated with an equation of the form x + (y - z) where the values are randomly generated (I might generate the operators randomly as well later).

Some key remarks about the implementation:

-
An equation whose result is not within the predetermined boundaries of the target solution, will be killed.

-
A new generation consists of mutated equations and children. Parents are no longer in the new generation.

-
When there's a single generation left, it will occassionally mutate until he is outside of the acceptable boundaries.

Which will raise the question: is this a good approach or should it be done differently?

Program

```
class Program
{
static void Main(string[] args)
{
new Program();
Console.Read();
}

private static void PrintTree(GeneticTree tree)
{
var output = string.Format("{0}: {1:0}{2, 15}[{3}]", tree.Name, tree.GetResult(), string.Empty, tree.GetDisplay());
Console.WriteLine(output);
}

private static void PrintWorld(World world)
{
Console.WriteLine("================================");
Console.WriteLine("Generation {0}", world.Generation);
foreach (var algorithm in world.Population)
{
PrintTree(algorithm);
}
}

public Program()
{
var world = new World(targetValue: 50, populationSize: 30, fitnessDelta: 100, mutationChance: 0.2d, minValue: -50, maxValue: 50);

do
{
PrintWorld(world);
} while (!world.AdvanceGeneration() && !world.Apocalypse);

if (world.Apocalypse)

Solution

You are organizing your algorithms into two categories: working algorithms and non-working algorithms; this is rather Manichean. You should try to design something where an algorithm is not "working" but "approaching the expected result better than the other ones". In other words, don't try to find "who works", but "who works better". The best thing you could do IMO is to get all the results for a generation, compare them to see which ones are closer to the expected result and which ones are farther. In other terms, you should give to your algorithms what I would call a "relative fitness" to know which solution is "relatively better" than the other ones.

This relative fitness will help you to generate a new generation with the following steps:

  • Attach a survival percentage to every algorithm, relative to its relative fitness (the closer it is approching the expected result, the higher the survival percentage).



  • For every algorithm in your population, get a random number between 0 and 1.



  • Remove the algorithms for whom the random number is greater than its survival percentage.



  • Keep the surviving algorithms for the next generation.



  • Complete the new generation by creating algorithms that are mutations and combinations of the surviving algorithms.



If you do this, then you should be able to almost always keep the best algorithms between generations, but you will also keep some other ones whose mutations and/or combinations may unexpectedly produce agorithms that are better than your current best ones. This process of "you may have an unexpected talent" is useful to avoid local extrema.

Context

StackExchange Code Review Q#69783, answer score: 17

Revisions (0)

No revisions yet.