Source code for embedded_voting.rules.singlewinner_rules.rule_model_aware

import numpy as np
from embedded_voting.rules.singlewinner_rules.rule import Rule
from embedded_voting.utils.cached import cached_property
from embedded_voting.ratings.ratings import Ratings


[docs]class RuleModelAware(Rule): """ A rule that is know the noise parameters of the model and use the maximum likelihood to select the best candidate. Parameters ---------- groups_sizes : list of int The number of voters in each group. groups_features : np.ndarray of shape (n_groups, n_features) The features of each group. group_noise : float The value of the feature noise. independent_noise : float The value of the distinct noise. Examples -------- >>> ratings = Ratings(np.array([[.5, .6, .3], [.7, 0, .2], [.2, 1, .8]])) >>> election = RuleModelAware([2, 1], [[1, 0], [0, 1]], group_noise=1, independent_noise=1)(ratings) >>> election.ranking_ [1, 2, 0] >>> election.scores_ [0.5, 0.7, 0.5666666...] >>> election.winner_ 1 """ def __init__(self, groups_sizes, groups_features, group_noise=1, independent_noise=0): super().__init__(score_components=1) self.groups_sizes = np.array(groups_sizes, dtype=int) self.n_voters = self.groups_sizes.sum() self.n_groups = self.groups_sizes.size self.groups_features = np.array(groups_features) self.groups_features_normalized = ( self.groups_features / self.groups_features.sum(1)[:, np.newaxis] ) noise_rescale_groups = self.groups_features.sum(1)/np.linalg.norm(self.groups_features, axis=1) self.m_voter_group = np.vstack([ np.hstack(( np.zeros((group_size, i_group)), np.ones((group_size, 1))*noise_rescale_groups[i_group], np.zeros((group_size, self.n_groups - i_group - 1)) )) for i_group, group_size in enumerate(self.groups_sizes) ]) v_noise_dependent = ( self.m_voter_group @ self.groups_features_normalized )*group_noise v_noise_independent = np.eye(self.n_voters)*independent_noise v_noise = np.concatenate([v_noise_dependent, v_noise_independent], axis=1) if independent_noise == 0: self.sigma_inv = (self.m_voter_group/self.m_voter_group.sum(0)).T else: self.sigma_inv = np.linalg.inv(np.dot(v_noise, v_noise.T)) @cached_property def weights_(self): return self.sigma_inv.sum(axis=0) def _score_(self, candidate): return self.ratings_.candidate_ratings(candidate) @ self.weights_