SimplexIndexing

org.appliedtopology.tda4j.streams.SimplexIndexing
See theSimplexIndexing companion object
class SimplexIndexing(val vertexCount: Int)

Attributes

Companion
object
Experimental
true
Graph
Supertypes
class Object
trait Matchable
class Any

Members list

Type members

Classlikes

final class CofacetCursor(startIndex: Long, size: Int, allCofacets: Boolean)

A hasNext/vertex/index/advance() cursor over sigma's cofacets, factored out of what cofacetIteratorWithVertex used to do directly as a hand-rolled Iterator[(Int, Long)], so a caller can read vertex/index as plain field accesses with zero per-step allocation -- not even the (Int, Long) tuple an Iterator[(Int, Long)] contract forces on every next() call. hasNext/advance() are deliberately split from a single next(): vertex/index stay valid to re-read as many times as a caller wants between one advance() and the next (both PackedRipserCohomology.scala's coboundaryOf and Homology.scala read both fields off one candidate before advancing).

A hasNext/vertex/index/advance() cursor over sigma's cofacets, factored out of what cofacetIteratorWithVertex used to do directly as a hand-rolled Iterator[(Int, Long)], so a caller can read vertex/index as plain field accesses with zero per-step allocation -- not even the (Int, Long) tuple an Iterator[(Int, Long)] contract forces on every next() call. hasNext/advance() are deliberately split from a single next(): vertex/index stay valid to re-read as many times as a caller wants between one advance() and the next (both PackedRipserCohomology.scala's coboundaryOf and Homology.scala read both fields off one candidate before advancing).

Decodes sigma via decodeToArray (a plain sorted Array[Int], binary-searched for membership), not apply (a Simplex[Int]/SortedSet[Int], O(log d) tree lookup per membership check) -- the same array-over-tree substitution decodeToArray's own doc motivates, folded in here since this cursor replaces cofacetIteratorWithVertex's body outright rather than wrapping it.

Attributes

Supertypes
class Object
trait Matchable
class Any
final class FacetCursor(startIndex: Long, size: Int)

A hasNext/vertex/index/advance() cursor over tau's facets, mirroring CofacetCursor above -- vertex is the vertex REMOVED to produce the facet at index. _index is iiB + iA (the OLD iA, before this step's own update), not iiB + iiA -- easy to invert by mistake, so kept exactly. Decodes tau via decodeToArray, not apply(...).toSeq.sorted (a Simplex[Int] decode followed by a redundant re-sort of an already-sorted SortedSet).

A hasNext/vertex/index/advance() cursor over tau's facets, mirroring CofacetCursor above -- vertex is the vertex REMOVED to produce the facet at index. _index is iiB + iA (the OLD iA, before this step's own update), not iiB + iiA -- easy to invert by mistake, so kept exactly. Decodes tau via decodeToArray, not apply(...).toSeq.sorted (a Simplex[Int] decode followed by a redundant re-sort of an already-sorted SortedSet).

Attributes

Supertypes
class Object
trait Matchable
class Any

Value members

Concrete methods

final def apply(n: Long, d: Int, upperAccum: Simplex[Int] = ...): Simplex[Int]

Uses the binomial numbering system to generate the nth simplex of dimension d-1, that is the nth subset of size d of the vertices.

Uses the binomial numbering system to generate the nth simplex of dimension d-1, that is the nth subset of size d of the vertices.

If n is greater than (vertexCount choose d) the result will not be a subset of size d.

n is Long, not Int -- see binomial's own doc: a combinatorial index can be astronomically larger than vertexCount/d themselves. The d == 0 base case converts back to Int via .toInt safely: by this algorithm's own invariant, the residual n at d == 0 is always a single vertex id, never a combinatorial index anymore.

Attributes

def apply(simplex: Simplex[Int]): Long
def cofacetCursor(index: Long, size: Int, allCofacets: Boolean = ...): CofacetCursor
def cofacetIterator(simplex: Simplex[Int]): Iterator[Long]
def cofacetIterator(index: Long, size: Int, allCofacets: Boolean = ...): Iterator[Long]
def cofacetIteratorWithVertex(index: Long, size: Int, allCofacets: Boolean = ...): Iterator[(Int, Long)]

