Skip to content

Type the power series input dicts in wronskian (fixes Core tests on TimerOutputs v1) - #558

Merged
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:fix/wronskian-typed-dicts
Sep 12, 2026
Merged

ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:fix/wronskian-typed-dicts

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member

Closes #556.

What changed and why

wronskian built the param_values / initial_conditions / input_values arguments of
power_series_solution with untyped dict comprehensions. TimerOutputs v1's @timeit emits
the wrapped body twice (inside if enabled … else … end), and that duplication makes Julia's
closure conversion box the locals those comprehensions capture — so their element types stop
inferring. For any model with no inputs the empty comprehension then produces
Dict{Any, Any} and power_series_solution has no matching method.

Spelling the element types out fixes the dispatch and is independent of whatever @timeit
does to the surrounding scope. Only src/wronskian.jl is touched; no behavior change for
models that do have inputs.

Full analysis, standalone TimerOutputs MWE and the registry timeline are in #556.

Verification

Julia 1.12.7, environment resolved with Pkg.update() (picks TimerOutputs v1.2.1,
RationalFunctionFields v0.3.5), ModelingToolkit master Pkg.developed in exactly as
ModelingToolkit.jl/.github/workflows/Downstream.yml does.

Failing before the fix

GROUP=Core julia +1.12 --project=StructuralIdentifiability.jl -e 'using Pkg; Pkg.test()'
on unmodified master (90f8452a61109fe29e434d604bd22ad80d474fdd):

Assessing identifiability: Error During Test at test/bodies/identifiability.jl:3
  Got exception outside of a @test
  MethodError: no method matching power_series_solution(::ODE{Nemo.fpMPolyRingElem}, ::Dict{Nemo.fpMPolyRingElem, Int64}, ::Dict{Nemo.fpMPolyRingElem, Int64}, ::Dict{Any, Any}, ::Int64)

  Closest candidates are:
    power_series_solution(::ODE{P}, ::Dict{P, Int64}, ::Dict{P, Int64}, !Matched::Dict{P, Vector{Int64}}, ::Int64) where P<:(MPolyRingElem{<:FieldElem})
     @ StructuralIdentifiability src/ODE.jl:202
    ...
  Stacktrace:
    [1] wronskian(io_equations::Dict{QQMPolyRingElem, QQMPolyRingElem}, ode::ODE{QQMPolyRingElem})
        @ StructuralIdentifiability src/wronskian.jl:218

Test Summary:                 | Error  Total   Time
Core/identifiability.jl       |     1      1  35.5s
ERROR: Package StructuralIdentifiability errored during testing

The group aborts there, so nothing after identifiability.jl runs at all.

Passing after the fix

Same command, same environment, with this branch:

Core/identifiability.jl |   11     11  2m13.7s
Core/identifiable_functions.jl |  800    800  37m14.5s
Core/io_cases.jl |    6      6  0.4s
...
Core/y_saturation.jl |    9      9  4m14.2s
     Testing StructuralIdentifiability tests passed

All 39 Core files pass; every one of them is new coverage relative to the current master
run, which never got past identifiability.jl.

QA

GROUP=QA julia +1.12 --project=StructuralIdentifiability.jl -e 'using Pkg; Pkg.test()'

Test Summary: | Pass  Total     Time
QA/qa.jl      |   21     21  1m36.9s
     Testing StructuralIdentifiability tests passed

Formatting / spelling

Runic.main(["--check", "src/wronskian.jl"]) → exit 0. typos src/wronskian.jl → clean.

What I did not verify

  • The Downgrade and 32-bit (Core 32-bit) lanes — not run locally.
  • The ModelingToolkitSIExt group — not run locally (it precompiled cleanly during the QA run).
  • The docs build — this PR touches no docstring, docs/, or public API.

Note for the reviewer

The underlying defect is in TimerOutputs v1's @timeit, not here; this is a targeted
workaround at the one call site whose dispatch depends on the dict type. The Core.Box
that @timeit introduces is present in every @timeit-annotated function in src/
and is silently costing inference elsewhere, so an upstream fix is still worth chasing —
see #556 for the standalone MWE to file with TimerOutputs.jl.

The alternative fix would be to cap TimerOutputs = "0.5.10" again, but #548 relaxed that
deliberately to resolve a Groebner conflict, so re-capping would reintroduce it.

