生物医学网络科学Biomedical Network Science
Example09 / 10

空间嵌入与布线代价——距离惩罚生成模型 vs 度保持随机化

所属专题
脑连接组:结构与功能连接
下载
Notebook · .py

在单位立方体内随机放置 80 个“脑区”,按 P(i~j) ∝ exp(−d_ij/λ) 生成空间网络(布线倾向短程)。 比较三者的总布线长度 Σ d_ij 与平均聚集系数:空间网络、同度序列的随机重连网络、同边数 ER 网络。 输出解读:空间网络的布线长度远低于两种随机网络,聚集系数则更高—— 仅凭“节省布线”就能产生高聚集与模块化,因此用不保留空间信息的零模型检验脑网络的“小世界”会高估其特殊性。

Output输出图

空间嵌入与布线代价——距离惩罚生成模型 vs 度保持随机化:输出图 1

Output文字输出

空间网络    : 边数 = 320, 总布线长度 =   116.7, 平均聚集系数 = 0.215
度保持重连   : 边数 = 320, 总布线长度 =   203.0, 平均聚集系数 = 0.103
ER 随机网络 : 边数 = 320, 总布线长度 =   212.2, 平均聚集系数 = 0.092
空间网络中边长的中位数 = 0.35 ;全部节点对距离的中位数 = 0.675

Code代码

# 在单位立方体内随机放置 80 个“脑区”,按 P(i~j) ∝ exp(−d_ij/λ) 生成空间网络(布线倾向短程)。
# 比较三者的总布线长度 Σ d_ij 与平均聚集系数:空间网络、同度序列的随机重连网络、同边数 ER 网络。
# 输出解读:空间网络的布线长度远低于两种随机网络,聚集系数则更高——
# 仅凭“节省布线”就能产生高聚集与模块化,因此用不保留空间信息的零模型检验脑网络的“小世界”会高估其特殊性。
import numpy as np
import networkx as nx

rng = np.random.default_rng(11)               # 模拟数据,仅用于演示方法
N, m_target, lam = 80, 320, 0.15
pos = rng.uniform(0, 1, (N, 3))
D = np.linalg.norm(pos[:, None] - pos[None, :], axis=2)
iu = np.triu_indices(N, 1)
p = np.exp(-D[iu] / lam)
p /= p.sum()
chosen = rng.choice(len(p), m_target, replace=False, p=p)
G = nx.Graph()
G.add_nodes_from(range(N))
G.add_edges_from(zip(iu[0][chosen], iu[1][chosen]))

def wiring(G):
    return sum(D[u, v] for u, v in G.edges())

Gr = G.copy()
nx.double_edge_swap(Gr, nswap=10 * G.number_of_edges(), max_tries=10 ** 6, seed=1)
Ge = nx.gnm_random_graph(N, G.number_of_edges(), seed=2)
for name, H in [("空间网络", G), ("度保持重连", Gr), ("ER 随机网络", Ge)]:
    print(f"{name:8s}: 边数 = {H.number_of_edges()}, 总布线长度 = {wiring(H):7.1f}, "
          f"平均聚集系数 = {nx.average_clustering(H):.3f}")

lens = np.array([D[u, v] for u, v in G.edges()])
print("空间网络中边长的中位数 =", round(float(np.median(lens)), 3),
      ";全部节点对距离的中位数 =", round(float(np.median(D[iu])), 3))

import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
for u, v in G.edges():
    axes[0].plot(pos[[u, v], 0], pos[[u, v], 1], color="gray", lw=0.5, alpha=0.6)
axes[0].scatter(pos[:, 0], pos[:, 1], s=60, c=pos[:, 2], cmap="viridis", edgecolor="k", lw=0.3, zorder=3)
axes[0].set(xlabel="x", ylabel="y", title="Distance-penalised network (x-y projection)", aspect="equal")
bins = np.linspace(0, D.max(), 30)
for H, ls, lab in [(G, "-", "spatial model"), (Gr, "--", "degree-preserving rewired"), (Ge, ":", "ER random")]:
    axes[1].hist([D[u, v] for u, v in H.edges()], bins=bins, histtype="step", ls=ls, lw=2, label=lab)
axes[1].set(xlabel="Edge length (Euclidean)", ylabel="Number of edges", title="Spatial wiring favours short edges")
axes[1].legend(fontsize=8)
plt.tight_layout(); plt.show()

Run在浏览器中运行

首次加载 Python 环境约需 20–40 秒;可以修改参数后重新运行。

空间嵌入与布线代价——距离惩罚生成模型 vs 度保持随机化