I'm writing a genetic algorithm in which I need to select 5 numbers from the binary list genotype
and flip them, so a 1
→0
and 0
→1
. I tried putting my code in a loop with a range(1,6)
however when I do this it still only changes one of the numbers. Below is my original code without the loop which randomly selects one of the binary values and mutates it. Does anyone know a better way of doing this but for 5 of the elements in the list?
genotype = [1,0,0,1,0,0,1,1,1,0]
def mutate(self):
gene = random.choice(genotype)
if genotype[gene] == 1:
genotype[gene] = 0
else:
genotype[gene] = 1
return genotype
While your primary problem seems solved after the answer given by ilyankou:
for i in random.sample(range(len(genotype)), 5):
genotype[i] ^= 1
and this alternative (more realistic) mutation model was suggested:
for i in [random.choice(range(len(genotype))) for _ in range(5)]:
genotype[i] ^= 1
I found this observation quite challenging and somewhat inspiring
I tried putting my code in a loop with a range(1,6) however when I do this it still only changes one of the numbers.
Is this this always true? Can it or must it be?
I tried several runs of the following code (I removed the superfluous self
from your original)
import random
genotype = [1,0,0,1,0,0,1,1,1,0]
def mutate():
gene = random.choice(genotype)
if genotype[gene] == 1:
genotype[gene] = 0
else:
genotype[gene] = 1
return genotype
print(genotype)
for _ in range(1,6):
mutate()
print(genotype)
and observed only these outputs:
[0, 0, 0, 1, 0, 0, 1, 1, 1, 0]
-- gene at index 0 flipped[1, 1, 0, 1, 0, 0, 1, 1, 1, 0]
-- gene at index 1 flippedAnd indeed this has to be like this for an odd count of calls to the mutate
function above:
Because gene
is one of 0
and 1
and double flips on the same gene reproduce the initial value, only mutations will remain that correspond to gene indices which are chosen an odd number of times, and since you call it for range(1, 6)
(an odd total), only one of 0
and 1
can be of odd quantity in the overall process.