From e4cc7c811e78265a10e6f061353cfb9808eda3c3 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Mon, 15 Jun 2026 10:28:15 -0400 Subject: [PATCH 1/5] Fix dde_tests: import OptimizationOptimJL for BFGS and use AutoForwardDiff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DDE test referenced `BFGS` and `Optimization` without importing the packages that provide them. Under the old `include`-everything `runtests.jl`, `optim_test.jl`'s `using Optim`/`OptimizationOptimJL` leaked `BFGS` into the shared `Main` scope, so the missing import went unnoticed. With the SciMLTesting v1.2 migration each test file now runs in its own isolated module, exposing `UndefVarError: BFGS not defined`. Add `using Optimization, OptimizationOptimJL` (both already test deps) and drop the dead, unused `Opt(:GN_ESCH, 1)` line. Fixing the import revealed a second, latent failure: `AutoZygote()` gradient preparation for the DDE loss errors with `MethodError: no method matching _prepare_pullback_aux` in DifferentiationInterface. The sibling `nlopt_test.jl` already documents this ("#zygote behaves weirdly here") and uses `AutoForwardDiff()`; switching the DDE test to `AutoForwardDiff()` makes it run and assert the real result (res.u[1] ≈ 0.5). Verified locally on Julia 1.10 with the CI-pinned stack (Optimization 4.8.0, OptimizationBase 2.14.0, OptimizationOptimJL 0.4.5, DifferentiationInterface 0.7.18) running the file in an isolated @safetestset: 1 Pass, 0 errors. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- test/dde_tests.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/dde_tests.jl b/test/dde_tests.jl index f37efe9..952fa56 100644 --- a/test/dde_tests.jl +++ b/test/dde_tests.jl @@ -19,7 +19,7 @@ t = collect(range(0, stop = 10, length = 30)) randomized = VectorOfArray([(sol(t[i]) + 0.03randn(2)) for i in 1:length(t)]) data = convert(Array, randomized) -using DiffEqParamEstim, OptimizationNLopt +using DiffEqParamEstim, Optimization, OptimizationOptimJL function f_lotka2(du, u, h, p, t) du[1] = 0.5 * u[1] - p[1] * u[1] * u[2] @@ -32,13 +32,12 @@ p = [0.5] prob_opt = DDEProblem(f_lotka2, u0, h, tspan, p, constant_lags = [0.5]) cost_function = build_loss_objective( prob_opt, MethodOfSteps(Tsit5()), - L2Loss(t, data), Optimization.AutoZygote(), + L2Loss(t, data), Optimization.AutoForwardDiff(), abstol = 1.0e-8, reltol = 1.0e-8 ) optprob = Optimization.OptimizationProblem(cost_function, [1.0], lb = [0.0], ub = [1.0]) -opt = Opt(:GN_ESCH, 1) res = solve(optprob, BFGS()) @test res.u[1] ≈ 0.5 atol = 5.0e-3 From de39fb22453f0b269c1ac6ae79b3e9174ec199a6 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Tue, 16 Jun 2026 05:16:07 -0400 Subject: [PATCH 2/5] Fix likelihood.jl and test_on_monte.jl: import Optimization explicitly After the SciMLTesting v1.2 migration (#308) each test file runs in its own isolated @safetestset module, so latent missing imports that were previously masked by the old include-everything runtests.jl now surface as UndefVarError. `test/likelihood.jl` and `test/test_on_monte.jl` both use the qualified `Optimization.OptimizationProblem`/`Optimization.AutoForwardDiff` but only imported a re-exporting backend (OptimizationBBO / OptimizationOptimJL). `using OptimizationOptimJL` re-exports Optimization's *exported symbols* but does not bind the `Optimization` *module* name into scope, so the qualified references errored with `UndefVarError: Optimization not defined`. This is the same class of failure #310 already fixed in dde_tests.jl. Add `Optimization` (already a test dep via [extras]/[targets]) to the `using` line of both files. No assertions changed. Verified locally on Julia 1.10 (the compat floor / CI lts) by running each file in an isolated @safetestset against the develop'd package: Core/likelihood.jl isolated | 5 Pass, 0 errors Core/test_on_monte.jl isolated | 1 Pass, 0 errors Both Runic-format clean (format_string is a no-op). Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- test/likelihood.jl | 2 +- test/test_on_monte.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/likelihood.jl b/test/likelihood.jl index 455e789..5b98a46 100644 --- a/test/likelihood.jl +++ b/test/likelihood.jl @@ -1,5 +1,5 @@ using OrdinaryDiffEq, DiffEqParamEstim, Distributions, Test, RecursiveArrayTools, - OptimizationBBO + Optimization, OptimizationBBO # ,BlackBoxOptim, pf_func = function (du, u, p, t) diff --git a/test/test_on_monte.jl b/test/test_on_monte.jl index fac35c0..64f1997 100644 --- a/test/test_on_monte.jl +++ b/test/test_on_monte.jl @@ -1,5 +1,5 @@ using DiffEqParamEstim, OrdinaryDiffEq, StochasticDiffEq, - DiffEqBase, RecursiveArrayTools, OptimizationOptimJL, Zygote + DiffEqBase, RecursiveArrayTools, Optimization, OptimizationOptimJL, Zygote using Test pf_func = function (du, u, p, t) From b7deb160dacf6d96c6e0b680bb04dbb6f85f0915 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Tue, 16 Jun 2026 09:29:55 -0400 Subject: [PATCH 3/5] docs: migrate examples to current solver/EnsembleSolution API The Documentation job was red on master after the OrdinaryDiffEq v7 / DifferentialEquations v8 ecosystem bump. Three independent docs-source breakages, all fixed against the current API: - verbose: OrdinaryDiffEq v7 rejects a `Bool` for `verbose` (`ArgumentError: Passing a Bool for verbose is no longer supported ... Use DEVerbosity() or a preset like Standard(), None(), etc. from SciMLLogging`). Replace `verbose = false` with `verbose = None()` (a SciMLLogging AbstractVerbosityPreset, the no-output preset) and add `using SciMLLogging: None`. Affects getting_started.md, generalized_likelihood.md, stochastic_evaluations.md. - StochasticDiffEq solvers: DifferentialEquations v8 was slimmed to {OrdinaryDiffEq, Reexport, SciMLBase} and no longer re-exports the SDE solvers, so `SRIW1`/`SOSRI` in stochastic_evaluations.md errored with UndefVarError. Add an explicit `using StochasticDiffEq: SRIW1, SOSRI` (matching how the package's own tests import them). - EnsembleSolution indexing: `sim[i]` now returns a scalar (flat element indexing), not the i-th trajectory, so the ensemble.md loss `losses[i](sim[i])` hit `MethodError: no method matching (::L2Loss)(::Float64)`. Use `sim.u[i]` to get the i-th ODESolution. Add SciMLLogging and StochasticDiffEq to docs/Project.toml [deps]+[compat]. No test/example was skipped, broken, warnonly-ed, or loosened. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/Project.toml | 4 ++++ docs/src/getting_started.md | 10 ++++++---- docs/src/tutorials/ensemble.md | 2 +- docs/src/tutorials/generalized_likelihood.md | 3 ++- docs/src/tutorials/stochastic_evaluations.md | 6 ++++-- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index f3773a5..05667b3 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -15,7 +15,9 @@ OptimizationNLopt = "4e6fcdb7-1186-4e1f-a706-475e75c168bb" OptimizationOptimJL = "36348300-93cb-4f02-beb5-3c3902f8871e" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" +SciMLLogging = "a6db7da4-7206-11f0-1eab-35f2a5dbe1d1" SciMLSensitivity = "1ed8b502-d754-442c-8d5d-10ac956f44a1" +StochasticDiffEq = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [compat] @@ -35,5 +37,7 @@ OptimizationNLopt = "0.1, 0.2, 0.3" OptimizationOptimJL = "0.1, 0.2, 0.3, 0.4" Plots = "1" RecursiveArrayTools = "2, 3, 4.0" +SciMLLogging = "2" SciMLSensitivity = "7" +StochasticDiffEq = "6, 7" Zygote = "0.6, 0.7" diff --git a/docs/src/getting_started.md b/docs/src/getting_started.md index 4b94011..e1c7eca 100644 --- a/docs/src/getting_started.md +++ b/docs/src/getting_started.md @@ -33,6 +33,7 @@ by defining the equation as a function with a single parameter `p=[a]`: ```@example ode using DifferentialEquations, RecursiveArrayTools, Plots, DiffEqParamEstim using Optimization, ForwardDiff, OptimizationOptimJL, OptimizationBBO +using SciMLLogging: None function f(du, u, p, t) a = p[] @@ -79,7 +80,7 @@ function: ```@example ode cost_function = build_loss_objective(prob, Tsit5(), L2Loss(t, data), Optimization.AutoForwardDiff(), - maxiters = 10000, verbose = false) + maxiters = 10000, verbose = None()) ``` This objective function internally is calling the ODE solver to get solutions @@ -88,7 +89,8 @@ Note that we set `maxiters` in a way that causes the differential equation solve error more quickly when in bad regions of the parameter space, speeding up the process. If the integrator stops early (due to divergence), then those parameters are given an infinite loss, and thus this is a quick way to avoid bad parameters. -We set `verbose=false` because this divergence can get noisy. The `Optimization.AutoForwardDiff()` +We set `verbose = None()` (from [SciMLLogging.jl](https://docs.sciml.ai/SciMLLogging/stable/)) +to silence the solver because this divergence can get noisy. The `Optimization.AutoForwardDiff()` is a choice of automatic differentiation, i.e., how the gradients are calculated. For more information on this choice, see [the automatic differentiation choice API](https://docs.sciml.ai/Optimization/stable/API/optimization_function/#Automatic-Differentiation-Construction-Choice-Recommendations). @@ -171,7 +173,7 @@ We can build an objective function and solve the multiple parameter version just ```@example ode cost_function = build_loss_objective(prob, Tsit5(), L2Loss(t, data), Optimization.AutoForwardDiff(), - maxiters = 10000, verbose = false) + maxiters = 10000, verbose = None()) optprob = Optimization.OptimizationProblem(cost_function, [1.3, 0.8, 2.8, 1.2]) result_bfgs = solve(optprob, BFGS()) ``` @@ -189,7 +191,7 @@ cost_function = build_loss_objective(prob, Tsit5(), L2Loss(t, data, differ_weight = 0.3, data_weight = 0.7), Optimization.AutoForwardDiff(), - maxiters = 10000, verbose = false) + maxiters = 10000, verbose = None()) optprob = Optimization.OptimizationProblem(cost_function, [1.3, 0.8, 2.8, 1.2]) result_bfgs = solve(optprob, BFGS()) ``` diff --git a/docs/src/tutorials/ensemble.md b/docs/src/tutorials/ensemble.md index ffa83e8..469d5f8 100644 --- a/docs/src/tutorials/ensemble.md +++ b/docs/src/tutorials/ensemble.md @@ -89,7 +89,7 @@ losses = [L2Loss(data_times, data[:, :, i]) for i in 1:N] So `losses[i]` is a function which computes the loss of a solution against the data of the ith trajectory. So to build our true loss function, we sum the losses: ```@example ensemble -loss(sim) = sum(losses[i](sim[i]) for i in 1:N) +loss(sim) = sum(losses[i](sim.u[i]) for i in 1:N) ``` As a double check, make sure that `loss(sim)` outputs zero (since we generated the data from sim). Now we generate data with other parameters: diff --git a/docs/src/tutorials/generalized_likelihood.md b/docs/src/tutorials/generalized_likelihood.md index d3fb91d..34af2b9 100644 --- a/docs/src/tutorials/generalized_likelihood.md +++ b/docs/src/tutorials/generalized_likelihood.md @@ -6,6 +6,7 @@ but in this case, fit just two parameters. ```@example likelihood using DifferentialEquations, DiffEqParamEstim, Optimization, OptimizationBBO +using SciMLLogging: None f1 = function (du, u, p, t) du[1] = p[1] * u[1] - p[2] * u[1] * u[2] du[2] = -3.0 * u[2] + u[1] * u[2] @@ -69,7 +70,7 @@ corresponding to that distribution fit: ```@example likelihood obj = build_loss_objective(prob1, Tsit5(), LogLikeLoss(t, distributions), - maxiters = 10000, verbose = false) + maxiters = 10000, verbose = None()) ``` First, let's use the objective function to plot the likelihood landscape: diff --git a/docs/src/tutorials/stochastic_evaluations.md b/docs/src/tutorials/stochastic_evaluations.md index d8f8300..247bf98 100644 --- a/docs/src/tutorials/stochastic_evaluations.md +++ b/docs/src/tutorials/stochastic_evaluations.md @@ -9,6 +9,8 @@ Let's use the same Lotka-Volterra equation as before, but this time add noise: ```@example sde using DifferentialEquations, DiffEqParamEstim, Plots, Optimization, ForwardDiff, OptimizationOptimJL +using StochasticDiffEq: SRIW1, SOSRI +using SciMLLogging: None pf_func = function (du, u, p, t) du[1] = p[1] * u[1] - p[2] * u[1] * u[2] @@ -53,7 +55,7 @@ We use Optim.jl for optimization below ```@example sde obj = build_loss_objective(monte_prob, SOSRI(), L2Loss(t, aggregate_data), Optimization.AutoForwardDiff(), - maxiters = 10000, verbose = false, trajectories = 1000) + maxiters = 10000, verbose = None(), trajectories = 1000) optprob = Optimization.OptimizationProblem(obj, [1.0, 0.5]) result = solve(optprob, Optim.BFGS()) ``` @@ -70,7 +72,7 @@ Instead, when we use `L2Loss` with first differencing enabled, we get much more obj = build_loss_objective(monte_prob, SRIW1(), L2Loss(t, aggregate_data, differ_weight = 1.0, data_weight = 0.5), Optimization.AutoForwardDiff(), - verbose = false, trajectories = 1000, maxiters = 1000) + verbose = None(), trajectories = 1000, maxiters = 1000) optprob = Optimization.OptimizationProblem(obj, [1.0, 0.5]) result = solve(optprob, Optim.BFGS()) result.original From eeb6f5d3d33ae0f7ebbadf18a1d1d874dc051a6e Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Wed, 17 Jun 2026 10:30:32 +0000 Subject: [PATCH 4/5] Update multiple_shooting_objective_test.jl --- test/multiple_shooting_objective_test.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/multiple_shooting_objective_test.jl b/test/multiple_shooting_objective_test.jl index 0fde9a2..aeae56e 100644 --- a/test/multiple_shooting_objective_test.jl +++ b/test/multiple_shooting_objective_test.jl @@ -55,4 +55,4 @@ optprob = Optimization.OptimizationProblem( ub = last.(bound) ) result = solve(optprob, BFGS(), maxiters = 500) -@test result.u[(end - 1):end] ≈ [1.5, 1.0] atol = 2.0e-1 broken = true +@test result.u[(end - 1):end] ≈ [1.5, 1.0] atol = 2.0e-1 From b9949ed3faf7c2dcd1a3f370d94c335bc7d7a078 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Fri, 19 Jun 2026 04:47:14 -0400 Subject: [PATCH 5/5] Fix out_of_place_odes.jl: import DiffEqParamEstim After the SciMLTesting v1.2 migration (#308) each test file runs in its own isolated @safetestset module, so latent missing imports that were previously masked by the old include-everything runtests.jl now surface as UndefVarError. `test/out_of_place_odes.jl` used `L2Loss`, `build_loss_objective`, and `two_stage_objective` (all exported by DiffEqParamEstim) but only imported `OrdinaryDiffEq, Test, SciMLSensitivity, Optimization, OptimizationOptimJL`. Under the old shared-`Main` runtests, a sibling file's `using DiffEqParamEstim` leaked those names into scope; under v1.2 isolation the file aborts the Core run with `UndefVarError: L2Loss not defined`. This was the last file failing all three Core variants (lts/1/pre) and the Downgrade job. Same class of failure already fixed in this PR for dde_tests.jl, likelihood.jl, and test_on_monte.jl. Add `DiffEqParamEstim` to the `using` line. No assertions changed; the `Optimization.AutoZygote()` loss path works here unchanged. Verified locally on Julia 1.10 (CI lts / compat floor) by running the file in an isolated @safetestset against the develop'd package: OOP isolated | 2 Pass, 0 errors (was: UndefVarError: L2Loss not defined) Runic-format clean (format_string is a no-op). Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- test/out_of_place_odes.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/out_of_place_odes.jl b/test/out_of_place_odes.jl index 6fbafe8..8926d35 100644 --- a/test/out_of_place_odes.jl +++ b/test/out_of_place_odes.jl @@ -1,4 +1,5 @@ -using OrdinaryDiffEq, Test, SciMLSensitivity, Optimization, OptimizationOptimJL +using OrdinaryDiffEq, Test, SciMLSensitivity, Optimization, OptimizationOptimJL, + DiffEqParamEstim function LotkaVolterraTest_not_inplace(u, a, t) b, c, d = 1.0, 3.0, 1.0