Skip to content

Commit f218193

Browse files
authored
Update NOMAD interface to NOMAD 4.5.1 (#83)
1 parent 5f63d63 commit f218193

24 files changed

Lines changed: 742 additions & 154 deletions

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "NOMAD"
22
uuid = "02130f1c-4665-5b79-af82-ff1385104aa0"
33
authors = ["Alexis Montoison (@amontoison), Pierrick Pascal (@ppascal97), Ludovic Salomon (@salomonl)"]
4-
version = "2.4.2"
4+
version = "3.0.0"
55

66
[deps]
77
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
@@ -12,6 +12,6 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1212
Tulip = "6dd1b50a-3aae-11e9-10b5-ef983d2400fa"
1313

1414
[compat]
15-
NOMAD_jll = "= 4.3.1"
15+
NOMAD_jll = "= 4.5.1"
1616
Tulip = "0.9"
1717
julia = "1.10"

docs/Project.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
[deps]
22
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
34

45
[compat]
5-
Documenter = "0.27"
6-
julia = "1.6"
6+
Documenter = "1.0"
7+
julia = "1.10"
8+
Plots = "1.41.1"

docs/make.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ makedocs(
1010
pages = ["Home" => "index.md",
1111
"Parameters" => "nomadProblem.md",
1212
"Run Optimization" => "run_nomad.md",
13-
#"Results" => "nomadResults.md",
14-
#"Surrogates" => "surrogates.md",
1513
"Tutorial" => "tutorial.md"
1614
]
1715
)

docs/src/nomadParameters.md

Lines changed: 0 additions & 7 deletions
This file was deleted.

docs/src/nomadResults.md

Lines changed: 0 additions & 7 deletions
This file was deleted.

docs/src/surrogates.md

Lines changed: 0 additions & 31 deletions
This file was deleted.

docs/src/tutorial.md

Lines changed: 155 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ p.options.display_stats = ["BBE", "EVAL", "SOL", "OBJ", "CONS_H"] # some display
6969
7070
# Solution
7171
result = solve(p, [0.0;2.0])
72-
println("Solution: ", result.x_best_feas)
72+
println("Optimization status: ", result.status)
73+
println("Solution: ", result.x_sol)
74+
println("is feasible: ", result.feasible)
7375
```
7476

7577
## Linear equality constraints
@@ -131,9 +133,10 @@ x0 = [0.57186958424864897665429452899843;
131133
132134
# Solution
133135
result = solve(p, x0)
134-
println("Solution: ", result.x_best_feas)
135-
println("Satisfy Ax = b: ", A * result.x_best_feas ≈ b)
136-
println("And inside bound constraints: ", all(-10.0 .<= result.x_best_feas .<= 10.0))
136+
println("status: ", result.status)
137+
println("Solution: ", result.x_sol)
138+
println("Satisfy Ax = b: ", A * result.x_sol ≈ b)
139+
println("And inside bound constraints: ", all(-10.0 .<= result.x_sol .<= 10.0))
137140
```
138141

139142
The reader can take a look at the [`test`](https://github.com/bbopt/NOMAD.jl/tree/master/test) folder for more complex examples.
@@ -203,3 +206,151 @@ For more details about the parameters used in this section, we refer the reader
203206

204207
[C. Audet, A. Ianni, S. Le Digabel and C. Tribes, Reducing the number of function evaluations in mesh
205208
adaptive direct search algorithms, *SIAM Journal on Optimization*, 24(2), 621-642, 2014.](https://doi.org/10.1137/120895056)
209+
210+
## Multiobjective optimization
211+
212+
`NOMAD.jl` can solve multiobjective optimization problems of the form:
213+
```math
214+
\begin{array}{rl}
215+
(MBB) \ \ \
216+
\displaystyle \min_{x \in \mathbb{R}^n} & f(x) = \left(f_1(x), f_2(x), \ldots, f_m(x)\right)^\top\\
217+
s.t.
218+
& c(x) \leq 0 \\
219+
& lb \leq x \leq ub \\
220+
\end{array}
221+
```
222+
where $m \geq 2$ is the number of objectives.
223+
224+
Unlike single-objective optimization, the set of solutions to such a problem is generally not a singleton.
225+
It is composed of several solutions whose objective values represent the best trade-offs that the
226+
algorithm may achieve at the end of the optimization.
227+
228+
`NOMAD.jl` switches to multiobjective mode when a `NomadProblem` is given more than one objective `OBJ` as
229+
parameter. However, `NOMAD.jl` only supports up to `5` objectives. Keep in mind that the larger the number of
230+
objectives, the more difficult the problem is to solve.
231+
232+
Finally, the multiobjective mode of `NOMAD.jl` does not support certain options available in
233+
single-objective optimization. Specifically, in multiobjective optimization, `NOMAD.jl` deactivates
234+
all search strategies except the speculative search, the `NM` search and the `Quadratic model`
235+
search. The default `eval_sort_type` and `direction_type` options are switched to `"DIR_LAST_SUCCESS"`
236+
and `"ORTHO N+1 QUAD"`, respectively.
237+
238+
We consider the following example, the optimal design of a welded beam.
239+
240+
```math
241+
\begin{array}{rl}
242+
(WB) \ \ \
243+
\displaystyle \min_{x = (h, l, t, b) \in \mathbb{R}^4} & \left(1.10471 h^2 l + 0.04811 t b (14.0 + l), \dfrac{2.1952}{t^3 b}\right)^\top \\
244+
s.t.
245+
& c_1(x) = \tau(x) - 13600 \leq 0 \\
246+
& c_2(x) = \sigma(x) - 30000 \leq 0\\
247+
& c_3(x) = h - b \leq 0\\
248+
& c_4(x) = 6000 - P_c(x) \leq 0\\
249+
& h, b \in [0.125, 5], l, t \in [0.1, 10]\\
250+
\end{array}
251+
```
252+
where $h, l, t, b$ are the four design parameters to optimize.
253+
254+
The following equations describe the physics constraints of the system (stress and buckling terms):
255+
256+
```math
257+
\begin{array}{rl}
258+
\tau(x) & = \sqrt{(\tau')^2 + (\tau'')^2 + \dfrac{l \tau' \tau''}{\sqrt{0.25 (l^2 + (h + t)^2))}}}, \\
259+
\tau' & = \dfrac{6000}{\sqrt{2} h l}, \\
260+
\tau'' & = \dfrac{6000 (14 + 0.5 l) \sqrt{0.25 (l^2 + (h + t)^2))}}{2 \left(0.707 h l (l^2/12 + 0.25 (h + t)^2)\right)},\\
261+
\sigma(x) & = \dfrac{504000}{t^2 b},\\
262+
P_c(x) & = 64746.022 (1 - 0.0282346 t) t b^3.
263+
\end{array}
264+
```
265+
266+
$f_1$ corresponds to the construction costs and $f_2$ the end deflection (which corresponds to rigidity) of the beam. Both must be minimized.
267+
268+
```@example welded_beam_design
269+
using NOMAD
270+
271+
# blackbox
272+
function welded_beam(x)
273+
# Variables
274+
h = x[1]
275+
l = x[2]
276+
t = x[3]
277+
b = x[4]
278+
279+
# Objectives
280+
f1 = 1.10471 * h^2 * l + 0.04811 * t * b * (14.0 + l)
281+
f2 = 2.1952 / (t^3 * b)
282+
283+
# Physics equations
284+
tau_p = 6000.0 / (sqrt(2) * h * l)
285+
tau_pp = 6000 * (14 + 0.5 * l) * sqrt(0.25 * (l^2 + (h + t)^2))
286+
tau_pp /= (2 * (0.707 * h * l * (l^2 / 12.0 + 0.25 * (h + t)^2)))
287+
tau = sqrt(tau_p^2 + tau_pp^2 + l * tau_p * tau_pp / sqrt(0.25 * (l^2 + (h + t)^2)))
288+
sigma = 504000 / (t^2 * b)
289+
Pc = 64746.022 * (1 - 0.0282346 * t) * t * b^3
290+
291+
# Constraints
292+
c1 = tau - 13600
293+
c2 = sigma - 30000
294+
c3 = h - b
295+
c4 = 6000 - Pc
296+
297+
bb_outputs = [f1, f2, c1, c2, c3, c4]
298+
success = true
299+
count_eval = true
300+
return (success, count_eval, bb_outputs)
301+
end
302+
303+
# Define the problem
304+
lb = [0.125, 0.1, 0.1, 0.125]
305+
ub = [5.0, 10.0, 10.0, 5.0]
306+
pb = NomadProblem(4, 6, ["OBJ", "OBJ", "PB", "PB", "PB", "PB"],
307+
welded_beam,
308+
lower_bound=[0.125, 0.1, 0.1, 0.125],
309+
upper_bound=[5.0, 10.0, 10.0, 5.0])
310+
311+
# Set some options
312+
pb.options.display_degree = 2
313+
pb.options.max_bb_eval = 1500
314+
315+
# As for the single-objective case, you could deactivate this
316+
# option to go faster, but the performance may be worse
317+
# pb.options.quad_model_search = false
318+
319+
# Start from a middle box point
320+
result = solve(pb, (lb + ub) / 2)
321+
322+
# The solution set is returned as a matrix of dimensions n x nb_solutions,
323+
# where n is the dimension of the problem.
324+
println("Optimization status: ", result.status)
325+
println("The algorithm has found ", size(result.x_sol, 2), " solutions:")
326+
for (ind, (x, bbo)) in enumerate(zip(eachcol(result.x_sol), eachcol(result.bbo_sol)))
327+
println("Solution ", ind, ": ", x,
328+
"; f(x) = ", bbo[1:2],
329+
"; c(x) = ", bbo[3:end])
330+
end
331+
println("They are ", result.feasible ? "feasible" : "infeasible")
332+
333+
# In multiobjective optimization, it can be interesting to see the
334+
# set of trade-offs in the objective space
335+
using Plots
336+
fig = scatter(result.bbo_sol[1, :], result.bbo_sol[2, :],
337+
xlabel="Cost", ylabel="Deflection",
338+
title="Pareto front approximation")
339+
```
340+
341+
For more information about the multiobjective algorithm (DMulti-MADS), please refer to the following articles:
342+
343+
[J. Bigeon, S. Le Digabel, & L. Salomon, DMulti-MADS: Mesh adaptive direct multisearch for bound-constrained
344+
blackbox multiobjective optimization, *Computational Optimization and Applications*, 79(2), 301-338, 2021.](https://doi.org/10.1007/s10589-021-00272-9)
345+
346+
[J. Bigeon, S. Le Digabel, & L. Salomon, Handling of constraints in multiobjective blackbox optimization,
347+
*Computational Optimization and Applications*, 89(1), 69-113, 2024.](https://doi.org/10.1007/s10589-024-00588-2)
348+
349+
[S. Le Digabel, A. Lesage-Landry, L. Salomon, & C. Tribes (2025),
350+
Efficient search strategies for constrained multiobjective blackbox optimization,
351+
arXiv preprint arXiv:2504.02986., 2025.](https://doi.org/10.48550/arXiv.2504.02986)
352+
353+
The problem is taken from:
354+
355+
[K. Deb, Evolutionary algorithms for multi-criterion optimization in engineering design,
356+
*Evolutionary algorithms in engineering and computer science*, 2, 135-161, (1999)]()

0 commit comments

Comments
 (0)