Add S/λ² spectral sequence and B/Z/E classification API#249
Conversation
|
Warning Review limit reached
Next review available in: 38 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds S/λ² classification and spectral-sequence support, stores and queries a lambda2 spectral sequence in the secondary algebra, adds computation safeguards, and updates examples and benchmark outputs to use B/Z/E labels and secondary element formatting. ChangesS/λ² spectral sequence and secondary classifications
Computation and persistence safeguards
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ext/examples/lambda2.rs`:
- Around line 139-147: print_table_iii is currently printing raw
lambda2_page_data() entries instead of the advertised B/Z/E-annotated conical
basis. Update print_table_iii to use the new BZE-related API when iterating the
E3/E∞ generators so each row includes the correct B/Z/E type alongside the
tridegree, and keep the output aligned with the table description in the
function’s doc comment.
- Around line 177-183: The Table IV output in the lambda2 example is missing the
commutator column even though the doc comment and table description say it
should be included. Update the Table IV generation logic in the function that
prints the secondary products so it also computes and prints the commutator from
the existing stem parities (using the x·y and y·x relation). Keep the secondary
product output, but extend the same loop/row formatting to include the
commutator information for each pair.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 96149d7c-f3a8-4050-b59d-348c29f958e1
📒 Files selected for processing (5)
ext/crates/sseq/src/sseq.rsext/examples/lambda2.rsext/src/ext_algebra/mod.rsext/src/ext_algebra/secondary.rsext/src/secondary.rs
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
ext/src/ext_algebra/secondary.rs (1)
228-244: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy liftDon’t expose λ² E3 dimensions when the underlying d₂ is uncomputed.
Line 240 skips unknown d₂ maps, but the λ² copies are already defined and the accessors return definite dimensions. Near the computation boundary this treats “d₂ target/source not computed” as “d₂ is zero”, unlike
d2()which returnsNone. Gate λ² degree definition/accessors on the same computability range, and add a boundary regression test.Possible direction
+ let d2_shift = Bidegree::n_s(-1, 2); + for b in res.iter_stem() { let dim = res.number_of_gens_in_bidegree(b); let [n, s] = b.coords(); - sseq.set_dimension(MultiDegree::new([n, s, 0]), dim); - sseq.set_dimension(MultiDegree::new([n, s, 1]), dim); + + if b.t() <= 0 || res.has_computed_bidegree(b + d2_shift) { + sseq.set_dimension(MultiDegree::new([n, s, 0]), dim); + } + + let incoming_source = b - d2_shift; + if incoming_source.s() < 0 + || incoming_source.t() <= 0 + || res.has_computed_bidegree(incoming_source) + { + sseq.set_dimension(MultiDegree::new([n, s, 1]), dim); + } }Also consider returning
Option<usize>fromlambda2_e3_dimensionifNonecan mean “not computed” rather than “zero”.Also applies to: 272-299, 439-503
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ext/src/ext_algebra/secondary.rs` around lines 228 - 244, The λ² E3 dimension accessors in secondary.rs are exposing definite dimensions even when the corresponding d₂ data is still uncomputed, unlike d2() which reports None. Update the λ² degree setup and the related accessors (including lambda2_e3_dimension and the code around res_lift/homotopy lookups) to gate on the same computability boundary as d₂, so unknown source/target bidegrees are not treated as zero. If appropriate, make the accessor return Option<usize> for not-yet-computed degrees, and add a regression test covering the boundary case.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@ext/src/ext_algebra/secondary.rs`:
- Around line 228-244: The λ² E3 dimension accessors in secondary.rs are
exposing definite dimensions even when the corresponding d₂ data is still
uncomputed, unlike d2() which reports None. Update the λ² degree setup and the
related accessors (including lambda2_e3_dimension and the code around
res_lift/homotopy lookups) to gate on the same computability boundary as d₂, so
unknown source/target bidegrees are not treated as zero. If appropriate, make
the accessor return Option<usize> for not-yet-computed degrees, and add a
regression test covering the boundary case.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 3feb8d09-2af3-42c4-918d-a3fd3fbf3fc1
📒 Files selected for processing (8)
ext/examples/benchmarks/secondary-C2ext/examples/benchmarks/secondary-C2-nassauext/examples/benchmarks/secondary-S_2ext/examples/benchmarks/secondary-tmfext/examples/lambda2.rsext/examples/secondary.rsext/examples/secondary_product.rsext/src/ext_algebra/secondary.rs
2c19f37 to
fa37ad9
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ext/examples/lambda2.rs`:
- Around line 35-46: Reject non-unit modules before building the tables in
lambda2’s main example flow: the current use of query_module(...),
ExtAlgebra::from_resolution, and later e2.resolution()/e2.unit_generator(...)
assumes unit-generator indexing that is only valid for a unit input. Update the
lambda2 example to fail fast unless e2.is_unit() is true, and keep the
resolution-dependent table generation behind that check so Table II cannot read
generators from the wrong basis.
In `@ext/examples/secondary_product.rs`:
- Around line 116-123: The classification in `secondary_multiply_into` is
currently inferred from `prod.source.vec().iter_nonzero().next()`, which
mislabels mixed sources by basis order instead of class. Update the
`secondary_product.rs` printing logic to use `SecondaryExtAlgebra::classify()`
for `prod.source` (or explicitly split mixed sources before formatting) so the
`B|Z|E` label reflects the full class rather than the first nonzero basis
element.
In `@ext/src/ext_algebra/mod.rs`:
- Around line 78-84: The cached sseq in ExtAlgebra becomes stale after
compute_through_bidegree() extends the underlying resolution, so sseq() can
return an outdated snapshot that no longer matches dimension() and basis() for
newly computed bidegrees. Update ExtAlgebra::new and the sseq()/build_sseq()
flow so the spectral sequence is rebuilt or invalidated whenever the resolution
grows, or make sseq() compute from the current resolution state instead of
storing a one-time cached value.
In `@ext/src/ext_algebra/secondary.rs`:
- Around line 496-528: `project_to_pi` is building `PiElement` with coordinates
from `sq.reduce(...)` but `basis_indices` from ambient generator filtering, so
the two bases can mismatch. Fix this in `secondary.rs` by deriving the basis
indices from the actual `Subquotient` generator basis used by
`lambda2_page_data(td)`/`Sq::reduce`, or by projecting into the same ambient
basis before constructing `PiElement`. Ensure `PiElement::coords`,
`basis_indices`, and `Display` all refer to the same basis.
- Around line 420-432: The current `classify()` implementation only delegates to
`lambda2_sseq().classify(...)` on the `(n, s, 0)` copy, so it misses the
weight-1 boundary case and can mislabel true `B` classes as `Z`. Update
`SecondaryExt::classify` to use the same boundary-aware logic as
`adams_classify()` (or otherwise incorporate the weight-1 incoming `d₂` check)
while preserving the existing `BZE` decomposition behavior for
`BidegreeGenerator`.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 42d44cc6-5fbc-4ffd-83ae-46ef7ed3bc60
📒 Files selected for processing (17)
ext/crates/sseq/src/coordinates/bze.rsext/crates/sseq/src/coordinates/mod.rsext/crates/sseq/src/sseq.rsext/examples/benchmarks/secondary-C2ext/examples/benchmarks/secondary-C2-nassauext/examples/benchmarks/secondary-S_2ext/examples/benchmarks/secondary-tmfext/examples/benchmarks/secondary_product-h_0-S_2ext/examples/benchmarks/secondary_product-h_0-S_2-nassauext/examples/benchmarks/secondary_product-v_1-C2ext/examples/lambda2.rsext/examples/secondary.rsext/examples/secondary_massey.rsext/examples/secondary_product.rsext/src/ext_algebra/mod.rsext/src/ext_algebra/secondary.rsext/src/secondary.rs
ef09a7a to
d2561a6
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
ext/src/save.rs (1)
462-527: 📐 Maintainability & Code Quality | 🔵 TrivialConsider factoring out the shared open/write-header logic.
try_create_fileduplicates most ofcreate_file(path resolution,OpenOptionschain,ChecksumWriterconstruction, header write), differing only in how the "already being written" case is handled (panic vs.None). Extracting a shared private helper that returnsResult<File, io::Error>(or similar) and letting each public method decide how to react toAlreadyExistswould avoid the two implementations drifting out of sync.♻️ Sketch of the shared helper
+ fn try_open_for_write(&self, p: &Path, overwrite: bool) -> Result<std::fs::File, io::Error> { + std::fs::OpenOptions::new() + .write(true) + .create_new(!overwrite) + .create(true) + .truncate(true) + .open(p) + } + pub fn create_file(&self, dir: PathBuf, overwrite: bool) -> impl io::Write + use<A> { let p = self.get_save_path(dir); tracing::info!(file = ?p, "open for writing"); assert!( open_files().lock().unwrap().insert(p.clone()), "File {p:?} is already opened" ); - let f = std::fs::OpenOptions::new() - .write(true) - .create_new(!overwrite) - .create(true) - .truncate(true) - .open(&p) - .with_context(|| format!("Failed to create save file {p:?}")) - .unwrap(); + let f = self.try_open_for_write(&p, overwrite) + .with_context(|| format!("Failed to create save file {p:?}")) + .unwrap(); let mut f = ChecksumWriter::new(p, io::BufWriter::new(f)); self.write_header(&mut f).unwrap(); f }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ext/src/save.rs` around lines 462 - 527, Factor the duplicated path resolution, file opening, ChecksumWriter construction, and header-writing logic from create_file and try_create_file into a private helper returning an appropriate Result. Keep open_files registration and cleanup correct, and let each public method preserve its existing behavior: create_file panics on failure while try_create_file returns None for AlreadyExists and panics for other errors.ext/src/resolution_homomorphism.rs (1)
144-165: 📐 Maintainability & Code Quality | 🔵 TrivialCorrect fix for Nassau's lazily-computed quasi-inverse.
Bounding
tbytarget.max_computed_quasi_inverse_degree(...)instead of the raw module degree closes the gap that could otherwise trip theassert!(apply_quasi_inverse(...))inextend_step_raw(line 329) when the target is a Nassau resolution whose quasi-inverses lag behind its module computation. No behavior change for non-lazyChainCompleximpls since the default trait method is equivalent to the old bound.Consider adding a regression test that calls
extend_allon aResolutionHomomorphismtargeting anassau::Resolutionto pin down the exact panic this fixes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ext/src/resolution_homomorphism.rs` around lines 144 - 165, Update ResolutionHomomorphism::extend_all so the upper t-bound uses target.max_computed_quasi_inverse_degree at the shifted source degree, then applies shift.t() and remains bounded by source.module(s).max_computed_degree(). Preserve the existing +1 extension behavior and degree bounds; add a regression test covering extend_all with a Nassau resolution target if the test suite supports it.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@ext/src/resolution_homomorphism.rs`:
- Around line 144-165: Update ResolutionHomomorphism::extend_all so the upper
t-bound uses target.max_computed_quasi_inverse_degree at the shifted source
degree, then applies shift.t() and remains bounded by
source.module(s).max_computed_degree(). Preserve the existing +1 extension
behavior and degree bounds; add a regression test covering extend_all with a
Nassau resolution target if the test suite supports it.
In `@ext/src/save.rs`:
- Around line 462-527: Factor the duplicated path resolution, file opening,
ChecksumWriter construction, and header-writing logic from create_file and
try_create_file into a private helper returning an appropriate Result. Keep
open_files registration and cleanup correct, and let each public method preserve
its existing behavior: create_file panics on failure while try_create_file
returns None for AlreadyExists and panics for other errors.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: d163b498-15e8-4dd8-a67f-faf7ee6b14ca
📒 Files selected for processing (21)
ext/crates/sseq/src/coordinates/bze.rsext/crates/sseq/src/coordinates/mod.rsext/crates/sseq/src/sseq.rsext/examples/benchmarks/secondary-C2ext/examples/benchmarks/secondary-C2-nassauext/examples/benchmarks/secondary-S_2ext/examples/benchmarks/secondary-tmfext/examples/benchmarks/secondary_product-h_0-S_2ext/examples/benchmarks/secondary_product-h_0-S_2-nassauext/examples/benchmarks/secondary_product-v_1-C2ext/examples/lambda2.rsext/examples/secondary.rsext/examples/secondary_massey.rsext/examples/secondary_product.rsext/src/chain_complex/mod.rsext/src/ext_algebra/mod.rsext/src/ext_algebra/secondary.rsext/src/nassau.rsext/src/resolution_homomorphism.rsext/src/save.rsext/src/secondary.rs
ExtAlgebra is a first-class Cλ-module, indexed by the coordinate triple Bidegree / BidegreeGenerator / BidegreeElement. SecondaryExtAlgebra is the analogous Cλ²-module but lacked the matching coordinate types; this adds them so you can index into it the same way. New secondary coordinate triple in ext/src/secondary.rs: - Weight: the λ-adic weight (Ext = 0, Lambda = 1; only two weights since λ² = 0), with an as_i32 synthetic coordinate. - SecondaryDegree: a base bidegree b — weight-0 part at b, weight-1 (λ) part at b + LAMBDA_BIDEGREE. Analog of Bidegree. - SecondaryGenerator: base + Weight + idx; into_element places the unit entry in the ext or λ part. Analog of BidegreeGenerator. - SecondaryElement: base + ext/λ FpVectors (promoted from the earlier SyntheticElement). A generic class is not weight-homogeneous, so both parts are stored. Analog of BidegreeElement. Indexing methods on SecondaryExtAlgebra mirror ExtAlgebra (dimension/basis/element/generator, weight_dimension, and unit_* variants). They read ambient generator counts like ExtAlgebra::dimension, so the secondary d2/E3 structure stays a separate computation; undefined bidegrees panic rather than yielding a silent 0. SecondaryProduct.value and both examples use SecondaryElement. The Weight enum is designed to feed a future 3-graded synthetic spectral sequence; the B/Z/E differential filtration is left for that later layer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0125sG5YPRQVfTs5eZ7hN7hA
Add AdamsLambda2 profile (SseqProfile<3>) for the trigraded Adams spectral sequence of S/λ². Extend SecondaryExtAlgebra with a lambda2_sseq field that builds the E2 page (two copies of Ext at Bockstein degrees 0 and 1) and installs d2 differentials from (n, s, 0) → (n-1, s+2, 1) using the hom_k data. The E3 = E∞ page gives π(S/λ²). New API: lambda2_sseq(), lambda2_page_data(), lambda2_e3_dimension(). New example: lambda2.rs with Table I (B/Z/E decomposition), Table II (Ext products), Table III (π(S/λ²) basis), and Table IV (secondary products with commutators). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
…xample Move the B/Z/E classification into SecondaryExtAlgebra as a public API (BZE enum + classify method) rather than keeping it inline in the example. Fix a panic in SecondaryLift::compute_homotopies when the homotopy range is empty (min.s >= max.s), which occurred for multipliers at high filtration near the resolution boundary. Rewrite the lambda2 example's Table IV to use proper range guards matching secondary_product. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
Update secondary.rs and secondary_product.rs to use the BZE enum for classified output, labelling each result as B/Z/E. This replaces the old unclassified d2 output in secondary.rs and the complement_pivots iteration in secondary_product.rs with the uniform BZE::from_page_data API. Also improve lambda2 Table III to annotate conical basis entries with their B/Z/E type (bock=0: B and Z survive; bock=1: Z and E survive), and Table IV to include commutator information per Proposition 6.4 ([x,y] = 2(x·y) when both stems are odd, 0 otherwise). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
Restore the original filtering in the secondary example: only print generators whose d2 target bidegree has nonzero dimension, keeping the output focused on where d2 can be nontrivial. Each such generator is now labelled B/Z/E. Update the four secondary benchmark files to match the new output format. Fix rustfmt issues in lambda2.rs and secondary.rs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
Use prod.value (SecondaryElement) instead of the removed ext_part/lambda_part fields in lambda2.rs Table IV. Fix nightly rustfmt import grouping. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
BZE classification (boundary/cycle/supports-differential) is intrinsic to any spectral sequence, not specific to the secondary layer. Move the enum to sseq::coordinates::BZE with from_page_data, Display. Add Sseq::classify and Sseq::bze_indices methods that read the page data directly. SecondaryExtAlgebra::classify now delegates to the lambda2 sseq. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
ExtAlgebra now carries a trigraded spectral sequence. With only weight 0 populated, d2 targets the empty weight-1 grading and is trivially zero, so the spectral sequence degenerates at E2 — matching the Adams spectral sequence for M. The secondary layer will clone and extend this base sseq with weight-1 data and d2 differentials on its own copy. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
PiGenerator represents a conical basis generator of π(S/λ²) (Condition 3.2 of the paper), annotated with its Adams BZE classification and weight. PiElement is an element in the E3 subquotient at a specific weight, with coordinates in the surviving-generator basis. New methods on SecondaryExtAlgebra: - adams_classify: full BZE using both weights of the lambda2 sseq - pi_basis: conical basis at a bidegree (B→wt0, Z→both, E→wt1) - to_pi: project a SecondaryElement to E3 subquotients at each weight Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
…arks lambda2.rs: Table III now uses pi_basis() for the conical basis listing, and Table IV uses to_pi() to project products into the E3 subquotient. Both tables use adams_classify for proper B/Z/E distinction. Benchmark files regenerated for secondary_product examples to match the SecondaryElement Display format introduced by the secondary_element branch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
- classify() now inspects both weights of the lambda2 sseq so it reports boundaries (B). The weight-0 copy only carries outgoing d2, so the old single-weight version could never return B and mislabeled boundaries as Z. Consolidates the former adams_classify into classify and drops the redundant method. - ExtAlgebra::sseq() is computed on demand from the current resolution instead of cached in new(), so it never goes stale after the resolution is extended. - secondary_product example classifies each source by membership in the boundary subspace rather than by its first nonzero basis index, which was basis-order dependent for mixed sources. - lambda2 example bails on non-unit modules, since its tables read multiplicands from the resolution basis and feed them as unit generators (valid only when M == k). - Clarify PiElement docs: coords are in the E3 generator basis, labeled by each surviving class's leading (pivot) ambient index, which lines up with Subquotient::reduce entry-for-entry. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
…asis Three fixes to the S/λ² (lambda2) machinery, surfaced running `examples/lambda2` against the shared S2 Nassau resolution. 1. Nassau quasi-inverse lag (the reported panic). Nassau writes the quasi-inverse for (s,t) only while stepping to (s+1,t), so QIs lag differentials by one homological degree on the computed frontier. `ResolutionHomomorphism::extend_all` walked onto QI-less bidegrees and tripped the `apply_quasi_inverse` assert. Added `ChainComplex::max_computed_quasi_inverse_degree` (default = module frontier, so minimal resolutions are unchanged; Nassau overrides to encode the lag) and had `extend_all` and `ExtAlgebra::multiply_into` bound their reach by it. The deeper trigger was Table IV multiplying by a bare generator e_i for each Z-classified index. `classify` partitions generator *indices* by echelon pivots, so a "Z" index names the cycle with that pivot (e.g. e_0 + e_1), not e_i itself; feeding the non-cycle e_i to the secondary lift made the obstruction fail to lift. Added `SecondaryExtAlgebra::z_cycles` returning genuine cycle vectors, and Table IV multiplies by those. 2. Secondary-intermediate save race. `get_intermediate` did check-then- create with no dedup; combined with `open_file` deleting a still-empty mid-flush file, two tasks could both compute the same deterministic intermediate and the loser's O_EXCL create panicked with "File exists". Added `SaveFile::try_create_file` (yields None instead of panicking on a create-new collision) and used it for the redundant deterministic write. 3. Express the tables in the original generator basis. The display named each class by its leading pivot generator, hiding that 65 of the ~1974 classes are non-trivial combinations. `PiElement`/`PiGenerator` now carry an ambient representative and Display it over the original generators; `pi_basis` is rebuilt from `b_boundaries`/`z_cycles`/ `e_supports`; Tables I/III/IV render accordingly. Table IV product row keys are unchanged — only values that land on combination classes are now written out in full. Verified: full stem-100/52 run of all four tables completes with no panic (57866 lines); 14/14 lib tests pass under default features. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EwLJtW5fUgVX75Q1D5R85k
Format try_create_file's signature per nightly rustfmt (CI runs cargo fmt --check), and factor the shared OpenOptions chain into a private open_for_write helper so create_file and try_create_file can't drift apart. Each keeps its own registration and error handling: one panics with context, the other maps AlreadyExists to None. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
cd5265b to
29bcd47
Compare
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (21)
📝 WalkthroughWalkthroughAdds S/λ² classification and spectral-sequence support, stores and queries a lambda2 spectral sequence in the secondary algebra, adds computation safeguards, and updates examples and benchmark outputs to use B/Z/E labels and secondary element formatting. ChangesS/λ² spectral sequence and secondary classifications
Computation and persistence safeguards
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
|
Caution Review failedAn error occurred during the review process. Please try again later. 📝 WalkthroughWalkthroughAdds S/λ² classification and spectral-sequence support, stores and queries a lambda2 spectral sequence in the secondary algebra, adds computation safeguards, and updates examples and benchmark outputs to use B/Z/E labels and secondary element formatting. ChangesS/λ² spectral sequence and secondary classifications
Computation and persistence safeguards
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (21)
📝 WalkthroughWalkthroughAdds S/λ² classification and spectral-sequence support, stores and queries a lambda2 spectral sequence in the secondary algebra, adds computation safeguards, and updates examples and benchmark outputs to use B/Z/E labels and secondary element formatting. ChangesS/λ² spectral sequence and secondary classifications
Computation and persistence safeguards
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Summary
Implements the computational machinery for S/λ² (the cofiber of the Adams d₂ differential) from "The Cofiber of the Adams d₂ Differential", integrated into
SecondaryExtAlgebra.Sseq<3, AdamsLambda2>): E2 has two copies of Ext at each (n, s) — one at Bockstein degree 0 and one at 1. The d₂ maps (n, s, 0) → (n−1, s+2, 1). E3 = E∞ gives π(S/λ²).BZEenum withSecondaryExtAlgebra::classify()andBZE::from_page_data()to decompose Ext = B ⊕ Z ⊕ E at each bidegree, where d₂: E_{(n,s)} ≅ B_{(n−1,s+2)}.lambda2example binary: Generates the four tables from the paper (B/Z/E decomposition, Ext products, conical basis for π(S/λ²), secondary products in Mod_{Cλ²}).SecondaryLift::compute_homotopies: guard against empty homotopy range (min.s >= max.s) which panicked for multipliers at high filtration near the resolution boundary.Changes
ext/crates/sseq/src/sseq.rsAdamsLambda2profile implementingSseqProfile<3>ext/src/ext_algebra/secondary.rsBZEenum,classify(),build_lambda2_sseq(),lambda2_page_data(),lambda2_e3_dimension()ext/src/ext_algebra/mod.rsBZEext/src/secondary.rscompute_homotopiesempty-range panicext/examples/lambda2.rsTest plan
test_lambda2_sseq— verifies dim(E) = dim(B) across bidegrees, h₄ killed, h₀ survivestest_sphere_d2— verifies d₂(h₄) = h₀h₃² and permanent cyclestest_sphere_products— verifies h₀² ≠ 0 and h₀h₁ = 0S_2at (n=16, s=6)test_tempdir_lockfailure)🤖 Generated with Claude Code
https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9
Generated by Claude Code
Summary by CodeRabbit