Source code for whalrus.ballots.ballot

# -*- coding: utf-8 -*-
"""
Copyright Sylvain Bouveret, Yann Chevaleyre and François Durand
sylvain.bouveret@imag.fr, yann.chevaleyre@dauphine.fr, fradurand@gmail.com

This file is part of Whalrus.

Whalrus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Whalrus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Whalrus.  If not, see <http://www.gnu.org/licenses/>.
"""
from whalrus.utils.utils import NiceSet


[docs]class Ballot: """ A ballot. The philosophy of this class is to stick as much as possible to the message that the voter emitted, in the context where she emitted it. For example, consider a range voting setting with candidates `a`, `b`, `c` and a scale of grades from 0 to 100. If the voter emits a ballot where `a` has grade 60 and `b` has grade 30, then the :class:`Ballot` object simply records all this: what candidates were present, what was the scale of authorized grades, and what the voter indicated in her ballot. But, for example: * It makes no assumption whether the voter prefers `a` to `c`. Maybe she did not mention `c` because she didn't like it, maybe because she didn't know it. * It makes no assumption about what would be the voter's ballot with a scale from 0 to 10. Maybe it would be ``{'a': 6, 'b': 3}``, maybe not. Ballot converters (cf. :class:`ConverterBallot`) will be used each time we need an information that is beyond what the ballot clearly indicated. """ @property def candidates(self) -> NiceSet: """NiceSet: The candidates that were available at the moment when the voter cast her ballot. As a consequence, candidates must be hashable objects. """ raise NotImplementedError
[docs] def first(self, candidates: set = None, **kwargs) -> object: """ The first (= most liked) candidate. Implementation is optional. In most subclasses, this method needs some options (``kwargs``) to solve ambiguities in this conversion. In some other subclasses, this method may even stay unimplemented. Parameters ---------- candidates : set of candidates It can be any set of candidates, not necessarily a subset of ``self.candidates``). Default: ``self.candidates``. kwargs Some options (depending on the subclass). Returns ------- candidate The first (= most liked) candidate, chosen in the intersection of ``self.candidates`` and the argument ``candidates``. Can return None for an "abstention". Examples -------- Typical example: the ballot was cast in a context where candidates `a`, `b`, `c`, `d` were declared. Hence ``self.candidates == {'a', 'b', 'c', 'd'}``. Later, candidate `a` is removed from the election. Then we can use this method with the optional argument ``candidates = {'b', 'c', 'd'}`` to know who is the most liked candidate of the voter in this new context. """ raise NotImplementedError
[docs] def last(self, candidates: set=None, **kwargs) -> object: """ The last (= most disliked) candidate. Implementation is optional. Cf. :meth:`first` for more information. Parameters ---------- candidates : set of candidates It can be any set of candidates, not necessarily a subset of ``self.candidates``). Default: ``self.candidates``. kwargs Some options (depending on the subclass). Returns ------- candidate The last (= most disliked) candidate, chosen in the intersection of ``self.candidates`` and the argument ``candidates``. Can return None for an "abstention". """ raise NotImplementedError
[docs] def restrict(self, candidates=None, **kwargs) -> 'Ballot': """ Restrict the ballot to less candidates. Implementation is optional. Additional candidates (that are in the argument ``candidates`` but not in ``self.candidates``) are generally not taken into account in the restricted ballot. For example, in a election with candidates `a`, `b`, `c`, assume that the voter emits an ordered ballot ``a > b > c``. Later, candidate `a` is removed and candidate `d` is added. Then the "restricted" ballot to ``{'b, 'c', 'd'}`` is ``b > c``. For more details, see for example :meth:`BallotOrder.restrict`. Parameters ---------- candidates : set of candidates It can be any set of candidates, not necessarily a subset of ``self.candidates``). Default: ``self.candidates``. kwargs Some options (depending on the subclass). Returns ------- Ballot The same ballot, "restricted" to the candidates given. """ raise NotImplementedError