Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 901f231

Browse files
BKarthik7realstealthninja
andauthored
feat: Added gale_shapley.cpp in greedy_algorithms (TheAlgorithms#2743)
* Added gale_shapley.cpp in greedy_algorithms * Added gale_shapley.cpp in greedy_algorithms * Genralized GaleShapley with reviewed change * fix: added description * fix: fixed nameing of namespace * fix: reviewed changes * fix: reviewed changes * TestCase Empty vector * function description * Update greedy_algorithms/gale_shapley.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Update greedy_algorithms/gale_shapley.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Change type * typechange with header documentation --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com>
1 parent cde1672 commit 901f231

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

‎greedy_algorithms/gale_shapley.cpp

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/**
2+
* @file
3+
* @brief [Gale Shapley Algorithm](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm)
4+
* @details
5+
* This implementation utilizes the Gale-Shapley algorithm to find stable matches.
6+
*
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:
12+
* [Wikipedia](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm)
13+
* [Wikipedia](https://en.wikipedia.org/wiki/Stable_matching_problem)
14+
*
15+
* @author [B Karthik](https://github.com/BKarthik7)
16+
*/
17+
18+
#include <iostream> /// for std::u32int_t
19+
#include <vector> /// for std::vector
20+
#include <algorithm> /// for std::find
21+
#include <cassert> /// for assert
22+
23+
/**
24+
* @namespace
25+
* @brief Greedy Algorithms
26+
*/
27+
namespace greedy_algorithms {
28+
/**
29+
* @namespace
30+
* @brief Functions for the Gale-Shapley Algorithm
31+
*/
32+
namespace stable_matching {
33+
/**
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
40+
* @returns matches the stable matching between the two sets
41+
*/
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) {
43+
std::uint32_t num_elements = secondary_preferences.size();
44+
std::vector<std::uint32_t> matches(num_elements, -1);
45+
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
47+
48+
while (true) {
49+
int free_primary_index = -1;
50+
51+
// Find the next free primary
52+
for (std::uint32_t i = 0; i < num_elements; i++) {
53+
if (is_free_primary[i]) {
54+
free_primary_index = i;
55+
break;
56+
}
57+
}
58+
59+
// If no free primary is found, break the loop
60+
if (free_primary_index == -1) break;
61+
62+
// Get the next secondary to propose
63+
std::uint32_t secondary_to_propose = primary_preferences[free_primary_index][proposal_index[free_primary_index]];
64+
proposal_index[free_primary_index]++;
65+
66+
// Get the current match of the secondary
67+
std::uint32_t current_match = matches[secondary_to_propose];
68+
69+
// If the secondary is free, match them
70+
if (current_match == -1) {
71+
matches[secondary_to_propose] = free_primary_index;
72+
is_free_primary[free_primary_index] = false;
73+
} else {
74+
// 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);
81+
82+
// If the new proposer is preferred over the current match
83+
if (new_proposer_rank < current_match_rank) {
84+
matches[secondary_to_propose] = free_primary_index;
85+
is_free_primary[free_primary_index] = false;
86+
is_free_primary[current_match] = true; // Current match is now free
87+
}
88+
}
89+
}
90+
91+
return matches;
92+
}
93+
} // namespace stable_matching
94+
} // namespace greedy_algorithms
95+
96+
/**
97+
* @brief Self-test implementations
98+
* @returns void
99+
*/
100+
static void tests() {
101+
// 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}));
105+
106+
// 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}));
110+
111+
// Test Case 3
112+
primary_preferences = {{0, 1, 2}, {2, 1, 0}, {1, 2, 0}};
113+
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}));
115+
116+
// Test Case 4
117+
primary_preferences = {};
118+
secondary_preferences = {};
119+
assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector<std::uint32_t>({}));
120+
}
121+
122+
/**
123+
* @brief Main function
124+
* @returns 0 on exit
125+
*/
126+
int main() {
127+
tests(); // Run self-test implementations
128+
return 0;
129+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /