-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSimulatedAnnealing.js
117 lines (103 loc) · 3.62 KB
/
SimulatedAnnealing.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
"use strict";
importScripts('./ContinuousOptimizer.js', './GaussianRNG.js');
function SimulatedAnnealing(parameters) {
ContinuousOptimizer.call(this, parameters);
this.T = parameters.T;
this.alpha = parameters.alpha;
this.epsilon = parameters.epsilon;
this.rng = new MarsagliaPolar();
}
;
SimulatedAnnealing.prototype = Object.create(ContinuousOptimizer.prototype);
SimulatedAnnealing.prototype.constructor = ContinuousOptimizer;
SimulatedAnnealing.prototype.createInitialSolution = function() {
var randomPos = this.createRandomPosition();
return new Solution(randomPos, this.calculateObjValue(randomPos));
};
SimulatedAnnealing.prototype.solve = function () {
var i, numOfFunctionEval = 0;
var current, neighborPos, neighborFitness, j;
current = this.createInitialSolution();
this.globalBest = new Solution(current.position.slice(), current.fitness); //set initial solution as the global best
while (numOfFunctionEval < this.maxFEs && this.T > this.epsilon) {
neighborPos = current.position.slice();
for (var j = 0; j < this.dimension; j++) {
neighborPos[j] = current.position[j] + this.rng.generateRandom(0, 1) * 6;
}
neighborPos = this.fixBoundary(neighborPos);
neighborFitness = this.calculateObjValue(neighborPos);
if (neighborFitness <= current.fitness) { //update current
current.position = neighborPos.slice();
current.fitness = neighborFitness;
if (current.fitness < this.globalBest.fitness) { //update globalbest
this.globalBest = new Solution(current.position.slice(), current.fitness);
postMessage([numOfFunctionEval, this.globalBest.fitness, this.globalBest.position]);
}
} else {
var prob = Math.random();
var delta = neighborFitness - current.fitness;
if (prob < Math.exp(-delta / this.T)) { //accept with metropolis criterion
current.position = neighborPos.slice();
current.fitness = neighborFitness;
}
}
this.T *= this.alpha; //decrease temperature
numOfFunctionEval ++;
}
postMessage([numOfFunctionEval, this.globalBest.fitness, this.globalBest.position]);
};
onmessage = function (e) {
var func;
switch (e.data[4]) {
case "sphere":
func = sphere;
break;
case "schwefel2_22":
func = schwefel2_22;
break;
case "schwefel1_2":
func = schwefel1_2;
break;
case "schwefel2_21":
func = schwefel2_21;
break;
case "rosenbrock":
func = rosenbrock;
break;
case "step":
func = step;
break;
case "quarticWithNoise":
func = quarticWithNoise;
break;
case "schwefel2_26":
func = schwefel2_26;
break;
case "rastrigin":
func = rastrigin;
break;
case "ackley":
func = ackley;
break;
case "griewank":
func = griewank;
break;
case "penalized":
func = penalized;
break;
default:
func = null;
}
var parameters = {
"T": e.data[0],
"alpha": e.data[1],
"epsilon": e.data[2],
"maxFEs": e.data[3],
"objFunc": func,
"upperBound": e.data[5],
"lowerBound": e.data[6],
"dimension": e.data[7]
};
var sa = new SimulatedAnnealing(parameters);
sa.solve();
};