-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgs.py
156 lines (146 loc) · 4.45 KB
/
gs.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#Matteo Mantese, Matthew King
#Referenced starter code and book.
def gs(men, women, pref):
"""
Gale-shapley algorithm, modified to exclude unacceptable matches
Inputs: men (list of men's names)
women (list of women's names)
pref (dictionary of preferences mapping names to list of preferred names in sorted order)
blocked (list of (man,woman) tuples that are unacceptable matches)
Output: dictionary of stable matches
"""
# preprocessing
## build the rank dictionary
rank={}
for w in women:
rank[w] = {}
i = 1
for m in pref[w]:
rank[w][m]=i
i+=1
## create a "pointer" to the next woman to propose
prefptr = {}
for m in men:
prefptr[m] = 0
freemen = set(men) #initially all men and women are free
numpartners = len(men)
S = {} #build dictionary to store engagements
#run the algorithm
while freemen:
m = freemen.pop()
#get the highest ranked woman that has not yet been proposed to
w = pref[m][prefptr[m]]
prefptr[m]+=1
if w not in S: S[w] = m
else:
mprime = S[w]
if rank[w][m] < rank[w][mprime]:
S[w] = m
freemen.add(mprime)
else:
freemen.add(m)
return S
def gs_block(men, women, pref, blocked):
"""
Gale-shapley algorithm, modified to exclude unacceptable matches
Inputs: men (list of men's names)
women (list of women's names)
pref (dictionary of preferences mapping names to list of preferred names in sorted order)
blocked (list of (man,woman) tuples that are unacceptable matches)
Output: dictionary of stable matches
"""
rank = {}
for w in women:
rank[w] = {}
i = 1
for m in pref[w]:
if (m, w) in blocked:
rank[w][m] = 4
else:
rank[w][m] = i
i+=1
prefptr = {m:0 for m in men}
numpartners = len(men)
freemen = set(men)
S = {}
while freemen:
m = freemen.pop()
if prefptr[m] >= numpartners:
continue
w = pref[m][prefptr[m]]
prefptr[m]+=1
if w not in S:
if rank[w][m] == 4:
freemen.add(m)
else:
S[w] = m
else:
mPrime = S[w]
if rank[w][m] < rank[w][mPrime]:
S[w] = m
freemen.add(mPrime)
else:
freemen.add(m)
return S
def gs_tie(men, women, preftie):
"""
Gale-shapley algorithm, modified to exclude unacceptable matches
Inputs: men (list of men's names)
women (list of women's names)
pref (dictionary of preferences mapping names to list of sets of preferred names in sorted order)
Output: dictionary of stable matches
"""
rank = {}
for w in women:
i = 1
rank[w] = {}
for st in preftie[w]:
for m in st:
rank[w][m] = i
i += 1
for m in men:
preftie[m].reverse()
freemen = set(men)
S = {}
while freemen:
m = freemen.pop()
st = preftie[m].pop()
w = st.pop()
if st:
preftie[m].append(st)
if w not in S:
S[w] = m
else:
mPrime = S[w]
if rank[w][m] >= rank[w][mPrime]:
S[w] = m
freemen.add(mPrime)
else:
freemen.add(m)
return S
if __name__=="__main__":
#input data
themen = ['xavier','yancey','zeus']
thewomen = ['amy','bertha','clare']
thepref = {'xavier': ['amy','bertha','clare'],
'yancey': ['bertha','amy','clare'],
'zeus': ['amy','bertha','clare'],
'amy': ['yancey','xavier','zeus'],
'bertha': ['xavier','yancey','zeus'],
'clare': ['xavier','yancey','zeus']
}
thepreftie = {'xavier': [{'bertha'},{'amy'},{'clare'}],
'yancey': [{'amy','bertha'},{'clare'}],
'zeus': [{'amy'},{'bertha','clare'}],
'amy': [{'zeus','xavier','yancey'}],
'bertha': [{'zeus'},{'xavier'},{'yancey'},],
'clare': [{'xavier','yancey'},{'zeus'}]
}
blocked = {('xavier','clare'),('zeus','clare'),('zeus','amy')}
#eng
match = gs(themen,thewomen,thepref)
print match
match_block = gs_block(themen,thewomen,thepref,blocked)
print match_block
match_tie = gs_tie(themen,thewomen,thepreftie)
print match_tie