1 """Select individuals into a new population trying to maintain diversity.
2
3 This selection mechanism seeks to try and get both high fitness levels
4 and high diversity levels in the population.
5 """
6
7 import random
8 import math
9
10
11 from Bio.Seq import MutableSeq
12
13
14 from Abstract import AbstractSelection
15 from Tournament import TournamentSelection
16
18 """Implement diversity selection.
19
20 Diversity selection is performed by trying to select individuals
21 from the population that aren't already in the new_population. A group
22 of selected individuals is then subjected to selection using
23 a passed selection routine.
24
25 If new individuals can not be selected, new individuals will be
26 randomly generated and inserted into the population.
27 """
28 - def __init__(self, internal_selector, genome_generator):
29 """Initialize a diversity selector.
30
31 Arguments:
32
33 o internal_selector - A selection object that will be used to select
34 individuals based on fitness, perform crossover, mutation and repair.
35
36 o genome_generator - A function that, when called, will return a
37 genome to be used for a new organism. The genome returned must
38 be a MutableSeq() object.
39 """
40 self._internal_selector = internal_selector
41 self._genome_generator = genome_generator
42
43 self.sub_pop_percent = .1
44 self.random_tries = 10
45
47 """Get a new organism from old_pop that isn't in new_pop.
48
49 This attempts to select an organism from old_pop that isn't in
50 new_pop. If we can't do this in the number of tries specified
51 by the class attribute random_tries, we generate a new random
52 organism and return that.
53 """
54
55 new_org = None
56 num_tries = 0
57 while new_org is None and num_tries < self.random_tries:
58 chance_org = random.choice(old_pop)
59
60 if chance_org not in new_pop:
61 new_org = chance_org
62
63 num_tries += 1
64
65
66 if new_org is None:
67 new_org = old_pop[0].copy()
68 random_genome = self._genome_generator()
69 new_org.genome = random_genome
70 new_org.recalculate_fitness()
71
72 return new_org
73
75 """Perform selection on the current population, encouraging diversity.
76 """
77 new_population = []
78
79 while len(new_population) < len(population):
80
81 sub_pop_size = int(math.ceil(len(population) *
82 self.sub_pop_percent))
83 sub_pop = []
84 for individual in range(sub_pop_size):
85 new_org = self._get_new_organism(new_population, population)
86 sub_pop.append(new_org)
87
88
89
90 new_sub_pop = self._internal_selector.select(sub_pop)
91
92 new_population.extend(new_sub_pop)
93
94
95
96 return new_population[:len(population)]
97