Please ignore until reviewed by @ChrisRackauckas.

🤖 Generated with Claude Code (model: claude-opus-5[1m])

https://claude.ai/code/session_01GdSpCLd7NBZuuePJmcDzU7

TimerOutputs v1's `@timeit` emits the wrapped body twice, inside an
`if enabled ... else ... end`. The duplication makes Julia's closure conversion
box the locals that the dict comprehensions capture, so their element types no
longer infer. For a model with no inputs the empty comprehension then produces
`Dict{Any, Any}` and `power_series_solution` fails to dispatch.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GdSpCLd7NBZuuePJmcDzU7
@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member Author

Downstream mirror: ModelingToolkit's failing job, reproduced and fixed locally

Exactly the configuration of ModelingToolkit.jl/.github/workflows/Downstream.yml
(StructuralIdentifiability.jl/Core/1/): MTK master Pkg.developed into this project plus
its lib/* subpackages, Pkg.update(), GROUP=Core Pkg.test(), Julia 1.12.7.

Before (master 90f8452a61109fe29e434d604bd22ad80d474fdd):

Test Summary:                 | Error  Total   Time
Core/identifiability.jl       |     1      1  35.5s
ERROR: Package StructuralIdentifiability errored during testing

After (this branch, same environment):

Core/y_saturation.jl |    9      9  4m15.2s
     Testing StructuralIdentifiability tests passed

45 test files, 0 errors. So merging this turns
https://github.com/SciML/ModelingToolkit.jl/actions/runs/34395760914/job/102614954099 green
without any change to ModelingToolkit.

Docs build

Master's docs build is broken by this same bug — julia +1.12 --project=docs docs/make.jl
on unmodified master gives three doctest failures, all
MethodError: no method matching power_series_solution(…, ::Dict{Any, Any}, ::Int64):

┌ Error: doctest failure in src/parametrizations.jl:165-183
┌ Error: doctest failure in src/observation_field.jl:22-37
┌ Error: doctest failure in src/identifiable_functions.jl:33-46

The same command on this branch, same package versions, exits 0 with no doctest failures.

The two red CI checks are both pre-existing and unrelated

tests / Core (julia 1, ubuntu-latest, x86) — fails during precompilation, not in any
test: MethodError: no method matching crt_precompute!(::BigInt, ::BigInt, ::BigInt, ::Vector{BigInt}, ::Vector{UInt64})
from Groebner on 32-bit. It has failed the same way since the lane was added, and #554 was
merged with it red:
https://github.com/SciML/StructuralIdentifiability.jl/actions/runs/34163517295/job/101771799884

Documentation — fails on src/lincomp.jl:35-44, purely equation ordering
(x4' x3' x1' x2' vs the documented x1' x3' x2' x4'). That job runs Julia 1.13.0,
which changed Dict iteration order. On unmodified master:

julia +1.12 → ORDER: x1' x3' x2' x4' y1     (matches the doctest)
julia +1.13 → ORDER: x4' x3' x1' x2' y1     (matches what CI printed)

No source from this PR is involved — linear_compartment_model never calls wronskian.
Master's docs build simply dies earlier, on the power_series_solution failures above, so
this ordering failure only becomes reachable once those are fixed. Filed separately as #559.

Green checks

Core (julia 1), Core (julia lts), Core (julia pre), QA (julia 1),
ModelingToolkitSIExt (julia 1), Downgrade (Core), Runic Format Check,
Runic Suggestions, Spell Check.

🤖 Generated with Claude Code (model: claude-opus-5[1m])

https://claude.ai/code/session_01GdSpCLd7NBZuuePJmcDzU7

@ChrisRackauckas
ChrisRackauckas marked this pull request as ready for review September 12, 2026 15:48
@ChrisRackauckas
ChrisRackauckas merged commit 3003b7a into SciML:master Sep 12, 2026
10 of 12 checks passed
ChrisRackauckas added a commit that referenced this pull request Sep 13, 2026
- Add AirspeedVelocity benchmarking CI (#562)
- Type the power series input dicts in wronskian (#558)



Agent-Harness: Claude Code
Agent-Model: claude-opus-5[1m]
Claude-Session: https://claude.ai/code/session_014FEzNTLFutCmTEAZ3zBg5R

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Core tests fail with TimerOutputs v1: MethodError from Dict{Any,Any} in wronskian (models with no inputs)

2 participants