Python小世界网络仿真图绘制求助:代码仅输出数值无图形
我来帮你搞定这个绘图问题!你的代码已经完成了核心的SARS传播仿真逻辑,但有两个关键问题需要解决:一是没有初始化小世界网络G,二是缺少论文中需要的可视化代码。下面是完整的修改后代码,同时我会解释每个新增/修正的部分:
完整修正代码
import matplotlib.pyplot as plt import numpy as np import networkx as nx import random # 修正邻居判断函数:适配N×N的网格节点(坐标0到N-1) def near_neighbours(node, N): res = [] x, y = node if x != 0: res.append((x-1, y)) if x != N-1: # 原代码这里是N,会超出节点坐标范围,修正为N-1 res.append((x+1,y)) if y != 0: res.append((x,y-1)) if y != N-1: # 同样修正为N-1 res.append((x,y+1)) return res # ---------------------- 1. 初始化小世界网络 ---------------------- N = 10 # 10×10网格,共100个节点 # 创建基础网格规则网络 G = nx.grid_2d_graph(N, N) # 添加小世界长程连接(模拟论文中的小世界模型) num_long_edges = int(N*N * 0.1) # 长程边数量设为节点数的10%,可调整 for _ in range(num_long_edges): u = random.choice(list(G.nodes())) v = random.choice(list(G.nodes())) # 避免自环和已经是网格邻居的节点 while u == v or v in near_neighbours(u, N): v = random.choice(list(G.nodes())) G.add_edge(u, v) # ---------------------- 2. 初始化状态 ---------------------- status = {} for node in G.nodes(): status[node] = 'S' # 随机感染一个节点 status[random.choice(list(G.nodes()))] = 'I' # 感染/康复参数(和原代码一致) p2 = 0.0 p1 = 0.1293 r0 = 1/11.2 r1 = 1/17.4 # 状态计数初始化 S = N * N - 1 E = 0 I = 1 R = 0 s = [] e = [] i = [] r = [] t = 0 time = [] graphs_in_time = [] # ---------------------- 3. 仿真循环 ---------------------- while I > 0: t += 1 newI = 0 newR = 0 newE = 0 for node in G.nodes(): if status[node] == 'I': for nei in G.neighbors(node): if status[nei] == 'S': if nei in near_neighbours(node, N): if random.random() < p1: newE += 1 status[nei] = 'E' else: if random.random() < p2: newE += 1 status[nei] = 'E' if random.random() < r1: newR += 1 status[node] = 'R' elif status[node] == 'E': if random.random() < r0: newI += 1 status[node] = 'I' # 更新状态计数 S -= newE E += (newE - newI) I += (newI - newR) R += newR # 记录关键时间点的状态 if t % 20 == 0: print(f't= {t} S, E, I, R, N = {S} {E} {I} {R} {S+E+I+R}') graphs_in_time.append({k: v for k, v in status.items()}) # 记录时间序列数据 s.append(S) i.append(I) r.append(R) e.append(E) time.append(t) # ---------------------- 4. 绘制疫情趋势曲线(对应论文核心图) ---------------------- plt.figure(figsize=(10, 6)) plt.plot(time, s, label='Susceptible (S)', color='blue', linewidth=2) plt.plot(time, e, label='Exposed (E)', color='orange', linewidth=2) plt.plot(time, i, label='Infected (I)', color='red', linewidth=2) plt.plot(time, r, label='Recovered (R)', color='green', linewidth=2) plt.xlabel('Time', fontsize=12) plt.ylabel('Number of Individuals', fontsize=12) plt.title('SARS Transmission Dynamics in Small-World Network', fontsize=14) plt.legend(fontsize=10) plt.grid(alpha=0.3) plt.show() # ---------------------- 5. 绘制不同时间点的网络状态可视化 ---------------------- num_plots = len(graphs_in_time) cols = 3 rows = (num_plots + cols - 1) // cols # 自动计算子图行数 fig, axes = plt.subplots(rows, cols, figsize=(15, 5*rows)) axes = axes.flatten() # 定义状态对应的颜色映射 color_map = {'S': 'blue', 'E': 'orange', 'I': 'red', 'R': 'green'} for idx, state_dict in enumerate(graphs_in_time): ax = axes[idx] # 获取每个节点的颜色 node_colors = [color_map[state_dict[node]] for node in G.nodes()] # 使用网格布局固定节点位置(贴合论文的网格可视化) pos = {(x, y): (x, y) for (x, y) in G.nodes()} nx.draw(G, pos, node_color=node_colors, node_size=200, ax=ax, with_labels=False, edge_color='gray') ax.set_title(f'Time = {20*(idx+1)}', fontsize=12) # 隐藏多余的空白子图 for ax in axes[num_plots:]: ax.axis('off') plt.tight_layout() plt.show()
关键修改说明
- 修正邻居判断函数:原代码中节点坐标判断错误(
x != N),导致访问不存在的节点,修正为x != N-1适配10×10的网格节点(坐标0-9)。 - 初始化小世界网络:添加了网格规则网络+随机长程边的创建逻辑,符合论文的小世界模型定义。
- 疫情趋势曲线:用matplotlib绘制S/E/I/R随时间变化的折线图,这是论文第1752页的核心动力学曲线。
- 网络状态可视化:在每20个时间点绘制一次网络节点状态,用颜色区分易感(蓝)、潜伏(橙)、感染(红)、康复(绿)节点,保持网格布局和论文的可视化风格一致。
运行这段代码后,你会先看到数值输出,然后自动弹出两个图形:一个是疫情传播的趋势曲线,另一个是不同时间点的网络状态演化图,和论文中的图形风格一致。
内容的提问来源于stack exchange,提问作者user9880140
相关产品推荐
相关产品推荐

