перечислить все возможные подключенные узлы - PullRequest
1 голос
/ 08 мая 2020

Допустим, у меня 100 узлов, тогда я даю каждому уникальный идентификатор от 1: 100.

Если бы мне нужен был список всех комбинаций узлов, я полагаю, что он имел бы длину 2^100. Это если какой-либо узел может отсутствовать на схеме.

Но скажем, у меня есть фрейм данных, который представляет соединения между узлами:

head(conn_)
  from  to
2    1   2
3    1   4
4    2   3
5    2   5
6    4   6
7  154 100
8  102 101

, поэтому в первой строке этого df указано, что существует соединение от узла 11 к узлу 10

Допустим, я хочу перечислить каждую комбинацию допустимых узлов, но комбинация действительна только в том случае, если между элементами набора нет разорванной связи. Как я мог это сделать?

Например, если у меня есть узлы 1->2->3->4->5->6->7->8->9, где -> представляет двустороннее соединение (1 подключается к 2, а 2 подключается к 1), тогда два действительных подмножества будут быть {1, 2, 3} & {4, 5, 6}, но недопустимым подмножеством будет {1, 3, 4, 6}. Это было бы недопустимо, потому что между двумя элементами в наборе разорвано соединение.

Если один узел подключается к нескольким другим узлам, это считается допустимым соединением, то есть для фрейма данных выше у меня может быть действительный набор {1, 2, 4, 6}

У меня действительно тяжелые времена пытаясь выяснить способ сделать это рекурсивно или с помощью циклов for / while.

Кроме того, если существует максимум пять двусторонних соединений на узел, в случае 100 узлов, то можно ли перечислить все? Как эта проблема разрастается?

редактировать:

Вот пример ввода / вывода:

conn_ =
  from  to
     1   2
     1   4
     2   3
     2   5
     4   6

Expected output : { {1}, {1, 2}, {1, 4}, {1, 2, 4}, {1, 2, 3}, {1, 2, 5}, {1, 4, 6}, {1, 2, 4, 6}, {1, 2, 3, 4}, {1, 2, 3, 4, 6}, {1, 2, 3, 4, 5, 6}, {2}, {2, 3}, {2, 5}, {2, 3, 5}, {3}, {4}, {4, 6} }

Примечание {1, 3, 5} отсутствует на выходе, потому что не может быть разрыва между элементами в наборе, но {1, 2, 4, 6} действительно, потому что 1 подключается к 2, а 1 подключается к 4

1 Ответ

2 голосов
/ 08 мая 2020

Вот решение с igraph. Это быстро исчерпает ваши ресурсы для больших графов с высокой связностью.

В основном, мы ищем все пути из каждой вершины. Это даст нам каждую комбинацию дважды, поэтому в конце мы разбиваем ее на уникальные комбинации. Кто-то, кто разбирается в графиках больше, чем я, может создать более эффективное решение.

DF <- read.table(text = "from  to
     1   2
     1   4
     2   3
     2   5
     4   6", header = TRUE)

library(igraph)

g <- graph_from_data_frame(DF, directed = FALSE)
plot(g)

plot of the graph

#all paths starting from each vertex
paths <- unlist(lapply(V(g), function(from) all_simple_paths(g, from)), FALSE)

res <- lapply(paths, names) #extract vertex names from each path
res <- c(as.list(names(V(g))), res)  #add single vertices
res <- lapply(res, sort) #sort
res <- res[!duplicated(res)] #remove duplicates
#for compact printing:
unname(sapply(res, paste, collapse = ","))
#[1] "1"         "2"         "4"         "3"         "5"         "6"         "1,2"       "1,2,3"     "1,2,5"     "1,4"       "1,4,6"     "1,2,4"     "1,2,4,6"   "2,3"      
#[15] "2,5"       "1,2,3,4"   "1,2,4,5"   "4,6"       "1,2,3,4,6" "2,3,5"     "1,2,4,5,6"
...