condorcet 0.1.1
Condorcet is a utility for evaluating votes using the condorcet method
License: MIT
Requires Python: >=3.8,<4.0
Keywords: condorcet,condorcet method,pairwise vote count,preferential voting

# Condorcet

Condorcet is a Python library for evaluating votes using [the condorcet method](https://en.wikipedia.org/wiki/Condorcet_method#Summary).


## Installation

```
pip install condorcet
```


## Synopsis

The library exposes a class `CondorcetEvaluator` which is called with a list of candidates and a list of votes in order to instantiate an evaluator.

```python
# Attention! This is pseudo-code!!
CondorcetEvaluator : List[Candidates], List[Votes] -> CondorcetEvaluator
```

This instantiated evaluator has a method `get_n_winners` which takes a (non-negative) integer, n, and returns a list containing __at most__ the first n winners in order, along with a table of pairwise wins and losses for __the remainder__ of the candidates (the ones who are not in the list of winners).

__At most__, because some times there may not be that many winners &mdash; a cycle might exist among a set of candidates. This is one of the motivations for returning a table of pairwise wins and losses along with the list of winners.

```python
# Attention! This is pseudo-code!!
CondorcetEvaluator.get_n_winners : int -> List[Candidates], WinsAndLossesTable
```

And that is that for that!


## Quick Start: Rochambeau Games

This years' edition of the Rochambeau Games had seven people ranking four candidates &mdash Rock, Paper, Scissors, and the relatively unknown Dynamite &mdash from 1 to 4, where candidate 1 on someone's ballot would be their most prefered candidate, and 4, the less preferred.

As the election officer you are to evaluate their votes according to the Condorcet method and announce the result.

You have the following data:

```python
candidates = ["Rock", "Paper", "Scissors", "Dynamite"]
votes = [
    {"Rock": 1, "Scissors": 2, "Dynamite": 3, "Paper": 4},
    {"Rock": 1, "Dynamite": 2, "Scissors": 3, "Paper": 4},
    {"Dynamite": 1, "Paper": 2, "Rock": 3, "Scissors": 4},
    {"Paper": 1, "Dynamite": 2, "Rock": 3, "Scissors": 4},
    {"Scissors": 1, "Paper": 2, "Dynamite": 3, "Rock": 4},
    {"Scissors": 1, "Dynamite": 2, "Paper": 3, "Rock": 4},
    {"Rock": 1, "Paper": 2, "Dynamite": 3, "Scissors": 4},
]
```

You want to announce how the four candidates fared with respect to each other. So, you instantiate a condorcet evaluator using the list of candidates and list of votes, and ask it to produce four winners as shown below:

```python
import condorcet

evaluator = condorcet.CondorcetEvaluator(candidates=candidates, votes=votes)
winners, rest_of_table = evaluator.get_n_winners(4)
```

Print out the list of winners.

```python
print(winners)

# ['Dynamite']
```

Four winners were asked for, but only one was returned. Studying the table of wins and losses for the rest of the candidates will throw light on the underlying issue.

```python
print(rest_of_table)

# {
#  'Paper': {
#      'losses': ['Scissors'],
#      'wins': ['Rock']
#   },
#  'Rock': {
#      'losses': ['Paper'],
#      'wins': ['Scissors']
#  },
#  'Scissors': {
#      'losses': ['Rock'],
#      'wins': ['Paper']
#  }
# }
```

The wins and losses table for the rest of the candidates shows that no winner could be picked among them, as each one has lost to at least one of the other.


## Contributing

Condorcet is happy to receive contributions. Please submit a PR/MR containing your contribution (including tests if it's a code contribution) and bug the maintainer to review and merge.

Don't forget to add yourself to CONTRIBUTORS.txt