-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.ts
More file actions
119 lines (113 loc) · 4.19 KB
/
main.ts
File metadata and controls
119 lines (113 loc) · 4.19 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
const catNum = 10;
const tracingCatNum = 2
const catImgSize = 32;
const canvasSize = 512;
const solutionDim = 2;
const seekingMemorySize = 10;
const seekingRange = canvasSize / 100;
const mayStayWhenSeeking = true
const interval = 10;
const velocityMax = canvasSize * interval / 1000;
const traceVelocityRate = 0.01
function fitness(position: number[]): number{
return 0.0005 * Math.pow(position[0] - canvasSize / 2, 2)
+ 0.005 * Math.pow(position[1] - canvasSize / 2, 2)
- 20 * Math.pow(Math.sin(position[0] / 100.0), 20)
}
interface Cat {
position: number[]
velocity: number[]
}
const cats: Cat[] = [...Array(catNum)].map(() => {
return {
position: [...Array(solutionDim)].map(() => Math.random() * canvasSize),
velocity: [...Array(solutionDim)].map(() => Math.random() * canvasSize)
}
});
function updateCats(): void{
/*
cats.forEach(cat => {
cat.position[0] += 2
cat.position[1] += 1
});
*/
const fitnessVals = cats.map(cat => fitness(cat.position));
const fittestCat = cats[argMin(fitnessVals)];
shuffledBits(catNum, tracingCatNum).forEach((bit, i) => {
const cat = cats[i];
if (bit === 0){// seeking
const newPositions =
[...Array(mayStayWhenSeeking ? seekingMemorySize - 1 : seekingMemorySize)].map(() =>
[...Array(solutionDim)].map((_, d) =>
cat.position[d] + (Math.random() * 2 - 1) * seekingRange));
if (mayStayWhenSeeking) newPositions.push(cat.position);
const newFitnessVals = newPositions.map(p => fitness(p));
const newFitnessValMax = Math.max(...newFitnessVals);
const probs = newFitnessValMax - Math.min(...newFitnessVals) == 0 ?
newFitnessVals.map(() => 1) :
newFitnessVals.map(newFitnessVal => newFitnessValMax - newFitnessVal);
cat.position = newPositions[roulette(probs)];
}
else{// tracing
///*
const coeff = Math.random() * traceVelocityRate;
[...Array(solutionDim)].forEach((_, d) => {
cat.velocity[d] += coeff * (fittestCat.position[d] - cat.position[d]);
});
cat.velocity = constrainVec(cat.velocity, velocityMax);
[...Array(solutionDim)].forEach((_, d) => {
cat.position[d] += cat.velocity[d];
});//*/
}
[...Array(solutionDim)].forEach((_, d) => {
cat.position[d] = constrain(cat.position[d], 0, canvasSize);
});
});
}
window.onload = () => {
const canvas = document.getElementById("canvas");
if (canvas == null || !(canvas instanceof HTMLCanvasElement)){
alert("Can't find \"canvas\": HTMLCanvasElement")
return
}
canvas.width = canvasSize;
canvas.height = canvasSize;
const context = canvas.getContext('2d');
if (context == null){
alert("Can't find context2d")
return
}
[...Array(canvasSize)].forEach((_, x) => {
[...Array(canvasSize)].forEach((_, y) => {
const z = Math.floor(constrain(fitness([x, y]), 0, 255) / 10) * 10
context.fillStyle = "rgb("+[z, z, z].join(",")+")"
context.fillRect(x, y, 1, 1)
});
});
const upper = document.getElementById("upper");
if (upper == null || !(upper instanceof HTMLDivElement)){
alert("Can't find \"upper\": HTMLDivElement")
return
}
upper.style.width = canvasSize + "px";
upper.style.height = canvasSize + "px";
const catImgs: HTMLImageElement[] = [...Array(catNum)].map(() => {
const catImg = document.createElement("img")
catImg.src = "kedukuroi.png"
catImg.style.position = "absolute"
catImg.style.width = catImgSize + "px"
upper.appendChild(catImg)
return catImg
});
const updateCatImgs: () => void = () => {
catImgs.forEach((_, i) => {
catImgs[i].style.left = cats[i].position[0] - catImgSize / 2 + "px"
catImgs[i].style.top = cats[i].position[1] - catImgSize / 2 + "px"
});
};
updateCatImgs();
setInterval(() => {
updateCats();
updateCatImgs();
}, interval);
};