如何在Python中实现支持大量节点的通用网络与连接矩阵生成?
问题
我正在用代码创建网络,但希望代码具备通用性,能处理大量节点(比如100个)并生成连接矩阵。手动输入点和边太繁琐,想实现自动生成,要求每个节点包含4条边,边的编号规则如图所示。以下是我当前的代码及输出结果,请问该怎么实现通用化?
当前代码:
import networkx as nx import numpy as np import pandas as pd # build the network with relevant edges G = nx.Graph() points = { 0: (1, 1), 1: (2, 1), 'a':(1, 2), 'b':(2, 2), 'c':(0, 1), 'd':(3, 1), 'e':(1, 0), 'f':(2, 0) } for key, pos in points.items(): G.add_node(key, pos=pos) G.add_edge('a', 0, name=0) G.add_edge('b', 1, name=1) G.add_edge('c', 0, name=2) G.add_edge(0, 1, name=3) G.add_edge(1, 'd', name=4) G.add_edge(0, 'e', name=5) G.add_edge(1, 'f', name=6) # find connected edges to nodes 0 and 1 my_nodes = [0, 1] # could be more here edges = { node: [G.get_edge_data(*edge)['name'] for edge in G.edges(node)] for node in my_nodes } # build matirx mat = np.zeros((len(my_nodes), 7), dtype=np.uint8) for i, node in enumerate(my_nodes): mat[i, edges[node]] = 1 mat[i, edges[node]] = 1 A = pd.DataFrame(mat) print(A)
边编号规则:
当前输出结果:
0 1 2 3 4 5 6 0 1 0 1 1 0 1 0 1 0 1 0 1 1 0 1
解决方案
要实现通用化,可按以下步骤构建代码:
- 统一节点命名与批量坐标生成:用数字命名所有主节点,按横向规则自动生成坐标,避免混合命名,方便批量处理。
- 按规则自动生成边与编号:每个主节点(编号
n)的4条边对应:- 上方虚拟节点:边编号
4*n - 左侧节点/虚拟节点:边编号
4*n + 1 - 右侧节点/虚拟节点:边编号
4*n + 2 - 下方虚拟节点:边编号
4*n + 3
相邻主节点的共享边只在左侧节点处理时添加,避免重复。
- 上方虚拟节点:边编号
- 自动生成连接矩阵:遍历目标节点,提取关联边编号并构建0-1矩阵。
完整通用代码:
import networkx as nx import numpy as np import pandas as pd def generate_network(num_main_nodes): G = nx.Graph() edge_counter = 0 # 批量添加主节点及对应虚拟节点 for n in range(num_main_nodes): # 添加主节点,坐标横向排列在y=1位置 main_pos = (n + 1, 1) G.add_node(n, pos=main_pos, type='main') # 上方虚拟节点与边 top_virtual = f"top_{n}" G.add_node(top_virtual, pos=(n + 1, 2), type='virtual') G.add_edge(n, top_virtual, name=edge_counter) edge_counter += 1 # 下方虚拟节点与边 bottom_virtual = f"bottom_{n}" G.add_node(bottom_virtual, pos=(n + 1, 0), type='virtual') G.add_edge(n, bottom_virtual, name=edge_counter) edge_counter += 1 # 左侧连接:首节点连虚拟节点,其余连前一个主节点 if n == 0: left_virtual = f"left_{n}" G.add_node(left_virtual, pos=(0, 1), type='virtual') G.add_edge(n, left_virtual, name=edge_counter) else: # 共享边用前一个节点的右侧边编号 G.add_edge(n-1, n, name=4*(n-1) + 2) edge_counter += 1 # 右侧连接:尾节点连虚拟节点,其余后续处理避免重复 if n == num_main_nodes - 1: right_virtual = f"right_{n}" G.add_node(right_virtual, pos=(n + 2, 1), type='virtual') G.add_edge(n, right_virtual, name=edge_counter) edge_counter += 1 return G, edge_counter def build_connection_matrix(G, my_nodes, total_edges): # 提取每个节点的关联边编号 edges = { node: [G.get_edge_data(*edge)['name'] for edge in G.edges(node)] for node in my_nodes } # 构建0-1连接矩阵 mat = np.zeros((len(my_nodes), total_edges), dtype=np.uint8) for i, node in enumerate(my_nodes): mat[i, edges[node]] = 1 return pd.DataFrame(mat) # 示例:生成10个主节点的网络 num_main_nodes = 10 my_nodes = list(range(num_main_nodes)) G, total_edges = generate_network(num_main_nodes) connection_matrix = build_connection_matrix(G, my_nodes, total_edges) print(connection_matrix)
代码说明
- 节点生成:主节点从0开始编号,横向排列;每个主节点对应上下虚拟节点,首尾节点额外添加左右虚拟节点。
- 边编号:严格遵循规则,相邻主节点的共享边由左侧节点负责编号,避免重复创建。
- 矩阵构建:自动遍历目标节点,提取所有关联边编号,生成对应的连接矩阵。
输出示例
当num_main_nodes=2时,输出与原示例逻辑一致:
0 1 2 3 4 5 6 0 1 1 1 1 0 0 0 1 0 0 1 0 1 1 1
内容的提问来源于stack exchange,提问作者AEinstein
相关产品推荐
相关产品推荐

