You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建度服从幂律分布的二分图及NetworkX相关技术问题

如何生成顶点度服从幂律分布的二分图?

我需要创建一个顶点度服从幂律分布的二分图,并用以下代码验证是否为二分图:

print(bipartite.is_bipartite(G))

但遇到了两个问题:

  • 使用bipartite.projected_graph()函数时,传入幂律度分布的随机图和顶点列表,无法得到二分图;如果传入二分图和幂律分布数据集则持续报错,不清楚该函数为何生成非二分图。
  • 尝试生成幂律度分布的图时,bipartite.is_bipartite(G)的结果随机返回True或False。

我尝试的代码与运行结果

代码1:随机生成幂律度序列图

from networkx.algorithms import bipartite
from networkx.generators.degree_seq import random_degree_sequence_graph
from networkx.algorithms.graphical import is_graphical
from networkx.utils.random_sequence import powerlaw_sequence
n, t = 10, 2
while True:  # 不断生成序列直到找到可图序列
    seq = sorted([int(round(d)) for d in powerlaw_sequence(n, t)], reverse=True)  # 取整得到离散度序列
    if is_graphical(seq):
        break
G_1 = random_degree_sequence_graph(seq, tries=100)  # 可调整尝试次数
print(sorted(d for _, d in G_1.degree()))
print(bipartite.is_bipartite(G_1))
degrees = dict(G_1.degree())
degree_distribution = {}
for d in degrees.values():
    if d in degree_distribution:
        degree_distribution[d] += 1
    else:
        degree_distribution[d] = 1

print(degree_distribution)

代码2:绘制度分布直方图

degrees = dict(G_1.degree())
degree_distribution = {}
for d in degrees.values():
    if d in degree_distribution:
        degree_distribution[d] += 1
    else:
        degree_distribution[d] = 1

x = np.array(list(degree_distribution.keys()))
y = np.array(list(degree_distribution.values()))

plt.loglog(x, y, 'ro')
plt.title('度分布')
plt.xlabel('顶点度数')
plt.ylabel('顶点数量')
plt.show()

度分布图

代码3:构建二分图并添加节点

import networkx as nx
import random

n = 100  # 总节点数
m = 4  # 新节点的连接数
p = 0.5  # 连接到第一分图的概率

G = nx.Graph()

G.add_nodes_from(range(n), bipartite=0)  # 第一分图
G.add_nodes_from(range(n, 2*n), bipartite=1)  # 第二分图

for i in range(n):
    for j in range(n, 2*n):
        if random.random() < p:
            G.add_edge(i, j)

for i in range(2*n, n+m):
    # 连接到第一分图的节点(优先选择度数高的节点)
    targets = []
    for j in range(n):
        targets += [j] * G.degree(j)
    target = random.choice(targets)
    G.add_edge(i, target)

    # 连接到第二分图的节点(优先选择度数高的节点)
    targets = []
    for j in range(n, 2*n):
        targets += [j] * G.degree(j)
    target = random.choice(targets)
    G.add_edge(i, target)

print(nx.bipartite.is_bipartite(G))

degrees = dict(G.degree())
degree_distribution = {}
for d in degrees.values():
    if d in degree_distribution:
        degree_distribution[d] += 1
    else:
        degree_distribution[d] = 1
for d, count in degree_distribution.items():
    print(f"度数 {d}: {count} 个节点")

代码3运行结果

True
度数 50: 18 个节点
度数 54: 5 个节点
度数 51: 20 个节点
度数 46: 14 个节点
度数 49: 17 个节点
度数 56: 7 个节点
度数 45: 14 个节点
度数 40: 4 个节点
度数 44: 9 个节点
度数 48: 16 个节点
度数 53: 11 个节点
度数 47: 16 个节点
度数 52: 11 个节点
度数 61: 4 个节点
度数 43: 7 个节点
度数 57: 4 个节点
度数 55: 9 个节点
度数 59: 1 个节点
度数 41: 4 个节点
度数 42: 3 个节点
度数 39: 3 个节点
度数 58: 1 个节点
度数 38: 1 个节点
度数 62: 1 个节点

问题分析与解决方案

问题1:bipartite.projected_graph()的使用误区

bipartite.projected_graph()的作用是从二分图生成单分图投影,它本身不会生成二分图。传入非二分图的幂律随机图,自然得不到二分图;传入二分图时,必须指定要投影的分图节点集合(比如bipartite.projected_graph(G, top_nodes),其中top_nodes是二分图其中一个分图的节点列表),否则会报错。如果目标是生成幂律度分布的二分图,这个函数不是生成工具,而是分析工具。

问题2:随机幂律图的二分性不稳定

random_degree_sequence_graph()生成的是普通无向图,不是二分图。这类图是否为二分图完全随机——只有当图中不存在奇数环时才是二分图,而随机生成的幂律图可能包含奇数环,所以is_bipartite()结果随机。

正确生成幂律度分布二分图的方法

直接针对二分图的两个分图分别指定幂律度序列,用bipartite.configuration_model()生成:

import networkx as nx
from networkx.algorithms import bipartite
from networkx.utils.random_sequence import powerlaw_sequence

# 定义两个分图的节点数
n_top = 50
n_bottom = 100

# 生成两个分图的幂律度序列(确保序列和相等,否则无法生成二分图)
while True:
    top_degrees = [int(round(d)) for d in powerlaw_sequence(n_top, exponent=2.5)]
    bottom_degrees = [int(round(d)) for d in powerlaw_sequence(n_bottom, exponent=2.5)]
    if sum(top_degrees) == sum(bottom_degrees):
        break

# 用配置模型生成二分图
G = bipartite.configuration_model(top_degrees, bottom_degrees)

# 移除自环(配置模型可能生成自环)
G.remove_edges_from(nx.selfloop_edges(G))

# 验证是否为二分图
print(bipartite.is_bipartite(G))

# 查看度分布
top_nodes = {n for n, d in G.nodes(data=True) if d['bipartite'] == 0}
bottom_nodes = set(G) - top_nodes

print("第一分图度分布:")
top_deg = sorted(d for n, d in G.degree(top_nodes))
print(top_deg)

print("第二分图度分布:")
bottom_deg = sorted(d for n, d in G.degree(bottom_nodes))
print(bottom_deg)

代码说明:

  1. bipartite.configuration_model()专门用于根据两个分图的度序列生成二分图,只要两个序列的和相等(总边数一致),就能保证生成合法的二分图。
  2. 生成幂律序列取整后,必须校验两个序列的和是否相等,否则无法生成二分图。
  3. 配置模型可能生成自环,需要手动移除,避免影响后续分析。

如果想在已有的二分图基础上添加幂律分布的节点,可以修改代码3的逻辑,直接给新节点指定幂律度数:

# 在代码3的基础上,给新节点添加幂律分布的边
new_nodes_degree_seq = [int(round(d)) for d in powerlaw_sequence(m, exponent=2.5)]
for i, deg in enumerate(new_nodes_degree_seq):
    node_id = 2*n + i
    # 随机分配到某个分图
    G.add_node(node_id, bipartite=0 if random.random() < 0.5 else 1)
    target_part = 1 if G.nodes[node_id]['bipartite'] == 0 else 0
    targets = [n for n in G.nodes if G.nodes[n]['bipartite'] == target_part]
    # 优先选择度数高的节点连接(模拟偏好依附)
    target_weights = [G.degree(n) for n in targets]
    selected_targets = random.choices(targets, weights=target_weights, k=deg)
    for target in selected_targets:
        G.add_edge(node_id, target)

内容的提问来源于stack exchange,提问作者Александр Соколов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 18:02:02