diff --git a/lib/OptimizationLBFGSB/src/OptimizationLBFGSB.jl b/lib/OptimizationLBFGSB/src/OptimizationLBFGSB.jl index 8dd2164e5d..6c5b95c89b 100644 --- a/lib/OptimizationLBFGSB/src/OptimizationLBFGSB.jl +++ b/lib/OptimizationLBFGSB/src/OptimizationLBFGSB.jl @@ -90,8 +90,6 @@ end function SciMLBase.__solve(cache::OptimizationCache{O}) where {O <: LBFGSB} maxiters = OptimizationBase._check_and_convert_maxiters(cache.solver_args.maxiters) - local x - solver_kwargs = __map_optimizer_args(cache, cache.opt; maxiters, cache.solver_args...) if !isnothing(cache.f.cons) @@ -220,12 +218,12 @@ function SciMLBase.__solve(cache::OptimizationCache{O}) where {O <: LBFGSB} stats = stats, retcode = opt_ret ) else - iter_count = Ref(0) + ub_iter_count = Ref(0) encountered_inf_nan = Ref(false) - _loss = function (θ) + ub_loss = function (θ) x = cache.f(θ, cache.p) - iter_count[] += 1 + ub_iter_count[] += 1 # Track if we encounter Inf/NaN values in the objective if !isfinite(x[1]) encountered_inf_nan[] = true @@ -267,7 +265,7 @@ function SciMLBase.__solve(cache::OptimizationCache{O}) where {O <: LBFGSB} t0 = time() res = optimizer( - _loss, _grad!, cache.u0, bounds; m = cache.opt.m, solver_kwargs... + ub_loss, _grad!, cache.u0, bounds; m = cache.opt.m, solver_kwargs... ) # Extract the task message from the result diff --git a/lib/OptimizationLBFGSB/test/core_tests.jl b/lib/OptimizationLBFGSB/test/core_tests.jl index fc0f76bc83..f372fe5e3d 100644 --- a/lib/OptimizationLBFGSB/test/core_tests.jl +++ b/lib/OptimizationLBFGSB/test/core_tests.jl @@ -95,4 +95,15 @@ import SciMLBase @test res_safe.u[1] < 0.0 @test res_safe.u[1] > -0.5 end + + # Regression: unconstrained LBFGSB path must not box `x` / dual-branch + # `iter_count`/`_loss` into Core.Box (dynamic dispatch on every eval). + @testset "no Core.Box in unconstrained LBFGSB __solve" begin + optf_box = OptimizationFunction(rosenbrock, OptimizationBase.AutoForwardDiff()) + prob_box = OptimizationProblem(optf_box, zeros(2)) + cache_box = init(prob_box, OptimizationLBFGSB.LBFGSB()) + src = only(code_typed(SciMLBase.__solve, (typeof(cache_box),)))[1] + nboxes = count(t -> t === Core.Box, something(src.ssavaluetypes, [])) + @test nboxes == 0 + end end