Vote objects and vote validation API

Vote type specifications and vote validators.

Vote types vary from system to system and are only loosely tied to the method of evaluation (usually, the richer vote types can be reduced to use simple evaluators but not vice versa). The following vote types are recognized by Votelib:

  • Simple votes - a voter votes for a single candidate. Represented by the candidate object itself.

  • Approval votes - a voter selects a number of candidates and votes for them equally. Represented by a frozen set of candidate objects.

  • Ranked votes - a voter ranks a number of candidates. Represented by a tuple of candidate objects or frozen sets of them (to account for possible tied rankings).

  • Score votes - a voter assigns a score (label) to a number of candidates. The scores might either be selected from a predefined set or arbitrary numbers from a range.

Voting systems generally require one of the above types and usually impose additional restrictions such as minimum and maximum number of candidates voted for or ranked. These restrictions are handled by parameters accepted by the vote validators.

Vote validators validate individual votes, i.e. the keys of the dictionaries that should be passed to the evaluators. If a vote is invalid, they raise a subclass of VoteError (or CandidateError, if a candidate contained in the vote is invalid). Some converter objects wrap these validators and catch these errors to remove invalid votes, for example.

Vote validators

class votelib.vote.SimpleVoteValidator(nominator=<votelib.candidate.BasicNominator object>)

Validate a simple vote (voting directly for a single candidate).

The candidate must be a valid atomic candidate object according to the nominator object specified.

Parameters

nominator (Nominator) – Nominator used to check candidates. The default uses only technical criteria specified by the Candidate class.

validate(vote)

Check if the candidate is valid.

Parameters

vote (Union[str, CandidateObject]) – Simple vote to be checked.

Raises

CandidateError – If the candidate is invalid.

Return type

None

class votelib.vote.ApprovalVoteValidator(vote_count_bounds=(None, None), count_checker=None, nominator=<votelib.candidate.BasicNominator object>)

Validate an approval vote (voting for a number of candidates equally).

The vote must be a frozen set containing valid atomic candidates. The atomic candidates must not be tuples.

Parameters
  • vote_count_bounds (Tuple[Optional[int], Optional[int]]) – A tuple with lower and upper bounds (inclusive) for the number of candidates any vote can contain. None means the respective bound is not checked. Ignored if count_checker is given.

  • count_checker (Optional[VoteMagnitudeChecker]) – A VoteMagnitudeChecker that checks the number of candidates any vote can contain.

  • nominator (Nominator) – Nominator used to check candidates. The default uses the technical criteria specified by the Candidate class.

validate(vote)

Check if the approval vote is valid.

Parameters

vote (FrozenSet[Union[str, CandidateObject]]) – Approval vote to be checked.

Raises
Return type

None

class votelib.vote.RankedVoteValidator(total_vote_count_bounds=(None, None), rank_vote_count_bounds=(1, 1), total_count_checker=None, rank_vote_count_checkers=None, nominator=<votelib.candidate.BasicNominator object>)

Validate a ranked vote (ranking of a number of candidates).

The vote must be a tuple of candidates or frozen sets thereof. Usage of sets indicates tied rankings, which are not common but allowed in some systems.

Parameters
  • total_vote_count_bounds (Tuple[Optional[int], Optional[int]]) – A tuple with lower and upper bounds (inclusive) for the number of candidates any vote can rank. None means the respective bound is not checked. Ignored if total_count_checker is given.

  • rank_vote_count_bounds (Union[Tuple[Optional[int], Optional[int]], Dict[int, Tuple[Optional[int], Optional[int]]]]) – A tuple with lower and upper bounds (inclusive) for the number of candidates allowed to share any rank. The default settings disallow tied rankings. None means the respective bound is not checked. Alternatively, a dictionary can be specified that maps ranks (1-indexed) to bound tuples. Ignored if rank_vote_count_checkers is given.

  • total_count_checker (Optional[VoteMagnitudeChecker]) – A VoteMagnitudeChecker that checks the total number of candidates any vote can rank.

  • rank_vote_count_checkers (Optional[Dict[int, VoteMagnitudeChecker]]) – A mapping of integer ranks to instances of VoteMagnitudeChecker to check numbers of candidates allowed to share any rank.

  • nominator (Nominator) – Nominator used to check candidates. The default uses only technical criteria specified by the Candidate class.

validate(vote)

Check if the ranked vote is valid.

Parameters

vote (Tuple[Union[str, CandidateObject, FrozenSet[Union[str, CandidateObject]]], …]) – Ranked vote to be checked.

Raises
  • VoteTypeError – If the vote is not a tuple.

  • VoteError – If any candidate is specified more than once in the ranking.

  • CandidateError – If any of the contained candidates is invalid.

  • VoteMagnitudeError – If the number of candidates (total or at particular ranking tier) is out of the specified bounds.

Return type

None

class votelib.vote.EnumScoreVoteValidator(score_levels, allowed_scorings=(None, None), sum_bounds=(None, None), n_scorings_checker=None, sum_checkers=None, nominator=<votelib.candidate.BasicNominator object>)

Validate an enumeration-based score vote.

An enumeration-based score vote assigns scores from a predefined finite set to candidates. It should be represented as a frozen set of doubles containing a candidate and the associated score. This variant is the most common for score-based voting systems since the voters are usually given a predefined finite set of (possibly non-numeric) scores; for true range voting where the voters might specify arbitrary score values, use RangeVoteValidator.

If numeric scores are used, the usage of exact numeric types (integers, fractions, decimals) is encouraged.

