Esempio n. 1
0
 def scores_(self) -> NiceDict:
     """NiceDict: The scores. A :class:`NiceDict` of triples.
     """
     levels_ = NiceDict({c: [] for c in self.candidates_})
     weights_ = NiceDict({c: [] for c in self.candidates_})
     for ballot, weight, voter in self.profile_converted_.items():
         for c, level in self.scorer(ballot=ballot, voter=voter, candidates=self.candidates_).scores_.items():
             levels_[c].append(level)
             weights_[c].append(weight)
     scores_ = NiceDict()
     for c in self.candidates_:
         if not levels_[c]:
             scores_[c] = (self.default_median, 0, 0)
             continue
         indexes = self.scorer.scale.argsort(levels_[c])
         levels_[c] = [levels_[c][i] for i in indexes]
         weights_[c] = [weights_[c][i] for i in indexes]
         total_weight = sum(weights_[c])
         half_total_weight = my_division(total_weight, 2)
         cumulative_weight = 0
         median = None
         for i, weight in enumerate(weights_[c]):
             cumulative_weight += weight
             if cumulative_weight >= half_total_weight:
                 median = levels_[c][i]
                 break
         p = sum([weights_[c][i] for i, level in enumerate(levels_[c]) if self.scorer.scale.gt(level, median)])
         q = sum([weights_[c][i] for i, level in enumerate(levels_[c]) if self.scorer.scale.lt(level, median)])
         if p > q:
             scores_[c] = (median, my_division(p, total_weight), -my_division(q, total_weight))
         else:
             scores_[c] = (median, -my_division(q, total_weight), my_division(p, total_weight))
     return scores_
 def scores_(self) -> NiceDict:
     return NiceDict({
         c: my_division(score,
                        self.weights_[c],
                        divide_by_zero=self.default_average)
         for c, score in self.gross_scores_.items()
     })
 def scores_(self) -> NiceDict:
     levels_ = NiceDict({c: [] for c in self.candidates_})
     weights_ = NiceDict({c: [] for c in self.candidates_})
     for ballot, weight, voter in self.profile_converted_.items():
         for c, level in self.scorer(ballot=ballot, voter=voter, candidates=self.candidates_).scores_.items():
             levels_[c].append(level)
             weights_[c].append(weight)
     scores_ = NiceDict()
     for c in self.candidates_:
         if not levels_[c]:
             scores_[c] = (self.default_median, 0)
             continue
         indexes = self.scorer.scale.argsort(levels_[c])
         levels_[c] = [levels_[c][i] for i in indexes]
         weights_[c] = [weights_[c][i] for i in indexes]
         total_weight = sum(weights_[c])
         half_total_weight = my_division(total_weight, 2)
         cumulative_weight = 0
         median = None
         for i, weight in enumerate(weights_[c]):
             cumulative_weight += weight
             if cumulative_weight >= half_total_weight:
                 median = levels_[c][i]
                 break
         support = convert_number(sum([
             weights_[c][i] for i, level in enumerate(levels_[c]) if self.scorer.scale.ge(level, median)]))
         scores_[c] = (median, support)
     return scores_
Esempio n. 4
0
 def scores_(self) -> NiceDict:
     scores = NiceDict()
     points_remaining = self.k
     # Ordered candidates
     for indifference_class in self.ballot_.as_weak_order[:]:
         n_indifference = len(indifference_class)
         if n_indifference <= points_remaining:
             scores.update({c: 1 for c in indifference_class})
             points_remaining -= n_indifference
         else:
             scores.update({
                 c: my_division(points_remaining, n_indifference)
                 for c in indifference_class
             })
             points_remaining = 0
     # Unordered candidates
     if self.unordered_receive_points is False:
         scores.update({c: 0 for c in self.ballot_.candidates_not_in_b})
     elif self.unordered_receive_points is True:
         unordered = self.ballot_.candidates_not_in_b
         n_unordered = len(unordered)
         if n_unordered <= points_remaining:
             scores.update({c: 1 for c in unordered})
             points_remaining -= n_unordered
         else:
             scores.update({
                 c: my_division(points_remaining, n_unordered)
                 for c in unordered
             })
             points_remaining = 0
     # Absent candidates
     if self.absent_receive_points is False:
         scores.update(
             {c: 0
              for c in self.candidates_ - self.ballot_.candidates})
     elif self.absent_receive_points is True:
         absent = self.candidates_ - self.ballot_.candidates
         n_absent = len(absent)
         if n_absent <= points_remaining:
             scores.update({c: 1 for c in absent})
         else:
             scores.update({
                 c: my_division(points_remaining, n_absent)
                 for c in absent
             })
     return scores
Esempio n. 5
0
 def as_dict_(self):
     net_matrix = {(c, d): self.diagonal_score if c == d else my_division(
         self.gross_[(c, d)], w, divide_by_zero=self.default_score)
                   for (c, d), w in self.weights_.items()}
     if self.antisymmetric:
         return {(c, d): net_matrix[(c, d)] - net_matrix[(d, c)]
                 for (c, d) in net_matrix.keys()}
     else:
         return net_matrix