Same enumeration as cofacetIterator, but also yields the INSERTED vertex alongside each cofacet index -- needed by a packed (index-only) reduction that has no materialized Simplex[Int] to recover it from afterward ((tau.underlying diff sigma.underlying).head, coboundaryOf's own approach, requires decoding tau). Now a thin Iterator[(Int, Long)] wrapper over CofacetCursor above, kept because cofacetIterator below and SimplexIndexingSpec's own Iterator-based assertions still go through it -- new call sites use cofacetCursor directly.

Same enumeration as cofacetIterator, but also yields the INSERTED vertex alongside each cofacet index -- needed by a packed (index-only) reduction that has no materialized Simplex[Int] to recover it from afterward ((tau.underlying diff sigma.underlying).head, coboundaryOf's own approach, requires decoding tau). Now a thin Iterator[(Int, Long)] wrapper over CofacetCursor above, kept because cofacetIterator below and SimplexIndexingSpec's own Iterator-based assertions still go through it -- new call sites use cofacetCursor directly.

Attributes

def decodeToArray(n0: Long, size: Int): Array[Int]

Same decode as apply(n, size), but returns the vertex set as a plain sorted Array[Int] instead of a Simplex[Int]/SortedSet[Int] -- for callers (PackedRipserCohomologyContext.sparseCofacets/coboundaryOf/ zeroPivotCofacet) that only ever wanted si(index, size).underlying.toArray and threw the decoded Simplex away immediately afterward. apply's own upperAccum + (id + d) builds the result via size separate persistent-tree insertions (each an O(log size) allocation this throwaway value never needs). This method performs the identical searchRow/binomialEntry arithmetic as apply -- a direct transcription of the same three base cases and recursive step -- but writes each vertex into a pre-sized Array[Int] and sorts once at the end (java.util.Arrays.sort, in-place, zero allocation) instead. Verified against apply directly (same vertex set, for every (index, size) pair the recursion can reach) in SimplexIndexingSpec's property test; apply itself is left unchanged, so any future divergence between the two shows up as a test failure.

Same decode as apply(n, size), but returns the vertex set as a plain sorted Array[Int] instead of a Simplex[Int]/SortedSet[Int] -- for callers (PackedRipserCohomologyContext.sparseCofacets/coboundaryOf/ zeroPivotCofacet) that only ever wanted si(index, size).underlying.toArray and threw the decoded Simplex away immediately afterward. apply's own upperAccum + (id + d) builds the result via size separate persistent-tree insertions (each an O(log size) allocation this throwaway value never needs). This method performs the identical searchRow/binomialEntry arithmetic as apply -- a direct transcription of the same three base cases and recursive step -- but writes each vertex into a pre-sized Array[Int] and sorts once at the end (java.util.Arrays.sort, in-place, zero allocation) instead. Verified against apply directly (same vertex set, for every (index, size) pair the recursion can reach) in SimplexIndexingSpec's property test; apply itself is left unchanged, so any future divergence between the two shows up as a test failure.

apply's own Simplex[Int]-returning callers are NOT switched to this method: building a SortedSet[Int] from an already-sorted array is not obviously cheaper than apply's own incremental construction (TreeSet has no exposed O(n) bulk-build-from-sorted-input path), so there's no clear win, only a different allocation shape -- left alone rather than "fixed" without a measurement to justify it.

Attributes

def facetCursor(index: Long, size: Int): FacetCursor
def facetIterator(index: Long, size: Int): Iterator[Long]

Now a thin Iterator[Long] wrapper over FacetCursor above, kept for SimplexIndexingSpec's own Iterator-based assertions -- new call sites use facetCursor directly.

Now a thin Iterator[Long] wrapper over FacetCursor above, kept for SimplexIndexingSpec's own Iterator-based assertions -- new call sites use facetCursor directly.

Attributes

def topCofacetIterator(simplex: Simplex[Int]): Iterator[Long]

Concrete fields

val vertexCount: Int