Skip to content

Commit 97a8e22

Browse files
Merge branch 'master' into multistartoptimization
2 parents 953b9b2 + b7090c9 commit 97a8e22

File tree

6 files changed

+128
-1
lines changed

6 files changed

+128
-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
@@ -46,6 +46,7 @@ function __init__()
4646
end
4747
end
4848
@require Metaheuristics="bcdb8e00-2c21-11e9-3065-2b553b22f898" include("solve/metaheuristics.jl")
49+
@require NOMAD="02130f1c-4665-5b79-af82-ff1385104aa0" include("solve/nomad.jl")
4950
@require SpeedMapping="f1835b91-879b-4a3f-a438-e4baacf14412" include("solve/speedmapping.jl")
5051

5152
# 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: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ end
169169
# sol = solve(prob, QuadDirect(); splits = ([-0.5, 0.0, 0.5],[-0.5, 0.0, 0.5]))
170170
# @test 10*sol.minimum < l1
171171

172-
@testset "Evolutionary, BlackBoxOptim, Metaheuristics, Nonconvex, GCMAES, SpeedMapping, MultistartOptimization" begin
172+
@testset "Evolutionary, BlackBoxOptim, Metaheuristics, Nonconvex, GCMAES, SpeedMapping, MultistartOptimization, NOMAD" begin
173173
optprob = OptimizationFunction(rosenbrock, GalacticOptim.AutoZygote())
174174
using Evolutionary
175175
prob = GalacticOptim.OptimizationProblem(optprob, x0, _p)
@@ -423,6 +423,17 @@ end
423423
sol = solve(prob, BayesOptAlg(NLoptAlg(:LN_NELDERMEAD)), sub_options=(;maxeval=100))
424424
@test 10*sol.minimum < l1
425425

426+
using NOMAD
427+
f = OptimizationFunction(rosenbrock)
428+
429+
prob = OptimizationProblem(f, x0, _p)
430+
sol = GalacticOptim.solve(prob,NOMADOpt())
431+
@test 10*sol.minimum < l1
432+
433+
prob = OptimizationProblem(f, x0, _p; lb = [-1.0,-1.0], ub = [1.5,1.5])
434+
sol = GalacticOptim.solve(prob,NOMADOpt())
435+
@test 10*sol.minimum < l1
436+
426437
using GCMAES
427438
f_ad = OptimizationFunction(rosenbrock, GalacticOptim.AutoForwardDiff())
428439
f_noad = OptimizationFunction(rosenbrock)

0 commit comments

Comments
 (0)