Feb
2
2009
Hello Gene
While on breaks at work I’ve been reading a bit about Genetic Programming. The following is a quick-and-dirty python script I threw together (mostly for myself) the other night. It evolves the target string “Hello World” over several generations, starting with random strings. After a bit of experimentation I found that a population size of 300 seems to work best for this.
import random import string class GenePool: def __init__(self, population_size): self.population_size = population_size self.population = [self.generate() for i in range(population_size)] def run(self): i = 0 while True: print "Generation " + str(i) + ": " + self.population[0] i = i + 1 if self.step(): return def step(self): fittest = self.get_best(self.population_size/2) if self.successful(fittest[0]): print "Success! " + fittest[0] return True else: self.population = self.get_new_generation(fittest) return False def generate(self): return "".join([random.choice(string.ascii_letters + " ") for i in range(11)]) def evaluate(self, individual): s = "Hello World" total = 0 for idx in range(len(s)): if individual[idx] == s[idx]: total = total + 1 return total / 11.0 def get_best(self, n): fitness = [] for idx, individual in enumerate(self.population): fitness.append((idx, self.evaluate(individual))) fitness.sort(cmp=lambda x,y: cmp(x[1], y[1]), reverse=True) best = [] return [self.population[tup[0]] for tup in fitness[:n]] def successful(self, individual): return individual == "Hello World" def get_new_generation(self, individuals): population = [] while len(population) < int(self.population_size * 0.75): population.extend(self.breed( random.choice(individuals), random.choice(individuals))) while len(population) < self.population_size: population.append(self.generate()) return population def breed(self, mother, father): point1 = random.randint(0,len(mother)-2) point2 = random.randint(point1+1, len(mother)-1) new1 = mother[:point1] + father[point1:point2] + mother[point2:] new2 = father[:point1] + mother[point1:point2] + father[point2:] if random.random() < 0.05: new1 = self.mutate(new1) if random.random() < 0.05: new2 = self.mutate(new2) return (new1, new2) def mutate(self, individual): x = list(individual) x[random.randint(0, len(x)-1)] = random.choice( random.choice( string.asciiletters + " ")) return "".join(x) if __name__ == "__main__": G = GenePool(300) G.run()