-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathprofiles.py
75 lines (64 loc) · 2.81 KB
/
profiles.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# Preferences profiles for perpetual voting rules
# Author: Martin Lackner
import copy
import numpy.random as random
from scipy.spatial.distance import euclidean
from future.utils import iteritems
import collections
# approval profile
class ApprovalProfile(object):
def __init__(self, voters, cands, approval_sets):
self.voters = voters
if isinstance(approval_sets, collections.Mapping):
self.approval_sets = approval_sets
elif isinstance(approval_sets, list):
assert len(approval_sets) == len(voters)
self.approval_sets = {}
for i in range(len(voters)):
self.approval_sets[voters[i]] = approval_sets[i]
else:
raise Exception("type of approval_sets neither dict nor list")
self.cands = cands
for v, appr in iteritems(self.approval_sets):
for c in appr:
if v not in voters:
raise Exception(str(v) + " is not a valid voter; "
+ "voters are " + str(voters)+".")
if c not in cands:
raise Exception(str(c) + " is not a valid candidate; "
+ "candidates are " + str(cands) + ".")
def __str__(self):
return ("Profile with %d votes and %d candidates: "
% (len(self.voters), len(self.cands))
+ ', '.join(map(str, self.approval_sets.values())))
def __deepcopy__(self, memodict=None):
if memodict is None:
memodict = {}
voters = list(self.voters)
approvals_sets = copy.deepcopy(self.approval_sets)
cands = list(self.cands)
return ApprovalProfile(voters, cands, approvals_sets)
def has_empty_sets(self):
for appr in self.approval_sets.values():
if len(appr) == 0:
return True
return False
# uniformly random profile:
# voters' approval sets have a size given by dict approval_set_sizes
def uniformly_random_profile(voters, cands, approval_set_sizes):
approval_sets = {}
for v in voters:
approval_sets[v] = set(random.choice(cands, approval_set_sizes[v],
replace=False))
return ApprovalProfile(voters, cands, approval_sets)
# create approval profile from 2d coordinates (Euclidean distance)
def approvalprofile_from_2d_euclidean(voters, cands, voter_points,
cand_points, threshold):
approval_sets = {}
for v in voters:
distances = {c: euclidean(voter_points[v], cand_points[c])
for c in cands}
mindist = min(distances.values())
approval_sets[v] = [c for c in cands
if distances[c] <= mindist * threshold]
return ApprovalProfile(voters, cands, approval_sets)