Skip to content

Pluggable combination rules for ensemble rank selection #42

@jc-macdonald

Description

@jc-macdonald

Summary

Implement a set of combination rules that take layer-level rank decisions (k₁, k₂, k₃ from pp-eigentest's RankSelectionResult) and produce a final rank. These should be pluggable strategies that can be swept as a design factor.

Motivation

pp-eigentest's _combine_layer_ranks() currently hardcodes one rule: majority → parsimony. The pp-eigentest paper Stage B needs to compare multiple combination strategies. Rather than adding all of these to the pp-eigentest package itself (which should remain focused on the spectral test), combination/ensembling logic belongs in trade-study as reusable evaluation infrastructure.

Proposed rules

Rule Logic
majority_parsimony All agree → use it; 2-of-3 agree → use majority; all differ → min(positive) or 0
maximum max(k₁, k₂, k₃) — aggressive, favours signal detection
minimum min(k₁, k₂, k₃) — conservative, favours parsimony
layer3_dominant Use k₃ (hypothesis test) unless k₃ = 0 and both others agree on k > 0
hierarchical_filter See #43 — L1 caps, L2 sharpens within cap, L3 confirms

Design

CombinationRule = Callable[[int, int, int], tuple[int, str]]
# Returns (final_rank, rule_name_used)

COMBINATION_RULES: dict[str, CombinationRule] = {
    "majority_parsimony": ...,
    "maximum": ...,
    "minimum": ...,
    "layer3_dominant": ...,
    "hierarchical_filter": ...,
}

These operate on the layer-level decisions already recorded in pp-eigentest simulation output (k_layer1, k_layer2, k_layer3 columns), so Stage B can be computed post-hoc from Stage A data without re-running the expensive null simulations.

Acceptance criteria

  • All 5 rules implemented with consistent signature
  • Registered in a dispatcher dict for sweep-by-name
  • Works as a Factor in design.py (categorical, 5 levels)
  • Unit tests with known layer inputs → expected final ranks
  • Post-hoc application function: takes DataFrame with k_layer1/2/3 columns, applies rule, returns new final_rank column

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions