From f165fa2f5097cabad9f4e88189eb7f50baaaf646 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Sat, 6 Jan 2024 00:15:04 +0000 Subject: [PATCH 1/9] CompatHelper: bump compat for OptimizationOptimJL to 0.2, (keep existing compat) --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 1201d166..bdb7df13 100644 --- a/Project.toml +++ b/Project.toml @@ -47,7 +47,7 @@ LogDensityProblems = "2" MCMCChains = "5, 6" Optim = "1.4" Optimization = "3" -OptimizationOptimJL = "0.1" +OptimizationOptimJL = "0.1, 0.2" PDMats = "0.11.26" PSIS = "0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9" ProgressLogging = "0.1.4" From 02753f43f3e7ed1fe1fbe56fe2dc0982cf1fdc85 Mon Sep 17 00:00:00 2001 From: Seth Axen Date: Thu, 11 Jan 2024 13:40:07 +0100 Subject: [PATCH 2/9] Drop support for Optimization 0.1 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index bdb7df13..8c4db2c6 100644 --- a/Project.toml +++ b/Project.toml @@ -47,7 +47,7 @@ LogDensityProblems = "2" MCMCChains = "5, 6" Optim = "1.4" Optimization = "3" -OptimizationOptimJL = "0.1, 0.2" +OptimizationOptimJL = "0.2" PDMats = "0.11.26" PSIS = "0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9" ProgressLogging = "0.1.4" From 6196d1bf0346331ef1369fb212d8ff712c79d39e Mon Sep 17 00:00:00 2001 From: Seth Axen Date: Thu, 11 Jan 2024 13:40:26 +0100 Subject: [PATCH 3/9] Use new Optimization callback API --- src/optimize.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/optimize.jl b/src/optimize.jl index db1c4f11..79824536 100644 --- a/src/optimize.jl +++ b/src/optimize.jl @@ -50,23 +50,23 @@ end function _make_optimization_callback( xs, fxs, ∇fxs, ∇f; progress_name, progress_id, maxiters, callback, fail_on_nonfinite ) - return function (x, nfx, args...) - ret = callback !== nothing && callback(x, nfx, args...) - iteration = length(xs) + return function (state, args...) + ret = callback !== nothing && callback(state, args...) + iteration = state.iter Base.@logmsg ProgressLogging.ProgressLevel progress_name progress = iteration / maxiters _id = progress_id + x = copy(state.u) + fx = -state.objective + ∇fx = state.grad === nothing ? ∇f(x) : -state.grad + # some backends mutate x, so we must copy it - push!(xs, copy(x)) - push!(fxs, -nfx) - # NOTE: Optimization doesn't have an interface for accessing the gradient trace, - # so we need to recompute it ourselves - # see https://github.com/SciML/Optimization.jl/issues/149 - ∇fx = ∇f(x) + push!(xs, x) + push!(fxs, fx) push!(∇fxs, ∇fx) if fail_on_nonfinite && !ret - ret = (isnan(nfx) || nfx == -Inf || any(!isfinite, ∇fx))::Bool + ret = (isnan(fx) || fx == Inf || any(!isfinite, ∇fx))::Bool end return ret From c3875123a4d1d07facc0ff7f12c028e0997b1653 Mon Sep 17 00:00:00 2001 From: Seth Axen Date: Thu, 11 Jan 2024 13:41:26 +0100 Subject: [PATCH 4/9] Update tests --- test/optimize.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/optimize.jl b/test/optimize.jl index e4785677..0947450e 100644 --- a/test/optimize.jl +++ b/test/optimize.jl @@ -57,7 +57,7 @@ end g[end] = gval return g end - callback = (x, fx, args...) -> cbfail + callback = (state, args...) -> cbfail cb = Pathfinder._make_optimization_callback( xs, fxs, @@ -72,7 +72,11 @@ end should_fail = cbfail || (fail_on_nonfinite && (isnan(fval) || fval == Inf || !isfinite(gval))) - @test cb(x, -fval) == should_fail + x0 = randn(5) + state = Optimization.OptimizationState(; + iter=0, u=x0, objective=-fval, grad=-∇f(x0) + ) + @test cb(state, -fval) == should_fail end end end From ecfda0b6a99c32c61523e8f04e30700a49294c5c Mon Sep 17 00:00:00 2001 From: Seth Axen Date: Thu, 11 Jan 2024 13:41:42 +0100 Subject: [PATCH 5/9] Increment patch number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 8c4db2c6..32e68cd2 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Pathfinder" uuid = "b1d3bc72-d0e7-4279-b92f-7fa5d6d2d454" authors = ["Seth Axen and contributors"] -version = "0.8.1" +version = "0.8.2" [deps] Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" From 5c0fc7c07c962b6f7cabe59d9104e62d5bf435a7 Mon Sep 17 00:00:00 2001 From: Seth Axen Date: Mon, 15 Jan 2024 12:53:43 +0100 Subject: [PATCH 6/9] Restore support for old OptimizationOptimJL versio --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 32e68cd2..fc6cf524 100644 --- a/Project.toml +++ b/Project.toml @@ -47,7 +47,7 @@ LogDensityProblems = "2" MCMCChains = "5, 6" Optim = "1.4" Optimization = "3" -OptimizationOptimJL = "0.2" +OptimizationOptimJL = "0.1, 0.2" PDMats = "0.11.26" PSIS = "0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9" ProgressLogging = "0.1.4" From 11d7196307db53e8b9ab113835f1cb8a8ec77afb Mon Sep 17 00:00:00 2001 From: Seth Axen Date: Mon, 15 Jan 2024 12:54:22 +0100 Subject: [PATCH 7/9] Add OptimizationCallback --- src/optimize.jl | 68 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/src/optimize.jl b/src/optimize.jl index 79824536..501c7a86 100644 --- a/src/optimize.jl +++ b/src/optimize.jl @@ -40,17 +40,39 @@ function optimize_with_trace( xs = typeof(u0)[] fxs = typeof(fun.f(u0, nothing))[] ∇fxs = typeof(u0)[] - _callback = _make_optimization_callback( - xs, fxs, ∇fxs, ∇f; progress_name, progress_id, maxiters, callback, fail_on_nonfinite + _callback = OptimizationCallback( + xs, fxs, ∇fxs, ∇f, progress_name, progress_id, maxiters, callback, fail_on_nonfinite ) sol = Optimization.solve(prob, optimizer; callback=_callback, maxiters, kwargs...) return sol, OptimizationTrace(xs, fxs, ∇fxs) end -function _make_optimization_callback( - xs, fxs, ∇fxs, ∇f; progress_name, progress_id, maxiters, callback, fail_on_nonfinite -) - return function (state, args...) +struct OptimizationCallback{X,FX,∇FX,∇F,ID,CB} + xs::X + fxs::FX + ∇fxs::∇FX + ∇f::∇F + progress_name::String + progress_id::ID + maxiters::Int + callback::CB + fail_on_nonfinite::Bool +end + +@static if isdefined(Optimization, :OptimizationState) + # Optimization v3.21.0 and later + function (cb::OptimizationCallback)(state::Optimization.OptimizationState, args...) + @unpack ( + xs, + fxs, + ∇fxs, + ∇f, + progress_name, + progress_id, + maxiters, + callback, + fail_on_nonfinite, + ) = cb ret = callback !== nothing && callback(state, args...) iteration = state.iter Base.@logmsg ProgressLogging.ProgressLevel progress_name progress = @@ -69,6 +91,40 @@ function _make_optimization_callback( ret = (isnan(fx) || fx == Inf || any(!isfinite, ∇fx))::Bool end + return ret + end +else + # Optimization v3.20.X and earlier + function (cb::OptimizationCallback)(x, nfx, args...) + @unpack ( + xs, + fxs, + ∇fxs, + ∇f, + progress_name, + progress_id, + maxiters, + callback, + fail_on_nonfinite, + ) = cb + ret = callback !== nothing && callback(x, nfx, args...) + iteration = length(cb.xs) + Base.@logmsg ProgressLogging.ProgressLevel progress_name progress = + iteration / maxiters _id = progress_id + + # some backends mutate x, so we must copy it + push!(xs, copy(x)) + push!(fxs, -nfx) + # NOTE: Optimization doesn't have an interface for accessing the gradient trace, + # so we need to recompute it ourselves + # see https://github.com/SciML/Optimization.jl/issues/149 + ∇fx = ∇f(x) + push!(∇fxs, ∇fx) + + if fail_on_nonfinite && !ret + ret = (isnan(nfx) || nfx == -Inf || any(!isfinite, ∇fx))::Bool + end + return ret end end From e96de939a35ba6a74e82cb01ac6e1475a387764a Mon Sep 17 00:00:00 2001 From: Seth Axen Date: Mon, 15 Jan 2024 12:54:37 +0100 Subject: [PATCH 8/9] Update callback test --- test/optimize.jl | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/test/optimize.jl b/test/optimize.jl index 0947450e..8c797f00 100644 --- a/test/optimize.jl +++ b/test/optimize.jl @@ -37,7 +37,7 @@ end @test prob.p === nothing end -@testset "_make_optimization_callback" begin +@testset "OptimizationCallback" begin @testset "callback return value" begin progress_name = "Optimizing" progress_id = nothing @@ -57,26 +57,34 @@ end g[end] = gval return g end - callback = (state, args...) -> cbfail - cb = Pathfinder._make_optimization_callback( + should_fail = + cbfail || + (fail_on_nonfinite && (isnan(fval) || fval == Inf || !isfinite(gval))) + if isdefined(Optimization, :OptimizationState) + # Optimization v3.21.0 and later + callback = (state, args...) -> cbfail + state = Optimization.OptimizationState(; + iter=0, u=x, objective=-fval, grad=-∇f(x) + ) + cb_args = (state, -fval) + else + # Optimization v3.20.X and earlier + callback = (x, fx, args...) -> cbfail + cb_args = (x, -fval) + end + cb = Pathfinder.OptimizationCallback( xs, fxs, ∇fxs, - ∇f; + ∇f, progress_name, progress_id, maxiters, callback, fail_on_nonfinite, ) - should_fail = - cbfail || - (fail_on_nonfinite && (isnan(fval) || fval == Inf || !isfinite(gval))) - x0 = randn(5) - state = Optimization.OptimizationState(; - iter=0, u=x0, objective=-fval, grad=-∇f(x0) - ) - @test cb(state, -fval) == should_fail + @test cb isa Pathfinder.OptimizationCallback + @test cb(cb_args...) == should_fail end end end From 94136cd06157cf5522186820f1ef0a6052e6b298 Mon Sep 17 00:00:00 2001 From: Seth Axen Date: Mon, 15 Jan 2024 13:21:06 +0100 Subject: [PATCH 9/9] Remove the 1.10 release client from CI Now that v1.10 is released, this is redundant. --- .github/workflows/CI.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 80f5abc5..66bcb77c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -29,11 +29,6 @@ jobs: num_threads: - 1 - 2 - include: - - version: '^1.10.0-rc1' - os: ubuntu-latest - arch: x64 - num_threads: 1 steps: - uses: actions/checkout@v2 - uses: julia-actions/setup-julia@v1