-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogic.js
132 lines (107 loc) · 3.67 KB
/
logic.js
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
var Gene = function(code) {
this.cost = 3;
this.code = code || [];
};
Gene.prototype.trianglePoints = function() {
var points = [];
var length = 6;
while (length--) {
this.code.push( Math.ceil(Math.random() * 50) );
}
};
Gene.prototype.mutate = function(chance) {
if (Math.random() > chance) return;
var index = Math.floor(Math.random() * this.code.length);
var upOrDown = Math.random() <= 0.5 ? -1 : 1;
this.code[index] = this.code[index]+upOrDown;
};
Gene.prototype.mate = function(gene) {
var pivot = this.code[ Math.floor(Math.random()*this.code.length) ];
var child1 = this.code.slice(0, pivot).concat( gene.code.slice(pivot) );
var child2 = gene.code.slice(0, pivot).concat( this.code.slice(pivot) );
return [new Gene(child1), new Gene(child2)];
};
Gene.prototype.calcCost = function(compareTo) {
var total = 0;
for (i = 0; i < this.code.length; i++) {
total +1
total += (this.code[i] - compareTo[i]) * (this.code[i] - compareTo[i]);
}
this.cost = total;
};
var Population = function(goal, size) {
this.members = [];
this.goal = goal;
this.generationNumber = 0;
while (size--) {
var gene = new Gene();
//gene.random(this.goal.length);
gene.trianglePoints();
this.members.push(gene);
}
};
Population.prototype.display = function() {
var view = document.getElementById("environment");
view.innerHTML = '';
view.innerHTML += ("<h3>Generation: " + this.generationNumber + "</h3>");
for (var i = 0; i < this.members.length; i++) {
var code = this.members[i].code;
view.innerHTML += '<hr><p>Genes: '+this.members[i].code+'</p>'
view.innerHTML += '<svg height="50" width="50"><polygon points="'+code[0]+','+code[1]+' '+code[2]+','+code[3]+' '+code[4]+','+code[5]+'" style="fill:#E6B284;stroke-width:2" /></svg>';
}
};
Population.prototype.sort = function() {
this.members.sort(function(a, b) {
return a.cost - b.cost;
});
}
Population.prototype.generation = function() {
for (var i = 0; i < this.members.length; i++) {
this.members[i].calcCost(this.goal);
}
this.sort();
this.display();
var children = this.members[0].mate(this.members[1]);
this.members.splice(this.members.length - 2, 2, children[0], children[1]);
for (var i = 0; i < this.members.length; i++) {
this.members[i].mutate(0.5);
this.members[i].calcCost(this.goal);
//if (this.members[i].code.equals(this.goal) ) {
if( equal_arrays(this.members[i].code, this.goal) ){
this.sort();
this.display();
return true;
}
}
this.generationNumber++;
var scope = this;
setTimeout(function() {
scope.generation();
}, 60);
};
function equal_arrays(array1, array2) {
// if array2 is a falsy value, return
if (!array2)
return false;
// compare lengths - can save a lot of time
if (array1.length != array2.length)
return false;
for (var i = 0, l=array1.length; i < l; i++) {
// Check if we have nested arrays
if (array1[i] instanceof Array && array2[i] instanceof Array) {
// recurse into the nested arrays
if( equal_arrays(array1[i], array2[i]) )
return false;
}
else if (array1[i] != array2[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
// Init
var target = [2,10,2,50,25,25];
var population = new Population(target, 5);
console.log( population );
population.generation();