From 7bfd10552d871ecf7a937a07c05c3c526a15fbf1 Mon Sep 17 00:00:00 2001 From: liuruoze Date: Sun, 24 Jun 2018 17:26:44 +0800 Subject: [PATCH 1/2] * fix #4 * fix #5 --- genetics/simulation/discrete.py | 22 +++++++------ main.py | 58 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 main.py diff --git a/genetics/simulation/discrete.py b/genetics/simulation/discrete.py index 555a5b9..b27f77d 100644 --- a/genetics/simulation/discrete.py +++ b/genetics/simulation/discrete.py @@ -1,9 +1,10 @@ from collections.abc import Sequence + def pairwise(iterable): ''' Given an iterable, yield the items in it in pairs. For instance: - + list(pairwise([1,2,3,4])) == [(1,2), (3,4)] ''' x = iter(iterable) @@ -11,9 +12,10 @@ def pairwise(iterable): class DiscreteSimulation: + def __init__(self, population_size, mutation_mask, crossover_mask, - selection_function, elite_size, - initial_generator, fitness_function): + selection_function, elite_size, + initial_generator, fitness_function): self.population_size = population_size self.mutation_mask = mutation_mask self.crossover_mask = crossover_mask @@ -45,7 +47,7 @@ def initial_population(self): Create an initial populaton ''' return [self.initial_generator() for _ in - range(self.population_size)] + range(self.population_size)] def step_generator(self, population): ''' @@ -53,14 +55,15 @@ def step_generator(self, population): population members ''' # Score and sort population - scored_population = sorted(self.find_scores(population), reverse=True, - key=lambda member: member[0]) + scored_population = [m[1] for m in sorted(self.find_scores(population), reverse=True, + key=lambda member: member[0])] # Yield the elite elements - yield from scored_population[:self.elite_size] - # Generate parents + for elite in scored_population[:self.elite_size]: + yield elite + + # Yield the crossover and mutate elements for parent1, parent2 in pairwise(self.parents(scored_population)): - # crossover parents mask = self.crossover_mask(parent1.total_length()) for child in parent1.combine(parent2, mask): # mutate @@ -72,4 +75,3 @@ def step(self, population): list. ''' return list(self.step_generator(population)) - diff --git a/main.py b/main.py new file mode 100644 index 0000000..44d15d3 --- /dev/null +++ b/main.py @@ -0,0 +1,58 @@ + +import string +import random + +import genetics + +letters = string.ascii_uppercase + string.ascii_lowercase + string.punctuation + ' ' +solution = 'Hello World!' + + +class LetterComponent(genetics.DNAComponent): + + def mutate_value(self): + return random.choice(letters) + + +class WordDNA(genetics.arrayed_segment(len(solution), LetterComponent)): + + def score(self): + score = sum(comp.value == letter for comp, letter in zip(self, solution)) + return score + + def __str__(self): + return ''.join(comp.value for comp in self) + + def __gt__(self, other): + return self.score() > other.score() + +sim = genetics.DiscreteSimulation( + population_size=100, + mutation_mask=genetics.mutation_rate(0.05), # Mutate at a 5% rate + crossover_mask=genetics.two_point_crossover, + selection_function=genetics.tournament(2), + elite_size=2, + initial_generator=WordDNA, + fitness_function=WordDNA.score) + + +def dna_stats(population): + '''Best DNA, best score, average score''' + best_dna = max(population) + best_score = best_dna.score + average_score = sum(member.score() for member in population) / len(population) + + return best_dna, best_score, average_score + + +population = sim.initial_population() + +while True: + best, best_score, average_score = dna_stats(population) + + print('{} | Average score: {}'.format(str(best), average_score)) + + if str(best) == solution: + break + + population = sim.step(population) From 1af5603ed5248beb2adc2a6c99c4bd8baeff4697 Mon Sep 17 00:00:00 2001 From: liuruoze Date: Sun, 24 Jun 2018 17:32:34 +0800 Subject: [PATCH 2/2] * fix issue --- genetics/simulation/discrete.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/genetics/simulation/discrete.py b/genetics/simulation/discrete.py index b27f77d..1cc5a13 100644 --- a/genetics/simulation/discrete.py +++ b/genetics/simulation/discrete.py @@ -59,11 +59,10 @@ def step_generator(self, population): key=lambda member: member[0])] # Yield the elite elements - for elite in scored_population[:self.elite_size]: - yield elite - - # Yield the crossover and mutate elements + yield from scored_population[:self.elite_size] + # Generate parents for parent1, parent2 in pairwise(self.parents(scored_population)): + # crossover parents mask = self.crossover_mask(parent1.total_length()) for child in parent1.combine(parent2, mask): # mutate