-
-
Notifications
You must be signed in to change notification settings - Fork 358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stable marriage Python implementation is cubic #1005
Comments
Hi!
If you have done all that, I think you can open a PR, in which we'll do a code review. As the code you provide in the issue is confusing (in my opinion), we'll definitely need to improve it before we can merge it in. |
The results are identical. They both implement the Gale–Shapley Algorithm, and interestingly, any G–S algorithm implementation has a unique output (regardless of execution order). I have confirmed that the produced matching is the same in both algorithms.
They both used the same seed in all ten runs. If necessary, I can try to get |
OK, good. We won't have to check too much, then. The thing I don't really understand is where you pull While in general I'd prefer fast code, in this case I'm not sure if that's necessary, as the AAA has a mainly pedagogical value, although it should definitely talk about performance in a dedication section. EDIT: What I failed to mention is that we have to assume people don't have a background in programming or algorithms, so clarity is key, sometimes even at the cost of performance. |
This looks good to me. To be honest, the stable marriage chapter is one of the few that need a major overhaul. There does not seem to be any standard implementation that spans across different languages, so the python version is radically different than the Julia one (for example). Right now, I find the current python implementation a bit harder to read than the one you provided, but we might need to work on it to standardize it across the other languages as well. |
Here is the modification that allowed me to run it for an arbitrary number of pairs -def main():
+def main(num_pairs):
# Set this to however many men and women you want, up to 26
- num_pairs = 5
# Create all Person objects
- men = [Person(name) for name in ascii_uppercase[:num_pairs]]
- women = [Person(name) for name in ascii_lowercase[:num_pairs]]
+ men = [Person(f"M{name}") for name in range(num_pairs)]
+ women = [Person(f"W{name}") for name in range(num_pairs)]
# Set everyone's preferences
for man in men:
@@ -136,4 +135,5 @@ class Person:
if __name__ == '__main__':
- main()
+ import sys
+ main(int(sys.argv[1]))
I realize that, and I think that's a good thing. I just don't know if the current SM implementation is optimal in that regard either. I think the OOP based approach to a relatively simple algorithm makes it more difficult to see what's going on. The stable marriage algorithm works as follows:
I think that an algorithm in the AAA should be as close in spirit as possible, to that one. A different issue is that I think that more modern expositions of the stable matching problem uses "hospitals" and "students", rather than "men" and "women". But that's a different discussion.
I could also take a shot at that while I'm at it (if I'm creating a PR anyway). Pps: I don't think it belongs under decision problems (that are typically yes/no). The Stable Marriage problem always has a solution. Perhaps it would be better suited under a flows & matchings category? |
Yeah, I agree with the points here. Also happy to change terminology to be stable matching instead of stable marriage (and also take down my youtube video on the topic). At the time, I had not seen the stable matching terminology. I wish I had because it kinda caused a bit of a rift in the community and I didn't know how to fix it. I think I would ideally like to revamp the entire chapter to be more inline with current standards. |
@pgdr Yep, I'm okay with those modifications for benchmarking, although we don't typically read from stdin (because of an ongoing-ish effort for standardization of inputs and outputs). I also agree that OOP might not be the best approach, although it was the approach I went for when I wanted to improve it (might have been misguided). If both of you want a revamp of the chapter, we'll need to rewrite all the implementations anyway, so might as well do a compromise solution (your code, but a bit less confusing). |
After a "quick" profile, these two are the longest running functions:
So the method call overhead seems to be part of the problem, since the time per call of those two functions is really low. |
My point is that the worst-case complexity of the current implementation is ϴ(n³), so it's not really the method call overhead that's doing it, it's just the sheer number of operations. When N = 3000, we have something like 1010 many "operations", and if each "operation" takes at least a couple of CPU cycles, then time starts to fly rather quickly. So I don't think there's any point in profiling the implementation. |
Indeed, just looking at the number of function calls (for N = 3000): Current implementation:
Alternative implementation:
That's 2833M vs 62M function calls. |
Yeah, that's what I meant but didn't articulate properly. The time cost is dominated by method call (and profiling) overhead due to the number of operations.
We'll see when we get around to rewriting the chapter. If @leios is comfortable enough letting you do this chapter rewrite, then please do take a few days to do it, and we'll review both the new code and the new chapter fairly. Although that has historically been a very long process. |
Bug Report
Description
The Python implementation in the stable marriage chapter is worst case ϴ(n³), but should be O(n²).
I have attached an alternative implementation that runs in worst-case quadratic time. I can make a PR if you want to replace the current algorithm.
Steps to Reproduce
Run the code with N = 3000.
Expected behavior
Terminate within seconds.
Screenshots
Additional context
For Algorithm Archive Developers
The text was updated successfully, but these errors were encountered: