def test_check_stability(): """Test that HospitalResident can recognise whether a matching is stable or not.""" residents = [Resident("A"), Resident("B"), Resident("C")] hospitals = [Hospital("X", 2), Hospital("Y", 2)] (a, b, c), (x, y) = residents, hospitals a.set_prefs([x, y]) b.set_prefs([y]) c.set_prefs([y, x]) x.set_prefs([c, a]) y.set_prefs([a, b, c]) game = HospitalResident(residents, hospitals) matching = game.solve() assert game.check_stability() (a, b, c), (x, y) = game.residents, game.hospitals matching[x] = [c] matching[y] = [a, b] assert not game.check_stability()
def multiples( draw, host_names_from=text(), player_names_from=text(), min_hosts=2, max_hosts=5, min_players=10, max_players=20, ): """A custom strategy for generating a matching for `MultipleMatching` out of `Hospital` and lists of `Player` instances.""" num_hosts = draw(integers(min_value=min_hosts, max_value=max_hosts)) num_players = draw(integers(min_value=min_players, max_value=max_players)) hosts = [ Hospital(draw(host_names_from), max_players) for _ in range(num_hosts) ] players = [Player(draw(player_names_from)) for _ in range(num_players)] dictionary = {} for host in hosts: matches = draw(lists(sampled_from(players), min_size=0, unique=True)) dictionary[host] = matches return dictionary
def test_check_for_unacceptable_matches_residents(resident_names, hospital_names, capacities, seed, clean): """Test that HospitalResident recognises a valid matching requires each resident to have a preference of their match, if they have one.""" _, _, game = make_game(resident_names, hospital_names, capacities, seed, clean) resident = game.residents[0] hospital = Hospital(name="foo", capacity=1) resident.matching = hospital issues = game._check_for_unacceptable_matches("residents") assert len(issues) == 1 issue = issues[0] assert issue.startswith(resident.name) assert issue.endswith(f"{resident.prefs}.") assert hospital.name in issue with pytest.raises(MatchingError) as e: game.check_validity() error = e.unacceptable_matches[0] assert issue == error
def test_init(name, capacity): """ Make an instance of Hospital and check their attributes are correct. """ hospital = Hospital(name, capacity) assert hospital.name == name assert hospital.capacity == capacity assert hospital.prefs is None assert hospital.pref_names is None assert hospital.matching == []
def test_check_if_match_is_unacceptable(name, capacity, pref_names): """ Check that a hospital can verify the acceptability of its matches. """ hospital = Hospital(name, capacity) others = [Resident(other) for other in pref_names] assert hospital.check_if_match_is_unacceptable() == [] hospital.set_prefs(others[:-1]) hospital.matching = [others[-1]] message = hospital.not_in_preferences_message(others[-1]) assert hospital.check_if_match_is_unacceptable() == [message]
def test_get_successors(name, capacity, pref_names): """Check that a hospital can get the successors to its worst current match.""" hospital = Hospital(name, capacity) others = [Resident(other) for other in pref_names] hospital.set_prefs(others) hospital.matching = [others[0]] assert hospital.get_successors() == others[1:] hospital.matching = others assert hospital.get_successors() == []
def test_match(name, capacity, pref_names): """ Check that a hospital can match to a player correctly. """ hospital = Hospital(name, capacity) others = [Resident(other) for other in pref_names] hospital.set_prefs(others) for i, other in enumerate(others[:-1]): hospital.match(other) assert hospital.matching == others[:i + 1] hospital.match(others[-1]) assert hospital.matching == others
def players(draw, **kwargs): """ A custom strategy for making a set of residents and hospitals. """ resident_prefs, hospital_prefs, capacities = draw(connections(**kwargs)) residents = [Resident(name) for name in resident_prefs] hospitals = [Hospital(name, cap) for name, cap in capacities.items()] residents = _get_preferences(residents, hospitals, resident_prefs) hospitals = _get_preferences(hospitals, residents, hospital_prefs) return residents, hospitals
def test_get_favourite(name, capacity, pref_names): """ Check the correct player is returned as the hospital's favourite. """ hospital = Hospital(name, capacity) others = [Resident(other) for other in pref_names] hospital.set_prefs(others) assert hospital.get_favourite() == others[0] hospital.matching = others assert hospital.get_favourite() is None
def test_check_if_oversubscribed(name, capacity, pref_names): """ Check that a hospital can verify whether it is oversubscribed. """ hospital = Hospital(name, capacity) others = [Resident(other) for other in pref_names] assert hospital.check_if_oversubscribed() is False hospital.matching = others hospital.capacity = 0 message = hospital.oversubscribed_message() assert hospital.check_if_oversubscribed() == message
def _make_instances(resident_prefs, hospital_prefs, capacities): """ Create ``Player`` (resident) and ``Hospital`` instances for the names in each dictionary. """ resident_dict, hospital_dict = {}, {} for resident_name in resident_prefs: resident = Resident(name=resident_name) resident_dict[resident_name] = resident for hospital_name in hospital_prefs: capacity = capacities[hospital_name] hospital = Hospital(name=hospital_name, capacity=capacity) hospital_dict[hospital_name] = hospital return resident_dict, hospital_dict
def test_unmatch(name, capacity, pref_names): """ Check that a hospital can unmatch from a player correctly. """ hospital = Hospital(name, capacity) others = [Resident(other) for other in pref_names] hospital.matching = others for i, other in enumerate(others[:-1]): hospital.unmatch(other) assert hospital.matching == others[i + 1:] hospital.unmatch(others[-1]) assert hospital.matching == []
def test_get_worst_match(name, capacity, pref_names): """ Check that a hospital can return its worst match. """ hospital = Hospital(name, capacity) others = [Resident(other) for other in pref_names] hospital.matching = [others[0]] assert hospital.get_worst_match() == others[0] hospital.matching = others assert hospital.get_worst_match() == others[-1]
def make_players(resident_names, hospital_names, capacities): """ Given some names and capacities, make a set of players for HR. """ residents = [Resident(name) for name in resident_names] hospitals = [ Hospital(name, capacity) for name, capacity in zip(hospital_names, capacities) ] possible_prefs = get_possible_prefs(hospitals) logged_prefs = {} for resident in residents: prefs = possible_prefs[np.random.randint(len(possible_prefs))] resident.set_prefs(prefs) for hospital in prefs: try: logged_prefs[hospital] += [resident] except KeyError: logged_prefs[hospital] = [resident] for hospital, resids in logged_prefs.items(): hospital.set_prefs(np.random.permutation(resids).tolist()) return residents, [hosp for hosp in hospitals if hosp.prefs is not None]