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()

Dec 20 2008

The Positivist Calendar

In 1849 Auguste Comte (1798-1857) published his ‘Calendrier positiviste’. This is not the place to expound Comte’s positivist philosophy, save to say that it encompassed lofty sentiments for the progress and betterment of the whole of mankind along rational lines. His calendar was intended as a vehicle for the inspiration of the people and to be transparently simple. Formally it broke new ground by dividing the year into 13 months, each containing 28 days or four seven-day weeks; these accounted for 364 days. The remaining day (or two days in leap years) were complementary epagomenal days placed at the end of the year; they did not belong to any week, nor were assigned a weekday name.

Mapping Time: The Calendar and its History, E.G. Richards

One of the nice things about the positivist calendar is that each day is dedicated to a particular person from history, ranging from Prometheus at the start of the year, all the way to Gall (a pioneer of neuroanatomy) at its end. This is also one of the reasons that few people other than Comte and his positivist friends took it seriously. Less fanciful attempts to reform the calendar have often failed, so Comte’s positivist calendar never stood a chance. These days it’s nothing more than an amusing historical footnote, which is a pity because even though it’s kind of ridiculous, it would be nice to live in a world where I could refer to today’s date as “Friday 19th Bichat, the day of Berthollet in the month of industry.” (That’s Marie François Xavier Bichat, an 18th Century French anatomist, and Claude Louis Berthollet, French chemist who helped devise modern chemical nomenclature.)

Obviously something had to be done. You can view the positivist date here. You can also download the source of the python script.