Open narendersaini32 opened 2 years ago
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.
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 } ]
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.
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'] ]
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
@lzear Thanks for your valuable time. Keep it up. 👍 One more question.
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
You are the best. 👍
Hi Izear Do we also have a code sandbox link for all algorithms demos? If not that's totally fine.
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:
- Demo/Playground: rank-votes.vercel.app (work in progress!)
- Library documentation lzear.github.io/votes
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 🙏
@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.
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.
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 😄
Totally, makes a lot of sense. Thank you.
Hi Izear First of all, I am very impressed with your work. I have a few questions.