Package: votepy
VotepyVotepy provides ready-to-use tools to calculate multi-winning ordinal elections, under different voting rules.InstallationClone the repository:git clone https://github.com/Janix4000/votepy.git path/to/libCreate and source new virtual environment:cd path/to/your/project && python3 -m venv venv && source venv/bin/activateInstall the main package:pip3 install -e path/to/lib/votepyUsageOrdered preference and electionWhen working with the ordered elections, we need to represent such data. Givenncandidates, we can represent voter's preference by permutation of lengthn, using a standard Python list:n=4voting_preference=[2,1,3,0]We will call such a preference avoting ballot.
Havingmvoters, we can group their preferences into theordered election:n=4m=3voting=[[2,1,3,0],# first voter's preference[1,2,3,0],# second voter's preference[3,0,2,1]# third voter's preference]Votepy also provides special data types for them, but they are not obligatory and all functions support python's primitives.
However, they give additional functionalities, such as mapping candidates to more human-readable representations:fromvotepy.ordinal_electionimportOrdinalElection,OrdinalBallotmapping={0:'Joe',1:'John',2:'Sue',3:'Anna'}single_voting_preference=OrdinalBallot([2,1,3,0],mapping=mapping)voting=OrdinalElection([[2,1,3,0],# first voter's preference[1,2,3,0],# second voter's preference[3,0,2,1]# third voter's preference],mapping=mapping)print(voting)# prints election using mapping representationVoting rulesFor a given election, we want to choose a set of representatives, with the predefined numberk(orcommittee size) of the delegates.
However, there are many strategies to choose such acommittee. These strategies are commonly calledvoting rulesand may optimize different objectives. We can print all of the implemented voting rules, with the corresponding python functions:importvotepyasvpprint(vp.get_rules())# prints rule_name->rule_function dictionaryLet's use for an exampleblocrule on the previously defined election:committee_size=2committee=vp.rules.bloc(voting,committee_size)print(committee)Votepy gives additional way to call the voting rules:# this is equivalent of calling vp.rules.bloccommittee=vp.solve('bloc',voting,committee_size)Voting-solving algorithmsSome of the voting rules are extremely costly to compute and finding the best committee may be very time-consuming for a greater number of candidates and voters. Luckily, many voting rules are defined by the maximization of some objective function (scoring function), so the best committees can be approximated using different tricks and methods.Let's look at thechamberlin_courant(shortlycc) rule, which turns out to be NP-Complete, and so no efficient algorithm is known for finding the best committees for the given election. For such a rules additional parameteralgorithmmust be provided. Algorithms can be specified by their name:committee=vp.rules.chamberlin_courant(voting,committee_size,algorithm='brute_force')or by using their corresponding algorithms objects:fromvotepy.algorithmsimportBruteForce# this is equivalent of 'brute_force' string namecommittee=vp.rules.chamberlin_courant(voting,committee_size,algorithm=BruteForce())In this case, thebrute forcealgorithm will check every possible combination of the candidates and take the best one to create committee.Some algorithms can accept additional parameters, and it is only possible by using their corresponding classes:# numeric algorithm, similar to simulated annealing, giving approximate resultsfromvotepy.algorithmsimportBasinHoppingcommittee=vp.rules.chamberlin_courant(voting,committee_size,algorithm=BasinHopping(niter=100,seed=1))There are better methods than brute force for getting exact solutions. We can check all algorithms implemented for the cc rule:# prints rule_name->algorithm_class dictionaryprint(vp.get_algorithms('chamberlin_courant'))One of the most common technice used for solving NP-Complete problems is usingILPsolvers. However, in contrast to the brute force algorithm, we need to specify solver engine during the initialization of the ILP.fromvotepy.algorithmsimportILP# Gurobi solver must be previously installed and activated on the machinefromvotepy.generic_ilpimportGurobicommittee=vp.rules.chamberlin_courant(voting,committee_size,algorithm=ILP(Gurobi))Contribution guideInstallationClone the repository:git clone https://github.com/Janix4000/votepy.git && cd votepyCreate and source new virtual environment:python3 -m venv venv && source venv/bin/activateInstall the main package:pip3 install -e .Install development packages:pip3 install -r ./requirements_dev.txtRun tests:pytestAdding a new voting ruleSee theguidefor adding new voting rule.