Repository navigation
GML part M5: layers and architectures share one method per Q/P pair, Bool choice and triangle - #351
Conversation
…Bool choice and triangle - _shift(Val(C), z, f) serves the Q/P pairs of the SympNet, symplectic attention and linear symplectic attention layers; every Bool keyword picks a Symbol type parameter in one expression, and ResNetLayer encodes its bias as :bias/:no_bias. - VolumePreservingFeedForwardLayer is the one struct of the lower and upper layers, whose initialparameters takes init_bias. - MultiHeadAttention has one initialparameters, keeps its draw order, and builds no head key per forward pass. - LASympNet has one Chain; _gradient_layers serves GSympNet, LST and ST; the DataLoader constructors delegate; GSympNet.activation; one encoder and decoder per AutoEncoder. - LinearSymplecticTransformer keeps its activation; upscaling_activation is spelled right; PositionalEncoding allocates on the backend of its input. - Pins against 4c4a832 at 8 ULPs, structure tests and forward inference tests. Closes known issues B11, C19 and K5. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The three merged SympNet forward methods check size(x.q, 1) == M ÷ 2 again, as the parent does; a dimension-2 activation layer broadcast a half of any length without it. The MHA forward pass finds each head by its name head_i from a generated constant tuple, so a reordered parameter set gives the parent's output and no key is built per pass. Tests for both, the LASympNet Chain signature on one line, the out-of-scope comment path restored, and known issues K20 and K21 recorded. Co-Authored-By: Claude Opus 5.5 <[email protected]>
K20 is a late finding about a field name, and the architectures with several activations name them with a prefix. K22 records the measured behaviour of a p of the wrong size: an error from the product or the unbroadcast +, never a value. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…23, K24 The verifier found that the headline and the header of test/layers/layer_structure.jl claimed every layer encodes its choices as a Symbol, while MultiHeadAttention and ClassificationLayer keep Bool parameters. K23 (decoder block count) and K24 (transformer docstrings) are present on 4c4a832. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…c4a832 Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Shared layer types and dispatch src/layers/*, test/layers/layer_structure.jl |
Layer constructors, parameter initialization, and Q/P forward methods use consolidated type parameters and shared dispatch. GradientLayer.second_dim is restricted to Int, and SympNet constructors convert dimensions to Int. |
Backend encoding and attention paths src/layers/multi_head_attention.jl, src/layers/positional_encoding.jl, src/layers/transformer.jl, test/layers/* |
Multi-head attention uses shared initialization helpers and compile-time head keys. Positional encoding creates its matrix on the input backend. Tests cover device-backed encoding, attention allocation, and inference with 32 heads. |
Architecture construction and wrapper dispatch src/architectures/*, test/architectures/architecture_structure.jl, test/integration/documented_defaults.jl |
Architecture builders use shared gradient-layer construction and unified encoder/decoder wrapper selection. The transformer integrator field is renamed to upscaling_activation; DataLoader constructors forward to dimension-based or positional constructors. |
Pinned outputs and inference coverage test/helpers/*, test/layers/layer_pins.jl, test/architectures/architecture_pins.jl, test/architectures/forward_inference.jl, test/runtests.jl |
Tests compare seeded layer, architecture, encoder, and decoder outputs with recorded pins. They also check output element types, inference, and expected LASympNet layer sequences. |
Release and issue records CHANGELOG.md, KNOWN_ISSUES.md |
The changelog records API and implementation changes. The known-issues file removes entries about positional encoding and duplicate architecture builders and adds entries for remaining issues. |
Priority:
Estimated code review effort: 4 (Complex) | ~60 minutes
Change: Refactor · Severity of issue fixed: Low
Merge Risk: 
Minimal · up to 52a01
-
The decoder metadata mismatch remains a pre-existing issue. This change is mergeable on the reviewed evidence.
Pre-merge checks: 
5
-
Full details: Docstring Coverage
-
Explanation
No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (11 skipped: 11 unsupported.)
Full details: Description check
-
Explanation
The pull request description directly covers the layer and architecture simplifications, bug fixes, backend allocation changes, breaking changes, tests, validation results, and known limitations shown in the changeset.
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
92ffaa16-27f6-49ca-9fd9-8942f33614e7
📒 Files selected for processing: 29
CHANGELOG.mdKNOWN_ISSUES.mdsrc/architectures/autoencoder.jlsrc/architectures/linear_symplectic_transformer.jlsrc/architectures/standard_transformer_integrator.jlsrc/architectures/symplectic_autoencoder.jlsrc/architectures/symplectic_transformer.jlsrc/architectures/sympnet.jlsrc/layers/linear_symplectic_attention.jlsrc/layers/multi_head_attention.jlsrc/layers/positional_encoding.jlsrc/layers/psd_like_layer.jlsrc/layers/resnet.jlsrc/layers/symplectic_attention.jlsrc/layers/sympnets.jlsrc/layers/transformer.jlsrc/layers/volume_preserving_attention.jlsrc/layers/volume_preserving_feedforward.jltest/architectures/architecture_pins.jltest/architectures/architecture_structure.jltest/architectures/forward_inference.jltest/helpers/pinned_outputs.jltest/helpers/pins.jltest/integration/documented_defaults.jltest/layers/layer_pins.jltest/layers/layer_structure.jltest/layers/multi_head_attention_allocation.jltest/layers/positional_encoding.jltest/runtests.jl
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
# Conflicts: # CHANGELOG.md # KNOWN_ISSUES.md
- Pins compare at 16 ULPs of the pinned vector's largest magnitude, and a failure prints the measured deviation (pin_ulps), as decided for M5. - ClassificationTransformer(dl) calls the dimension constructor, as in #350. - ActivationLayerQ/P and LinearLayerQ/P convert the dimension to Int, as in #349, so an Int32 dimension names the same layer. - Tests: the Stiefel branch of the MHA initialisation and its draw order; inference at 32 heads (layer and StandardTransformerIntegrator(32)); the alias test reads the source, because Julia drops an unused alias variable; the stale header of the MHA inference test; a narrower name for the Bool-ladder testset. Co-Authored-By: Claude Opus 5.5 <[email protected]>
michakraus
left a comment
There was a problem hiding this comment.
Review of 52a01a8
Verdict: request changes (posted as a comment review, because the author is the account owner).
Findings
| # | severity | file:line | claim | evidence |
|---|---|---|---|---|
| 1 | bug (from CodeRabbit, accepted) | src/architectures/autoencoder.jl:236 |
decoder(::NeuralNetwork{<:AutoEncoder}) passes arch.n_encoder_blocks into the field n_decoder_blocks of UnknownDecoder / UnknownSymplecticDecoder. The PR rewrites this line and keeps the defect. Its reason, "kept so that the outputs stay unchanged", does not hold: nothing reads the field. |
Fields: autoencoder.jl:113 and :125 are n_decoder_blocks. decoder_model reads arch.n_decoder_blocks through compute_decoder_iterations (:140), and decoder_parameters counts the layers of decoder_model (:172). A grep of src/ finds no read of n_decoder_blocks on a Decoder. Probe on the head: a custom AutoEncoder with (6, 2, 2, 3) gives UnknownDecoder(6, 2, 2) with 2 decoder layers, which is what 3 decoder blocks build. With the method redefined to pass arch.n_decoder_blocks, the four decoder pin outputs are identical before and after, at 0.0 ULPs from AUTOENCODER_PINS. |
| 2 | quality | src/layers/symplectic_attention.jl:131, src/layers/sympnets.jl:225-239, src/architectures/linear_symplectic_transformer.jl:22, src/architectures/symplectic_transformer.jl:35, src/architectures/symplectic_autoencoder.jl:36, src/architectures/autoencoder.jl:102,108 |
The PR records five existing defects as known issues (K22, K23, K25, K26, K27) instead of fixing them. Each one is in code that the diff rewrites, or is the docstring of that code. Each fix changes one comment, one docstring line, or one check, and moves no output. K23's own entry says that its fix changes only the message of an error that is raised already. | KNOWN_ISSUES.md K22-K27 at the head, and the diff hunks at those locations: the comment at :131 sits directly above the rewritten symmetric forward method; the three rewritten SympNet forward methods each keep the size(x.q, 1) check alone; the Chain builders of both transformers and the SymplecticAutoencoder constructor are rewritten; UnknownDecoder is the type that finding 1's line builds. |
| 3 | quality | PR body | The PR body does not describe the head. (a) It says that the pins compare at 8 ULPs, but test/helpers/pins.jl:24 is const PIN_ULPS = 16. (b) It numbers the new known issues K20-K26, but the file has K21-K27, and K20 is the existing DataLoader((q = ..., p = ...)) entry. (c) It says that "the two commits after the critic's PASS change text only", but 52a01a8 changes src/layers/sympnets.jl (the Int conversions) and src/architectures/transformer_neural_network.jl (the ClassificationTransformer(dl) delegation). The critic verdict on 179d093 therefore does not cover the head. (d) It lists the Bool-ladder testset name as unresolved, but 52a01a8 renames that testset. |
git show --stat 52a01a88; grep -n '^### ' KNOWN_ISSUES.md; pins.jl:24. |
| 4 | quality | KNOWN_ISSUES.md (B11 removal), test/devices/metal.jl |
B11 is closed on a JLArray proxy. The proxy cannot show B11's failure: the test's own comment says that a broadcast on a JLArray also reads a host matrix, so it checks the type of the encoding instead. The metal group does not run PositionalEncoding, so no real device runs the layer whose GPU failure B11 recorded. One forward pass in test/devices/metal.jl closes this. |
grep -rn PositionalEncoding test/devices/ gives no hit. The testset at test/layers/positional_encoding.jl:165-184 runs on JLArray only; see its comment at :173-174. |
| 5 | nit | KNOWN_ISSUES.md K23 location |
The location src/layers/sympnets.jl:224 is a blank line at the head. The check is at :226. The two comment lines that 52a01a8 adds at :153-154 moved it. Name the function, not the line. |
sed -n 224p src/layers/sympnets.jl prints an empty line. |
CodeRabbit
- Inline comment on
autoencoder.jl:236(id 4335228541): accepted. This is finding 1. I checked each part of the claim at 52a01a8. The PR rewrites that line: true. The third argument fillsn_decoder_blocksof both decoder types: true (:113,:125).decoder_modelanddecoder_parametersreadn_decoder_blocks: true. No pin moves: true, because the decoder pin outputs are bit-identical with the fix applied. "KNOWN_ISSUES.mdK23 records this defect": this was true at c03002a, which CodeRabbit reviewed. At the head, the entry is K24, and K23 is the SympNet half-size check. When the fix lands, K24 leaves the file, and K27 (theUnknownDecoderdocstring) should leave with it. In practice,PSDArchalways has 2 and 2 blocks andSymplecticAutoencoderhas its owndecoder, so only a user-definedAutoEncodershows the wrong field. - Summary comment: rejected where it states a fact. "Architecture and encoder/decoder outputs are corrected" is not true. The 88 pinned outputs (layers, architectures, encoders and decoders, in
Float32andFloat64) hash identically onmain(e759f20) and on the head. The summary has no other actionable claim.
Verified, and the result held
- Outputs do not change. I ran the PR's
layer_pins.jlandarchitecture_pins.jlagainstmaine759f20 and against the head, each in its own environment that develops that tree (Julia 1.13.2, arm64). Both pass 202/202. All 88 outputs hash identically on the two trees, so they are bit-identical here, not only within 16 ULPs. - MHA key allocations, measured with
--check-bounds=autoin one cold process per tree, minimum of 3 runs of 1000 passes: onmain, the forward pass allocates 192 000 B (1 head) and 384 000 B (2 heads) more than the constant-key reference. On the head, the difference is 0 B for both. The CHANGELOG figure reproduces. - Test files that the PR adds or reaches, run on the head through
run-tests.jl(Julia 1.13.2):layer_structure,architecture_structure,positional_encoding,multi_head_attention_allocation,multi_head_attention_inference,forward_inference,symplectic_attention_network_parameters_gradient,resnet_tests,volume_preserving_feedforward,sympnet_layers_test,gradient_layer_tests,transformer_gradient,linear_symplectic_transformer,symplectic_transformer_chain,integration/documented_defaults,quality/aqua. 844/844 pass. _gradient_layersalternation is the same as the oldis_upper_criterionfor bothinit_uppervalues. The LST and ST builders repeat one tuple where the old code restarted the count in each block, so the layers are the same.- RNG draw order in the merged
initialparametersof ResNet, VPFF and MHA is weight before bias, and per head Q, K, V. This is the same as onmain, and the bit-identical pins confirm it. - Renamed names have no stale callers: no
init_bias!,upsacling,_make_block_for_initializationor GSympNet.actinsrc,test,docs,scripts,extorREADME.md. Thedocs/@asserts onVolumePreservingLowerLayer{...}still hold through the 4-parameter alias.
CI, read from the jobs
- Downgrade - ubuntu-latest: known red, not caused by this PR.
julia-downgrade-compatforcedeps fails before any test runs: GPUArraysCore 0.2.1 > 0.2.0, Zygote 0.7.5 > 0.7.0, ChainRulesCore 1.25.1 > 1.0.0, NNlib 0.9.30 > 0.8.0, KernelAbstractions 0.9.38 > 0.9.0. The same five errors occur onmaine759f20 (run 39978614949). The PR does not touchProject.toml. - Julia nightly - ubuntu-latest (1.15.0-DEV.111): known red, not caused by this PR. GPUCompiler fails to precompile with "UndefVarError:
libLLVMExtranot defined inLLVM.API", Metal is skipped, and the job dies before any test.mainfails the same way on 1.15.0-DEV.100. - Julia pre - ubuntu-latest (1.14): the same GPUCompiler precompile failure, also on
main. Known red, not caused by this PR. - Doctests, Metal (Julia 1) and Metal (Julia min) pass. Julia 1 and Julia min on ubuntu, macOS and windows, Documentation and Scripts were still pending at the time of this review. These jobs are the only cross-platform check of the 16-ULP pin tolerance.
Not checked
PositionalEncodingon Metal: my local Metal session stalled before it ran.- Inference and the suite on the 1.12 floor: the pending
Julia minjobs cover this. - The need to widen the tolerance from 8 to 16 ULPs: on arm64 the outputs are bit-identical to
main. The need is on other platforms, which the pending Linux and Windows jobs show.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #351 +/- ##
==========================================
+ Coverage 87.10% 91.61% +4.50%
==========================================
Files 58 58
Lines 1342 1228 -114
==========================================
- Hits 1169 1125 -44
+ Misses 173 103 -70 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
decoder(nn::NeuralNetwork{<:AutoEncoder}) passes arch.n_decoder_blocks to UnknownDecoder and UnknownSymplecticDecoder, where it passed arch.n_encoder_blocks (CodeRabbit comment, review finding 1, known issue K24). The model and the parameters already read the decoder count, so no pinned output moves.
The three SympNet forward methods on a (q, p) input check size(x.q, 1) == size(x.p, 1) == M / 2, so a p of the wrong size raises the layer's own Dimension mismatch error (known issue K23). Both defects are present on main. Tests in architecture_pins.jl and layer_structure.jl; both K entries leave KNOWN_ISSUES.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review findings: resolution after 3e9b7adThis resolves each finding of the review on 52a01a8 by its number. Commit 3e9b7ad is pushed to
CodeRabbit
CI on 52a01a8
🤖 Generated with Claude Code |
Summary
Part M5 of the GeometricMachineLearning 0.9 simplification: the layers and architectures share one method where a pair differed in one choice, four bugs are fixed, the multi-head attention builds its head keys once, and
PositionalEncodingallocates on the backend of its input. The outputs do not change.This pull request is the one M5. It combines the three builds of the part, and #349 and #350 are closed in its favour. The basis is this branch, because its
MultiHeadAttentionmaps over1:n_headswith_head_keys(Val(N))and infers at every head count; #349 and #350 inferAnyfrom 32 heads, which is the default ofStandardTransformerIntegrator(32). From #350 come theClassificationTransformer(dl)delegation and its keyword test. From #349 comes theIntconversion of the dimension in the SympNet layer constructors._shift(Val(C), z, f), addsfof one half of a(q, p)input to the other half:src/layers/sympnets.jlhas 3 forward methods on a(q, p)input where it had 6,symplectic_attention.jl2 where it had 4,linear_symplectic_attention.jl1 where it had 2. Each of the three SympNet forward methods keeps the layer's dimension check, and checks the rows ofpas well as those ofq. The six SympNet layer constructors (GradientLayerQ/P,ActivationLayerQ/P,LinearLayerQ/P) convert the dimension toInt, soActivationLayerQ(Int32(4), tanh) === ActivationLayerQ(4, tanh).GradientLayer.second_dimis anInt, and the aliasesLinearLayerQ/LinearLayerPno longer name an unused parameter.Boolladders. EachBoolkeyword ofVolumePreservingAttention, the two volume-preserving feedforward layers,SymplecticAttentionQ/P,SymplecticAutoencoderandResNetLayerpicks aSymboltype parameter in one expression.ResNetLayerencodes its bias as:bias/:no_bias, as the volume-preserving layers do; itsuse_bias::Boolkeyword stays.VolumePreservingLowerLayerandVolumePreservingUpperLayerare aliases of one structVolumePreservingFeedForwardLayer{M, N, bias, AT, Triangle}, with oneinitialparameters; the bias keyword isinit_biasin every layer.initialparametersfor both weight kinds. The forward pass finds each head by its namehead_i, from a key tuple that a generated function builds once for each number of heads, where it builtSymbol("head_", i)on every pass.LASympNethas oneChainmethod where it had four; one_gradient_layersbuilds the gradient layers ofGSympNet,LinearSymplecticTransformerandSymplecticTransformerand replaces the two_make_block_for_initializationmethods (known issue C19 leavesKNOWN_ISSUES.md); theDataLoaderconstructors ofLASympNetandGSympNet, andClassificationTransformer(dl)(src/architectures/transformer_neural_network.jl), delegate;GSympNetnames its activation fieldactivation; oneencoderand onedecoderserve everyAutoEncoderthat is not aSymplecticAutoencoder.LinearSymplecticTransformerkeeps its activation (it builtnew{typeof(tanh)}, soactivation = sinraised aMethodError).StandardTransformerIntegrator's fieldupsacling_activationis spelledupscaling_activation.decoderof anAutoEncodergives the decoder the decoder's block count, where it gave itn_encoder_blocks; the model and the parameters already read the right count, so no output changes. A SympNet layer raises its ownDimension mismatch.error for apof the wrong size, where it failed later in the product or the broadcast.::Type{T}everywhere undersrc/layers/.PositionalEncodingfillssimilar(x, eltype(x), dim, seq_length)by one broadcast, so it runs on aJLArraywith scalar indexing disallowed; the "CPU only" docstring warnings go (known issues B11 and K5 leaveKNOWN_ISSUES.md).Breaking changes are listed in
CHANGELOG.md:ResNetLayer's third type parameter, the one volume-preserving feedforward struct,init_bias!→init_bias,GSympNet.act→activation, and theupscaling_activationspelling.Tests
test/layers/layer_pins.jlandtest/architectures/architecture_pins.jl: 27 layer cases, 13 architecture cases and the encoders and decoders of two autoencoders, each inFloat32andFloat64, against the outputs that4c4a8320gives for the same seeds and inputs. The cases cover dense,SymmetricMatrix, triangular,SkewSymMatrixand Stiefel leaves.architecture_pins.jlalso checks that the encoder and the decoder of an autoencoder with different block counts each keep their own count.layer_pins.jlhas a self-test of the comparison: it shifts the entry -0.25 of[1.5, -0.25, 3]by 16 and by 17eps(3); 16 passes and 17 fails, so the scale is the vector's and not the entry's, and a size mismatch givesInf.test/layers/layer_structure.jl: the merged methods, the type parameters, the two bugs, the dimension check ofqand ofp, theIntdimensions of all six SympNet constructors, the MHA draw order and head lookup by name, and the::Type{T}grep. The draw-order test checks that each Stiefel leaf is aStiefelManifold, drawn head by head asStiefelLayerdraws them. The alias test reads the source line, because Julia drops an unused alias type variable.test/architectures/architecture_structure.jl: the merged architecture methods, and theClassificationTransformer(dl)keyword test (from GML part M5: one functor per layer family, the Bool keywords as type parameters, and the MHA head keys built once #350) in both precisions.test/layers/multi_head_attention_allocation.jl: the forward pass allocates what the same head products allocate with constant keys, within 1024 B over 1000 passes, for one and two heads.test/layers/multi_head_attention_inference.jl: both forward methods infer at 4 and at 32 heads.test/architectures/forward_inference.jl:@inferredon the forward pass of every exported architecture with a chain, inFloat32andFloat64, includingStandardTransformerIntegrator(32)(32 heads by default).test/layers/positional_encoding.jl: the layer on aJLArraywith scalar indexing disallowed.The MultiHeadAttention draw order is unchanged, and no seeded pin moved. The one
initialparametersdraws head by head, and in each head the query, the key and the value projection, as before.Out of the
Bool-ladder item:MultiHeadAttention(Stiefel,add_connection) andClassificationLayer(average) encode other choices and keep theirBoolparameters, and the ANNDenselayer is outside this part.The pinned outputs were recorded on arm64 and are compared at 16 ULPs of the largest magnitude of the pinned vector (
PIN_ULPSintest/helpers/pins.jl). A comparison at 8 ULPs of each entry's own magnitude failed Julia 1 on Ubuntu and Windows at the fullSymplecticAutoencoderFloat64pass (run 39577642351). That pass is the deepest case, encoder then decoder, and its output holds entries such as -0.0686 beside 1.276 that come out of cancellation. The rounding error of such an entry is set by the terms it came from, so a bound relative to the entry's own magnitude asks for an accuracy that floating point does not give. At 16 ULPs of 1.276 the bound is about 3.6e-15 inFloat64; a wrong layer moves an output by a fraction, thousands of ULPs away. A failure prints the measured deviation:@test pin_ulps(vec(y), pin) ≤ PIN_ULPSgivesEvaluated: <n> ≤ 16. The pins, the seeds, the inputs and the Stiefel fix are unchanged.Suite at the critic-passed code: full suite with Metal on Julia 1.13.2, pass (Metal 40/40, one known broken: the JET
@test_brokenof #325); full suite with Metal on Julia 1.12.7 (the floor), pass (Metal 40/40, one broken); doctests pass; the Documenter docs build gives 0 unresolved references on Julia 1.13.2.Critic
Verdict: PASS (round verify 2, branch simplify/part-m5-3 at 179d093, judged 7ada06d..HEAD). Mutants: 12 CAUGHT, 0 SURVIVED, 0 UNKNOWN, 0 INVALID. Blocking defects: none.
@test_broken isempty(reports) # #325at quality/jet.jl:96)Earlier blocking defects (round 1): the SympNet dimension guard deleted; the MHA forward pass reading heads by field position. Both are fixed, and their reproducers pass.
The critic's verdict covers 179d093. The commits after it are not covered by it. 56c3443, 9ff44a5 and c03002a change text only:
KNOWN_ISSUES.md, the headline of oneCHANGELOG.mdentry, and the header comment oftest/layers/layer_structure.jl. e152ae7 mergesorigin/main. 52a01a8 also changes code: theIntconversion of the dimension in the SympNet layer constructors (src/layers/sympnets.jl),src/architectures/transformer_neural_network.jl, the pin tolerance from 8 to 16 ULPs (test/helpers/pins.jl), and several test files. The review fix commit after it changessrc/architectures/autoencoder.jlandsrc/layers/sympnets.jl(known issues K23 and K24 below).Checks of 52a01a8, which the critic did not judge:
pin_ulpswith each entry's owneps(the old scale);PIN_ULPS = 8;<for≤at the 16-ULP case (each by the comparison self-test);ActivationLayerQkeeping anInt32dimension ("a SympNet layer stores its dimensions as Int"); the Stiefel branch of_head_weightdrawing a plain matrix ("MultiHeadAttention draws Stiefel weights head by head");ClassificationTransformer(dl)swappingStiefelandadd_connection("a DataLoader gives the ClassificationTransformer of its dimensions").mainon 2026-10-21; not triaged againstmain).pre-pushskips it on a topic branch.Known issues added
IDs as in
KNOWN_ISSUES.mdat the head of this branch.LagrangianNeuralNetworkstores its activation in the fieldact. Present on4c4a8320.src/layers/symplectic_attention.jlnames a test file undertest/parameters/, which does not exist. Present on4c4a8320.LinearSymplecticTransformerandSymplecticTransformersay thatn_sympnet = 1gives oneGradientLayerQand oneGradientLayerP; withinit_upper = truethe chain has twoGradientLayerQ. Present on4c4a8320.SymplecticAutoencoderdocstring says thatdecoder_init_q = truemakes the first layer of each decoder block a p-type layer; it is aGradientLayerQ. Present on4c4a8320.UnknownDecoderdocstring names its third argumentn_encoder_blocksand links to itself for an example. Present on4c4a8320.K23 (the SympNet forward methods checked the rows of
qonly) and K24 (decodergave the decoder of anAutoEncoderthe encoder's block count) were recorded on this branch and are fixed on it, so they leaveKNOWN_ISSUES.mdagain. Both were present on4c4a8320.Known issues closed: B11, C19, K5.
Reported, not fixed
VolumePreservingFeedForward(the architecture) keeps itsif/elseinit_upperladder.LagrangianNeuralNetwork.act(K21).symplectic_attention.jl(K22).n_sympnet = 1(K25).SymplecticAutoencoderandUnknownDecoderdocstrings (K26, K27).Advisor decisions
For review, verbatim from the plan of this part:
(The plan corrects that figure to the measured one: one rebuilt key costs 192 B a pass on Julia 1.13.2, 187× the 1024 B tolerance. The tolerance stays as decided.)
(The advisor's
test/architectures/forward_pins.jlistest/architectures/architecture_pins.jlon this branch.)Pre-PR verification
Two passes. Pass 1 ran over the full branch. Pass 2 ran over the text-only commits after the critic's PASS, and it checked every CHANGELOG line that the branch adds.
Fixed
Symbol-parameter change said too much. It now namesResNetLayer's bias parameter, the single volume-preserving feedforward struct, and the two renamed fields and the renamed keyword.test/layers/layer_structure.jlnow names the layers whoseBoolkeywords becomeSymbolparameters.4c4a8320.Unresolved
test/layers/layer_structure.jlreads "each Bool keyword of a ladder becomes a Symbol type parameter".Checked and clean
src,test,docs,scriptsorext. The fourLASympNetcombinations match the base. The CHANGELOG counts and the K21, K23–K26 evidence reproduce.test_piraciespasses.Float32andFloat64(82 combinations).initialparameters(::MultiHeadAttention)cannot infer on the base either, because its keys depend on the runtimen_heads.fatou lintis clean. The shared_shiftmethods andPositionalEncodingallocate the same bytes as the base bodies, with equal outputs, in a warm session. The 384 000 B difference for a two-headMultiHeadAttentionover 1000 passes at the base reproduces (Julia 1.13.2).CHANGELOG.md.Not checked
forward_inference.jl, passed on 1.12.7.PositionalEncodingon a device is covered by theJLArraytestset only. The Metal group does not runPositionalEncoding, and a broadcast on aJLArrayalso reads a host matrix, so theJLArraytestset asserts where the encoding is allocated, not that a device kernel compiles.🤖 Generated with Claude Code