提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
#网络的最大流问题(最大流量是指在一个图中,在每个边允许的最大流量的情况下,能从源点到汇点的最大流量)
#费用最小流问题(对源点到汇点设置一个流量demand,求从源点到汇点通过这个流量的费用最小值,每条边的流量受边的capacity属性控制)
#最小费用最大流问题(求解从源点到汇点的最大流的最小费用路径)
一、包
示例:使用networkx来进行创建图,使用matplotlib来实现图的可视化
二、问题
1.图的最大流问题
代码
#网络的最大流问题(最大流量是指在一个图中,在每个边允许的最大流量的情况下,能从源点到汇点的最大流量)
#使用nx.maximum_flow(flowG, _s, _t, capacity=‘capacity’)来求解网络的最大流问题
# 这个方法只能对有向图使用,而且图的边的属性只能是capacity,而不是weight
import matplotlib.pyplot as plt
import networkx as nx
#网络的最大流问题必须是一个有向图,使用DiGraph创建一个有向图
G = nx.DiGraph()
G.add_edge('a', 'c', capacity=3)
G.add_edge('a', 'b', capacity=7)
G.add_edge('c', 'd', capacity=5)
G.add_edge('d', 't', capacity=9)
G.add_edge('b', 't', capacity=6)
G.add_edge('c', 'e', capacity=1)
G.add_edge('e', 'g', capacity=4)
G.add_edge('t', 'g', capacity=2)
#求解最大流量问题,nx.maximum_flow()返回一个元组,第一个是最大流量的值,第二个是最大流量的每条边的分配情况
max_flow_value, max_flow = nx.maximum_flow(G, 'a', 'g') #可以对flow_func传参来改变算法
print(max_flow_value)
print(max_flow)
#将最大流量的每条边的分配情况和每条边的最大容量合并,这一步是为了下面的可视化
label = nx.get_edge_attributes(G, 'capacity')
max_flow_label = {}
for name_1 in max_flow.keys():
for name_2 in max_flow[name_1].keys():
max_flow_label[(name_1, name_2)] = max_flow[name_1][name_2]
G_label = {}
for label_key in label.keys():
G_label[label_key] = str(label[label_key]) + ',' + str(max_flow_label[label_key])
print(G_label)
#可视化
pos = nx.spring_layout(G)
nx.draw(G, pos=pos, with_labels=True)
nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=G_label)
plt.show()
结果
2.图的最小费用流问题
代码
#费用最小流问题(对源点到汇点设置一个流量demand,求从源点到汇点通过这个流量的费用最小值,每条边的流量受边的capacity属性控制)
#使用nx.min_cost_flow()方法来求解图中的最小流问题,这里同样只能对有向图来使用,capacity属性表示的是容量,weight属性表示的是单位流量的费用
import matplotlib.pyplot as plt
import networkx as nx
#创建有向图
G = nx.DiGraph()
G.add_edges_from(
[
('a', 'c', {"weight": 2, "capacity": 3}),
('a', 'b', {"weight": 5, "capacity": 7}),
('c', 'd', {"weight": 9, "capacity": 5}),
('d', 't', {"weight": 3, "capacity": 9}),
('b', 't', {"weight": 1, "capacity": 6}),
('c', 'e', {"weight": 4, "capacity": 1}),
('e', 'g', {"weight": 2, "capacity": 4}),
('t', 'g', {"weight": 3, "capacity": 2}),
]
)
#获取并合并每条边的weight和capacity属性,生成标签
weight_label = nx.get_edge_attributes(G, "weight")
capacity_label = nx.get_edge_attributes(G, "capacity")
label = {}
for key in weight_label.keys():
label[key] = "weight:{}, capacity:{}".format(weight_label[key], capacity_label[key])
#添加demand
G.add_node('a', demand=-3) #使用nx.add_node()方法来改变节点的属性,设置从源点到汇点的流量为3,后面求解流量为3时的最小流
G.add_node('g', demand=3)
#求解最小费用流
min_cost, min_cost_way = nx.network_simplex(G) #返回一个元组,第一个是最小流的值,第二个取得最小流的路径
#获取在最小费用流下的流量标签,并将最小费用流的标签也加入到绘图的标签中
min_cost_label = {}
for first_key in min_cost_way.keys():
for second_key in min_cost_way[first_key].keys():
min_cost_label[(first_key, second_key)] = min_cost_way[first_key][second_key]
for key in label.keys():
label[key] += ", flow:{}".format(min_cost_label[key])
#绘图
pos = {'a': (10, 0), 'c': (5, 5), 'b': (15, 5), 'd': (10, 5), 'e': (5, 15), 't': (15, 15), 'g': (10, 20)}
nx.draw(G, pos=pos, with_labels=True)
nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=label)
nx.draw_networkx_edges(G, pos=pos)
plt.show()
结果
3.图的最小费用最大流问题
代码
#最小费用最大流问题(求解从源点到汇点的最大流的最小费用路径)
#使用nx.max_flow_min_cost()方法来求解最小费用最大流
import networkx as nx
import matplotlib.pyplot as plt
#创建有向图
G = nx.DiGraph()
G.add_edges_from(
[
('a', 'c', {"weight": 2, "capacity": 3}),
('a', 'b', {"weight": 5, "capacity": 7}),
('c', 'd', {"weight": 9, "capacity": 5}),
('d', 't', {"weight": 3, "capacity": 9}),
('b', 't', {"weight": 1, "capacity": 6}),
('c', 'e', {"weight": 4, "capacity": 1}),
('e', 'g', {"weight": 2, "capacity": 4}),
('t', 'g', {"weight": 3, "capacity": 2}),
]
)
#求解图的最小费用最大流问题
max_flow_min_cost = nx.max_flow_min_cost(G, 'a', 'g')
total_cost = nx.cost_of_flow(G, max_flow_min_cost) #用于计算路径费用
print(max_flow_min_cost)
print(total_cost)
#合并边标签
weight_label = nx.get_edge_attributes(G, "weight")
capacity_label = nx.get_edge_attributes(G, "capacity")
cost_label = {}
label = {}
for first_label in max_flow_min_cost.keys():
for second_label in max_flow_min_cost[first_label].keys():
cost_label[(first_label, second_label)] = max_flow_min_cost[first_label][second_label]
for l in weight_label.keys():
label[l] = "weight:{},capacity:{},flow:{}".format(weight_label[l], capacity_label[l], cost_label[l])
#绘图
pos = {'a': (10, 0), 'c': (5, 5), 'b': (15, 5), 'd': (10, 5), 'e': (5, 15), 't': (15, 15), 'g': (10, 20)}
nx.draw(G, pos=pos, with_labels=True)
nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=label)
nx.draw_networkx_edges(G, pos=pos)
plt.show()