Beispiel #1
0
def test_check_stability():
    """ Test that StableMarriage can recognise whether a matching is stable. """

    from matching import Player

    suitors = [Player("A"), Player("B")]
    reviewers = [Player("X"), Player("Y")]

    (a, b), (x, y) = suitors, reviewers

    a.set_prefs(reviewers)
    b.set_prefs(reviewers[::-1])

    x.set_prefs(suitors)
    y.set_prefs(suitors[::-1])

    game = StableMarriage(suitors, reviewers)

    matching = game.solve()
    assert game.check_stability()

    (a, b), (x, y) = game.suitors, game.reviewers
    matching[a] = y
    matching[b] = x

    assert not game.check_stability()
Beispiel #2
0
def test_check_validity(player_names, seed):
    """ Test that StableMarriage finds no errors when the game is solved. """

    suitors, reviewers = make_players(player_names, seed)
    game = StableMarriage(suitors, reviewers)

    game.solve()
    assert game.check_validity()
Beispiel #3
0
def test_solve(player_names, seed):
    """ Test that StableMarriage can solve games correctly when passed players.
    """

    for optimal in ["suitor", "reviewer"]:
        suitors, reviewers = make_players(player_names, seed)
        game = StableMarriage(suitors, reviewers)

        matching = game.solve(optimal)
        assert isinstance(matching, Matching)
        assert set(matching.keys()) == set(suitors)
        assert set(matching.values()) == set(reviewers)
Beispiel #4
0
def test_all_matched(player_names, seed):
    """ Test that StableMarriage recognises a valid matching requires all
    players to be matched as players and as part of the game. """

    suitors, reviewers = make_players(player_names, seed)
    game = StableMarriage(suitors, reviewers)

    matching = game.solve()
    matching[game.suitors[0]].matching = None
    game.matching[game.suitors[0]] = None

    with pytest.raises(Exception):
        game._check_all_matched()
Beispiel #5
0
def test_inputs_num_players(player_names, seed):
    """ Test StableMarriage raises a ValueError when a different number of
    suitors and reviewers are passed. """

    suitors, reviewers = make_players(player_names, seed)
    game = StableMarriage(suitors, reviewers)

    assert game._check_num_players()

    suitors = suitors[:-1]

    with pytest.raises(ValueError):
        StableMarriage(suitors, reviewers)
Beispiel #6
0
def test_inputs_player_ranks(player_names, seed):
    """ Test StableMarriage raises a ValueError when a player has not ranked all
    members of the opposing party. """

    suitors, reviewers = make_players(player_names, seed)
    game = StableMarriage(suitors, reviewers)

    for player in game.suitors + game.reviewers:
        assert game._check_player_ranks(player)

    suitors[0].prefs = suitors[0].prefs[:-1]

    with pytest.raises(ValueError):
        StableMarriage(suitors, reviewers)
Beispiel #7
0
def test_check_for_players_not_in_matching(player_names, seed):
    """Test that StableMarriage recognises a valid matching requires all
    players to be matched in the matching."""

    suitors, reviewers = make_players(player_names, seed)
    game = StableMarriage(suitors, reviewers)
    matching = game.solve()

    player = game.suitors[0]
    matching[player] = None

    with pytest.raises(MatchingError) as e:
        game.check_validity()
        error = e.players[0]
        assert error.startswith(player.name)
Beispiel #8
0
def solve(inputs):
    cur = 0

    (N, index) = parse.parse("{:d} {:d}", inputs[cur])
    cur += 1
    college_preferences = {}
    student_preferences = {}
    names = []
    for i in range(N):
        xs = list(map(int, inputs[cur].split(" ")))
        cur += 1
        college_preferences[i] = xs
    for i in range(N):
        xs = list(map(int, inputs[cur].split(" ")))
        cur += 1
        student_preferences[i] = xs
    for i in range(N):
        names.append(inputs[cur])
        cur += 1
    game = StableMarriage.create_from_dictionaries(
        student_preferences, college_preferences
    )
    t = game.solve()
    ks = list(t.keys())
    vs = list(t.values())
    pairs = {}
    for i in range(N):
        pairs[vs[i].name] = ks[i].name
    return names[pairs[index]]
Beispiel #9
0
def test_init(player_names, seed):
    """ Test that the StableMarriage solver takes two sets of preformed players
    correctly. """

    suitors, reviewers = make_players(player_names, seed)
    game = StableMarriage(suitors, reviewers)

    assert game.suitors == suitors
    assert game.reviewers == reviewers
    assert all(
        [player.matching is None for player in game.suitors + game.reviewers])
    assert game.matching is None
