Skip to content

Fix restructure pullback source projection - #507

Draft
ChrisRackauckas-Claude wants to merge 1 commit into
JuliaArrays:masterfrom
ChrisRackauckas-Claude:codex/fix-restructure-pullback-shape
Draft

Fix restructure pullback source projection#507
ChrisRackauckas-Claude wants to merge 1 commit into
JuliaArrays:masterfrom
ChrisRackauckas-Claude:codex/fix-restructure-pullback-shape

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor

Summary

Project restructure pullback cotangents into the differentiated source's tangent space instead of the target's. The existing rule fails whenever target and src have different array shapes, including SciMLSensitivity's mixed GPU/CPU adjoint test with matrix parameters.

Ignore this PR until reviewed by @ChrisRackauckas.

Root cause

restructure(target, src) returns values from src arranged like target. Its pullback reconstructs the output cotangent into src's layout, but then applies ProjectTo(target). A flat source and matrix target therefore produce a flat cotangent that the matrix projector rejects.

The rule must project with ProjectTo(src): the third pullback result is the cotangent of the third argument.

Failing before

The added ChainRules test uses a 2×2 matrix target and length-4 vector source. On clean master at 97b9fe8, the full Core group reached the new test and failed:

$ GROUP=Core julia +release --project=. -e 'using Pkg; Pkg.test()'
test_rrule: restructure on Matrix{Float64},Vector{Float64}: Error During Test
DimensionMismatch: variable with size(x) == (2, 2) cannot have a gradient with size(dx) == (4,)
Test Summary: | Pass  Error  Total
ChainRules    |   26      1     27
ERROR: Some tests did not pass: 26 passed, 0 failed, 1 errored, 0 broken.

Passing after

The same full group passes with the source projector:

$ GROUP=Core julia +release --project=. -e 'using Pkg; Pkg.test()'
Test Summary: | Pass  Total   Time
ChainRules    |   29     29  24.7s
Test Summary: | Pass  Total  Time
FillArrays    |    7      7  0.0s
Testing ArrayInterface tests passed

$ GROUP=Core julia +lts --project=. -e 'using Pkg; Pkg.test()'
Test Summary: | Pass  Total   Time
ChainRules    |   29     29  16.6s
Test Summary: | Pass  Total  Time
FillArrays    |    7      7  0.0s
Testing ArrayInterface tests passed

The exact CPU analogue of SciMLSensitivity's failing matrix-parameter BacksolveAdjoint(autojacvec = ZygoteVJP()) path also passes against this checkout and agrees with ForwardDiff:

matrix_parameter_gradient_pass relerr=4.4129021327423305e-9

Additional verification

$ julia +release -e '<JuliaFormatter SciMLStyle check>' ext/ArrayInterfaceChainRulesCoreExt.jl test/chainrules.jl
# exit 0

$ typos ext/ArrayInterfaceChainRulesCoreExt.jl test/chainrules.jl
# exit 0

$ git diff --check
# exit 0

The repository has no QA test group. An additional direct Aqua.test_all(ArrayInterface) run failed only its stale-dependency check for Adapt. Independent audit showed that this is an extension-awareness false positive: the base load intentionally omits Adapt, while loading GPUArraysCore activates ArrayInterfaceGPUArraysCoreExt, which imports and uses it. The CUDA job was not run locally because this host has no NVIDIA device. ArrayInterface's existing downstream CI covers SciMLSensitivity Core1–Core5.

Links

🤖 Generated with Codex CLI 0.151.0 (model: gpt-5.6-sol; session: local session ID 01a0598f-11b9-72d1-91d9-b2fbb186557d).

Project the reconstructed cotangent into the differentiated source's tangent
space so sources and targets with different shapes have a valid pullback.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Agent-Harness: Codex CLI 0.151.0
Agent-Model: gpt-5.6-sol
Agent-Session: local session ID 01a0598f-11b9-72d1-91d9-b2fbb186557d
@codecov

codecov Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.35%. Comparing base (97b9fe8) to head (defe995).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #507   +/-   ##
=======================================
  Coverage   61.35%   61.35%           
=======================================
  Files          16       16           
  Lines         634      634           
=======================================
  Hits          389      389           
  Misses        245      245           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor Author

CI triage: the failed Julia 1.10 all-dependencies downgrade job is an unchanged base-branch failure, not a failure of this pullback change.

The current run fails while resolving the minimum dependency set: ArrayInterfaceChainRulesExt cannot precompile against ChainRules 1.35 because OneElement is undefined, then the Core test reaches an undefined ComponentVector from ComponentArrays 0.1. The previous merged PR's downgrade run has the identical two errors and the identical Core summary (220 passed, 1 errored).

The normal current-Julia Linux/macOS/Windows Core jobs pass on this PR. I have queued the pre-existing downgrade defect for a separate root-cause investigation so it is not mixed into this focused ChainRules pullback fix.

Links:

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.

2 participants