/**
 * Bradley-Terry / Elo tournament evaluation.
 *
 * For multi-candidate sweeps, comparing every candidate's score against
 * a fixed comparator wastes information — the comparator becomes a high-
 * variance reference and rank flips between near-tied middle-rank
 * candidates are dominated by noise. Pairwise tournaments fix this:
 * every (i, j) pair contributes a comparison to a Bradley-Terry MLE that
 * estimates each candidate's strength on a unified scale.
 *
 * For online updating (rolling campaigns where new candidates arrive
 * over time), we also ship classical Elo with configurable K-factor.
 *
 * References:
 *   - Bradley, R. A., Terry, M. E. (1952). Rank analysis of incomplete
 *     block designs. Biometrika, 39(3/4), 324–345.
 *   - Hunter, D. R. (2004). MM algorithms for generalized Bradley-Terry
 *     models. Annals of Statistics, 32(1), 384–406. (The MLE algorithm
 *     used here.)
 *   - Elo, A. E. (1978). The Rating of Chess Players, Past and Present.
 *
 * This is a useful primitive because most LLM-eval communities (Chatbot
 * Arena, AlpacaEval, ELO-style ablation) have converged on pairwise
 * tournament eval as the most sample-efficient and most rank-stable
 * method when you have many candidates.
 */
export interface PairwiseOutcome {
    /** Winner candidate id. */
    winner: string;
    /** Loser candidate id. */
    loser: string;
    /**
     * Optional draw flag. When true, both candidates get half-credit
     * (Bradley-Terry handles draws as half-wins for each side).
     */
    draw?: boolean;
    /**
     * Optional weight — useful if some pairwise comparisons are stronger
     * signals than others (e.g. a paired test with a wider score gap is
     * a more confident comparison). Default 1.
     */
    weight?: number;
}
export interface BradleyTerryRating {
    candidateId: string;
    /** Latent strength θ ≥ 0 from the BT MLE. */
    strength: number;
    /** Log-strength = log(θ) — interpretable on a linear scale. */
    logStrength: number;
    /** Number of pairwise comparisons this candidate appears in. */
    n: number;
    /** Win count (+ 0.5 per draw). */
    wins: number;
}
export interface BradleyTerryFit {
    ratings: BradleyTerryRating[];
    /** Iterations of the MM algorithm before convergence. */
    iterations: number;
    /** Final maximum |θ_new - θ_old| / θ_old. */
    finalDelta: number;
    converged: boolean;
}
/**
 * Bradley-Terry MLE via Hunter's MM algorithm.
 *
 * Iteration: θ_i^new = W_i / Σ_{j ≠ i} N_ij / (θ_i + θ_j)
 *   where W_i = wins by i (+ 0.5 per draw), N_ij = total comparisons.
 *
 * Returns log-strengths normalized so the smallest is 0 (any constant
 * offset is unobservable in BT — only differences are identified).
 */
export declare function fitBradleyTerry(outcomes: PairwiseOutcome[], opts?: {
    tolerance?: number;
    maxIterations?: number;
    smoothing?: number;
}): BradleyTerryFit;
/**
 * Online Elo updates. Use when comparisons arrive over time and you want
 * a running rating without re-fitting the full BT MLE on every update.
 *
 * Initialize ratings to `defaultRating` (1500 by default). Each call to
 * `applyEloUpdate` mutates the map in place and returns the deltas so
 * the caller can log per-comparison rating changes.
 */
export interface EloOptions {
    /** Default rating for unseen candidates. Default 1500. */
    defaultRating?: number;
    /** K-factor controls the step size. Default 32 (FIDE-ish). */
    kFactor?: number;
}
export declare function applyEloUpdate(ratings: Map<string, number>, outcome: PairwiseOutcome, opts?: EloOptions): {
    winnerDelta: number;
    loserDelta: number;
};
/**
 * Build pairwise outcomes from the campaign artifact: for every scenario
 * shared by two candidates, the higher-scoring run wins. Useful when you
 * want a tournament view of an existing campaign without an additional
 * pairwise judge call.
 */
export interface BuildPairwiseFromCampaignInput {
    runs: Array<{
        candidateId: string;
        /** Stable identifier for the matching unit (typically scenarioId). */
        matchKey: string;
        score: number;
    }>;
    /**
     * Tied-score margin. Below this, the comparison is a draw. Default 0
     * (no ties).
     */
    drawMargin?: number;
}
export declare function buildPairwiseFromCampaign(input: BuildPairwiseFromCampaignInput): PairwiseOutcome[];
//# sourceMappingURL=tournament.d.ts.map