UNPKG

ecclesia

Version:

Framework for political and electoral simulations

84 lines (81 loc) 3.79 kB
import { Collection } from '@gouvernathor/python/collections/abc'; import { RandomObjParam } from '../utils.js'; import { Ballots, Simple, Order, Scores } from './ballots.js'; import '@gouvernathor/rng'; import '@gouvernathor/python/collections'; interface DisagreementFunction<T, U> { (t: T, u: U): number; } interface Voting<Voter, Party, B extends Ballots<Party>> { (voters: Collection<Voter>, candidates: Collection<Party>): B; } /** * Turns a voting method into one in which the candidates are shuffled randomly * before being given to the actual voting method passed to this function. * * If a RNG instance is passed (through options), it will be used directly, * without reseeding, at each call of the voting method. * * If a seed is passed, the random object is reseeded * with the same seed at each call of the voting method, * making the resulting function return the same values for the same parameters * (assuming the passed base voting method does). * If you want the generator to be seeded only once with a given seed, and reused afterwards, * seed it yourself and pass it as a random object to this function. */ declare function toShuffledVote<Voter, Party, B extends Ballots<Party>>({ voting, ...rest }: { voting: Voting<Voter, Party, B>; } & RandomObjParam): Voting<Voter, Party, B>; /** * The most basic and widespread voting system : each voter casts one ballot for * one of the available candidates, or (not implemented here) for none of them. */ declare function singleVote<Voter, Party>({ disagree }: { disagree: DisagreementFunction<Voter, Party>; }): Voting<Voter, Party, Simple<Party>>; /** * Each voter ranks all, or (not implemented here) some, of the candidates. */ declare function orderingVote<Voter, Party>({ disagree }: { disagree: DisagreementFunction<Voter, Party>; }): Voting<Voter, Party, Order<Party>>; /** * Each voter gives a note (or grade) to each candidate. * The number of grades must be provided to the constructor. * * This one is not as straightforward as the two previous ones, even setting * strategic voting aside. * What is to be considered to be the range of grades to cover ? * From nazis to angels, or from the worst present candidate to the best ? * The answer lies only in the minds of the voters. * The latter is more akin to OrderingVote, so I made the former the default, * but it causes issues for lower grades so ApprovalVote uses the latter. * * In this implementation, each voter gives a grade to each party * proportional to the raw disagreement. This may yield situations * where every party is graded 0, especially with low ngrades values. */ declare function cardinalVote<Voter, Party>({ nGrades, disagree }: { nGrades: number; disagree: DisagreementFunction<Voter, Party>; }): Voting<Voter, Party, Scores<Party>>; /** * Alternative implementation of CardinalVote. */ declare function balancedCardinalVote<Voter, Party>({ nGrades, disagree }: { nGrades: number; disagree: DisagreementFunction<Voter, Party>; }): Voting<Voter, Party, Scores<Party>>; /** * Each voter approves or disapproves each of the candidates * * Technically a special case of grading vote where grades are 0 and 1, * but it makes it open to additional attribution methods * (proportional ones for example). * That's why the format it returns is not the same as with the cardinal vote. * If you want a scores-like attribution, use balancedCardinalVote({ nGrades: 2 }) instead. */ declare function approvalVote<Voter, Party>({ disagree }: { disagree: DisagreementFunction<Voter, Party>; }): Voting<Voter, Party, Simple<Party>>; export { type DisagreementFunction, type Voting, approvalVote, balancedCardinalVote, cardinalVote, orderingVote, singleVote, toShuffledVote };