1
1
/* *
2
2
* @file
3
- * @brief [Gale Shapley Algorithm](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm)
3
+ * @brief [Gale Shapley
4
+ * Algorithm](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm)
4
5
* @details
5
- * This implementation utilizes the Gale-Shapley algorithm to find stable matches.
6
+ * This implementation utilizes the Gale-Shapley algorithm to find stable
7
+ * matches.
6
8
*
7
- * **Gale Shapley Algorithm** aims to find a stable matching between two equally sized
8
- * sets of elements given an ordinal preference for each element. The algorithm was
9
- * introduced by David Gale and Lloyd Shapley in 1962.
10
- *
11
- * Reference:
9
+ * **Gale Shapley Algorithm** aims to find a stable matching between two equally
10
+ * sized sets of elements given an ordinal preference for each element. The
11
+ * algorithm was introduced by David Gale and Lloyd Shapley in 1962.
12
+ *
13
+ * Reference:
12
14
* [Wikipedia](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm)
13
15
* [Wikipedia](https://en.wikipedia.org/wiki/Stable_matching_problem)
14
16
*
15
17
* @author [B Karthik](https://github.com/BKarthik7)
16
18
*/
17
19
18
- #include < iostream> // / for std::u32int_t
19
- #include < vector> // / for std::vector
20
20
#include < algorithm> // / for std::find
21
21
#include < cassert> // / for assert
22
+ #include < cstdint> // / for std::uint32_t
23
+ #include < vector> // / for std::vector
22
24
23
25
/* *
24
26
* @namespace
@@ -31,19 +33,25 @@ namespace greedy_algorithms {
31
33
*/
32
34
namespace stable_matching {
33
35
/* *
34
- * @brief The main function that finds the stable matching between two sets of elements
35
- * using the Gale-Shapley Algorithm.
36
- * @note This doesn't work on negative preferences. the preferences should be continuous integers starting from
37
- * 0 to number of preferences - 1.
38
- * @param primary_preferences the preferences of the primary set should be a 2D vector
39
- * @param secondary_preferences the preferences of the secondary set should be a 2D vector
36
+ * @brief The main function that finds the stable matching between two sets of
37
+ * elements using the Gale-Shapley Algorithm.
38
+ * @note This doesn't work on negative preferences. the preferences should be
39
+ * continuous integers starting from 0 to number of preferences - 1.
40
+ * @param primary_preferences the preferences of the primary set should be a 2D
41
+ * vector
42
+ * @param secondary_preferences the preferences of the secondary set should be a
43
+ * 2D vector
40
44
* @returns matches the stable matching between the two sets
41
45
*/
42
- std::vector<std::uint32_t > gale_shapley (const std::vector<std::vector<std::uint32_t >>& secondary_preferences, const std::vector<std::vector<std::uint32_t >>& primary_preferences) {
46
+ std::vector<std::uint32_t > gale_shapley (
47
+ const std::vector<std::vector<std::uint32_t >>& secondary_preferences,
48
+ const std::vector<std::vector<std::uint32_t >>& primary_preferences) {
43
49
std::uint32_t num_elements = secondary_preferences.size ();
44
50
std::vector<std::uint32_t > matches (num_elements, -1 );
45
51
std::vector<bool > is_free_primary (num_elements, true );
46
- std::vector<std::uint32_t > proposal_index (num_elements, 0 ); // Tracks the next secondary to propose for each primary
52
+ std::vector<std::uint32_t > proposal_index (
53
+ num_elements,
54
+ 0 ); // Tracks the next secondary to propose for each primary
47
55
48
56
while (true ) {
49
57
int free_primary_index = -1 ;
@@ -57,10 +65,13 @@ std::vector<std::uint32_t> gale_shapley(const std::vector<std::vector<std::uint3
57
65
}
58
66
59
67
// If no free primary is found, break the loop
60
- if (free_primary_index == -1 ) break ;
68
+ if (free_primary_index == -1 )
69
+ break ;
61
70
62
71
// Get the next secondary to propose
63
- std::uint32_t secondary_to_propose = primary_preferences[free_primary_index][proposal_index[free_primary_index]];
72
+ std::uint32_t secondary_to_propose =
73
+ primary_preferences[free_primary_index]
74
+ [proposal_index[free_primary_index]];
64
75
proposal_index[free_primary_index]++;
65
76
66
77
// Get the current match of the secondary
@@ -72,18 +83,21 @@ std::vector<std::uint32_t> gale_shapley(const std::vector<std::vector<std::uint3
72
83
is_free_primary[free_primary_index] = false ;
73
84
} else {
74
85
// Determine if the current match should be replaced
75
- auto new_proposer_rank = std::find (secondary_preferences[secondary_to_propose].begin (),
76
- secondary_preferences[secondary_to_propose].end (),
77
- free_primary_index);
78
- auto current_match_rank = std::find (secondary_preferences[secondary_to_propose].begin (),
79
- secondary_preferences[secondary_to_propose].end (),
80
- current_match);
86
+ auto new_proposer_rank =
87
+ std::find (secondary_preferences[secondary_to_propose].begin (),
88
+ secondary_preferences[secondary_to_propose].end (),
89
+ free_primary_index);
90
+ auto current_match_rank =
91
+ std::find (secondary_preferences[secondary_to_propose].begin (),
92
+ secondary_preferences[secondary_to_propose].end (),
93
+ current_match);
81
94
82
95
// If the new proposer is preferred over the current match
83
96
if (new_proposer_rank < current_match_rank) {
84
97
matches[secondary_to_propose] = free_primary_index;
85
98
is_free_primary[free_primary_index] = false ;
86
- is_free_primary[current_match] = true ; // Current match is now free
99
+ is_free_primary[current_match] =
100
+ true ; // Current match is now free
87
101
}
88
102
}
89
103
}
@@ -99,31 +113,43 @@ std::vector<std::uint32_t> gale_shapley(const std::vector<std::vector<std::uint3
99
113
*/
100
114
static void tests () {
101
115
// Test Case 1
102
- std::vector<std::vector<std::uint32_t >> primary_preferences = {{0 , 1 , 2 , 3 }, {2 , 1 , 3 , 0 }, {1 , 2 , 0 , 3 }, {3 , 0 , 1 , 2 }};
103
- std::vector<std::vector<std::uint32_t >> secondary_preferences = {{1 , 0 , 2 , 3 }, {3 , 0 , 1 , 2 }, {0 , 2 , 1 , 3 }, {1 , 2 , 0 , 3 }};
104
- assert (greedy_algorithms::stable_matching::gale_shapley (secondary_preferences, primary_preferences) == std::vector<std::uint32_t >({0 , 2 , 1 , 3 }));
116
+ std::vector<std::vector<std::uint32_t >> primary_preferences = {
117
+ {0 , 1 , 2 , 3 }, {2 , 1 , 3 , 0 }, {1 , 2 , 0 , 3 }, {3 , 0 , 1 , 2 }};
118
+ std::vector<std::vector<std::uint32_t >> secondary_preferences = {
119
+ {1 , 0 , 2 , 3 }, {3 , 0 , 1 , 2 }, {0 , 2 , 1 , 3 }, {1 , 2 , 0 , 3 }};
120
+ assert (greedy_algorithms::stable_matching::gale_shapley (
121
+ secondary_preferences, primary_preferences) ==
122
+ std::vector<std::uint32_t >({0 , 2 , 1 , 3 }));
105
123
106
124
// Test Case 2
107
- primary_preferences = {{0 , 2 , 1 , 3 }, {2 , 3 , 0 , 1 }, {3 , 1 , 2 , 0 }, {2 , 1 , 0 , 3 }};
108
- secondary_preferences = {{1 , 0 , 2 , 3 }, {3 , 0 , 1 , 2 }, {0 , 2 , 1 , 3 }, {1 , 2 , 0 , 3 }};
109
- assert (greedy_algorithms::stable_matching::gale_shapley (secondary_preferences, primary_preferences) == std::vector<std::uint32_t >({0 , 3 , 1 , 2 }));
125
+ primary_preferences = {
126
+ {0 , 2 , 1 , 3 }, {2 , 3 , 0 , 1 }, {3 , 1 , 2 , 0 }, {2 , 1 , 0 , 3 }};
127
+ secondary_preferences = {
128
+ {1 , 0 , 2 , 3 }, {3 , 0 , 1 , 2 }, {0 , 2 , 1 , 3 }, {1 , 2 , 0 , 3 }};
129
+ assert (greedy_algorithms::stable_matching::gale_shapley (
130
+ secondary_preferences, primary_preferences) ==
131
+ std::vector<std::uint32_t >({0 , 3 , 1 , 2 }));
110
132
111
133
// Test Case 3
112
134
primary_preferences = {{0 , 1 , 2 }, {2 , 1 , 0 }, {1 , 2 , 0 }};
113
135
secondary_preferences = {{1 , 0 , 2 }, {2 , 0 , 1 }, {0 , 2 , 1 }};
114
- assert (greedy_algorithms::stable_matching::gale_shapley (secondary_preferences, primary_preferences) == std::vector<std::uint32_t >({0 , 2 , 1 }));
136
+ assert (greedy_algorithms::stable_matching::gale_shapley (
137
+ secondary_preferences, primary_preferences) ==
138
+ std::vector<std::uint32_t >({0 , 2 , 1 }));
115
139
116
140
// Test Case 4
117
141
primary_preferences = {};
118
142
secondary_preferences = {};
119
- assert (greedy_algorithms::stable_matching::gale_shapley (secondary_preferences, primary_preferences) == std::vector<std::uint32_t >({}));
143
+ assert (greedy_algorithms::stable_matching::gale_shapley (
144
+ secondary_preferences, primary_preferences) ==
145
+ std::vector<std::uint32_t >({}));
120
146
}
121
147
122
148
/* *
123
149
* @brief Main function
124
150
* @returns 0 on exit
125
151
*/
126
152
int main () {
127
- tests (); // Run self-test implementations
153
+ tests (); // Run self-test implementations
128
154
return 0 ;
129
155
}
0 commit comments