Skip to content
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

Graphs: isCyclic Digraph sometimes fails to detect cycles #3626

Open
taboege opened this issue Jan 16, 2025 · 1 comment
Open

Graphs: isCyclic Digraph sometimes fails to detect cycles #3626

taboege opened this issue Jan 16, 2025 · 1 comment

Comments

@taboege
Copy link
Contributor

taboege commented Jan 16, 2025

The Graphs package has a method isCyclic to detect whether a Digraph contains a directed cycle. It often works:

isCyclic digraph({{1,2},{2,3},{3,1}}) --> true (correct)
isCyclic digraph({{1,2},{2,3},{3,4},{4,3}}) --> true (correct)
isCyclic digraph({{1,2},{2,3},{3,4},{2,4},{3,4}}) --> false (correct)

But on other small examples, it fails, reporting a graph as acyclic when it has a cycle

isCyclic digraph({{1,3},{1,4},{2,4},{3,2},{4,3}}) --> false (incorrect: 2 -> 4 -> 3 -> 2)
taboege added a commit to taboege/M2 that referenced this issue Jan 17, 2025
This fixes the detection of cycles in directed graphs (see issue Macaulay2#3626) by
not relying on the numbers from DFS but by attempting a topological sort.
It succeeds if and only if the graph is acyclic. This reuses existing code
as much as possible.

Also added tests that document previous bugs which are now fixed.
taboege added a commit to taboege/M2 that referenced this issue Jan 17, 2025
This fixes the detection of cycles in directed graphs (see issue Macaulay2#3626) by
not relying on the numbers from DFS but by attempting a topological sort.
It succeeds if and only if the graph is acyclic. This reuses existing code
as much as possible.

Also added tests that document previous bugs which are now fixed.
@taboege
Copy link
Contributor Author

taboege commented Jan 17, 2025

The implementation of isCyclic currently relies on depthFirstSearch which records a discovery time and a finishing time for each vertex. However, these numbers cannot distinguish between a cyclic and an acyclic graph:

E = {{1,3},{1,4},{3,2},{4,3}};
-- The two hash tables are equal:
print depthFirstSearch(digraph(E)); -- acyclic
print depthFirstSearch(digraph(E|{{2,4}})); -- cyclic

Here, the edge {2,4} creates a cycle but because of the (chance) order in which DFS visits the nodes (in my case 1 -> 4 -> 3 -> 2), that edge has no influence on the discovery and finishing times. Cycle detection has to happen during the DFS traversal.

The topologicalSort implementation actually contains all the gears to detect cycles. I'll post a pull request which uses that instead of DFS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant