I appreciate the way you initially boost performance by dividing the population into champions.
Areas for improvement:
Consider calculating fitness as soon as a new individual is created to avoid cycling through offspring each time.
It might be beneficial to define population class.
Explore the option of having more bits changed in each mutation. Additionally, consider reducing the tournament size; while 5 is
acceptable, 2 or 3 might be more optimal.
In Box 6, constants should be in capital letters.
Explore the possibility of pipelining crossover and mutation.
Address code redundancy. You simply change the mutation or crossover functions in the improvements there is no need to rewrite all
the code every time.
Your code should check if fitness one is reached to stop calculating fitness. The main reason you never reached fitness one is because
you never considered a different rate of changing 1->0 and vice versa
Hi, thank you for your advice!
A quick comment on something that I don't understand on your current review:
I explored the option of mutating more bits in one mutation both with inversion_mutation_random_range and with local_search_mutation
the costants actually are in capital letters
I did not consider a different rate of changing 1-> 0 and vice versa because I would have not considered the fitness as a black box (considering that you need to have more 1's is cheating)
checking if fitness one is reached would lead to infinite loops most of the times
I was talking about numerous bits, hundreds of bits changed with each mutation.
My comment was specifically directed to the constants in box 6.
I propose incorporating a probabilistic learning variable, initially set at 0.5, which adjusts based on whether ones or zeros prove superior. It's the code that modifies the variable, so it is no cheating !
By verifying individual.fitness == 1, you can promptly stop the code, saving time and avoiding unnecessary calls to the fitness function beyond what is necessery.
What I liked:
Areas for improvement: