Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions README_STV.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
The format for all election data is (each element on a new line):
* Number of Candidates
* 1, Candidate Name
* 2, Candidate Name
* ...
* Number of Voters, Sum of Vote Count, Number of Unique Orders
* count, preference list. (12,1,2,{3,4}). A strict ordering is indicated by a comma (,) and elements that are indifferent are grouped with a ({ }).
* count, preference list. (12,1,2,3,4). A strict ordering is indicated by a comma (,) and elements that are indifferent are grouped with a ({ }).
* ...

The above is based on preflib's format. [Visit them for more info](http://www.preflib.org/data/format.php#election-data)

Demo usage code is in [mechanismSTVRunner.py](./prefpy/mechanismSTVRunner.py)
Sample input are in [prefpy/tests](./tests)

There are two main mechanisms that implement STV: MechanismSTV and MechanismSTVAll.

* MechanismSTV has several child mechanisms, each implementing its own tie-breaking rule. Tie-breaking is done to determine which candidate is eliminated.
* MechanismSTVForward implements forward tie-breaking
* The candidate with the least votes in the earliest round is eliminated
* MechanismSTVBackward implements backward tie-breaking
* The candidate with the leave votes at the latest non-tied round is eliminated
* MechanismSTVBorda implements borda tie-breaking
* The candidate with the lowest Borda score is eliminated
* MechanismSTVCoombs implements coombs tie-breaking
* The candidate with the most last-place votes is eliminated
* MechanismSTVAll determines all possible winners given all possible tie-breaking schemes
561 changes: 561 additions & 0 deletions prefpy/mechanismSTV.py

Large diffs are not rendered by default.

95 changes: 95 additions & 0 deletions prefpy/mechanismSTVRunner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import sys
from prefpy import io
from prefpy import mechanismSTV
from .preference import Preference
from .profile import Profile

def electionFileToProfile(file):
inputFile = open(sys.argv[1], 'r')
candMap, rankMaps, rankMapsCounts, numVoters = io.read_election_file(inputFile)

preferences = []
# ranking: [dict<cand,pos in order>, freq of ranking]
for ranking in zip(rankMaps,rankMapsCounts):
cands = list(ranking[0].keys())
wmg = {}
for i in range(len(cands)):
for j in range(i+1, len(cands)):
cand1, cand2 = cands[i], cands[j]
if cand1 not in wmg:
wmg[cand1] = {}
if cand2 not in wmg:
wmg[cand2] = {}
if ranking[0][cand1] < ranking[0][cand2]:
wmg[cand1][cand2] = 1
wmg[cand2][cand1] = -1
elif ranking[0][cand1] > ranking[0][cand2]:
wmg[cand1][cand2] = -1
wmg[cand2][cand1] = 1
else:
wmg[cand1][cand2] = 0
wmg[cand2][cand1] = 0
preferences.append(Preference(wmg, ranking[1]))
return Profile(candMap, preferences)

if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python3 -m prefpy.mechanismSTVRunner tests/<any test file>\n",
''' input file follows the election data format described at (http://www.preflib.org/data/format.php#election-data):
* <number of candidates>
* <candidate number; e.g. 1>,<candidate name; e.g. apple>
* ... //until all candidates listed
* <total number of voters>,<sum of vote count;usually same as total number of votes>,<number of unique rankings>
* <number of votes with this ranking>,<ranking;e.g. 1,2,3,4>
* ... //until all unique rankings are listed''')
exit()
profile = electionFileToProfile(sys.argv[1])

import time

t0 = time.time()
stv = mechanismSTV.MechanismSTVForward()
winners = stv.getWinners(profile)
t1 = (time.time() - t0) * 1000000.0
print("\n\n")
print("Using STV with forward tie breaking")
print(winners)
print("Took %.1fus" % t1)
print("\n" + "=" * 80)

t0 = time.time()
stv = mechanismSTV.MechanismSTVBackward()
winners = stv.getWinners(profile)
t2 = (time.time() - t0) * 1000000.0
print("Using STV with backward tie breaking")
print(winners)
print("Took %.1fus" % t2)
print("\n" + "=" * 80)

t0 = time.time()
stv = mechanismSTV.MechanismSTVBorda()
winners = stv.getWinners(profile)
t3 = (time.time() - t0) * 1000000.0
print("Using STV with Borda tie breaking")
print(winners)
print("Took %.1fus" % t3)
print("\n" + "=" * 80)

t0 = time.time()
stv = mechanismSTV.MechanismSTVCoombs()
winners = stv.getWinners(profile)
t4 = (time.time() - t0) * 1000000.0
print("Using STV with Coombs tie breaking")
print(winners)
print("Took %.1fus" % t4)
print("\n" + "=" * 80)

t0 = time.time()
stv = mechanismSTV.MechanismSTVAll()
winners = stv.getWinners(profile)
t5 = (time.time() - t0) * 1000000.0
print("Using STV - All possible winners")
print(winners)
print("Took %.1fus" % t5)
print("\n" + "=" * 80)
print("\n\n")
10 changes: 10 additions & 0 deletions tests/stvTestInput01
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
4
1,a
2,b
3,c
4,d
26,26,4
10,1,2,3,4
7,4,1,2,3
6,3,4,1,2
3,2,3,4,1
10 changes: 10 additions & 0 deletions tests/stvTestInput02
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
4
1,a
2,b
3,c
4,d
24,24,4
10,1,2,3,4
7,4,1,2,3
6,3,4,1,2
1,2,3,4,1
11 changes: 11 additions & 0 deletions tests/stvTestInput03
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
4
1,a
2,b
3,c
4,d
20,20,5
10,1,2,3,4
5,4,3,2,1
3,3,4,3,1
1,1,3,2,4
1,3,2,{1,4}
12 changes: 12 additions & 0 deletions tests/stvTestInput04
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
4
1,a
2,b
3,c
4,d
18,18,6
6,1,2,3,4
4,2,1,4,3
1,3,1,4,2
3,3,2,4,1
2,4,2,1,3
2,4,1,3,2
12 changes: 12 additions & 0 deletions tests/stvTestInput05
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
4
1,a
2,b
3,c
4,d
20,20,6
6,1,2,3,4
6,2,1,4,3
2,3,2,4,1
2,3,4,1,2
3,4,2,1,3
1,4,3,1,2
11 changes: 11 additions & 0 deletions tests/stvTestInput06
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
4
1,a
2,b
3,c
4,d
22,22,5
6,1,2,3,4
9,2,3,1,4
3,3,1,2,4
2,4,1,2,3
2,4,2,1,3
11 changes: 11 additions & 0 deletions tests/stvTestInput07
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
4
1,a
2,b
3,c
4,d
18,18,5
7,1,2,3,4
7,2,3,1,4
1,3,2,1,4
2,3,1,2,4
1,4,2,1,3
17 changes: 17 additions & 0 deletions tests/stvTestInput08
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
7
1,a
2,b
3,c
4,d
5,e
6,f
7,g
228,228,8
43,1,2,3,4,5,7,6
11,2,5,1,4,3,6,7
33,3,1,5,4,2,6,7
21,4,3,2,1,5,7,6
11,5,4,2,1,3,6,7
1,4,1,2,5,3,6,7
54,6,3,1,2,3,5,7
54,7,3,6,1,2,3,4