-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpopulation.js
More file actions
127 lines (98 loc) · 3.04 KB
/
Copy pathpopulation.js
File metadata and controls
127 lines (98 loc) · 3.04 KB
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
class Population {
constructor(size) {
this.size = size;
this.players = [];
// probability that a child is created by crossing over
this.crossoverRate = 0.75;
// probability that mutation occurs
this.mutationRate = 0.05;
this.initPlayers();
}
initPlayers() {
for (let i = 0; i < this.size; i++) {
this.players[i] = new Player();
}
}
update() {
for (let i = 0; i < this.players.length; i++) {
this.players[i].update();
}
if (this.allDead()) {
this.evolve();
}
}
show() {
for (let i = 0; i < this.players.length; i++) {
this.players[i].show();
}
}
allDead() {
for (let i = 0; i < this.players.length; i++) {
if (!this.players[i].isDead) {
return false;
}
}
return true;
}
evolve() {
let newPlayers = [];
this.calculateFitnesses();
for (let i = 0; i < this.players.length - 1; i++) {
let parent1 = this.selectParent();
let parent2 = this.selectParent();
let childDNA = this.crossover(parent1.neuralNet.toDNA(), parent2.neuralNet.toDNA());
this.mutate(childDNA);
let child = new Player();
child.neuralNet = child.neuralNet.fromDNA(childDNA).value;
newPlayers.push(child);
}
let fittestPlayer = this.players[0];
let fitnessRecord = 0;
for (let i = 0; i < this.players.length; i++) {
if (this.players[i].fitness > fitnessRecord) {
fittestPlayer = this.players[i];
}
}
newPlayers.push(fittestPlayer);
this.players = newPlayers;
gTerrain = new Terrain(900, 350);
}
calculateFitnesses() {
for (let i = 0; i < this.players.length; i++) {
this.players[i].calculateFitness();
}
}
selectParent() {
let fitnessSum = 0;
for (let i = 0; i < this.players.length; i++) {
fitnessSum += this.players[i].fitness;
}
let randomNumber = random(fitnessSum);
let runningSum = 0;
for (let i = 0; i < this.players.length; i++) {
runningSum += this.players[i].fitness;
if (runningSum > randomNumber) {
return this.players[i];
}
}
}
crossover(parentDNA1, parentDNA2) {
let childDNA = [];
if (random(1) > this.crossoverRate) {
childDNA = parentDNA1.slice(0);
}
else {
let splitPoint = int(random(parentDNA1.length));
childDNA = parentDNA1.slice(0, splitPoint);
childDNA.push(...parentDNA2.slice(splitPoint));
}
return childDNA;
}
mutate(dna) {
for (let i = 0; i < dna.length; i++) {
if (random(1) < this.mutationRate) {
dna[i] = biolib.Utils.normalizedRandom();
}
}
}
}