Python案例如何用Networkx做网络演化

wen python案例 1

本文目录导读:

Python案例如何用Networkx做网络演化

  1. 基础网络演化模型
  2. 动态网络演化模型
  3. 网络演化统计与可视化
  4. 实际应用案例

我来为您介绍如何使用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在网络演化分析中的强大功能,包括:

  • 多种演化模型的实现
  • 动态可视化
  • 网络拓扑指标分析
  • 实际应用场景模拟

您可以根据具体需求调整参数和模型,应用到不同的网络演化研究场景中。

抱歉,评论功能暂时关闭!