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.