Skip to content

Conversation

ffloresbrito
Copy link
Contributor

@ffloresbrito ffloresbrito commented Nov 1, 2017

Edit: ( @reiniscirpons ): the current implementation seems have some bug and it fails on DigraphFromGraph6String("HoStIv{") (this is Graph 33668 on house of graphs). The expected output is 4, currently the method gives 3. My hunch is that the bug may be in the Edmonds-Karp method. It seems PR #584 implements a max-flow method, so once this is merged, we may be able to fix this PR as well.

Hopefully within the next 7 years we will be able to merge this PR!


Original comment:
This pull request adds an attribute called VertexConnectivity which for a graph G = (V, E) computes the least cardinality |S| of a subset S of V, such that G - S is either disconnected, is trivial, or has no vertices. Documentation and tests are included.

Copy link
Collaborator

@wilfwilson wilfwilson left a comment

Choose a reason for hiding this comment

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

A few more fairly minor comments. I've still not studied the algorithm in detail, to see whether you're implementing it correctly. Not sure whether I will. Maybe @james-d-mitchell knows more about the algorithm and could weigh in?

wilfwilson
wilfwilson previously approved these changes Nov 1, 2017
Copy link
Member

@james-d-mitchell james-d-mitchell left a comment

Choose a reason for hiding this comment

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

This looks quite reasonable, apart from some design decisions that are likely rather costly (in terms of time and space). I'd like to see the code in this PR refactored to remove these things.

@james-d-mitchell james-d-mitchell added enhancement A label for PRs that provide enhancements. do not merge A label for PRs that should not be merged for whatever reason. 0.12 and removed 0.11 labels Nov 21, 2017
@wilfwilson wilfwilson added 0.13 and removed 0.12 labels Jan 31, 2018
@wilfwilson wilfwilson added 0.14 and removed 0.13 labels Sep 18, 2018
@wilfwilson wilfwilson added 0.15 and removed 0.14 labels Nov 23, 2018
@wilfwilson
Copy link
Collaborator

@james-d-mitchell Did @ffloresbrito address your changes? Is @ffloresbrito still involved in any GAP-related activity?

@wilfwilson wilfwilson removed the 0.15 label Aug 22, 2019
@wilfwilson wilfwilson changed the title add VertexConnectivity Add VertexConnectivity Mar 3, 2021
@wilfwilson wilfwilson force-pushed the vertex-connectivity branch from de81d16 to b27af13 Compare March 3, 2021 16:55
@wilfwilson
Copy link
Collaborator

@james-d-mitchell I have squashed and rebased this PR on the latest master branch, and fixed the CI errors, and pushed. Assuming that @ffloresbrito is no longer involved with this, we can now decide how to proceed with this PR (or whether just to just close it).

On the whole, I'd say it's better to have a slow implementation than no implementation - it could always be a student project to improve or rewrite it. But that assumes that this implementation is correct, and it's been long enough that I don't remember if it is. So I'll review it again sometime.

@wilfwilson wilfwilson force-pushed the vertex-connectivity branch 2 times, most recently from 7671666 to f26545c Compare March 3, 2021 18:48
@digraphs digraphs deleted a comment from codecov bot Mar 3, 2021
@wilfwilson wilfwilson force-pushed the vertex-connectivity branch 2 times, most recently from 5b55e83 to 7aa5e9d Compare March 10, 2021 07:53
Copy link
Collaborator

@wilfwilson wilfwilson left a comment

Choose a reason for hiding this comment

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

I accidentally marked a comment from James as resolved, but it's not. It basically said:

You should add a citation to the documentation, stating where this algorithm is taken from.

@wilfwilson wilfwilson dismissed james-d-mitchell’s stale review March 10, 2021 13:10

Looks like all of the specific changes that James asked for were made.

@wilfwilson wilfwilson self-assigned this Mar 10, 2021
@wilfwilson wilfwilson force-pushed the vertex-connectivity branch from e21ba66 to da6864e Compare May 26, 2021 19:35
@digraphs digraphs deleted a comment from github-actions bot Aug 26, 2024
Copy link
Contributor

@MeikeWeiss MeikeWeiss left a comment

Choose a reason for hiding this comment

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

For us this method would be very helpful. I looked at the algorithm and the implementation and to me it looks like a useful implementation of vertex connectivity.
In my opinion two parts are written a bit awkwardly as you can see below. Is there anything else that needs to be done apart from adding a citation to the documentation?

