-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathGaleShapleyAlgorithm.java
195 lines (169 loc) · 7.35 KB
/
GaleShapleyAlgorithm.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
* Code by:@yinengy
* Time: 9/6/2018
*
* Correspond to the algorithm state in page 6,
* all /* comments are from the book.
*/
import java.util.Collections;
import java.util.HashMap;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
public class GaleShapleyAlgorithm {
/**
* @param M the one who selects individual (M in book)
* @param W the individual who will be selected (W in book)
* @param mPref the preference list of all the M
* @param wPref the preference list of all the W
* @return a stable perfect matching
*/
public static String[][] StableMatching(String[] M, String[] W, String[][] mPref, String[][] wPref) {
/* Initially all m ∈M and w ∈W are free */
// queue that store all the free M
Queue<String> freeM = new ArrayBlockingQueue<>(M.length);
Collections.addAll(freeM, M);
// HashMap that M be key and W be value to store a pair, so can search W by M in O(1)
HashMap<String, String> pairMW = new HashMap<>();
// HashMap that W be key and M be value to store a pair, so can search M by W in O(1)
HashMap<String, String> pairWM = new HashMap<>();
// HashMap contains the Ws that has not been proposed by M
HashMap<String, Queue<String>> ProposedList = buildProposedList(M, mPref);
// HashMap which can search the preference of each W by O(1)
HashMap<String, String[]> PreferenceList = buildPreferenceList(W, wPref);
/* While there is a man m who is free and hasn’t proposed to every woman */
while (!freeM.isEmpty() && !ProposedList.get(freeM.peek()).isEmpty()) {
/* Choose such a man m */
String m = freeM.peek();
/* Let w be the highest-ranked woman in m’s preference list
to whom m has not yet proposed */
String w = ProposedList.get(m).remove();
/* If w is free then */
if (!pairWM.containsKey(w)) {
/* (m, w) become engaged */
pairMW.put(m, w);
pairWM.put(w, m);
freeM.remove();
/* Else w is currently engaged to m' */
} else {
String mPrime = pairWM.get(w);
String[] preference = PreferenceList.get(w);
int mPrimeIndex = -1;
int mIndex = -1;
//log the preference order of certain m in w's list
for (int i = 0; i < preference.length; i++) {
if (preference[i].equals(mPrime)) {
mPrimeIndex = i;
}
if (preference[i].equals(m)) {
mIndex = i;
}
if (mPrimeIndex > -1 && mIndex > -1) {
break;
}
}
/* If w prefers m' to m then */
if (mPrimeIndex < mIndex) {
/* m remains free */
// do nothing
/* Else w prefers m to m' */
} else {
/* (m, w) become engaged */
/* m' becomes free */
pairMW.remove(mPrime);
pairWM.remove(w);
pairMW.put(m, w);
pairWM.put(w, m);
freeM.remove();
freeM.add(mPrime);
}
/* Endif */ // O(1)
}
/* Endif */ // O(n) in the worst for travers the the preference list, O(1) in best
}
/* Endwhile */ // O(n)
// convert HashMap to 2D list to show the pair, the row is each pair, the first column is m and second is w;
String[][] S = new String[M.length][2];
for (int i = 0; i < M.length; i++) {
S[i][0] = M[i];
String temp = pairMW.get(M[i]);
S[i][1] = temp;
}
/* Return the set S of engaged pairs */
return S;
}
/**
* change the 2-D list preferList to a HashMap will lead to O(1) to
* check if certain W has been proposed by certain M
* The queue is in the order of the preference of M, if empty, all the Ws have been proposed
*
* @param M the one who selects individual (M in book)
* @param prefList the 2-D list of preference in the same order of M
* @return a HashMap can to searched to check if certain W has been proposed by certain M
*/
private static HashMap<String, Queue<String>> buildProposedList(String[] M, String[][] prefList) {
HashMap<String, Queue<String>> map = new HashMap<>();
for (int i = 0; i < prefList.length; i++) {
Queue<String> pref = new ArrayBlockingQueue<>(prefList[0].length);
Collections.addAll(pref, prefList[i]);
map.put(M[i], pref);
}
return map;
}
/**
* change the 2-D list preferList to a HashMap will lead to O(1) to
* search the preference of every W
*
* @param W the individual who will be selected (W in book)
* @param prefList the 2-D list of preference in the same order of W
* @return a HashMap that can search the preference of every W
*/
private static HashMap<String, String[]> buildPreferenceList(String[] W, String[][] prefList) {
HashMap<String, String[]> map = new HashMap<>();
for (int i = 0; i < prefList.length; i++) {
String[] pref = prefList[i];
map.put(W[i], pref);
}
return map;
}
/**
* Simple test case
*/
public static void main(String[] args) {
String[] M = {"Atlanta", "Boston", "Chicago", "Dallas", "Eugene"};
String[] W = {"Val", "Wayne", "Xavier", "Yolanda", "Zeus"};
//in the same order of m
String[][] mPref = {{"Wayne", "Val", "Yolanda", "Zeus", "Xavier"},
{"Yolanda", "Wayne", "Val", "Xavier", "Zeus"},
{"Wayne", "Zeus", "Xavier", "Yolanda", "Val"},
{"Val", "Yolanda", "Xavier", "Wayne", "Zeus"},
{"Wayne", "Yolanda", "Val", "Zeus,", "Xavier"}};
String[][] wPref = {{"Eugene", "Atlanta", "Boston", "Dallas", "Chicago"},
{"Chicago", "Boston", "Dallas", "Atlanta", "Eugene"},
{"Boston", "Chicago", "Dallas", "Eugene", "Atlanta"},
{"Atlanta", "Eugene", "Dallas", "Chicago", "Boston"},
{"Dallas", "Boston", "Eugene", "Chicago", "Atlanta"}};
String[][] S = StableMatching(M, W, mPref, wPref);
for (String[] value : S) {
for (String var : value) {
System.out.print(var + " ");
}
System.out.println();
}
String[] M2 = {"m1", "m2", "m3"};
String[] W2 = {"w1", "w2", "w3"};
//in the same order of m
String[][] mPref2 = {{"w2", "w1", "w3"},
{"w1", "w2", "w3"},
{"w1", "w3", "w2"}};
String[][] wPref2 = {{"m1", "m3", "m2"}, // change m3 and m2's order lead to better off, which correspond to Capter 1 exercise 8
{"m2", "m1", "m3"},
{"m1", "m2", "m3"}};
String[][] S2 = StableMatching(M2, W2, mPref2, wPref2);
for (String[] value : S2) {
for (String var : value) {
System.out.print(var + " ");
}
System.out.println();
}
}
}