Skip to content

Commit

Permalink
Move unmatching inside second_phase of SR (#125)
Browse files Browse the repository at this point in the history
* Move unmatching inside `second_phase`

This was causing simple examples to fail because the second phase of the
algorithm never kicked in. By moving the unmatching, this is avoided,
and is fine because of the corollaries in Irving's paper.

* Add example tests from #124

* Checkout CI file from dev.
  • Loading branch information
daffidwilde authored Oct 15, 2020
1 parent 77e63cb commit 581ba05
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 5 deletions.
4 changes: 3 additions & 1 deletion src/matching/games/stable_roommates.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ def forget_successors(players):
for player in players:
if player.matching:
successors = player.get_successors()
player.unmatch()
for successor in successors:
forget_pair(player, successor)

Expand Down Expand Up @@ -178,6 +177,9 @@ def second_phase(players):
(rotations) are located and removed from the game. These reduced preference
lists form a matching."""

for player in players:
player.unmatch()

player_with_second_preference = next(p for p in players if len(p.prefs) > 1)
while True:
cycle = locate_all_or_nothing_cycle(player_with_second_preference)
Expand Down
13 changes: 10 additions & 3 deletions tests/stable_roommates/test_algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ def test_first_phase(player_names, seed):
players = first_phase(players)

for player in players:
assert player.matching is None
if player.matching is None:
assert player.prefs == []
else:
assert player.matching in player.prefs

assert {p.name for p in player.prefs}.issubset(player.pref_names)


Expand Down Expand Up @@ -60,7 +64,10 @@ def test_stable_roommates(player_names, seed):
players = make_players(player_names, seed)
matching = stable_roommates(players)

for player, other in matching.items():
if other is not None:
if None in matching.values():
assert all(val is None for val in matching.values())

else:
for player, other in matching.items():
assert player.prefs == [other]
assert other.matching == player
40 changes: 39 additions & 1 deletion tests/stable_roommates/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def test_original_paper():
assert matching == {a: f, b: c, c: b, d: e, e: d, f: a}


def test_example_in_issue():
def test_example_in_issue_64():
"""Verify that the matching found is consistent with the example provided
in #64."""

Expand All @@ -48,3 +48,41 @@ def test_example_in_issue():
kelly: peter,
sam: charlie,
}


def test_examples_in_issue_124():
"""Verify that the matching is consistent with the examples provided in
#124."""

a, b, c, d = players = [Player(name) for name in ("a", "b", "c", "d")]

a.set_prefs([b, c, d])
b.set_prefs([a, c, d])
c.set_prefs([a, b, d])
d.set_prefs([a, b, c])

matching = stable_roommates(players)
assert matching == {a: b, b: a, c: d, d: c}

for player in players:
player.unmatch()

a.set_prefs([b, c, d])
b.set_prefs([a, c, d])
c.set_prefs([d, b, a])
d.set_prefs([c, b, a])

matching = stable_roommates(players)
assert matching == {a: b, b: a, c: d, d: c}


def test_trivial_case():
""" Verify that a matching is given when there are only two players. """

p1, p2 = players = [Player(1), Player(2)]

p1.set_prefs([p2])
p2.set_prefs([p1])

matching = stable_roommates(players)
assert matching == {p1: p2, p2: p1}

0 comments on commit 581ba05

Please sign in to comment.