gap/attr.gi Outdated
mindeg := degs[i];
mindegv := i;
fi;
od;
Copy link
Contributor

@MeikeWeiss MeikeWeiss Aug 27, 2024

Choose a reason for hiding this comment

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

I think mindegv:=PositionMinimum(degs) andmindeg:=degs[mindegv] should do the same and is an easier computation and easier to read.

degs[j] := degs[j] + 1;
fi;
od;
od;
Copy link
Contributor

@MeikeWeiss MeikeWeiss Aug 27, 2024

Choose a reason for hiding this comment

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

It should be also possible to compute degs with OutDegrees and InDegrees such that it is maybe shorter and easier to read.

@james-d-mitchell james-d-mitchell removed the do not merge A label for PRs that should not be merged for whatever reason. label Aug 30, 2024
@wilfwilson
Copy link
Collaborator

Thanks for your review last year @MeikeWeiss. I'll have a look at reviewing and hopefully merging this, once and for all.

For now I'll rebase on main and fix any merge conflicts and CI errors.

@wilfwilson
Copy link
Collaborator

The method currently seems to have a bug:

testing: /tmp/gaproot/pkg/Digraphs/tst/standard/attr.tst
########> Diff in /tmp/gaproot/pkg/Digraphs/tst/standard/attr.tst:
3152
# Input is:
VertexConnectivity(D);
# Expected output:
4
# But found:
3
########
    4903 ms (366 ms GC) and 1.16GB allocated for attr.tst

