-
Notifications
You must be signed in to change notification settings - Fork 0
/
solver_cbo.jl
79 lines (69 loc) · 2.3 KB
/
solver_cbo.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
69
70
71
72
73
74
75
76
77
78
79
module Cbo
import Random
include("lib_inverse_problem.jl")
export Config, step
struct Config
β::Float64
λ::Float64
σ::Float64
Δ::Float64
ν::Float64
ε::Float64
end
function step(problem, config, ensembles;
eq_constraint=nothing, ineq_constraint=nothing,
grad_eq_constraint=nothing, grad_ineq_constraint=nothing,
verbose=false)
if occursin("InverseProblem", string(typeof(problem)))
objective(u) = Ip.reg_least_squares(problem, u)
else
objective = problem
end
ν = config.ν
ε = config.ε
function extra_objective(x)
result = 0
if ! (eq_constraint == nothing)
result += (1/ν) * eq_constraint(x)^2
elseif ! (ineq_constraint == nothing)
val = ineq_constraint(x)
result += (val > 0) ? 0 : (1/ν) * val^2
end
return result
end
λ = config.λ
σ = config.σ
Δ = config.Δ
d, J = size(ensembles)
fensembles = zeros(J)
for i in 1:length(fensembles)
fensembles[i] = objective(ensembles[:, i])
fensembles[i] += extra_objective(ensembles[:, i])
verbose && print(".")
end
verbose && println("")
fensembles = fensembles .- minimum(fensembles)
weights = exp.(- config.β*fensembles)
weights = weights / sum(weights)
mean = sum(ensembles.*weights', dims=2)
diff = ensembles .- mean
new_ensembles = ensembles .- λ*Δ*diff .+ σ*sqrt(2Δ)*(diff .* Random.randn(d, J))
if ! (grad_eq_constraint == nothing)
for i in 1:length(fensembles)
# SPECIAL CASE !!!
new_ensembles[:, i] = new_ensembles[:, i] / (1 + 4*(Δ/ε)*eq_constraint(ensembles[:, i]))
# new_ensembles[:, i] -= (2/ε)*Δ * eq_constraint(ensembles[:, i]) * grad_eq_constraint(ensembles[:, i])
end
end
if ! (grad_ineq_constraint == nothing)
for i in 1:length(fensembles)
# SPECIAL CASE !!!
# if ineq_constraint(ensembles[:, i]) < 0
# new_ensembles[:, i] = new_ensembles[:, i] / (1 + 4*(Δ/ε)*ineq_constraint(ensembles[:, i]))
# end
# new_ensembles[:, i] -= (2/ε)*Δ * eq_constraint(ensembles[:, i]) * grad_eq_constraint(ensembles[:, i])
end
end
return new_ensembles
end
end