11
$\begingroup$

I am doing a research on networks which consists of polygons with different number of sides. I am trying to find all simple cycles in a network which are chordless. As an example, consider the following graph:

graph = Graph[
  {
    1 <-> 2,   2 <-> 3,   3 <-> 4,  4 <-> 5,   5 <-> 6,   1 <-> 6,  
    3 <-> 7,   7 <-> 8,   8 <-> 9,  9 <-> 10, 10 <-> 11, 11 <-> 3,
    4 <-> 12, 12 <-> 13, 13 <-> 11
  }, 
    VertexLabels -> "Name"
]

enter image description here

{1,2,3,4,5,6}, {3,4,11,12,13},{3,7,8,9,10,11} are rings and we can extract them:

cycles = FindFundamentalCycles[graph];
rings = Sort @* VertexList @* Graph /@ cycles  

enter image description here

But the above solution doesn't always work as it might give non-chordless cycles. Consider the following example:

grapht = Graph[
{
  1 <-> 2, 1 <-> 3, 2 <-> 4, 4 <-> 5, 5 <-> 6, 4 <-> 6, 
  6 <-> 7, 3 <-> 5, 3 <-> 9, 5 <-> 8, 8 <-> 9
},
VertexLabels -> "Name"];

enter image description here

Rings (cycles) are:

