Skip to content

Conversation

@frankiegillis
Copy link
Contributor

This adds the function DigraphMinimumCutSet using the DigraphMaximumFlow method and the max-flow min-cut theorem. See issue #867.

…ough all triples of vertices, and instead checks center vertices of 2-edges
@mtorpey mtorpey added the WIP Label of PRs that are a Work In Progress (WIP) label Nov 5, 2025
Copy link
Collaborator

@reiniscirpons reiniscirpons left a 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.

Comment on lines +804 to +806
while not IsEmpty(Q) do
u := Q[1];
Remove(Q, 1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.

Comment on lines +809 to +811
if not outs[u][v] in S then
Add(Q, outs[u][v]);
Add(S, outs[u][v]);
Copy link
Collaborator

@reiniscirpons reiniscirpons Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WIP Label of PRs that are a Work In Progress (WIP)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants