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
15 """Implement tournament style selection.
16 """
17 - def __init__(self, mutator, crossover, repairer, num_competitors = 2):
18 """Initialize the tournament selector.
19
20 Arguments:
21
22 o num_competitors-- The number of individiuals that should be
23 involved in a selection round. By default we just have two
24 individuals (head to head!).
25
26 See AbstractSelection for a description of the arguments to
27 the initializer.
28 """
29 AbstractSelection.__init__(self, mutator, crossover, repairer)
30
31 if num_competitors < 2:
32 raise ValueError("Must have at least 2 competitors!")
33
34 self._num_competitors = num_competitors
35
37 """Comparison function for comparing two organisms.
38
39 This just allows us to easily sort organisms by fitness.
40 """
41 return cmp(org_1.fitness, org_2.fitness)
42
44 """Perform selection on the population using the Tournament model.
45
46 Arguments:
47
48 o population -- A population of organisms on which we will perform
49 selection. The individuals are assumed to have fitness values which
50 are due to their current genome (ie. the fitness is up to date).
51 """
52
53 new_population = []
54
55 while len(new_population) < len(population):
56
57 new_orgs = []
58
59 for round_num in range(2):
60 competitors = []
61 while len(competitors) < self._num_competitors:
62 new_org = random.choice(population)
63 if new_org not in competitors:
64 competitors.append(new_org)
65
66
67
68 competitors.sort(self._fitness_cmp)
69
70
71 new_orgs.append(competitors[-1])
72
73 assert len(new_orgs) == 2, "Expected two organisms to be selected"
74
75
76 new_org_1, new_org_2 = self.mutate_and_crossover(new_orgs[0],
77 new_orgs[1])
78
79 new_population.extend([new_org_1, new_org_2])
80
81 return new_population
82