Mapping the library: class diagrams

This page is a structural sketch to help you get oriented, not an exhaustive or automatically generated reference — field names and signatures can drift out of sync with source over time. When a diagram and the actual .scala file disagree, trust the file.

Typeclass hierarchy (RingModule.scala, Field.scala, Chain.scala)

classDiagram
    class RingModule {
        <<typeclass: type Self, type R>>
        zero: Self
        plus(x, y) Self
        minus(x, y) Self
        negate(x) Self
        scale(r, y) Self
        +(rhs) Self
        -(rhs) Self
        unary_-() Self
        R.⊠(t) Self
    }
    class Field {
        <<typeclass: type Self>>
        plus(x, y) Self
        times(x, y) Self
        divide(x, y) Self
        invert(x) Self
        zero: Self
        one: Self
    }
    class HasDimension {
        <<typeclass: type Self>>
        dim: Int
    }
    class Cell {
        <<typeclass: type Self, extends HasDimension>>
        boundary~CoefficientT~() Seq~Tuple2~
    }
    class OrderedCell {
        <<typeclass: type Self : Ordering as ordering, extends Cell>>
    }
    class OrderedBasis {
        <<typeclass: type Self, requires CellT:Ordering, CoefficientT:Field>>
        leadingCell: Option~CellT~
        leadingCoefficient: CoefficientT
        leadingTerm: Tuple2
    }
    HasDimension <|-- Cell
    Cell <|-- OrderedCell
    Simplex ..|> OrderedCell : given instance
    Cube ..|> OrderedCell : given instance
    FiniteSimplicialSet ..|> OrderedCell : per-instance given (cellInstance)
    Chain ..|> OrderedBasis : given instance
    Chain ..|> RingModule : given instance

Three concrete OrderedCell instances exist: Simplex[VertexT], Cube, and a FiniteSimplicialSet[G]'s own generators (that last one is a per-instance given, not a global one, since its boundary depends on that particular simplicial set's own face data). There is no dual Cocell/OrderedCocell trait pair (an earlier version had one; removed as the wrong shape for coboundary, which is extrinsic to a cell, not intrinsic like boundary) — RipserCohomologyContext/PackedRipserCohomologyContext compute coboundaries directly against SimplexIndexing instead (see Persistence engines). See the Scala 3 primer for what "typeclass: type Self" and "given instance" mean concretely in this codebase's syntax.

Chain[CellT, CoefficientT] (Chain.scala)

classDiagram
    class Chain {
        -entries: PriorityQueue~Tuple2~
        collapseHead() Unit
        collapseAll() Unit
        isZero() Boolean
        items: Seq~Tuple2~
    }
    class `Chain$` {
        <<companion object>>
        empty~CellT,CoefficientT~() Chain
        apply(cs: Tuple2*) Chain
        from(cs: Seq~Tuple2~) Chain
        reduceBy(z, basis, log) Tuple2
        reduceByUntil(z, basis, log, stop) Tuple2
    }
    `Chain$` ..> Chain : constructs

reduceBy/reduceByUntil are the shared reduction primitives every persistence engine in Homology.scala builds on — see Architecture and Hard-won invariants #4.

Simplex[VertexT] (Simplex.scala, SimplexOps.scala)

classDiagram
    class Simplex {
        <<opaque type = SortedSet~VertexT~>>
        underlying: SortedSet~VertexT~
        dim: Int
        boundary~CoefficientT~() Seq~Tuple2~
    }
    class `Simplex$` {
        <<companion object>>
        apply(vertices: VertexT*) Simplex
        from(vertices: Seq~VertexT~) Simplex
        unapplySeq(s: Simplex) Option~Seq~
    }
    Simplex ..|> OrderedCell : given defaultSimplexIsOrderedCell

SimplexOps.scala adds a large extension block delegating most of SortedSet's surface (.size, .map, .union, .dropIndex, ...) so Simplex "feels like" a set even though it's a zero-cost opaque wrapper at runtime — see the primer.

Streams (SimplexStream.scala, SimplexIndexing.scala, VietorisRips.scala)

classDiagram
    class Filtration {
        <<typeclass: CellT:Cell, FiltrationT:Ordering,FiltrationT:Filterable>>
        filtrationValue: PartialFunction
    }
    class CellStream {
        <<typeclass: extends Filtration, IterableOnce>>
        filtrationOrdering: Ordering~CellT~
    }
    class SimplexStream {
        <<CellStream specialized to Simplex~VertexT~>>
    }
    class StratifiedCellStream {
        iterateDimension: PartialFunction~Int, Iterator~
    }
    Filtration <|-- CellStream
    CellStream <|-- SimplexStream
    CellStream <|-- StratifiedCellStream
    SimplexStream <|-- StratifiedSimplexStream
    StratifiedCellStream <|-- StratifiedSimplexStream
    StratifiedSimplexStream <|-- CofaceSimplexStream
    CofaceSimplexStream <|-- EnumeratingCofaceSimplexStream
    EnumeratingCofaceSimplexStream <|-- RipserCofaceSimplexStream
    RipserCofaceSimplexStream <|-- CechCofaceSimplexStream
    RipserCofaceSimplexStream <|-- LazyWitnessSimplexStream
    RipserCofaceSimplexStream <|-- WitnessCofaceSimplexStream
    RipserCofaceSimplexStream <|-- SheehyRipsSimplexStream
    RipserCofaceSimplexStream <|-- DowkerCofaceSimplexStream
    EnumeratingCofaceSimplexStream <|-- InorderCofaceSimplexStream
    SimplexStream <|-- ExplicitStream
    StratifiedSimplexStream <|-- RecursiveStackVietorisRipsSimplexStream
    StratifiedSimplexStream <|-- IncrementalVietorisRipsSimplexStream
    StratifiedSimplexStream <|-- AlphaShapes
    AlphaShapes <|-- HelixDelaunay
    AlphaShapes <|-- AlphaShapeDQP
    StratifiedCellStream <|-- CubicalGridStream
    StratifiedCellStream <|-- ExplicitCubicalStream
    CellStream <|-- SimplicialSetStream
    StratifiedCellStream <|-- FilteredSimplicialSetStream

