利用Python进行数学建模:图的最优解

本文介绍了如何使用Python的networkx库解决图的三种流问题:最大流问题、最小费用流问题以及最小费用最大流问题。通过实例展示了如何创建有向图,设置边的容量和费用,并利用networkx提供的函数计算最大流、最小费用流以及最小费用最大流。最后,文章通过可视化展示了解决方案的结果。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

#网络的最大流问题(最大流量是指在一个图中,在每个边允许的最大流量的情况下,能从源点到汇点的最大流量)
#费用最小流问题(对源点到汇点设置一个流量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()

结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值