转运运输问题——Python实现(二)

转运运输问题在供应链管理中起着至关重要的作用。供应链是一个涉及从原材料采购到产品交付的复杂网络,其中运输是连接不同环节的关键环节。转运运输问题涉及如何高效地将物品从一个地点转移到另一个地点,以满足客户需求并最小化成本。在供应链背景下,转运运输问题需要考虑多个因素,如货物类型、数量、运输距离、交货时间、货车容量等。优化转运运输可以帮助企业降低成本、提高交付效率,从而增强竞争力。这可以通过合理的运输路线规划、货车装载优化、运输调度等方式实现。现代技术的应用使得解决转运运输问题变得更加高效。例如,使用智能物流系统和物流管理软件可以实时跟踪货物位置、优化运输路线和调度,减少空载率和运输时间。另外,物联网技术可以实现对货物和运输工具的远程监控,提供数据支持决策。

一、转运问题

除了常规的运输路线,运输是还可能包括发点到发点、收点到收点,甚至收点到发点的运输,这类运输问题考虑复杂的运输网络,称为转运问题。转运问题是指除了供给点和需求点之外运输时的中间节点,并且可以转化为一个运输问题。

供给点(supply point)是指可以发货但不能收货的点
需求点(demand point)是指可以收货但不能发货的点
转运点(transshipment point)是同时可以收货和发货的点

二、转运问题的数学模型

设有\(m\)个地点(称为产地或发地)\(A_i,i=1,2,...,m\)的某种物资调至\(n\)个地点(称为销地或收地)\(B_{m+j},j=1,2,...,n\),各个产地需要调出的物资量分别为\(a_i\)单位,各个销地需要调进的物资量分别为\(b_j\)单位,且$$ \sum_{i=1}^{m}a_i = \sum_{j=1}^{n}b_j=Q$$
现假设各个产地和销地之间可以转运,将产地和销地重新编号,就变成共有\(m+n\)个产地和\(m+n\)销地的运输问题,已知每个产地\(i\)到每个销地\(j\)的物资单位调运价格为\(c_{ij}\);各个运输节点的单位转运费\(c_k,k=1,2,...,m+n\);各个运输节点的转运量为\(t_k,k=1,2,...,m+n\),现问如何安排调运,才能使总运费最小。

序号 1 ... \(m\) \(m+1\) ... \(m+n\) 发送量
产地 1 ... \(x_{1m}\) \(x_{1,m+1}\) ... \(x_{1,m+n}\) \(a_1+t_1\)
... ... ... ... ... ... ...
\(m\) \(x_{m1}\) ... \(x_{m,m+1}\) ... \(x_{m,m+n}\) \(a_m+t_m\)
销地 \(m+1\) \(x_{m+1,1}\) ... \(x_{m+1,m}\) ... \(x_{m+1,m+n}\) \(t_{m+1}\)
... ... ... ... ... ... ...
\(m+n\) \(x_{m+n,1}\) ... \(x_{m+n,m}\) \(x_{m+n,m+1}\) ... \(t_{m+n}\)
接收量 \(t_1\) ... \(t_m\) \(b_1+t_{m+1}\) ... \(b_n+t_{m+n}\)

根据上面变量表,可建立有转运的运输问题的数学模型

