本文目录导读:

我来为您介绍如何使用NetworkX进行网络演化分析,包含多个实用案例。
基础网络演化模型
1 随机网络演化(ER模型)
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation
# 随机图演化过程
def random_graph_evolution(n_initial=5, n_max=50, p=0.1):
"""
模拟随机图的演化过程
"""
graphs = []
G = nx.Graph()
# 初始图
G.add_nodes_from(range(n_initial))
for i in range(n_initial):
for j in range(i+1, n_initial):
if np.random.random() < p:
G.add_edge(i, j)
graphs.append(G.copy())
# 逐步添加新节点
for t in range(n_initial, n_max):
G.add_node(t)
# 新节点与现有节点随机连接
for i in range(t):
if np.random.random() < p:
G.add_edge(t, i)
graphs.append(G.copy())
return graphs
# 可视化演化过程
def visualize_evolution(graphs, interval=200):
"""
动态显示网络演化
"""
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
def update(frame):
axes[0].clear()
axes[1].clear()
G = graphs[frame]
# 网络结构图
pos = nx.spring_layout(G, k=2, iterations=50)
nx.draw(G, pos, ax=axes[0],
node_color='lightblue',
node_size=200,
edge_color='gray',
with_labels=True)
axes[0].set_title(f'时间步 {frame}: {len(G.nodes)} 节点, {len(G.edges)} 边')
# 度分布
degrees = [d for n, d in G.degree()]
axes[1].hist(degrees, bins=range(min(degrees), max(degrees)+2),
alpha=0.7, color='skyblue', edgecolor='black')
axes[1].set_xlabel('度')
axes[1].set_ylabel('频率')
axes[1].set_title('度分布')
plt.tight_layout()
ani = FuncAnimation(fig, update, frames=len(graphs),
interval=interval, repeat=False)
plt.show()
return ani
# 运行示例
graphs = random_graph_evolution(n_initial=3, n_max=20, p=0.15)
visualize_evolution(graphs)
2 BA无标度网络演化
def ba_scale_free_evolution(n_initial=3, n_max=100, m=2):
"""
Barabási-Albert 无标度网络演化
"""
graphs = []
# 初始完全图
G = nx.complete_graph(n_initial)
graphs.append(G.copy())
# 使用BA模型添加节点
for t in range(n_initial, n_max):
G.add_node(t)
# 优先连接:新节点更倾向于连接度高的节点
targets = []
for _ in range(min(m, len(G.nodes)-1)):
degrees = np.array([d for n, d in G.degree()])
probs = degrees / degrees.sum()
# 避免重复连接
available = [n for n in G.nodes() if n != t and n not in targets]
if len(available) > 0:
probs_available = np.array([G.degree(n) for n in available])
probs_available = probs_available / probs_available.sum()
target = np.random.choice(available, p=probs_available)
G.add_edge(t, target)
targets.append(target)
graphs.append(G.copy())
return graphs
# 分析BA网络特性
def analyze_network_properties(G):
"""
分析网络的各种统计特性
"""
properties = {}
# 基本统计
properties['节点数'] = len(G.nodes())
properties['边数'] = len(G.edges())
properties['平均度'] = np.mean([d for n, d in G.degree()])
# 连通性分析
if nx.is_connected(G):
properties['平均路径长度'] = nx.average_shortest_path_length(G)
else:
components = list(nx.connected_components(G))
properties['连通分量数'] = len(components)
properties['最大分量比例'] = len(max(components, key=len)) / len(G.nodes())
# 聚类系数
properties['平均聚类系数'] = nx.average_clustering(G)
# 度分布幂律拟合
degrees = [d for n, d in G.degree()]
properties['最大度'] = max(degrees)
properties['度分布偏度'] = np.mean(degrees) / np.median(degrees) if degrees else 0
return properties
# 运行并分析
graphs = ba_scale_free_evolution(n_initial=5, n_max=50, m=2)
final_graph = graphs[-1]
props = analyze_network_properties(final_graph)
print("BA网络特性分析:")
for key, value in props.items():
print(f"{key}: {value:.3f}")
动态网络演化模型
1 边演化模型
def edge_dynamics_evolution(n_nodes=20, p_add=0.05, p_remove=0.02, t_max=50):
"""
边的动态添加和移除演化
"""
graphs = []
# 初始化随机图
G = nx.erdos_renyi_graph(n_nodes, 0.1)
graphs.append(G.copy())
for t in range(t_max):
# 随机添加边
for i in range(n_nodes):
for j in range(i+1, n_nodes):
if not G.has_edge(i, j) and np.random.random() < p_add:
G.add_edge(i, j)
# 随机移除边
edges_to_remove = []
for edge in G.edges():
if np.random.random() < p_remove:
edges_to_remove.append(edge)
G.remove_edges_from(edges_to_remove)
graphs.append(G.copy())
return graphs
# 可视化边演化
def plot_edge_evolution(graphs):
"""
绘制边数随时间的演化
"""
edge_counts = [len(G.edges()) for G in graphs]
node_counts = [len(G.nodes()) for G in graphs]
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# 边数变化
axes[0].plot(edge_counts, 'b-', linewidth=2)
axes[0].set_xlabel('时间步')
axes[0].set_ylabel('边数')
axes[0].set_title('网络边数演化')
axes[0].grid(True, alpha=0.3)
# 密度变化
densities = [2*e/(n*(n-1)) if n > 1 else 0
for n, e in zip(node_counts, edge_counts)]
axes[1].plot(densities, 'r-', linewidth=2)
axes[1].set_xlabel('时间步')
axes[1].set_ylabel('网络密度')
axes[1].set_title('网络密度演化')
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 运行示例
graphs = edge_dynamics_evolution(n_nodes=30, p_add=0.03, p_remove=0.01, t_max=30)
plot_edge_evolution(graphs)
2 节点和边同时演化
def complete_network_evolution(n_initial=5, n_max=30,
p_add_edge=0.1, p_remove_edge=0.05,
p_add_node=0.2, p_remove_node=0.05):
"""
完整的网络演化:节点和边同时变化
"""
graphs = []
G = nx.complete_graph(n_initial)
graphs.append(G.copy())
current_id = n_initial
for t in range(50): # 最多50个时间步
if len(G.nodes()) >= n_max:
break
# 添加新节点
if np.random.random() < p_add_node and len(G.nodes()) < n_max:
G.add_node(current_id)
# 新节点连接策略:优先连接
if len(G.nodes()) > 1:
degrees = np.array([d for n, d in G.degree() if n != current_id])
if degrees.sum() > 0:
probs = degrees / degrees.sum()
nodes = [n for n in G.nodes() if n != current_id]
# 连接2-3个节点
n_connections = min(np.random.randint(2, 4), len(nodes))
targets = np.random.choice(nodes, size=n_connections,
p=probs, replace=False)
for target in targets:
G.add_edge(current_id, target)
current_id += 1
# 移除节点
if np.random.random() < p_remove_node and len(G.nodes()) > n_initial:
node_to_remove = np.random.choice(list(G.nodes()))
G.remove_node(node_to_remove)
# 边演化
all_nodes = list(G.nodes())
for i in range(len(all_nodes)):
for j in range(i+1, len(all_nodes)):
if np.random.random() < p_add_edge and not G.has_edge(all_nodes[i], all_nodes[j]):
G.add_edge(all_nodes[i], all_nodes[j])
elif np.random.random() < p_remove_edge and G.has_edge(all_nodes[i], all_nodes[j]):
G.remove_edge(all_nodes[i], all_nodes[j])
graphs.append(G.copy())
return graphs
网络演化统计与可视化
1 演化指标追踪
def track_evolution_metrics(graphs):
"""
追踪网络演化的多种指标
"""
metrics = {
'time': [],
'nodes': [],
'edges': [],
'density': [],
'avg_degree': [],
'clustering': [],
'connectivity': []
}
for t, G in enumerate(graphs):
metrics['time'].append(t)
metrics['nodes'].append(len(G.nodes()))
metrics['edges'].append(len(G.edges()))
n = len(G.nodes())
metrics['density'].append(2*len(G.edges())/(n*(n-1)) if n > 1 else 0)
degrees = [d for n, d in G.degree()]
metrics['avg_degree'].append(np.mean(degrees) if degrees else 0)
metrics['clustering'].append(nx.average_clustering(G))
metrics['connectivity'].append(nx.is_connected(G))
return metrics
def plot_evolution_metrics(metrics):
"""
绘制多个演化指标
"""
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
plot_configs = [
(0, 0, 'nodes', '节点数', 'b-'),
(0, 1, 'edges', '边数', 'g-'),
(0, 2, 'density', '网络密度', 'r-'),
(1, 0, 'avg_degree', '平均度', 'c-'),
(1, 1, 'clustering', '聚类系数', 'm-'),
(1, 2, 'connectivity', '连通性', 'y-')
]
for row, col, key, title, style in plot_configs:
axes[row, col].plot(metrics['time'], metrics[key], style, linewidth=2)
axes[row, col].set_xlabel('时间步')
axes[row, col].set_ylabel(title)
axes[row, col].set_title(f'{title}演化')
axes[row, col].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 运行完整的演化分析
print("开始网络演化分析...")
graphs = complete_network_evolution(n_initial=4, n_max=25)
metrics = track_evolution_metrics(graphs)
plot_evolution_metrics(metrics)
2 网络演化模拟器类
class NetworkEvolutionSimulator:
"""
网络演化模拟器类
"""
def __init__(self, initial_nodes=5):
self.graph = nx.Graph()
self.graph.add_nodes_from(range(initial_nodes))
self.history = [self.graph.copy()]
self.current_id = initial_nodes
def add_random_node(self, m=2):
"""添加新节点(优先连接)"""
n = len(self.graph.nodes())
self.graph.add_node(self.current_id)
if n > 0:
# 优先连接
degrees = np.array([d for n, d in self.graph.degree() if n != self.current_id])
if degrees.sum() > 0:
probs = degrees / degrees.sum()
nodes = [n for n in self.graph.nodes() if n != self.current_id]
n_connections = min(m, len(nodes))
if n_connections > 0:
targets = np.random.choice(nodes, size=n_connections,
p=probs, replace=False)
for target in targets:
self.graph.add_edge(self.current_id, target)
self.current_id += 1
self.history.append(self.graph.copy())
def remove_random_node(self):
"""随机移除节点"""
if len(self.graph.nodes()) > 3: # 保留至少3个节点
node = np.random.choice(list(self.graph.nodes()))
self.graph.remove_node(node)
self.history.append(self.graph.copy())
def add_random_edges(self, prob=0.1):
"""随机添加边"""
nodes = list(self.graph.nodes())
for i in range(len(nodes)):
for j in range(i+1, len(nodes)):
if not self.graph.has_edge(nodes[i], nodes[j]):
if np.random.random() < prob:
self.graph.add_edge(nodes[i], nodes[j])
self.history.append(self.graph.copy())
def rewire_edges(self, prob=0.05):
"""重连边"""
edges = list(self.graph.edges())
for u, v in edges:
if np.random.random() < prob:
# 随机选择一个新端点
nodes = [n for n in self.graph.nodes() if n not in [u, v]]
if nodes:
new_v = np.random.choice(nodes)
if not self.graph.has_edge(u, new_v):
self.graph.remove_edge(u, v)
self.graph.add_edge(u, new_v)
self.history.append(self.graph.copy())
def get_summary(self):
"""获取当前网络摘要"""
G = self.graph
summary = {
'nodes': len(G.nodes()),
'edges': len(G.edges()),
'density': nx.density(G),
'avg_degree': np.mean([d for n, d in G.degree()]),
'clustering': nx.average_clustering(G),
'is_connected': nx.is_connected(G)
}
return summary
def simulate_evolution(self, n_steps=20):
"""运行演化模拟"""
for step in range(n_steps):
action = np.random.choice(['add_node', 'remove_node',
'add_edges', 'rewire'],
p=[0.4, 0.1, 0.3, 0.2])
if action == 'add_node':
self.add_random_node(m=np.random.randint(1, 4))
elif action == 'remove_node' and len(self.graph.nodes()) > 5:
self.remove_random_node()
elif action == 'add_edges':
self.add_random_edges(prob=np.random.uniform(0.05, 0.15))
elif action == 'rewire':
self.rewire_edges(prob=np.random.uniform(0.05, 0.15))
return self.history
# 使用模拟器
sim = NetworkEvolutionSimulator(initial_nodes=5)
history = sim.simulate_evolution(n_steps=30)
# 分析结果
metrics = track_evolution_metrics(history)
plot_evolution_metrics(metrics)
print("最终网络摘要:")
summary = sim.get_summary()
for key, value in summary.items():
print(f"{key}: {value:.3f}")
实际应用案例
1 社交网络演化
def social_network_evolution(n_users=50, n_steps=100):
"""
模拟社交网络的演化
"""
G = nx.Graph()
# 初始化用户
G.add_nodes_from(range(n_users))
# 用户属性
for node in G.nodes():
G.nodes[node]['age'] = np.random.randint(18, 60)
G.nodes[node]['interests'] = set(np.random.choice(
['sports', 'music', 'tech', 'art', 'travel', 'food'],
size=np.random.randint(1, 4), replace=False))
history = [G.copy()]
for step in range(n_steps):
# 基于共同兴趣添加边
for i in range(n_users):
for j in range(i+1, n_users):
if not G.has_edge(i, j):
common_interests = len(G.nodes[i]['interests'] & G.nodes[j]['interests'])
age_diff = abs(G.nodes[i]['age'] - G.nodes[j]['age'])
# 连接概率:共同兴趣越多,年龄越接近,概率越大
prob = (common_interests * 0.1 + (1 - age_diff/60) * 0.05)
if np.random.random() < prob:
G.add_edge(i, j)
# 基于弱关系断开边
edges_to_remove = []
for u, v in G.edges():
if len(G.nodes[u]['interests'] & G.nodes[v]['interests']) == 0:
if np.random.random() < 0.1:
edges_to_remove.append((u, v))
G.remove_edges_from(edges_to_remove)
history.append(G.copy())
return history
# 运行社交网络演化
social_history = social_network_evolution(n_users=30, n_steps=20)
print(f"社交网络演化:从{social_history[0].number_of_nodes()}节点到"
f"{social_history[-1].number_of_nodes()}节点")
这些案例展示了NetworkX在网络演化分析中的强大功能,包括:
- 多种演化模型的实现
- 动态可视化
- 网络拓扑指标分析
- 实际应用场景模拟
您可以根据具体需求调整参数和模型,应用到不同的网络演化研究场景中。