问题描述

物流配送问题描述的是在一个物流网络之中,如何从工厂出发经由不同路径,将满足经销商需求的货物以最小代价配送到各经销商处。

这里用的是自己生成的数据,保存在一张excel表格中,其3个sheet中的内容分别如下:

sheetname: 工厂




python运筹学出现none怎么判断 python求解运输问题_建模


sheetname: 经销商


python运筹学出现none怎么判断 python求解运输问题_python运筹学出现none怎么判断_02


sheetname: 路线


python运筹学出现none怎么判断 python求解运输问题_python运筹学出现none怎么判断_03


决策变量

在这个问题中,可以取从节点


到节点


之间的流量作为决策变量:



目标函数

为了方便表达,设定以下参数:



那么目标函数就是所有路径上的物流成本之和,即:



约束条件

此问题中的约束主要有三方面:

  1. 路径流量不能超过运力限制



2. 必须满足每个经销商的需求



3. 每个工厂发出的货物必须小于其产量限制



编程求解

对于图问题的建模可以用networkx包来操作,这里只是做了简单的图建模和可视化,还有很多功能都没有用到。在复杂网络中,它附带的图分析网络和一些算法都非常有用。此问题的网络可视化如下:


python运筹学出现none怎么判断 python求解运输问题_python运筹学出现none怎么判断_04


在这个问题的编程求解中,严重参考了这里,感兴趣的朋友们可以去github看看。

完整代码如下:


from pulp import *
import pandas as pd
import networkx as nx
import os
import time
import matplotlib.pyplot as plt

# 导入数据
fpath = os.path.join("data", "物流配送模型数据.xlsx")
factories = pd.read_excel(fpath, sheet_name="工厂")
vendors = pd.read_excel(fpath, sheet_name="经销商")
routes = pd.read_excel(fpath, sheet_name="路线")

import networkx as nx
# 创建有向图
G = nx.DiGraph()
# 添加节点
for i, row in factories.iterrows():
    G.add_node(row.工厂, supply=row.产量, node_type = '工厂')
    
for i, row in vendors.iterrows():
    G.add_node(row.经销商, demand=row.需求量, node_type = '经销商')
# 添加边
for i, row in routes.iterrows():
    G.add_edge(row.起点, row.终点, cost=row.运输费用, capacity=row.运力)

# 网络可视化
top = nx.bipartite.sets(G)[0]
layout = nx.layout.bipartite_layout(G, top)
nx.draw(G,layout,node_shape='s',node_size=1200, node_color='#5C7EFF', arrow_size=50)
nx.draw_networkx_labels(G,layout)
plt.show()
# 建立模型
model = LpProblem("物流配送模型", LpMinimize)

# 建立变量
shipping_amount = LpVariable.dicts("配送量", G.edges(), lowBound=0)

# 目标函数
model += lpSum([data['cost']*shipping_amount[(origin, destination)] for(origin, destination, data) in G.edges(data=True)])

# 约束条件
# 满足经销商的需求
for name, data in G.nodes(data=True):
    if data["node_type"] == "经销商":
        model += lpSum([shipping_amount[(origin, name)] for origin,_ in G.in_edges(name)]) == data['demand']
            
# 满足工厂产量约束
for name, data in G.nodes(data=True):
    if data["node_type"] == "工厂":
        model += lpSum([shipping_amount[(name, destination)] for _,destination in G.out_edges(name)]) <= data['supply']
        
# 满足路线运力约束
for (origin, destination, data) in  G.edges(data=True):
    model += shipping_amount[(origin, destination)] <= data['capacity']

# 求解
start_time = time.clock()
model.solve()
print("用时:", time.clock()-start_time," s")
print("求解状态:", LpStatus[model.status])

# 组织计算结果
rsl = []
for origin, destination in G.edges():
    val = value(shipping_amount[(origin, destination)])
    rsl.append({"起点": origin, "终点":destination, "运输量": val})
rsl_df = pd.DataFrame(rsl)
print(rsl_df[rsl_df.运输量>0])
print("最小运输代价为: ",value(model.objective))


结果:


用时: 0.009226999999999874  s
求解状态: Optimal
                 终点     起点    运输量
3         Carrefour    SVW  105.0
4           Rt-mart    SVW   81.0
5            Auchan    SVW   76.0
8          CP Lotus    SGM   36.0
9   Century Lianhua    SGM   85.0
13            Tesco    SGM   13.0
19           Auchan    NIO   66.0
20            Tesco    NIO   77.0
21          Walmart  Tesla   87.0
24        Carrefour  Tesla   15.0
27            Tesco  Tesla   56.0
29         CP Lotus   GTMC   30.0
33           Auchan   GTMC    1.0
最小运输代价为:  1096.57