\[\begin{aligned} & \min z=\sum_{\substack{i=1 \\ i\neq j}}^{m+n} \sum_{j=1\\ j \neq i}^{m+n} c_{i j} x_{i j}+\sum_{i=1}^{m+n} c_i t_i \\ & \left\{\begin{array}{c} \sum_{j=1,j\neq i}^{m+n}x_{ij} =a_i+t_i \quad i=1,2, \cdots, m \\ \sum_{j=1,j\neq i}^{m+n}x_{ij}=t_i \quad i=m+1, m+2, \cdots, m+n \\ \sum_{i=1,i\neq j}^{m+n}x_{ij}=t_j \quad j=1,2, \cdots, m \\ \sum_{i=1,i\neq j}^{m+n}x_{ij} =b_{j-m}+t_j \quad j=m+1, m+2, \cdots, m+n \\ x_{ij}\geq 0,(i \neq j) \quad Q \geq \mathrm{t}_i, \mathrm{t}_j \geq 0 \end{array}\right. \\ & \end{aligned} \]

做变换,令\(x_{ii}=Q-t_i\)\(c_{ii}=-c_i\),代入上面模型,得

\[\begin{aligned} & \min z=\sum_{i=1}^{m+n} \sum_{j=1}^{m+n} c_{i j} x_{i j} \\ & \left\{\begin{array}{c} \sum_{j=1}^{m+n}x_{ij} =Q+a_i \quad i=1,2, \cdots, m \\ \sum_{j=1}^{m+n}x_{ij}=Q \quad i=m+1, m+2, \cdots, m+n \\ \sum_{i=1}^{m+n}x_{ij}=Q \quad j=1,2, \cdots, m \\ \sum_{i=1}^{m+n}x_{ij} =Q+b_{j-m}\quad j=m+1, m+2, \cdots, m+n \\ x_{ij}\geq 0,(i \neq j) \quad Q \geq \mathrm{t}_i, \mathrm{t}_j \geq 0 \end{array}\right. \\ & \end{aligned} \]

序号 1 ... \(m\) \(m+1\) ... \(m+n\) 发送量
产地 1 \(-c_1\) ... \(x_{1m}\) \(x_{1,m+1}\) ... \(x_{1,m+n}\) \(Q+a_1\)
... ... \(-c_i\) ... ... ... ... ...
\(m\) \(x_{m1}\) ... \(-c_m\) \(x_{m,m+1}\) ... \(x_{m,m+n}\) \(Q+a_m\)
销地 \(m+1\) \(x_{m+1,1}\) ... \(x_{m+1,m}\) \(-c_{m+1}\) ... \(x_{m+1,m+n}\) \(Q\)
... ... ... ... ... \(-c_{m+j}\) ... ...
\(m+n\) \(x_{m+n,1}\) ... \(x_{m+n,m}\) \(x_{m+n,m+1}\) ... \(-c_{m+n}\) \(Q\)
接收量 \(Q\) ... \(Q\) \(Q+b_1\) ... \(Q+b_n\)

三、转运问题示例

3.1 示例1

建立转运矩阵,注意单位转运费为零

A B C D E 供应量
A 0 3 12 10 4 47
B 3 0 6 10 5 34
C 12 6 0 2 3 27
D 10 10 2 0 6 27
E 4 5 2 6 0 27
需求量 27 27 36 36 36

该问题Python求解

import pulp
import numpy as np
from pprint import pprint

def transport_problem(costs, x_max, y_max):
    row = len(costs)
    col = len(costs[0])
    prob = pulp.LpProblem('Transportation Problem', sense=pulp.LpMinimize)  # Changed to minimize
    var = [[pulp.LpVariable(f'x{i}{j}', lowBound=0, cat=pulp.LpInteger)
            for j in range(col)] for i in range(row)]
    flatten = lambda x: [y for l in x for y in flatten(l)] if type(x) is list else [x]
    prob += pulp.lpDot(flatten(var), costs.flatten())  # Objective function
    for i in range(row):
        prob += (pulp.lpSum(var[i])) == x_max[i]  # Modified constraint: Equality instead of inequality
    for j in range(col):
        prob += (pulp.lpSum(var[i][j] for i in range(row))) == y_max[j]  # Modified constraint: Equality instead of inequality
    prob.solve()
    return {'objective': pulp.value(prob.objective), 'var': [[pulp.value(var[i][j]) for j in range(col)] for
                                                               i in range(row)]}


if __name__ == '__main__':
    costs = np.array([[0, 3, 12, 10, 4],
                      [3, 0, 6, 10, 5],
                      [12, 6, 0, 2, 3],
                      [10, 10, 2, 0, 6],
                      [4, 5, 2, 6, 0]])
    max_plant = [47, 34, 27, 27, 27]
    max_cultivation = [27, 27, 36, 36, 36]
    res = transport_problem(costs, max_plant, max_cultivation)
    print(f'最小值为{res["objective"]}')
    print('各变量的取值为: ')
    pprint(res['var'])
最小值为162.0
各变量的取值为: 
[[27.0, 0.0, 0.0, 0.0, 20.0],
 [0.0, 27.0, 7.0, 0.0, 0.0],
 [0.0, 0.0, 18.0, 9.0, 0.0],
 [0.0, 0.0, 0.0, 27.0, 0.0],
 [0.0, 0.0, 11.0, 0.0, 16.0]]

3.2 示例2

建立转运矩阵

发送地 转运 发送量
接收地 1 2 3 4 5 发送量
1 -4 5 3 2 M 60
2 5 -1 2 M 4 90
转运 3 3 2 -3 5 5 50
4 2 M 5 -3 6 50
5 M 4 5 6 -5 50
接收量 接收量 50 50 50 80 70 300\300

求出调运方案

发送地 转运
接收地 1 2 3 4 5 发送量
1 -4(50) 5 3 2 (10) M 60
2 5 -1(50) 2(20) M 4 (20) 90
转运 3 3 2 -3(30) 5 (20) 5 50
4 2 M 5 -3 (50) 6 50
5 M 4 5 6 -5(50) 50
接收量 50 50 50 80 70 300\300

\(Z=c_{14}x_{14}+c_{23}x_{23}+c_{25}x_{25}+c_{34}x_{34}=2\times 10+2\times 20+4\times 20+5\times 20=240\)

3.3 示例3(前例3)

例3:某供应链企业经销汽车配件A,下设2个分别位于沈阳和郑州的加工厂。该公司每月需要把各产地生产的产品分别运往北京、上海、广州3个销售点。运输过程中,允许经天津、武汉2个中转站进行转运。公司在租用运输车辆时,租赁公司给出如下的单位运价表。天津和武汉两个中转地的运输能力约束为500,400,问在考虑到产销地之间非直接运输的各种可能方案的情况下,如何将2个加工厂每月生产的产品运往销售地,使总的运费最低?

天津\(T_1\) 武汉\(T_2\) 北京\(B_1\) 上海\(B_2\) 广州\(B_3\) 供应量
沈阳\(A_1\) 210 470 500
郑州\(A_2\) 230 160 300
天津\(T_1\) 100 170 300 500
武汉\(T_2\) 315 130 150 400
需求量 500 400 300 400 100

建立转运矩阵

序号 沈阳1 郑州 2 天津3 武汉4 北京5 上海6 广州7 发送量
产地 1 0 \(M\) 210 470 \(M\) \(M\) \(M\) 800+500
2 \(M\) 0 230 160 \(M\) \(M\) \(M\) 800+300
中转 3 \(M\) \(M\) 0 \(M\) 100 170 300 800
4 \(M\) \(M\) \(M\) 0 315 130 100 800
销地 5 \(M\) \(M\) \(M\) \(M\) 0 \(M\) \(M\) 800
6 \(M\) \(M\) \(M\) \(M\) \(M\) 0 \(M\) 800
7 \(M\) \(M\) \(M\) \(M\) \(M\) \(M\) 0 800
接收量 800 800 800 800 800+300 800+400 800+100
#修改上面程序的数据即可,f是程序运算中的无穷,也就是运筹的M
if __name__ == '__main__':
    f=10000000  #float("inf")
    costs = np.array([[0, f, 210, 470, f, f, f],
                      [f, 0, 230, 160, f, f, f],
                      [f, f, 0, f, 100, 170, 300],
                      [f, f, f,0, 315, 130, 150],
                      [f, f, f,f, 0, f, f],
                      [f, f, f, f, f, 0, f],
                      [f, f, f, f, f, f, 0]])
    max_plant = [1300, 1100, 800, 800, 800, 800, 800]
    max_cultivation = [800, 800, 800, 800, 1100, 1200, 900]
最小值为258000.0
各变量的取值为: 
[[800.0, 0.0, 500.0, 0.0, 0.0, 0.0, 0.0],
 [0.0, 800.0, 0.0, 300.0, 0.0, 0.0, 0.0],
 [0.0, 0.0, 300.0, 0.0, 300.0, 200.0, 0.0],
 [0.0, 0.0, 0.0, 500.0, 0.0, 200.0, 100.0],
 [0.0, 0.0, 0.0, 0.0, 800.0, 0.0, 0.0],
 [0.0, 0.0, 0.0, 0.0, 0.0, 800.0, 0.0],
 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 800.0]]

四、练习题

4.1 练习1

某种物资需从甲、乙两个产地运往A,B和C三个销地,并允许中间经过某产地或销地转运,其网络图如下:

已知甲和乙的供应量各为100和200,A、B和C的需求量均为100,线段(弧)上的数字为单位运费。试求(1)用表格形式列出此问题的运输模型;(2)求此问题的最优解。

4.2 练习2

某种物资需从甲、乙两个产地运往A,B和C三个销地,并允许中间经过某产地或销地转运,其网络图如下:

已知甲和乙的供应量各为100和200,A、B和C的需求量分别为100、100和170,线段(弧)上的数字为单位运费。试求(1)用表格形式列出此问题的运输模型;(2)求此问题的最优解。(解题提示:可添加虚拟产地化为标准的转运运输问题,如练习1)

参考文献

  1. 运筹学笔记——运输、指派和转运问题
  2. 有转运运输问题的求解
  3. 运筹学-11-1-运输问题-转运问题
  4. 数学建模——运输问题(Python实现)
posted @ 2023-07-09 21:38  郝hai  阅读(599)  评论(0编辑  收藏  举报