-
Notifications
You must be signed in to change notification settings - Fork 95
/
Copy pathcmaes.jl
68 lines (65 loc) · 1.74 KB
/
cmaes.jl
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
using Random
using LinearAlgebra
using Statistics
mutable struct CMAES
N::Int
μ::Int
λ::Int
τ::Float64
τ_c::Float64
τ_σ::Float64
population::Array{Array{Float64}}
offspring::Array{Array{Float64}}
F_μ::Array{Float64}
F_λ::Array{Float64}
C::Array{Float64}
s::Array{Float64}
s_σ::Array{Float64}
σ::Float64
E::Array{Float64}
W::Array{Float64}
x::Array{Float64}
end
function CMAES(;N=2, μ=1, λ=10, τ=sqrt(N), τ_c=N^2, τ_σ=sqrt(N))
x = randn(N)
population = fill(x, µ)
offspring = Array{Array{Float64}}(undef, λ)
F_µ = Inf .* ones(µ)
F_λ = Inf .* ones(λ)
C = Array(Diagonal{Float64}(I, N))
s = zeros(N)
s_σ = zeros(N)
σ = 1.0
E = zeros(N, λ)
W = zeros(N, λ);
CMAES(N, μ, λ, τ, τ_c, τ_σ, population, offspring, F_µ, F_λ, C, s, s_σ, σ, E, W, x)
end
function step!(c::CMAES, obj::Function)
# L1
sqrt_c = cholesky((c.C + c.C') / 2.0).U
for i in 1:c.λ
c.E[:,i] = randn(c.N)
c.W[:,i] = c.σ * (sqrt_c * c.E[:,i])
c.offspring[i] = c.x + c.W[:,i]
c.F_λ[i] = obj(c.offspring[i])
end
# Select new parent population
idx = sortperm(c.F_λ)[1:c.μ]
for i in 1:c.μ
c.population[i] = c.offspring[idx[i]]
c.F_μ[i] = c.F_λ[idx[i]]
end
# L2
w = vec(mean(c.W[:,idx], dims=2))
c.x += w
# L3
c.s = (1.0 - 1.0/c.τ)*c.s + (sqrt(c.μ/c.τ * (2.0 - 1.0/c.τ))/c.σ)*w
# L4
c.C = (1.0 - 1.0/c.τ_c).*c.C + (c.s./c.τ_c)*c.s'
# L5
ɛ = vec(mean(c.E[:,idx], dims=2))
c.s_σ = (1.0 - 1.0/c.τ_σ)*c.s_σ + sqrt(c.μ/c.τ_σ*(2.0 - 1.0/c.τ_σ))*ɛ
# L6
c.σ = c.σ*exp(((c.s_σ'*c.s_σ)[1] - c.N)/(2*c.N*sqrt(c.N)))
c
end