1 """Implement Roulette Wheel selection on a population.
2
3 This implements Roulette Wheel selection in which individuals are
4 selected from a population randomly, with their proportion of selection
5 based on their relative fitness in the population.
6 """
7
8 import random
9 import copy
10
11
12 from Abstract import AbstractSelection
13
14
16 """Roulette wheel selection proportional to individuals fitness.
17
18 The implements a roulette wheel selector that selects individuals
19 from the population, and performs mutation and crossover on
20 the selected individuals.
21 """
22 - def __init__(self, mutator, crossover, repairer = None):
23 """Initialize the selector.
24
25 Arguments:
26
27 o mutator -- A Mutation object which will perform mutation
28 on an individual.
29
30 o crossover -- A Crossover object which will take two
31 individuals and produce two new individuals which may
32 have had crossover occur.
33
34 o repairer -- A class which can do repair on rearranged genomes
35 to eliminate infeasible individuals. If set at None, so repair
36 will be done.
37 """
38 AbstractSelection.__init__(self, mutator, crossover, repairer)
39
41 """Perform selection on the population based using a Roulette model.
42
43 Arguments:
44
45 o population -- A population of organisms on which we will perform
46 selection. The individuals are assumed to have fitness values which
47 are due to their current genome.
48 """
49
50
51 prob_wheel = self._set_up_wheel(population)
52 probs = prob_wheel.keys()
53 probs.sort()
54
55
56 new_population = []
57
58 for pair_spin in range(len(population) // 2):
59
60 choice_num_1 = random.random()
61 choice_num_2 = random.random()
62
63
64 chosen_org_1 = None
65 chosen_org_2 = None
66 prev_prob = 0
67 for cur_prob in probs:
68 if choice_num_1 > prev_prob and choice_num_1 <= cur_prob:
69 chosen_org_1 = prob_wheel[cur_prob]
70 if choice_num_2 > prev_prob and choice_num_2 <= cur_prob:
71 chosen_org_2 = prob_wheel[cur_prob]
72
73 prev_prob = cur_prob
74
75 assert chosen_org_1 is not None, "Didn't select organism one"
76 assert chosen_org_2 is not None, "Didn't select organism two"
77
78
79 new_org_1, new_org_2 = self.mutate_and_crossover(chosen_org_1,
80 chosen_org_2)
81
82 new_population.extend([new_org_1, new_org_2])
83
84 return new_population
85
87 """Set up the roulette wheel based on the fitnesses.
88
89 This creates a fitness proportional 'wheel' that will be used for
90 selecting based on random numbers.
91
92 Returns:
93
94 o A dictionary where the keys are the 'high' value that an
95 individual will be selected. The low value is determined by
96 the previous key in a sorted list of keys. For instance, if we
97 have a sorted list of keys like:
98
99 [.1, .3, .7, 1]
100
101 Then the individual whose key is .1 will be selected if a number
102 between 0 and .1 is chosen, the individual whose key is .3 will
103 be selected if the number is between .1 and .3, and so on.
104
105 The values of the dictionary are the organism instances.
106 """
107
108 total_fitness = 0
109 for org in population:
110 total_fitness += org.fitness
111
112
113 wheel_dict = {}
114 total_percentage = 0
115 for org in population:
116 org_percentage = float(org.fitness) / float(total_fitness)
117
118
119
120
121 wheel_dict[total_percentage + org_percentage] = copy.copy(org)
122
123
124 total_percentage += org_percentage
125
126 return wheel_dict
127