Skip to content

Commit c2e8431

Browse files
ChrisRackauckas-ClaudeChrisRackauckasclaude
authored
Fix Runic format check: add return in test/runtests.jl core_body() (#218)
* Apply Runic formatting to test/runtests.jl The Runic Format Check on main fails because core_body()'s final expression (the Layers Tests @safetestset) is missing the explicit return that Runic requires. Add it to make the format check pass. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Restore LuxCUDA test dependency dropped during v1.2 CI conversion The grouped-tests v1.2 conversion (#217) dropped LuxCUDA from the test [extras]/[targets]. The self-hosted GPU lane sets BACKEND_GROUP=CUDA, which makes test/shared_testsetup.jl do `using LuxCUDA`; without the dependency the GPU job errors with `ArgumentError: Package LuxCUDA not found in current path`. Re-add LuxCUDA (compat 0.3) to [compat], [extras], and the test target, using the correct registry UUID d0bbae9a-e099-4d5b-a835-1c6931763bda (the pre-conversion Project.toml had carried a typo'd UUID ...1c6931f17571). Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix MNIST docs build: steady-state adjoint VJP shape + missing VCAB3 import The Documentation build failed on two genuine bugs in the basic MNIST DEQ tutorial (both reproduce on `main`, independent of the test/Project.toml changes in this PR): 1. `DimensionMismatch` in the steady-state adjoint VJP. For a conv DEQ the rootfind state is a 4D array (e.g. `(13, 13, 64, 2)`). When the state has more than 50 elements, SciMLSensitivity's `SteadyStateAdjoint` takes the matrix-free `VecJacOperator` path and builds the operator from `vec(y)`, so it seeds the residual's pullback with a *flat* cotangent. Zygote's `ProjectTo` then rejects that flat cotangent when it is broadcast against the multi-dimensional `u` in the residual `y .- u`, raising `variable with size(x) == (13,13,64,2) cannot have a gradient with size(dx) == (21632,)`. The Core test suite never hit this because its conv states are <= 50 elements (dense-Jacobian path). Fix: compute the residual in flattened space, `reshape(vec(y) .- vec(u), size(u))` — a value-preserving no-op that keeps the broadcast operands consistent with the flat cotangent. 2. `UndefVarError: VCAB3`. The tutorial calls `VCAB3()` but only imports `OrdinaryDiffEq`, which (v7) no longer re-exports `VCAB3`. Added `OrdinaryDiffEqAdamsBashforthMoulton` to the docs project and an explicit `using OrdinaryDiffEqAdamsBashforthMoulton: VCAB3` in the tutorial. Verified locally on Julia 1.12: - Full `docs/make.jl` builds end-to-end (both MNIST `@example` blocks run; only a transient ColPrac linkcheck 429 from the sandbox differs from CI). - `GROUP=Core Pkg.test()` passes: Utils 11/11, Layers 1538/1538. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: ChrisRackauckas-Claude <accounts@chrisrackauckas.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 0cca4d0 commit c2e8431

5 files changed

Lines changed: 13 additions & 4 deletions

File tree

Project.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "DeepEquilibriumNetworks"
22
uuid = "6748aba7-0e9b-415e-a410-ae3cc0ecb334"
33
authors = ["Avik Pal <avikpal@mit.edu>"]
4-
version = "2.7.0"
4+
version = "2.7.1"
55

66
[deps]
77
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
@@ -37,6 +37,7 @@ GPUArraysCore = "0.1, 0.2"
3737
SafeTestsets = "0.1"
3838
InteractiveUtils = "<0.0.1, 1"
3939
Lux = "1"
40+
LuxCUDA = "0.3"
4041
LuxCore = "1"
4142
LuxTestUtils = "1, 2"
4243
MLDataDevices = "1"
@@ -67,6 +68,7 @@ Functors = "d9f16b24-f501-4c13-a1f2-28368ffc5196"
6768
GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527"
6869
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
6970
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
71+
LuxCUDA = "d0bbae9a-e099-4d5b-a835-1c6931763bda"
7072
LuxTestUtils = "ac9de150-d08f-4546-94fb-7472b5760531"
7173
MLDataDevices = "7e8f7934-dd98-4c1a-8fe8-92b47a384d40"
7274
NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
@@ -80,4 +82,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
8082
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
8183

