diff --git a/lib/OptimizationNLopt/src/OptimizationNLopt.jl b/lib/OptimizationNLopt/src/OptimizationNLopt.jl index a21cf262a..956903b19 100644 --- a/lib/OptimizationNLopt/src/OptimizationNLopt.jl +++ b/lib/OptimizationNLopt/src/OptimizationNLopt.jl @@ -75,7 +75,7 @@ function __map_optimizer_args!(cache::OptimizationCache, opt::NLopt.Opt; if !isnothing(local_options) for j in Dict(pairs(local_options)) - eval(Meta.parse("NLopt." * string(j.first) * "!"))(local_meth, j.second) + NLopt.nlopt_set_param(opt, j.first, j.second) end end @@ -93,7 +93,7 @@ function __map_optimizer_args!(cache::OptimizationCache, opt::NLopt.Opt; # add optimiser options from kwargs for j in kwargs if j.first != :cons_tol - eval(Meta.parse("NLopt." * string(j.first) * "!"))(opt, j.second) + NLopt.nlopt_set_param(opt, j.first, j.second) end end diff --git a/lib/OptimizationNLopt/test/runtests.jl b/lib/OptimizationNLopt/test/runtests.jl index 14c6a568e..de18f42fb 100644 --- a/lib/OptimizationNLopt/test/runtests.jl +++ b/lib/OptimizationNLopt/test/runtests.jl @@ -100,6 +100,29 @@ using Test, Random @test sol.retcode == ReturnCode.MaxTime end + @testset "dual_ftol_rel parameter" begin + # Test that dual_ftol_rel parameter can be passed to NLopt without errors + # This parameter is specific to MMA/CCSA algorithms for dual optimization tolerance + x0_test = zeros(2) + optprob = OptimizationFunction(rosenbrock, Optimization.AutoZygote()) + prob = OptimizationProblem(optprob, x0_test, _p) + + # Test with NLopt.Opt interface + opt = NLopt.Opt(:LD_MMA, 2) + # This should not throw an error - the PR fixed the UndefVarError + sol = solve(prob, opt, dual_ftol_rel = 1e-6, maxiters = 100) + @test sol.retcode ∈ [ReturnCode.Success, ReturnCode.MaxIters] + + # Test with direct algorithm interface + sol = solve(prob, NLopt.LD_MMA(), dual_ftol_rel = 1e-5, maxiters = 100) + @test sol.retcode ∈ [ReturnCode.Success, ReturnCode.MaxIters] + + # Verify it works with other solver options + sol = solve(prob, NLopt.LD_MMA(), dual_ftol_rel = 1e-4, ftol_rel = 1e-6, + xtol_rel = 1e-6, maxiters = 100) + @test sol.retcode ∈ [ReturnCode.Success, ReturnCode.MaxIters] + end + @testset "constrained" begin Random.seed!(1) cons = (res, x, p) -> res .= [x[1]^2 + x[2]^2 - 1.0]