Skip to content

Commit b7090c9

Browse files
Merge pull request #176 from jonasmac16/NOMAD
New basic interface to NOMAD.jl
2 parents 6c70b86 + 5c4f613 commit b7090c9

File tree

6 files changed

+129
-1
lines changed

6 files changed

+129
-1
lines changed

docs/make.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ makedocs(
3535
"MathOptInterface.jl" => "optimization_packages/mathoptinterface.md",
3636
"MultistartOptimization.jl" => "optimization_packages/multistartoptimization.md",
3737
"Metaheuristics.jl" => "optimization_packages/metaheuristics.md",
38+
"NOMAD.jl" => "optimization_packages/nomad.md",
3839
"NLopt.jl" => "optimization_packages/nlopt.md",
3940
"Nonconvex.jl" => "optimization_packages/nonconvex.md",
4041
"Optim.jl" => "optimization_packages/optim.md",
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# NOMAD.jl
2+
[`NOMAD`](https://github.com/bbopt/NOMAD.jl) is Julia package interfacing to NOMAD,which is a C++ implementation of the Mesh Adaptive Direct Search algorithm (MADS), designed for difficult blackbox optimization problems. These problems occur when the functions defining the objective and constraints are the result of costly computer simulations. [`NOMAD.jl documentation`](https://bbopt.github.io/NOMAD.jl/stable/)
3+
4+
The NOMAD algorithm is called by `NOMADOpt()`
5+
6+
## Global Optimizer
7+
### Without Constraint Equations
8+
9+
The method in [`NOMAD`](https://github.com/bbopt/NOMAD.jl) is performing global optimization on problems both with and without
10+
constraint equations. Currently however, linear and nonlinear constraints defined in `GalacticOPtim` are not passed.
11+
12+
NOMAD works both with and without lower and upper boxconstraints set by `lb` and `ub` in the `OptimizationProblem`.
13+
14+
15+
The Rosenbrock function can optimized using the `NOMADOpt()` with and without boxcontraints as follows:
16+
17+
```julia
18+
rosenbrock(x, p) = (p[1] - x[1])^2 + p[2] * (x[2] - x[1]^2)^2
19+
x0 = zeros(2)
20+
p = [1.0, 100.0]
21+
f = OptimizationFunction(rosenbrock)
22+
23+
prob = OptimizationProblem(f, x0, _p)
24+
sol = GalacticOptim.solve(prob,NOMADOpt())
25+
26+
prob = OptimizationProblem(f, x0, _p, lb = [-1.0,-1.0], ub = [1.5,1.5])
27+
sol = GalacticOptim.solve(prob,NOMADOpt())
28+
```

src/GalacticOptim.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ function __init__()
4444
end
4545
end
4646
@require Metaheuristics="bcdb8e00-2c21-11e9-3065-2b553b22f898" include("solve/metaheuristics.jl")
47+
@require NOMAD="02130f1c-4665-5b79-af82-ff1385104aa0" include("solve/nomad.jl")
4748
@require SpeedMapping="f1835b91-879b-4a3f-a438-e4baacf14412" include("solve/speedmapping.jl")
4849

4950
# AD backends

src/solve/nomad.jl

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
export NOMADOpt
2+
struct NOMADOpt end
3+
4+
5+
function __map_optimizer_args(prob::OptimizationProblem, opt::NOMAD.NomadProblem;
6+
cb=nothing,
7+
maxiters::Union{Number, Nothing}=nothing,
8+
maxtime::Union{Number, Nothing}=nothing,
9+
abstol::Union{Number, Nothing}=nothing,
10+
reltol::Union{Number, Nothing}=nothing,
11+
kwargs...)
12+
13+
for j in kwargs
14+
setproperty!(opt.options, j.first, j.second)
15+
end
16+
17+
if !isnothing(maxiters)
18+
opt.options.max_bb_eval=maxiters
19+
end
20+
21+
if !isnothing(maxtime)
22+
opt.options.max_time=maxtime
23+
end
24+
25+
if !isnothing(reltol)
26+
@warn "common reltol is currently not used by $(opt)"
27+
end
28+
29+
if !isnothing(abstol)
30+
@warn "common abstol is currently not used by $(opt)"
31+
end
32+
33+
return nothing
34+
end
35+
36+
function __solve(prob::OptimizationProblem, opt::NOMADOpt;
37+
maxiters::Union{Number, Nothing} = nothing,
38+
maxtime::Union{Number, Nothing} = nothing,
39+
abstol::Union{Number, Nothing}=nothing,
40+
reltol::Union{Number, Nothing}=nothing,
41+
progress = false,
42+
kwargs...)
43+
44+
local x
45+
46+
maxiters = _check_and_convert_maxiters(maxiters)
47+
maxtime = _check_and_convert_maxtime(maxtime)
48+
49+
50+
_loss = function(θ)
51+
x = prob.f(θ, prob.p)
52+
return first(x)
53+
end
54+
55+
function bb(x)
56+
bb_outputs = [_loss(x)]
57+
success = true
58+
count_eval = true
59+
return (success, count_eval, bb_outputs)
60+
end
61+
62+
if !isnothing(prob.lcons) | !isnothing(prob.ucons)
63+
@warn "Linear and nonlinear constraints defined in OptimizationProblem are currently not used by $(opt)"
64+
end
65+
66+
bounds=(;)
67+
if !isnothing(prob.lb)
68+
bounds = (; bounds..., lower_bound=prob.lb)
69+
end
70+
71+
if !isnothing(prob.ub)
72+
bounds = (; bounds..., upper_bound=prob.ub)
73+
end
74+
75+
opt_setup = NOMAD.NomadProblem(length(prob.u0), 1, ["OBJ"], bb; bounds...)
76+
77+
_map_optimizer_args(prob, opt_setup, maxiters=maxiters, maxtime=maxtime,abstol=abstol, reltol=reltol; kwargs...)
78+
79+
t0 = time()
80+
opt_res = NOMAD.solve(opt_setup, prob.u0)
81+
t1 = time()
82+
83+
SciMLBase.build_solution(prob, opt, opt_res.x_best_feas, first(opt_res.bbo_best_feas); original=opt_res)
84+
end

test/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Metaheuristics = "bcdb8e00-2c21-11e9-3065-2b553b22f898"
1515
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
1616
MultistartOptimization = "3933049c-43be-478e-a8bb-6e0f7fd53575"
1717
NLopt = "76087f3c-5699-56af-9a33-bf431cd00edd"
18+
NOMAD = "02130f1c-4665-5b79-af82-ff1385104aa0"
1819
Nonconvex = "01bcebdf-4d21-426d-b5c4-6132c1619978"
1920
NonconvexBayesian = "fb352abc-de7b-48de-9ebd-665b54b5d9b3"
2021
NonconvexIpopt = "bf347577-a06d-49ad-a669-8c0e005493b8"
@@ -52,6 +53,7 @@ Metaheuristics = ">=3.0.2"
5253
ModelingToolkit = ">= 6.4.7"
5354
MultistartOptimization = ">= 0.1.2"
5455
NLopt = ">= 0.6"
56+
NOMAD = ">= 2.1"
5557
Nonconvex = ">= 1.0"
5658
NonconvexBayesian = ">= 0.1"
5759
NonconvexIpopt = ">= 0.1"

test/rosenbrock.jl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ end
173173
# sol = solve(prob, QuadDirect(); splits = ([-0.5, 0.0, 0.5],[-0.5, 0.0, 0.5]))
174174
# @test 10*sol.minimum < l1
175175

176-
@testset "Evolutionary, BlackBoxOptim, Metaheuristics, Nonconvex, GCMAES, SpeedMapping" begin
176+
177+
@testset "Evolutionary, BlackBoxOptim, Metaheuristics, Nonconvex, GCMAES, SpeedMapping, NOMAD" begin
177178
optprob = OptimizationFunction(rosenbrock, GalacticOptim.AutoZygote())
178179
using Evolutionary
179180
prob = GalacticOptim.OptimizationProblem(optprob, x0, _p)
@@ -426,6 +427,17 @@ end
426427

427428
sol = solve(prob, BayesOptAlg(NLoptAlg(:LN_NELDERMEAD)), sub_options=(;maxeval=100))
428429
@test 10*sol.minimum < l1
430+
431+
using NOMAD
432+
f = OptimizationFunction(rosenbrock)
433+
434+
prob = OptimizationProblem(f, x0, _p)
435+
sol = GalacticOptim.solve(prob,NOMADOpt())
436+
@test 10*sol.minimum < l1
437+
438+
prob = OptimizationProblem(f, x0, _p; lb = [-1.0,-1.0], ub = [1.5,1.5])
439+
sol = GalacticOptim.solve(prob,NOMADOpt())
440+
@test 10*sol.minimum < l1
429441

430442
using GCMAES
431443
f_ad = OptimizationFunction(rosenbrock, GalacticOptim.AutoForwardDiff())

0 commit comments

Comments
 (0)