无需第三方包使用R生成4节点所有DAG的简化实现方法咨询
解决方案
你的原有代码仅生成了所有可能的有向图(包含带环结构),并未过滤出合法的无环DAG,下面提供两个仅使用base R的优化方案:
方案1:精简现有逻辑+环过滤(保留expand.grid)
大幅压缩冗余的条件判断代码,同时补充环检测逻辑筛选合法DAG:
# 预定义所有无序节点对,对应6组边 node_pairs <- list(c(1,2), c(1,3), c(1,4), c(2,3), c(2,4), c(3,4)) n_nodes <- 4 # 生成所有边状态组合 all_states <- expand.grid(rep(list(c("A", "B", "C")), 6)) res <- list() # 环检测函数:输入邻接矩阵,返回TRUE代表为合法DAG is_dag <- function(adj) { power <- adj for (i in 2:n_nodes) { power <- power %*% adj if (any(diag(power) > 0)) return(FALSE) } return(TRUE) } for (i in seq_len(nrow(all_states))) { adj <- matrix(0, nrow = n_nodes, ncol = n_nodes) # 遍历6组边统一赋值 for (j in 1:6) { u <- node_pairs[[j]][1] v <- node_pairs[[j]][2] state <- all_states[i, j] if (state == "B") adj[u, v] <- 1 if (state == "C") adj[v, u] <- 1 } # 仅保留无环的DAG if (is_dag(adj)) res[[length(res)+1]] <- adj } # 4节点合法DAG共318种,可验证结果长度是否正确 length(res)
方案2:DFS递归实现(不使用expand.grid)
完全通过深度优先搜索生成所有边状态组合,符合你不想依赖内置expand.grid的需求:
n_nodes <- 4 node_pairs <- list(c(1,2), c(1,3), c(1,4), c(2,3), c(2,4), c(3,4)) res <- list() # 环检测函数与方案1一致 is_dag <- function(adj) { power <- adj for (i in 2:n_nodes) { power <- power %*% adj if (any(diag(power) > 0)) return(FALSE) } return(TRUE) } # DFS递归生成函数 dfs <- function(edge_idx, current_adj) { # 所有边赋值完成,检测是否为DAG if (edge_idx > length(node_pairs)) { if (is_dag(current_adj)) { res[[length(res)+1]] <<- current_adj } return() } u <- node_pairs[[edge_idx]][1] v <- node_pairs[[edge_idx]][2] # 状态A:无边,直接递归下一组边 dfs(edge_idx + 1, current_adj) # 状态B:u→v,赋值后递归再回溯 current_adj[u, v] <- 1 dfs(edge_idx + 1, current_adj) current_adj[u, v] <- 0 # 状态C:v→u,赋值后递归再回溯 current_adj[v, u] <- 1 dfs(edge_idx + 1, current_adj) current_adj[v, u] <- 0 } # 启动DFS遍历 dfs(1, matrix(0, nrow = n_nodes, ncol = n_nodes)) # 验证结果数量 length(res)
两种方案输出结果完全一致,均生成全部318种4节点合法DAG。
内容的提问来源于stack exchange,提问作者yining wang
相关产品推荐
相关产品推荐

