本文目录导读:

我来为你详细介绍如何使用NetworkX解决各种流问题,包括最大流、最小费用流等经典案例。
安装和导入NetworkX
import networkx as nx import matplotlib.pyplot as plt import numpy as np # 设置中文显示 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False
最大流问题案例
案例1:基础网络最大流
# 创建有向图
G = nx.DiGraph()
# 添加边(源点,终点,容量)
edges = [
('S', 'A', 10), # S->A 容量10
('S', 'B', 5), # S->B 容量5
('A', 'B', 15), # A->B 容量15
('A', 'C', 10), # A->C 容量10
('A', 'D', 5), # A->D 容量5
('B', 'C', 5), # B->C 容量5
('B', 'D', 10), # B->D 容量10
('C', 'T', 10), # C->T 容量10
('D', 'T', 10) # D->T 容量10
]
# 添加边的容量属性
for u, v, capacity in edges:
G.add_edge(u, v, capacity=capacity)
# 计算最大流
flow_value, flow_dict = nx.maximum_flow(G, 'S', 'T')
print(f"最大流值: {flow_value}")
print("\n各边的流量分配:")
for u in flow_dict:
for v, flow in flow_dict[u].items():
capacity = G[u][v]['capacity']
print(f"{u} -> {v}: 流量 = {flow}, 容量 = {capacity}")
# 可视化网络
def draw_flow_network(G, flow_dict):
pos = nx.spring_layout(G, seed=42)
# 绘制节点
nx.draw_networkx_nodes(G, pos, node_color='lightblue',
node_size=500)
nx.draw_networkx_labels(G, pos)
# 绘制边
edge_labels = {}
for u, v, data in G.edges(data=True):
capacity = data['capacity']
flow = flow_dict[u][v]
edge_labels[(u, v)] = f"{flow}/{capacity}"
# 根据利用率改变颜色
utilization = flow / capacity if capacity > 0 else 0
if utilization > 0.8:
color = 'red'
elif utilization > 0.5:
color = 'orange'
else:
color = 'green'
nx.draw_networkx_edges(G, pos, edgelist=[(u, v)],
edge_color=color, width=2)
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
plt.title(f"最大流网络 (总流量 = {sum(flow_dict['S'].values())})")
plt.show()
draw_flow_network(G, flow_dict)
案例2:多源多汇最大流
def solve_multi_source_sink_flow():
"""解决多源多汇问题"""
G = nx.DiGraph()
# 原始网络
edges = [
('A', 'C', 10), ('A', 'D', 8),
('B', 'C', 5), ('B', 'D', 12),
('C', 'E', 9), ('C', 'F', 7),
('D', 'E', 6), ('D', 'F', 8),
('E', 'G', 12), ('F', 'G', 10)
]
# 添加超源点和超汇点
G.add_edge('SuperSource', 'A', capacity=100)
G.add_edge('SuperSource', 'B', capacity=100)
G.add_edge('E', 'SuperSink', capacity=100)
G.add_edge('F', 'SuperSink', capacity=100)
# 添加原始边
for u, v, cap in edges:
G.add_edge(u, v, capacity=cap)
# 计算最大流
flow_value, flow_dict = nx.maximum_flow(G, 'SuperSource', 'SuperSink')
print(f"多源多汇最大流值: {flow_value}")
# 只显示原始网络的流量
print("\n原始网络流量分配:")
for u, v, cap in edges:
if v in flow_dict.get(u, {}):
print(f"{u} -> {v}: 流量 = {flow_dict[u][v]}, 容量 = {cap}")
return flow_value, flow_dict
solve_multi_source_sink_flow()
最小费用流问题案例
案例3:运输问题
def solve_transportation_problem():
"""解决运输问题(最小费用流)"""
G = nx.DiGraph()
# 工厂(供应节点)
factories = {
'F1': 40, # 供应量
'F2': 50 # 供应量
}
# 仓库(需求节点)
warehouses = {
'W1': 30, # 需求量
'W2': 35, # 需求量
'W3': 25 # 需求量
}
# 运输成本(工厂->仓库)
costs = {
('F1', 'W1'): 3,
('F1', 'W2'): 5,
('F1', 'W3'): 7,
('F2', 'W1'): 4,
('F2', 'W2'): 6,
('F2', 'W3'): 8
}
# 添加超源点和超汇点
G.add_edge('Source', 'F1', capacity=factories['F1'], weight=0)
G.add_edge('Source', 'F2', capacity=factories['F2'], weight=0)
G.add_edge('W1', 'Sink', capacity=warehouses['W1'], weight=0)
G.add_edge('W2', 'Sink', capacity=warehouses['W2'], weight=0)
G.add_edge('W3', 'Sink', capacity=warehouses['W3'], weight=0)
# 添加运输边
for (f, w), cost in costs.items():
min_capacity = min(factories[f], warehouses[w])
G.add_edge(f, w, capacity=min_capacity, weight=cost)
# 计算最小费用流
flow_cost, flow_dict = nx.network_simplex(G)
# 计算实际流量
total_flow = sum(flow_dict['Source'].values())
print(f"最小运输费用: {flow_cost}")
print(f"总运输量: {total_flow}")
print("\n运输方案:")
for (f, w), cost in costs.items():
flow = flow_dict.get(f, {}).get(w, 0)
if flow > 0:
print(f"{f} -> {w}: {flow}单位, 成本={cost}/单位, 总成本={flow*cost}")
return flow_cost, flow_dict
solve_transportation_problem()
实际应用案例
案例4:通信网络带宽分配
def solve_bandwidth_allocation():
"""通信网络带宽分配问题"""
G = nx.DiGraph()
# 网络拓扑(路由器之间的可用带宽)
links = [
('R1', 'R2', 100), # R1->R2 100Mbps
('R1', 'R3', 50), # R1->R3 50Mbps
('R2', 'R3', 80), # R2->R3 80Mbps
('R2', 'R4', 70), # R2->R4 70Mbps
('R3', 'R4', 60), # R3->R4 60Mbps
('R3', 'R5', 90), # R3->R5 90Mbps
('R4', 'R5', 50) # R4->R5 50Mbps
]
# 添加边(带宽作为容量)
for u, v, bandwidth in links:
G.add_edge(u, v, capacity=bandwidth)
G.add_edge(v, u, capacity=bandwidth) # 双向链路
# 假设服务器在R1,客户端在R5
# 需要分配带宽给多个应用
apps = ['视频流', '文件传输', '远程桌面']
demands = {app: {'min': 20, 'max': 40} for app in apps}
# 计算最大有效带宽
flow_value, flow_dict = nx.maximum_flow(G, 'R1', 'R5')
print(f"R1到R5的最大可用带宽: {flow_value} Mbps")
print("\n带宽分配建议:")
total_bandwidth = flow_value
total_demand_min = sum(d['min'] for d in demands.values())
total_demand_max = sum(d['max'] for d in demands.values())
for app, demand in demands.items():
if total_demand_max <= total_bandwidth:
allocated = demand['max']
elif total_demand_min <= total_bandwidth:
# 按比例分配
proportion = demand['min'] / total_demand_min
allocated = min(demand['max'],
demand['min'] + proportion * (total_bandwidth - total_demand_min))
else:
allocated = demand['min'] * (total_bandwidth / total_demand_min)
print(f" {app}: {allocated:.1f} Mbps")
return flow_value, flow_dict
solve_bandwidth_allocation()
案例5:排水系统网络
def solve_drainage_system():
"""城市排水系统容量分析"""
G = nx.DiGraph()
# 排水管道(节点,节点,最大容量m³/s)
pipes = [
('入口1', '分流1', 50),
('入口2', '分流1', 30),
('入口3', '分流2', 40),
('分流1', '分流2', 20),
('分流1', '管道1', 60),
('分流2', '管道1', 30),
('分流2', '管道2', 50),
('管道1', '处理厂1', 70),
('管道2', '处理厂2', 40),
('处理厂1', '出口', 80),
('处理厂2', '出口', 60)
]
for u, v, capacity in pipes:
G.add_edge(u, v, capacity=capacity)
# 计算从入口到出口的最大排水能力
flow_value, flow_dict = nx.maximum_flow(G, '入口1', '出口')
print("排水系统容量分析:")
print(f"最大排水能力: {flow_value} m³/s")
# 识别瓶颈
print("\n瓶颈分析(高利用率管道):")
for u, v, data in G.edges(data=True):
if v in flow_dict.get(u, {}):
utilization = flow_dict[u][v] / data['capacity']
if utilization > 0.8:
print(f" {u} -> {v}: 利用率 {utilization:.1%} [瓶颈]")
elif utilization > 0.5:
print(f" {u} -> {v}: 利用率 {utilization:.1%}")
return flow_value, flow_dict
solve_drainage_system()
高级功能
多重流分析
def multiple_flow_analysis():
"""分析不同源汇组合的流量"""
G = nx.DiGraph()
# 构建一个中型网络
nodes = ['A', 'B', 'C', 'D', 'E', 'F']
edges = [
('A', 'B', 20), ('A', 'C', 15),
('B', 'C', 10), ('B', 'D', 25),
('C', 'D', 15), ('C', 'E', 20),
('D', 'E', 10), ('D', 'F', 20),
('E', 'F', 25)
]
for u, v, cap in edges:
G.add_edge(u, v, capacity=cap)
G.add_edge(v, u, capacity=cap) # 双向
# 分析不同的源汇对
source_sink_pairs = [('A', 'F'), ('A', 'E'), ('B', 'F'), ('C', 'F')]
print("不同源汇对的最大流:")
for source, sink in source_sink_pairs:
flow_value = nx.maximum_flow_value(G, source, sink)
print(f" {source} -> {sink}: {flow_value}")
# 找到所有节点对之间的最大流
print("\n容量矩阵(源\\汇):")
nodes_sorted = sorted(nodes)
print(f"{'':>6}", end="")
for sink in nodes_sorted:
print(f"{sink:>6}", end="")
print()
for source in nodes_sorted:
print(f"{source:>6}", end="")
for sink in nodes_sorted:
if source != sink:
flow = nx.maximum_flow_value(G, source, sink)
print(f"{flow:>6}", end="")
else:
print(f"{' -':>6}", end="")
print()
multiple_flow_analysis()
可视化辅助函数
def visualize_flow_with_animation(G, flow_dict, pos=None):
"""动态可视化流量分配"""
if pos is None:
pos = nx.spring_layout(G, seed=42)
fig, axes = plt.subplots(1, 2, figsize=(15, 6))
# 原始网络
ax1 = axes[0]
nx.draw_networkx_nodes(G, pos, ax=ax1, node_color='lightblue',
node_size=500)
nx.draw_networkx_labels(G, pos, ax=ax1)
edge_labels_orig = {(u, v): f"cap={d['capacity']}"
for u, v, d in G.edges(data=True)}
nx.draw_networkx_edges(G, pos, ax=ax1)
nx.draw_networkx_edge_labels(G, pos, edge_labels_orig, ax=ax1)
ax1.set_title("原始网络(容量)")
# 流量网络
ax2 = axes[1]
nx.draw_networkx_nodes(G, pos, ax=ax2, node_color='lightgreen',
node_size=500)
nx.draw_networkx_labels(G, pos, ax=ax2)
# 根据流量着色
colors = []
edge_labels_flow = {}
for u, v, d in G.edges(data=True):
flow = flow_dict.get(u, {}).get(v, 0)
utilization = flow / d['capacity'] if d['capacity'] > 0 else 0
if utilization > 0.8:
colors.append('red')
elif utilization > 0.5:
colors.append('orange')
else:
colors.append('green')
edge_labels_flow[(u, v)] = f"{flow}/{d['capacity']}"
nx.draw_networkx_edges(G, pos, ax=ax2, edge_color=colors, width=3)
nx.draw_networkx_edge_labels(G, pos, edge_labels_flow, ax=ax2)
ax2.set_title("流量分配(流量/容量)")
plt.tight_layout()
plt.show()
# 使用示例
G = nx.DiGraph()
edges = [('S', 'A', 10), ('S', 'B', 5), ('A', 'B', 15),
('A', 'T', 10), ('B', 'T', 10)]
for u, v, cap in edges:
G.add_edge(u, v, capacity=cap)
flow_value, flow_dict = nx.maximum_flow(G, 'S', 'T')
visualize_flow_with_animation(G, flow_dict)
这些案例展示了NetworkX在处理流问题时的强大功能,包括:
- 最大流问题:基础网络、多源多汇
- 最小费用流:运输问题、资源分配
- 实际应用:带宽分配、排水系统
- 高级分析:多重流、瓶颈识别
- 可视化:流量分配展示
通过这些案例,你可以快速上手使用NetworkX解决各种实际的流问题。