copeland_ranker
Copeland pairwise preference ranker. Ranks each item by its number of matchup wins minus losses after aggregating weighted pairwise preferences per observed opponent pair.
The library implements the ranker_protocol defined in the
ranking_protocols library. It provides predicates for learning a
ranker from pairwise preference judgments, using it to order candidate
items, and exporting it as a list of predicate clauses or to a file.
Datasets are represented as objects implementing the
pairwise_ranking_dataset_protocol protocol from the
ranking_protocols library. See the test_datasets directory for
examples. The training dataset must declare each ranked item once, use
only declared items in preferences, assign positive weights to
preferences between distinct items, and induce a connected undirected
comparison graph.
API documentation
Open the ../../apis/library_index.html#copeland_ranker link in a web browser.
Loading
To load this library, load the loader.lgt file:
| ?- logtalk_load(copeland_ranker(loader)).
Testing
To test this library predicates, load the tester.lgt file:
| ?- logtalk_load(copeland_ranker(tester)).
Features
Pairwise Preference Learning: Learns one deterministic score per item from pairwise preference datasets.
Portable Copeland Scoring: Computes Copeland scores from aggregated head-to-head outcomes using only standard Logtalk library predicates.
Integer Score Semantics: Learned scores are restricted to integers, because each observed aggregated matchup contributes exactly
+1,-1, or0to an item’s total score.Deterministic Ranking: Orders candidate items by learned score with deterministic tie-breaking using the standard term order of the item identifiers after sorting by descending score.
Strict Dataset Validation: Rejects duplicate items, undeclared items in preferences, self-preferences, non-positive weights, and disconnected comparison graphs.
Training Diagnostics: Learned rankers include dataset summary metadata that can be accessed using the
diagnostics/2predicate.Ranker Export: Learned rankers can be exported as self-contained terms.
Shared Ranking Infrastructure: Uses the common
ranking_protocolshelper predicates for option processing, dataset validation, diagnostics, export, and candidate ranking.
Scoring semantics
This implementation uses a Copeland score defined over aggregated
observed matchups. For each unordered pair of observed opponents, the
preference data is aggregated into total wins for the left and right
item. The item with the higher aggregated total receives +1 for that
matchup, the item with the lower total receives -1, and both receive
0 when the aggregated totals tie.
Only observed opponent pairs contribute to the learned scores. Unobserved pairs are ignored rather than treated as implicit ties. This makes the implementation a sparse-data Copeland variant suitable for incomplete pairwise datasets.
Because each observed matchup contributes only +1, -1, or 0,
every learned Copeland score is an integer. The ranker validation logic
enforces this invariant when consuming serialized or exported ranker
terms so that malformed non-integer score payloads are rejected instead
of silently accepted.
Usage
Learning a ranker
% Learn from a pairwise ranking dataset object
| ?- copeland_ranker::learn(my_dataset, Ranker).
...
% Learn with an explicit empty options list
| ?- copeland_ranker::learn(my_dataset, Ranker, []).
...
The current implementation accepts only the empty options list [].
Any non-empty options list is rejected.
Inspecting diagnostics
% Inspect model and dataset summary metadata
| ?- copeland_ranker::learn(my_dataset, Ranker),
copeland_ranker::diagnostics(Ranker, Diagnostics).
Diagnostics = [...]
...
Ranking candidate items
% Rank a candidate set from most preferred to least preferred
| ?- copeland_ranker::learn(my_dataset, Ranker),
copeland_ranker::rank(Ranker, [item_a, item_b, item_c], Ranking).
Ranking = [...]
...
Candidate lists must be proper lists of unique, ground items declared by the training dataset. Invalid ranker terms, duplicate candidates, and candidates containing variables are rejected with errors instead of being silently accepted.
Exporting the ranker
Learned rankers can be exported as a list of clauses or to a file for later use.
% Export as predicate clauses
| ?- copeland_ranker::learn(my_dataset, Ranker),
copeland_ranker::export_to_clauses(my_dataset, Ranker, my_ranker, Clauses).
Clauses = [my_ranker(copeland_ranker(...))]
...
% Export to a file
| ?- copeland_ranker::learn(my_dataset, Ranker),
copeland_ranker::export_to_file(my_dataset, Ranker, my_ranker, 'ranker.pl').
...
Diagnostics syntax
The diagnostics/2 predicate returns a list of metadata terms with
the form:
[
model(copeland_ranker),
options(Options),
dataset_summary(DatasetSummary)
]
Where:
model(copeland_ranker)identifies the learning algorithm that produced the ranker.options(Options)stores the effective learning options after merging the user options with the library defaults.dataset_summary(DatasetSummary)stores a summary list describing the validated training dataset.
The current dataset_summary/1 payload has the form:
[
items(NumberOfItems),
preferences(NumberOfPreferences),
connected_components(NumberOfComponents),
isolated_items(IsolatedItems)
]
Use the ranking_protocols diagnostic/2 and ranker_options/2
helper predicates when you only need a single metadata term or the
effective options.
Options
The current learn/3 implementation does not define any user options
beyond the default empty list. Non-empty options lists are rejected.
Ranker representation
The learned ranker is represented by a compound term of the form:
copeland_ranker(Items, Scores, Diagnostics)
Where:
Items: List of ranked items.Scores: List ofItem-Scorepairs.Diagnostics: List of metadata terms, including the effective options and dataset summary.
The Scores payload is expected to contain integer Copeland scores
only. This restriction is not just an implementation preference but a
direct consequence of the scoring semantics: each observed aggregated
matchup changes an item’s score by one of the three integer values
+1, -1, or 0.
When exported using export_to_clauses/4 or export_to_file/4,
this ranker term is serialized directly as the single argument of the
generated predicate clause so that the exported model can be loaded and
reused as-is.
References
Copeland, A. H. (1951). A reasonable social welfare function. Seminar on Mathematics in the Social Sciences, University of Michigan.