0
votes

I'm currently trying to make my genetic algorithm "generate" or "evolve" towards an given word. The problem is, that it never fully reaches this word, it stops at an too high fitness score, even if it should continue mutating.

Heres an example:

User input = "HelloWorld"
After 500 generations = "XelgoWorfd"

And I have no clue why it won't continue mutating. Normally it just should resume with changing randomly some chars in the string.

So I would be very glad about some help.

Here's an basic step by step explanation:

  1. Create 20 Chromosomes with fully randomized strings
  2. Calculate the fitness score compared to the goal word. (Counting Ascii ids differences)
  3. Mate the two Chromosomes with the best score.
  4. Mutate some of the Chromosomes randomly (change random string chars)
  5. Kill 90% of the weak population and replace it with elite chromosomes (The chromosomes with the currently best fitness score).
  6. Repeat everything.

So here the most important methods of my algorithm:

public Chromoson[] mate(string gene) {
    Console.WriteLine("[MATING] In Progress : "+gens+" "+gene);

    int pivot = (int)Math.Round((double)gens.Length / 2) - 1;

    string child1 = this.gens.Substring(0, pivot) + gene.Substring(pivot);
    string child2 = gene.Substring(0, pivot) + this.gens.Substring(pivot);

    Chromoson[] list = new Chromoson[2];

    list[0] = new Chromoson(child1);
    list[1] = new Chromoson(child2);

    Console.WriteLine("[MATING] Pivot : "+pivot);
    Console.WriteLine("[MATING] Children : "+child1+" "+child2);

    return list;
}

public void mutate(float chance, int possiblyChanges) {
    if (random.Next(0,101) <= chance) return;

    int changes = random.Next(0, possiblyChanges + 1);
    //int index = (int) Math.Floor((double)random.Next() * this.gens.Length);

    for (int i = 0; i < changes; i++) {
        int index = random.Next(0, 13);
        StringBuilder builder = new StringBuilder(gens);
        int upOrDown = random.Next(0, 101);

        if (upOrDown <= 50 && (int)builder[index] > 0 && chars.Contains(Convert.ToChar(builder[index] - 1)))
            builder[index] = Convert.ToChar(builder[index] - 1);
        else if (upOrDown >= 50 && (int)builder[index] < 127 && chars.Contains(Convert.ToChar(builder[index] + 1)))
            builder[index] = Convert.ToChar(builder[index] + 1);
        else
            mutate(chance, possiblyChanges);

        gens = builder.ToString();
    }
    Console.WriteLine("[MUTATING] In Progress");
}

public void calculateCost(string otherGens)
{
    int total = 0;
    for (int i = 0; i < gens.Length; i++)
    {
        total += (((int)gens[i] - (int)otherGens[i]) * ((int)gens[i] - (int)otherGens[i])) * (i*i);
    }
    Console.WriteLine("[CALCULATING] Costs : " + total);
    this.cost = total;
}
2
Please don't tag spam. - shmosel
May be because of the random? if (random.Next(0,101) <= chance) return; - Samvel Petrosov
This is not complete code. Please post Minimum, complete, verifiable example. - Renats Stozkovs

2 Answers

1
votes

Your mutate and calculateCost functions are weird. In particular, mutate() looks designed to get trapped in local minimas. Any mutation up or down will be worse than the elites (which are probably identical so crossover changes nothing). Use a different mutate: Pick a random index and change it completely. Also remove i*i from cost().

1
votes

Something is completely off in your timesteps:

  1. Create 20 Chromosomes with fully randomized strings. Seems okay.
  2. Calculate the fitness score compared to the goal word. (Counting Ascii ids differences). Seems okay.
  3. Mate the two Chromosomes with the best score. What? Your only breeding the two fittest chromosomes to create the new population? That means you will have a population that is nearly completely similar. Breedfitness proportionally, so all genomes have a chance to have an offspring
  4. Mutate some of the Chromosomes randomly (change random string chars)
  5. Kill 90% of the weak population and replace it with elite chromosomes (The chromosomes with the currently best fitness score). You kill 90%? So basically, you're keeping the 2 best genomes every iteration and then replacing the other 18 with step 1? What you want is to keep the 2 fittest at step 3, and create the other 18 individuals by breeding.
  6. Repeat everything.

So change your steps to:

INIT. Initialise population, create 20 random chromosomes

  1. Calculate score for each chromsome
  2. Save the two fittest chromosomes to the next population (aka elitism), getthe other 18 needed individuals by breeding fitness proportionally
  3. Mutate the chromsomes with a certain chance
  4. Repeat

Do not create random individuals every round. This turns your algorithm into a random search.