Source code for pref_voting.generate_utility_profiles
''' File: generate_utility_profiles.py Author: Wes Holliday (wesholliday@berkeley.edu) and Eric Pacuit (epacuit@umd.edu) Date: May 26, 2023 Functions to generate utility profiles.'''frommathimportceilimportnumpyasnpfromscipy.spatialimportdistancefromfunctoolsimportpartialfrompref_voting.utility_profilesimportUtilityProfilefrompref_voting.utility_functionsimport*# turn off future warnings.# getting the following warning when calling tabulate to display a profile: # /Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tabulate.py:1027: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison# if headers == "keys" and not rows:# see https://stackoverflow.com/questions/40659212/futurewarning-elementwise-comparison-failed-returning-scalar-but-in-the-futur#importwarningswarnings.simplefilter(action='ignore',category=FutureWarning)
[docs]defgenerate_utility_profile_uniform(num_candidates,num_voters,num_profiles=1):""" Generate a utility profile where each voter assigns a random number between 0 and 1 to each candidate. Args: num_candidates (int): The number of candidates. num_voters (int): The number of voters. Returns: UtilityProfile: A utility profile. """cand_utils=np.random.uniform(size=(num_profiles,num_voters,num_candidates))uprofs=[UtilityProfile([{c:cand_utils[pidx][v][c]forcinrange(num_candidates)}forvinrange(num_voters)])forpidxinrange(num_profiles)]returnuprofsifnum_profiles>1elseuprofs[0]
[docs]defgenerate_utility_profile_normal(num_candidates,num_voters,std=0.1,normalize=None,num_profiles=1):""" Generate a utility profile where each voter assigns a random number drawn from a normal distribution with a randomly chosen mean (between 0 and 1) with standard deviation ``std`` to each candidate. Args: num_candidates (int): The number of candidates. num_voters (int): The number of voters. std (float): The standard deviation of the normal distribution. The default is 0.1. normalize (str): The normalization method to use. The default is None. Returns: UtilityProfile: A utility profile. """mean_utilities={c:np.random.uniform(0,1)forcinrange(num_candidates)}cand_utils={c:np.random.normal(mean_utilities[c],std,size=(num_profiles,num_voters))forcinrange(num_candidates)}ifnormalize=="range":uprofs=[UtilityProfile([{c:cand_utils[c][pidx][vidx]forcinrange(num_candidates)}forvidxinrange(num_voters)]).normalize_by_range()forpidxinrange(num_profiles)]elifnormalize=="score":uprofs=[UtilityProfile([{c:cand_utils[c][pidx][vidx]forcinrange(num_candidates)}forvidxinrange(num_voters)]).normalize_by_standard_score()forpidxinrange(num_profiles)]else:# do not normalizeuprofs=[UtilityProfile([{c:cand_utils[c][pidx][vidx]forcinrange(num_candidates)}forvidxinrange(num_voters)])forpidxinrange(num_profiles)]returnuprofsifnum_profiles>1elseuprofs[0]
[docs]defgenerate_spatial_utility_profile(num_cands,num_voters,num_dims=2,utility_function="Quadratic",utility_function_param=None):""" Create a spatial utility profile using specified utility functions. Args: num_cands (int): The number of candidates. num_voters (int): The number of voters. num_dims (int): The number of dimensions. The default is 2. utility_function (str): The utility function to use. The default is "Linear". utility_function_param (float): The parameter of the utility function. The default is None. Returns: UtilityProfile: A spatial utility profile. """# the first component of the parameter is the number of dimensions, # the second component is used to define the mixed model: # beta = 1 is proximity model (i.e., squared Euclidean distance)mean=[0]*num_dims# mean is 0 for each dimensioncov=np.diag([1]*num_dims)# diagonal covariance_utility_fnc=utility_functions[utility_function]["func"]ifutility_functions[utility_function]["param"]isnotNoneorutility_function_paramisnotNone:util_parm=utility_function_paramifutility_function_paramisnotNoneelseutility_functions[utility_function]["param"]utility_fnc=partial(_utility_fnc,util_parm)else:utility_fnc=_utility_fnc# sample candidate/voter positions using a multivariate normal distributioncand_positions=np.random.multivariate_normal(np.array(mean),cov,num_cands)voter_positions=np.random.multivariate_normal(np.array(mean),cov,num_voters)utilities=[{c:utility_fnc(v_pos,c_pos)forc,c_posinenumerate(cand_positions)}for_,v_posinenumerate(voter_positions)]returnUtilityProfile(utilities)