Beispiel #10
0
def test_solve(player_names, seed):
    """Test that StableMarriage can solve games correctly when passed players."""

    for optimal in ["suitor", "reviewer"]:
        suitors, reviewers = make_players(player_names, seed)
        game = StableMarriage(suitors, reviewers)

        matching = game.solve(optimal)
        assert isinstance(matching, Matching)

        suitors = sorted(suitors, key=lambda s: s.name)
        reviewers = sorted(reviewers, key=lambda r: r.name)

        matching_keys = sorted(matching.keys(), key=lambda k: k.name)
        matching_values = sorted(matching.values(), key=lambda v: v.name)

        for game_suitor, suitor in zip(matching_keys, suitors):
            assert game_suitor.name == suitor.name
            assert game_suitor.pref_names == suitor.pref_names

        for game_reviewer, reviewer in zip(matching_values, reviewers):
            assert game_reviewer.name == reviewer.name
            assert game_reviewer.pref_names == reviewer.pref_names
Beispiel #11
0
def test_check_stability():
    """ Test that StableMarriage can recognise whether a matching is stable. """

    from matching import Player

    suitors = [Player("A"), Player("B")]
    reviewers = [Player(1), Player(2)]

    suitors[0].set_prefs(reviewers)
    suitors[1].set_prefs(reviewers[::-1])

    reviewers[0].set_prefs(suitors)
    reviewers[1].set_prefs(suitors[::-1])

    game = StableMarriage(suitors, reviewers)

    matching = game.solve()
    assert game.check_stability()

    (s_a, s_b), (r_1, r_2) = game.suitors, game.reviewers
    matching[s_a] = r_2
    matching[s_b] = r_1

    assert not game.check_stability()
Beispiel #12
0
def test_create_from_dictionaries(player_names, seed):
    """Test that the StableMarriage solver can take two preference dictionaries
    correctly."""

    suitor_prefs, reviewer_prefs = make_prefs(player_names, seed)
    game = StableMarriage.create_from_dictionaries(suitor_prefs, reviewer_prefs)

    for suitor in game.suitors:
        assert suitor_prefs[suitor.name] == suitor.pref_names
        assert suitor.matching is None

    for reviewer in game.reviewers:
        assert reviewer_prefs[reviewer.name] == reviewer.pref_names
        assert reviewer.matching is None

    assert game.matching is None
Beispiel #13
0
def test_matching_consistent(player_names, seed):
    """ Test that StableMarriage recognises a valid matching requires there to
    be consistency between the game's matching and its players'. """

    suitors, reviewers = make_players(player_names, seed)

    game = StableMarriage(suitors, reviewers)
    game.solve()

    game.suitors[0].matching = None
    game.reviewers[0].matching = None

    with pytest.raises(Exception):
        game._check_matching_consistent()
Beispiel #14
0
def solveProblem(member_list1, member_list2, coeff_list):
    """Solve the matching problem"""

    # randomize lists in order to avoid unwanted effects
    print('Randomize lists...')
    random.shuffle(member_list1)
    random.shuffle(member_list2)

    # creating the dicts
    print('Creating the dicts for solving...')
    N = len(member_list1)
    firstYear_prefs = {}
    secondYear_prefs = {}
    for i in range(N):
        firstYear_prefs[i] = sorted(
            range(N),
            key=lambda n: loveScore(member_list2[n]['answers'], member_list1[i]
                                    ['answers'], coeff_list))
        secondYear_prefs[i] = sorted(
            range(N),
            key=lambda n: loveScore(member_list2[i]['answers'], member_list1[n]
                                    ['answers'], coeff_list))

    # make the marriage and solve the problem! Les 1A sont privilégiés dans leurs préférences
    print('Solving...')
    game = StableMarriage.create_from_dictionaries(firstYear_prefs,
                                                   secondYear_prefs)
    dict_solved = game.solve()

    # get the family for each 1A
    print('Add families to 1A members')
    for player_1A, player_2A in dict_solved.items():
        id_1A = player_1A.name
        id_2A = player_2A.name
        member_list1[id_1A]['family'] = member_list2[id_2A]['family']

    return member_list1
    firstYear_prefs[i] = sorted(
        range(N),
        key=lambda n: loveScore(students_secondYear[n].answers,
                                students_firstYear[i].answers))
    secondYear_prefs[i] = sorted(
        range(N),
        key=lambda n: loveScore(students_secondYear[i].answers,
                                students_firstYear[n].answers))

