GithubHelp home page GithubHelp logo

gsa's Introduction

Gale-Shapley Algorithm

References

Start from Bijection

The traditional algorithm describes a way to find a stable bijection between two sets such that no two elements prefer each other to their current partners. We start with two equally sized sets.

apps([a,b,c]).
slots([x,y,z]).

Natural Positions

prefs(a,[x,y,z]).
prefs(b,[y,x,z]).
prefs(c,[z,y,x]).
prefs(x,[a,b,c]).
prefs(y,[b,a,c]).
prefs(z,[c,b,a]).

The matching outcome should be [a,x], [b,y], [c,z] regardless of order of proposals.

If [x,y,z] are proposers:

?- gsa(slot,R).
--------------------------------------
Proposers with preferences: [[x,[a,b,c]],[y,[b,a,c]],[z,[c,b,a]]]
Accepters: [[a,om],[b,om],[c,om]]
Accepter preferences: [[x,y,z],[y,x,z],[z,y,x]]
--------------------------------------
x is proposing to a
The accumulator state is: []
--------------------------------------
New accumulator state is: [[a,x]]
New unpaired state is: [[b,om],[c,om]]
--------------------------------------
y is proposing to b
The accumulator state is: [[a,x]]
--------------------------------------
New accumulator state is: [[a,x],[b,y]]
New unpaired state is: [[c,om]]
--------------------------------------
z is proposing to c
The accumulator state is: [[a,x],[b,y]]
--------------------------------------
New accumulator state is: [[a,x],[b,y],[c,z]]
New unpaired state is: []
R = [[a, x], [b, y], [c, z]] .

If [a,b,c] are proposers:

?- gsa(app,R).
--------------------------------------
Proposers with preferences: [[a,[x,y,z]],[b,[y,x,z]],[c,[z,y,x]]]
Accepters: [[x,om],[y,om],[z,om]]
Accepter preferences: [[a,b,c],[b,a,c],[c,b,a]]
--------------------------------------
a is proposing to x
The accumulator state is: []
--------------------------------------
New accumulator state is: [[x,a]]
New unpaired state is: [[y,om],[z,om]]
--------------------------------------
b is proposing to y
The accumulator state is: [[x,a]]
--------------------------------------
New accumulator state is: [[x,a],[y,b]]
New unpaired state is: [[z,om]]
--------------------------------------
c is proposing to z
The accumulator state is: [[x,a],[y,b]]
--------------------------------------
New accumulator state is: [[x,a],[y,b],[z,c]]
New unpaired state is: []
R = [[x, a], [y, b], [z, c]] .

Stability predicate confirms no other stable pairing for the given inputs.

?- is_stable([[x, a], [y, b], [z, c]]).
true .
?- is_stable([[x, c], [y, b], [z, a]]).
false.
?- is_stable([[x, b], [y, a], [z, c]]).
false.
?- is_stable([[x, b], [y, c], [z, a]]).
false.
?- is_stable([[x, a], [y, c], [z, b]]).
false.

Stable Matching Problem

More formally, the input of the stable matching problem is two sets of equal length. Traditionally, n men and n women. A matching between the sets is stable when there does not exist any pair (A,B) which both prefer each other to their current partner under the matching. When there is a bijection between input sets, a stable matching always exists and Gale-Shapley yields an algorithmic solution.

Change b preferences to [x,y,z] changes nothing.

prefs(a,[x,y,z]).
prefs(b,[x,y,z]).
prefs(c,[z,y,x]).
prefs(x,[a,b,c]).
prefs(y,[b,a,c]).
prefs(z,[c,b,a]).

The matching outcome is still [a,x], [b,y], [c,z] regardless of order of proposals. Stability is also unchanged:

?- is_stable([[a, x], [b, y], [c, z]]).
true .
?- is_stable([[a, y], [b, x], [c, z]]).
false.
?- is_stable([[a, y], [b, z], [c, x]]).
false.
?- is_stable([[a, z], [b, x], [c, y]]).
false.

Why? Each proposer proposes to their highest remaining preference, in order, until they are paired or no preferences remains (in the current implementation, unpairable proposers are tossed, but they are also an impossibility if there is a bijection between proposer and accepter sets).

?- gsa(app,R).
R = [[x, a], [y, b], [z, c]] .

The algorithm starts with a proposing to its top choice x. Then b proposes to its top choice x, but x prefers a to b so x rejects b's proposal.

