mixle.analysis.rank_aggregation module

Rank aggregation, consensus rankings, and permutation distances.

Given several orderings of the same items (voters’ preferences, judges’ rankings, search results to fuse), recover a single consensus ordering and quantify how dispersed the inputs are:

  • borda_count() – positional scoring (fast, the average-rank consensus).

  • copeland() – pairwise-majority (Condorcet-flavoured) scoring.

  • kemeny_consensus() – the median ranking minimising total Kendall-tau distance to the inputs (the maximum-likelihood Condorcet aggregation); exact for small item sets, local search beyond.

  • mallows_fit() – fit a Mallows model: its central ranking (Kemeny consensus) plus a dispersion theta (larger = more agreement among voters).

Permutation distances kendall_distance(), spearman_footrule(), and cayley_distance() are exposed directly. Orderings are passed as sequences of item ids, best first (a permutation of 0..m-1); rankings is a 2-D array with one ordering per row.

kendall_distance(a, b)[source]

Kendall-tau distance: the number of item pairs ordered oppositely by a and b.

Parameters:
Return type:

int

spearman_footrule(a, b)[source]

Spearman footrule distance: the sum of absolute position differences across items.

Parameters:
Return type:

int

cayley_distance(a, b)[source]

Cayley distance: the minimum number of transpositions turning a into b (m - #cycles).

Parameters:
Return type:

int

borda_count(rankings)[source]

Borda positional aggregation: each item scores (m - 1 - position) summed over voters.

Returns:

{'consensus', 'scores'} – the consensus ordering (best first) and per-item Borda scores.

Parameters:

rankings (ndarray)

Return type:

dict[str, ndarray]

copeland(rankings)[source]

Copeland pairwise-majority aggregation.

Each ordered pair contributes a win/loss by majority across voters; an item’s score is wins minus losses. Closely tracks the Condorcet winner when one exists.

Returns:

{'consensus', 'scores', 'wins'}.

Parameters:

rankings (ndarray)

Return type:

dict[str, ndarray]

kemeny_consensus(rankings, *, exact_max_items=8)[source]

Kemeny median ranking: minimise the total Kendall-tau distance to all input orderings.

The Kemeny consensus is the maximum-likelihood aggregation under the Mallows–Kendall model and the Condorcet-consistent choice. Exact by enumeration when m <= exact_max_items; otherwise a local search (adjacent transpositions) from the Borda ordering. Exact enumeration evaluates m! permutations, so exact_max_items is an explicit factorial resource boundary; it must be an exact non-Boolean nonnegative integer.

Returns:

{'consensus', 'distance', 'exact', 'search_mode', 'exact_max_items'} – the consensus, total Kendall distance, whether the result is exact, and the requested/achieved search mode.

Parameters:
Return type:

dict

mallows_fit(rankings, *, exact_max_items=8)[source]

Fit a Mallows model (Kendall): central ranking + dispersion theta.

The central ranking is the kemeny_consensus(); theta is the MLE concentration, found by matching the observed mean Kendall distance to its expectation under the model. Larger theta means tighter agreement (theta -> 0 is uniform/no-consensus).

theta is nan when fewer than two items are ranked (MXR-080-1594): with m < 2 there is exactly one possible ordering, so every ranking has Kendall distance zero under every theta and the likelihood is flat – the dispersion is unidentifiable, not infinite. Reporting inf there (the perfect-agreement branch below) would claim maximal evidence for concentration from data that carries no evidence at all. The trivial center is still returned, since it is correct. inf remains the honest answer for genuine perfect agreement among two or more items, where the observed zero distance really was one of many attainable outcomes.

Returns:

{'center', 'theta', 'mean_distance', 'consensus_distance', 'exact', 'search_mode', 'exact_max_items'}, preserving the Kemeny search guarantee used to obtain the center.

Parameters:
Return type:

dict