RipserCohomologyContext
maxDimension means "top HOMOLOGICAL DEGREE reported," not "top simplex dimension built" -- fixed at the source (previously only worked around at the MATLAB facade layer, which built requestedMaxDimension + 1 internally and filtered the extra dimension back out; see .claude/WORKLOG-maxdim-semantics-fix.md). Before this fix, coboundaryOf/zeroPivotCofacet refused to look past sigma.dim + 1 > maxDimension, i.e. sigma.dim == maxDimension always got a trivially-empty coboundary and therefore always came out essential -- a well-known truncation artifact (H_k needs (k+1)-chains to resolve correctly), not real information about H_maxDimension. Fixed by relaxing that guard to sigma.dim > maxDimension: a real (maxDimension + 1)-simplex is now enumerated on the fly, transiently, whenever needed to resolve a dimension-maxDimension pairing -- never materialized into its own currentLevel/reduced as its own column, so totalSimplexCount and the main loop's own bounds are unchanged; only the two guards moved. Any external caller previously passing maxDimension + 1 and filtering out dim == maxDimension + 1 bars itself should now pass the real requested degree directly and drop that workaround.
Attributes
- Experimental
- true
- Graph
-
- Supertypes
-
class Objecttrait Matchableclass Any
Members list
Type members
Classlikes
Ascending by filtration value; ties broken so a LARGER combinatorial index sorts as OLDER (smaller) -- the lexicographically-refined tie-break Definition 3.2/Proposition 3.9 rely on. Chain's leadingCell is the MINIMUM under whatever Ordering is supplied (Chain.from builds its PriorityQueue with ord.reverse), and persistent cohomology's pivot is the OLDEST cofacet in the reduced coboundary chain -- so this ascending ordering, not a reversed one, is what the coboundary-side Chain/RingModule machinery needs in scope. This is the opposite convention from CellularHomologyContext's stream.filtrationOrdering, which is deliberately reversed so ITS leadingCell means youngest -- see WORKLOG-cohomology.md for the full "transpose + reverse filtration order" derivation from the paper. Safe to declare at class scope (unlike the chainRM hazard documented on CellularHomologyContext): this ordering is self-contained, built directly from filtrationValue/si rather than by summoning some other ambient Ordering, so there is no stream-not-yet-available timing issue to worry about here.
Ascending by filtration value; ties broken so a LARGER combinatorial index sorts as OLDER (smaller) -- the lexicographically-refined tie-break Definition 3.2/Proposition 3.9 rely on. Chain's leadingCell is the MINIMUM under whatever Ordering is supplied (Chain.from builds its PriorityQueue with ord.reverse), and persistent cohomology's pivot is the OLDEST cofacet in the reduced coboundary chain -- so this ascending ordering, not a reversed one, is what the coboundary-side Chain/RingModule machinery needs in scope. This is the opposite convention from CellularHomologyContext's stream.filtrationOrdering, which is deliberately reversed so ITS leadingCell means youngest -- see WORKLOG-cohomology.md for the full "transpose + reverse filtration order" derivation from the paper. Safe to declare at class scope (unlike the chainRM hazard documented on CellularHomologyContext): this ordering is self-contained, built directly from filtrationValue/si rather than by summoning some other ambient Ordering, so there is no stream-not-yet-available timing issue to worry about here.
Attributes
- Supertypes
- Self type
-
Value members
Concrete methods
Built directly on SimplexIndexing.CofacetCursor, not si.cofacetIterator + si(idx, ...) decode (.claude/WORKLOG-ripser-profiling.md): the vertex-less cofacetIterator would force every candidate to be fully decoded back into a Simplex[Int] and then linearly scanned just to recover the ONE vertex CofacetCursor already hands over directly as cur.vertex, on top of cofacetIteratorWithVertex's own (Int, Long) tuple allocation per candidate -- once the single largest remaining allocation source measured in this engine. tau is built by inserting cur.vertex directly into sigma's own vertex set (sigma.underlying + v, O(log d)), the same incremental-insertion sparseCofacets above already uses.
Built directly on SimplexIndexing.CofacetCursor, not si.cofacetIterator + si(idx, ...) decode (.claude/WORKLOG-ripser-profiling.md): the vertex-less cofacetIterator would force every candidate to be fully decoded back into a Simplex[Int] and then linearly scanned just to recover the ONE vertex CofacetCursor already hands over directly as cur.vertex, on top of cofacetIteratorWithVertex's own (Int, Long) tuple allocation per candidate -- once the single largest remaining allocation source measured in this engine. tau is built by inserting cur.vertex directly into sigma's own vertex set (sigma.underlying + v, O(log d)), the same incremental-insertion sparseCofacets above already uses.
Attributes
Coboundary of a whole chain, linearly extending coboundaryOf. Unlike Chain.scala's .boundary extension (intrinsic to a cell), a coboundary is extrinsic -- it depends on which higher-dimensional simplices exist in this (possibly truncated) complex -- so it lives here rather than as a general-purpose Chain extension. Used by tests to check that a representative essential cocycle genuinely has zero coboundary -- genuinely meaningful at every dimension up to and including maxDimension (not vacuously true at the top dimension anymore, since coboundaryOf now computes a real coboundary there too; see its own doc).
Coboundary of a whole chain, linearly extending coboundaryOf. Unlike Chain.scala's .boundary extension (intrinsic to a cell), a coboundary is extrinsic -- it depends on which higher-dimensional simplices exist in this (possibly truncated) complex -- so it lives here rather than as a general-purpose Chain extension. Used by tests to check that a representative essential cocycle genuinely has zero coboundary -- genuinely meaningful at every dimension up to and including maxDimension (not vacuously true at the top dimension anymore, since coboundaryOf now computes a real coboundary there too; see its own doc).
Attributes
How many times the on-the-fly substitution above actually fired during the most recent persistentCohomology() call -- i.e. how many times some OTHER column's reduction reached an apparent pair's tau as an unresolved pivot and had to recompute that pair's coboundary on the fly. Exposed purely for testing: WORKLOG-lazy-enumeration.md's whole point is that this should be RARE (most apparent pairs are never looked up by anyone else's reduction) -- a test that only checks the final barcode is unchanged cannot distinguish "the fallback fired and computed correctly" from "the fallback never fired at all," so a discriminating test needs this counter, not just the bars.
How many times the on-the-fly substitution above actually fired during the most recent persistentCohomology() call -- i.e. how many times some OTHER column's reduction reached an apparent pair's tau as an unresolved pivot and had to recompute that pair's coboundary on the fly. Exposed purely for testing: WORKLOG-lazy-enumeration.md's whole point is that this should be RARE (most apparent pairs are never looked up by anyone else's reduction) -- a test that only checks the final barcode is unchanged cannot distinguish "the fallback fired and computed correctly" from "the fallback never fired at all," so a discriminating test needs this counter, not just the bars.
Attributes
Total number of simplices actually assembled across all dimensions during the most recent persistentCohomology() call -- exposed for testing. NOT Σ binomial(n, d+1): that formula assumes every combinatorially-possible subset exists, which is only true at maxFiltrationValue = +Infinity. For a genuinely thresholded complex most subsets never get generated at all (see sparseCofacets), so the finite*2 + essential == totalSimplices structural invariant RipserCohomologySpec checks needs THIS count, not the binomial formula, once a finite threshold is in play.
Total number of simplices actually assembled across all dimensions during the most recent persistentCohomology() call -- exposed for testing. NOT Σ binomial(n, d+1): that formula assumes every combinatorially-possible subset exists, which is only true at maxFiltrationValue = +Infinity. For a genuinely thresholded complex most subsets never get generated at all (see sparseCofacets), so the finite*2 + essential == totalSimplices structural invariant RipserCohomologySpec checks needs THIS count, not the binomial formula, once a finite threshold is in play.
Attributes
Concrete fields
Optionally-memoized wrapper around rawFiltrationValue: MaximumDistanceFiltrationValue.apply recomputes an O(d^2) max over pairwise vertex distances from scratch on every call, with no caching of its own. Gated behind memoizeFiltrationValue (default false -- see the class doc above for why): the enumeration/assembly path (insertionDiameter, sparseCofacets, persistentCohomology's own per-dimension loop) never goes through this at all, carrying diameters incrementally instead, so this field's remaining callers are cohomologyOrdering (consulted on every SortedMap/PriorityQueue comparison inside Chain.reduceBy's reduction machinery) plus the handful of once-per-simplex lookups in coboundaryOf/zeroPivotCofacet/zeroPivotFacet/bar-endpoint reporting. See .claude/WORKLOG-lazy-enumeration.md for the measured cost of leaving this false.
Optionally-memoized wrapper around rawFiltrationValue: MaximumDistanceFiltrationValue.apply recomputes an O(d^2) max over pairwise vertex distances from scratch on every call, with no caching of its own. Gated behind memoizeFiltrationValue (default false -- see the class doc above for why): the enumeration/assembly path (insertionDiameter, sparseCofacets, persistentCohomology's own per-dimension loop) never goes through this at all, carrying diameters incrementally instead, so this field's remaining callers are cohomologyOrdering (consulted on every SortedMap/PriorityQueue comparison inside Chain.reduceBy's reduction machinery) plus the handful of once-per-simplex lookups in coboundaryOf/zeroPivotCofacet/zeroPivotFacet/bar-endpoint reporting. See .claude/WORKLOG-lazy-enumeration.md for the measured cost of leaving this false.
Attributes
Givens
Givens
Ascending by filtration value; ties broken so a LARGER combinatorial index sorts as OLDER (smaller) -- the lexicographically-refined tie-break Definition 3.2/Proposition 3.9 rely on. Chain's leadingCell is the MINIMUM under whatever Ordering is supplied (Chain.from builds its PriorityQueue with ord.reverse), and persistent cohomology's pivot is the OLDEST cofacet in the reduced coboundary chain -- so this ascending ordering, not a reversed one, is what the coboundary-side Chain/RingModule machinery needs in scope. This is the opposite convention from CellularHomologyContext's stream.filtrationOrdering, which is deliberately reversed so ITS leadingCell means youngest -- see WORKLOG-cohomology.md for the full "transpose + reverse filtration order" derivation from the paper. Safe to declare at class scope (unlike the chainRM hazard documented on CellularHomologyContext): this ordering is self-contained, built directly from filtrationValue/si rather than by summoning some other ambient Ordering, so there is no stream-not-yet-available timing issue to worry about here.
Ascending by filtration value; ties broken so a LARGER combinatorial index sorts as OLDER (smaller) -- the lexicographically-refined tie-break Definition 3.2/Proposition 3.9 rely on. Chain's leadingCell is the MINIMUM under whatever Ordering is supplied (Chain.from builds its PriorityQueue with ord.reverse), and persistent cohomology's pivot is the OLDEST cofacet in the reduced coboundary chain -- so this ascending ordering, not a reversed one, is what the coboundary-side Chain/RingModule machinery needs in scope. This is the opposite convention from CellularHomologyContext's stream.filtrationOrdering, which is deliberately reversed so ITS leadingCell means youngest -- see WORKLOG-cohomology.md for the full "transpose + reverse filtration order" derivation from the paper. Safe to declare at class scope (unlike the chainRM hazard documented on CellularHomologyContext): this ordering is self-contained, built directly from filtrationValue/si rather than by summoning some other ambient Ordering, so there is no stream-not-yet-available timing issue to worry about here.