apps([a,b,c]).
slots([x,y,z]).
prefs(a,[x,y,z]).
prefs(b,[x,y,z]).
prefs(c,[z,y,x]).
prefs(x,[a,b,c]).
prefs(y,[b,a,c]).
prefs(z,[c,b,a]).

The output for the query writes the relevant proposal information:

?- gsa(app,R).
--------------------------------------
Proposers with preferences: [[a,[x,y,z]],[b,[x,y,z]],[c,[z,y,x]]]
Accepters: [[x,om],[y,om],[z,om]]
Accepter preferences: [[a,b,c],[b,a,c],[c,b,a]]
--------------------------------------
a is proposing to x
The accumulator state is: []
--------------------------------------
New accumulator state is: [[x,a]]
New unpaired state is: [[y,om],[z,om]]
--------------------------------------
b is proposing to x
The accumulator state is: [[x,a]]
--------------------------------------
x rejects proposal from b
--------------------------------------
b is proposing to y
The accumulator state is: [[x,a]]
--------------------------------------
New accumulator state is: [[x,a],[y,b]]
New unpaired state is: [[z,om]]
--------------------------------------
c is proposing to z
The accumulator state is: [[x,a],[y,b]]
--------------------------------------
New accumulator state is: [[x,a],[y,b],[z,c]]
New unpaired state is: []
R = [[x, a], [y, b], [z, c]] .

If we change the proposer set, nothing changes because a proposes to x and, even though b prefers x to y, b never gets a proposal from x, so they end up settling for y.

?- gsa(slot,R).
--------------------------------------
Proposers with preferences: [[x,[a,b,c]],[y,[b,a,c]],[z,[c,b,a]]]
Accepters: [[a,om],[b,om],[c,om]]
Accepter preferences: [[x,y,z],[x,y,z],[z,y,x]]
--------------------------------------
x is proposing to a
The accumulator state is: []
--------------------------------------
New accumulator state is: [[a,x]]
New unpaired state is: [[b,om],[c,om]]
--------------------------------------
y is proposing to b
The accumulator state is: [[a,x]]
--------------------------------------
New accumulator state is: [[a,x],[b,y]]
New unpaired state is: [[c,om]]
--------------------------------------
z is proposing to c
The accumulator state is: [[a,x],[b,y]]
--------------------------------------
New accumulator state is: [[a,x],[b,y],[c,z]]
New unpaired state is: []
R = [[a, x], [b, y], [c, z]] .

Does anything change if we also make c's preferences the same as a and b?

apps([a,b,c]).
slots([x,y,z]).
prefs(a,[x,y,z]).
prefs(b,[x,y,z]).
prefs(c,[x,y,z]).
prefs(x,[a,b,c]).
prefs(y,[b,a,c]).
prefs(z,[c,b,a]).

Nothing changes because all elements of app propose in order.

?- gsa(app,R).
--------------------------------------
Proposers with preferences: [[a,[x,y,z]],[b,[x,y,z]],[c,[x,y,z]]]
Accepters: [[x,om],[y,om],[z,om]]
Accepter preferences: [[a,b,c],[b,a,c],[c,b,a]]
--------------------------------------
a is proposing to x
The accumulator state is: []
--------------------------------------
New accumulator state is: [[x,a]]
New unpaired state is: [[y,om],[z,om]]
--------------------------------------
b is proposing to x
The accumulator state is: [[x,a]]
--------------------------------------
x rejects proposal from b
--------------------------------------
b is proposing to y
The accumulator state is: [[x,a]]
--------------------------------------
New accumulator state is: [[x,a],[y,b]]
New unpaired state is: [[z,om]]
--------------------------------------
c is proposing to x
The accumulator state is: [[x,a],[y,b]]
--------------------------------------
x rejects proposal from c
--------------------------------------
c is proposing to y
The accumulator state is: [[x,a],[y,b]]
--------------------------------------
y rejects proposal from c
--------------------------------------
c is proposing to z
The accumulator state is: [[x,a],[y,b]]
--------------------------------------
New accumulator state is: [[x,a],[y,b],[z,c]]
New unpaired state is: []
R = [[x, a], [y, b], [z, c]] .

The slot proposal matching sequence:

