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
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
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
#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():