Skip to content

algebra: extract the Milnor product and derive generic from the prime - #292

Open
JoeyBF wants to merge 1 commit into
SpectralSequences:masterfrom
JoeyBF:milnor-product-extract
Open

algebra: extract the Milnor product and derive generic from the prime#292
JoeyBF wants to merge 1 commit into
SpectralSequences:masterfrom
JoeyBF:milnor-product-extract

Conversation

@JoeyBF

@JoeyBF JoeyBF commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

Pure refactor of the Milnor product path — no behaviour change, no new API surface beyond one free function.

Extract milnor_product

multiply_with_allocation branched on generic(), but the two arms were the same computation. multiply_qpart(m1, 0) returns [(1, m1)]BitflagIterator::set_bit_iterator(0) yields nothing — so the classical arm is the generic arm with an empty exterior part. The two are collapsed into one free function:

pub fn milnor_product(
    p: ValidPrime,
    m1: MilnorBasisElement,
    m2: MilnorBasisElement,
    allocation: PPartAllocation,
    f: impl FnMut(u32, &MilnorBasisElement),
) -> PPartAllocation

which reports each (coefficient, basis element) through a callback, leaving the index lookup and excess filter to the caller. multiply_qpart becomes free too; it only ever read self.p. MilnorAlgebra::multiply_with_allocation is now a thin wrapper.

The motivation is downstream: $A_C/\tau \cong \mathbb{F}_2[\xi_i] \otimes E(\tau_i)$ has the odd-primary dual's shape with $2^i$ in place of $p^i$, so its product is the same commutation rule plus one PPartMultiplier walk. Sharing this function rather than reimplementing it keeps one algorithm under test instead of two.

Derive generic from the prime

The field was written once by the constructor as p != 2 and never mutated — a cached derivation, not state. generic() now computes it.

That also drops its #[cfg(feature = "odd-primes")] gate. Without the feature ValidPrime is the zero-sized type $2$, so self.p != 2 folds to a constant false on its own; the cfg was doing nothing the type system wasn't already doing.

Removing the field also closes a latent trap. A hand-constructed p = 2, generic = true algebra has exactly the graded dimensions of $A_C/\tau$ (41 degrees checked, 0 differ), which makes it tempting as a shortcut — but generators() finds $Q_k$ via factor_pk(p, degree + 1) == (k, 2), the odd-primary $|Q_k| = 2p^k - 1$. At $p = 2$, factor_pk(2, 2^{k+1}) = (k+1, 1), so every $Q_k$ past $Q_0$ silently vanishes from the generating set. Correct at odd primes, unreachable through the constructor today, and now unreachable by construction.

Checks

cargo test -p algebra (63 pass), cargo fmt --check, cargo clippy --all-targets, cargo check --no-default-features, and just docs under CI's RUSTFLAGS/RUSTDOCFLAGS: -D warnings — all clean.

Relationship to the motivic work

Independent of #266 — the two touch disjoint regions of milnor_algebra.rs and rebase past each other in either order. Only the follow-up $A_C/\tau$ PR needs both.

🤖 Generated with Claude Code

https://claude.ai/code/session_01F25ZVbsP7ULg41iY3MP6FX

Summary by CodeRabbit

  • New Features

    • Added a public Milnor product operation for multiplying Milnor basis elements with allocation support.
  • Improvements

    • Unified multiplication behavior across supported prime configurations.
    • Improved handling of exterior and polynomial components during multiplication.

@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 50 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: af2a0acf-7c9e-45bd-b6d8-10c7914fc266

📥 Commits

Reviewing files that changed from the base of the PR and between 7b9dc78 and fc807dc.

📒 Files selected for processing (1)
  • ext/crates/algebra/src/algebra/milnor_algebra.rs

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: fa28be4c-bd2e-485a-b5d1-81854fd4af8d

📥 Commits

Reviewing files that changed from the base of the PR and between b496e8e and 7b9dc78.

📒 Files selected for processing (1)
  • ext/crates/algebra/src/algebra/milnor_algebra.rs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The change removes stored generic-prime state and derives it from the prime. It extracts Milnor multiplication into the public milnor_product function and moves exterior-part multiplication into a free function.

Changes

Milnor product refactor

