在networkx有向图中如何查找无出边的悬挂节点?
问题解答
一、NetworkX有向图悬挂节点(无出边节点)的判断方法
NetworkX的DiGraph对象提供了out_degree属性可以直接获取节点的出度,出度为0的节点就是你要找的悬挂节点:
- 单个节点判断:
if G.out_degree(node) == 0:即可确认该节点是悬挂节点 - 批量获取所有悬挂节点的列表,直接替换你代码里的空列表赋值行即可:
list_of_dangl = [node for node in G.nodes if G.out_degree(node) == 0]
你现有代码的else分支逻辑可以简化,不需要遍历统计边数,也不需要取边对象再提取目标节点,直接用successors方法就能拿到所有出边指向的节点:
# 替换else内的原有逻辑 neighbours = list(G.successors(currNode)) if not neighbours: # 当前是悬挂节点,直接触发随机跳转 currNode = rand.choice(list(G.nodes)) else: currNode = rand.choice(neighbours) list_of_nodes.append(currNode)
二、不依赖NetworkX内置PageRank的实现方案
1. 随机游走版(你当前方案的优化版)
核心逻辑是遇到悬挂节点直接触发全局随机跳转,避免无出边时的逻辑错误,完整参考代码:
import random as rand import networkx as nx from collections import Counter def randomSurf(G, moves, damping=0.15): all_nodes = list(G.nodes) currNode = rand.choice(all_nodes) list_of_nodes = [currNode] # 提前缓存悬挂节点集合,查询效率更高 dangling_nodes = {node for node in all_nodes if G.out_degree(node) == 0} for _ in range(moves-1): # 要么触发阻尼随机跳转,要么当前是悬挂节点也触发跳转 if rand.random() <= damping or currNode in dangling_nodes: currNode = rand.choice(all_nodes) else: # 随机选一个后继节点 currNode = rand.choice(list(G.successors(currNode))) list_of_nodes.append(currNode) # 可选:统计节点访问频率得到PageRank得分 # rank = {k: v/moves for k,v in Counter(list_of_nodes).items()} return list_of_nodes
2. 矩阵迭代版(收敛更快,适合中小规模图)
仅用numpy实现PageRank核心逻辑,不依赖NetworkX内置方法:
import numpy as np import networkx as nx def matrix_pagerank(G, damping=0.15, max_iter=100, tol=1e-6): n = G.number_of_nodes() node_list = list(G.nodes) node_to_idx = {node:i for i, node in enumerate(node_list)} # 构造转移矩阵M M = np.zeros((n, n)) for u in G.nodes: out_edges = list(G.successors(u)) if not out_edges: # 悬挂节点的出边均匀指向所有节点 M[node_to_idx[u], :] = 1/n else: for v in out_edges: M[node_to_idx[u], node_to_idx[v]] = 1/len(out_edges) # 引入阻尼因子修正转移矩阵 M = (1 - damping) * M + damping / n # 迭代计算rank向量直到收敛 pr = np.ones(n) / n for _ in range(max_iter): new_pr = pr @ M if np.linalg.norm(new_pr - pr) < tol: break pr = new_pr # 转换为节点到得分的映射返回 return {node_list[i]: pr[i] for i in range(n)}
内容的提问来源于stack exchange,提问作者EleBeth
相关产品推荐
相关产品推荐

