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

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

    matching = Matching(dictionary)
    assert list(matching.values()) == reviewers
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
class StableRoommates(BaseGame):
    """A class for solving instances of the stable roommates problem (SR).

    Parameters
    ----------
    players : list of Player
        The players in the game. Each must rank all other players.

    Attributes
    ----------
    matching : Matching or None
        Once the game is solved, a matching is available. This uses the players
        as keys and values in a ``Matching`` object. Initialises as ``None``.
    """
    def __init__(self, players):

        players = copy.deepcopy(players)
        self.players = players

        super().__init__()
        self.check_inputs()

    @classmethod
    def create_from_dictionary(cls, player_prefs):
        """ Create an instance of SR from a preference dictionary. """

        players = _make_players(player_prefs)
        game = cls(players)

        return game

    def solve(self):
        """Solve the instance of SR using Irving's algorithm. Return the
        matching."""

        self.matching = Matching(stable_roommates(self.players))
        return self.matching

    def check_validity(self):
        """Check whether the current matching is valid. Raise `MatchingError`
        detailing the issues if not."""

        issues = []
        for player in self.players:
            issue = player.check_if_match_is_unacceptable(unmatched_okay=False)
            if issue:
                issues.append(issue)

        if issues:
            raise MatchingError(unmatched_players=issues)

        return True

    def check_stability(self):
        """Check for the existence of any blocking pairs in the current
        matching. Then the stability of the matching holds when there are no
        blocking pairs and all players have been matched."""

        if None in self.matching.values():
            return False

        blocking_pairs = []
        for player in self.players:
            others = [p for p in self.players if p != player]
            for other in others:
                if (other, player) not in blocking_pairs:
                    both_matched = player.matching and other.matching
                    prefer_each_other = player.prefers(
                        other, player.matching) and other.prefers(
                            player, other.matching)
                    if both_matched and prefer_each_other:
                        blocking_pairs.append((player, other))

        self.blocking_pairs = blocking_pairs
        return not any(blocking_pairs)

    def check_inputs(self):
        """ Check that all players have ranked all other players. """

        for player in self.players:
            others = {p for p in self.players if p != player}
            if set(player.prefs) != others:
                raise ValueError(
                    "Every player must rank all other players. "
                    f"{player}: {player.prefs} is not a permutation of {others}"
                )

        return True
Exemplo n.º 4
0
    #V2 = V2Handle.product()
    V3 = V3Handle.product()
    V40 = V40Handle.product()
    V41 = V41Handle.product()
    #V42 = V42Handle.product()
    mV1 = Matching(genJpsis, V1)
    #mV2 = Matching( genJpsis, V2)
    mV3 = Matching(genJpsis, V3)
    mV40 = Matching(genJpsis, V40)
    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():