-
-
Save 1328/ad192afc6e33a4e48c9b to your computer and use it in GitHub Desktop.
matie
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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