Skip to content

Commit 6bb4e7b

Browse files
Merge pull request #817 from SciML/nomadcons
Add constraints support for NOMAD
2 parents 4c989c1 + d31fd15 commit 6bb4e7b

File tree

2 files changed

+49
-11
lines changed

2 files changed

+49
-11
lines changed

lib/OptimizationNOMAD/src/OptimizationNOMAD.jl

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ using NOMAD, Optimization.SciMLBase
77
export NOMADOpt
88
struct NOMADOpt end
99

10+
@enum ConstraintBarrierType ExtremeBarrierMethod ProgressiveBarrierMethod
11+
1012
SciMLBase.allowsbounds(::NOMADOpt) = true
1113
SciMLBase.allowscallback(::NOMADOpt) = false
14+
SciMLBase.allowsconstraints(::NOMADOpt) = true
1215

1316
function __map_optimizer_args!(prob::OptimizationProblem, opt::NOMAD.NomadProblem;
1417
callback = nothing,
@@ -40,12 +43,14 @@ function __map_optimizer_args!(prob::OptimizationProblem, opt::NOMAD.NomadProble
4043
return nothing
4144
end
4245

46+
@inline strcnsmethod(m::ConstraintBarrierType) = m === ExtremeBarrierMethod ? "EB" : "PB"
47+
4348
function SciMLBase.__solve(prob::OptimizationProblem, opt::NOMADOpt;
4449
maxiters::Union{Number, Nothing} = nothing,
4550
maxtime::Union{Number, Nothing} = nothing,
4651
abstol::Union{Number, Nothing} = nothing,
4752
reltol::Union{Number, Nothing} = nothing,
48-
progress = false,
53+
cons_method = ExtremeBarrierMethod,
4954
kwargs...)
5055
local x
5156

@@ -57,15 +62,27 @@ function SciMLBase.__solve(prob::OptimizationProblem, opt::NOMADOpt;
5762
return first(x)
5863
end
5964

60-
function bb(x)
61-
l = _loss(x)
62-
success = !isnan(l) && !isinf(l)
63-
count_eval = true
64-
return (success, count_eval, [l])
65-
end
66-
67-
if !isnothing(prob.lcons) | !isnothing(prob.ucons)
68-
@warn "Linear and nonlinear constraints defined in OptimizationProblem are currently not used by $(opt)"
65+
if prob.f.cons === nothing
66+
function bb(x)
67+
l = _loss(x)
68+
success = !isnan(l) && !isinf(l)
69+
count_eval = true
70+
return (success, count_eval, [l])
71+
end
72+
else
73+
eqinds = findall(i -> prob.lcons[i] == prob.ucons[i], 1:length(prob.ucons))
74+
function bbcons(x)
75+
l = _loss(x)
76+
c = zeros(eltype(x), length(prob.ucons))
77+
prob.f.cons(c, x, prob.p)
78+
c -= prob.ucons
79+
if !isempty(eqinds)
80+
c[eqinds] = abs.(c[eqinds])
81+
end
82+
success = !isnan(l) && !isinf(l)
83+
count_eval = true
84+
return (success, count_eval, vcat(l, c))
85+
end
6986
end
7087

7188
bounds = (;)
@@ -77,7 +94,13 @@ function SciMLBase.__solve(prob::OptimizationProblem, opt::NOMADOpt;
7794
bounds = (; bounds..., upper_bound = prob.ub)
7895
end
7996

80-
opt_setup = NOMAD.NomadProblem(length(prob.u0), 1, ["OBJ"], bb; bounds...)
97+
if prob.f.cons === nothing
98+
opt_setup = NOMAD.NomadProblem(length(prob.u0), 1, ["OBJ"], bb; bounds...)
99+
else
100+
opt_setup = NOMAD.NomadProblem(length(prob.u0), 1 + length(prob.ucons),
101+
vcat("OBJ", fill(strcnsmethod(cons_method), length(prob.ucons))),
102+
bbcons; bounds...)
103+
end
81104

82105
__map_optimizer_args!(prob, opt_setup, maxiters = maxiters, maxtime = maxtime,
83106
abstol = abstol, reltol = reltol; kwargs...)

lib/OptimizationNOMAD/test/runtests.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,19 @@ using Test
1616
prob = OptimizationProblem(f, x0, _p; lb = [-1.0, -1.0], ub = [1.5, 1.5])
1717
sol = Optimization.solve(prob, NOMADOpt())
1818
@test 10 * sol.objective < l1
19+
20+
cons = (res, x, p) -> (res[1] = x[1]^2 + x[2]^2; nothing)
21+
f = OptimizationFunction(rosenbrock, cons = cons)
22+
prob = OptimizationProblem(f, x0, _p; lcons = [-Inf], ucons = [1.0])
23+
sol = Optimization.solve(prob, NOMADOpt(), maxiters = 5000)
24+
@test 10 * sol.objective < l1
25+
26+
function con2_c(res, x, p)
27+
res .= [x[1]^2 + x[2]^2, x[2] * sin(x[1]) - x[1]]
28+
end
29+
30+
f = OptimizationFunction(rosenbrock, cons = con2_c)
31+
prob = OptimizationProblem(f, x0, _p; lcons = [-Inf, -Inf], ucons = [0.5, 0.0])
32+
sol = Optimization.solve(prob, NOMADOpt(), maxiters = 5000)
33+
@test sol.objective < l1
1934
end

0 commit comments

Comments
 (0)