@@ -68,26 +68,38 @@ Random.seed!(1234)
6868 @test haskey (sol. original. trace[end ]. metadata, " TESTVAL" ) &&
6969 haskey (sol. original. trace[end ]. metadata, " curr_u" )
7070
71- # Test Suite for Different Multi-Objective Functions
72- function test_multi_objective (func, initial_guess)
73- # Define the gradient function using ForwardDiff
74- function gradient_multi_objective (x, p = nothing )
75- ForwardDiff. jacobian (func, x)
76- end
77-
78- # Create an instance of MultiObjectiveOptimizationFunction
79- obj_func = MultiObjectiveOptimizationFunction (func, jac = gradient_multi_objective)
80-
81- # Set up the evolutionary algorithm (e.g., NSGA2)
71+ # NSGA2 returns stochastic Pareto candidates; assert wrapper invariants instead of
72+ # exact population indices, which can change across Evolutionary releases.
73+ function test_multi_objective (func, initial_guess; seed, lb = nothing , ub = nothing )
74+ Random. seed! (seed)
75+ obj_func = MultiObjectiveOptimizationFunction (func)
8276 algorithm = OptimizationEvolutionary. NSGA2 ()
77+ problem = if lb === nothing && ub === nothing
78+ OptimizationProblem (obj_func, initial_guess)
79+ else
80+ OptimizationProblem (obj_func, initial_guess; lb = lb, ub = ub)
81+ end
82+ return solve (problem, algorithm)
83+ end
8384
84- # Define the optimization problem
85- problem = OptimizationProblem (obj_func, initial_guess)
86-
87- # Solve the optimization problem
88- result = solve (problem, algorithm)
89-
90- return result
85+ function check_multi_objective_result (
86+ result, func, initial_guess; lb = nothing , ub = nothing , min_population = 1
87+ )
88+ @test result != = nothing
89+ @test result. u isa AbstractVector
90+ @test ! isempty (result. u)
91+ @test length (result. u) >= min_population
92+ @test length (unique (result. u)) >= min_population
93+ @test all (u -> u isa AbstractVector && length (u) == length (initial_guess), result. u)
94+
95+ objective_values = [func (u, nothing ) for u in result. u]
96+ @test result. objective == objective_values[1 ]
97+ @test all (obj -> length (obj) == length (result. objective), objective_values)
98+ @test all (obj -> all (isfinite, obj), objective_values)
99+
100+ if lb != = nothing && ub != = nothing
101+ @test all (u -> all ((lb .<= u) .& (u .<= ub)), result. u)
102+ end
91103 end
92104
93105 @testset " Multi-Objective Optimization Tests" begin
@@ -99,13 +111,8 @@ Random.seed!(1234)
99111 f2 = sum (x .^ 2 .- 10 .* cos .(2 π .* x) .+ 10 ) # Rastrigin function
100112 return [f1, f2]
101113 end
102- result = test_multi_objective (multi_objective_1, [0.0 , 1.0 ])
103- @test result ≠ nothing
104- println (" Solution for Sphere and Rastrigin: " , result)
105- @test result. u[1 ][1 ] ≈ 7.88866e-5 atol = 1.0e-3
106- @test result. u[1 ][2 ] ≈ 4.96471e-5 atol = 1.0e-3
107- @test result. objective[1 ] ≈ 8.6879e-9 atol = 1.0e-3
108- @test result. objective[2 ] ≈ 1.48875349381683e-6 atol = 1.0e-3
114+ result = test_multi_objective (multi_objective_1, [0.0 , 1.0 ]; seed = 1101 )
115+ check_multi_objective_result (result, multi_objective_1, [0.0 , 1.0 ])
109116 end
110117
111118 # Test 2: Rosenbrock and Ackley Functions
@@ -116,31 +123,30 @@ Random.seed!(1234)
116123 exp (0.5 * (cos (2 π * x[1 ]) + cos (2 π * x[2 ]))) + exp (1 ) + 20.0 # Ackley function
117124 return [f1, f2]
118125 end
119- result = test_multi_objective (multi_objective_2, [0.1 , 1.0 ])
120- @test result ≠ nothing
121- println (" Solution for Rosenbrock and Ackley: " , result)
122- @test result. u[1 ][1 ] ≈ 0.003993274873103834 atol = 1.0e-3
123- @test result. u[1 ][2 ] ≈ 0.001433311246712721 atol = 1.0e-3
124- @test result. objective[1 ] ≈ 0.9922302888530358 atol = 1.0e-3
125- @test result. objective[2 ] ≈ 0.012479470703588902 atol = 1.0e-3
126+ result = test_multi_objective (multi_objective_2, [0.1 , 1.0 ]; seed = 1102 )
127+ check_multi_objective_result (
128+ result, multi_objective_2, [0.1 , 1.0 ]; min_population = 2
129+ )
126130 end
127131
128132 # Test 3: ZDT1 Function
129133 @testset " ZDT1 Function" begin
130134 function multi_objective_3 (x, p = nothing ):: Vector{Float64}
131135 f1 = x[1 ]
132136 g = 1 + 9 * sum (x[2 : end ]) / (length (x) - 1 )
133- sqrt_arg = f1 / g
134- f2 = g * (1 - (sqrt_arg >= 0 ? sqrt (sqrt_arg) : NaN ))
137+ f2 = g * (1 - sqrt (f1 / g))
135138 return [f1, f2]
136139 end
137- result = test_multi_objective (multi_objective_3, [0.25 , 1.5 ])
138- @test result ≠ nothing
139- println (" Solution for ZDT1: " , result)
140- @test result. u[1 ][1 ] ≈ - 0.365434 atol = 1.0e-3
141- @test result. u[1 ][2 ] ≈ 1.22128 atol = 1.0e-3
142- @test result. objective[1 ] ≈ - 0.365434 atol = 1.0e-3
143- @test isnan (result. objective[2 ])
140+ lb = zeros (2 )
141+ ub = ones (2 )
142+ initial_guess = [0.25 , 0.75 ]
143+ result = test_multi_objective (
144+ multi_objective_3, initial_guess; seed = 1103 , lb = lb, ub = ub
145+ )
146+ check_multi_objective_result (
147+ result, multi_objective_3, initial_guess; lb = lb, ub = ub,
148+ min_population = 2
149+ )
144150 end
145151
146152 # Test 4: DTLZ2 Function
@@ -150,13 +156,16 @@ Random.seed!(1234)
150156 f2 = (1 + sum (x[2 : end ] .^ 2 )) * sin (x[1 ] * π / 2 )
151157 return [f1, f2]
152158 end
153- result = test_multi_objective (multi_objective_4, [0.25 , 0.75 ])
154- @test result ≠ nothing
155- println (" Solution for DTLZ2: " , result)
156- @test result. u[1 ][1 ] ≈ 0.899183 atol = 1.0e-3
157- @test result. u[2 ][1 ] ≈ 0.713992 atol = 1.0e-3
158- @test result. objective[1 ] ≈ 0.1599915 atol = 1.0e-3
159- @test result. objective[2 ] ≈ 1.001824893932647 atol = 1.0e-3
159+ lb = zeros (2 )
160+ ub = ones (2 )
161+ initial_guess = [0.25 , 0.75 ]
162+ result = test_multi_objective (
163+ multi_objective_4, initial_guess; seed = 1104 , lb = lb, ub = ub
164+ )
165+ check_multi_objective_result (
166+ result, multi_objective_4, initial_guess; lb = lb, ub = ub,
167+ min_population = 2
168+ )
160169 end
161170
162171 # Test 5: Schaffer Function N.2
@@ -166,13 +175,16 @@ Random.seed!(1234)
166175 f2 = (x[1 ] - 2 )^ 2
167176 return [f1, f2]
168177 end
169- result = test_multi_objective (multi_objective_5, [1.0 ])
170- @test result ≠ nothing
171- println (" Solution for Schaffer N.2: " , result)
172- @test result. u[19 ][1 ] ≈ 0.252635 atol = 1.0e-3
173- @test result. u[9 ][1 ] ≈ 1.0 atol = 1.0e-3
174- @test result. objective[1 ] ≈ 1.0 atol = 1.0e-3
175- @test result. objective[2 ] ≈ 1.0 atol = 1.0e-3
178+ lb = [0.0 ]
179+ ub = [2.0 ]
180+ initial_guess = [1.0 ]
181+ result = test_multi_objective (
182+ multi_objective_5, initial_guess; seed = 1105 , lb = lb, ub = ub
183+ )
184+ check_multi_objective_result (
185+ result, multi_objective_5, initial_guess; lb = lb, ub = ub,
186+ min_population = 2
187+ )
176188 end
177189 end
178190end
0 commit comments