Reputation: 73
I am trying to count the number of chordless cycles of length four in an undirected graph using R (igraph
package).
This is my adyacency matrix (with '0' and integer numbers > 1, since it represents the number of shared objects between nodes):
0 8 4 10 7 11 1
3 1 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 5 0 2 0 1
9 0 1 1 0 0 1
This is the piece of code I have:
library(igraph)
A <- matrix(c(0L, 3L, 0L, 0L, 0L, 0L, 9L,
8L, 1L, 0L, 0L, 0L, 0L, 0L,
4L, 0L, 0L, 0L, 0L, 5L, 1L,
10L, 0L, 0L, 0L, 0L, 0L, 1L,
7L, 0L, 0L, 0L, 0L, 2L, 0L,
11L, 0L, 0L, 0L, 0L, 0L, 0L,
1L, 0L, 0L, 0L, 0L, 1L, 1L),
7, 7)
g <- graph.adjacency(A, mode = "undirected", diag=FALSE, weighted=TRUE)
Any help with this would be much appreciated!
Upvotes: 2
Views: 495
Reputation: 3429
TL;DR: the answer is 0, because the graph is cordal.
The graph itself looks like this:
From the look of this graph, I'm not very optimistic we will find a chordless cycle of length four. And this can be quickly confirmed by this command:
is.chordal(g)
It returns TRUE
, which means that this graph is chordal. In other words, "each of its cycles of four or more nodes has a chord".
I attempted anyway to enumerate all the chordless cycles of lenght 4. Since I don't know any smart way of doing it, I will do it with a few simpler steps:
Each of these steps can be performed with a function from the igraph
package.
res <- NULL
for (vi in V(g)) {
pi <- all_simple_paths(g, from=vi, to = V(g))
pi_4 <- pi[sapply(pi, length)==4]
last_v <- sapply(pi_4, "[", 4)
pi_4_c <- pi_4[sapply(last_v, function(v) are.connected(g, 1, v))]
subgi <- lapply(pi_4_c, function(v) induced.subgraph(g, v))
ci <- sapply(subgi, function(g) is_chordal(g)$chordal)
res[[vi]] <- subgi[!ci]
}
res_with_dupl <- data.frame(t(sapply(res, V)))
unique(res_with_dupl)
Again, the result is that there is no chordless cycle of length 4 in this graph (res
is empty).
I really look forward to reading the other answers!
Upvotes: 2
Reputation: 3647
Here is another approach. Although probably not a very efficient way to do it algorithmically, it has the merit of drawing on fast native igraph routines. The basic strategy is:
Find all cycles of length 4
Find all triangles
If a length-4 cycle shares 3 nodes with a triangle its not chordless so we get rid of it and return what's left.
Below is a function, then we can test it on a easy to interpret artificial graph, and a random graph:
library(igraph)
getChordless4s <- function(g) {
# Add names to save on annoyance later
if (is.null(names(V(g)))) {V(g)$name <- V(g)}
# We get all the triangles
tr <- triangles(g)
tr <- matrix(names(tr), nrow=length(tr)/3, byrow = T)
# Now we get all the cycles of length-4
g2 <- make_ring(4)
res <- subgraph_isomorphisms(pattern = g2, target = g)
# strip these to the node names and drop reduncancies
res <- unique(lapply(res, function(cyc){sort(names(cyc))}))
# If one of our triangles appears in a length-4 cycle than
# that cycle is not chordless.
# Test for this by checking if the length of the intersection of the vertex
# names of the 4-cycle and any triangle is 3.
res <- res[!unlist(lapply(res, function(cyc){any(apply(tr, 1, function(row){length(intersect(cyc, row))==3}))}))]
# Print anything we have if we have it
if (length(res)==0) {cat("No chordless cycles of length-4 found")} else {
res
}
}
Now lets generate a toy graph where we should be clear what the expected result should be:
g <- graph_from_data_frame(data.frame(from = c("A", "B", "C", "D", "A", "E", "E", "F"),
to = c("B", "C", "D", "A", "E", "D", "F", "D")),
directed = F)
plot(g)
We clearly want the function to return A-B-C-D and not A-D-E-F:
getChordless4s(g)
#> [[1]]
#> [1] "A" "B" "C" "D"
Now let's try a random graph:
set.seed(42)
g <- random.graph.game(10, .2)
plot(g)
# Check that there are chordless graphs to find
is.chordal(g)$chordal
#> [1] FALSE
getChordless4s(g)
#> [[1]]
#> [1] "2" "3" "7" "8"
#>
#> [[2]]
#> [1] "2" "3" "6" "7"
#>
#> [[3]]
#> [1] "2" "3" "5" "7"
#>
#> [[4]]
#> [1] "3" "5" "7" "8"
#>
#> [[5]]
#> [1] "3" "5" "6" "7"
There's probably some published algorithm on efficient ways of finding chordless cycles, and now I'd be curious to know what it is. Fun problem.
Created on 2018-05-09 by the reprex package (v0.2.0).
Upvotes: 2