?- gsa(slot,R).
--------------------------------------
Proposers with preferences: [[x,[a,b,c]],[y,[b,a,c]],[z,[c,b,a]]]
Accepters: [[a,om],[b,om],[c,om]]
Accepter preferences: [[x,y,z],[x,y,z],[x,y,z]]
--------------------------------------
x is proposing to a
The accumulator state is: []
--------------------------------------
New accumulator state is: [[a,x]]
New unpaired state is: [[b,om],[c,om]]
--------------------------------------
y is proposing to b
The accumulator state is: [[a,x]]
--------------------------------------
New accumulator state is: [[a,x],[b,y]]
New unpaired state is: [[c,om]]
--------------------------------------
z is proposing to c
The accumulator state is: [[a,x],[b,y]]
--------------------------------------
New accumulator state is: [[a,x],[b,y],[c,z]]
New unpaired state is: []
R = [[a, x], [b, y], [c, z]] .

What changes must be made to the preferences to change the output of the gale-shapley algorithm? There must be two pairs in which members of the opposite set prefer each other to their current paired partner.

For example, if we configure the preferences so that a prefers y and y prefers a, then output changes regardless of the proposal order.

?- gsa(app,R).
--------------------------------------
Proposers with preferences: [[a,[y,x,z]],[b,[x,y,z]],[c,[x,y,z]]]
Accepters: [[x,om],[y,om],[z,om]]
Accepter preferences: [[a,b,c],[a,b,c],[c,b,a]]
--------------------------------------
a is proposing to y
The accumulator state is: []
--------------------------------------
New accumulator state is: [[y,a]]
New unpaired state is: [[x,om],[z,om]]
--------------------------------------
b is proposing to x
The accumulator state is: [[y,a]]
--------------------------------------
New accumulator state is: [[y,a],[x,b]]
New unpaired state is: [[z,om]]
--------------------------------------
c is proposing to x
The accumulator state is: [[y,a],[x,b]]
--------------------------------------
x rejects proposal from c
--------------------------------------
c is proposing to y
The accumulator state is: [[y,a],[x,b]]
--------------------------------------
y rejects proposal from c
--------------------------------------
c is proposing to z
The accumulator state is: [[y,a],[x,b]]
--------------------------------------
New accumulator state is: [[y,a],[x,b],[z,c]]
New unpaired state is: []
R = [[y, a], [x, b], [z, c]] .

?- gsa(slot,R).
--------------------------------------
Proposers with preferences: [[x,[a,b,c]],[y,[a,b,c]],[z,[c,b,a]]]
Accepters: [[a,om],[b,om],[c,om]]
Accepter preferences: [[y,x,z],[x,y,z],[x,y,z]]
--------------------------------------
x is proposing to a
The accumulator state is: []
--------------------------------------
New accumulator state is: [[a,x]]
New unpaired state is: [[b,om],[c,om]]
--------------------------------------
y is proposing to a
The accumulator state is: [[a,x]]
--------------------------------------
a accepts proposal from y and displaces x
--------------------------------------
x is proposing to b
The accumulator state is: [[a,y]]
--------------------------------------
New accumulator state is: [[a,y],[b,x]]
New unpaired state is: [[c,om]]
--------------------------------------
z is proposing to c
The accumulator state is: [[a,y],[b,x]]
--------------------------------------
New accumulator state is: [[a,y],[b,x],[c,z]]
New unpaired state is: []
R = [[a, y], [b, x], [c, z]] .

The stability predicate confirms the gsa algorithm output:

?- is_stable([[a, y], [b, x], [c, z]]).
true .
?- is_stable([[a, x], [b, y], [c, z]]).
false.

Properties

gsa always produces a stable bijection between two sets of the same size. Moreover, the assignment is always best for the proposer set.

Proof By Contradiction: Assume there exist some gsa output which is unstable => (by defn of stability) there exists two member of the opposite set that prefer each other to their current partner. We can assign the two pairs [A,B],[C,D] and, wlog, A prefers D to B and D prefers A to C. If the proposing set is [A,C], then A would propose to D before B, and, if C proposes to D while D is with A, D would reject because D prefers A to C. Therefore, it is impossible to get [A,B],[C,D] from gsa if [A,C] are the proposers. Similarly, if [B,D] are the proposers, then B proposes to A and A accepts, but D proposes next to A and A would displace B to accept D so [A,B],[C,D] is an impossible outcome of gsa with [B,D] as proposers. Therefore, no unstable pair can exist in the gsa output because we have fully explored the gsa solution space by alternating the proposer set.

gsa's People

Contributors

4meta5 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.