8284
[targets]
83-
test = ["Aqua", "Documenter", "ExplicitImports", "ForwardDiff", "Functors", "GPUArraysCore", "InteractiveUtils", "LuxTestUtils", "MLDataDevices", "NLsolve", "NonlinearSolve", "OrdinaryDiffEq", "OrdinaryDiffEqAdamsBashforthMoulton", "SafeTestsets", "SciMLSensitivity", "SciMLTesting", "StableRNGs", "Test", "Zygote"]
85+
test = ["Aqua", "Documenter", "ExplicitImports", "ForwardDiff", "Functors", "GPUArraysCore", "InteractiveUtils", "LuxCUDA", "LuxTestUtils", "MLDataDevices", "NLsolve", "NonlinearSolve", "OrdinaryDiffEq", "OrdinaryDiffEqAdamsBashforthMoulton", "SafeTestsets", "SciMLSensitivity", "SciMLTesting", "StableRNGs", "Test", "Zygote"]

docs/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
1212
OneHotArrays = "0b1bfda6-eb8a-41d2-88d8-f5af5cad476f"
1313
Optimisers = "3bd65402-5787-11e9-1adc-39752487f4e2"
1414
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
15+
OrdinaryDiffEqAdamsBashforthMoulton = "89bda076-bce5-4f1c-845f-551c83cdda9a"
1516
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
1617
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1718
SciMLSensitivity = "1ed8b502-d754-442c-8d5d-10ac956f44a1"
@@ -31,6 +32,7 @@ NonlinearSolve = "3, 4"
3132
OneHotArrays = "0.2"
3233
Optimisers = "0.3, 0.4"
3334
OrdinaryDiffEq = "6, 7"
35+
OrdinaryDiffEqAdamsBashforthMoulton = "1, 2"
3436
Random = "1"
3537
SciMLSensitivity = "7"
3638
Setfield = "1"

docs/src/tutorials/basic_mnist_deq.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ We will train a simple Deep Equilibrium Model on MNIST. First we load a few pack
55
```@example basic_mnist_deq
66
using DeepEquilibriumNetworks, SciMLSensitivity, Lux, NonlinearSolve, OrdinaryDiffEq,
77
Random, Optimisers, Zygote, LinearSolve, Dates, Printf, Setfield, OneHotArrays
8+
using OrdinaryDiffEqAdamsBashforthMoulton: VCAB3
89
using MLDatasets: MNIST
910
using MLUtils: DataLoader, splitobs
1011
using LuxCUDA # For NVIDIA GPU support

src/layers.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,11 @@ function (deq::DEQ)(x, ps, st::NamedTuple, ::Val{false})
128128
# The type-assert is needed because of an upstream Lux issue with type stability of
129129
# conv with Dual numbers
130130
y = model((u, p.x), p.ps)::typeof(u)
131-
return y .- u
131+
# Subtract in flattened space: the matrix-free SteadyStateAdjoint VJP seeds the
132+
# residual pullback with a flat cotangent (it builds the operator from `vec(y)`),
133+
# which Zygote's `ProjectTo` rejects when broadcasting against a multi-dim `u`
134+
# (e.g. a conv state). `vec`/`reshape` round-trip is a no-op on the value.
135+
return reshape(vec(y) .- vec(u), size(u))
132136
end
133137

134138
prob = construct_prob(deq.kind, ODEFunction{false}(dudt), z, (; ps = ps.model, x))

test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ using SafeTestsets
77
# cannot be expressed as a separate folder of files. Hence explicit-args run_tests.
88
function core_body()
99
@safetestset "Utils Tests" include("utils_tests.jl")
10-
@safetestset "Layers Tests" include("layers_tests.jl")
10+
return @safetestset "Layers Tests" include("layers_tests.jl")
1111
end
1212

1313
run_tests(;

0 commit comments

Comments
 (0)