The correct answer is indeed 4 (as proved by brute force, according to some additional lines that I've since added to the test).

@reiniscirpons
Copy link
Collaborator

reiniscirpons commented Sep 27, 2025

To add my 2 cents:

  1. I think the error is most likely in the edmondskarp method for computing maximum flows. As of Edge weights #5: maximum flow #751, however we have our own implementation of maximum flow computations, so I think it would make sense to just replace the edmondskarp call with calls to DigraphMaximumFlow. Note that due to the differences in output format, the total flow would be given by calling Sum(DigraphMaximumFlow(digraph, start, destination)[start]) as per the docs.

  2. The way that Algorithm 9 from [1] is implemented, a new graph (via the newnetw function) is constructed for every call to edmondskarp. This is how Algorithm 9 is described in [1], but its a bit wasteful, since each constructed graph is almost identical to every other constructed graph. In fact in the book [2] that Algorithm 9 is taken from, only a single augmented graph is constructed, see the proof of Theorem 6.4:

If the original digraph $D = (V, E)$ has no loops or multiple edges, then construct the graph $\overline{D}$ by letting the vertex set $V(\overline{D} ) = V' \cup V''$ where $V'$ and $V''$ are formal copies of vertices in $V$, so that if $v\in V$ then $v' \in V$ and $v''\in V''$ are the corresponding copies of vetices, and let the edge set be given by
$$E(\overline{D}) = \lbrace (v', v'') : v \in V \rbrace \cup \lbrace (u'', v') : (u, v) \in E \rbrace.$$
Essentially each vertex $v$ gets split into 2 vertices an "in" vertex $v'$ and and "out" vertex $v''$ - all in-edges of $v$ go into $v'$ and all out-edges of $v$ leave from $v''$.

It follows from this theorem that, instead of computing the max-flow with source $u$ and target $v$ in the graph newnetw(D, u, v) as is currently done in the algorithm, we can compute the max-flow with source $u''$ and target $v'$ in the graph $\overline{D}$ instead. This means that we only need to compute the single graph $\overline{D}$ instead of the $O(n^2)$ newnetw graphs as it's done currently.

I'll have a crack at making these changes if thats ok with you @wilfwilson

[1] https://www.cse.msu.edu/~cse835/Papers/Graph_connectivity_revised.pdf
[2] https://www.cambridge.org/core/books/graph-algorithms/8B295BD0845A174FFE6B2CD6D4B2C63F

@wilfwilson
Copy link
Collaborator

Please do, @reiniscirpons! Be my guest. Thank you very much.

What you describe sounds smart.

@reiniscirpons
Copy link
Collaborator

Ok I think I fixed the bug. The new DigraphMaximumFlow function made it quite easy, the actual function is not too long, but I included quite a lot of verbose comments to justify what is going on. Happy to remove later on.

There are still a few questions that should be resolved (currently down as TODOs in the source), namely:

  1. Should we rename the function from VertexConnectivity to DigraphVertexConnectivity? This would be more in line with other digraphs functions.
  2. Should we change the convention for vertex-connectivity of the complete graphs? At the moment we follow the wikipedia definition (https://en.wikipedia.org/wiki/Connectivity_(graph_theory)), see also (https://mathworld.wolfram.com/VertexConnectivity.html), which imply that VertexConnectivity(CompleteDigraph(n)) == n-1. This has the potentially confusing consequence that for the singleton digraph, VertexConnectivity(Digraph([[]])) == 0 but at the same time IsConnectedDigraph(Digraph([[]])) == true. Similarly, because of the convention, VertexConnectivity(CycleDigraph(2)) == 1 and yet IsBiconnectedDigraph(CycleDigraph(2)) == true. The reason we need a convention in the first place is that the simple definition for vertex connectivity - "the least set of vertices whose removal disconnects the digraph" - works for all digraphs except for the complete ones. This is because no set of vertices you remove from a complete digraph disconnects it, unless you count the empty digraph as disconnected (which has its own set of issues). To quote the MathWorld article the convention VertexConnectivity(CompleteDigraph(n)) == n-1 "allows most general results about connectivity to remain valid on complete graphs (West 2001, p. 149)". Other reasonable choices would be VertexConnectivity(CompleteDigraph(n)) == n (this would implicitly make us assume that the empty digraph is not connected) or VertexConnectivity(CompleteDigraph(n)) == infinity (indicating that no set of vertices disconnects the graph, but of course now you need to deal with infinities in your computations). At the moment I take the n-1 convention and just explain the issues with connectivity and biconnectivity for the singleton and 2-cycle in the docs.
  3. To speed up the computation we can remove loops and multiple edges, furthermore we need to symmetrize the graph. At the moment I check if the graph has loops, multiple edges or is not symmetric and if either condition holds then I do all three modifications if any condition holds. In theory I could also test each separately and then perform the change or somehow incorporate all of these modifications when constructing the doubled_digraph digraph. See line 3386 in attr.gi. Might also be premature optimizations, this probably doesn't take too much time when compared to the max-flow computations. Should we optimize these graph modifications?
  4. I need to check adjacency for quite a lot of vertices (we only run a max-flow on non-adjacent vertices), at worst I will need to look at every pair of vertices, I'm currently using DigraphAdjacencyFunction(digraph) for this, is there a better way of checking for adjacency?

@wilfwilson could you give the code a review, when you have the chance? Thanks!

wilfwilson
wilfwilson previously approved these changes Oct 1, 2025
Copy link
Collaborator

@wilfwilson wilfwilson left a comment

Choose a reason for hiding this comment

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

This is looking good, thank you for working on it.

Perhaps to avoid any weirdness we could only define vertex connectivity for digraphs with at least two vertices? (Or whatever the relevant number would be to avoid the weird cases).

I'm happy with the file having lengthy comments, they're harmless and potentially helpful!

I've got a few suggestions that I've commented directly on the code.

@wilfwilson
Copy link
Collaborator

@reiniscirpons In response to your specific questions above, here are my answers:

  1. Yes
  2. I don't mind.
  3. I think it'd be easy enough to do these separately:
multi := IsMultiDigraph(D);
loops := DigraphHasLoops(D);
nsymm := not IsSymmetricDigraph(D);

if multi or loops or nsymm then
  D := DigraphMutableCopy(D);
  if multi then
    DigraphRemoveAllMultipleEdges(D);
  fi;
  if loops then
    DigraphRemoveLoops(D);
  fi;
  if nsymm then
    DigraphSymmetricClosure(D);
  fi;
  MakeImmutable(D);
fi;
  1. I commented about this directly on the code.

@reiniscirpons
Copy link
Collaborator

reiniscirpons commented Oct 2, 2025

@wilfwilson thanks for the comments! I've made the changes requested, good catch on improving the adjacency checks and the changes to the loop and multiple edge removal logic. I renamed the method and variables. I ended up not changing the behavior on complete graphs because its not all that confusing and is also the convention used in literature anyway, but I did update the docs to be more clear about the caveats for small graphs.

Should be good to merge if the CI passes unless someone else has anything to add!

@wilfwilson
Copy link
Collaborator

Thanks so much!

Goodbye to the final pull request with a two-digit number 😢

@wilfwilson wilfwilson merged commit 303b27d into digraphs:main Oct 3, 2025
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement A label for PRs that provide enhancements.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants