降低算法的复杂度,从满足给定约束的无向图构建有向图DAG

问题描述

我有一个包含 4,000 多个节点的网络,并且我有一个边列表(节点对之间的连接)。所有节点都应该收敛到一个中心点,但我无法对节点进行排序,因为它们没有以可以重新排序的方式进行编号或标记。

我需要什么?:根据附上的小例子,我需要所有节点都指向节点F(F可以从所有节点到达),这样无向图就变成了有向图( DAG) 并且作为 限制,每个节点对之间只有一条边。当且仅当要删除循环(例如 A -> B、B

我拥有的是这个:

 library(igraph)
 library(tidygraph)
 library(ggraph)
 library(tidyverse)

 # edge list
 edgelist <- tribble(
  ~from,~to,"A","B","C","D","E","F")
 
 # create the graph
 g <- as_tbl_graph(edgelist)
 
 # undirected graph 
 g %>% 
  ggraph(layout = "graphopt") +
  geom_edge_link() +
  geom_node_point(shape = 21,size = 18,fill = 'white') +
  geom_node_text(aes(label = name),size = 3) +
  theme_graph() 

这是我想出的排序过程,以便边列表成为 DAG:

 s <- names(V(g))
 
 # define node objective
 target <- "F"
 
 # exclude target from vertex list
 vertex_list <- s[s != target]
 
 # calculate the simple path of each node to the destination node (target)
 route_list <- map(vertex_list,~ all_simple_paths(graph = g,from = .x,to = target)) %>% 
  set_names(vertex_list) %>% 
  map(~ map(.,~ names(.x))) %>%
  flatten() %>% 
  map(~ str_c(.x,collapse = ","))
 
 
 # generate the list of ordered edges
 ordered_edges <- do.call(rbind,route_list) %>% 
  as.data.frame(row.names = F) %>%  
  set_names("chain") %>% 
  group_by(chain) %>% 
  summarise(destination = str_split(chain,","),.groups = "drop") %>% 
  mutate(
   
   from = map(destination,~ lag(.x)) %>% 
    map(~ .x[!is.na(.x)]),to = map(destination,~ lead(.x)) %>% 
    map(~ .x[!is.na(.x)]),) %>% 
  
  select(from,to) %>% 
  unnest(cols = everything()) %>% 
  group_by(across(everything())) %>% 
  summarise(enlaces = n(),.groups = "drop") %>% 
  select(-enlaces)

警告:当节点数量达到一定大小(假设为 90)时,该算法会生成使图非循环的循环,因此我执行的附加程序是应用函数在 Python 中调用 feedback_arc_set 以删除将使图成为 DAG 的边。

为简单起见,我没有包含删除这些循环所需的代码,因为在这个特定示例中没有生成任何循环。

 # draw the graph again
 as_tbl_graph(ordered_edges) %>% 
  ggraph(layout = "graphopt") +
  geom_edge_link(arrow = arrow(length = unit(3,'mm'),type = "closed",angle = 30),end_cap = circle(7,'mm')) +
  geom_node_point(shape = 21,size = 3) +
  theme_graph() 

reprex package (v2.0.0) 于 2021 年 7 月 7 日创建

那么问题是什么?:当节点数大于2000时算法的复杂度

如果我尝试使用 2000 个节点来执行此操作,则算法永远不会结束。我让它运行了 24 小时,但它没有完成。事实上,我没有找到知道它是否有效的方法。在这个 place 中我发现 {igraph} all_simple_paths 的函数在幕后使用了 DFS,但是复杂度是 O (|V|!) 其中 |V|是顶点数和|V|!是顶点数的阶乘。

有没有办法以更低的复杂性做到这一点?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)