-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathGenetic.java
187 lines (165 loc) · 5.26 KB
/
Genetic.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
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Individual {
public int fitness, cols;
public double[] chromosomes;
private static int MUCHANCE = 20;
Random r;
public Individual (int cols) {
chromosomes = Weights.randomWeights().toArray();
this.cols = cols;
this.r = new Random();
}
public static Individual procreate(Individual i1, Individual i2) {
Individual child = new Individual(i1.cols);
int rand = child.r.nextInt(child.chromosomes.length);
for (int i = 0; i < child.chromosomes.length; i++) {
if (i < rand)
child.chromosomes[i] = i1.chromosomes[i];
else
child.chromosomes[i] = i2.chromosomes[i];
}
return child;
}
public void mutate() {
double stdDev = 0.3; // std dev for random multiplication and scale factor
double scale = 0.5*stdDev*r.nextGaussian()+1.0;
double flipChance = 0.10;
// double scale = 1;
for (int i = 0; i < chromosomes.length; i++) {
double chr = chromosomes[i];
double mutated = chr * (stdDev*r.nextGaussian()+1.0) * scale;
chromosomes[i] = mutated;
}
}
public void print(int num) {
System.out.format("%d Fitness: %d - Chromosomes: ", num, fitness);
for (int i = 0; i < chromosomes.length; i++)
System.out.format("[%f]", chromosomes[i]);
System.out.format("\n");
}
}
class Genetic {
Individual allTimeBest;
Individual[] individuals;
PlayerSkeleton p;
int rows, cols, populationSize;
public Genetic(int populationSize, int rows, int cols) {
individuals = new Individual[populationSize];
this.rows = rows;
this.cols = cols;
this.populationSize = populationSize;
this.allTimeBest = new Individual(cols);
this.allTimeBest.fitness = 0;
for (int i = 0; i < populationSize; i++)
individuals[i] = new Individual(cols);
}
private void resetIndividuals(){
this.allTimeBest = new Individual(cols);
for (int i = 0; i < populationSize; i++)
individuals[i] = new Individual(cols);
}
private void calculateFitness() {
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
for (int i = 0; i < individuals.length; i++) {
final Weights w = Weights.fromArray(individuals[i].chromosomes);
// PlayerSkeleton p = new PlayerSkeleton(w, rows, cols);
// individuals[i].fitness = p.playAndReturnScore();
int noRounds = 10; // How many rounds to take the average of
final Individual in = individuals[i];
in.fitness = 0;
for(int j = 0; j < noRounds; j++) {
Runnable aRunnable = new Runnable(){
@Override
public void run() {
PlayerSkeleton p = new PlayerSkeleton(w, rows, cols);
in.fitness += p.playAndReturnScore();
}
};
executor.execute(aRunnable);
}
individuals[i].fitness = individuals[i].fitness/noRounds;
}
executor.shutdown();
while (!executor.isTerminated()) {}
System.out.println("Finished all threads");
}
private int totalFitness() {
int total = 0;
for (int i = 0; i < individuals.length; i++)
total += individuals[i].fitness;
return total;
}
private Individual selectParent(int rand, Individual exclude) {
int i = 0;
Individual indi;
while (rand >= 0) {
indi = individuals[i++];
if (rand < indi.fitness && indi != exclude) {
System.out.format("%d ", i-1);
return indi;
} else if (indi != exclude) {
rand -= indi.fitness;
}
}
return null; // will not happen
}
private void selectAndProcreateFittest() {
int total = totalFitness();
Individual[] children = new Individual[individuals.length];
Individual p1, p2;
// keep best 1
children[0] = getBest();
// create the rest (NOTE FROM i = 1)
for (int i = 1; i < children.length; i++) {
p1 = selectParent(individuals[0].r.nextInt(total), null);
p2 = selectParent(individuals[0].r.nextInt(total), null);
children[i] = Individual.procreate(p1, p2);
children[i].mutate();
}
individuals = children;
System.out.println();
}
private Individual getBest() {
Individual best = individuals[0];
for (int i = 0; i < individuals.length; i++)
if (individuals[i].fitness > best.fitness)
best = individuals[i];
System.out.format("\nBest: ");
best.print(1);
// if(best.fitness > allTimeBest.fitness) {
// allTimeBest.fitness = best.fitness;
// System.arraycopy(best.chromosomes, 0, allTimeBest.chromosomes, 0, best.chromosomes.length);
// }
return best;
}
private void printGenerationInfo(int gen) {
System.out.format("\nGeneration %d:\n", gen);
for (int i = 0; i < individuals.length; i++) {
individuals[i].print(i);
}
System.out.println("\nGENERATION AVERAGE: " + totalFitness()/populationSize);
}
public Weights train(int generations) {
System.out.println("training for " + generations + " generations");
for (int i = 0; i < generations; i++) {
System.out.println("generation begin");
calculateFitness();
while(totalFitness() == 0){
resetIndividuals();
calculateFitness();
System.out.println("resetting");
}
printGenerationInfo(i);
selectAndProcreateFittest();
System.out.println("generation complete");
}
System.out.println("generation begin");
calculateFitness();
printGenerationInfo(generations);
Individual best = getBest();
System.out.println("generation complete");
return Weights.fromArray(best.chromosomes);
}
}