Summary
This short post covers a Python implementation of the Gale-Shapely algorithm for the Stable Marriage Problem (SMP). Stable matching is a well-studied problem in multiple fields. It has applications in nearly any two-sided market scenario.
Code Snippets
Preference Generator
Below is a Python function to generate a random set of preferences for two classes. Those preferences are then subsequently used by Gale-Shapley to determine a stable matching.
def generate_prefs(class1, class2):
if len(class1) != len(class2):
raise Exception("Invalid input: unequal list sizes")
prefs = {}
for item in class1:
random.shuffle(class2)
prefs[item] = class2.copy()
for item in class2:
random.shuffle(class1)
prefs[item] = class1.copy()
return dict(sorted(prefs.items()))
Gale-Shapley
def gale_shapley(prefs, proposers):
matches = []
while len(proposers) > 0: #terminating condition - all proposers are matched
proposer = proposers.pop(0) #Each round - proposer is popped from the free list
proposee = prefs[proposer].pop(0) #Each round - the proposer's top preference is popped
matchLen= len(matches)
found = False
for index in range(matchLen):
match = matches[index]
if proposee in match: #proposee is already matched
found = True
temp = match.copy()
temp.remove(proposee)
matchee = temp.pop()
if prefs[proposee].index(proposer) < prefs[proposee].index(matchee): #proposer is a higher preference
matches.remove(match) #remove old match
matches.append([proposer, proposee]) #create new match with proposer
proposers.append(matchee) #add the previous proposer to the free list of proposers
else:
proposers.append(proposer) #proposer wasn't a higher prefence, so gets put back on free list
break
else:
continue
if not found: #proposee was not previously matched so is automatically matched to proposer
matches.append([proposer, proposee])
else:
continue
return matches
Output
Below is a sample run with two three-member classes: (a1, a2, a3) and (b1, b2, b3).
Preferences
{'a1': ['b2', 'b3', 'b1'],
'a2': ['b3', 'b2', 'b1'],
'a3': ['b1', 'b2', 'b3'],
'b1': ['a2', 'a1', 'a3'],
'b2': ['a1', 'a3', 'a2'],
'b3': ['a3', 'a1', 'a2']}
Matches
[['a3', 'b1'], ['a1', 'b2'], ['a2', 'b3']]
Source
Copyright ©1993-2024 Joey E Whelan, All rights reserved.