I need a working algorithm for finding all simple cycles in an undirected graph. I know the cost can be exponential and the problem is NP-complete, but I am going to use it in a small graph (up to 20-30 vertices) and the cycles are small in number.
After a long research (mainly here) I still don't have a working approach. Here is a summary of my search:
Finding all cycles in an undirected graph
Cycles in an Undirected Graph -> detects only whether there is a cycle or not
Finding polygons within an undirected Graph -> very nice description, but no solution
Finding all cycles in a directed graph -> finds cycles only in directed graphs
Detect cycles in undirected graph using boost graph library
The only answer I found, which approaches my problem, is this one:
Find all cycles in graph, redux
It seems that finding a basic set of cycles and XOR-ing them could do the trick. Finding a basic set of cycles is easy, but I don't understand how to combine them in order to obtain all cycles in the graph...
Inspired by @LetterRip and @Axel Kemper Here is a shorter version of Java:
It seems that the cycle finder above has some problems. The C# version fails to find some cycles. My graph is:
For example, the cycle:
1-9-3-12-5-10
is not found. I tried the C++ version as well, it returns very large (tens of millions) number of cycles which is apparently wrong. Probably, it fails to match the cycles.Sorry, I am in a bit of crunch and I have not investigated further. I wrote my own version based on post of Nikolay Ognyanov (thank you very much for your post). For the graph above my version returns 8833 cycles and I am trying to verify that it is correct. The C# version returns 8397 cycles.
Here is a node version of the python code.
The following is a demo implementation in C# (and Java, see end of answer) based on depth first search.
An outer loop scans all nodes of the graph and starts a search from every node. Node neighbours (according to the list of edges) are added to the cycle path. Recursion ends if no more non-visited neighbours can be added. A new cycle is found if the path is longer than two nodes and the next neighbour is the start of the path. To avoid duplicate cycles, the cycles are normalized by rotating the smallest node to the start. Cycles in inverted ordering are also taken into account.
This is just a naive implementation. The classical paper is: Donald B. Johnson. Finding all the elementary circuits of a directed graph. SIAM J. Comput., 4(1):77–84, 1975.
A recent survey of modern algorithms can be found here
The cycles for the demo graph:
The algorithm coded in Java: