Source code for embedded_voting.rules.multiwinner_rules.multiwinner_rule_iter_svd

import numpy as np
from embedded_voting.embeddings.embeddings_generator_polarized import EmbeddingsGeneratorPolarized
from embedded_voting.ratings_from_embeddings.ratings_from_embeddings_correlated import RatingsFromEmbeddingsCorrelated
from embedded_voting.rules.multiwinner_rules.multiwinner_rule_iter import MultiwinnerRuleIter


[docs]class MultiwinnerRuleIterSVD(MultiwinnerRuleIter): """ Iterative multiwinner rule based on a SVD aggregation rule. Parameters __________ k : int The size of the committee. aggregation_rule : callable The aggregation rule for the singular values. By default, it is the maximum. square_root : bool If True, we take the square root of the scores instead of the scores for the :meth:`~embedded_voting.Embeddings.scored_embeddings`. quota : str The quota used for the re-weighing step. Either ``'droop'`` quota `(n/(k+1) +1)` or ``'classic'`` quota `(n/k)`. take_min : bool If True, when the total satisfaction is less than the :attr:`~embedded_voting.MultiwinnerRuleIter.quota`, we replace the quota by the total satisfaction. By default, it is set to False. Examples -------- >>> np.random.seed(42) >>> ratings_dim_candidate = np.array([[1, 0.8, 0.5, 0, 0, 0], [0, 0, 0, 0.5, 0.8, 1]]) >>> probability = [3/4, 1/4] >>> embeddings = EmbeddingsGeneratorPolarized(100, 2, probability)(1) >>> ratings = RatingsFromEmbeddingsCorrelated(coherence=1, ratings_dim_candidate=ratings_dim_candidate)(embeddings) >>> election = MultiwinnerRuleIterSVD(3)(ratings, embeddings) >>> election.winners_ [0, 1, 5] >>> _ = election.set_k(4) >>> election.winners_ [0, 1, 5, 2] >>> election.plot_weights(dim=[0, 0, 0], show=False) Weight / remaining candidate : [25.0, 24.99999999999999, 24.999999999999996, 30.999999999999993] >>> election.features_vectors Embeddings([[1., 0.], [1., 0.], [0., 1.], [1., 0.]]) """ def __init__(self, k=None, aggregation_rule=np.max, square_root=True, quota="classic", take_min=False): self.aggregation_rule = aggregation_rule self.square_root = square_root super().__init__(k=k, quota=quota, take_min=take_min) def _winner_k(self, winners): vectors = [] scores = [] n_candidates = self.ratings.n_candidates n_dim = self.embeddings.n_dim for candidate in range(n_candidates): if candidate in winners: scores.append(0) vectors.append(np.zeros(n_dim)) continue if self.square_root: embeddings = self.embeddings.times_ratings_candidate(np.sqrt(self.ratings.candidate_ratings(candidate))) else: embeddings = self.embeddings.times_ratings_candidate(self.ratings.candidate_ratings(candidate)) weights = self.weights if self.square_root: weights = np.sqrt(weights) embeddings = np.dot(np.diag(weights), embeddings) _, s_values, s_vectors = np.linalg.svd(embeddings, full_matrices=False) scores.append(self.aggregation_rule(s_values)) vec = s_vectors[0] if vec.sum() < 0: vec = -vec vectors.append(vec) scores = np.array(scores) scores[winners] = 0 winner_j = np.argmax(scores) vec = vectors[winner_j] return winner_j, vec