-
Notifications
You must be signed in to change notification settings - Fork 145
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
Generate all connected subgraphs of size k #1104
Conversation
Pull Request Test Coverage Report for Build 8126957629Details
💛 - Coveralls |
Awesome! Looking forward to review this |
Thanks for reviewing this - this is my first rustworkx and also rust contribution so let me know if you have general remarks! :-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a couple of Rust comments. The iterative vs recursion one is the hardest one to deal with but in general we avoid deeply nested recursion in the library.
src/connectivity/subgraphs.rs
Outdated
while graph.node_count() >= max(k, 1) { | ||
let mut p: HashSet<NodeIndex> = HashSet::new(); | ||
let v: NodeIndex = graph.node_indices().next().unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd use while let
to avoid having the .unwrap()
. Then you can come the if
to break the loop early at the end
src/connectivity/subgraphs.rs
Outdated
while x.is_empty().not() { | ||
let u: NodeIndex = x.iter().next().cloned().unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another good place for while let to avoid .unwrap()
@sbrandhsn I have thought more about the iterative version and I think it is achievable. Here is the pseudocode for it in Python:
I hope that helps, I know the original paper only gave a recursive version |
Thanks for your comments! :-) I wasn't aware of For the five 64 bit arguments and a stack size of 1 MB, the stack depth (and Lemma 4 in https://www.uni-marburg.de/de/fb12/arbeitsgruppen/algorith/paper/enucon.pdf actually introduces an iterative version. I will look into that version to see if I can implement it in reasonable time (as it improves the runtime asymptotically) and otherwise use your pseudo code. :-) |
I don't think we need to emit a warning. At first before rewriting the algorithm wasn't obvious that the bound in the recursion depth is the number of nodes of the graph. If the bound was the number of subgraphs though reaching 25000 is trivial so I had to ask. I think for the first version the recursive version is ok. The iterative version would be slightly faster and more consistent with most of the code we had. But the final version will hopefully something that we can parallelize (and it does not need to come in this version!) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am going to merge this version, I think it is correct and will bring a lot of benefits. We can think about parallelization and other improvements later
This PR addresses #1068
Here, a method for generating all connected subgraphs of a certain size
k
is developed based on the work in "Enumerating Connected Induced Subgraphs: Improved Delay and Experimental Comparison". Christian Komusiewicz and Frank Sommer. Compared to the brute-force approach of drawing all combinations ofk=3..6
nodes and then checking whether this combination is a connected subgraph, the method demonstrates a runtime speedup of two orders of magnitude as seen in the following figure. The evaluated graph is a heavy-hex graph of distanced=1, 3, 5, ..., 99
.Raw data: raw_data.txt