Skip to content

Add S/λ² spectral sequence and B/Z/E classification API#249

Open
JoeyBF wants to merge 13 commits into
SpectralSequences:masterfrom
JoeyBF:claude/spectralsequences-implementation-6um4zr
Open

Add S/λ² spectral sequence and B/Z/E classification API#249
JoeyBF wants to merge 13 commits into
SpectralSequences:masterfrom
JoeyBF:claude/spectralsequences-implementation-6um4zr

Conversation

@JoeyBF

@JoeyBF JoeyBF commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

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.

  • Trigraded spectral sequence (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/λ²).
  • B/Z/E classification API: BZE enum with SecondaryExtAlgebra::classify() and BZE::from_page_data() to decompose Ext = B ⊕ Z ⊕ E at each bidegree, where d₂: E_{(n,s)} ≅ B_{(n−1,s+2)}.
  • lambda2 example binary: Generates the four tables from the paper (B/Z/E decomposition, Ext products, conical basis for π(S/λ²), secondary products in Mod_{Cλ²}).
  • Edge case fix in SecondaryLift::compute_homotopies: guard against empty homotopy range (min.s >= max.s) which panicked for multipliers at high filtration near the resolution boundary.

Changes

File Description
ext/crates/sseq/src/sseq.rs Add AdamsLambda2 profile implementing SseqProfile<3>
ext/src/ext_algebra/secondary.rs Add BZE enum, classify(), build_lambda2_sseq(), lambda2_page_data(), lambda2_e3_dimension()
ext/src/ext_algebra/mod.rs Re-export BZE
ext/src/secondary.rs Fix compute_homotopies empty-range panic
ext/examples/lambda2.rs New example binary for the four tables

Test plan

  • test_lambda2_sseq — verifies dim(E) = dim(B) across bidegrees, h₄ killed, h₀ survives
  • test_sphere_d2 — verifies d₂(h₄) = h₀h₃² and permanent cycles
  • test_sphere_products — verifies h₀² ≠ 0 and h₀h₁ = 0
  • All four tables run without panic on S_2 at (n=16, s=6)
  • Full test suite passes (only pre-existing test_tempdir_lock failure)

🤖 Generated with Claude Code

https://claude.ai/code/session_017kezHiWcYod7hYovRPczz9


Generated by Claude Code

Summary by CodeRabbit

  • New Features
    • Added an (S/\lambda^2) spectral sequence with new APIs to query page data and (E_3) dimensions.
    • Exposed (B/Z/E) classification and added helpers to enumerate (d_2) boundaries, cycles, and supports.
    • Added (\pi(S/\lambda^2)) helpers (basis generation and projection) and a new example that prints (d_2)-tables.
    • Added an entry point to build the degree-3 spectral sequence from the current resolution state.
  • Bug Fixes
    • Prevented empty/inverted degree ranges from being processed during homotopy computations.
    • Improved product out-of-range handling and made save-file creation more robust under contention.
  • Tests
    • Expanded coverage for secondary indexing, (S/\lambda^2), and (\pi)-projection/display behavior.

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@JoeyBF, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 38 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7d3d493e-8b88-4720-9817-9c0608fe6b89

📥 Commits

Reviewing files that changed from the base of the PR and between d2561a6 and cd5265b.

📒 Files selected for processing (1)
  • ext/src/save.rs
📝 Walkthrough

Walkthrough

Adds 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.

Changes

S/λ² spectral sequence and secondary classifications

