-
Notifications
You must be signed in to change notification settings - Fork 68
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
Implement complement for undirected graphs #237
Implement complement for undirected graphs #237
Conversation
@gabrielelana @sphaso Thank you! :) Could you estimate the complexity of your implementation in terms of time and memory, as well as the size of the resulting expression? I suspect it can only handle very small graphs because of the repeated use of expensive Of course, having an expensive algorithm is much better than having none, so I'm still happy to merge your PR, but I'd like to document the complexity.
I think the answer is Yes because we don't rule out self-loops. It is not entirely clear how |
Hi @snowleopard , thanks for getting back :)
If you deem
We were indeed a bit puzzled by loops, because then one might start thinking about multigraphs, and the property As you said, an expensive algorithm is better than none, so we're happy to analyze the complexity of |
It's linear w.r.t. to the size of the graph expression, which is quite expensive: http://hackage.haskell.org/package/algebraic-graphs-0.4/docs/Algebra-Graph.html#v:removeEdge
I think filtering existing edges may indeed be faster, although it would be nice to do some benchmarking. Could you compare your approach with
The basic
Why don't you simply leave self-loops as is, without removing them? As far as I can see, this is the simplest option.
Great, please do! And some benchmarking would be nice too: I'm curious how your current implementation based on |
I feel there might be a critical piece of information regarding this library I'm missing. The problem I see is that:
So the situation is: I want We'll work on the benchmark ASAP. |
Hi @snowleopard , Here you can find the benchmark code. For easier reference, these are the two differing implementations. We took some time to calculate the complexity of the faster one as well as handling loops: complement :: Ord a => Graph a -> Graph a
complement g@(UG _) = overlay (edges loops) $ foldr (uncurry removeEdge) (cliqueG g) previousEdges
where cliqueG = clique . vertexList
previousEdges = edgeList g
loops = filter (uncurry (==)) previousEdges
-- Complexity: /O(E^2+V)/ time, /O(E+V)/ memory where
-- E is the number of edges and V is the number of vertices
-- The quadratic bound is due to `edges`.
complement' :: Ord a => Graph a -> Graph a
complement' g@(UG _) = overlay (vertices allVertices) (edges complementEdges)
where cliqueG = clique . vertexList
allVertices = vertexList g
previousEdges = edgeList g
loops = filter (uncurry (==)) previousEdges
complementEdges = loops ++ (edgeList (cliqueG g) \\ previousEdges) We were curious about the time complexity of What do you think? If you like our implementation we'll move it to the current PR. |
@sphaso Great, thank you for doing this!
Yes, http://hackage.haskell.org/package/algebraic-graphs-0.4/docs/Algebra-Graph.html#v:edges Did you expect its complexity to be non-linear?
Yes, let's use the faster implementation based on Responding to your earlier comment: yes, I think what you call "re-applying" will work. Conceptually, it's not very complex: you complement all non-loop edges and make sure to keep the original self-loops in the final graph. |
Regarding benchmarks: there is a separate repository for benchmarks, which you can find here: |
When estimating the complexity of
We'll adjust our estimates of |
@sphaso Oh, that's just wrong. If you correct it to "Complexity: O(L) time, memory and size, where L is the length of the given list." right in this PR that would be great! |
@snowleopard we ported the faster implementation and amended the complexity of |
@gabrielelana Many thanks! The implementation looks good, but see my comments regarding the docs; they should be easy to address. |
@snowleopard I should have addressed all the points you mentioned in the latest comments. Good catch on the quadratic complexity! |
@sphaso Thanks for the fixes! The result doesn't seem completely right though, please see my comments. |
@snowleopard I pushed a new commit that takes care of at least one concern, see my answer above for the other (time \ memory estimates, for which I already updated it as |
@sphaso Indeed :-) Thanks! |
@snowleopard hopefully I got everything right this time :) thanks! |
@sphaso Thank you, merged! :) By the way, feel free to add yourself and @gabrielelana to the list of contributors: https://github.com/snowleopard/alga/blob/master/AUTHORS.md |
Regarding the last tests we don't know if it's ok for Arbitrary to generate graphs with loops
Fixes #21
Proudly made by @sphaso and @gabrielelana at "Open Source Saturday Milano"