Genetic Algorithms in Python: Help me flip a random bit in a list. SOLVED


#1

I have a list of randomly generated 0's and 1's. I need to pick a single bit and flip it to its opposite: either a zero to a one or a one to a zero. This is part of a genetic algorithm problem in Python.

What I have tried:

import random as randint
 
pop_size = int(input('Enter a population size:'))
length = int(input('Enter an organism length:'))
 
orgs = []
for i in range(pop_size):
    org = []
    for a in range(length):
        org.append(randint.randint(0,1))
    orgs.append(org) 
    
orgs.sort(reverse=True)
print orgs 
 
new_orgs = []
new_org = orgs[0:(pop_size/2):1] 
#look at user input for 50 or 25, etc
new_orgs.append(new_org) 
print new_orgs
 
import random as randint  
x = randint.choice(new_orgs)
j = randint.randrange(len(x))
x[j] = int(not x[j])
print x

The code above returns this:

Enter a population size: 4
Enter an organism length: 3
[[1, 1, 1], [1, 0, 1], [1, 0, 0], [0, 1, 1]] #sorted list by sum
[[[1, 1, 1], [1, 0, 1]]] # half of list which has 'higher' fitness
[[1, 1, 1], 0] #output

I need to get something like this:
[[1, 0, 1], [1,1,1,]] #in regards to output


#2

I do not understand why the name change is necessary. Why not just,

import random

?


#3

import random
x = random.choice(new_orgs)
j = random.randrange(len(x))
x[j] = int(not x[j])
print x

Still returns:

Enter a population size: 4
Enter an organism length: 2
[[1, 0], [1, 0], [0, 1], [0, 1]]
[[[1, 0], [1, 0]]]
[[1, 0], 0]

#4

>>> import random
>>> orgs = [[1, 1, 1], [1, 0, 1], [1, 0, 0], [0, 1, 1]]
>>> x = random.choice(orgs)
>>> x
[1, 1, 1]
>>> j = random.randrange(len(x))
>>> j
0
>>> x[j] = int(not x[j])
>>> x
[0, 1, 1]
>>>

Not sure why your output is different from the above.


#5

You specified the lists org, but I need it to be user input, not specified directly in the code


#6

That was just for testing directly in the interactive console.


#7

import random as randint
 
pop_size = int(input('Enter a population size:'))
length = int(input('Enter an organism length:'))
 
orgs = []
for i in range(pop_size):
    org = []
    for a in range(length):
        org.append(randint.randint(0,1))
    orgs.append(org) 
    
orgs.sort(reverse=True)
print orgs 
 
new_orgs = []
new_org = orgs[0:(pop_size/2):1] 
#look at user input for 50 or 25, etc
new_orgs.append(new_org) 
print new_orgs

import random
x = random.choice(orgs)
j = random.randrange(len(x))
x[j] = int(not x[j])
print x

returns:

Enter a population size: 4
Enter an organism length: 2
[[1, 1], [1, 1], [0, 0], [0, 0]]
[[[1, 1], [1, 1]]]
[1, 1, 0]

#8

I believe you want to operate on new_orgs. My test was generic and I called the list orgs arbitrarily. Don't read anything into it.


#9

The code I have above doesn't look at orgs, but still returns the incorrect output.


#10

Hi @captainap,

Does the code below reflect what you are trying to do? I assumed you wanted to mutate an individual within orgs, based on this statement ...

x = random.choice(orgs)

Should it be within new_orgs, instead? If so, that is easily fixed.

The organisms and locations within organisms are numbered starting at 0, here. The following code was executed in Python 3.

import random
 
pop_size = int(input('Enter a population size:'))
length = int(input('Enter an organism length:'))
 
orgs = []
for i in range(pop_size):
    org = []
    for a in range(length):
        org.append(random.randint(0,1))
    orgs.append(org) 
    
orgs.sort(reverse=True)
print(orgs)
 
new_orgs = []
new_org = orgs[0:(pop_size//2):1] 
#look at user input for 50 or 25, etc
new_orgs.append(new_org) 
print(new_orgs)

x = random.randint(0,len(orgs) - 1)
j = random.randint(0,len(orgs[x]) - 1)
orgs[x][j] = int(not orgs[x][j])
print("Mutation at organism {:d} location {:d}".format(x, j))
print(orgs[x])

#11

Here is my final code:

import random
pop_size = int(input('Enter an even population size:'))
length = int(input('Enter an organism length:')) 
      
orgs = []
for i in range(pop_size):
    org = []
    for a in range(length):
        org.append(random.randint(0,1))
    orgs.append(org)

print orgs
print "created pop"
orgs.sort(reverse=True)

fit = sum(org)
for fit in org:
    print fit 
    print 'hello'
print orgs

print "sorted pop"
new_orgs = orgs[0:(pop_size//2)]
print new_orgs
print "best pop"
 
for some_org in new_orgs:
    bit_to_flip = random.randrange(len(some_org))
    if some_org[bit_to_flip] == 1:
        some_org[bit_to_flip] = 0
    else:
        some_org[bit_to_flip] = 1
print new_orgs
print "mutated pop"

Returns this:

Enter an even population size: 4
Enter an organism length: 2
[[0, 0], [1, 0], [0, 0], [0, 1]]
created pop
0
hello
1
hello
[[0, 1], [1, 0], [0, 0], [0, 0]]
sorted pop
[[0, 1], [1, 0]]
best pop
[[1, 1], [0, 0]]
mutated pop

Yes, I know this code can be simplified. I'm still in the debugging stage and have a few more things to add. The prints are just there to guide me. What I'm working on next is creating a dictionary with organism as a key and fitness as a value. Then I should be able to take half of that dictionary and use it to sort. I also want to add in some user input: instead of half the population maybe I can get ten or twenty five percent. I'm also working on getting only an even number that the user inputs, which I believe can be solved with a While loop... And lastly, I have to create offspring and mutate them again and again!

...I love this project... :heart_eyes:


#12