These are alternate stream implementations with a common output contract, not layers on top of one another — see Architecture. CubicalGridStream/ExplicitCubicalStream produce Cubes rather than Simplexes; SimplicialSetStream/FilteredSimplicialSetStream produce a FiniteSimplicialSet[G]'s own generator type G.

Persistence engines (homology/Homology.scala, homology/PackedRipserCohomology.scala, homology/FastCubicalHomology.scala, homology/FastAlphaHomology.scala)

Deliberately not diagrammed field-by-field here — their exact state and trust status belongs in one place. See Persistence engines for the full, current picture across CellularHomologyContext/SimplicialHomologyContext, CellularPersistenceInChunksContext/PersistenceInChunksContext, RipserCohomologyContext, PackedRipserCohomologyContext, CellularCohomologyContext, FastCubicalHomologyContext and FastAlphaHomologyContext (HelixDelaunay alpha complexes) -- both valid at any ambient dimension >= 2, both via a chunks hybrid above 2D -- wired into matlab/cli as engine="fast-cubical"/engine="fast-alpha".

Circular coordinates (homology/CircularCoordinates.scala)

classDiagram
    class CircularCoordinates {
        <<object>>
        h1Bars(metricSpace, maxFiltrationValue) IndexedSeq~(Double, Double)~
        compute(metricSpace, r, cocycleIndex, prime, maxFiltrationValue) Result
    }
    class Result {
        theta: Map~Int, Double~
        birth: Double
        death: Double
        r: Double
        prime: Int
    }
    class NoIntegerCocycleException {
        <<RuntimeException>>
    }
    CircularCoordinates --> Result : returns
    CircularCoordinates ..> CellularCohomologyContext : computes K_r's cohomology with
    CircularCoordinates ..> NoIntegerCocycleException : throws (no ℤ-lift at prime)

A standalone construction, not a fifth persistence engine — see Architecture's own homology.CircularCoordinates section for the truncated-complex reframing, the harmonic-smoothing linear system, and why the output is a per-point angle map rather than a barcode.

Metric spaces (FiniteMetricSpace.scala)

classDiagram
    class FiniteMetricSpace {
        <<typeclass: type VertexT>>
        distance(x, y) Double
        size: Int
        elements: Iterable~VertexT~
        minimumEnclosingRadius: Double
    }
    FiniteMetricSpace <|-- IntMetricSpace
    FiniteMetricSpace <|-- ExplicitMetricSpace
    FiniteMetricSpace <|-- EuclideanMetricSpace
    FiniteMetricSpace <|-- SparseMetricSpace
    class SpatialQuery {
        <<typeclass: type VertexT>>
        neighbors(v, epsilon) Set~VertexT~
    }
    SpatialQuery <|-- JVPTree
    SpatialQuery <|-- BruteForce
    SparseMetricSpace --> SpatialQuery : uses (JVPTree)

Barcode representation (Barcode.scala, package org.appliedtopology.tda4j.barcode)

classDiagram
    class BarcodeEndpoint {
        <<sealed trait>>
        flip() BarcodeEndpoint
        isFinite: Boolean
    }
    BarcodeEndpoint <|-- PositiveInfinity
    BarcodeEndpoint <|-- NegativeInfinity
    BarcodeEndpoint <|-- OpenEndpoint
    BarcodeEndpoint <|-- ClosedEndpoint
    class PersistenceBar {
        dim: Int
        lower: BarcodeEndpoint
        upper: BarcodeEndpoint
        annotation: Option~AnnotationT~
    }
    class Barcode {
        isMap(source, target, matrix) Boolean
        image(source, target, matrix) List~PersistenceBar~
        kernel(source, target, matrix) List~PersistenceBar~
        cokernel(source, target, matrix) List~PersistenceBar~
    }
    class BarcodeDistance {
        <<object>>
        bottleneckDistance(diagram1, diagram2, groundNorm) Double
        wassersteinDistance(diagram1, diagram2, order, groundNorm) Double
        bottleneckDistanceByDimension(diagram1, diagram2, groundNorm) Map~Int, Double~
        wassersteinDistanceByDimension(diagram1, diagram2, order, groundNorm) Map~Int, Double~
    }
    class Vectorization {
        <<object>>
        landscape(diagram, numLevels, tMin, tMax, resolution) Array~Array~Double~~
        persistenceImage(diagram, sigma, birthRange, persistenceRange, birthResolution, persistenceResolution, weightCap) Array~Array~Double~~
    }
    BarcodeDistance ..> PersistenceBar : reads
    Vectorization ..> PersistenceBar : reads

AnnotationT in practice is always Chain[CellT, CoefficientT] — the representative cycle/cocycle for a bar, when an engine tracks one. BarcodeDistance/Vectorization only ever read a bar's dim/lower/upper (never annotation), and are specialized to PersistenceBar[Double, _] rather than sharing Barcode's own FiltrationT: Ordering genericity — see Architecture's "Barcode.scala" section for why, and for BipartiteMatching.scala's two package-private combinatorial primitives (HopcroftKarp/Hungarian) BarcodeDistance is built on, omitted here as an implementation detail rather than part of this package's public shape.