-
Notifications
You must be signed in to change notification settings - Fork 61
Added DigraphMinimumCutSet
#879
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
base: main
Are you sure you want to change the base?
Conversation
…ough all triples of vertices, and instead checks center vertices of 2-edges
…2EdgeTransitive has multiple edges to doc
reiniscirpons
left a comment
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.
Thanks for the contribution, looks solid, some suggestions for docs and performance above, mostly minor.
In addition to the comments above, it looks like doc for the function is not linked in the manual, you should add
<#Include Label="DigraphMinimumCut">to z-chap5.xml in the appropriate location to get your documentation to show up in the manual (you can test this by seeing if ?DigraphMinimumCut finds the doc inside of gap).
I would also suggest changing the name of the function to DigraphMinimumCut since what its computing is the cut not the cut-set (see the definitions in https://en.wikipedia.org/wiki/Max-flow_min-cut_theorem#Cuts). It might also be good to implement a separate DigraphMinimumCutSet which wraps your current function and computes the edges.
| while not IsEmpty(Q) do | ||
| u := Q[1]; | ||
| Remove(Q, 1); |
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.
| while not IsEmpty(Q) do | |
| u := Q[1]; | |
| Remove(Q, 1); | |
| while i <= Length(Q) do | |
| u := Q[i]; |
Removing an element from the front of a list is an O(n) operation, which gets called every loop. A slight improvement would be to, instead of removing the front element, to just maintain an index i, and at the start of iteration of the while loop to just take the i-th element from Q (constant time), and then increment i at the end of the loop (also constant time). This means that Q will grow to be slightly bigger, but since it wont ever exceed the number of vertices in D, this is not a problem.
Its a rather minor optimization since almost certainly most of the time spent by this function will be taken by the DigraphMaximumFlow function, but still good to not leave performance on the table.
| if not outs[u][v] in S then | ||
| Add(Q, outs[u][v]); | ||
| Add(S, outs[u][v]); |
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.
| if not outs[u][v] in S then | |
| Add(Q, outs[u][v]); | |
| Add(S, outs[u][v]); | |
| if not seen[outs[u][v]] then | |
| Add(Q, outs[u][v]); | |
| seen[outs[u][v]] = true; |
Another minor optimization: you are adding to the list S, which means it will be an unordered list, hence the lookup outs[u][v] in S will take O(n) time.
GAP provides the AddSet function, which adds an element while maintaining the an ordering on the elements of a list. So if you used AddSet(S, outs[u][v]); instead, the lookup time would go down to something like O(log(n)) I think. But in general the AddSet function may be quite slow too (don't know complexity off the top of my head, certainly no more than linear).
However, if you used a boolean list (blist) seen instead, initializing it as seen = BlistList(DigraphVertices(D), []) before entering the while loop, this would create a boolean list consisting of false for every vertex in D, so we would pay a one-time upfront cost of O(n). But for this, we can now check if a vertex has already been visited in constant time (since its just a lookup seen[outs[u][v]] to check if the stored entry is true or false), and you can update the set of seen vertices in constant time (since its just an assignment seen[outs[u][v]] = true in a list without needing to increase the size of the list (since seen was initialized for every vertex already)). See https://docs.gap-system.org/doc/ref/chap22_mj.html for more info on boolean lists.
Same as before, minor optimization but worth making.
This adds the function
DigraphMinimumCutSetusing theDigraphMaximumFlowmethod and the max-flow min-cut theorem. See issue #867.