Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Questions #64

Open
narendersaini32 opened this issue Apr 15, 2022 · 9 comments
Open

Questions #64

narendersaini32 opened this issue Apr 15, 2022 · 9 comments

Comments

@narendersaini32
Copy link

narendersaini32 commented Apr 15, 2022

Hi Izear
First of all, I am very impressed with your work.
I have a few questions.

  1. What's the meaning of weight in the below example?
  2. What's the use of scoresFromBallots?
  3. Can you share one example for Minimax Condorcet method?
  4. Is there any similar npm package for voting algorithms?

return scoresFromBallots(
[
{ ranking: [['Lion'], ['Bear'], ['Sheep']], weight: 4 },
{ ranking: [['Sheep'], ['Bear'], ['Lion']], weight: 3 },
{ ranking: [['Bear', 'Sheep'], ['Lion']], weight: 2 },
],
['Lion', 'Bear', 'Sheep'],
VotingSystem.Schulze,
)

@lzear
Copy link
Owner

lzear commented Apr 15, 2022

Hello @narendersaini32

Thank you very much for the message! I'm very happy to see someone reaching out about this project.

You motivated me to finish the release of a version 2. Unfortunately, I ended up unpublishing the whole package while trying to delete an invalid version 😕 Sorry if I cause any inconvenience. I will republish it in 24 hours.

  1. What's the meaning of weight in the below example?

    The weight property matches the strength of a vote. You're free to set any positive value, and you probably want it to match the number of voters that ranked candidates with the same order.

    // syntax for v2
    const borda = new Borda({
      candidates: ['Lion', 'Bear', 'Sheep'],
      ballots: [
        { ranking: [['Lion'], ['Bear'], ['Sheep']], weight: 2 }, // 2 voters voted "Lion > Bear > Sheep"
        { ranking: [['Sheep'], ['Bear'], ['Lion']], weight: 3 }, // 3 voters voted "Sheep > Bear > Lion"
      ],
    })

    You're free to keep the votes ungrouped, this also works:

    const borda = new Borda({
      candidates: ['Lion', 'Bear', 'Sheep'],
      ballots: [
        { ranking: [['Lion'], ['Bear'], ['Sheep']], weight: 1 },
        { ranking: [['Lion'], ['Bear'], ['Sheep']], weight: 1 },
        { ranking: [['Sheep'], ['Bear'], ['Lion']], weight: 1 },
        { ranking: [['Sheep'], ['Bear'], ['Lion']], weight: 1 },
        { ranking: [['Sheep'], ['Bear'], ['Lion']], weight: 1 },
      ],
    })

    There is an util to make the conversion, if you want to

    import { utils as votesUtils } from 'votes'
    utils.toWeightedBallots([
        [['a'], ['b'], ['c']],
        [['a'], ['b'], ['c']],
        [['b'], ['c'], ['a']],
      ]) // -> [ { ranking: [['a'], ['b'], ['c']], weight: 2 }, { ranking: [['b'], ['c'], ['a']], weight: 1 } ]
  2. What's the use of scoresFromBallots?

    I just realised that the readme code example was missing this line:
    `const { scoresToRanking, scoresFromBallots } = voteUtils

    scoresFromBallots (will soon be deprecated!) is a way to get a ScoreObject from an array of ballots and a voting system: an object with candidates as keys, and scores as value (the higher the better).

    Scores can be converted to rankings with the utility function scoresToRanking which orders candidates by score in descending order.

  3. Can you share one example for Minimax Condorcet method?

    With v2:

    import fill from 'lodash/fill'
    import { Minimax, utils as votesUtils } from 'votes'
     
    const balinski = votesUtils.toWeightedBallots([
      ...fill(new Array(33), [['a'], ['b'], ['c'], ['d'], ['e']]),
      ...fill(new Array(16), [['b'], ['d'], ['c'], ['e'], ['a']]),
      ...fill(new Array(3), [['c'], ['d'], ['b'], ['a'], ['e']]),
      ...fill(new Array(8), [['c'], ['e'], ['b'], ['d'], ['a']]),
      ...fill(new Array(18), [['d'], ['e'], ['c'], ['b'], ['a']]),
      ...fill(new Array(22), [['e'], ['c'], ['b'], ['d'], ['a']]),
    ])
     
    const election = new Minimax(
      votesUtils.matrixFromBallots(balinski, ['a', 'b', 'c', 'd', 'e']),
    )
    election.scores() // { a: -34, b: -2, c: -0, d: -58, e: -40 }
    election.ranking() // [ ['c'], ['b'], ['a'], ['e'], ['d'] ]
  4. Is there any similar npm package for voting algorithms?

    I searched a bit in the past without finding any. Today I found that one which looks good: https://github.com/Perlkonig/condorcet-ts

@narendersaini32
Copy link
Author

narendersaini32 commented Apr 16, 2022

@lzear
Thanks for your valuable time.
Keep it up. 👍
One more question.

  1. In Wikipedia Minimax Condorcet method have three different variations. Which one you have implemented and is there a way for us to use all three variations using your package or any suggestion?

Screenshot 2022-04-16 at 7 21 27 AM

@lzear
Copy link
Owner

lzear commented Apr 16, 2022

Very good point.
The implementation was only using the margins variant. I just made an update so you can use the other variants:

new Minimax({
  candidates: ['a', 'b', 'c'],
  array: [[0, 1, 0], [0, 0, 0], [2, 1, 0]],
  // 'PAIRWISE_OPPOSITION' | 'WINNING_VOTES' | 'MARGINS' (default)
  variant: 'PAIRWISE_OPPOSITION',
}).scores()

I published a working example here: https://runkit.com/lzear/minimax-example


I managed to publish the package again: https://www.npmjs.com/package/votes
But the v1 was lost, unfortunately

@narendersaini32
Copy link
Author

You are the best. 👍

@narendersaini32
Copy link
Author

Hi Izear
Do we also have a code sandbox link for all algorithms demos? If not that's totally fine.

Screenshot 2022-04-18 at 8 16 55 AM

@lzear
Copy link
Owner

lzear commented Apr 18, 2022

Hi again :)

It's not really a code sandbox, maybe playground would have been a better term. Anyway, it's here: rank-votes.vercel.app

I just added some links in the Readme:

This morning, I added Minimax to the voting systems in the demo (only the margins variant for now). Many other systems are still missing.

Thanks for showing interest in this project 🙏

@maiconcarraro
Copy link

@lzear first of all, amazing work!

I had the same question around the weight that is clear now, but I don't get it why it has an array with double entries here:

{ ranking: [['Bear', 'Sheep'], ['Lion']], weight: 2 },

Bear and Sheep same array, what is the difference for

{ ranking: [['Bear'], ['Sheep'], ['Lion']], weight: 2 },

Thank you in advance.

@lzear
Copy link
Owner

lzear commented Oct 5, 2022

Hello @maiconcarraro

The library allows voters to indicate equal preferences in their ballots:

  • [['Bear', 'Sheep'], ['Lion']] means that the voter prefers Bear to Lion, and Sheep to Lion, but is indifferent between Bear and Sheep. The order inside a ranking does not matter: [['Sheep', 'Bear'], ['Lion']] is equivalent to [['Bear', 'Sheep'], ['Lion']].
  • [['Bear'], ['Sheep'], ['Lion']] is the simple case where the voter ranked Bear > Sheep > Lion with no draws in the person's preferences.

To get a better understanding of draws, you can maybe play around on https://rank-votes.vercel.app. Clicking the "✏️" icon, you can edit preferences by dragging candidates and generate preferences with draws. Or you can see another vote with draw here: https://www.elzear.de/poll/Uug62KMX

Here is an example of what happens with in a Borda votes: the points for the ranks get shared amongst the candidates.
Screenshot 2022-10-05 at 21 10 25

As a consumer of the library, you are of course free to disallow draws by making sure the rankings only contains arrays of length 1.

I hope the answer is understandable. Please ask if you need any additional clarifications, I'm very happy to see some people here 😄

@maiconcarraro
Copy link

Totally, makes a lot of sense. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants