Skip to content

Instantly share code, notes, and snippets.

@1328
Created April 24, 2015 13:54
Show Gist options
  • Select an option

  • Save 1328/ad192afc6e33a4e48c9b to your computer and use it in GitHub Desktop.

Select an option

Save 1328/ad192afc6e33a4e48c9b to your computer and use it in GitHub Desktop.
matie
#!/usr/bin/python
import random
import string
from functools import partial
from pprint import pprint
TARGET = "Michael Kilby"
DNA_SIZE = len(TARGET)
POP_SIZE = 1000
GENERATIONS = 100
MUTATE_CHANCE = [1,10] # chance kid will mutate
RANDO_MATCH = 20 # randomness added to mate selection process
LETTERS_AND_SPACE = string.ascii_letters + ' '
def random_char():
# Return a random character
return random.choice(LETTERS_AND_SPACE)
def make_population():
# Returns a list of POP_SIZE strings.
population = [''.join(random_char() for _ in range(DNA_SIZE))
for _ in range(POP_SIZE)]
return population
def trigger_mutation():
picked = random.randrange(0,MUTATE_CHANCE[1])
return MUTATE_CHANCE[0] > picked
def mutate(dna):
# Use MUTATE_CHANCE to create randomness in population
dna = ''.join(random_char() if trigger_mutation() else g for g in dna)
return dna
def fitness(dna):
# Calculate the difference between a character in the same position in the
# TARGET string.
# fitness = 0
correct_chars = sum(1 for a,b in zip(dna, TARGET) if a == b)
correct_percent = (correct_chars/DNA_SIZE) * 100
return correct_percent
def mate(mother, father):
# another comprehension for spped
kid = ''.join(random.choice([a,b]) for a,b in zip(mother, father))
mutate(kid)
return kid
def fitness_random(chaos, dna):
''' introduce a bit of randomness to the fitness assessment '''
r = chaos * random.random()
return fitness(dna) + r
def cross(pop):
''' take a population adn cross them based on fitness with a bit of rando
mixed in
'''
#pprint(pop)
f = fitness # no random
f = partial(fitness_random, RANDO_MATCH) # bit'o'random
weighted_pop = [(p, f(p)) for p in pop]
weighted_pop = sorted(weighted_pop, key = lambda x:-x[1])
#pprint(weighted_pop)
#pprint(weighted_pop)
its = [iter(weighted_pop)]*2
for a,b in zip(*its):
yield a[0], b[0]
def main():
# Make an initial population
population = make_population()
for generation in range(GENERATIONS):
kids = []
for a,b in cross(population):
kids.append(mate(a,b))
kids.append(mate(a,b))
population = kids
if generation % 30 == 0 or False:
print("Generation {} (pop = {})... Random sample: {} = {}".format(
generation,
len(population),
population[0],
fitness(population[0]),
))
best = max(population, key = fitness)
print('best: {} fitness = {}'.format(
best,
fitness(best)
))
def test():
#print('testing')
#print(list(cross(['michyyl', 'Michael', 'ppsdf'])))
#print(mate('abcdef','123456'))
print([trigger_mutation() for _ in range(10)])
if __name__ == "__main__":
#test()
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment