Skip to content

Make the Algebra and Module traits multigrading-capable#268

Open
JoeyBF wants to merge 2 commits into
SpectralSequences:masterfrom
JoeyBF:claude/259-phase1-multigrade
Open

Make the Algebra and Module traits multigrading-capable#268
JoeyBF wants to merge 2 commits into
SpectralSequences:masterfrom
JoeyBF:claude/259-phase1-multigrade

Conversation

@JoeyBF

@JoeyBF JoeyBF commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

What & why

Generalize the Algebra/Module trait family to be multigrading-capable, so a bigraded object (like Ext) can implement them directly. This is groundwork for #259 (splitting ExtAlgebra into a ring Ext(k, k) and a module Ext(M, k) that are an Algebra and a Module); on its own it is a pure generalization with zero behavior change for all existing single-graded code.

The grading types already exist in the sseq crate (MultiDegree<N>, with Bidegree = MultiDegree<2>); this PR just makes the traits consume them.

How

  • trait Algebra<const N: usize = 1> and trait Module<const N: usize = 1>. The defaulted const generic means every existing A: Algebra / M: Module bound and the Arc<dyn Module> alias keep working unchanged — only future bigraded code writes <2>.
  • Degree inputs take impl Into<MultiDegree<N>>. With From<i32> for MultiDegree<1>, every existing i32 call site (~350 of them) compiles unchanged; the method .into()s at the top. Degree returns stay i32 (the distinguished filtration direction), so the resolution engine's degree arithmetic is entirely untouched.
  • Object safety. Module is used as dyn Module, and impl Into<…> arguments are not object-safe. So the object-safe core methods take a concrete MultiDegree<N> and are suffixed _multi (dimension_multi, act_on_basis_multi, …); a blanket ModuleExt extension trait re-exposes the ergonomic names (dimension, act_on_basis, …) taking impl Into<MultiDegree<N>>, and works even on dyn Module. Downstream code just gains use algebra::module::ModuleExt.
  • enum_dispatch. It cannot dispatch a const-generic trait parameter, so Algebra is removed from SteenrodAlgebra's #[enum_dispatch(...)] list and hand-dispatched via the existing dispatch_steenrod! macro (the same pattern PairAlgebra already uses for its associated type). UnstableAlgebra/GeneratedAlgebra/MuAlgebra stay singly graded and keep #[enum_dispatch].

Only the ~3 concrete algebras (Milnor, Adem, Field) and ~8 module implementors gain impl Into + a one-line .into() per method; the bulk of the diff is those mechanical signature updates plus ModuleExt imports at call sites.

Testing

  • cargo test --features concurrent --lib --tests --workspace, cargo test --examples, and doctests: green (the lone test_tempdir_lock failure is a pre-existing sandbox/permissions artifact, unrelated — it fails on master too).
  • Nightly cargo fmt --check, the clippy matrix (--no-default-features / --all-targets, -D warnings), and rustdoc (-D warnings, private items, all features): clean.
  • The single-graded code path is byte-for-byte identical; this PR adds no new behavior.

Follow-ups

The actual #259 split (ExtAlgebra ring / ExtModule module implementing these traits) builds on this and will come as a separate PR, followed by the secondary-layer split. This PR intentionally does not close #259.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Nk9J57zb6GpvZxrduhGSdY


Generated by Claude Code

Summary by CodeRabbit

  • New Features
    • Added support for multi-dimensional grading across algebra and module operations.
    • Algebra and module APIs now accept flexible degree representations while retaining compatibility with single-degree workflows.
    • Added convenient helper methods for dimension queries, actions, basis generation, and element formatting.
    • Extended feature support for concurrent processing and odd-prime calculations.
  • Compatibility
    • Existing singly graded operations continue to work with the updated interfaces.

