https://github.com/mieuxvoter/majority-judgment-library-go
A Golang module to deliberate polls using Majority Judgment, using a score-based algorithm for performance and scalability
https://github.com/mieuxvoter/majority-judgment-library-go
golang majority-judgment political-science poll
Last synced: about 1 month ago
JSON representation
A Golang module to deliberate polls using Majority Judgment, using a score-based algorithm for performance and scalability
- Host: GitHub
- URL: https://github.com/mieuxvoter/majority-judgment-library-go
- Owner: MieuxVoter
- License: mit
- Created: 2021-07-03T00:32:04.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2023-11-23T11:01:06.000Z (over 1 year ago)
- Last Synced: 2024-06-20T22:35:30.646Z (10 months ago)
- Topics: golang, majority-judgment, political-science, poll
- Language: Go
- Homepage:
- Size: 146 KB
- Stars: 3
- Watchers: 6
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Contributing: docs/CONTRIBUTING.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Majority Judgment for Golang
[](LICENSE.md)
[](https://github.com/MieuxVoter/majority-judgment-library-go/releases)
[](https://github.com/MieuxVoter/majority-judgment-library-go/actions/workflows/go.yml)
[](https://app.codecov.io/gh/MieuxVoter/majority-judgment-library-go/)
[](https://www.codefactor.io/repository/github/mieuxvoter/majority-judgment-library-go)
[](https://goreportcard.com/report/github.com/mieuxvoter/majority-judgment-library-go)

[](https://discord.gg/rAAQG9S)A Golang module to deliberate using Majority Judgment to rank proposals/candidates.
Majority Judgment is a simple, subtle and fair voting system.## Features
- **score-based algorithm**, for performance and scalability
- supports billions of judgments with almost the same cost as dozens
- supports thousands of proposals per poll
- default judgment balancing tools: static grade, median grade## Installation
go get -u github.com/mieuxvoter/majority-judgment-library-go
It exposes the package `judgment`, for concision, since the repo name itself is quite long and we can't rename it.
> It's a pre-release. We still have some int types that may change until v1.
## Usage
Say you have the following tally:

You can compute out the majority judgment rank of each proposal like so:
```go
package mainimport (
"fmt"
"github.com/mieuxvoter/majority-judgment-library-go/judgment"
"log"
)func main() {
pollTally := &(judgment.PollTally{
AmountOfJudges: 10,
Proposals: []*judgment.ProposalTally{
{Tally: []uint64{2, 2, 2, 2, 2}}, // Proposal A Amount of judgments received for each grade,
{Tally: []uint64{2, 1, 1, 1, 5}}, // Proposal B from "worst" grade to "best" grade.
{Tally: []uint64{2, 1, 1, 2, 4}}, // Proposal C Make sure all tallies are balanced, that is they
{Tally: []uint64{2, 1, 5, 0, 2}}, // Proposal D hold the same total amount of judgments.
{Tally: []uint64{2, 2, 2, 2, 2}}, // Proposal E Equal proposals share the same rank.
// …
},
})
deliberator := &(judgment.MajorityJudgment{})
result, err := deliberator.Deliberate(pollTally)if nil != err {
log.Fatalf("Deliberation failed: %v", err)
}// Proposals results are ordered like tallies, but Rank is available.
// result.Proposals[0].Rank == 4 // Proposal A
// result.Proposals[1].Rank == 1 // Proposal B
// result.Proposals[2].Rank == 2 // Proposal C
// result.Proposals[3].Rank == 3 // Proposal D
// result.Proposals[4].Rank == 4 // Proposal E// You may also use proposals sorted by Rank ; their initial Index is available
// result.ProposalsSorted[0].Index == 1 // Proposal B
// result.ProposalsSorted[1].Index == 2 // Proposal C
// result.ProposalsSorted[2].Index == 3 // Proposal D
// result.ProposalsSorted[3].Index == 0 // Proposal A
// result.ProposalsSorted[4].Index == 4 // Proposal E
fmt.Printf("Best Proposal Index: %d\n", result.ProposalsSorted[0].Index)}
```### Balancing uneven proposals
Sometimes, some proposals receive more judgments than others, and the tallies are unbalanced.
In those cases, a _default judgment_ strategy has to be picked:#### Static Default Grade
Missing (or "I don't know") judgments are considered of a grade defined in advance,
usually `to reject` in order to incentivize proposals to be explicit and clear.You may use `PollTally.BalanceWithStaticDefault(defaultGrade)` to that effect:
```go
pollTally := &PollTally{
AmountOfJudges: 10,
Proposals: []*ProposalTally{
{Tally: []uint64{2, 1, 2, 2, 1}}, // Proposal A
{Tally: []uint64{3, 1, 3, 1, 1}}, // Proposal B
{Tally: []uint64{0, 1, 1, 0, 0}}, // Proposal C
// …
},
}
defaultGrade := 0
pollTally.BalanceWithStaticDefault(defaultGrade)// pollTally was mutated and now contains balanced proposals' tallies
// pollTally.Proposals[0].Tally == {4, 1, 2, 2, 1} // Proposal A is now balanced
// pollTally.Proposals[1].Tally == {4, 1, 3, 1, 1} // Proposal B is now balanced
// pollTally.Proposals[2].Tally == {8, 1, 1, 0, 0} // Proposal C is now balanced
```#### Median Default Grade
Same behavior as static, but the default grade for each proposal is its median grade.
Use `PollTally.BalanceWithMedianDefault()`.
#### Normalization
> Not implemented yet ; would require either `math/big` for LCM or floating-point arithmetic
> This is part of why deciding on int types is so tricky.## License
`MIT` 🐜
## Contribute
This project needs a review by `Go` devs.
Feel free to suggest changes, report issues, make improvements, etc.Some more information is available in [`docs/`](./docs).