Source code for pref_voting.generate_spatial_profiles

import numpy as np
from pref_voting.spatial_profiles import SpatialProfile


[docs] def generate_covariance(n_dimensions, std, rho): """ Generates a covariance matrix for a multivariate normal distribution with the given standard deviation and correlation coefficient. Parameters ---------- n_dimensions : int The number of dimensions. std : float The standard deviation. rho : float The correlation coefficient. Returns ------- cov : numpy.ndarray The covariance matrix for a multivariate normal distribution. """ assert std > 0, "Standard deviation must be positive" assert rho >= 0 and rho <= 1, "Correlation coefficient must be between 0 and 1" assert n_dimensions > 0, "Number of dimensions must be positive" cov = (std**2) * (np.eye(n_dimensions) + rho * (np.ones((n_dimensions, n_dimensions)) - np.eye(n_dimensions))) return cov
[docs] def generate_spatial_profile(num_cands, num_voters, num_dims, cand_cov = None, voter_cov = None, num_profiles = 1): """ Generates a spatial profile with the candidate and voter positions generated by a multivariate normal distribution with num_dims dimensions and cand_cov the covariance matrix for candidates and voter_cov the covariance matrix for voters. Parameters ---------- num_cands : int The number of candidates. num_voters : int The number of voters. num_dims : int The number of dimensions. cand_cov : numpy.ndarray, optional The covariance matrix for the multivariate normal distribution for candidates. The default is None. voter_cov : numpy.ndarray, optional The covariance matrix for the multivariate normal distribution for voters. The default is the identity matrix. Returns ------- SpatialProfile A spatial profile with the candidate and voter positions generated by a multivariate normal distribution with num_dims dimensions and cand_cov the covariance matrix for candidates and voter_cov the covariance matrix for voters. """ cand_cov = np.eye(num_dims) if cand_cov is None else cand_cov voter_cov = np.eye(num_dims) if voter_cov is None else voter_cov assert num_dims == cand_cov.shape[0] == cand_cov.shape[1], "Candidate covariance matrix must be square and have the same number of dimensions as the number of dimensions specified" assert num_dims == voter_cov.shape[0] == voter_cov.shape[1], "Voter covariance matrix must be square and have the same number of dimensions as the number of dimensions specified" cand_mean = np.zeros(num_dims) voter_mean = np.zeros(num_dims) cand_samples = np.random.multivariate_normal(cand_mean, cand_cov, size=(num_profiles,num_cands)) voter_samples = np.random.multivariate_normal(voter_mean, voter_cov, size=(num_profiles,num_voters)) profs = [SpatialProfile({c: cand_samples[pidx][c] for c in range(num_cands)}, {v: voter_samples[pidx][v] for v in range(num_voters)}) for pidx in range(num_profiles)] return profs[0] if num_profiles == 1 else profs
[docs] def generate_spatial_profile_polarized(cand_clusters, voter_clusters, num_profiles = 1): """ Generates a spatial profile with polarized clusters of candidates and voters. Parameters ---------- cand_clusters : list A list of tuples of the form (mean, covariance, number of candidates) for each cluster of candidates. voter_clusters : list A list of tuples of the form (mean, covariance, number of voters) for each cluster of voters. num_profiles : int, optional The number of profiles to generate. The default is 1. Returns ------- SpatialProfile A spatial profile with polarized clusters of candidates and voters. """ cand_samples = list() total_num_cands = 0 for cand_cluster in cand_clusters: cand_mean, cand_cov, num_cands = cand_cluster total_num_cands += num_cands cluster_samples = np.random.multivariate_normal(cand_mean, cand_cov, size=(num_profiles,num_cands)) if len(cand_samples) == 0: cand_samples = cluster_samples else: cand_samples = np.concatenate([cand_samples, cluster_samples], axis=1) voter_samples = list() total_num_voters = 0 for voter_cluster in voter_clusters: voter_mean, voter_cov, num_voters = voter_cluster total_num_voters += num_voters cluster_samples = np.random.multivariate_normal(voter_mean, voter_cov, size=(num_profiles,num_voters)) if len(voter_samples) == 0: voter_samples = cluster_samples else: voter_samples = np.concatenate([voter_samples, cluster_samples], axis=1) profs = [SpatialProfile({cidx: cand_samples[pidx][cidx] for cidx in range(total_num_cands)}, {vidx: voter_samples[pidx][vidx] for vidx in range(total_num_voters)}) for pidx in range(num_profiles)] return profs[0] if num_profiles == 1 else profs
def generate_spatial_profile_polarized_cands_randomly_polarized_voters( cand_clusters, num_voters, voter_distributions, num_profiles = 1): """ Generates a spatial profile with polarized clusters of candidates and voters. Parameters ---------- cand_clusters : list A list of tuples of the form (mean, covariance, number of candidates) for each cluster of candidates. num_voters : int The number of voters. voter_distributions : list A list of tuples of the form (mean, covariance, prob) for each distribution of voters, where prob is the probability that a voter is assigned to this cluster. num_profiles : int, optional The number of profiles to generate. The default is 1. Returns ------- SpatialProfile A spatial profile with polarized clusters of candidates and voters. """ cand_samples = list() total_num_cands = 0 for cand_cluster in cand_clusters: cand_mean, cand_cov, num_cands = cand_cluster total_num_cands += num_cands cluster_samples = np.random.multivariate_normal(cand_mean, cand_cov, size=(num_profiles,num_cands)) if len(cand_samples) == 0: cand_samples = cluster_samples else: cand_samples = np.concatenate([cand_samples, cluster_samples], axis=1) all_potential_voters = list() voter_cluster_probs = list() for voter_distribution in voter_distributions: voter_mean, voter_cov, prob = voter_distribution all_potential_voters.append(np.random.multivariate_normal(voter_mean, voter_cov, size=(num_profiles, num_voters))) voter_cluster_probs.append(prob) # for each profile, randomly assign voters to clusters #voters = range(num_voters) voters_clusters_assignment = np.random.choice(len(all_potential_voters), size=(num_profiles, num_voters), p = voter_cluster_probs) profs = [SpatialProfile({cidx: cand_samples[pidx][cidx] for cidx in range(total_num_cands)}, {vidx: all_potential_voters[voters_clusters_assignment[pidx][vidx]][pidx][vidx] for vidx in range(num_voters)}) for pidx in range(num_profiles)] return profs[0] if num_profiles == 1 else profs