Giter Club home page Giter Club logo

socialchoice's Introduction

socialchoice: a library for Social Choice Theory

This library implements social choice mechanisms.

Install

socialchoice is on PyPI, so:

pip3 install socialchoice

A minimal example

Here, we have two pairwise votes submitted, where "a" beat "b", and "c" lost to "b". We want to compute the ranked pairs result for this vote set.

>>> from socialchoice import PairwiseBallotBox, Election   
>>> pairwise_ballots = PairwiseBallotBox([("a", "b", "win"), ("c", "b", "loss")])
>>> election = Election(pairwise_ballots)
>>> election.ranking_by_ranked_pairs()
['a', 'b', 'c']

A slightly less minimal example

Let's run a ranked choice election, using ranked pairs again.

>>> from socialchoice import RankedChoiceBallotBox, Election   
>>> ranked_ballots = RankedChoiceBallotBox([[1,2,3,4], [1, {2,3}, 4]])
>>> election = Election(ranked_ballots)
>>> election.ranking_by_ranked_pairs()
[1, 2, 3, 4]

Notice that ties are allowed - simply submit a set as one element of your ranking, and each of those will be counted as ties. Ranked choice ballots are converted into pairwise preferences, and then ranked pairs can be run on the result.

Converting pairwise votes to orderings

Suppose you've collected pairwise votes from several voters, and you want to run a position-based method like Borda count. This is easy if each set of pairwise votes is transitive and complete - that is, the voters have consistent preferences (if A is preferred to B, and B is preferred to C, the voter doesn't also prefer C to A) and they have a preference submitted for each candidate pairing. Then, you can topologically sort the graph of their votes, and the resulting sorted list of candidates is their ordering.

But what if the vote set is intransitive or incomplete? If intransitive, you will have cycles, meaning there will be no clear ordering. If incomplete, the output will not contain each candidate. Both make it impossible to run position count directly. However, there are ways of making a vote set transitive, or filling in blanks in an ordering.

Here is an example of removing an edge from a cycle.

>>> from socialchoice import *
>>> ballots = VoterTrackingPairwiseBallotBox([(1, 2, "win", 1), (2, 3, "win", 1), (3, 1, "win", 1)])
>>> break_random_link = IntransitivityResolverFactory(ballots).make_break_random_link()
>>> add_random_edges = IncompletenessResolverFactory(ballots).make_add_random_edges()

>>> ballots.enable_ordering_based_methods(break_random_link, add_random_edges)
>>> Election(ballots).ranking_by_borda_count() in [[1,2,3], [2,3,1], [3,1,2]]
True

As the names imply, this resolves intransitivity by breaking random links, and then ensures that the output is complete by adding random edges. This example resolves an intransitive set of votes (1 beats 2, 2 beats 3, 3 beats 1) to one of the three orderings listed on the last line.

socialchoice's People

Contributors

drassaby avatar

Stargazers

Zhouliang Yu avatar Vathy M. Kamulete avatar dhuizinga avatar Ryan Sudhakaran avatar  avatar Brian Cline avatar Pietro Monticone avatar Vishal Belsare avatar Marcelo Maciel avatar Parker Griep avatar  avatar Aydin Mohseni avatar

Watchers

Julian Zucker avatar  avatar

socialchoice's Issues

Add pairwise ballot boxes that track voters

It is much more efficient to convert pairwise ballots to orderings with pairwise collapse if you know which votes belong to the same voter. A new BallotBox-extending class could accept either four-tuples (as (candidate1, candidate2, result, voter_id)) or a list of sets of the old three-tuple voters, each set corresponding to a voter.

Factories for intransitivity resolvers

Right now, getting the intransitivity/incompleteness resolvers to the pairwise collapse function is hard. The import names are long, and if you want to try multiple, you need to pull out the functions. A factory will be a better API that makes constructing them easier.

Support ties in rankings

The current data format for rankings is a flat array, which has no way to represent ties. Changing it to a list of lists or a list of sets will allow representing ties. Hopefully this can increase performance of the pairwise collapse method.

Specify "win", "loss", "tie" strings in pairwise ballot box

Right now, the three-tuples need to have "win", "loss", and "tie" be the literal strings in the tuples. Users that store their votes different might want to pass in which strings denote a win, loss, or tie. So, we should make that possible!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.