Layer / File(s) Summary
Derive generic-prime status
ext/crates/algebra/src/algebra/milnor_algebra.rs
MilnorAlgebra no longer stores generic. The generic() accessor derives the value from self.p != 2.
Extract Milnor product flow
ext/crates/algebra/src/algebra/milnor_algebra.rs
multiply_qpart is now a free function. multiply_with_allocation delegates to the public milnor_product function, which reports products through a callback.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 7b9dc

This refactor centralizes Milnor multiplication and derives the prime-mode flag without changing the established algebra behavior or wrapper safeguards. No actionable merge-blocking risk remains beyond normal checks and review.

Suggested reviewers: hoodmane

Poem

A rabbit checks the prime by moonlight bright
The product hops through parts in ordered flight
An exterior trail moves past the core
Callbacks carry coefficients to the door
The Milnor meadow blooms with less state tonight

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes both primary refactors: extracting the Milnor product and deriving generic from the prime.
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.

@JoeyBF
JoeyBF force-pushed the milnor-product-extract branch from f961df1 to 3052fd3 Compare August 30, 2026 22:31
@JoeyBF

JoeyBF commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@JoeyBF
JoeyBF force-pushed the milnor-product-extract branch from 3052fd3 to 7b9dc78 Compare August 31, 2026 21:04
JoeyBF pushed a commit to JoeyBF/sseq that referenced this pull request Aug 31, 2026
…r_product

The motivic algebra engine landed on master with the Tau coefficient
removed, so this tranche takes master's engine wholesale, drops the now
dead tau.rs, and rewrites the A_C/tau view against the new API.

A_C/tau is F_2[xi_i] tensor E(tau_i) — the odd-primary dual's shape with
2^i for p^i — so its product is the classical one at p = 2: the exterior
commutation shifts by 2^k and the signs collapse over F_2. CTauAlgebra now
multiplies through milnor_product (from the unmerged SpectralSequences#292, carried here)
rather than filtering the engine's F_2[tau] product, so one algorithm
stays under test instead of two.

milnor_product takes its left factor first, commuting the right factor's
exterior part past it; the engine's product_indexed orders its arguments
the other way. The cross-check test pins this down: it asserts the two
independent products — the classical machinery and the engine's Kong-Lin
closed form — agree on the tau^0 part across every product up to total
degree 5, and that some product really does drop a tau-divisible term.

The engine also dropped its basis-element string API and its profiling
counters, so the string round-trip moves here (inverting the Dual<Monomial>
display) and the profile line loses its product counters.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013ePtYD7Bt4iPeCtmqtqvZE
JoeyBF pushed a commit to JoeyBF/sseq that referenced this pull request Sep 1, 2026
Carve the motivic resolution layer out of the integration branch as the
next tranche after the algebra engine (SpectralSequences#266).

Adds CTauAlgebra, the A_C/tau view the ordinary resolution engine resolves,
and MotivicResolution: resolve the trivial module over A_C/tau, then lift
the differential to A_C by correcting along the weight grading. Includes
the resolution cache and the resolve_motivic_ctau example.

A_C/tau is F_2[xi_i] tensor E(tau_i) — the odd-primary dual's shape with
2^i for p^i — so its product is the classical one at p = 2: the exterior
commutation shifts by 2^k and the signs collapse over F_2. It therefore
multiplies through `milnor_product` (SpectralSequences#292) rather than reimplementing the
walk, and a test cross-checks that against the engine's independent
closed-form product, which is derived from Kong-Lin duality instead.

Note that `milnor_product` takes its left factor first while the engine's
`product_indexed` orders its arguments the other way; the two agree exactly
under that transposition.

Depends on SpectralSequences#292, which is not yet merged and so is included here.

The Ext-side cohomology, the deformation spectral sequence, products and
Massey products land in follow-ups.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013ePtYD7Bt4iPeCtmqtqvZE
`multiply_with_allocation` branched on `generic()`, but the two arms were the same
computation: `multiply_qpart(m1, 0)` returns `[(1, m1)]`, so the classical arm is the
generic one with an empty exterior part. Collapse them into `milnor_product`, a free
function that reports each `(coefficient, basis element)` through a callback, leaving
the index lookup and excess filter to the caller. `multiply_qpart` becomes free too; it
only ever read the prime.

`generic` was a `bool` field written once as `p != 2` and never mutated. Derive it
instead. That also drops its `#[cfg(feature = "odd-primes")]` gate: without the feature
`ValidPrime` is the zero-sized type 2, so the comparison folds to a constant on its own.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F25ZVbsP7ULg41iY3MP6FX
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.

1 participant