borkbork
borkbork

Reputation: 73

Creating a very simple 'evolutionary' algorithm in python

I'm trying to create a very simple 'evolutionary' algorithm in python.

I initially want to create a population of ~100 individuals with four numerical attributes (a1-4), use a function to get a score from these attributes, then remove the worst scoring 20 individuals.

This is what I have so far

import random
population = 100

class Individual(object):
    def __init__(self, a1, a2, a3, a4):
        self.a1 = a1
        self.a2 = a2
        self.a3 = a3
        self.a4 = a4

starting_population = list()

for i in range (population):
    a1 = random.randint(1,10)
    a2 = random.randint(1,10)
    a3 = random.randint(1,10)
    a4 = random.randint(1,10)
    starting_population.append(Individual(a1,a2,a3,a4))

def fitness(x):
    fitness = a1*a2/a3*a4
    return fitness

I'm stuck on how to apply a function to the members of the population list?

Also, I'm very new to Python and I'm sure I've done some things badly, so any tips are very appreciated!

Thank you

Upvotes: 1

Views: 374

Answers (2)

Thierry Lathuille
Thierry Lathuille

Reputation: 24234

First, you should make fitness a method of Individual:

import random
population = 100

class Individual(object):
    def __init__(self, a1, a2, a3, a4):
        self.a1 = a1
        self.a2 = a2
        self.a3 = a3
        self.a4 = a4

    def fitness(self):
        fitness = self.a1*self.a2/self.a3*self.a4
        return fitness

starting_population = list()

for i in range (population):
    a1 = random.randint(1,10)
    a2 = random.randint(1,10)
    a3 = random.randint(1,10)
    a4 = random.randint(1,10)
    starting_population.append(Individual(a1,a2,a3,a4))

If you want to remove the 20 least scoring ones, first sort them by fitness, then take a slice of the list:

sorted_people = sorted(starting_population, key=lambda i:i.fitness())
fit_people = sorted_people[20:]

You could also filter them according to the value of their fitness, like that, using a list comprehension:

fit_people = [i for i in starting_population if i.fitness() > 0.5]

Upvotes: 0

kabanus
kabanus

Reputation: 25895

What is wrong with looping?

for person in starting_population:
    person.fitness = person.a1*person.a2/person.a3*person.a4 #Add fitness to object

Also note, the order of operations is:

((a1*a2)/a3)*a4)

in case you meant something different. You may consider making fitness a method of an individual:

class Individual(object):
    def __init__(self, a1, a2, a3, a4):
        self.a1 = a1
        self.a2 = a2
        self.a3 = a3
        self.a4 = a4

    def fitness(self,x):
        fitness = self.a1*self.a2/self.a3*self.a4
        return fitness

starting_population = list()   
for i in range (population):
    a1 = random.randint(1,10)
    a2 = random.randint(1,10)
    a3 = random.randint(1,10)
    a4 = random.randint(1,10)
    starting_population.append(Individual(a1,a2,a3,a4))

so you immediately can call starting_population[i].fitness(), or calculate the value in __init__ and make it a field.

Another solution, dropping the object clarity of code in favor of a numpy array for speed:

import numpy.random as rnd
rnd.seed(78943598743)
starting_population=rnd.randint(1,10,size=100*4).reshape(100,4) #100 rows, 4 columns, each row a person
fitness_vector = starting_population[:,0]*starting_population[:,1]/starting_population[:,2]*starting_population[:,3]

Upvotes: 1

Related Questions