Exemplo n.º 1
0
def test_keys():
    """ Check a Matching can have its `keys` accessed. """

    matching = Matching()
    assert list(matching.keys()) == []

    matching = Matching(dictionary)
    assert list(matching.keys()) == suitors
Exemplo n.º 2
0
class StableMarriage(BaseGame):
    """ A class for solving instances of the stable marriage problem (SM).

    Parameters
    ----------
    suitors : list of Player
        The suitors in the game. Each suitor must rank all elements in
        ``reviewers``.
    reviewers : list of Player
        The reviewers in the game. Each reviewer must rank all elements in
        ``suitors``.

    Attributes
    ----------
    matching : Matching or None
        Once the game is solved, a matching is available. This uses the suitors
        and reviewers as keys and values, respectively, in a ``Matching``
        object. Initialises as `None`.
    blocking_pairs : list of (Player, Player)
        The suitor-reviewer pairs that both prefer one another to their current
        match. Initialises as ``None``.
    """
    def __init__(self, suitors, reviewers):

        suitors, reviewers = copy.deepcopy([suitors, reviewers])
        self.suitors = suitors
        self.reviewers = reviewers

        super().__init__()
        self._check_inputs()

    @classmethod
    def create_from_dictionaries(cls, suitor_prefs, reviewer_prefs):
        """ Create an instance of SM from two preference dictionaries. """

        suitors, reviewers = _make_players(suitor_prefs, reviewer_prefs)
        game = cls(suitors, reviewers)

        return game

    def solve(self, optimal="suitor"):
        """ Solve the instance of SM using either the suitor- or
        reviewer-oriented Gale-Shapley algorithm. Return the matching. """

        self.matching = Matching(
            stable_marriage(self.suitors, self.reviewers, optimal))
        return self.matching

    def check_stability(self):
        """ Check for the existence of any blocking pairs in the current
        matching, thus determining the stability of the matching. """

        blocking_pairs = []
        for suitor in self.suitors:
            for reviewer in self.reviewers:
                if suitor.prefers(reviewer,
                                  suitor.matching) and reviewer.prefers(
                                      suitor, reviewer.matching):
                    blocking_pairs.append((suitor, reviewer))

        self.blocking_pairs = blocking_pairs
        return not any(blocking_pairs)

    def check_validity(self):
        """ Check whether the current matching is valid. """

        self._check_all_matched()
        self._check_matching_consistent()
        return True

    def _check_all_matched(self):
        """ Check everyone has a match. """

        errors = []
        for player in self.suitors + self.reviewers:
            if player.matching is None:
                errors.append(ValueError(f"{player} is unmatched."))
            if player not in list(self.matching.keys()) + list(
                    self.matching.values()):
                errors.append(
                    ValueError(f"{player} does not appear in matching."))

        if errors:
            raise Exception(*errors)

        return True

    def _check_matching_consistent(self):
        """ Check that the game matching is consistent with the players. """

        errors = []
        matching = self.matching
        for suitor in self.suitors:
            if suitor.matching != matching[suitor]:
                errors.append(
                    ValueError(
                        f"{suitor} is matched to {suitor.matching} but matching"
                        f" says {matching[suitor]}."))

        for reviewer in self.reviewers:
            suitor = [s for s in matching if matching[s] == reviewer][0]
            if reviewer.matching != suitor:
                errors.append(
                    ValueError(
                        f"{reviewer} is matched to {reviewer.matching} but "
                        f"matching says {suitor}."))

        if errors:
            raise Exception(*errors)

        return True

    def _check_inputs(self):
        """ Raise an error if any of the conditions of the game have been
        broken. """

        self._check_num_players()
        for suitor in self.suitors:
            self._check_player_ranks(suitor)
        for reviewer in self.reviewers:
            self._check_player_ranks(reviewer)

    def _check_num_players(self):
        """ Check that the number of suitors and reviewers are equal. """

        if len(self.suitors) != len(self.reviewers):
            raise ValueError(
                "There must be an equal number of suitors and reviewers.")

        return True

    def _check_player_ranks(self, player):
        """ Check that a player has ranked all of the other group. """

        others = self.reviewers if player in self.suitors else self.suitors
        if set(player.prefs) != set(others):
            raise ValueError(
                "Every player must rank each name from the other group. "
                f"{player}: {player.prefs} != {others}")

        return True
Exemplo n.º 3
0
    mV41 = Matching(genJpsis, V41)
    #mV42 = Matching( genJpsis, V42)

    #print "genJpsi : %d // Size of J/psi v1  : %d  // j/psi v2 : %d  // j/psi v3 :  %d  // j/psi v4 :  %d"%(jpsi_idx, len(V1), len(V2),len(V3), len(V4))
    if (len(mV1) > 0):
        profile1.Fill(1, 1)
        for cat in mV1.values():
            diff_1.Fill(cat.pt())
    else:
        profile1.Fill(1, 0)

    #if ( len(mV2) > 0 ) : profile1.Fill(2,1)
    #else : profile1.Fill(2,0)
    if (len(mV3) > 0):
        profile1.Fill(3, 1)
        for idx in mV3.keys():
            diff_3.Fill(genJpsis[idx].pt())
    else:
        profile1.Fill(3, 0)
    if (len(mV40) > 0):
        profile1.Fill(4, 1)
        for idx in mV40.keys():
            diff_40.Fill(genJpsis[idx].pt())
    else:
        profile1.Fill(4, 0)
    if (len(mV41) > 0):
        profile1.Fill(5, 1)
        for idx in mV41.keys():
            diff_41.Fill(genJpsis[idx].pt())
    else:
        profile1.Fill(5, 0)