Esempio n. 6
0
 def scores_(self) -> NiceDict:
     scores = NiceDict()
     points_from_lower_candidates = 0
     # Absent candidates
     if self.absent_give_points or self.absent_receive_points is not None:
         absent = self.candidates_ - self.ballot_.candidates
         n_absent = len(absent)
         if self.absent_receive_points is False:
             scores.update({c: 0 for c in absent})
         if self.absent_receive_points is True:
             points_temp = my_division(n_absent - 1,
                                       2) if self.absent_give_points else 0
             scores.update({c: points_temp for c in absent})
         if self.absent_give_points:
             points_from_lower_candidates += n_absent
     # Unordered candidates
     if self.unordered_give_points or self.unordered_receive_points is not None:
         unordered = self.ballot_.candidates_not_in_b
         n_unordered = len(unordered)
         if self.unordered_receive_points is False:
             scores.update({c: 0 for c in unordered})
         if self.unordered_receive_points is True:
             points_temp = points_from_lower_candidates
             if self.unordered_give_points:
                 points_temp += my_division(n_unordered - 1, 2)
             scores.update({c: points_temp for c in unordered})
         if self.unordered_give_points:
             points_from_lower_candidates += n_unordered
     # Ordered candidates
     for indifference_class in self.ballot_.as_weak_order[::-1]:
         n_indifference = len(indifference_class)
         points_temp = points_from_lower_candidates + my_division(
             n_indifference - 1, 2)
         scores.update({c: points_temp for c in indifference_class})
         points_from_lower_candidates += n_indifference
     return scores
 def detailed_scores_(self) -> list:
     """list: Detailed scores. A list of :class:`NiceDict`. The first dictionary gives the scores of the first round,
     etc.
     """
     n_candidates = len(self.candidates_)
     detailed_scores = []
     for k in range(1, n_candidates + 1):
         self.scorer.k = k
         gross_scores = NiceDict({c: 0 for c in self.candidates_})
         weights = NiceDict({c: 0 for c in self.candidates_})
         for ballot, weight, voter in self.profile_converted_.items():
             for c, value in self.scorer(
                     ballot=ballot, voter=voter,
                     candidates=self.candidates_).scores_.items():
                 gross_scores[c] += weight * value
                 weights[c] += weight
         scores = NiceDict({
             c: my_division(score, weights[c], divide_by_zero=0)
             for c, score in gross_scores.items()
         })
         detailed_scores.append(scores)
         if max(scores.values()) > Fraction(1, 2):
             break
     return detailed_scores
Esempio n. 8
0
 def average_score_(self) -> Number:
     """Number: The average score.
     """
     return my_division(sum(self.scores_.values()), self.n_candidates_)
Esempio n. 9
0
def test_my_division():
    with pytest.raises(ZeroDivisionError):
        _ = my_division(1, 0)
    with pytest.raises(NotImplementedError):
        # noinspection PyTypeChecker
        _ = my_division(1, 'a')
Esempio n. 10
0
 def __call__(self, x: object, candidates: set = None) -> BallotLevels:
     x = ConverterBallotGeneral()(x, candidates=None)
     if isinstance(x, BallotVeto):
         if x.candidate is None:
             return BallotLevels(
                 dict(), candidates=x.candidates,
                 scale=self.scale).restrict(candidates=candidates)
         return BallotLevels(
             {
                 c: self.low if c == x.candidate else self.high
                 for c in x.candidates
             },
             candidates=x.candidates,
             scale=self.scale).restrict(candidates=candidates)
     if isinstance(x, BallotOneName):  # Including Plurality
         if x.candidate is None:
             return BallotLevels(
                 dict(), candidates=x.candidates,
                 scale=self.scale).restrict(candidates=candidates)
         return BallotLevels(
             {
                 c: self.high if c == x.candidate else self.low
                 for c in x.candidates
             },
             candidates=x.candidates,
             scale=self.scale).restrict(candidates=candidates)
     if isinstance(x, BallotLevels):
         if not x.scale.is_bounded:
             if all([isinstance(v, numbers.Number) for v in x.values()]):
                 x_min, x_max = min(x.values()), max(x.values())
                 if x_min >= self.low and x_max <= self.high:
                     return BallotLevels(
                         x.as_dict,
                         candidates=x.candidates,
                         scale=ScaleInterval(low=self.low,
                                             high=self.high)).restrict(
                                                 candidates=candidates)
                 else:
                     x = BallotLevels(x.as_dict,
                                      candidates=x.candidates,
                                      scale=ScaleInterval(
                                          low=min(x.values()),
                                          high=max(x.values())))
             else:
                 x = BallotLevels(x.as_dict,
                                  candidates=x.candidates,
                                  scale=ScaleFromSet(set(x.values())))
         try:  # Interpret as a cardinal ballot
             return BallotLevels(
                 {
                     c: self.low + my_division(
                         (self.high - self.low) * (v - x.scale.low),
                         (x.scale.high - x.scale.low))
                     for c, v in x.items()
                 },
                 candidates=x.candidates,
                 scale=self.scale).restrict(candidates=candidates)
         except (TypeError, AttributeError):
             x_scale = x.scale
             if isinstance(x_scale, ScaleFromList):
                 return BallotLevels(
                     {
                         c: self.low + my_division(
                             (self.high - self.low) * x_scale.as_dict[x[c]],
                             (len(x_scale.levels) - 1))
                         for c, v in x.items()
                     },
                     candidates=x.candidates,
                     scale=self.scale).restrict(candidates=candidates)
     if isinstance(x, BallotOrder):
         borda = ScorerBorda(
             ballot=x,
             candidates=x.candidates,
             unordered_give_points=self.borda_unordered_give_points).scores_
         score_max = len(
             x.candidates) - 1 if self.borda_unordered_give_points else len(
                 x.candidates_in_b) - 1
         return BallotLevels(
             {
                 c: self.low + my_division(
                     (self.high - self.low) * borda[c], score_max)
                 for c in x.candidates_in_b
             },
             candidates=x.candidates,
             scale=self.scale).restrict(candidates=candidates)
     raise NotImplementedError