forked from melih23/test
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGeneticAlgorithm.java
206 lines (170 loc) · 5.88 KB
/
GeneticAlgorithm.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package chapter5;
public class GeneticAlgorithm {
private int populationSize;
private double mutationRate;
private double crossoverRate;
private int elitismCount;
protected int tournamentSize;
public GeneticAlgorithm(int populationSize, double mutationRate, double crossoverRate, int elitismCount,
int tournamentSize) {
this.populationSize = populationSize;
this.mutationRate = mutationRate;
this.crossoverRate = crossoverRate;
this.elitismCount = elitismCount;
this.tournamentSize = tournamentSize;
}
/**
* Initialize population
*
* @param chromosomeLength
* The length of the individuals chromosome
* @return population The initial population generated
*/
public Population initPopulation(Timetable timetable) {
// Initialize population
Population population = new Population(this.populationSize, timetable);
return population;
}
/**
* Check if population has met termination condition
*
* @param generationsCount
* Number of generations passed
* @param maxGenerations
* Number of generations to terminate after
* @return boolean True if termination condition met, otherwise, false
*/
public boolean isTerminationConditionMet(int generationsCount, int maxGenerations) {
return (generationsCount > maxGenerations);
}
/**
* Check if population has met termination condition
*
* @param population
* @return boolean True if termination condition met, otherwise, false
*/
public boolean isTerminationConditionMet(Population population) {
return population.getFittest(0).getFitness() == 1.0;
}
/**
* Calculate individual's fitness value
*
* @param individual
* @param timetable
* @return fitness
*/
public double calcFitness(Individual individual, Timetable timetable) {
// Create new timetable object to use -- cloned from an existing timetable
Timetable threadTimetable = new Timetable(timetable);
threadTimetable.createClasses(individual);
// Calculate fitness
int clashes = threadTimetable.calcClashes();
double fitness = 1 / (double) (clashes + 1);
individual.setFitness(fitness);
return fitness;
}
/**
* Evaluate population
*
* @param population
* @param timetable
*/
public void evalPopulation(Population population, Timetable timetable) {
double populationFitness = 0;
// Loop over population evaluating individuals and summing population
// fitness
for (Individual individual : population.getIndividuals()) {
populationFitness += this.calcFitness(individual, timetable);
}
population.setPopulationFitness(populationFitness);
}
/**
* Selects parent for crossover using tournament selection
*
* Tournament selection works by choosing N random individuals, and then
* choosing the best of those.
*
* @param population
* @return The individual selected as a parent
*/
public Individual selectParent(Population population) {
// Create tournament
Population tournament = new Population(this.tournamentSize);
// Add random individuals to the tournament
population.shuffle();
for (int i = 0; i < this.tournamentSize; i++) {
Individual tournamentIndividual = population.getIndividual(i);
tournament.setIndividual(i, tournamentIndividual);
}
// Return the best
return tournament.getFittest(0);
}
/**
* Apply mutation to population
*
* @param population
* @param timetable
* @return The mutated population
*/
public Population mutatePopulation(Population population, Timetable timetable) {
// Initialize new population
Population newPopulation = new Population(this.populationSize);
// Loop over current population by fitness
for (int populationIndex = 0; populationIndex < population.size(); populationIndex++) {
Individual individual = population.getFittest(populationIndex);
// Create random individual to swap genes with
Individual randomIndividual = new Individual(timetable);
// Loop over individual's genes
for (int geneIndex = 0; geneIndex < individual.getChromosomeLength(); geneIndex++) {
// Skip mutation if this is an elite individual
if (populationIndex > this.elitismCount) {
// Does this gene need mutation?
if (this.mutationRate > Math.random()) {
// Swap for new gene
individual.setGene(geneIndex, randomIndividual.getGene(geneIndex));
}
}
}
// Add individual to population
newPopulation.setIndividual(populationIndex, individual);
}
// Return mutated population
return newPopulation;
}
/**
* Apply crossover to population
*
* @param population The population to apply crossover to
* @return The new population
*/
public Population crossoverPopulation(Population population) {
// Create new population
Population newPopulation = new Population(population.size());
// Loop over current population by fitness
for (int populationIndex = 0; populationIndex < population.size(); populationIndex++) {
Individual parent1 = population.getFittest(populationIndex);
// Apply crossover to this individual?
if (this.crossoverRate > Math.random() && populationIndex >= this.elitismCount) {
// Initialize offspring
Individual offspring = new Individual(parent1.getChromosomeLength());
// Find second parent
Individual parent2 = selectParent(population);
// Loop over genome
for (int geneIndex = 0; geneIndex < parent1.getChromosomeLength(); geneIndex++) {
// Use half of parent1's genes and half of parent2's genes
if (0.5 > Math.random()) {
offspring.setGene(geneIndex, parent1.getGene(geneIndex));
} else {
offspring.setGene(geneIndex, parent2.getGene(geneIndex));
}
}
// Add offspring to new population
newPopulation.setIndividual(populationIndex, offspring);
} else {
// Add individual to new population without applying crossover
newPopulation.setIndividual(populationIndex, parent1);
}
}
return newPopulation;
}
}