-
Notifications
You must be signed in to change notification settings - Fork 153
/
de.lua
109 lines (96 loc) · 3.27 KB
/
de.lua
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
--[[ An implementation of `DE` (Differential Evolution),
ARGS:
-`opfunc` : a function that takes a single input (X), the point of
evaluation, and returns f(X) and df/dX. Note that df/dX is not used
-`x` : the initial point
-`state.popsize`: population size. If this is left empty, 10*d will be used
-`state.scaleFactor`: float, usually between 0.4 and 1
-`state.crossoverRate`: float, usually between 0.1 and 0.9
-`state.maxEval`: int, maximal number of function evaluations
RETURN:
- `x*` : the new `x` vector, at the optimal point
- `f` : a table of all function values:
`f[1]` is the value of the function before any optimization and
`f[#f]` is the final fully optimized value, at `x*`
]]
require 'torch'
function optim.de(opfunc, x, config, state)
-- process input parameters
local config = config or {}
local state = state
local popsize = config.popsize -- population size
local scaleFactor = config.scaleFactor -- scale factor
local crossoverRate = config.crossoverRate -- crossover rate
local maxFEs = tonumber(config.maxFEs) -- maximal number of function evaluations
local maxRegion = config.maxRegion -- upper bound of search region
local minRegion = config.minRegion -- lower bound of search region
local xmean = x:clone():view(-1) -- distribution mean, a flattened copy
local D = xmean:size(1) -- number of objective variables/problem dimension
if config.popsize == nil then
popsize = 10 * D
end
if config.maxRegion == nil then
maxRegion = 30
end
if config.minRegion == nil then
minRegion = -30
end
-- Initialize population
local fx = x.new(maxFEs)
local pop = x.new(popsize, D)
local children = x.new(popsize, D)
local fitness = x.new(popsize)
local children_fitness = x.new(popsize)
local fes = 1 -- number of function evaluations
local best_fitness
local best_solution = x.new(D)
-- Initialize population and evaluate the its fitness value
local gen = torch.Generator()
torch.manualSeed(gen, 1)
pop:uniform(gen, minRegion, maxRegion)
for i = 1, popsize do
fitness[i] = opfunc(pop[i])
fx[fes] = fitness[i]
fes = fes + 1
end
-- Find the best solution
local index
best_fitness, index = fitness:max(1)
best_fitness = best_fitness[1]
index = index[1]
best_solution:copy(pop[index])
-- Main loop
while fes < maxFEs do
local r1, r2
for i = 1, popsize do
repeat
r1 = torch.random(gen, 1, popsize)
until(r1 ~= i)
repeat
r2 = torch.random(gen, 1, popsize)
until(r2 ~= r1 and r2 ~= i)
local jrand = torch.random(gen, 1, D)
for j = 1, D do
if torch.uniform(gen, 0, 1) < crossoverRate or i == jrand then
children[i][j] = best_solution[j] + scaleFactor * (pop[r1][j] - pop[r2][j])
else
children[i][j] = pop[i][j]
end
end
children_fitness[i] = opfunc(children[i])
fx[fes] = children_fitness[i]
fes = fes + 1
end
for i = 1, popsize do
if children_fitness[i] <= fitness[i] then
pop[i]:copy(children[i])
fitness[i] = children_fitness[i]
if fitness[i] < best_fitness then
best_fitness = fitness[i]
best_solution:copy(children[i])
end
end
end
end
return best_solution, fx
end