From 60d25dc6552c88f0e4d460cc3b59caa05c71508c Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Thu, 25 Jun 2026 13:21:11 -0400 Subject: [PATCH 1/3] QA: run_qa v1.6 form + ExplicitImports (root + sublibs) Convert every QA environment in the monorepo to the SciMLTesting v1.6 run_qa form with ExplicitImports enabled: - Root test/qa: new qa.jl calls run_qa(DataDrivenDiffEq; jet = false, explicit_imports = true). Aqua and ExplicitImports now run via run_qa; the curated JET @test_opt checks stay in jet_tests.jl (JET.test_package on the whole method table reports many false positives from the re-exported Symbolics/ModelingToolkit surface). runtests.jl QA body includes both. - lib/DataDrivenDMD, DataDrivenSparse, DataDrivenSR, DataDrivenLux test/qa: qa.jl rewritten to using SciMLTesting, , JET, Test + run_qa(; explicit_imports = true). Aqua + JET preserved. ExplicitImports: no_implicit_imports is marked ei_broken in every env because each module pulls a re-exported public surface in implicitly by design (root: @reexport using ModelingToolkit/StatsBase/DataInterpolations/MLUtils/CommonSolve; sublibs: umbrella using DataDrivenDiffEq, plus DataDrivenSR's @reexport using SymbolicRegression). The other five EI checks run hard. QA env Project.toml: add SciMLTesting (compat 1.6); ExplicitImports stays a transitive SciMLTesting dep (not listed). Aqua + JET kept where they run. The [sources]/develop wiring that pins the in-repo sublib + umbrella root is unchanged. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/DataDrivenDMD/test/qa/Project.toml | 2 ++ lib/DataDrivenDMD/test/qa/qa.jl | 18 +++++++++--------- lib/DataDrivenLux/test/qa/Project.toml | 2 ++ lib/DataDrivenLux/test/qa/qa.jl | 17 ++++++++--------- lib/DataDrivenSR/test/qa/Project.toml | 2 ++ lib/DataDrivenSR/test/qa/qa.jl | 19 ++++++++++--------- lib/DataDrivenSparse/test/qa/Project.toml | 2 ++ lib/DataDrivenSparse/test/qa/qa.jl | 18 +++++++++--------- test/qa/Project.toml | 2 +- test/qa/qa.jl | 18 ++++++++++++++++++ test/runtests.jl | 3 +++ 11 files changed, 66 insertions(+), 37 deletions(-) create mode 100644 test/qa/qa.jl diff --git a/lib/DataDrivenDMD/test/qa/Project.toml b/lib/DataDrivenDMD/test/qa/Project.toml index 6049d18d..73043c13 100644 --- a/lib/DataDrivenDMD/test/qa/Project.toml +++ b/lib/DataDrivenDMD/test/qa/Project.toml @@ -2,6 +2,7 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" DataDrivenDMD = "3c9adf31-5280-42ff-b439-b71cc6b07807" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" +SciMLTesting = "09d9d899-5365-40a9-917a-5f67fddea283" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [sources] @@ -10,5 +11,6 @@ DataDrivenDMD = {path = "../.."} [compat] Aqua = "0.8" JET = "0.9, 0.10, 0.11" +SciMLTesting = "1.6" Test = "1" julia = "1.10" diff --git a/lib/DataDrivenDMD/test/qa/qa.jl b/lib/DataDrivenDMD/test/qa/qa.jl index 9ac5e175..8c5aeada 100644 --- a/lib/DataDrivenDMD/test/qa/qa.jl +++ b/lib/DataDrivenDMD/test/qa/qa.jl @@ -1,13 +1,13 @@ +using SciMLTesting using DataDrivenDMD -using Aqua using JET using Test -@testset "QA" begin - @testset "Aqua" begin - Aqua.test_all(DataDrivenDMD) - end - @testset "JET" begin - JET.test_package(DataDrivenDMD; target_defined_modules = true) - end -end +run_qa( + DataDrivenDMD; + explicit_imports = true, + # The umbrella `using DataDrivenDiffEq` (plus the `using DataDrivenDiffEq.` + # re-exports) pulls the DataDrivenDiffEq public surface in implicitly; making every + # name explicit is a large refactor tracked separately. + ei_broken = (:no_implicit_imports,) +) diff --git a/lib/DataDrivenLux/test/qa/Project.toml b/lib/DataDrivenLux/test/qa/Project.toml index f8e71d7e..ed9e7e50 100644 --- a/lib/DataDrivenLux/test/qa/Project.toml +++ b/lib/DataDrivenLux/test/qa/Project.toml @@ -3,6 +3,7 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" DataDrivenDiffEq = "2445eb08-9709-466a-b3fc-47e12bd697a2" DataDrivenLux = "47881146-99d0-492a-8425-8f2f33327637" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" +SciMLTesting = "09d9d899-5365-40a9-917a-5f67fddea283" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [sources] @@ -12,5 +13,6 @@ DataDrivenLux = {path = "../.."} [compat] Aqua = "0.8" JET = "0.9, 0.10, 0.11" +SciMLTesting = "1.6" Test = "1" julia = "1.10" diff --git a/lib/DataDrivenLux/test/qa/qa.jl b/lib/DataDrivenLux/test/qa/qa.jl index be147625..41b0fc52 100644 --- a/lib/DataDrivenLux/test/qa/qa.jl +++ b/lib/DataDrivenLux/test/qa/qa.jl @@ -1,13 +1,12 @@ +using SciMLTesting using DataDrivenLux -using Aqua using JET using Test -@testset "QA" begin - @testset "Aqua" begin - Aqua.test_all(DataDrivenLux) - end - @testset "JET" begin - JET.test_package(DataDrivenLux; target_defined_modules = true) - end -end +run_qa( + DataDrivenLux; + explicit_imports = true, + # The umbrella `using DataDrivenDiffEq` pulls its public surface in implicitly; + # making every name explicit is a large refactor tracked separately. + ei_broken = (:no_implicit_imports,) +) diff --git a/lib/DataDrivenSR/test/qa/Project.toml b/lib/DataDrivenSR/test/qa/Project.toml index cf48581f..23e56db8 100644 --- a/lib/DataDrivenSR/test/qa/Project.toml +++ b/lib/DataDrivenSR/test/qa/Project.toml @@ -3,6 +3,7 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" DataDrivenDiffEq = "2445eb08-9709-466a-b3fc-47e12bd697a2" DataDrivenSR = "7fed8a53-d475-4873-af3a-ba53cceea094" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" +SciMLTesting = "09d9d899-5365-40a9-917a-5f67fddea283" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [sources] @@ -12,5 +13,6 @@ DataDrivenSR = {path = "../.."} [compat] Aqua = "0.8" JET = "0.9, 0.10, 0.11" +SciMLTesting = "1.6" Test = "1" julia = "1.10" diff --git a/lib/DataDrivenSR/test/qa/qa.jl b/lib/DataDrivenSR/test/qa/qa.jl index 11ee918b..be531200 100644 --- a/lib/DataDrivenSR/test/qa/qa.jl +++ b/lib/DataDrivenSR/test/qa/qa.jl @@ -1,13 +1,14 @@ +using SciMLTesting using DataDrivenSR -using Aqua using JET using Test -@testset "QA" begin - @testset "Aqua" begin - Aqua.test_all(DataDrivenSR) - end - @testset "JET" begin - JET.test_package(DataDrivenSR; target_defined_modules = true) - end -end +run_qa( + DataDrivenSR; + explicit_imports = true, + # The umbrella `using DataDrivenDiffEq` and `@reexport using SymbolicRegression` + # (plus the `using DataDrivenDiffEq.` re-exports) pull those public + # surfaces in implicitly; making every name explicit is a large refactor tracked + # separately. + ei_broken = (:no_implicit_imports,) +) diff --git a/lib/DataDrivenSparse/test/qa/Project.toml b/lib/DataDrivenSparse/test/qa/Project.toml index 3025a59a..07d18597 100644 --- a/lib/DataDrivenSparse/test/qa/Project.toml +++ b/lib/DataDrivenSparse/test/qa/Project.toml @@ -2,6 +2,7 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" DataDrivenSparse = "5b588203-7d8b-4fab-a537-c31a7f73f46b" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" +SciMLTesting = "09d9d899-5365-40a9-917a-5f67fddea283" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [sources] @@ -10,5 +11,6 @@ DataDrivenSparse = {path = "../.."} [compat] Aqua = "0.8" JET = "0.9, 0.10, 0.11" +SciMLTesting = "1.6" Test = "1" julia = "1.10" diff --git a/lib/DataDrivenSparse/test/qa/qa.jl b/lib/DataDrivenSparse/test/qa/qa.jl index 7454f4f2..c7071dfc 100644 --- a/lib/DataDrivenSparse/test/qa/qa.jl +++ b/lib/DataDrivenSparse/test/qa/qa.jl @@ -1,13 +1,13 @@ +using SciMLTesting using DataDrivenSparse -using Aqua using JET using Test -@testset "QA" begin - @testset "Aqua" begin - Aqua.test_all(DataDrivenSparse) - end - @testset "JET" begin - JET.test_package(DataDrivenSparse; target_defined_modules = true) - end -end +run_qa( + DataDrivenSparse; + explicit_imports = true, + # The umbrella `using DataDrivenDiffEq` (plus the `using DataDrivenDiffEq.` + # re-exports) pulls the DataDrivenDiffEq public surface in implicitly; making every + # name explicit is a large refactor tracked separately. + ei_broken = (:no_implicit_imports,) +) diff --git a/test/qa/Project.toml b/test/qa/Project.toml index a06d3f07..f2acc4ba 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -11,5 +11,5 @@ DataDrivenDiffEq = {path = "../.."} [compat] JET = "0.9, 0.10, 0.11" SafeTestsets = "0.0.1, 0.1" -SciMLTesting = "1" +SciMLTesting = "1.6" Test = "1" diff --git a/test/qa/qa.jl b/test/qa/qa.jl new file mode 100644 index 00000000..5ea1fb19 --- /dev/null +++ b/test/qa/qa.jl @@ -0,0 +1,18 @@ +using SciMLTesting +using DataDrivenDiffEq +using Test + +# Aqua + ExplicitImports via run_qa. JET is handled separately by jet_tests.jl: +# `JET.test_package` on this package's whole method table reports many false +# positives from the re-exported symbolic infrastructure (Symbolics/ModelingToolkit), +# so the root keeps the curated `@test_opt` checks (jet_tests.jl) targeted at concrete +# DataDrivenDiffEq code instead. +run_qa( + DataDrivenDiffEq; + jet = false, + explicit_imports = true, + # The `@reexport using ModelingToolkit/StatsBase/DataInterpolations/MLUtils/CommonSolve` + # surface is pulled in implicitly by design (this package re-exports it); making every + # name explicit is a large refactor tracked separately. + ei_broken = (:no_implicit_imports,) +) diff --git a/test/runtests.jl b/test/runtests.jl index e5793161..8fea6b20 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -80,6 +80,9 @@ const GROUP = get(ENV, "GROUP", "All") qa = (; env = joinpath(@__DIR__, "qa"), body = function () + @safetestset "Quality Assurance" begin + include("qa/qa.jl") + end @safetestset "JET Static Analysis" begin include("qa/jet_tests.jl") end From 478e89eb9cd620920cd830546df88ff2ab7e8631 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sat, 27 Jun 2026 09:52:06 -0400 Subject: [PATCH 2/3] Fix DataDrivenLux downgrade CI: raise IntervalArithmetic and Optim floors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Downgrade Sublibraries / test (lib/DataDrivenLux) lane resolves and builds, then fails at runtime with 5 errors (reproduces on master, not introduced by this QA PR; the PR does not touch DataDrivenLux src or Project.toml). Two distinct root causes, both gated by [compat] floors: 1. IntervalArithmetic floor 0.22.0 (4 errors). `safe_sin`/`safe_cos` in src/utils.jl evaluate `real(sin(Complex(x)))` on `x::Interval{Float64}` during path-interval propagation (path_state.jl `update_path`). Base's `sin(::Complex)` does `zr == 0`, which dispatches to `==(::Interval, ::Interval)`. IntervalArithmetic 0.22.0-0.22.9 throw `ArgumentError("== is purposely not supported for intervals")` there; 0.22.10 added the thin-interval fallback so the comparison returns a value and `sin(Complex{Interval})` works. Bisected locally: 0.22.9 THROW, 0.22.10 OK. Raise floor to 0.22.10. 2. Optim floor 1.7.6 (1 BoundsError). `BoundsError: attempt to access Float64 at index [2]` in `LineSearches.var"#ϕdϕ#2"`. Optim's `ManifoldObjective.value_gradient!` returns a scalar `value(...)` in all Optim versions; LineSearches <= 7.5.x `make_ϕdϕ` does `f, g = value_gradient!(df, x_new)` and fails to unpack the scalar into 2 vars. LineSearches 7.6.0 switched to `value_jvp!(df, x_new, s)` (which returns a 2-tuple) and requires NLSolversBase 8. No Optim 1.x admits NLSolversBase 8 (all cap "7.9.0"), so LineSearches stays <= 7.5.x at the Optim 1.7 floor. Optim 2.0.0 requires LineSearches "7.6" + NLSolversBase "8". The passing Core lane already resolves Optim 2.2.1 / LineSearches 7.7.1 / NLSolversBase 8. Raise Optim floor to 2. Verified locally on Julia 1.10 by pinning the new floors and running `Pkg.test("DataDrivenLux")`: sandbox resolved IntervalArithmetic 0.22.10, Optim 2.0.0, LineSearches 7.7.1, NLSolversBase 8.0.0; result 96/96 pass (was 0 pass / 5 errored on the old floors). Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/DataDrivenLux/Project.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/DataDrivenLux/Project.toml b/lib/DataDrivenLux/Project.toml index 07591e38..6816c8c5 100644 --- a/lib/DataDrivenLux/Project.toml +++ b/lib/DataDrivenLux/Project.toml @@ -1,6 +1,6 @@ name = "DataDrivenLux" uuid = "47881146-99d0-492a-8425-8f2f33327637" -version = "0.2.4" +version = "0.2.5" authors = ["JuliusMartensen "] [deps] @@ -45,13 +45,13 @@ Distributions = "0.25.123" DistributionsAD = "0.6" DocStringExtensions = "0.9.3" ForwardDiff = "0.10, 1" -IntervalArithmetic = "0.22, 0.23, 1" +IntervalArithmetic = "0.22.10, 0.23, 1" InverseFunctions = "0.1" LinearAlgebra = "1.10" Logging = "1.10" Lux = "1" LuxCore = "1" -Optim = "1.7, 2" +Optim = "2" Optimisers = "0.3, 0.4" OrdinaryDiffEq = "6, 7" Pkg = "1.10" From 79f9437102cc281a7999759c715f7d88893157b7 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Mon, 29 Jun 2026 07:10:58 -0400 Subject: [PATCH 3/3] QA: make run_qa lanes green (fix latent bugs, curate Aqua/EI suppressions) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The run_qa conversion runs Aqua.test_all + ExplicitImports for the first time (the old QA group only ran curated JET @test_opt), surfacing pre-existing latent findings on every lane. This commit addresses them: Real source fixes: - src/DataDrivenDiffEq.jl: drop the stale `AbstractTimeseriesSolution` explicit import (all uses are already qualified `SciMLBase.AbstractTimeseriesSolution`). - Project.toml: drop `ProgressMeter` (unused in the root package; only the DataDrivenLux sublib uses it) — fixes Aqua stale_deps. - lib/DataDrivenSparse: fix two genuine bugs JET typo-mode caught: result.jl `:traineerror` -> `:trainerror` (field typo), and proximals.jl ClippedAbsoluteDeviation functor `@unpack ρ = h` -> `= s` (undefined `h`). - DMD/Lux/SR/Sparse src: remove genuinely-stale `using DataDrivenDiffEq: ...` imports flagged by ExplicitImports.no_stale_explicit_imports. QA suppressions (documented, pre-existing-latent only): - Root aqua_broken=(:ambiguities,:unbound_args,:piracies): the `unique!`/ `deleteat!` Basis methods on Symbolics types are intentional API; the ambiguities are their direct consequence; DataDrivenDataset's `Vararg{T,N}` is unbound for the zero-arg signature. - Sparse aqua_broken=(:ambiguities,): inherited from the parent piracy. - DMD aqua_broken=(:undefined_exports,): `get_trainerror`/`get_testerror` are exported but never defined (dead exports from the #371 refactor). - ei_kwargs ignore-lists for non-public upstream names (SciMLBase/Symbolics/ SymbolicUtils/ModelingToolkit/Optim/etc.) and DataDrivenDiffEq's own non-exported extension API consumed by its sublibraries. - Root test/qa/Project.toml: add Aqua as a direct dep (so the ambiguities child-process can load it, matching the sublib qa envs). Verified on Julia 1.12 (the CI QA lane): root 13 pass/4 broken, DMD 16/2, Sparse 16/2, SR 17/1, Lux 17/1 — 0 fail, 0 error on every lane. Co-Authored-By: Chris Rackauckas --- Project.toml | 2 - lib/DataDrivenDMD/src/DataDrivenDMD.jl | 2 - lib/DataDrivenDMD/test/qa/qa.jl | 20 +++++++++ lib/DataDrivenLux/src/DataDrivenLux.jl | 9 ++-- lib/DataDrivenLux/test/qa/qa.jl | 32 ++++++++++++++ lib/DataDrivenSR/src/DataDrivenSR.jl | 7 +-- lib/DataDrivenSR/test/qa/qa.jl | 21 +++++++++ lib/DataDrivenSparse/src/DataDrivenSparse.jl | 5 +-- .../src/algorithms/proximals.jl | 2 +- lib/DataDrivenSparse/src/result.jl | 2 +- lib/DataDrivenSparse/test/qa/qa.jl | 19 ++++++++ src/DataDrivenDiffEq.jl | 2 +- test/qa/Project.toml | 2 + test/qa/qa.jl | 44 +++++++++++++++++++ 14 files changed, 148 insertions(+), 21 deletions(-) diff --git a/Project.toml b/Project.toml index 24f9565f..77f9a192 100644 --- a/Project.toml +++ b/Project.toml @@ -13,7 +13,6 @@ MLUtils = "f1d291b0-491e-4a28-83b9-f70985020b54" ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78" Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" -ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca" QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" @@ -38,7 +37,6 @@ OrdinaryDiffEqTsit5 = "1, 2" Parameters = "0.12.1, 0.13" Pkg = "1" PrecompileTools = "1" -ProgressMeter = "1.6" QuadGK = "2.4" Random = "1" RecipesBase = "1" diff --git a/lib/DataDrivenDMD/src/DataDrivenDMD.jl b/lib/DataDrivenDMD/src/DataDrivenDMD.jl index 43af19fb..02c24fc3 100644 --- a/lib/DataDrivenDMD/src/DataDrivenDMD.jl +++ b/lib/DataDrivenDMD/src/DataDrivenDMD.jl @@ -5,14 +5,12 @@ using DataDrivenDiffEq using DataDrivenDiffEq: AbstractBasis using DataDrivenDiffEq: AbstractDataDrivenAlgorithm using DataDrivenDiffEq: AbstractDataDrivenResult -using DataDrivenDiffEq: AbstractDataDrivenProblem using DataDrivenDiffEq: DDReturnCode, ABSTRACT_CONT_PROB, ABSTRACT_DISCRETE_PROB using DataDrivenDiffEq: InternalDataDrivenProblem using DataDrivenDiffEq: is_implicit, is_controlled using DataDrivenDiffEq.DocStringExtensions using DataDrivenDiffEq.CommonSolve -using DataDrivenDiffEq.CommonSolve: solve! using DataDrivenDiffEq.StatsBase using DataDrivenDiffEq.Parameters diff --git a/lib/DataDrivenDMD/test/qa/qa.jl b/lib/DataDrivenDMD/test/qa/qa.jl index 8c5aeada..4a57b68f 100644 --- a/lib/DataDrivenDMD/test/qa/qa.jl +++ b/lib/DataDrivenDMD/test/qa/qa.jl @@ -6,6 +6,26 @@ using Test run_qa( DataDrivenDMD; explicit_imports = true, + # `get_trainerror`/`get_testerror` are listed in `export` (src/DataDrivenDMD.jl) but + # no method is ever defined for them (dead exports from the #371 refactor). Aqua was + # never run before this conversion, so this is pre-existing and surfaced, not + # introduced; marked broken rather than silenced. + aqua_broken = (:undefined_exports,), + ei_kwargs = (; + # DataDrivenDiffEq exposes these names as the (non-`export`ed) extension API its + # own sublibraries build on. They are used deliberately; declaring them `public` + # upstream is tracked separately. + all_explicit_imports_are_public = (; + ignore = ( + :AbstractBasis, :AbstractDataDrivenAlgorithm, :AbstractDataDrivenResult, + :ABSTRACT_CONT_PROB, :ABSTRACT_DISCRETE_PROB, + :InternalDataDrivenProblem, :is_controlled, :is_implicit, + ), + ), + all_qualified_accesses_are_public = (; + ignore = (:__EMPTY_MATRIX, :__construct_basis, :get_fit_targets), + ), + ), # The umbrella `using DataDrivenDiffEq` (plus the `using DataDrivenDiffEq.` # re-exports) pulls the DataDrivenDiffEq public surface in implicitly; making every # name explicit is a large refactor tracked separately. diff --git a/lib/DataDrivenLux/src/DataDrivenLux.jl b/lib/DataDrivenLux/src/DataDrivenLux.jl index f3d7fe70..1e5f553d 100644 --- a/lib/DataDrivenLux/src/DataDrivenLux.jl +++ b/lib/DataDrivenLux/src/DataDrivenLux.jl @@ -3,13 +3,12 @@ module DataDrivenLux using DataDrivenDiffEq # Load specific (abstract) types -using DataDrivenDiffEq: AbstractBasis, AbstractDataDrivenAlgorithm, +using DataDrivenDiffEq: AbstractDataDrivenAlgorithm, AbstractDataDrivenResult, AbstractDataDrivenProblem, DDReturnCode, - ABSTRACT_CONT_PROB, ABSTRACT_DISCRETE_PROB, - InternalDataDrivenProblem, is_implicit, is_controlled + InternalDataDrivenProblem using DocStringExtensions: DocStringExtensions, FIELDS, TYPEDEF, SIGNATURES -using CommonSolve: CommonSolve, solve! +using CommonSolve: CommonSolve using ConcreteStructs: @concrete using Setfield: Setfield, @set! @@ -25,7 +24,7 @@ using TransformVariables: TransformVariables, as, transform_logdensity using Distributions: Distributions, Distribution, Normal, Uniform, Univariate, dof, loglikelihood, logpdf, mean, mode, quantile, scale, truncated using DistributionsAD: DistributionsAD -using StatsBase: StatsBase, aicc, nobs, nullloglikelihood, r2, rss, sum, weights +using StatsBase: StatsBase, aicc, nobs, nullloglikelihood, r2, rss, sum using ChainRulesCore: @ignore_derivatives using ComponentArrays: ComponentArrays, ComponentVector diff --git a/lib/DataDrivenLux/test/qa/qa.jl b/lib/DataDrivenLux/test/qa/qa.jl index 41b0fc52..5a83793d 100644 --- a/lib/DataDrivenLux/test/qa/qa.jl +++ b/lib/DataDrivenLux/test/qa/qa.jl @@ -6,6 +6,38 @@ using Test run_qa( DataDrivenLux; explicit_imports = true, + ei_kwargs = (; + all_explicit_imports_are_public = (; + ignore = ( + # DataDrivenDiffEq non-`export`ed extension API its sublibraries build on. + :AbstractDataDrivenAlgorithm, :AbstractDataDrivenProblem, + :AbstractDataDrivenResult, :InternalDataDrivenProblem, + # External non-public names, used deliberately. + :AbstractBackend, :ForwardDiffBackend, :gradient, # AbstractDifferentiation + :converged, :Options, # Optim + :isempty, # IntervalArithmetic + :square, # InverseFunctions + ), + ), + all_explicit_imports_via_owners = (; + ignore = (:isempty,), # IntervalArithmetic.isempty (owner Base) + ), + all_qualified_accesses_are_public = (; + ignore = ( + # DataDrivenDiffEq internals accessed qualified. + :get_f, :get_fit_targets, :get_implicit_data, :get_oop_args, + :remake_problem, :_set_default_val, :AbstractDataDrivenResult, + :getdefaultval, # Symbolics + :isvariable, # ModelingToolkit + :promote_eltype, # Base + :AbstractBackend, :ForwardDiffBackend, :gradient, # AbstractDifferentiation + :converged, :Options, # Optim + ), + ), + all_qualified_accesses_via_owners = (; + ignore = (:isvariable,), # ModelingToolkit.isvariable (owner ModelingToolkitBase) + ), + ), # The umbrella `using DataDrivenDiffEq` pulls its public surface in implicitly; # making every name explicit is a large refactor tracked separately. ei_broken = (:no_implicit_imports,) diff --git a/lib/DataDrivenSR/src/DataDrivenSR.jl b/lib/DataDrivenSR/src/DataDrivenSR.jl index 25799329..56a32af8 100644 --- a/lib/DataDrivenSR/src/DataDrivenSR.jl +++ b/lib/DataDrivenSR/src/DataDrivenSR.jl @@ -2,17 +2,14 @@ module DataDrivenSR using DataDrivenDiffEq # Load specific (abstract) types -using DataDrivenDiffEq: AbstractBasis, Difference +using DataDrivenDiffEq: Difference using DataDrivenDiffEq: AbstractDataDrivenAlgorithm using DataDrivenDiffEq: AbstractDataDrivenResult -using DataDrivenDiffEq: AbstractDataDrivenProblem -using DataDrivenDiffEq: DDReturnCode, ABSTRACT_CONT_PROB, ABSTRACT_DISCRETE_PROB +using DataDrivenDiffEq: DDReturnCode using DataDrivenDiffEq: InternalDataDrivenProblem -using DataDrivenDiffEq: is_implicit, is_controlled using DataDrivenDiffEq.DocStringExtensions using DataDrivenDiffEq.CommonSolve -using DataDrivenDiffEq.CommonSolve: solve! using DataDrivenDiffEq.StatsBase using DataDrivenDiffEq.Parameters diff --git a/lib/DataDrivenSR/test/qa/qa.jl b/lib/DataDrivenSR/test/qa/qa.jl index be531200..fea1fa30 100644 --- a/lib/DataDrivenSR/test/qa/qa.jl +++ b/lib/DataDrivenSR/test/qa/qa.jl @@ -6,6 +6,27 @@ using Test run_qa( DataDrivenSR; explicit_imports = true, + ei_kwargs = (; + all_explicit_imports_are_public = (; + # DataDrivenDiffEq non-`export`ed extension API its sublibraries build on. + ignore = ( + :AbstractDataDrivenAlgorithm, :AbstractDataDrivenResult, + :InternalDataDrivenProblem, + ), + ), + all_qualified_accesses_are_public = (; + ignore = ( + # DataDrivenDiffEq internals accessed qualified. + :assert_lhs, :get_implicit_data, :remake_problem, :_set_default_val, + :setdefaultval, # Symbolics + :Sym, # SymbolicUtils + :toparam, # ModelingToolkit + ), + ), + all_qualified_accesses_via_owners = (; + ignore = (:toparam,), # ModelingToolkit.toparam (owner ModelingToolkitBase) + ), + ), # The umbrella `using DataDrivenDiffEq` and `@reexport using SymbolicRegression` # (plus the `using DataDrivenDiffEq.` re-exports) pull those public # surfaces in implicitly; making every name explicit is a large refactor tracked diff --git a/lib/DataDrivenSparse/src/DataDrivenSparse.jl b/lib/DataDrivenSparse/src/DataDrivenSparse.jl index 22d9ee13..54e5e010 100644 --- a/lib/DataDrivenSparse/src/DataDrivenSparse.jl +++ b/lib/DataDrivenSparse/src/DataDrivenSparse.jl @@ -2,13 +2,10 @@ module DataDrivenSparse using DataDrivenDiffEq # Load specific (abstract) types -using DataDrivenDiffEq: AbstractBasis using DataDrivenDiffEq: AbstractDataDrivenAlgorithm using DataDrivenDiffEq: AbstractDataDrivenResult -using DataDrivenDiffEq: AbstractDataDrivenProblem -using DataDrivenDiffEq: DDReturnCode, ABSTRACT_CONT_PROB, ABSTRACT_DISCRETE_PROB +using DataDrivenDiffEq: DDReturnCode using DataDrivenDiffEq: InternalDataDrivenProblem -using DataDrivenDiffEq: is_implicit, is_controlled using DataDrivenDiffEq.DocStringExtensions using DataDrivenDiffEq.CommonSolve diff --git a/lib/DataDrivenSparse/src/algorithms/proximals.jl b/lib/DataDrivenSparse/src/algorithms/proximals.jl index f3099324..096487ef 100644 --- a/lib/DataDrivenSparse/src/algorithms/proximals.jl +++ b/lib/DataDrivenSparse/src/algorithms/proximals.jl @@ -136,7 +136,7 @@ ClippedAbsoluteDeviation() = ClippedAbsoluteDeviation(NaN) end function (s::ClippedAbsoluteDeviation)(x::AbstractArray, λ::T) where {T <: Real} - @unpack ρ = h + @unpack ρ = s ρ = isnan(ρ) ? convert(T, 5) * λ : convert(T, ρ) for i in eachindex(x) x[i] = abs(x[i]) > ρ ? x[i] : sign(x[i]) * max(abs(x[i]) - λ, 0) diff --git a/lib/DataDrivenSparse/src/result.jl b/lib/DataDrivenSparse/src/result.jl index b6d6a779..3e38bc47 100644 --- a/lib/DataDrivenSparse/src/result.jl +++ b/lib/DataDrivenSparse/src/result.jl @@ -20,7 +20,7 @@ is_success(k::SparseRegressionResult) = getfield(k, :retcode) == DDReturnCode(1) l2error(k::SparseRegressionResult) = is_success(k) ? getfield(k, :testerror) : Inf function l2error(k::SparseRegressionResult{<:Any, <:Any, Nothing}) - return is_success(k) ? getfield(k, :traineerror) : Inf + return is_success(k) ? getfield(k, :trainerror) : Inf end get_coefficients(k::SparseRegressionResult) = getfield(k, :coefficients) diff --git a/lib/DataDrivenSparse/test/qa/qa.jl b/lib/DataDrivenSparse/test/qa/qa.jl index c7071dfc..437da07c 100644 --- a/lib/DataDrivenSparse/test/qa/qa.jl +++ b/lib/DataDrivenSparse/test/qa/qa.jl @@ -6,6 +6,25 @@ using Test run_qa( DataDrivenSparse; explicit_imports = true, + # The `unique!`/`deleteat!` Basis methods that DataDrivenDiffEq defines on + # `Symbolics.Num`/`Symbolics.Arr` vectors are ambiguous against `Base.unique!`/ + # `Base.deleteat!`; the ambiguity is inherited from the parent package (it predates + # this conversion and Aqua was never run before), so it is marked broken here. + aqua_broken = (:ambiguities,), + ei_kwargs = (; + # DataDrivenDiffEq exposes these names as the (non-`export`ed) extension API its + # own sublibraries build on; declaring them `public` upstream is tracked separately. + all_explicit_imports_are_public = (; + ignore = ( + :AbstractDataDrivenAlgorithm, :AbstractDataDrivenResult, + :InternalDataDrivenProblem, + ), + ), + all_qualified_accesses_are_public = (; + # __construct_basis/is_implicit: DataDrivenDiffEq internals; transform: StatsBase. + ignore = (:__construct_basis, :is_implicit, :transform), + ), + ), # The umbrella `using DataDrivenDiffEq` (plus the `using DataDrivenDiffEq.` # re-exports) pulls the DataDrivenDiffEq public surface in implicitly; making every # name explicit is a large refactor tracked separately. diff --git a/src/DataDrivenDiffEq.jl b/src/DataDrivenDiffEq.jl index 64beb38d..00958f4f 100644 --- a/src/DataDrivenDiffEq.jl +++ b/src/DataDrivenDiffEq.jl @@ -6,7 +6,7 @@ module DataDrivenDiffEq using LinearAlgebra using DiffEqBase -using SciMLBase: SciMLBase, AbstractTimeseriesSolution +using SciMLBase: SciMLBase using CommonSolve using Reexport diff --git a/test/qa/Project.toml b/test/qa/Project.toml index f2acc4ba..224d8d81 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -1,4 +1,5 @@ [deps] +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" DataDrivenDiffEq = "2445eb08-9709-466a-b3fc-47e12bd697a2" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" @@ -9,6 +10,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" DataDrivenDiffEq = {path = "../.."} [compat] +Aqua = "0.8" JET = "0.9, 0.10, 0.11" SafeTestsets = "0.0.1, 0.1" SciMLTesting = "1.6" diff --git a/test/qa/qa.jl b/test/qa/qa.jl index 5ea1fb19..7b168b9f 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -1,5 +1,6 @@ using SciMLTesting using DataDrivenDiffEq +using Aqua using Test # Aqua + ExplicitImports via run_qa. JET is handled separately by jet_tests.jl: @@ -11,6 +12,49 @@ run_qa( DataDrivenDiffEq; jet = false, explicit_imports = true, + # `deleteat!`/`unique!` are defined on `Symbolics.Num`/`Symbolics.Arr` vectors in + # src/basis/type.jl as the public Basis-manipulation API. Aqua flags them as type + # piracy and, as a direct consequence, reports the resulting method ambiguities + # against `Base.unique!`/`Base.deleteat!`. `DataDrivenDataset` uses `Vararg{T, N}` + # where `N` is unbound for the zero-argument signature. All three are pre-existing + # design properties (Aqua was never run before this conversion), surfaced—not + # introduced—here, so they are marked broken rather than silenced. `aqua_broken` + # also disables each named sub-check in the `Aqua.test_all` call. + aqua_broken = (:ambiguities, :unbound_args, :piracies), + ei_kwargs = (; + # All flagged names are non-public (un-`export`ed / not `public`-declared) + # internals of upstream packages, accessed deliberately. They are owned by the + # listed modules; making them public is an upstream change tracked separately. + all_qualified_accesses_are_public = (; + ignore = ( + :NullParameters, # DiffEqBase + :Tunable, :canonicalize, # SciMLStructures + :isscimlstructure, # SciMLStructures + :derivative, # DataInterpolations + :getdefaultval, :setdefaultval, :symtype, # Symbolics + :isconst, :promote_symtype, # SymbolicUtils + :nameof, :toparam, :tovar, # ModelingToolkit / Base.nameof method + :promote_eltype, # Base + :transform!, # StatsBase + ), + ), + all_explicit_imports_are_public = (; + ignore = ( + :Operator, # Symbolics (owner SymbolicUtils): `Difference <: Operator` + :issym, # SymbolicUtils + ), + ), + # `Operator` is re-exported by Symbolics from SymbolicUtils; importing it via the + # `Symbolics` namespace is intentional (Symbolics is the user-facing surface here). + all_explicit_imports_via_owners = (; + ignore = (:Operator,), + ), + # `NullParameters`/`nameof`/`symtype`/`toparam`/`tovar` are accessed through a + # re-exporting/owning namespace rather than `Base.which`'s reported owner. + all_qualified_accesses_via_owners = (; + ignore = (:NullParameters, :nameof, :symtype, :toparam, :tovar), + ), + ), # The `@reexport using ModelingToolkit/StatsBase/DataInterpolations/MLUtils/CommonSolve` # surface is pulled in implicitly by design (this package re-exports it); making every # name explicit is a large refactor tracked separately.