Parameters
  • score_levels (Collection[Any]) – A collection of allowed scores.

  • allowed_scorings (Tuple[Optional[int], Optional[int]]) – A tuple with lower and upper bounds (inclusive) for the number of candidates allowed to appear in any single vote. None means the respective bound is not checked. Ignored if n_scorings_checker is given.

  • sum_bounds (Union[Tuple[Optional[Number], Optional[Number]], Dict[int, Tuple[Optional[Number], Optional[Number]]]]) – A tuple with lower and upper bounds (inclusive) for the total sum of numeric scores allowed for any single vote. None means the respective bound is not checked. You can also provide a dictionary that gives different sum bounds for different numbers of candidates scored (numbers of candidates scored that do not have a corresponding key will not have their sums checked then). Ignored if sum_checkers are given.

  • n_scorings_checker (Optional[VoteMagnitudeChecker]) – A VoteMagnitudeChecker that checks the total number of candidates any vote can score.

  • sum_checkers (Optional[Dict[int, VoteMagnitudeChecker]]) – A mapping of integer numbers of scored candidates to instances of VoteMagnitudeChecker checking the allowed total score allocated to all candidates.

  • nominator (Nominator) – Nominator used to check candidates. The default uses only technical criteria specified by the Candidate class.

validate(vote)

Check if the enumeration-based score vote is valid.

Parameters

vote (FrozenSet[Tuple[Union[str, CandidateObject], Any]]) – Score vote to be checked.

Raises
  • VoteTypeError – If the vote is not a frozen set.

  • CandidateError – If any of the contained candidates is invalid.

  • VoteMagnitudeError – If the number of candidates scored or the total sum of scores is out of the specified bounds, or any of the items in the vote is not a tuple pair.

  • VoteValueError – If any of the scores is not in the predefined set of allowed scores.

Return type

bool

class votelib.vote.RangeVoteValidator(range=(None, None), allowed_scorings=(None, None), sum_bounds=(None, None), range_checker=None, n_scorings_checker=None, sum_checkers=None, nominator=<votelib.candidate.BasicNominator object>)

Validate a range (non-enumerative score) vote.

An range vote assigns scores from a predefined interval to candidates. It should be represented as a frozen set of doubles containing a candidate and the associated score. This variant is mostly theoretical since most systems only allow choice from a finite set of scores; for that variant, use EnumScoreVoteValidator.

The usage of exact numeric types (integers, fractions, decimals) for scores is encouraged.

Parameters
  • range (Tuple[Optional[Number], Optional[Number]]) – A tuple with lower and upper bounds (inclusive) for any single score value. None means the respective bound is not checked.

  • allowed_scorings (Tuple[Optional[int], Optional[int]]) – A tuple with lower and upper bounds (inclusive) for the number of candidates allowed to appear in any single vote. None means the respective bound is not checked. Ignored if n_scorings_checker is given.

  • sum_bounds (Union[Tuple[Optional[Number], Optional[Number]], Dict[int, Tuple[Optional[Number], Optional[Number]]]]) – A tuple with lower and upper bounds (inclusive) for the total sum of numeric scores allowed for any single vote. None means the respective bound is not checked. Ignored if sum_checkers are given.

  • n_scorings_checker (Optional[VoteMagnitudeChecker]) – A VoteMagnitudeChecker that checks the total number of candidates any vote can score.

  • sum_checkers (Optional[Dict[int, VoteMagnitudeChecker]]) – A mapping of integer numbers of scored candidates to instances of VoteMagnitudeChecker checking the allowed total score allocated to all candidates.

  • nominator (Nominator) – Nominator used to check candidates. The default uses only technical criteria specified by the Candidate class.

validate(vote)

Check if the range vote is valid.

Parameters

vote (FrozenSet[Tuple[Union[str, CandidateObject], Any]]) – Range (score) vote to be checked.

Raises
  • VoteTypeError – If the vote is not a frozen set.

  • CandidateError – If any of the contained candidates is invalid.

  • VoteMagnitudeError – If the number of candidates scored, the total sum of scores or any single score is out of the specified bounds, or any of the items in the vote is not a tuple pair.

Return type

bool

An abstract class defining the vote validator interface is also present.

class votelib.vote.VoteValidator

Validate that a single vote is valid under the election rules.

Base class, not intended for direct use.

abstract validate(vote)

Check if the vote satisfies criteria given by the voting system.

Raises

NotImplementedError

Return type

None

Vote validation errors

class votelib.vote.VoteError

A vote is invalid given the election rules.

class votelib.vote.VoteTypeError(vtype, expected=None)

A vote is of an invalid type.

E.g. ranked votes in place of simple votes.

Parameters
  • vtype (type) – Vote type detected as invalid.

  • expected (Optional[type]) – Vote type that was expected.

class votelib.vote.VoteMagnitudeError(value, min_value=None, max_value=None, value_name='count')

A vote is too small or too large.

Parameters
  • value (Number) – Size of the vote that was found to be invalid.

  • min_value (Optional[Number]) – Minimum value permissible in the context.

  • max_value (Optional[Number]) – Maximum value permissible in the context.

  • value_name (str) – Role of the vote size (e.g. number of approval votes, number of ranked candidates…)

class votelib.vote.VoteValueError(value, candidate=None, allowed=None)

An explicitly given vote value is invalid.

Parameters
  • value (Any) – Value of the vote that is invalid.

  • candidate (Union[str, CandidateObject, None]) – A candidate that the vote was given for. If None, a specific candidate could not be pinpointed.

  • allowed (Optional[Any]) – A spectrum of values that is allowed at the given point.