-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGeneticAlgorithm.pde
323 lines (303 loc) · 8.23 KB
/
GeneticAlgorithm.pde
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
//"Constants"
int POPULATION_SIZE = 25;
//Global Variables
int selectedX;
int selectedY;
int bestX;
int bestY;
boolean continuous = false;
float totalFitness;
int speed;
int generation;
float mutationRate = 0.05;
int rad;
int row;
int col;
//The actual individuals
Individual[] population;
Individual selected;
Individual best;
/*=====================================
Create an initial population of randomly
generated individuals.
Setup the basic window properties
====================================*/
void setup() {
speed = 30;
generation = 0;
frameRate(speed);
int temp = round(sqrt(POPULATION_SIZE));
int temp2 = temp;
while (POPULATION_SIZE % temp != 0 && POPULATION_SIZE % temp2 !=0) {
temp--;
temp2++;
}
if (POPULATION_SIZE % temp == 0) {
row = temp;
col = POPULATION_SIZE / row;
} else {
row = temp2;
col = POPULATION_SIZE / row;
}
population = new Individual[POPULATION_SIZE];
population[0] = new Individual(0.0, 0.0);
rad = 5;
for (int i = 0; i < population[0].RADIUS_GENE_SIZE; i++) {
rad += pow(2, i);
}
populate();
size(row * rad * 2, col * rad * 2);
}
/*=====================================
Redraw very Individual in the population
each frame. Make sure they are drawn in a grid without
overlaping each other.
If an individual has been slected (by the mouse), draw a box
around it and draw a box around the individual with the
highest fitness value.
If mating mode is set to continuous, call mating season
====================================*/
void draw() {
background(255, 255, 255);
for (int i = 0; i < population.length; i++) {
stroke(0, 0, 0);
population[i].display();
}
if (continuous) {
matingSeason();
}
if (selected != null) {
noFill();
stroke(255, 0, 0);
rect(selectedX - rad, selectedY -rad, rad*2, rad*2);
stroke(0, 0, 255);
rect(bestX - rad, bestY - rad, rad*2, rad*2);
}
}
/*=====================================
When the mouse is clicked, set selected to
the individual clicked on, and set
selectedX and selectedY so that a box can be
drawn around it.
====================================*/
void mouseClicked() {
int beginX = 0;
int beginY = 0;
int endX = 0;
int endY = 0;
if (mouseX > rad) {
beginX = mouseX - rad;
}
else {
beginX = 0;
}
if (mouseY > rad) {
beginY = mouseY - rad;
}
else {
beginY = 0;
}
if (mouseX + rad < width) {
endX = mouseX + rad;
}
else {
endX = width;
}
if (mouseY + rad < height) {
endY = mouseY + rad;
}
else {
endY = height;
}
for (int i = 0; i < population.length; i++) {
if ( (population[i].phenotype).x > beginX && (population[i].phenotype).x < endX
&& (population[i].phenotype).y > beginY && (population[i].phenotype).y < endY) {
Individual temp = population[0];
int tempx = int((population[i].phenotype).x);
int tempy = int((population[i].phenotype).y);
population[0] = population[i];
(population[0].phenotype).x = rad;
(population[0].phenotype).y = rad;
population[i] = temp;
(population[i].phenotype).x = tempx;
(population[i].phenotype).y = tempy;
}
}
selected = population[0];
totalFitness();
selectedX = int((selected.phenotype).x);
selectedY = int((selected.phenotype).y);
}
/*====================================
The following keys are mapped to actions:
Right Arrow: move forard one generation
Up Arrow: speed up when in continuous mode
Down Arrow: slow down when in continuous mode
Shift: toggle continuous mode
Space: reset the population
f: toggle fitness value display
s: toggle smiley display
m: increase mutation rate
n: decrease mutation rate
==================================*/
void keyPressed() {
if (keyCode == RIGHT) {
matingSeason();
}
if (keyCode == UP) {
System.out.print("Speed: ");
speed += 5;
frameRate(speed);
System.out.println(speed);
}
if (keyCode == DOWN) {
System.out.print("Speed: ");
speed -= 5;
frameRate(speed);
System.out.println(speed);
}
if (keyCode == SHIFT) {
continuous = !(continuous);
if(continuous) {
System.out.println("continuous");
}
else {
System.out.println("non-continuous");
}
}
if (keyCode == ' ') {
generation = 0;
populate();
}
if (keyCode == 'm' || keyCode == 'M') {
System.out.print("Mutation Rate: ");
if (mutationRate >= 100) {
System.out.println("Maxed");
}
else {
mutationRate += 0.01;
System.out.println(mutationRate);
}
}
if (keyCode == 'n' || keyCode == 'N') {
System.out.print("Mutation Rate: ");
if (mutationRate < 0) {
System.out.println("Minimum");
}
mutationRate -= 0.01;
System.out.println(mutationRate);
}
}
/*====================================
select will return a pseudo-random chromosome from the population
Uses roulette wheel selection:
A random number is generated between 0 and the total fitness
Go through the population and add each member's fitness until you exceed the random
number that was generated.
Return the individual that the algorithm stopped on
Do not include the "selected" Blob as a possible return value
==================================*/
Individual select() {
totalFitness();
float sum = 0;
int fin = 0;
float rand = random(totalFitness);
Individual[] temp = new Individual[population.length];
arrayCopy(population, temp);
int pos = 0;
while (sum < rand) {
pos = int(random(1, population.length));
while (temp[pos] == null) {
pos = int(random(1, population.length));
}
sum += temp[pos].fitness;
if (sum < rand) {
temp[pos] = null;
}
}
return population[pos];
}
/*====================================
Replaces the current population with a totally new one by
selecting pairs of Individuals and "mating" them.
Make sure that totalFitness is set before you use select().
The goal shape (selected) should always be rist Individulation, unmodified.
==================================*/
void matingSeason() {
int x = 0;
int y = 0;
Individual[] pop = new Individual[population.length];
pop[0] = population[0];
for (int i = 1; i < population.length; i++) {
Individual parent1 = select();
Individual parent2 = select();
x = int((population[i].phenotype).x);
y = int((population[i].phenotype).y);
pop[i] = parent1.mate(parent2, x, y);
}
arrayCopy(pop, population);
mutate();
generation++;
System.out.println("Generation: " + generation);
totalFitness();
System.out.println("Total Fitness: " + totalFitness);
System.out.println("Best Fitness: " + best.fitness);
}
/*====================================
Randomly call the mutate method an Individual (or Individuals)
in the population.
==================================*/
void mutate() {
for (int i = 1; i < population.length; i++) {
float rand = random(1);
if ( rand < mutationRate ) {
population[i].mutate();
}
}
}
/*====================================
Set the totalFitness to the sum of the fitness values
of each individual.
Make sure that each individual has an accurate fitness value
==================================*/
void totalFitness() {
totalFitness = 0.0;
for (int i = 1; i < population.length; i++) {
population[i].setFitness(selected);
totalFitness += population[i].fitness;
}
findBest();
}
/*====================================
Fill the population with randomly generated Individuals
Make sure to set the location of each individual such that
they display nicely in a grid.
==================================*/
void populate() {
int cRow = 1;
int cCol = 1;
for (int i = 0; i < population.length; i++) {
population[i] = new Individual(cRow * rad, cCol * rad);
cCol+=2;
if (cCol > 2 * col) {
cCol = 1;
cRow += 2;
}
}
}
/*====================================
Go through the population and find the Individual with the
highest fitness value.
Set bestX and bestY so that the best Individual can have a
square border drawn around it.
==================================*/
void findBest() {
best = population[1];
for (int i = 2; i < population.length; i++) {
if (best.fitness < population[i].fitness) {
best = population[i];
}
}
bestX = int((best.phenotype).x);
bestY = int((best.phenotype).y);
}