CellularCohomologyContext
Persistent cohomology (Bauer's algorithm, arXiv:1908.02518) generic over CellT: OrderedCell -- the cohomology counterpart to CellularHomologyContext, filling in what CLAUDE.md's own architecture notes call a real, previously-unfilled asymmetry: cohomology in this codebase used to mean RipserCohomologyContext/ PackedRipserCohomologyContext only, both hardcoded to Simplex[Int] via SimplexIndexing's combinatorial number system. This class instead works for any CellT: OrderedCell this library has -- Simplex, Cube, FiniteSimplicialSet generators alike -- including complexes that already use Simplex[Int] but aren't flag complexes (Cech, Alpha), which the VR-specialized engines can't serve either way. See .claude/DESIGN-generic-cohomology.md for the full design derivation (including an advisor() review and a later correction dropping apparent pairs from the design entirely); this doc summarizes the load-bearing points, not the exploration.
'''The key idea''': the coboundary matrix persistent cohomology reduces is the transpose of the ordinary boundary matrix, same coefficients -- if tau.boundary contains (sigma, c), sigma's coboundary contains (tau, c). Every stream this class targets (Cube, FiniteSimplicialSet, Cech, Alpha, and even ordinary Simplex[Int] VR complexes at a size where the reference/oracle engines matter more than raw speed) already gets fully materialized before persistence runs, unlike Vietoris-Rips at the scale RipserCohomologyContext targets -- so unlike that class's elaborate SimplexIndexing/insertionDiameter/sparseCofacets apparatus (built specifically to avoid ever materializing a combinatorially-exploding full flag complex), this class builds the coboundary relation directly, by inverting each materialized cell's own already-generic boundary[CoefficientT] call -- no cell-type-specific coboundary formula needed anywhere, and no dual Cocell/OrderedCocell typeclass either (removed from Chain.scala, on the same understanding: coboundary is extrinsic to a cell, not intrinsic the way boundary is, since it depends on which higher-dimensional cells actually exist in the ambient complex).
'''No maxDim parameter''', unlike every other engine in this codebase's history -- deliberately, not by oversight: this class simply computes cohomology up to whatever top dimension the materialized stream actually contains, which deletes the whole "does maxDim mean top built or top reported degree" footgun class (CellularPersistenceInChunksContext, RipserCohomologyContext, and PackedRipserCohomologyContext each had to fix this exact bug once -- see .claude/WORKLOG-maxdim-semantics-fix.md) rather than reimplementing it a fourth time. A caller wanting only H_0..H_k wraps the input stream first -- LimitedCofaceSimplexStream(stream, k + 1), the mechanism RipserCohomologySpec's own oracle and the MATLAB facade's engine=naive path already use for exactly this -- so real (k+1)-dimensional cells exist to correctly resolve whether a k-born class is finite or essential, and drops any dim == k + 1 bars from the returned list itself afterward.
'''No apparent pairs''', also deliberately: Definition 3.2/Proposition 3.9's whole point is avoiding coboundary enumeration for cells that turn out to be trivially paired -- and this class has no enumeration to avoid, because it must materialize the coboundary relation for every cell up front just to have "coboundary" exist at all. What would be left after porting the mutual-pair check (skip one basis write, skip one call into an already-cheap Chain.reduceBy miss) is noise, plausibly a net loss once the pair- detection scan itself is counted, and not worth the extra machinery. See the design doc's "What does NOT carry over" section for the full argument.
'''Representatives''': every bar carries a V-column (tracked exactly the way RipserCohomologyContext.persistentCohomology already does), satisfying this codebase's standing "every engine needs generic Field + real representatives" principle automatically -- this is also this class's actual point, not an afterthought: over a field the cohomology barcode is identical to the homology barcode (the reason Ripser computes cohomology at all -- same answer, cheaper algorithm), so a bars-only version of this class would be entirely redundant with CellularHomologyContext, which already covers every cell type this class does. Only an ''essential'' bar's V-column is a genuine cocycle (d(vcol) = 0) by construction -- Algorithm 1's invariant is d(V_j) = R_j throughout, and R_j is zero exactly when the bar is essential; a finite bar's V-column has coboundary equal to its own nonzero reduced pivot chain instead (still a valid representative -- it witnesses the class on the sub-level set strictly before the bar's death, since every term of that nonzero coboundary is born at or after the death value -- just not a cocycle over the whole complex). coboundaryOfChain exists specifically so a caller (in practice, a test) can verify this directly for essential bars (coboundaryOfChain(rep, ...).isZero()) -- something no engine in this codebase could check for Cube/FiniteSimplicialSet/Cech/Alpha before this class existed, since none of them ever had a cocycle representative to check in the first place.
Attributes
- Experimental
- true
- Graph
-
- Supertypes
-
class Objecttrait Matchableclass Any