|
1 | 1 | /**
|
2 | 2 | * @file
|
3 |
| - * @brief Stable Marriage Problem implementation |
| 3 | + * @brief [Stable Marriage](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm) |
4 | 4 | * @details
|
5 | 5 | * This implementation utilizes the Gale-Shapley algorithm to find stable matches
|
6 |
| - * between men and women based on their preferences. |
7 | 6 | *
|
8 | 7 | * **Stable Marriage Problem** aims to find a stable matching between two equally sized
|
9 | 8 | * sets of elements given an ordinal preference for each element. The algorithm was
|
10 | 9 | * introduced by David Gale and Lloyd Shapley in 1962.
|
| 10 | + * |
| 11 | + * Reference: |
| 12 | + * [Wikipedia](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm) |
| 13 | + * [Wikipedia](https://en.wikipedia.org/wiki/Stable_marriage_problem) |
11 | 14 | *
|
12 | 15 | * @author [B Karthik](https://github.com/BKarthik7)
|
13 | 16 | */
|
|
16 | 19 | #include <vector>
|
17 | 20 | #include <cstring>
|
18 | 21 | #include <algorithm>
|
19 |
| -using namespace std; |
20 | 22 |
|
21 |
| -void stableMatch(const vector<vector<int>>& women_prefs, const vector<vector<int>>& men_prefs, int n) { |
22 |
| - vector<int> engagements(n, -1); |
23 |
| - vector<bool> free_men(n, true); |
24 |
| - vector<int> next_proposal(n, 0); // Tracks the next woman to propose for each man |
| 23 | +/** |
| 24 | + * @namespace |
| 25 | + * @brief Greedy Algorithms |
| 26 | + */ |
| 27 | +namespace greedy_algorithms { |
| 28 | +/** |
| 29 | + * @namespace |
| 30 | + * @brief Functions for the [Gale Shapley](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm) algorithm |
| 31 | + */ |
| 32 | +namespace stable_marriage { |
| 33 | +void gale_shapley(const std::vector<std::vector<int>>& set_2_prefs, const std::vector<std::vector<int>>& set_1_prefs) { |
| 34 | + int n = set_2_prefs.size(); |
| 35 | + std::vector<int> engagements(n, -1); |
| 36 | + std::vector<bool> free_set_1_s(n, true); |
| 37 | + std::vector<int> next_proposal(n, 0); // Tracks the next set_2 to propose for each set_1 |
25 | 38 |
|
26 | 39 | while (true) {
|
27 |
| - int freeMan; |
28 |
| - for (freeMan = 0; freeMan < n; freeMan++) { |
29 |
| - if (free_men[freeMan]) break; |
| 40 | + int free_set_1; |
| 41 | + for (free_set_1 = 0; free_set_1 < n; free_set_1++) { |
| 42 | + if (free_set_1_s[free_set_1]) break; |
30 | 43 | }
|
31 |
| - if (freeMan == n) break; |
| 44 | + if (free_set_1 == n) break; |
32 | 45 |
|
33 |
| - int womanToPropose = men_prefs[freeMan][next_proposal[freeMan]]; |
34 |
| - next_proposal[freeMan]++; |
35 |
| - int currentFiance = engagements[womanToPropose]; |
| 46 | + int set_2_to_propose = set_1_prefs[free_set_1][next_proposal[free_set_1]]; |
| 47 | + next_proposal[free_set_1]++; |
| 48 | + int currentFiance = engagements[set_2_to_propose]; |
36 | 49 |
|
37 | 50 | if (currentFiance == -1) {
|
38 |
| - engagements[womanToPropose] = freeMan; |
39 |
| - free_men[freeMan] = false; |
| 51 | + engagements[set_2_to_propose] = free_set_1; |
| 52 | + free_set_1_s[free_set_1] = false; |
40 | 53 | } else {
|
41 |
| - if (find(women_prefs[womanToPropose].begin(), women_prefs[womanToPropose].end(), freeMan) < |
42 |
| - find(women_prefs[womanToPropose].begin(), women_prefs[womanToPropose].end(), currentFiance)) { |
43 |
| - engagements[womanToPropose] = freeMan; |
44 |
| - free_men[freeMan] = false; |
45 |
| - free_men[currentFiance] = true; |
| 54 | + if (std::find(set_2_prefs[set_2_to_propose].begin(), set_2_prefs[set_2_to_propose].end(), free_set_1) < |
| 55 | + std::find(set_2_prefs[set_2_to_propose].begin(), set_2_prefs[set_2_to_propose].end(), currentFiance)) { |
| 56 | + engagements[set_2_to_propose] = free_set_1; |
| 57 | + free_set_1_s[free_set_1] = false; |
| 58 | + free_set_1_s[currentFiance] = true; |
46 | 59 | }
|
47 | 60 | }
|
48 | 61 | }
|
49 | 62 |
|
50 |
| - cout << "Stable Matches:\n"; |
51 |
| - for (int woman = 0; woman < n; woman++) { |
52 |
| - cout << "Woman " << woman << " is engaged to Man " << engagements[woman] << endl; |
| 63 | + std::cout << "Stable Matches:\n"; |
| 64 | + for (int set_2 = 0; set_2 < n; set_2++) { |
| 65 | + std::cout << "set_2's " << set_2 << " is matched to set_1's " << engagements[set_2] << std::endl; |
53 | 66 | }
|
| 67 | + std::cout << std::endl; |
54 | 68 | }
|
| 69 | +} // namespace stable_marriage |
| 70 | +} // namespace greedy_algorithms |
55 | 71 |
|
56 |
| -void runTestCase(int caseNum) { |
57 |
| - const int n = 4; // Number of men and women |
| 72 | +/** |
| 73 | + * @brief Self-test implementations |
| 74 | + * @returns void |
| 75 | + */ |
58 | 76 |
|
| 77 | +static void tests() { |
59 | 78 | // Test Case 1
|
60 |
| - if (caseNum == 1) { |
61 |
| - cout << "Test Case 1:\n"; |
62 |
| - vector<vector<int>> women_prefs = { |
63 |
| - {1, 0, 3, 2}, // Alice |
64 |
| - {0, 1, 2, 3}, // Becky |
65 |
| - {1, 2, 0, 3}, // Cathy |
66 |
| - {3, 2, 1, 0} // Diana |
67 |
| - }; |
68 |
| - vector<vector<int>> men_prefs = { |
69 |
| - {0, 1, 2, 3}, // Bob |
70 |
| - {1, 0, 3, 2}, // Charlie |
71 |
| - {0, 2, 3, 1}, // David |
72 |
| - {2, 1, 0, 3} // Edward |
73 |
| - }; |
74 |
| - stableMatch(women_prefs, men_prefs, n); |
75 |
| - } |
76 |
| - |
| 79 | + std::vector<std::vector<int>> set_1_prefs = {{0, 1, 2, 3}, {2, 1, 3, 0}, {1, 2, 0, 3}, {3, 0, 1, 2}}; |
| 80 | + std::vector<std::vector<int>> set_2_prefs = {{1, 0, 2, 3},{3, 0, 1, 2},{0, 2, 1, 3},{1, 2, 0, 3}}; |
| 81 | + greedy_algorithms::stable_marriage::gale_shapley(set_2_prefs, set_1_prefs); |
| 82 | + |
77 | 83 | // Test Case 2
|
78 |
| - else if (caseNum == 2) { |
79 |
| - cout << "Test Case 2:\n"; |
80 |
| - vector<vector<int>> women_prefs = { |
81 |
| - {0, 1, 2, 3}, // Eve |
82 |
| - {1, 0, 3, 2}, // Grace |
83 |
| - {2, 1, 0, 3}, // Hannah |
84 |
| - {3, 2, 1, 0} // Ivy |
85 |
| - }; |
86 |
| - vector<vector<int>> men_prefs = { |
87 |
| - {1, 0, 3, 2}, // Frank |
88 |
| - {0, 1, 2, 3}, // George |
89 |
| - {1, 2, 0, 3}, // Henry |
90 |
| - {2, 0, 1, 3} // Ian |
91 |
| - }; |
92 |
| - stableMatch(women_prefs, men_prefs, n); |
93 |
| - } |
| 84 | + set_1_prefs = {{0, 2, 1, 3}, {2, 3, 0, 1}, {3, 1, 2, 0}, {2, 1, 0, 3}}; |
| 85 | + set_2_prefs = {{1, 0, 2, 3},{3, 0, 1, 2},{0, 2, 1, 3},{1, 2, 0, 3}}; |
| 86 | + greedy_algorithms::stable_marriage::gale_shapley(set_2_prefs, set_1_prefs); |
94 | 87 |
|
95 | 88 | // Test Case 3
|
96 |
| - else if (caseNum == 3) { |
97 |
| - cout << "Test Case 3:\n"; |
98 |
| - vector<vector<int>> women_prefs = { |
99 |
| - {2, 1, 0, 3}, // Jade |
100 |
| - {0, 2, 3, 1}, // Lucy |
101 |
| - {3, 2, 1, 0}, // Mia |
102 |
| - {1, 3, 0, 2} // Nina |
103 |
| - }; |
104 |
| - vector<vector<int>> men_prefs = { |
105 |
| - {1, 0, 2, 3}, // Kyle |
106 |
| - {0, 2, 3, 1}, // Liam |
107 |
| - {2, 1, 3, 0}, // Mason |
108 |
| - {3, 2, 1, 0} // Nathan |
109 |
| - }; |
110 |
| - stableMatch(women_prefs, men_prefs, n); |
111 |
| - } |
| 89 | + set_1_prefs = {{0, 1, 2}, {2, 1, 0}, {1, 2, 0}}; |
| 90 | + set_2_prefs = {{1, 0, 2},{2, 0, 1},{0, 2, 1}}; |
| 91 | + greedy_algorithms::stable_marriage::gale_shapley(set_2_prefs, set_1_prefs); |
112 | 92 | }
|
113 | 93 |
|
| 94 | +/** |
| 95 | + * @brief Main function |
| 96 | + * @returns 0 on exit |
| 97 | + */ |
114 | 98 | int main() {
|
115 |
| - for (int i = 1; i <= 3; i++) { |
116 |
| - runTestCase(i); |
117 |
| - cout << endl; |
118 |
| - } |
| 99 | + tests(); // run self-test implementations |
119 | 100 | return 0;
|
120 | 101 | }
|
0 commit comments