def per_genome_mutation(probability=0.01, mutate=None): def fn(genome): if random.random() < probability: component_to_mutate = random.randint(0, len(genome) - 1) if mutate: mutate(genome, component_to_mutate) else: genome.mutate(component_to_mutate) return genome return Mixin('per_genome_mutation', fn, {'probability': probability, 'mutate': mutate})
def split_crossover(p=1): def fn(parent_a, parent_b): child = SymbolVectorGenotype(parent_a.symbol_set_size, len(parent_a)) if random.random() < p: split = random.randint(0, len(parent_a) - 1) for i, _ in enumerate(child): child[i] = parent_a[i] if i < split else parent_b[i] else: for i, _ in enumerate(parent_a): child[i] = parent_a[i] child.fitness = parent_a.fitness return child return Mixin('split_crossover', fn, kwargs={'p': p})
def fitness_proportionate_selection(): def fn(population, fitnesses=None): fitnesses = fitnesses or\ [individual.fitness for individual in population] total_fitness = sum(fitnesses) roll = random.uniform(0, total_fitness) counter = 0 for fitness, individual in zip(fitnesses, population): counter += fitness if counter >= roll: return individual return Mixin('fitness_proportionate_selection', fn)
def per_genome_component_mutation(probability=0.01, mutate=None): def fn(genome): for i, _ in enumerate(genome): if random.random() < probability: if mutate: mutate(genome, i) else: genome.mutate(i) return genome return Mixin('per_genome_component_mutation', fn, { 'probability': probability, 'mutate': mutate, })
def genome_component_crossover(p=1): def fn(parent_a, parent_b): child = SymbolVectorGenotype(parent_a.symbol_set_size, len(parent_a)) if random.random() < p: for i, _ in enumerate(child): child[i] = parent_a[i] if random.random() < 0.5\ else parent_b[i] return child else: for i, _ in enumerate(parent_a): child[i] = parent_a[i] child.fitness = parent_a.fitness return child return Mixin('genome_component_crossover', fn, kwargs={'p': p})
def tournament_selection(k=1, epsilon=0.05): def fn(population): tournament_participants = random.sample(population, k) if random.random() < epsilon: return random.choice(tournament_participants) else: return max(tournament_participants, key=lambda x: x.fitness) return Mixin('tournament_selection', fn, kwargs={ 'k': k, 'epsilon': epsilon })
def sigma_scaling_selection(): fps = fitness_proportionate_selection() def fn(population): fitnesses = [individual.fitness for individual in population] average_fitness = np.mean(fitnesses) standard_deviation = np.std(fitnesses) standard_deviation = max(0.0001, standard_deviation) scaled_fitnesses = [ 1 + (fitness - average_fitness) / (2 * standard_deviation) for fitness in fitnesses ] return fps(population, fitnesses=scaled_fitnesses) return Mixin('sigma_scaling_selection', fn)
def rank_selection(): fps = fitness_proportionate_selection() def fn(population): sorted_population = sorted(population, key=lambda individual: individual.fitness) fitnesses = [individual.fitness for individual in population] min_fitness = min(fitnesses) max_fitness = max(fitnesses) N = len(population) scaled_fitnesses = [ min_fitness + (max_fitness - min_fitness) * i / (N - 1) for i in range(N) ] return fps(sorted_population, fitnesses=scaled_fitnesses) return Mixin('rank_selection', fn)
def full_generational_replacement(): def fn(adults, children, adult_pool_size): new_adults = children return new_adults return Mixin('full_generational_replacement', fn)
def generational_mixing(): def fn(adults, children, adult_pool_size): new_adults = random.sample(children + adults, adult_pool_size) return new_adults return Mixin('generational_mixing', fn)
def over_production(): def fn(adults, children, adult_pool_size): new_adults = random.sample(children, adult_pool_size) return new_adults return Mixin('over_production', fn)
def random_selection(): def fn(population): return random.choice(population) return Mixin('random_selection', fn)