Skip to content

Criteria and configuration

DOptimality dataclass

DOptimality()

Maximize the log determinant in the informative score subspace.

to_dict

to_dict() -> dict[str, JsonValue]

Return the JSON-compatible criterion contract.

ProfiledDOptimality dataclass

ProfiledDOptimality(interest: tuple[int, ...] | tuple[str, ...])

Maximize profiled information for declared parameters of interest.

Nuisance information is estimated from the same labels. The full-data efficient-score upper problem is intentionally a separate workflow.

Parameters:

  • interest (tuple[int, ...] | tuple[str, ...]) –

    The parameters of interest, either as unique nonnegative score-column indices or as unique parameter names. Names require a :class:~scorequant.ScoreSchema on the sample being optimized and are resolved to indices once, at the public task boundary. At least one nuisance column must remain when the criterion is applied.

Examples:

>>> ProfiledDOptimality(interest=(4,)).interest
(4,)
>>> ProfiledDOptimality(interest=("HSPCs",)).interest
('HSPCs',)

named property

named: bool

Whether interest is expressed as parameter names rather than indices.

interest_indices property

interest_indices: tuple[int, ...]

Return the parameters of interest as score-column indices.

Every consumer downstream of the public task boundary -- the profiled objective, the information algebra, the soft solver and the reports -- reads this rather than interest, so an unresolved criterion fails here by name instead of indexing a score matrix with a string.

__post_init__

__post_init__() -> None

Validate the representation-independent part of the block contract.

resolve

resolve(schema: ScoreSchema | None) -> ProfiledDOptimality

Return an equivalent criterion whose interest is score-column indices.

Downstream information algebra, solvers and reports consume indices only, so names are translated exactly once here rather than being re-resolved at every consumer.

Raises:

  • ValueError

    When names were supplied but the sample carries no schema to resolve them against.

  • KeyError

    When a name is not declared by the schema.

to_dict

to_dict() -> dict[str, JsonValue]

Return the JSON-compatible same-label profiling contract.

NormalizedTrace dataclass

NormalizedTrace()

Minimize within-bin distortion after Fisher whitening.

to_dict

to_dict() -> dict[str, JsonValue]

Return the JSON-compatible criterion contract.

DExchangeConfig dataclass

DExchangeConfig(rank_rtol: float | None = None, seed: int = 0, initializer_restarts: int = 8, max_scans: int | None = None, batch_moves: bool = True, solver_restarts: int = 1, init: Literal['kmeans++', 'random'] = 'kmeans++', gain_tolerance: float = 1e-10, first_improvement: bool = False, collapse_duplicates: bool | None = None)

Configure exact positive-gain D-optimal point exchange.

One scan is one complete evaluation of every admissible single-row relocation. A scan accepts either one move or, under batch_moves, many relocations at once, so accepted_moves and scans are different quantities.

Parameters:

  • rank_rtol (float | None, default: None ) –

    Relative threshold for the informative Fisher subspace.

  • seed (int, default: 0 ) –

    Base seed of deterministic initialization. Exchange restart r uses seed + r.

  • initializer_restarts (int, default: 8 ) –

    Number of k-means seeding restarts inside one exchange restart. This nests inside solver_restarts: the total seeding work is the product of the two.

  • max_scans (int | None, default: None ) –

    Maximum number of complete candidate scans. None runs until the exchange is stable, which strict positive-gain acceptance guarantees; a generous internal safety bound still stops a numerically pathological run and records best_remaining_gain.

  • batch_moves (bool, default: True ) –

    Relocate many positive-gain rows per scan. The batch is ranked by gain, truncated before it would displace too much of any cell's weight, and accepted only when the exactly recomputed objective strictly improves; a rejected batch is halved and retried, finally falling back to the single best move. Small improving sets always use that single exact move, so results match batch_moves=False on small samples. Ignored when first_improvement is set.

  • solver_restarts (int, default: 1 ) –

    Number of independent exchange restarts. The restart with the best exact final objective wins, ties resolving to the earliest restart, and every reported diagnostic describes that winning restart.

  • init (Literal['kmeans++', 'random'], default: 'kmeans++' ) –

    Initial labeling of each restart: weighted k-means++ seeding or a balanced random labeling.

  • gain_tolerance (float, default: 1e-10 ) –

    Strict minimum accepted log-determinant gain.

  • first_improvement (bool, default: False ) –

    Accept the first improving move in deterministic row/bin order instead of the best move in a scan. This stops each scan early, so it forces single-move acceptance and disables batch_moves.

  • collapse_duplicates (bool | None, default: None ) –

    Merge identical score rows into one weighted atom before solving. None (default) collapses automatically below 100,000 effective rows and skips it above, since the O(N log N) merge only pays for itself against the O(N) exchange scan it speeds up on samples with many repeated score atoms. True/False always collapses or always skips, regardless of sample size.

__post_init__

__post_init__() -> None

Validate exchange settings at construction time.

to_dict

to_dict() -> dict[str, JsonValue]

Return a JSON-compatible configuration mapping.

MahalanobisLloydConfig dataclass

MahalanobisLloydConfig(rank_rtol: float | None = None, seed: int = 0, initializer_restarts: int = 8, max_iter: int = 100, guard: Literal['exchange', 'reject'] = 'exchange', gain_tolerance: float = 1e-10, collapse_duplicates: bool | None = None)

Configure guarded batch Mahalanobis-Lloyd iteration.

One iteration freezes the current criterion metric, proposes the complete nearest-centroid relabeling of every row in that metric, and accepts the proposal only when the exactly rebuilt objective strictly improves. The unguarded batch step is not monotone: the tangent of the concave log determinant is an upper bound, not a minorizer, and a committed eight-row fixture loses 0.136521 nat in one such step. The guard is therefore part of the solver contract, not an optional safeguard.

