
As it turns out, thanks to two men, David Gale and Lloyd Shapley, we can use maths to cure a global pandemic that has been plaguing humanity for far too long. Thatās right - we can cure infidelity. āWait, no, thatās impossible,ā you say. āCan we really reduce human desire and instinct to parameters of a finite and definite algorithm?ā Probably not, but we can try.
After watching Numberphileās video on the Stable Marriage problem, I was inspired to research similar matching problems, so this will hopefully be one in a series of posts. But first, Iāll explain the Stable Marriage problem and discuss the algorithm that solves it.
The Stable Marriage problem consists of two equally sized sets ā for simplicity, we will say one set is a group of men, whilst the other is a group of women (yes, weāll have to look past heteronormativity for this post). The aforementioned parameters of āhuman desire and instinctā are reduced to a list of preferences. Each man has a list of preferences ranking each woman and vice versa. In order to solve the Stable Marriage problem, a stable matching must be found, where everyone is married and no two people prefer each other over their spouse, reducing the likelihood of any cheating to occur to zero.
In 1962, mathematicians David Gale and Lloyd Shapley proved this problem can always be solved and provided the following algorithm.
In order to compensate for the heteronormativity, letās assume that the women are proposing to the men. The algorithm consists of iterations where any women who are still single propose to the highest ranking man on their list to whom they have not already proposed. The men then accept the woman they prefer the most out of the proposals they received and reject the other proposals, including their current fiancĆ©e, if they have one.
This can best be explained with an example. Letās first define our to-be-weds and their preferences:
# Dictionaries for set of women and men where key represents a person,
# and value holds their list of preferences from least preferred to most.
women = {'Mimi': ['Winston', 'Edward', 'Roger', 'Jake'],
'Julia': ['Edward', 'Jake', 'Roger', 'Winston'],
'Amy': ['Winston', 'Roger', 'Edward', 'Jake'],
'Jane': ['Jake', 'Winston', 'Edward', 'Roger']}
men = {'Jake': ['Julia', 'Jane', 'Mimi', 'Amy'],
'Winston': ['Amy', 'Mimi', 'Julia', 'Jane'],
'Edward': ['Mimi', 'Julia', 'Jane', 'Amy'],
'Roger': ['Jane', 'Amy', 'Mimi', 'Julia']}
The following diagrams have the order of preference swapped around (that is, they go from most preferred to least). A little annoying, I know, but itās just nicer for the diagrams to go from most preferred to least, and, for the sake of reducing runtime, the dictionaries for our implementation to go from least preferred to most. Anyway, with these sets of men and women, the algorithm would play out as follows:

All of the women propose to their top preference. Jake receives two proposals, Winston and Roger both receive one and Edward receives zero proposals. Poor Edward.

Winston and Roger accept their only proposals. Jake has two, so he accepts Amy and rejects Mimi because Amy is ranked higher on his list. Mimi is now left single, so she proposes to Roger, the next highest person on her list.

Mimi is ranked higher on Rogerās list than Jane, his current fiancĆ©e. So he rejects Jane and accepts Mimi. Now Jane is left single, so she proposes to Edward.

Edward has had no proposals thus far, so he accepts Jane. All of the couples have been matched and the algorithm stops. Congratulations Mimi and Roger, Julia and Winston, Amy and Jake, and Jane and Edward! Thanks to Gale and Shapley, you have all avoided disastrous marriages. You are all very welcome.

Here is how the algorithm can be implemented in Python:
def stable_match(proposers, proposees):
"""
Use the Gale-Shapley algorithm to find a stable matching between two sets.
:param proposers: dict where key represents a proposer, and value holds their list of preferences
(least preferred to most)
:param proposees: dict where key represents a proposee, and value holds their list of preferences
(least preferred to most)
:return: dict where key, value pairs correspond to a matched couple
"""
proposers = copy.deepcopy(proposers)
proposees = copy.deepcopy(proposees)
proposer_queue = list(proposers.keys())
couples = {}
# Whilst there is a proposer yet to be engaged...
while len(proposer_queue):
proposer = proposer_queue.pop(0)
proposee = proposers[proposer].pop()
print("%s proposed to %s." % (proposer, proposee))
if proposee not in couples:
# The proposee is single!
couples[proposee] = proposer
print("%s accepted %s's proposal." % (proposee, proposer))
else:
# The proposee is already engaged
fiance = couples[proposee]
if proposees[proposee].index(proposer) > proposees[proposee].index(fiance):
# The proposee prefers the proposer to their fiance
couples[proposee] = proposer
proposer_queue.append(fiance) # Fiance is now single :(
print("%s accepted %s's proposal and left %s." % (proposee, proposer, fiance))
else:
# The proposer is still single :(
proposer_queue.append(proposer)
print("%s rejected %s because they are already engaged to %s." %
(proposee, proposer, fiance))
# We found our stable matches!
return couples
We can call our stable_match function and pass in our dictionaries that we declared earlier:
>>> print(stable_match(women, men))
Mimi proposed to Jake.
Jake accepted Mimi's proposal.
Julia proposed to Winston.
Winston accepted Julia's proposal.
Amy proposed to Jake.
Jake accepted Amy's proposal and left Mimi.
Jane proposed to Roger.
Roger accepted Jane's proposal.
Mimi proposed to Roger.
Roger accepted Mimi's proposal and left Jane.
Jane proposed to Edward.
Edward accepted Jane's proposal.
{'Jake': 'Amy', 'Winston': 'Julia', 'Roger': 'Mimi', 'Edward': 'Jane'}
Since infidelity is a worldwide phenomenon that does not discriminate, it would be useful to know how well this algorithm scales as the number of men and women being considered increases.
Letās consider what would happen in the worst case. We know that a woman can make at most
If we were to write this in Big O notation, which is to remove any lower order terms and constants, we would get that the time complexity of the algorithm is
Unfortunately (but pretty interestingly), this algorithm is biased towards one of the two sets - the proposers, who are, in this case, the women. We can see that a woman cannot do any better than the man to whom they are engaged because any man that is ranked above who she ended up with rejected her proposal whilst the algorithm was running. In turn, this also proves that a man cannot do any worse than the woman to whom they are engaged.
Real-life applications? You mean⦠like, solving infidelity and providing the human race with Stable Marriages? Sure, if everyone was straight, monogamous, could identify as one of two categories, and we could get everyone to submit a list of preferences ranking the other half of the population.
So, the Gale-Shapley algorithm to solve the Stable Marriage problem may not be so useful for actually providing stable marriages in the real world. However, the algorithm often plays a role in solving many other important problems, such as assigning graduating med students to hospitals for residency, and assigning users to servers in CDNs.
Real-world impracticalities aside, let me know if you would let an algorithm determine who you get stuck with for the rest of your life. And if you would, why?