Mirror of a Majority Judgment library for Java
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Go to file
Dominique Merle 093ae22354
refacto: dry up the static and median default grade tallies
3 years ago
.github/workflows chore(ci): run in batch mode to get leaner logs 3 years ago
bin chore(git): ignore "build" files in bin/ 3 years ago
src refacto: dry up the static and median default grade tallies 3 years ago
.gitignore docs: document usage of maven 3 years ago
LICENSE.md feat: implement a majority judgment deliberator 3 years ago
README.md feat: median default grade tally 3 years ago
build.gradle test: prepare for a more exhaustive test-suite, using JSON 3 years ago
pom.xml test: prepare for a more exhaustive test-suite, using JSON 3 years ago
settings.gradle chore(packaging): add some gradle configuration 3 years ago

README.md

Majority Judgment Library for Java

MIT Build Status Release Join the Discord chat at https://discord.gg/rAAQG9S

Test-driven java library to help deliberate using Majority Judgment.

The goal is to be scalable, reliable, fast and extensible. We therefore use a score-based algorithm and no floating-point arithmetic whatsoever.

Features

  • Supports billions of participants
  • Supports thousands of proposals
  • Handles default grades (static or normalized)
  • No floating-point arithmetic
  • Room for other deliberators (central, usual)

Example Usage

Collect the tallies for each Proposal (aka. Candidate) by your own means, provide them to the MajorityJudgmentDeliberator, and get back the rank of each Proposal.

Let's say you have the following tally:

To Reject Poor Passable Somewhat Good Good Very Good Excellent
Proposal A 4 5 2 1 3 1 2
Proposal B 3 6 2 2 2 1 2

A Tally is the amount of judgments received per grade, by each proposal.

DeliberatorInterface mj = new MajorityJudgmentDeliberator();
TallyInterface tally = new Tally(new ProposalTallyInterface[] {
        // Amounts of judgments received for each grade, from "worst" grade to "best" grade
        new ProposalTally(new Integer[]{4, 5, 2, 1, 3, 1, 2}),  // Proposal A
        new ProposalTally(new Integer[]{3, 6, 2, 1, 3, 1, 2}),  // Proposal B
        // …
}, 18);
ResultInterface result = mj.deliberate(tally);

// Each proposal result has a rank, and results are returned by input order
assert(2 == result.getProposalResults().length);
assert(2 == result.getProposalResults()[0].getRank());  // Proposal A
assert(1 == result.getProposalResults()[1].getRank());  // Proposal B

Got more than 2³² judges? Use a Long[] in a ProposalTally.

Got even more than that ? Use BigIntegers !

Using a static default grade

Want to set a static default grade ? Use a TallyWithDefaultGrade instead of a Tally.

Integer amountOfJudges = 18;
Integer defaultGrade = 0;  // "worst" grade (usually "to reject")
TallyInterface tally = new TallyWithDefaultGrade(new ProposalTallyInterface[] {
        // Amounts of judgments received of each grade, from "worst" grade to "best" grade
        new ProposalTally(new Integer[]{4, 5, 2, 1, 3, 1, 2}),  // Proposal A
        new ProposalTally(new Integer[]{3, 6, 2, 1, 3, 1, 2}),  // Proposal B
        // …
}, amountOfJudges, defaultGrade);

Using normalized tallies

In some polls with a very high amount of proposals, where participants cannot be expected to judge every last one of them, it may make sense to normalize the tallies instead of using a default grade.

To that effect, use a NormalizedTally instead of a Tally.

TallyInterface tally = new NormalizedTally(new ProposalTallyInterface[] {
        // Amounts of judgments received of each grade, from "worst" grade to "best" grade
        new ProposalTally(new Integer[]{4, 5, 2, 1, 3, 1, 2}),  // Proposal A
        new ProposalTally(new Integer[]{3, 6, 2, 1, 3, 1, 2}),  // Proposal B
        // …
});

This normalization uses the Least Common Multiple, in order to skip floating-point arithmetic.

Collect a Tally from judgments

It's usually best to use structured queries (eg: in SQL) directly in your database to collect the tallies, since it scales better with high amounts of participants, but if you must you can collect the tally directly from individual judgments, with a CollectedTally.

Integer amountOfProposals = 2;
Integer amountOfGrades = 4;
DeliberatorInterface mj = new MajorityJudgmentDeliberator();
CollectedTally tally = new CollectedTally(amountOfProposals, amountOfGrades);

Integer firstProposal = 0;
Integer secondProposal = 1;
Integer gradeReject = 0;
Integer gradePassable = 1;
Integer gradeGood = 2;
Integer gradeExcellent = 3;

// Collect the judgments, one-by-one, with `collect()`
tally.collect(firstProposal, gradeReject);
tally.collect(firstProposal, gradeReject);
tally.collect(firstProposal, gradePassable);
tally.collect(firstProposal, gradePassable);
tally.collect(firstProposal, gradePassable);
tally.collect(firstProposal, gradeExcellent);
tally.collect(firstProposal, gradeExcellent);

tally.collect(secondProposal, gradeReject);
tally.collect(secondProposal, gradeReject);
tally.collect(secondProposal, gradeGood);
tally.collect(secondProposal, gradeGood);
tally.collect(secondProposal, gradeGood);
tally.collect(secondProposal, gradeExcellent);
tally.collect(secondProposal, gradeExcellent);

// …

ResultInterface result = mj.deliberate(tally);

Roadmap

  • Unit-Tests
  • Deliberation algorithm
    • Tally Analysis
    • Score Calculus
    • Ranking
  • Release v0.1.0
  • Guess the amount of judges
  • Allow defining a default grade
    • Static Grade (configurable)
    • Normalization (using Least Common Multiple)
    • Median Grade
  • Release v0.2.0
  • Publish on package repositories
    • Gradle
    • Maven
    • … ? (please share your knowledge to help us!)
  • Release v0.3.0
  • Use it somewhere in an application, adjust API as needed (one last time)
  • Release v1.0.0

Gondor calls for Help!

We are not accustomed to Java library development and we'd love reviews from seasoned veterans !

Feel free to fork and request merges for your contributions and active readings !

Run the test-suite

Install maven, and run:

mvn test

Maven is available as a debian package: apt install maven

You can also use a runner in Eclipse. (CTRL+F11 to rerun)

License

MITDo whatever you want except complain.

Majority Judgment itself is part of the Commons, obviously.

Fund us

We'd love to invest more energy in Majority Judgment development.

Please consider funding us, every bit helps : https://www.paypal.com/donate/?hosted_button_id=QD6U4D323WV4S