Generalize the `Algebra` trait family to be multigrading-capable, as the
foundation for treating Ext(k,k) as a genuine bigraded algebra (issue SpectralSequences#259).

- `Algebra<const N: usize = 1>`: degree *inputs* now take
  `impl Into<MultiDegree<N>>`, so singly-graded callers keep passing bare
  `i32`s (via new `From<i32> for MultiDegree<1>`). The default `N = 1` keeps
  every existing `A: Algebra` bound and `dyn` usage working unchanged.
- `enum_dispatch` cannot handle a generic trait, so `Algebra` is removed from
  `SteenrodAlgebra`'s dispatch list and hand-rolled via `dispatch_steenrod!`
  (the pattern already used for `PairAlgebra`). `UnstableAlgebra`,
  `GeneratedAlgebra`, and `MuAlgebra` stay singly-graded and keep enum_dispatch.
- Milnor, Adem, and Field implement `Algebra` (default `N = 1`), converting the
  incoming degree to `i32` at each method boundary.
- Degree-returning methods stay `i32` (the distinguished filtration direction),
  so the resolution engine's degree arithmetic is untouched.
- `algebra` now depends on `sseq` for `MultiDegree` (no dependency cycle).

Behavior is unchanged for the singly-graded path; all 51 algebra tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nk9J57zb6GpvZxrduhGSdY
@coderabbitai

coderabbitai Bot commented Jul 13, 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: 37 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: 67c3198d-b1dc-4136-a492-c678b6b4cdca

📥 Commits

Reviewing files that changed from the base of the PR and between df73512 and a6b6947.

📒 Files selected for processing (32)
  • ext/crates/algebra/src/module/finite_dimensional_module.rs
  • ext/crates/algebra/src/module/finitely_presented_module.rs
  • ext/crates/algebra/src/module/free_module.rs
  • ext/crates/algebra/src/module/hom_module.rs
  • ext/crates/algebra/src/module/homomorphism/free_module_homomorphism.rs
  • ext/crates/algebra/src/module/homomorphism/full_module_homomorphism.rs
  • ext/crates/algebra/src/module/homomorphism/hom_pullback.rs
  • ext/crates/algebra/src/module/homomorphism/mod.rs
  • ext/crates/algebra/src/module/homomorphism/quotient_homomorphism.rs
  • ext/crates/algebra/src/module/mod.rs
  • ext/crates/algebra/src/module/module_trait.rs
  • ext/crates/algebra/src/module/quotient_module.rs
  • ext/crates/algebra/src/module/rpn.rs
  • ext/crates/algebra/src/module/suspension_module.rs
  • ext/crates/algebra/src/module/tensor_module.rs
  • ext/examples/bruner.rs
  • ext/examples/ext_m_n.rs
  • ext/examples/lift_hom.rs
  • ext/examples/resolution_size.rs
  • ext/examples/sq0.rs
  • ext/examples/steenrod.rs
  • ext/src/chain_complex/chain_homotopy.rs
  • ext/src/chain_complex/finite_chain_complex.rs
  • ext/src/chain_complex/mod.rs
  • ext/src/nassau.rs
  • ext/src/resolution.rs
  • ext/src/resolution_homomorphism.rs
  • ext/src/secondary.rs
  • ext/src/yoneda.rs
  • ext/tests/extend_identity.rs
  • ext/tests/non_zero_min_degree.rs
  • web_ext/sseq_gui/src/actions.rs
📝 Walkthrough

Walkthrough

The algebra crate adopts const-generic MultiDegree APIs for algebras and modules. Scalar degree conversions preserve existing singly graded behavior, while implementations, dispatch, examples, and integrations migrate to the new trait methods.

Changes

Multi-degree API migration

Layer / File(s) Summary
Algebra contracts and implementations
ext/crates/algebra/Cargo.toml, ext/crates/algebra/src/algebra/*, ext/crates/sseq/src/coordinates/degree.rs
Algebra becomes const-generic and accepts MultiDegree inputs; algebra implementations convert them to scalar degrees internally.
Module trait and extension wrappers
ext/crates/algebra/src/module/module_trait.rs
Module gains const-generic multi-degree hooks, while ModuleExt provides scalar-compatible wrappers.
Module implementations
ext/crates/algebra/src/module/*
Concrete modules migrate basis, dimension, action, and formatting hooks to multi-degree variants.
Dispatch and integration updates
ext/crates/algebra/src/module/homomorphism/*, ext/examples/*, ext/src/*, ext/tests/*
Dispatch code, examples, chain-complex code, and tests import or implement the updated APIs.

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

Possibly related PRs

Suggested reviewers: hoodmane

Poem

I’m a rabbit hopping through degrees,
From scalar paths to tuples’ ease.
Traits grow wide, wrappers guide,
Modules act with bounds beside.
MultiDegree leaves carrots bright!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds multigrading support, but it does not perform the requested ExtAlgebra/ExtModule split or shared ring/module cache separation for #259. Implement the ring ExtAlgebra and separate ExtModule with shared ring caches, and remove the current M == k special-casing as described in #259.
Docstring Coverage ⚠️ Warning Docstring coverage is 70.77% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: making the Algebra and Module traits support multigrading.
Out of Scope Changes check ✅ Passed The changes shown all support the multigrading trait migration and downstream call-site updates; no clearly unrelated code changes are evident.
✨ 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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ext/crates/algebra/src/module/module_trait.rs (1)

67-148: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Validate the target degree before promising a non-panicking action.

Both methods delegate without computing the target basis or validating result against op_degree + input_degree. A valid source/index with a mismatched output slice can therefore still panic inside implementations.

Proposed validation
+        let output_degree = op_degree + mod_degree;
+        self.compute_basis_multi(output_degree);
+        let output_dim = self.dimension_multi(output_degree);
+        if result.as_slice().len() != output_dim {
+            return Err(ActError::InvalidInput(format!(
+                "result length {} does not match module dimension {output_dim} in degree {output_degree}",
+                result.as_slice().len()
+            )));
+        }

Apply the equivalent check using op_degree + input_degree in try_act_multi.

🤖 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/crates/algebra/src/module/module_trait.rs` around lines 67 - 148, Update
try_act_multi to compute and validate the target degree, op_degree +
input_degree, before delegating to act_multi: ensure the target degree is
supported and result has the required target dimension, returning the
appropriate ActError instead of allowing implementation panics. Apply the
equivalent target-basis and result validation in try_act_on_basis_multi using
op_degree + mod_degree before calling act_on_basis_multi.
🤖 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/crates/algebra/src/module/module_trait.rs`:
- Around line 153-158: Update the default Module trait method is_unit to return
false whenever the grading has more than one component (N > 1), before applying
the existing degree and dimension checks. Retain the current checks for the
single-component case, allowing multigraded implementations to provide accurate
behavior by overriding is_unit.

---

Outside diff comments:
In `@ext/crates/algebra/src/module/module_trait.rs`:
- Around line 67-148: Update try_act_multi to compute and validate the target
degree, op_degree + input_degree, before delegating to act_multi: ensure the
target degree is supported and result has the required target dimension,
returning the appropriate ActError instead of allowing implementation panics.
Apply the equivalent target-basis and result validation in
try_act_on_basis_multi using op_degree + mod_degree before calling
act_on_basis_multi.
🪄 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: 126d7619-142a-4309-b461-21e59fc2559b

📥 Commits

Reviewing files that changed from the base of the PR and between a3a63cb and df73512.

📒 Files selected for processing (38)
  • ext/crates/algebra/Cargo.toml
  • ext/crates/algebra/src/algebra/adem_algebra.rs
  • ext/crates/algebra/src/algebra/algebra_trait.rs
  • ext/crates/algebra/src/algebra/field.rs
  • ext/crates/algebra/src/algebra/milnor_algebra.rs
  • ext/crates/algebra/src/algebra/steenrod_algebra.rs
  • ext/crates/algebra/src/module/finite_dimensional_module.rs
  • ext/crates/algebra/src/module/finitely_presented_module.rs
  • ext/crates/algebra/src/module/free_module.rs
  • ext/crates/algebra/src/module/hom_module.rs
  • ext/crates/algebra/src/module/homomorphism/free_module_homomorphism.rs
  • ext/crates/algebra/src/module/homomorphism/full_module_homomorphism.rs
  • ext/crates/algebra/src/module/homomorphism/hom_pullback.rs
  • ext/crates/algebra/src/module/homomorphism/mod.rs
  • ext/crates/algebra/src/module/homomorphism/quotient_homomorphism.rs
  • ext/crates/algebra/src/module/mod.rs
  • ext/crates/algebra/src/module/module_trait.rs
  • ext/crates/algebra/src/module/quotient_module.rs
  • ext/crates/algebra/src/module/rpn.rs
  • ext/crates/algebra/src/module/suspension_module.rs
  • ext/crates/algebra/src/module/tensor_module.rs
  • ext/crates/sseq/src/coordinates/degree.rs
  • ext/examples/bruner.rs
  • ext/examples/ext_m_n.rs
  • ext/examples/lift_hom.rs
  • ext/examples/resolution_size.rs
  • ext/examples/sq0.rs
  • ext/examples/steenrod.rs
  • ext/src/chain_complex/chain_homotopy.rs
  • ext/src/chain_complex/finite_chain_complex.rs
  • ext/src/chain_complex/mod.rs
  • ext/src/nassau.rs
  • ext/src/resolution.rs
  • ext/src/resolution_homomorphism.rs
  • ext/src/secondary.rs
  • ext/src/yoneda.rs
  • ext/tests/extend_identity.rs
  • ext/tests/non_zero_min_degree.rs

Comment thread ext/crates/algebra/src/module/module_trait.rs
Second half of the multigrading foundation for issue SpectralSequences#259: generalize the
`Module` trait to bigraded (and N-graded) modules, so Ext(M, k) can be a genuine
`Module` over the ring Ext(k, k).

- `Module<const N: usize = 1>` with `type Algebra: Algebra<N>`. The default
  `N = 1` keeps every existing `M: Module` bound and the `dyn Module` /
  `SteenrodModule` alias working unchanged.
- `Module` must stay object-safe (`SteenrodModule = Arc<dyn Module>`), so its
  degree-taking methods take concrete `MultiDegree<N>` and are suffixed `_multi`
  (e.g. `dimension_multi`, `act_on_basis_multi`). A blanket `ModuleExt` trait
  provides the canonical ergonomic names (`dimension`, `act_on_basis`, …) taking
  `impl Into<MultiDegree<N>>`, forwarding to the core methods. It is implemented
  for every module including `dyn Module`, so callers keep passing bare `i32`s.
- All eight module implementors (free, FD, FP, hom, quotient, RPn, suspension,
  tensor) implement the `_multi` methods, converting to `i32` at the boundary.
- Degree-returning methods (`min_degree`, `max_degree`, `max_computed_degree`)
  stay `i32` (the distinguished filtration direction), so the resolution
  engine's degree arithmetic is untouched.
- Downstream call sites (resolution, nassau, yoneda, secondary, chain complexes,
  examples, tests) gain a `use algebra::module::ModuleExt` import; no logic
  changes.

Behavior is unchanged for the singly-graded path: all algebra and ext tests pass
(the one failing test, `test_tempdir_lock`, is a pre-existing environment issue
about read-only file permissions under root, unrelated to this change).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nk9J57zb6GpvZxrduhGSdY
@JoeyBF
JoeyBF force-pushed the claude/259-phase1-multigrade branch from df73512 to a6b6947 Compare July 13, 2026 06:53

JoeyBF commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Pushed a6b6947 addressing the review + a CI fix:

  • is_unit for N > 1 — applied the guard (returns false for multigraded modules, overridable), since min_degree/max_degree are the single i32 filtration and can't characterize the unit when degrees share a t. N = 1 behavior is unchanged.
  • sseq_gui build fixweb_ext/sseq_gui/src/actions.rs needed use algebra::module::ModuleExt for the renamed dimension/basis_element_to_string methods. This is what broke the lint and webserver jobs; a downstream consumer of the rename I'd missed. (The sseq.rs dimension calls are on a different type and are unaffected.)

I did not add the suggested output validation to try_act_multi / try_act_on_basis_multi. Those methods are unchanged from master (a3a63cb) apart from the _multi rename, so adding it is out of scope for this zero-behavior-change PR — and a strict result-length check would contradict the documented contract that "the length of input need not be equal to the dimension of the module" (the flexibility resolution-to-a-stem relies on). Happy to tackle output validation as a separate change if you'd like it.

Context: this PR is deliberately just the multigrading groundwork; the ExtAlgebra/ExtModule split for #259 (which CodeRabbit's "Linked Issues" check flags as missing) is the follow-up PR that builds on this one.


Generated by Claude Code

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.

Split ExtAlgebra into a ring ExtAlgebra (over k) and an ExtModule (over M)

2 participants