cyclest = FindFundamentalCycles[grapht]; 
HighlightGraph[grapht, #] & /@ cyclest

enter image description here

But I need to get {4,5,6} as a ring not {1,2,3,4,5,6} since there is an edge in the latter. Is there any way to filter out only chordless cycles?


W Community crosspost

$\endgroup$
0

3 Answers 3

5
$\begingroup$

First, let us find all cycles in the graph. Then, we will filter out the ones that contain chords; this we can detect by checking if the $n$-vertex induced subgraph is isomorphic to a cycle of length $n$ or not.

Let us use your graph as an example:

g = Graph[{1 <-> 2, 1 <-> 3, 2 <-> 4, 4 <-> 5, 5 <-> 6, 4 <-> 6, 
   6 <-> 7, 3 <-> 5, 3 <-> 9, 5 <-> 8, 8 <-> 9}, 
  VertexLabels -> "Name"];

cy = VertexList[Graph[#]] & /@ FindCycle[g, Infinity, All];
Select[cy, IsomorphicGraphQ[CycleGraph[Length[#]], Subgraph[g, #]] &]
(* {{4, 5, 6}, {5, 8, 9, 3}, {1, 2, 4, 5, 3}} *)

HighlightGraph[g, %]

Of course, if you have additional constraints, you can simply modify the call to FindCycle with different parameters to only find cycles of length e.g. of size 5, 6, 7, or 8. To achieve this, just do FindCycle[g, {5, 8}, All] instead.

$\endgroup$
2
  • $\begingroup$ This seems to work like a charm! A huge thank! $\endgroup$
    – Mahdi
    Commented Mar 22, 2015 at 19:42
  • $\begingroup$ Although, I found that this doesn't work in Mathematica 9 mostly because of FindCycle. $\endgroup$
    – Mahdi
    Commented Apr 3, 2015 at 5:59
9
$\begingroup$

Here's a weird way to find chordless cycles in V12+: convert the Graph into a Molecule and query for the set of smallest rings.

Your example:

grapht = Graph[
{
  1 <-> 2, 1 <-> 3, 2 <-> 4, 4 <-> 5, 5 <-> 6, 4 <-> 6, 
  6 <-> 7, 3 <-> 5, 3 <-> 9, 5 <-> 8, 8 <-> 9
},
VertexLabels -> "Name"];

rings = Molecule[grapht]["SmallestSetOfSmallestRings"]
{{1, 2, 4, 5, 3}, {6, 5, 4}, {8, 9, 3, 5}}
HighlightGraph[grapht, PathGraph[Append[#, First[#]]]] & /@ rings

enter image description here

Now it seems a graph with vertex degree greater than 4 can't become a molecule, but we can work around this with a hidden option. I've packed this into a function:

ChordlessRings[g_?GraphQ] :=
  Block[{mol, rings},
    mol = Quiet[Molecule[IndexGraph[g], "GraphValenceRules" -> {_ -> "C"}]];
    (
      rings = mol["SmallestSetOfSmallestRings"];

      rings /; ListQ[rings]

    ) /; MoleculeQ[mol]
  ]

ChordlessRings[___] = $Failed;

A larger example:

SeedRandom[4];
vm = VoronoiMesh[RandomReal[{-1, 1}, {100, 2}], {{-1, 1}, {-1, 1}}];
g = PlanarGraph[MeshCells[vm, 1][[All, 1]], VertexSize -> Large]

(rings = ChordlessRings[g]) // Length
100
HighlightGraph[g, PathGraph[Append[#, First[#]]]] & /@ rings[[1 ;; 5]]

enter image description here

Graphics @ GraphicsComplex[
  GraphEmbedding[g], 
  {EdgeForm[Black], {RandomColor[Hue[_]], Polygon[#]} & /@ rings}
]

Or we can ensure no 2 adjacent faces share the same color:

Block[{Print}, << IGraphM`]

imat = SparseArray[Join @@ MapIndexed[Thread[Thread[{First[#2], #1}] -> 1] &, rings]];
faceadj = Unitize[imat.Transpose[imat]];
faceconn = SimpleGraph@AdjacencyGraph[faceadj];

colors = IGMinimumVertexColoring[faceconn];

Graphics @ GraphicsComplex[
  GraphEmbedding[g], 
  {EdgeForm[Black], MapThread[{ColorData[112, #2], Polygon[#]} &, {rings, colors}]}
]

$\endgroup$
12
  • $\begingroup$ What's amusing about this solution is that it very likely uses an external method in RDKit which will probably then call back into a graph-theory library. Interesting the way the library calls chain. $\endgroup$
    – b3m2a1
    Commented Dec 17, 2019 at 22:34
  • $\begingroup$ In the Voronoi example you show, the outer face is also a chordless cycle, isn't it? But it's not returned by ChordlessRings. $\endgroup$
    – Szabolcs
    Commented Dec 18, 2019 at 13:42
  • 1
    $\begingroup$ I think I'll leave my answer though since I find the method amusingly absurd. $\endgroup$
    – Greg Hurst
    Commented Dec 18, 2019 at 13:50
  • 1
    $\begingroup$ I am not sure what the exact definition of "SmallestSetOfSmallestRings" is, but I notice that the number of results it returns is the dimension of the cycle basis. So perhaps it finds a minimal cycle basis? $\endgroup$
    – Szabolcs
    Commented Dec 18, 2019 at 14:05
  • 1
    $\begingroup$ @CATrevillian The coloring was just randomly chosen with RandomColor[Hue[_]]. I added an example showing a proper 4 coloring. See my latest edit. $\endgroup$
    – Greg Hurst
    Commented Dec 18, 2019 at 17:17
4
$\begingroup$

IGraph/M may help with this.

IGLADFindSubisomorphisms can look for induced subgraphs, and you are looking for induced cycles.

We can construct a function like this:

Needs["IGraphM`"]
chordlessCycles[graph_?UndirectedGraphQ] := 
  Join @@ Table[
    DeleteDuplicatesBy[Sort]@Values@IGLADFindSubisomorphisms[CycleGraph[k], graph, "Induced" -> True], 
    {k, IGGirth[graph], VertexCount[graph]}
  ]

This function will look for cycles of all sizes starting with the girth up to the vertex count. For your graph, it returns

chordlessCycles[graph]
(* {{3, 4, 12, 13, 11}, {1, 6, 5, 4, 3, 2}, {3, 7, 8, 9, 10, 11}} *) 

Beware that in general there may be a very large number of induced cycles. Stealing Chip's graph generation code, here's an example:

SeedRandom[4];
vm = VoronoiMesh[RandomReal[{-1, 1}, {10, 2}], {{-1, 1}, {-1, 1}}];
g = PlanarGraph[MeshCells[vm, 1][[All, 1]], VertexSize -> Large]

enter image description here

cycle[vlist_] := PathGraph[Append[vlist, First[vlist]]]

HighlightGraph[g, cycle[#], GraphHighlightStyle -> "Thick", 
   ImageSize -> 60] & /@ chordlessCycles[g]

enter image description here

$\endgroup$
3
  • 2
    $\begingroup$ I was going to use IGFaces but noticed it didn't find the 5 cycle in OP's problematic example, e.g. HighlightGraph[grapht, UndirectedEdge @@@ Partition[#, 2, 1, 1]] & /@ IGFaces[grapht]. Why is this? $\endgroup$
    – Greg Hurst
    Commented Dec 18, 2019 at 12:53
  • $\begingroup$ @ChipHurst You're right, finding faces may not be a good method at all, perhaps unless the graph is planar and 3-vertex-connected, in which case its embedding is unique. This graph is not 3-connected, even after removing that dangling part. To get an idea of the embedding that IGraph/M is considering here, take a look at IGLayoutPlanar[grapht]. In that embedding, the 5 cycle is not a face. $\endgroup$
    – Szabolcs
    Commented Dec 18, 2019 at 13:35
  • $\begingroup$ I removed the suggestion to use IGFaces. It was not a good one, for other reasons too: some chordless cycles cannot be faces in any embedding. $\endgroup$
    – Szabolcs
    Commented Dec 18, 2019 at 13:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.