From 5e23fc51117b5158f250bbe9301b3736fb710307 Mon Sep 17 00:00:00 2001 From: Zentrik Date: Sat, 30 Sep 2023 23:48:56 +0100 Subject: [PATCH 1/8] Fix so #519 works again and remove call to fieldnames --- lib/OptimizationBBO/src/OptimizationBBO.jl | 8 ++++---- src/cache.jl | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/OptimizationBBO/src/OptimizationBBO.jl b/lib/OptimizationBBO/src/OptimizationBBO.jl index 8d3a4773d..fdda1ae6d 100644 --- a/lib/OptimizationBBO/src/OptimizationBBO.jl +++ b/lib/OptimizationBBO/src/OptimizationBBO.jl @@ -125,7 +125,7 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ BlackBoxOptim.shutdown_optimizer!(trace) #doesn't work end - if !isnothing(cache.data) + if cache.data != Optimization.DEFAULT_DATA cur, state = iterate(cache.data, state) end cb_call @@ -135,11 +135,11 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ maxtime = Optimization._check_and_convert_maxtime(cache.solver_args.maxtime) _loss = function (θ) - if isnothing(cache.callback) && isnothing(cache.data) + if isnothing(cache.callback) && cache.data == Optimization.DEFAULT_DATA return first(cache.f(θ, cache.p)) elseif isnothing(cache.callback) return first(cache.f(θ, cache.p, cur...)) - elseif isnothing(cache.data) + elseif cache.data != Optimization.DEFAULT_DATA x = cache.f(θ, cache.p) return first(x) else @@ -150,7 +150,7 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ opt_args = __map_optimizer_args(cache, cache.opt; callback = isnothing(cache.callback) && - isnothing(cache.data) ? + cache.data == Optimization.DEFAULT_DATA ? nothing : _cb, cache.solver_args..., maxiters = maxiters, diff --git a/src/cache.jl b/src/cache.jl index 08d4cb910..f08cabf95 100644 --- a/src/cache.jl +++ b/src/cache.jl @@ -1,6 +1,6 @@ function Base.getproperty(cache::SciMLBase.AbstractOptimizationCache, x::Symbol) - if x in fieldnames(Optimization.ReInitCache) + if x in (:u0, :p) return getfield(cache.reinit_cache, x) end return getfield(cache, x) @@ -52,7 +52,7 @@ struct OptimizationCache{F, RC, LB, UB, LC, UC, S, O, D, P, C} <: end function OptimizationCache(prob::SciMLBase.OptimizationProblem, opt, data; - callback = (args...) -> (false), + callback = nothing, maxiters::Union{Number, Nothing} = nothing, maxtime::Union{Number, Nothing} = nothing, abstol::Union{Number, Nothing} = nothing, @@ -71,7 +71,7 @@ end function SciMLBase.__init(prob::SciMLBase.OptimizationProblem, opt, data = Optimization.DEFAULT_DATA; - callback = (args...) -> (false), + callback = nothing, maxiters::Union{Number, Nothing} = nothing, maxtime::Union{Number, Nothing} = nothing, abstol::Union{Number, Nothing} = nothing, From 14b3b358fcce02551311fa2fa2ff0f30d4b3545c Mon Sep 17 00:00:00 2001 From: Zentrik Date: Sun, 1 Oct 2023 00:00:13 +0100 Subject: [PATCH 2/8] Define default callback instead of using nothing This is so nothing breaks, if callback is called if its nothing --- lib/OptimizationBBO/src/OptimizationBBO.jl | 8 ++++---- lib/OptimizationOptimisers/src/sophia.jl | 6 +++--- src/cache.jl | 4 ++-- src/utils.jl | 2 ++ 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/OptimizationBBO/src/OptimizationBBO.jl b/lib/OptimizationBBO/src/OptimizationBBO.jl index fdda1ae6d..6f2da1593 100644 --- a/lib/OptimizationBBO/src/OptimizationBBO.jl +++ b/lib/OptimizationBBO/src/OptimizationBBO.jl @@ -112,7 +112,7 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ cur, state = iterate(cache.data) function _cb(trace) - if isnothing(cache.callback) + if cache.callback == DEFAULT_CALLBACK cb_call = false else cb_call = cache.callback(decompose_trace(trace, cache.progress), x...) @@ -135,9 +135,9 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ maxtime = Optimization._check_and_convert_maxtime(cache.solver_args.maxtime) _loss = function (θ) - if isnothing(cache.callback) && cache.data == Optimization.DEFAULT_DATA + if cache.callback == DEFAULT_CALLBACK && cache.data == Optimization.DEFAULT_DATA return first(cache.f(θ, cache.p)) - elseif isnothing(cache.callback) + elseif cache.callback == DEFAULT_CALLBACK return first(cache.f(θ, cache.p, cur...)) elseif cache.data != Optimization.DEFAULT_DATA x = cache.f(θ, cache.p) @@ -149,7 +149,7 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ end opt_args = __map_optimizer_args(cache, cache.opt; - callback = isnothing(cache.callback) && + callback = cache.callback == DEFAULT_CALLBACK && cache.data == Optimization.DEFAULT_DATA ? nothing : _cb, cache.solver_args..., diff --git a/lib/OptimizationOptimisers/src/sophia.jl b/lib/OptimizationOptimisers/src/sophia.jl index ff396ab89..b24eaa2ae 100644 --- a/lib/OptimizationOptimisers/src/sophia.jl +++ b/lib/OptimizationOptimisers/src/sophia.jl @@ -71,11 +71,11 @@ function SciMLBase.__solve(cache::OptimizationCache{ maxiters = Optimization._check_and_convert_maxiters(maxiters) _loss = function (θ) - if isnothing(cache.callback) && isnothing(data) + if cache.callback == DEFAULT_CALLBACK && data == Optimization.DEFAULT_DATA return first(cache.f(θ, cache.p)) - elseif isnothing(cache.callback) + elseif cache.callback == DEFAULT_CALLBACK return first(cache.f(θ, cache.p, cur...)) - elseif isnothing(data) + elseif data == Optimization.DEFAULT_DATA x = cache.f(θ, cache.p) return first(x) else diff --git a/src/cache.jl b/src/cache.jl index f08cabf95..7fd4e0f1b 100644 --- a/src/cache.jl +++ b/src/cache.jl @@ -52,7 +52,7 @@ struct OptimizationCache{F, RC, LB, UB, LC, UC, S, O, D, P, C} <: end function OptimizationCache(prob::SciMLBase.OptimizationProblem, opt, data; - callback = nothing, + callback = Optimization.DEFAULT_CALLBACK, maxiters::Union{Number, Nothing} = nothing, maxtime::Union{Number, Nothing} = nothing, abstol::Union{Number, Nothing} = nothing, @@ -71,7 +71,7 @@ end function SciMLBase.__init(prob::SciMLBase.OptimizationProblem, opt, data = Optimization.DEFAULT_DATA; - callback = nothing, + callback = Optimization.DEFAULT_CALLBACK, maxiters::Union{Number, Nothing} = nothing, maxtime::Union{Number, Nothing} = nothing, abstol::Union{Number, Nothing} = nothing, diff --git a/src/utils.jl b/src/utils.jl index 686295b70..baf955f18 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,3 +1,5 @@ +const DEFAULT_CALLBACK = (args...) -> false + struct NullData end const DEFAULT_DATA = Iterators.cycle((NullData(),)) Base.iterate(::NullData, i = 1) = nothing From ca333bcd5044b8fc334be83c689b9b3ce4c6ade0 Mon Sep 17 00:00:00 2001 From: Zentrik Date: Sun, 1 Oct 2023 00:01:20 +0100 Subject: [PATCH 3/8] Fix namespace issue --- lib/OptimizationBBO/src/OptimizationBBO.jl | 8 ++++---- lib/OptimizationOptimisers/src/sophia.jl | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/OptimizationBBO/src/OptimizationBBO.jl b/lib/OptimizationBBO/src/OptimizationBBO.jl index 6f2da1593..ff1929931 100644 --- a/lib/OptimizationBBO/src/OptimizationBBO.jl +++ b/lib/OptimizationBBO/src/OptimizationBBO.jl @@ -112,7 +112,7 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ cur, state = iterate(cache.data) function _cb(trace) - if cache.callback == DEFAULT_CALLBACK + if cache.callback == Optimization.DEFAULT_CALLBACK cb_call = false else cb_call = cache.callback(decompose_trace(trace, cache.progress), x...) @@ -135,9 +135,9 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ maxtime = Optimization._check_and_convert_maxtime(cache.solver_args.maxtime) _loss = function (θ) - if cache.callback == DEFAULT_CALLBACK && cache.data == Optimization.DEFAULT_DATA + if cache.callback == Optimization.DEFAULT_CALLBACK && cache.data == Optimization.DEFAULT_DATA return first(cache.f(θ, cache.p)) - elseif cache.callback == DEFAULT_CALLBACK + elseif cache.callback == Optimization.DEFAULT_CALLBACK return first(cache.f(θ, cache.p, cur...)) elseif cache.data != Optimization.DEFAULT_DATA x = cache.f(θ, cache.p) @@ -149,7 +149,7 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ end opt_args = __map_optimizer_args(cache, cache.opt; - callback = cache.callback == DEFAULT_CALLBACK && + callback = cache.callback == Optimization.DEFAULT_CALLBACK && cache.data == Optimization.DEFAULT_DATA ? nothing : _cb, cache.solver_args..., diff --git a/lib/OptimizationOptimisers/src/sophia.jl b/lib/OptimizationOptimisers/src/sophia.jl index b24eaa2ae..4e6487082 100644 --- a/lib/OptimizationOptimisers/src/sophia.jl +++ b/lib/OptimizationOptimisers/src/sophia.jl @@ -71,9 +71,9 @@ function SciMLBase.__solve(cache::OptimizationCache{ maxiters = Optimization._check_and_convert_maxiters(maxiters) _loss = function (θ) - if cache.callback == DEFAULT_CALLBACK && data == Optimization.DEFAULT_DATA + if cache.callback == Optimization.DEFAULT_CALLBACK && data == Optimization.DEFAULT_DATA return first(cache.f(θ, cache.p)) - elseif cache.callback == DEFAULT_CALLBACK + elseif cache.callback == Optimization.DEFAULT_CALLBACK return first(cache.f(θ, cache.p, cur...)) elseif data == Optimization.DEFAULT_DATA x = cache.f(θ, cache.p) From 57fb30458fbbf4a972d8147b4930a42cec5bda89 Mon Sep 17 00:00:00 2001 From: Zentrik Date: Sun, 1 Oct 2023 00:17:43 +0100 Subject: [PATCH 4/8] Fix performance issue Not entirely sure what was going on, but we started boxing variables again I think (see #519) --- src/utils.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils.jl b/src/utils.jl index baf955f18..9b40aec16 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,4 +1,6 @@ -const DEFAULT_CALLBACK = (args...) -> false +struct NullCallback end +NullCallback(args) = false; +const DEFAULT_CALLBACK = NullCallback() struct NullData end const DEFAULT_DATA = Iterators.cycle((NullData(),)) From 679c401a294a4293992ff7450f302a577af2c37e Mon Sep 17 00:00:00 2001 From: Zentrik Date: Sun, 1 Oct 2023 00:31:17 +0100 Subject: [PATCH 5/8] Fix method for calling default callback --- src/utils.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.jl b/src/utils.jl index 9b40aec16..92986eb93 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,5 +1,5 @@ struct NullCallback end -NullCallback(args) = false; +(x::NullCallback)(args...) = false; const DEFAULT_CALLBACK = NullCallback() struct NullData end From 868f4ca718fdf63cf35bfaca7d51547c495d9497 Mon Sep 17 00:00:00 2001 From: Zentrik Date: Sun, 1 Oct 2023 00:56:03 +0100 Subject: [PATCH 6/8] Add test to check regression in allocations Currently I get 4609144 bytes allocated, whilst with `callback = (args...) -> false` I get 69929923 which should be a lower bound if the fixes in this pr were undone. --- lib/OptimizationBBO/test/runtests.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/OptimizationBBO/test/runtests.jl b/lib/OptimizationBBO/test/runtests.jl index 4e2211759..8eb03bc8c 100644 --- a/lib/OptimizationBBO/test/runtests.jl +++ b/lib/OptimizationBBO/test/runtests.jl @@ -13,6 +13,8 @@ using Test sol = solve(prob, BBO_adaptive_de_rand_1_bin_radiuslimited()) @test 10 * sol.objective < l1 + @test (@allocated solve(prob, BBO_adaptive_de_rand_1_bin_radiuslimited())) < 1e7 + prob = Optimization.OptimizationProblem(optprob, nothing, _p, lb = [-1.0, -1.0], ub = [0.8, 0.8]) sol = solve(prob, BBO_adaptive_de_rand_1_bin_radiuslimited()) From 78b398e7fc2cec756d68a57dab149747da8fb4e9 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 30 Sep 2023 20:05:38 -0400 Subject: [PATCH 7/8] Update lib/OptimizationOptimisers/src/sophia.jl --- lib/OptimizationOptimisers/src/sophia.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/OptimizationOptimisers/src/sophia.jl b/lib/OptimizationOptimisers/src/sophia.jl index 4e6487082..1f0ed87f7 100644 --- a/lib/OptimizationOptimisers/src/sophia.jl +++ b/lib/OptimizationOptimisers/src/sophia.jl @@ -75,7 +75,7 @@ function SciMLBase.__solve(cache::OptimizationCache{ return first(cache.f(θ, cache.p)) elseif cache.callback == Optimization.DEFAULT_CALLBACK return first(cache.f(θ, cache.p, cur...)) - elseif data == Optimization.DEFAULT_DATA + elseif data === Optimization.DEFAULT_DATA x = cache.f(θ, cache.p) return first(x) else From 87f72a92a7522609cdff844d523c40a6bf769b08 Mon Sep 17 00:00:00 2001 From: Zentrik Date: Sun, 1 Oct 2023 01:09:47 +0100 Subject: [PATCH 8/8] Use `===` instead of `==` Co-authored-by: Christopher Rackauckas --- lib/OptimizationBBO/src/OptimizationBBO.jl | 14 +++++++------- lib/OptimizationOptimisers/src/sophia.jl | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/OptimizationBBO/src/OptimizationBBO.jl b/lib/OptimizationBBO/src/OptimizationBBO.jl index ff1929931..9ef8ccd61 100644 --- a/lib/OptimizationBBO/src/OptimizationBBO.jl +++ b/lib/OptimizationBBO/src/OptimizationBBO.jl @@ -112,7 +112,7 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ cur, state = iterate(cache.data) function _cb(trace) - if cache.callback == Optimization.DEFAULT_CALLBACK + if cache.callback === Optimization.DEFAULT_CALLBACK cb_call = false else cb_call = cache.callback(decompose_trace(trace, cache.progress), x...) @@ -125,7 +125,7 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ BlackBoxOptim.shutdown_optimizer!(trace) #doesn't work end - if cache.data != Optimization.DEFAULT_DATA + if cache.data !== Optimization.DEFAULT_DATA cur, state = iterate(cache.data, state) end cb_call @@ -135,11 +135,11 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ maxtime = Optimization._check_and_convert_maxtime(cache.solver_args.maxtime) _loss = function (θ) - if cache.callback == Optimization.DEFAULT_CALLBACK && cache.data == Optimization.DEFAULT_DATA + if cache.callback === Optimization.DEFAULT_CALLBACK && cache.data === Optimization.DEFAULT_DATA return first(cache.f(θ, cache.p)) - elseif cache.callback == Optimization.DEFAULT_CALLBACK + elseif cache.callback === Optimization.DEFAULT_CALLBACK return first(cache.f(θ, cache.p, cur...)) - elseif cache.data != Optimization.DEFAULT_DATA + elseif cache.data !== Optimization.DEFAULT_DATA x = cache.f(θ, cache.p) return first(x) else @@ -149,8 +149,8 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ end opt_args = __map_optimizer_args(cache, cache.opt; - callback = cache.callback == Optimization.DEFAULT_CALLBACK && - cache.data == Optimization.DEFAULT_DATA ? + callback = cache.callback === Optimization.DEFAULT_CALLBACK && + cache.data === Optimization.DEFAULT_DATA ? nothing : _cb, cache.solver_args..., maxiters = maxiters, diff --git a/lib/OptimizationOptimisers/src/sophia.jl b/lib/OptimizationOptimisers/src/sophia.jl index 1f0ed87f7..fa9fa827b 100644 --- a/lib/OptimizationOptimisers/src/sophia.jl +++ b/lib/OptimizationOptimisers/src/sophia.jl @@ -71,9 +71,9 @@ function SciMLBase.__solve(cache::OptimizationCache{ maxiters = Optimization._check_and_convert_maxiters(maxiters) _loss = function (θ) - if cache.callback == Optimization.DEFAULT_CALLBACK && data == Optimization.DEFAULT_DATA + if cache.callback === Optimization.DEFAULT_CALLBACK && data === Optimization.DEFAULT_DATA return first(cache.f(θ, cache.p)) - elseif cache.callback == Optimization.DEFAULT_CALLBACK + elseif cache.callback === Optimization.DEFAULT_CALLBACK return first(cache.f(θ, cache.p, cur...)) elseif data === Optimization.DEFAULT_DATA x = cache.f(θ, cache.p)