# -- --

# -- Solve the problem --
from matching.games import StableMarriage

game = StableMarriage.create_from_dictionaries(firstYear_prefs,
                                               secondYear_prefs)
dict_solved = game.solve()
# -- --

families_solved = {}
orphans = {}

f = open('out.log', 'w')

for fillot_id, parrain_id in dict_solved.items():
    fillot = students_firstYear[fillot_id.name]
    parrain = students_secondYear[parrain_id.name]

    fillot.parrain = parrain
    parrain.fillot = fillot
Beispiel #16
0
def Match(atom_ID,ss_freqs,RefFile,ShiftFile):
	warnings.filterwarnings("ignore")

	#All Atom Info
	natoms = sum(atom_ID)
	dim = natoms * 3
	ss_freqs = np.reshape(ss_freqs,(-1,dim))

	Ref_UCParams = data.ReadYaml(RefFile)
	[ref_freqs, ref_vecs] = Ref_UCParams.get_UC()
	ref_vecs = np.reshape(ref_vecs,(-1,dim))
	ref_freqs[0] = 0
	ref_freqs[1] = 0
	ref_freqs[2] = 0

	Shift_UCParams = data.ReadYaml(ShiftFile)
	[shift_freqs, shift_vecs] = Shift_UCParams.get_UC()
	shift_vecs = np.reshape(shift_vecs,(-1,dim))

	#Get initial dotprod matrix
	dots = get_dots(dim,shift_vecs,ref_vecs)

	dft_ranks = [] #Ranking DFT matches with FIXED DFTB modes
	for i in range(dim):
		sort_dots = np.sort(dots[i,:])[::-1]
		seen = set()
		available_matches = list(range(0,dim))
		for j in range(dim):
			val = sort_dots[j]
			arr = dots[i,:]
			tmp = (np.where(arr == val)[0][0])
			if tmp not in seen:
				available_matches.remove(tmp)
				seen.add(tmp)
			else:
				availdots = []
				for k in available_matches:
					availdots.append(dots[i,k])
				tmp = available_matches[availdots.index(max(availdots))]
				available_matches.remove(tmp)
			dft_ranks = np.append(dft_ranks,tmp)

	dftb_ranks = [] #Ranking DFTB matches with FIXED DFT modes
	for i in range(dim):
		sort_dots = np.sort(dots[:,i])[::-1]
		seen = set()
		available_matches = list(range(0,dim))
		for j in range(dim):
			val = sort_dots[j]
			arr = dots[:,i]
			tmp = (np.where(arr == val)[0][0])
			if tmp not in seen:
				available_matches.remove(tmp)
				seen.add(tmp)
			else:
				availdots = []
				for k in available_matches:
					availdots.append(dots[k,i])
				tmp = available_matches[availdots.index(max(availdots))]
				available_matches.remove(tmp)
			dftb_ranks = np.append(dftb_ranks,tmp)

	dft_ranks = dft_ranks.reshape([-1,dim])
	dftb_ranks = dftb_ranks.reshape([-1,dim])

	dftRankDict = dict(((i), dft_ranks[i][:]) for i in range(dim)) #Favored DFT pairing to a DFTB mode -- "Suitor"
	dftbRankDict = dict(((i), dftb_ranks[i][:]) for i in range(dim)) #Favored DFTB pairing to a DFT mode -- "Reviewer"
	
	matching = StableMarriage.create_from_dictionaries(dftRankDict, dftbRankDict)
	AllMatches = matching.solve()
	AllMatches = list(str(AllMatches).replace('{','').replace('}','').split(','))
	matches = []

	for i in AllMatches:
		line = (i.split(':'))
		DFTmode  = int(line[0])
		DFTBmode = int(line[1])
		matches.append(DFTmode)
		matches.append(DFTBmode)

	matches = np.array(matches).reshape([dim,2])

	##In matches array, the first column is the DFT modes, and the second is DFTB. Need to re-sort in order to get the
	##DFTB modes in ascending order for the shift
	match_array = matches[np.argsort(matches[:,1])]
	match_array = match_array[:,0]
	#Set new order according to match
	shift_freqs = shift_freqs[match_array]

	#Apply shifts to dftb freqs
	shifts = [ref_freqs - shift_freqs]
	shifts = np.array(shifts).reshape(dim,-1)

	ss_freqs = ss_freqs.transpose() 
	shifted_freqs = ss_freqs[match_array] + shifts
	shifted_freqs = shifted_freqs.flatten()
	

	
	
	return shifted_freqs
        #except KeyError:
        #  row_str = row_str + ", " + str(0)
    print(row_str)