Layer / File(s) Summary
Secondary degree and element model
ext/src/secondary.rs
Defines secondary weight, degree, generator, and element types and guards homotopy traversal for empty ranges.
AdamsLambda2 profile and BZE classification
ext/crates/sseq/..., ext/src/ext_algebra/mod.rs
Introduces BZE, the AdamsLambda2 profile, Sseq classification helpers, and ExtAlgebra spectral-sequence wiring.
Secondary lambda2 cache and Pi projection
ext/src/ext_algebra/secondary.rs
Adds lambda2 construction and caching, B/Z/E decomposition, Pi projection, secondary indexing, product representation, and tests.
Example output updates
ext/examples/lambda2.rs, ext/examples/secondary*.rs
Adds lambda2 tables and updates example output to use B/Z/E classifications and SecondaryElement formatting.
Benchmark trace rewrites
ext/examples/benchmarks/*
Rewrites benchmark traces and product equations with explicit Z, B, and E markers.

Computation and persistence safeguards

Layer / File(s) Summary
Quasi-inverse computation bounds
ext/src/chain_complex/mod.rs, ext/src/nassau.rs, ext/src/resolution_homomorphism.rs, ext/src/ext_algebra/mod.rs
Tracks computed quasi-inverse bounds and applies them when limiting products and resolution extensions.
Concurrent intermediate-file creation
ext/src/save.rs, ext/src/secondary.rs
Adds collision-safe save-file creation and uses it for secondary intermediate persistence.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Poem

🐇 Lambda two begins to glow,
B, Z, and E now plainly show.
Pi paths align,
Tables neatly shine,
While saved hops safely flow.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main addition: the S/λ² spectral sequence and the new B/Z/E classification API.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between faff1d6 and 1c4e6f3.

📒 Files selected for processing (5)
  • ext/crates/sseq/src/sseq.rs
  • ext/examples/lambda2.rs
  • ext/src/ext_algebra/mod.rs
  • ext/src/ext_algebra/secondary.rs
  • ext/src/secondary.rs

Comment thread ext/examples/lambda2.rs
Comment thread ext/examples/lambda2.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 lift

Don’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 returns None. 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> from lambda2_e3_dimension if None can 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

📥 Commits

Reviewing files that changed from the base of the PR and between 1c4e6f3 and 2c19f37.

📒 Files selected for processing (8)
  • ext/examples/benchmarks/secondary-C2
  • ext/examples/benchmarks/secondary-C2-nassau
  • ext/examples/benchmarks/secondary-S_2
  • ext/examples/benchmarks/secondary-tmf
  • ext/examples/lambda2.rs
  • ext/examples/secondary.rs
  • ext/examples/secondary_product.rs
  • ext/src/ext_algebra/secondary.rs

@JoeyBF
JoeyBF force-pushed the claude/spectralsequences-implementation-6um4zr branch from 2c19f37 to fa37ad9 Compare June 28, 2026 19:34

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2c19f37 and fa37ad9.

📒 Files selected for processing (17)
  • ext/crates/sseq/src/coordinates/bze.rs
  • ext/crates/sseq/src/coordinates/mod.rs
  • ext/crates/sseq/src/sseq.rs
  • ext/examples/benchmarks/secondary-C2
  • ext/examples/benchmarks/secondary-C2-nassau
  • ext/examples/benchmarks/secondary-S_2
  • ext/examples/benchmarks/secondary-tmf
  • ext/examples/benchmarks/secondary_product-h_0-S_2
  • ext/examples/benchmarks/secondary_product-h_0-S_2-nassau
  • ext/examples/benchmarks/secondary_product-v_1-C2
  • ext/examples/lambda2.rs
  • ext/examples/secondary.rs
  • ext/examples/secondary_massey.rs
  • ext/examples/secondary_product.rs
  • ext/src/ext_algebra/mod.rs
  • ext/src/ext_algebra/secondary.rs
  • ext/src/secondary.rs

Comment thread ext/examples/lambda2.rs
Comment thread ext/examples/secondary_product.rs Outdated
Comment thread ext/src/ext_algebra/mod.rs Outdated
Comment thread ext/src/ext_algebra/secondary.rs Outdated
Comment thread ext/src/ext_algebra/secondary.rs
@JoeyBF
JoeyBF force-pushed the claude/spectralsequences-implementation-6um4zr branch from ef09a7a to d2561a6 Compare July 16, 2026 19:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🔵 Trivial

Consider factoring out the shared open/write-header logic.

try_create_file duplicates most of create_file (path resolution, OpenOptions chain, ChecksumWriter construction, header write), differing only in how the "already being written" case is handled (panic vs. None). Extracting a shared private helper that returns Result<File, io::Error> (or similar) and letting each public method decide how to react to AlreadyExists would 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 | 🔵 Trivial

Correct fix for Nassau's lazily-computed quasi-inverse.

Bounding t by target.max_computed_quasi_inverse_degree(...) instead of the raw module degree closes the gap that could otherwise trip the assert!(apply_quasi_inverse(...)) in extend_step_raw (line 329) when the target is a Nassau resolution whose quasi-inverses lag behind its module computation. No behavior change for non-lazy ChainComplex impls since the default trait method is equivalent to the old bound.

Consider adding a regression test that calls extend_all on a ResolutionHomomorphism targeting a nassau::Resolution to 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

📥 Commits

Reviewing files that changed from the base of the PR and between fa37ad9 and d2561a6.

📒 Files selected for processing (21)
  • ext/crates/sseq/src/coordinates/bze.rs
  • ext/crates/sseq/src/coordinates/mod.rs
  • ext/crates/sseq/src/sseq.rs
  • ext/examples/benchmarks/secondary-C2
  • ext/examples/benchmarks/secondary-C2-nassau
  • ext/examples/benchmarks/secondary-S_2
  • ext/examples/benchmarks/secondary-tmf
  • ext/examples/benchmarks/secondary_product-h_0-S_2
  • ext/examples/benchmarks/secondary_product-h_0-S_2-nassau
  • ext/examples/benchmarks/secondary_product-v_1-C2
  • ext/examples/lambda2.rs
  • ext/examples/secondary.rs
  • ext/examples/secondary_massey.rs
  • ext/examples/secondary_product.rs
  • ext/src/chain_complex/mod.rs
  • ext/src/ext_algebra/mod.rs
  • ext/src/ext_algebra/secondary.rs
  • ext/src/nassau.rs
  • ext/src/resolution_homomorphism.rs
  • ext/src/save.rs
  • ext/src/secondary.rs

claude and others added 13 commits July 16, 2026 22:25
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
@JoeyBF
JoeyBF force-pushed the claude/spectralsequences-implementation-6um4zr branch from cd5265b to 29bcd47 Compare July 16, 2026 22:29
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3d6f1dc7-2e24-46c6-b75c-3967043c01d4

📥 Commits

Reviewing files that changed from the base of the PR and between d2561a6 and 29bcd47.

📒 Files selected for processing (21)
  • ext/crates/sseq/src/coordinates/bze.rs
  • ext/crates/sseq/src/coordinates/mod.rs
  • ext/crates/sseq/src/sseq.rs
  • ext/examples/benchmarks/secondary-C2
  • ext/examples/benchmarks/secondary-C2-nassau
  • ext/examples/benchmarks/secondary-S_2
  • ext/examples/benchmarks/secondary-tmf
  • ext/examples/benchmarks/secondary_product-h_0-S_2
  • ext/examples/benchmarks/secondary_product-h_0-S_2-nassau
  • ext/examples/benchmarks/secondary_product-v_1-C2
  • ext/examples/lambda2.rs
  • ext/examples/secondary.rs
  • ext/examples/secondary_massey.rs
  • ext/examples/secondary_product.rs
  • ext/src/chain_complex/mod.rs
  • ext/src/ext_algebra/mod.rs
  • ext/src/ext_algebra/secondary.rs
  • ext/src/nassau.rs
  • ext/src/resolution_homomorphism.rs
  • ext/src/save.rs
  • ext/src/secondary.rs
 ________________________________________________________________________________
< A bunny is never late, nor is he early, he reviews precisely when he means to. >
 --------------------------------------------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
📝 Walkthrough

Walkthrough

Adds 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.

Changes

S/λ² spectral sequence and secondary classifications

Layer / File(s) Summary
Secondary degree and element model
ext/src/secondary.rs
Defines secondary weight, degree, generator, and element types and guards homotopy traversal for empty ranges.
AdamsLambda2 profile and BZE classification
ext/crates/sseq/..., ext/src/ext_algebra/mod.rs
Introduces BZE, the AdamsLambda2 profile, Sseq classification helpers, and ExtAlgebra spectral-sequence wiring.
Secondary lambda2 cache and Pi projection
ext/src/ext_algebra/secondary.rs
Adds lambda2 construction and caching, B/Z/E decomposition, Pi projection, secondary indexing, product representation, and tests.
Example output updates
ext/examples/lambda2.rs, ext/examples/secondary*.rs
Adds lambda2 tables and updates example output to use B/Z/E classifications and SecondaryElement formatting.
Benchmark trace rewrites
ext/examples/benchmarks/*
Rewrites benchmark traces and product equations with explicit Z, B, and E markers.

Computation and persistence safeguards

Layer / File(s) Summary
Quasi-inverse computation bounds
ext/src/chain_complex/mod.rs, ext/src/nassau.rs, ext/src/resolution_homomorphism.rs, ext/src/ext_algebra/mod.rs
Tracks computed quasi-inverse bounds and applies them when limiting products and resolution extensions.
Concurrent intermediate-file creation
ext/src/save.rs, ext/src/secondary.rs
Adds collision-safe save-file creation and uses it for secondary intermediate persistence.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Poem

🐇 Lambda two begins to glow,
B, Z, and E now plainly show.
Pi paths align,
Tables neatly shine,
While saved hops safely flow.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main addition: the S/λ² spectral sequence and the new B/Z/E classification API.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

An error occurred during the review process. Please try again later.

📝 Walkthrough

Walkthrough

Adds 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.

Changes

S/λ² spectral sequence and secondary classifications

Layer / File(s) Summary
Secondary degree and element model
ext/src/secondary.rs
Defines secondary weight, degree, generator, and element types and guards homotopy traversal for empty ranges.
AdamsLambda2 profile and BZE classification
ext/crates/sseq/..., ext/src/ext_algebra/mod.rs
Introduces BZE, the AdamsLambda2 profile, Sseq classification helpers, and ExtAlgebra spectral-sequence wiring.
Secondary lambda2 cache and Pi projection
ext/src/ext_algebra/secondary.rs
Adds lambda2 construction and caching, B/Z/E decomposition, Pi projection, secondary indexing, product representation, and tests.
Example output updates
ext/examples/lambda2.rs, ext/examples/secondary*.rs
Adds lambda2 tables and updates example output to use B/Z/E classifications and SecondaryElement formatting.
Benchmark trace rewrites
ext/examples/benchmarks/*
Rewrites benchmark traces and product equations with explicit Z, B, and E markers.

Computation and persistence safeguards

Layer / File(s) Summary
Quasi-inverse computation bounds
ext/src/chain_complex/mod.rs, ext/src/nassau.rs, ext/src/resolution_homomorphism.rs, ext/src/ext_algebra/mod.rs
Tracks computed quasi-inverse bounds and applies them when limiting products and resolution extensions.
Concurrent intermediate-file creation
ext/src/save.rs, ext/src/secondary.rs
Adds collision-safe save-file creation and uses it for secondary intermediate persistence.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Poem

🐇 Lambda two begins to glow,
B, Z, and E now plainly show.
Pi paths align,
Tables neatly shine,
While saved hops safely flow.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main addition: the S/λ² spectral sequence and the new B/Z/E classification API.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3d6f1dc7-2e24-46c6-b75c-3967043c01d4

📥 Commits

Reviewing files that changed from the base of the PR and between d2561a6 and 29bcd47.

📒 Files selected for processing (21)
  • ext/crates/sseq/src/coordinates/bze.rs
  • ext/crates/sseq/src/coordinates/mod.rs
  • ext/crates/sseq/src/sseq.rs
  • ext/examples/benchmarks/secondary-C2
  • ext/examples/benchmarks/secondary-C2-nassau
  • ext/examples/benchmarks/secondary-S_2
  • ext/examples/benchmarks/secondary-tmf
  • ext/examples/benchmarks/secondary_product-h_0-S_2
  • ext/examples/benchmarks/secondary_product-h_0-S_2-nassau
  • ext/examples/benchmarks/secondary_product-v_1-C2
  • ext/examples/lambda2.rs
  • ext/examples/secondary.rs
  • ext/examples/secondary_massey.rs
  • ext/examples/secondary_product.rs
  • ext/src/chain_complex/mod.rs
  • ext/src/ext_algebra/mod.rs
  • ext/src/ext_algebra/secondary.rs
  • ext/src/nassau.rs
  • ext/src/resolution_homomorphism.rs
  • ext/src/save.rs
  • ext/src/secondary.rs
 _______________________
< R2-D2 is my co-pilot. >
 -----------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
📝 Walkthrough

Walkthrough

Adds 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.

Changes

S/λ² spectral sequence and secondary classifications

Layer / File(s) Summary
Secondary degree and element model
ext/src/secondary.rs
Defines secondary weight, degree, generator, and element types and guards homotopy traversal for empty ranges.
AdamsLambda2 profile and BZE classification
ext/crates/sseq/..., ext/src/ext_algebra/mod.rs
Introduces BZE, the AdamsLambda2 profile, Sseq classification helpers, and ExtAlgebra spectral-sequence wiring.
Secondary lambda2 cache and Pi projection
ext/src/ext_algebra/secondary.rs
Adds lambda2 construction and caching, B/Z/E decomposition, Pi projection, secondary indexing, product representation, and tests.
Example output updates
ext/examples/lambda2.rs, ext/examples/secondary*.rs
Adds lambda2 tables and updates example output to use B/Z/E classifications and SecondaryElement formatting.
Benchmark trace rewrites
ext/examples/benchmarks/*
Rewrites benchmark traces and product equations with explicit Z, B, and E markers.

Computation and persistence safeguards

Layer / File(s) Summary
Quasi-inverse computation bounds
ext/src/chain_complex/mod.rs, ext/src/nassau.rs, ext/src/resolution_homomorphism.rs, ext/src/ext_algebra/mod.rs
Tracks computed quasi-inverse bounds and applies them when limiting products and resolution extensions.
Concurrent intermediate-file creation
ext/src/save.rs, ext/src/secondary.rs
Adds collision-safe save-file creation and uses it for secondary intermediate persistence.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Poem

🐇 Lambda two begins to glow,
B, Z, and E now plainly show.
Pi paths align,
Tables neatly shine,
While saved hops safely flow.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main addition: the S/λ² spectral sequence and the new B/Z/E classification API.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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