Вот другой подход. Хотя, вероятно, это не очень эффективный способ сделать это алгоритмически, он имеет преимущество в том, чтобы рисовать на быстрых процедурах нативных игр. Основная стратегия:
Найти все циклы длины 4
Найти все треугольники
Если цикл длины 4 делит 3 узла с треугольником, он не является аккордом, поэтому мы избавляемся от него и возвращаем то, что осталось.
Ниже приведена функция, затем мы можем проверить ее на простом для интерпретации искусственном графе и случайном графе:
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
}
}
Теперь давайте сгенерируем игрушечный график, где нам должно быть понятно, каким должен быть ожидаемый результат:
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)
Мы явно хотим, чтобы функция возвращала A-B-C-D, а не A-D-E-F:
getChordless4s(g)
#> [[1]]
#> [1] "A" "B" "C" "D"
Теперь давайте попробуем случайный график:
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"
Вероятно, есть какой-то опубликованный алгоритм эффективных способов поиска аккордовых циклов, и теперь мне было бы интересно узнать, что это такое. Забавная проблема.
Создано в 2018-05-09 пакетом представ (v0.2.0).