一、题目:
物流配送问题
随着电子商务的迅猛发展,电商平台对物流配送的需求日益增长。为了确保货物能够按时、高效地送达消费者手中,电商平台与第三方物流公司建立了紧密的合作关系。然而,面对大量的货物和多样的目的地,如何制定合理的运输策略成为了物流公司面临的一大挑战。
传统的物流优化方法在应对复杂的运输需求时往往具有较高的复杂度。为了解决这个问题,物流公司希望借助数学建模方法寻求运输综合策略,从而可以更合理地规划运输路线、选择合适的运输方式和工具,并确保在规定的时间内将货物送达目的地。这样不仅能够提高物流效率,降低运输成本,还能够提升消费者对电商平台的满意度。
一、货物当前所在城市
城市 | 公司一 | 公司一 |
数量 (吨) | ||
上海 | 29 | 14 |
西安 | 20 | 24 |
郑州 | 12 | 18 |
二、货物需要运往的城市
货物类型 | 小组一 | 小组二 | 终点城市 |
货物数量(吨) | |||
普货 | 19 | 27 | 昆明 |
普货 | 25 | 10 | 深圳 |
普货 | 17 | 19 | 天津 |
三、卡车
市场上有12吨载重卡车和5吨载重卡车两种卡车供租赁,租金分别为每天 5000元和每天3000元。这些卡车可以在任何地方租赁,并且客户可以根据自己的需求选择合适的卡车类型和租赁时长。假设每个城市有足够数量的可供租赁的卡车。
四、卡车运输
为节约成本,各小组间可在任何一个城市拼货和中转运输。拼货是指将来自不同发货人的货物合并在一起,由同一辆车或同一批运输工具运送的方式。同时货物可以由一辆车辆全部或者部分卸货后,暂存在当前城市,待后续的车辆将其运走。通过拼货可以更加灵活地安排运输计划,提高运输效率,降低成本,优化运输路线和运输资源的利用。
卡车单趟时间单位:天
上海 | 西安 | 昆明 | 深圳 | 天津 | 郑州 | |
上海 | -- | 3 | 6 | 4 | 3 | 2 |
西安 | 3 | -- | 4 | 4 | 2 | 1 |
昆明 | 6 | 4 | -- | 2 | 6 | 5 |
深圳 | 4 | 4 | 2 | -- | 5 | 4 |
天津 | 3 | 2 | 6 | 5 | -- | 1 |
郑州 | 2 | 1 | 5 | 4 | 1 | -- |
普通卡车A(12 吨)单趟成本 单位:元
上海 | 西安 | 昆明 | 深圳 | 天津 | 郑州 | |
上海 | -- | 13500 | 26500 | 16500 | 13500 | 8500 |
西安 | 13500 | -- | 18500 | 20500 | 10500 | 3500 |
昆明 | 26500 | 18500 | -- | 7500 | 31500 | 24500 |
深圳 | 16500 | 20500 | 7500 | -- | 25500 | 17500 |
天津 | 13500 | 10500 | 31500 | 25500 | -- | 5500 |
郑州 | 8500 | 3500 | 24500 | 17500 | 5500 | -- |
普通卡车B(5 吨)单趟成本 单位:元
上海 | 西安 | 昆明 | 深圳 | 天津 | 郑州 | |
上海 | -- | 11000 | 24000 | 14000 | 11000 | 6000 |
西安 | 11000 | -- | 16000 | 18000 | 8000 | 1000 |
昆明 | 24000 | 16000 | -- | 5000 | 29000 | 22000 |
深圳 | 14000 | 18000 | 5000 | -- | 23000 | 15000 |
天津 | 11000 | 8000 | 29000 | 23000 | -- | 3000 |
郑州 | 6000 | 1000 | 22000 | 15000 | 3000 | -- |
五、航空运输
除了陆路运输,货物也可以通过航空运输,题目中考虑的任意两个城市之间都可以通过航空运输进行货物运输。为简化计算,假设货物的国内航空运价无论远近均为 10000 元/吨,当日到达。
二、问题:
假设这两个物流公司独立运营,拼货只发生在公司内部。你的任务是以最小化单个物流公司的运营成本为目标,为两个物流公司分别设计货车租赁方案和货物运输方案。
三、建模:
需要分别为两个物流公司设计货车租赁方案和货物运输方案,由于物流公司货物当前所在城市相同,只是各城市的备货量不同,为了简化问题,我们可以先为单个物流公司构建模型,之后通过代入不同的参数分别求解两个公司的问题。根据题目已知消息,可以构建优化模型如下:
-
决策变量:
- 卡车运输决策变量
表示从城市i到城市j使用第k辆载重为12吨的卡车。
表示从城市i到城市j使用第k辆载重为5吨的卡车。
- 航空运输决策变量
表示从城市i到城市j通过航空运输的货物重量(吨),实际操作中将其离散化处理,使用多个1吨的单位。
- 中转货物决策变量
表示从城市i向城市j中转的货物重量(吨)
-
目标函数:
需要最小化公司的运输成本,目标函数包括卡车租赁成本、运输成本和航空运输成本
其中,tij表示从城市i 到城市 j 使用卡车运输所需的时间(天);cij 表示从城市 i 到城市 j 使用12吨和5吨卡车的单趟成本;cair表示航空运输每吨货物的成本,为10000元/吨;r分别表示12吨和5吨卡车的日租金,分别为5000元/天与3000元/天;M 表示所需最大卡车数量估计值的一个上界(结合货物数量和卡车运量)。
-
约束条件
(1)需求约束:确保每个目的地城市的需求量得到满足,这里为不等式约束,以确保可以满足需求但不强制所有运输量必须满载:
其中,Dj表示目的地城市 j 的需求量;Si表示出发城市 i 的库存量。
(2)供给约束:确保每个出发城市的供给量不超过其库存
(3)中转约束:确保中转城市的中转平衡,即输入的中转货物等于输出的中转货物
(4)非负约束:所有决策变量均为非负整数
综上,建立公司运输成本最小的0-1规划模型如下:
四、程序:
from ortools.linear_solver import pywraplp
import pandas as pd
# Parameters
city_num = 6 #城市数量
M = 5 #所需最大卡车数量估计值的一个上界(结合货物数量和卡车运量)
S = [29,20,0,0,0,12]#出发城市中含有的货物数量
D = [0,0,19,25,17,0]#目标城市含有的货物数量
C_12 = [[0,13500,26500,16500,13500,8500],#普通卡车A(12 吨)单趟成本 单位:元
[13500,0,18500,20500,10500,3500],
[26500,18500,0,7500,31500,24500],
[16500,20500,7500,0,25500,24500],
[13500,10500,31500,25500,0,5500],
[8500,3500,24500,17500,5500,0]]
C_5 = [[0,11000,24000,14000,11000,6000],#普通卡车B(5 吨)单趟成本 单位:元
[11000,0,16000,18000,8000,1000],
[24000,16000,0,5000,29000,22000],
[14000,18000,5000,0,23000,15000],
[11000,8000,29000,23000,0,3000],
[6000,1000,22000,15000,3000,0]]
T = [[0,3,6,4,3,2],#卡车单趟时间单位:天
[3,0,4,4,2,1],
[6,4,0,2,6,5],
[3,2,6,5,0,1],
[2,1,5,4,1,0]]
C_air = 10000
r_12 = 5000
r_5 = 3000
solver = pywraplp.Solver.CreateSolver('SCIP')
# Define variables.
x = {}#表示从城市i到城市j使用第k辆载重为12吨的卡车
y = {}#表示从城市i到城市j使用第k辆载重为5吨的卡车
z = {}#表示从城市i到城市j通过航空运输的货物重量(吨),实际操作中将其离散化处理,使用多个1吨的单位。
q = {}#表示从城市i向城市j中转的货物重量(吨)
for k in range(M):
for i in range(city_num):
for j in range(city_num):
x[k,i,j] = solver.IntVar(0.0, 1.0, f'r{k}{i}{j}')
y[k,i,j] = solver.IntVar(0.0, 1.0, f's{k}{i}{j}')
for i in range(city_num):
for j in range(city_num):
z[i, j] = solver.IntVar(0.0, 999999.0, f'r{i}{j}')
q[i, j] = solver.IntVar(0.0, 999999.0, f's{i}{j}')
# Define constraints
for j in range(city_num):
solver.Add(sum(sum(12 * x[k, i, j] + 5 * y[k, i, j] for k in range(M)) + z[i, j] + q[i, j] for i in range(city_num)) >= D[j])
for i in range(city_num):
solver.Add(sum(sum(12 * x[k, i, j] + 5 * y[k, i, j] for k in range(M)) + z[i, j] + q[i, j] for j in range(city_num)) <= S[i])
for i in range(city_num):
solver.Add(sum(q[i, j] for j in range(city_num)) == sum(q[j, i] for j in range(city_num)))
for i in range(city_num):
for j in range(city_num):
solver.Add(q[i, j] >= 0)
solver.Add(z[i, j] >= 0)
# Define objective function
Cost_total = sum(sum((C_12[i-1][j-1]+r_12*T[i-1][j-1])*x[k, i, j] + (C_5[i-1][j-1]+r_5*T[i-1][j-1])*y[k, i, j]for k in range (M))+C_air*z[i, j]for i in range(city_num) for j in range(city_num))
solver.Minimize(Cost_total)
# Solve problem
status = solver.Solve()
# Print solution
if status == pywraplp.Solver.OPTIMAL:
print('Total cost =', solver.Objective().Value())
# 下表为最优解中 表示从城市i到城市j通过航空运输的货物重量(吨)
units = pd.DataFrame(columns=range(6), index=range(6), data=0.0)
for i in range (city_num):
for j in range (city_num):
units.loc[i, j] = z[i, j].solution_value()
print("下表为最优解中表示从城市i到城市j通过航空运输的货物重量(吨)")
print(units)
q_out = pd.DataFrame(columns=range(city_num), index=range(6), data=0.0)
trunk_12 = pd.DataFrame(columns=range(city_num), index=range(6), data=0.0)
trunk_5 = pd.DataFrame(columns=range(city_num), index=range(6), data=0.0)
for i in range(city_num):
for j in range(city_num):
q_out.loc[i, j] = q[i, j].solution_value()
print("表示从城市i向城市j中转的货物重量(吨)")
print(q_out)
for k in range(M):
for i in range(city_num):
for j in range(city_num):
trunk_12.loc[i, j] = x[k, i, j].solution_value()
print("下表为从城市i向j中开启的第"+str(k+1)+"辆A类车")
print(trunk_12)
for k in range(M):
for i in range(city_num):
for j in range(city_num):
trunk_5.loc[i, j] = x[k, i, j].solution_value()
print("下表为从城市i向j中开启的第"+str(k+1)+"辆B类车")
print(trunk_5)
else:
print('The problem does not have an optimal solution.')
本文只是记录自己训练过程,不一定正确。