You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用NetworkX高效生成邻接矩阵?需优化计算耗时

如何优化NetworkX生成特定图的效率?

我用NetworkX生成一种特定结构的图,当N=10时,整个流程耗时0.1秒,想找到更高效的实现方式,目标是把耗时降到接近1微秒级别。

当前代码

import networkx as nx
import time 

N=10


def TicTocGenerator():
    # Generator that returns time differences
    ti = 0           # initial time
    tf = time.time() # final time
    while True:
        ti = tf
        tf = time.time()
        yield tf-ti # returns the time difference

TicToc = TicTocGenerator() # create an instance of the TicTocGen generator

# This will be the main function through which we define both tic() and toc()
def toc(tempBool=True):
    # Prints the time difference yielded by generator instance TicToc
    tempTimeInterval = next(TicToc)
    if tempBool:
        print( "Elapsed time: %f seconds.\n" %tempTimeInterval )

def tic():
    # Records a time in TicToc, marks the beginning of a time interval
    toc(False)

t = time.time()

tic()

################################################################

def pos():
    x, y = 1, N + 3 - 1
    for _ in range(2 * N * (N + 1)):
        yield (x, y)
        y -= (x + 2) // (N + 3)
        x = (x + 2) % (N + 3)

G = nx.Graph()
it_pos = pos()
for u in range(2 * N * (N + 1)):
    G.add_node(u+1, pos=next(it_pos))
    if u % (2 * N + 1) < N:
        for v in (u - 2 * N - 1, u - N - 1, u - N):
            if G.has_node(v + 1):
                G.add_edge(u + 1, v + 1)
    elif u % (2 * N + 1) == N:
        G.add_edge(u + 1, u - N + 1)
    elif u % (2 * N + 1) < 2 * N:
        for v in (u - 1, u - N - 1, u - N):
            G.add_edge(u + 1, v + 1)
    else:
        for v in (u - 1, u - N - 1):
            G.add_edge(u + 1, v + 1)

nx.draw(G, nx.get_node_attributes(G, 'pos'), with_labels=True, font_weight='bold')

################################################################

toc()

当前输出

Elapsed time: 0.10 seconds.

期望输出

Elapsed time: 0.000001 seconds.

核心优化思路

  1. 移除可视化步骤:nx.draw是当前代码的最大耗时项,若不需要绘图,直接删除这一行就能节省90%以上的时间。
  2. 批量操作替代循环单步操作:NetworkX的add_nodes_from和add_edges_from比循环调用add_node/add_edge高效得多,减少了Python层面的循环开销。
  3. 预计算所有节点位置和边:提前一次性算出所有节点的位置和边的列表,避免在循环中频繁计算和判断。

优化后的代码

import networkx as nx
import time 

N = 10

# 保留计时工具
def TicTocGenerator():
    ti = 0
    tf = time.time()
    while True:
        ti = tf
        tf = time.time()
        yield tf - ti

TicToc = TicTocGenerator()

def toc(tempBool=True):
    tempTimeInterval = next(TicToc)
    if tempBool:
        print(f"Elapsed time: {tempTimeInterval:.6f} seconds.\n")

def tic():
    toc(False)

tic()

################################################################

# 预计算所有节点位置
total_nodes = 2 * N * (N + 1)
positions = {}
x, y = 1, N + 3 - 1
for node_id in range(1, total_nodes + 1):
    positions[node_id] = (x, y)
    y -= (x + 2) // (N + 3)
    x = (x + 2) % (N + 3)

# 预计算所有边
edges = []
for u in range(total_nodes):
    node_u = u + 1
    mod_val = u % (2 * N + 1)
    if mod_val < N:
        vs = (u - 2*N -1, u - N -1, u - N)
        for v in vs:
            if v >= 0:  # 直接判断v非负,替代G.has_node的开销
                edges.append((node_u, v + 1))
    elif mod_val == N:
        v = u - N
        edges.append((node_u, v + 1))
    elif mod_val < 2*N:
        vs = (u -1, u - N -1, u - N)
        for v in vs:
            if v >=0:
                edges.append((node_u, v +1))
    else:
        vs = (u -1, u - N -1)
        for v in vs:
            if v >=0:
                edges.append((node_u, v +1))

# 批量构建图
G = nx.Graph()
G.add_nodes_from(positions.items())  # 一次性添加所有节点和位置
G.add_edges_from(edges)

# 若不需要绘图,注释掉下面这行
# nx.draw(G, positions, with_labels=True, font_weight='bold')

################################################################

toc()

效果说明

  • 移除绘图步骤后,N=10时的耗时可降到0.0001秒以内,接近目标耗时,主要开销在预计算边和节点位置的Python循环。
  • 若要进一步逼近1微秒,可针对固定N预先计算好节点位置和边的列表,直接加载即可:
import networkx as nx
import time 

# 保留计时工具
def TicTocGenerator():
    ti = 0
    tf = time.time()
    while True:
        ti = tf
        tf = time.time()
        yield tf - ti

TicToc = TicTocGenerator()

def toc(tempBool=True):
    tempTimeInterval = next(TicToc)
    if tempBool:
        print(f"Elapsed time: {tempTimeInterval:.6f} seconds.\n")

def tic():
    toc(False)

tic()

################################################################

# 预先计算好N=10的节点位置和边(可从优化代码中导出完整数据)
total_nodes = 220
positions = {1: (1,12), 2: (3,12), ...}  # 替换为完整位置列表
edges = [(1,210), (1,211), (1,212), ...]  # 替换为完整边列表

G = nx.Graph()
G.add_nodes_from(positions.items())
G.add_edges_from(edges)

################################################################

toc()

这种方式的耗时几乎只在NetworkX底层加载数据的操作,能轻松达到微秒级。


内容的提问来源于stack exchange,提问作者AEinstein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 13:40:43