考虑到形成一个具有各种特性的网络,希望形成一个具有小世界性、无标度性和分层性的网络,通过先构建这个网络的初始化,然后实现了一个具有层次性、偏好连接(无标度性)的小世界性网络模型,并通过模拟网络的演化过程来构建网络,最后对网络的性质进行研究。
1.主要流程及实现
主要目标是生成一个复杂网络,并计算其一些关键特性。这个过程可以分为以下几个步骤:
初始化网络:使用initialize_network(n)函数创建一个环形网络,其中每个节点都与其相邻的节点相连。
网络演化:使用evolve_network(G, n, m, hierarchy_level, hierarchy_nodes, p)函数进行网络演化。在每一步中,都会添加一个新节点,然后进行偏好连接和层次性连接。
偏好连接:使用preferential_attachment(G, new_node, m)函数实现偏好连接机制,即新节点更倾向于连接到度数较大的节点。这是通过计算每个节点的度数占总度数的比例,然后根据这个比例随机选择m个节点进行连接来实现的。
层次性连接:使用hierarchical_attachment(G, new_node, hierarchy_level, hierarchy_nodes)函数实现层次性连接机制,即新节点只能连接到某个层次以下的节点。这是通过在指定的层次范围内随机选择节点进行连接来实现的。每个层次的设置为30个节点。
在添加节点后,如果网络不再连通,会打印出警告信息。在网络达到一定规模时,会显示当前的网络和邻接矩阵。
计算网络特性:在网络演化完成后,计算了一些网络的特性,包括度序列、度分布、平均聚类系数、邻接矩阵、无标度性、小世界性和层次性。这些特性可以帮助我们更好地理解网络的结构和演化过程。
度序列:节点的度是指与其相连的边的数量。度序列是网络中所有节点度的列表。
度分布:度分布是网络中各个度的节点的数量。
平均聚类系数:聚类系数是一个测量节点的邻居之间连接密度的指标。平均聚类系数是网络中所有节点聚类系数的平均值。
邻接矩阵:邻接矩阵是一个二维数组,其中的元素表示相应节点之间是否存在边。
无标度性:无标度性是指网络的度分布遵循幂律分布,即少数节点有很高的度,而大多数节点的度很低。
小世界性:小世界网络是指网络的平均路径长度很短,而聚类系数很高。
层次性:层次性是指网络的节点可以被分成多个层次,每个层次的节点数量不同。
2.实现代码
码使用了networkx库来创建和操作网络,numpy库来进行数值计算,matplotlib.pyplot库来显示网络,以及scipy.sparse库来创建稀疏矩阵。
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from scipy.sparse import csr_matrix
import pandas as pd
# 初始化网络
def initialize_network(n):
G = nx.Graph()
for i in range(n):
G.add_edge(i, (i + 1) % n)
return G
# 偏好连接
def preferential_attachment(G, new_node, m):
degrees = list(G.degree())
total_degree = sum(dd for _, dd in degrees)
probabilities = [dd / total_degree for _, dd in degrees]
chosen_nodes = np.random.choice(
list(G.nodes()),
size=min(m, len(G.nodes())),
p=probabilities,
replace=True
)
for node in chosen_nodes:
if not G.has_edge(new_node, node):
G.add_edge(new_node, node)
# 层次性连接
def hierarchical_attachment(G, new_node, hierarchy_level, hierarchy_nodes):
for _ in range(hierarchy_level):
node = np.random.randint(0, hierarchy_nodes)
G.add_edge(new_node, node)
def display_network_and_matrix(G, title, i, hierarchy_nodes):
print(title)
node_layers = {node: node // hierarchy_nodes for node in G.nodes()}
colors = [node_layers[node] for node in G.nodes()]
nx.draw(G, with_labels=True, node_color=colors, cmap=plt.cm.Blues)
plt.show()
sparse_matrix = nx.adjacency_matrix(G)
df = pd.DataFrame(sparse_matrix.toarray())
df.to_excel(f'sparse_matrix{i+1}.xlsx')
print(sparse_matrix.toarray())
# 网络演化机制
def evolve_network(G, n, m, hierarchy_level, hierarchy_nodes, p):
for i in range(n, total_nodes):
new_node = i
G.add_node(new_node)
hierarchical_attachment(G, new_node, hierarchy_level, hierarchy_nodes)
preferential_attachment(G, new_node, m)
if not nx.is_connected(G):
print("添加节点时网络未连通:", new_node)
if i + 1 in [15, 30, 45, 60, 75, 90]:
display_network_and_matrix(G, f"网络有 {i + 1} 节点时", i, hierarchy_nodes)
initial_nodes = 10
total_nodes = 90
m = 3
hierarchy_level = 2
hierarchy_nodes = 30
p = 0.01
G = initialize_network(initial_nodes)
nx.draw(G, with_labels=True)
plt.show()
evolve_network(G, initial_nodes, m, hierarchy_level, hierarchy_nodes, p)
# 计算网络特性
degree_sequence = sorted([degree for _, degree in G.degree()], reverse=True)
degree_distribution = {node: degree for node, degree in G.degree()}
average_clustering = nx.average_clustering(G)
print("度序列:", degree_sequence)
print("度分布:", degree_distribution)
print("平均聚类:", average_clustering)
sparse_matrix = nx.adjacency_matrix(G)
print("最终网络的稀疏矩阵:\n", sparse_matrix.toarray())
degree_sequence = sorted([degree for _, degree in G.degree()], reverse=True)
degree_sum = sum(degree_sequence)
degree_probabilities = [degree / degree_sum for degree in degree_sequence]
log_degree_probabilities = np.log10(degree_probabilities)
log_degrees = np.log10(range(1, len(degree_sequence) + 1))
slope, intercept = np.polyfit(log_degrees, log_degree_probabilities, 1)
scaling_exponent = -slope
print("幂律分布:", scaling_exponent)
average_shortest_path_length = nx.average_shortest_path_length(G)
clustering_coefficient = nx.average_clustering(G)
print("平均最短路径长度:", average_shortest_path_length)
print("平均聚类系数:", clustering_coefficient)
node_layers = {node: node // hierarchy_nodes for node in G.nodes()}
layer_sizes = {layer: sum(1 for node in G.nodes() if node_layers[node] == layer) for layer in set(node_layers.values())}
print("每层的节点数:", layer_sizes)
3.结果
度序列: [49, 48, 47, 46, 46, 45, 45, 44, 42, 42, 40, 40, 38, 38, 37, 36, 36, 36, 36, 34, 33, 32, 32, 30, 29, 28, 28, 27, 25, 20, 20, 13, 13, 13, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
度分布: {0: 36, 1: 38, 2: 47, 3: 33, 4: 42, 5: 20, 6: 30, 7: 40, 8: 36, 9: 34, 10: 38, 28: 45, 29: 37, 11: 28, 12: 32, 25: 29, 13: 46, 26: 48, 14: 44, 24: 32, 15: 28, 16: 27, 17: 25, 21: 42, 18: 45, 19: 49, 22: 46, 20: 36, 23: 36, 27: 40, 30: 12, 31: 6, 32: 9, 33: 8, 34: 6, 35: 9, 36: 13, 37: 9, 38: 7, 39: 12, 40: 9, 41: 11, 42: 11, 43: 7, 44: 20, 45: 6, 46: 9, 47: 9, 48: 8, 49: 11, 50: 6, 51: 8, 52: 8, 53: 5, 54: 7, 55: 6, 56: 5, 57: 9, 58: 7, 59: 9, 60: 12, 61: 10, 62: 8, 63: 7, 64: 8, 65: 11, 66: 9, 67: 9, 68: 6, 69: 7, 70: 7, 71: 7, 72: 6, 73: 8, 74: 5, 75: 7, 76: 10, 77: 8, 78: 12, 79: 4, 80: 10, 81: 6, 82: 6, 83: 11, 84: 9, 85: 7, 86: 5, 87: 7, 88: 6, 89: 5, 90: 9, 91: 13, 92: 6, 93: 6, 94: 6, 95: 8, 96: 9, 97: 12, 98: 5, 99: 6, 100: 11, 101: 6, 102: 8, 103: 6, 104: 6, 105: 8, 106: 9, 107: 6, 108: 13, 109: 9, 110: 10, 111: 7, 112: 6, 113: 5, 114: 6, 115: 6, 116: 6, 117: 10, 118: 6, 119: 6, 120: 5, 121: 5, 122: 5, 123: 6, 124: 6, 125: 7, 126: 8, 127: 7, 128: 5, 129: 7, 130: 6, 131: 5, 132: 5, 133: 8, 134: 6, 135: 5, 136: 7, 137: 8, 138: 6, 139: 5, 140: 6, 141: 8, 142: 7, 143: 6, 144: 6, 145: 5, 146: 6, 147: 7, 148: 4, 149: 6, 150: 7, 151: 8, 152: 9, 153: 5, 154: 6, 155: 5, 156: 8, 157: 8, 158: 5, 159: 6, 160: 7, 161: 8, 162: 5, 163: 6, 164: 6, 165: 4, 166: 6, 167: 5, 168: 6, 169: 5, 170: 6, 171: 7, 172: 5, 173: 4, 174: 7, 175: 6, 176: 5, 177: 6, 178: 5, 179: 6, 180: 5, 181: 5, 182: 6, 183: 5, 184: 6, 185: 6, 186: 6, 187: 5, 188: 6, 189: 6, 190: 7, 191: 5, 192: 4, 193: 4, 194: 6, 195: 6, 196: 5, 197: 6, 198: 6, 199: 6, 200: 5, 201: 5, 202: 7, 203: 5, 204: 6, 205: 5, 206: 5, 207: 5, 208: 6, 209: 5, 210: 4, 211: 5, 212: 8, 213: 6, 214: 7, 215: 5, 216: 5, 217: 5, 218: 4, 219: 5, 220: 4, 221: 5, 222: 5, 223: 5, 224: 7, 225: 6, 226: 6, 227: 7, 228: 5, 229: 5, 230: 5, 231: 4, 232: 5, 233: 5, 234: 5, 235: 6, 236: 5, 237: 5, 238: 5, 239: 5, 240: 5, 241: 5, 242: 5, 243: 5, 244: 5, 245: 5, 246: 5, 247: 5, 248: 5, 249: 5, 250: 5, 251: 5, 252: 5, 253: 5, 254: 5, 255: 5, 256: 5, 257: 5, 258: 5, 259: 5, 260: 5, 261: 5, 262: 5, 263: 5, 264: 5, 265: 5, 266: 5, 267: 6, 268: 5, 269: 6, 270: 5, 271: 5, 272: 5, 273: 5, 274: 5, 275: 4, 276: 5, 277: 5, 278: 5, 279: 5, 280: 6, 281: 4, 282: 4, 283: 5, 284: 5, 285: 5, 286: 5, 287: 5, 288: 5, 289: 5, 290: 4, 291: 5, 292: 5, 293: 5, 294: 5, 295: 5, 296: 5, 297: 5, 298: 5, 299: 5}
平均聚类: 0.11799806017464197
最终网络的稀疏矩阵:
[[0 1 0 ... 0 1 0]
[1 0 1 ... 0 0 0]
[0 1 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[1 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]
幂律分布: 0.5926734274713935
平均最短路径长度: 2.5320624303233
平均聚类系数: 0.11799806017464197
每层的节点数: {0: 30, 1: 30, 2: 30, 3: 30, 4: 30, 5: 30, 6: 30, 7: 30, 8: 30, 9: 30}
4.特性及结果分析
无标度性: 网络的度分布幂律指数为0.5926734274713935,小于2,表明网络展现出无标度特性,即少数节点拥有非常多的连接,而大多数节点连接较少。
小世界性: 网络的平均最短路径长度较短为2.5320624303233,表明网络中任意两个节点之间的距离不远,这是小世界模型的特征。
层次性: 网络的设计确保了每层有相同数量的节点,也就是30个。
聚类系数: 聚类系数为0.11799806017464197,比较高,表现出网络的平均聚类系数可以反映网络的社区结构,高聚类系数表明网络可能存在明显的社区结构。
5.结果可视化
这里使用networkx和matplotlib简单绘制图形。分别为初始化的环形图,以及节点数量分别为15,30,45,60,75,90个时的复杂网络图。
这些复杂网络图形很简单,建议使用Gephi进行优化和特性分析等。
随写内容属于个人见解,不足之处请指正。
此外,这里简单介绍Gephi这个软件。Gephi是专门用于进行复杂网络可视化和分析的软件,之前的文章有关于Gephi下载配置的,Gephi小白下载过程。再安装一个布局插件Network Splitter 3D,该插件的具体使用方法网上查询之后很多,这里不再赘述,还可使用其他插件或方法,比如Isometric Layout插件也可以。