1 """Provide Tournament style selection.
2
3 This implements selection based on a tournament style. In this model of
4 selection, two individuals are randomly chosen from the population, and
5 the organism with the higher fitness is considered the 'winner' and moves
6 to the next generation.
7 """
8
9 import random
10
11
12 from Abstract import AbstractSelection
13
14
16 """Implement tournament style selection.
17 """
18 - def __init__(self, mutator, crossover, repairer, num_competitors = 2):
19 """Initialize the tournament selector.
20
21 Arguments:
22
23 o num_competitors-- The number of individiuals that should be
24 involved in a selection round. By default we just have two
25 individuals (head to head!).
26
27 See AbstractSelection for a description of the arguments to
28 the initializer.
29 """
30 AbstractSelection.__init__(self, mutator, crossover, repairer)
31
32 if num_competitors < 2:
33 raise ValueError("Must have at least 2 competitors!")
34
35 self._num_competitors = num_competitors
36
38 """Perform selection on the population using the Tournament model.
39
40 Arguments:
41
42 o population -- A population of organisms on which we will perform
43 selection. The individuals are assumed to have fitness values which
44 are due to their current genome (ie. the fitness is up to date).
45 """
46
47 new_population = []
48
49 while len(new_population) < len(population):
50
51 new_orgs = []
52
53 for round_num in range(2):
54 competitors = []
55 while len(competitors) < self._num_competitors:
56 new_org = random.choice(population)
57 if new_org not in competitors:
58 competitors.append(new_org)
59
60
61
62 competitors.sort(key = lambda org: org.fitness)
63
64
65 new_orgs.append(competitors[-1])
66
67 assert len(new_orgs) == 2, "Expected two organisms to be selected"
68
69
70 new_org_1, new_org_2 = self.mutate_and_crossover(new_orgs[0],
71 new_orgs[1])
72
73 new_population.extend([new_org_1, new_org_2])
74
75 return new_population
76