# future strategy
# GS algo fine for small enough dataset & guarantees stable solution that optimizes max allocations
# but since it's iterative & evaluates entire solution space, grows exponential
# so use these pairings & scores & feedback to develop an ML soluted
# also use ML to develop more sophisticated ranking & explore different scoring (objective) functions

# pseudo-global matching based on ranked preferences

suitors = [Player(name="A"), Player(name="B"), Player(name="C")]
reviewers = [Player(name="D"), Player(name="E"), Player(name="F")]
(A, B, C), (D, E, F) = suitors, reviewers

#print(type(suitors))

A.set_prefs([D, E, F])
B.set_prefs([D, F, E])
C.set_prefs([F, D, E])

D.set_prefs([B, C, A])
E.set_prefs([A, C, B])
F.set_prefs([C, B, A])

from matching.games import StableMarriage
game = StableMarriage(suitors, reviewers)
print(game.solve())
# {A: E, B: D, C: F}
from matching.games import StableMarriage

malePreferences = {1: [2, 3, 1], 2: [2, 3, 1], 3: [1, 3, 2]}

femalePreferences = {1: [2, 3, 1], 2: [3, 2, 1], 3: [1, 3, 2]}

# females review males preferences
game = StableMarriage.create_from_dictionaries(malePreferences,
                                               femalePreferences)

print("{Male: Female} pairs\n", game.solve())
def makeQuintuplets(quads: list, aloneStudents: dict, singles: dict, matchBefore: dict):
    #Each quad needs to match with one alone Student
    #make an empty list to avoid changing quads and aloneStudents
    extraStudentsQuads = []
    extraStudentsAlone = []
    for quad in quads:
        extraStudentsQuads.append(quad)
    for key in aloneStudents:
        extraStudentsAlone.append(aloneStudents[key])

    quintuplets = []

    finished = False
    if len(extraStudentsAlone) != len(extraStudentsQuads):
        print("Error: size mismatch in makeQuintuplets")
    if len(extraStudentsAlone) == 0:
        finished = True
    i = 0

    while (not finished) and i < 5:
        preferenceListOnes = preferenceAsymmetricalSort(extraStudentsAlone, extraStudentsQuads, "GroupByOne", matchBefore)
        preferenceListQuads = preferenceAsymmetricalSort(extraStudentsQuads, extraStudentsAlone, "OneByGroup", matchBefore)
        
        game = StableMarriage.create_from_dictionaries(preferenceListOnes, preferenceListQuads)
        ans = game.solve()

        
        removeImpossibleQuin(ans, matchBefore, singles, aloneStudents, extraStudentsAlone, extraStudentsQuads)
        
        moveStudentsGroups(quintuplets, ans, singles, aloneStudents, quads)
        
        if len(extraStudentsAlone) == 0:
            finished = True
        i = i+ 1

        if len(extraStudentsAlone) != len(extraStudentsQuads):
            print("Errror: size mismatch in makeQuintuplets")

    
    listUsedIndexesAlone = list()
    listUsedIndexesQuads = list()
    groupsToMake = list()
    for index1 in range(len(extraStudentsAlone)):
        for index2 in range(len(extraStudentsQuads)):
            if index1 not in listUsedIndexesAlone and index2 not in listUsedIndexesQuads:
                tempList = [(extraStudentsAlone[index1])]
                tempList.extend(extraStudentsQuads[index2])
                if isValidGroup(matchBefore, tempList) == 0:
                    listUsedIndexesAlone.append(index1)
                    listUsedIndexesQuads.append(index2)
                    groupsToMake.append([index1, index2])
    
    usedAlone = list()
    usedQuads = list()
    for groupToMake in groupsToMake:
        tempList = [extraStudentsAlone[groupToMake[0]]]
        tempList.extend(extraStudentsQuads[groupToMake[1]])
        quintuplets.append(tempList)
        usedAlone.append(extraStudentsAlone[groupToMake[0]])
        usedQuads.append(extraStudentsQuads[groupToMake[1]])

    for student in usedAlone:
        extraStudentsAlone.remove(student)
    
    for student in usedQuads:
        extraStudentsQuads.remove(student)

    for index in range(0, len(extraStudentsAlone)):
        tempList = extraStudentsQuads[index]
        tempList.append(extraStudentsAlone[index])
        quintuplets.append(tempList)
    
    extraStudentsAlone.clear()
    extraStudentsQuads.clear()
    
    return quintuplets