枚举所有可能连接的节点
enumerate all possible connected nodes
假设我有 100 个节点,然后我给每个节点一个来自 1:100 的唯一 ID。
如果我想要每个节点组合的列表,我相信它的长度会是 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
这是一个使用 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)
#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"
假设我有 100 个节点,然后我给每个节点一个来自 1:100 的唯一 ID。
如果我想要每个节点组合的列表,我相信它的长度会是 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
这是一个使用 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)
#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"