Parameters:

  • rank_rtol (float | None, default: None ) –

    Relative threshold for the informative Fisher subspace.

  • seed (int, default: 0 ) –

    Nonnegative seed of the deterministic k-means seeding.

  • initializer_restarts (int, default: 8 ) –

    Number of weighted k-means++ restarts used to seed the labels.

  • max_iter (int, default: 100 ) –

    Maximum number of guarded batch iterations.

  • guard (Literal['exchange', 'reject'], default: 'exchange' ) –

    Behavior once a proposal stops improving. "exchange" hands the labels to the exact positive-gain exchange engine, so the reported state is exchange-stable and a nonsingular D result stays compilable. "reject" stops at the last accepted labeling and only certifies exchange stability with one final scan, which may report False.

  • gain_tolerance (float, default: 1e-10 ) –

    Strict minimum accepted objective gain, shared by the guarded batch and the exchange phase.

  • collapse_duplicates (bool | None, default: None ) –

    Merge identical score rows into one weighted atom before solving. None (default) collapses automatically below 100,000 effective rows and skips it above, since the O(N log N) merge only pays for itself against the O(N) work it speeds up on samples with many repeated score atoms. True/False always collapses or always skips, regardless of sample size.

__post_init__

__post_init__() -> None

Validate the guarded batch settings at construction time.

to_dict

to_dict() -> dict[str, JsonValue]

Return a JSON-compatible configuration mapping.

KMeansConfig dataclass

KMeansConfig(whiten: bool = True, rank_rtol: float | None = None, seed: int = 0, solver_restarts: int = 8, max_iter: int = 100, tolerance: float = 1e-06, record_every: int = 1)

Configure deterministic weighted score-space k-means.

Parameters:

  • whiten (bool, default: True ) –

    Whiten retained Fisher directions before computing distances.

  • rank_rtol (float | None, default: None ) –

    Relative eigenvalue threshold for informative-rank selection. The dtype-aware default is used when omitted.

  • seed (int, default: 0 ) –

    Nonnegative JAX random seed.

  • solver_restarts (int, default: 8 ) –

    Number of weighted k-means++ restarts after invariant row ordering. This is k-means' own restart count: the run with the lowest final objective wins.

  • max_iter (int, default: 100 ) –

    Maximum Lloyd iterations per restart.

  • tolerance (float, default: 1e-06 ) –

    Relative objective-change convergence tolerance.

  • record_every (int, default: 1 ) –

    Number of Lloyd iterations between trace snapshots.

__post_init__

__post_init__() -> None

Validate the complete configuration at construction time.

to_dict

to_dict() -> dict[str, JsonValue]

Return a JSON-compatible configuration mapping.

SoftVoronoiConfig dataclass

SoftVoronoiConfig(whiten: bool = True, rank_rtol: float | None = None, seed: int = 0, initializer_restarts: int = 8, kmeans_max_iter: int = 100, tolerance: float = 1e-06, max_steps: int = 1000, learning_rate: float = 0.01, gradient_clip: float = 10.0, temperature_end_ratio: float = 0.05, record_every: int = 10)

Configure differentiable D-optimal soft Voronoi fitting.

Parameters:

  • whiten (bool, default: True ) –

    Whiten retained Fisher directions before computing distances.

  • rank_rtol (float | None, default: None ) –

    Relative eigenvalue threshold for informative-rank selection. The dtype-aware default is used when omitted.

  • seed (int, default: 0 ) –

    Nonnegative JAX random seed.

  • initializer_restarts (int, default: 8 ) –

    Number of k-means restarts used to initialize the centers.

  • kmeans_max_iter (int, default: 100 ) –

    Maximum Lloyd iterations for each initialization restart.

  • tolerance (float, default: 1e-06 ) –

    Relative convergence tolerance for initialization.

  • max_steps (int, default: 1000 ) –

    Number of Adam updates.

  • learning_rate (float, default: 0.01 ) –

    Adam learning rate before scaling by initial center separation.

  • gradient_clip (float, default: 10.0 ) –

    Global gradient-norm clipping threshold.

  • temperature_end_ratio (float, default: 0.05 ) –

    Final temperature divided by the initial temperature.

  • record_every (int, default: 10 ) –

    Number of Adam steps between trace snapshots.

__post_init__

__post_init__() -> None

Validate the complete configuration at construction time.

to_dict

to_dict() -> dict[str, JsonValue]

Return a JSON-compatible configuration mapping.

ScalarDPConfig dataclass

ScalarDPConfig(whiten: bool = True, rank_rtol: float | None = None, seed: int = 0, max_rows: int = 20000)

Configure exact interval dynamic programming for one score coordinate.

The solver is exact and deterministic: on a rank-one score law the optimal hard partition has ordered interval cells, and the weighted interval dynamic program returns the global optimum rather than a local one.

Parameters:

  • whiten (bool, default: True ) –

    Whiten the single retained Fisher direction before solving. Scalar whitening is a strictly positive rescaling, so it never changes the optimal interval labels; it fixes the units of the reported within-segment objective and matches the other score-space solvers.

  • rank_rtol (float | None, default: None ) –

    Relative threshold for the informative score direction.

  • seed (int, default: 0 ) –

    Nonnegative seed recorded for reproducibility. The dynamic program consumes no randomness and resolves ties by the smallest split index.

  • max_rows (int, default: 20000 ) –

    Maximum number of distinct positive-weight score atoms. The exact dynamic program uses quadratic work in this count and is evaluated in memory-bounded stripes.

__post_init__

__post_init__() -> None

Validate the exact-solver capacity contract.

to_dict

to_dict() -> dict[str, JsonValue]

Return a JSON-compatible configuration mapping.