作者:下里巴人

来自南京审计大学

前言:

本篇文章主要记录一下本次慧发发项目中,实现根据货物目的地自动判定物流园选择的矩阵并进行优化的过程。

算法原理

原理图如下:

我们需要完成的是,在一张表中,显示出所有符合要求的方案,也就是输入货物目的地,最终输出 Cij,以便后续的规划算法。

算法实现

第一版算法如下

Models

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

#初始化货物类
class Goods:

def __init__(self,destination,deadline,weight,volume):
#定义了该批货品的目的地
self.destination = destination
#定义了货品的发货截止日期
self.deadline = deadline
#定义了货品的重量
self.weight = weight
#定义了货品的体积
self.volume = volume

#初始化物流园类
class Logistics:

def __init__(self,name,Latitude_and_longitude,rates):
#定义了物流园的名称
self.name = name
#定义了经纬度
self.Latitude_and_longitude = Latitude_and_longitude
#定义了物流园中的商户(多个,类型为列表)
self.commercial_tenants = []
#定义了物流园的进场费
self.rates = rates

def add_commercial_tenant(self,commercial_tenant):
#定义添加物流园专线的方法
self.commercial_tenants.append(commercial_tenant)

#初始化物流园专线
class Commercial_tenant:

def __init__(self,site,price,time_consuming,interval):
#定义了物流园的目的地
self.site = site
#定义了发货单价
self.price = price
#定义了发货耗时
self.time_consuming = time_consuming
#定义了发货间隔
self.interval = interval

#创建两个物流商户实例
chengdu_site1 = Commercial_tenant('chengdu',15,4,3)
changsha_site1 = Commercial_tenant('changsha',12,4,2)
wuhan_site1 = Commercial_tenant('wuhan',8,3,2)
nanchang_site1 = Commercial_tenant('nanchang',15,3,2)

chengdu_site2 = Commercial_tenant('chengdu',7,4,3)
changsha_site2 = Commercial_tenant('changsha',16,4,2)
luoyang_site2 = Commercial_tenant('luoyang',8,3,2)
zhenzhou_site2 = Commercial_tenant('zhenzhou',15,3,2)

chengdu_site3 = Commercial_tenant('chengdu',41,4,3)
changsha_site3 = Commercial_tenant('changsha',17,4,2)
nanyang_site3 = Commercial_tenant('nanyang',8,3,2)
hefei_site4 = Commercial_tenant('heifei',15,3,2)

chengdu_site4 = Commercial_tenant('chengdu',21,4,3)
changsha_site4 = Commercial_tenant('changsha',13,4,2)
beijin_site4 = Commercial_tenant('beijin',8,3,2)
nancahng_site4 = Commercial_tenant('nanchang',15,3,2)

#创建一个物流园实例
wuliuyuan1 = Logistics(1,'13.173;31.321',15)
wuliuyuan2 = Logistics(2,'12.125;35.321',10)
wuliuyuan3 = Logistics(3,'13.553;34,321',15)
wuliuyuan4 = Logistics(4,'12.123;34.111',10)

#将物流园专线添加至实例中
wuliuyuan1.add_commercial_tenant(chengdu_site1)
wuliuyuan1.add_commercial_tenant(changsha_site1)
wuliuyuan1.add_commercial_tenant(wuhan_site1)
wuliuyuan1.add_commercial_tenant(nanchang_site1)

wuliuyuan2.add_commercial_tenant(chengdu_site2)
wuliuyuan2.add_commercial_tenant(changsha_site2)
wuliuyuan2.add_commercial_tenant(luoyang_site2)
wuliuyuan2.add_commercial_tenant(zhenzhou_site2)

wuliuyuan3.add_commercial_tenant(chengdu_site3)
wuliuyuan3.add_commercial_tenant(changsha_site3)
wuliuyuan3.add_commercial_tenant(nanyang_site3)
wuliuyuan3.add_commercial_tenant(hefei_site4)

wuliuyuan4.add_commercial_tenant(chengdu_site4)
wuliuyuan4.add_commercial_tenant(changsha_site4)
wuliuyuan4.add_commercial_tenant(beijin_site4)
wuliuyuan4.add_commercial_tenant(nancahng_site4)

#添加货物实例destination,deadline,weight,volume
huowu1 = Goods('chengdu','2023/3/10',1,1)
huowu2 = Goods('changsha','2023/3/10',1,1)
huowu3 = Goods('nanyang','2023/3/10',1,1)

Sizer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from Models import *
import math
import time
import datetime


# 初始化一个i*j的二维列表,i为物流园实例数,j为此次货物实例数,值均为M(无限大)
table = [[math.inf for i in range(4)] for j in range(3)]

#货物目的地列表
V = [huowu1.destination,huowu2.destination,huowu3.destination]
#定义了一个时间格式化的函数
def format_time(x):

formattime = datetime.datetime.strptime(x,r'%Y/%m/%d')

return formattime
#货物截止时间列表
T = list(map(format_time,[huowu1.deadline,huowu2.deadline,huowu3.deadline]))
#货物目的地对应截止日期的字典
V_T = dict(zip(V,T))
#每个物流园商户具有的地点列表
S1_site = [s.site for s in wuliuyuan1.commercial_tenants]
S2_site = [s.site for s in wuliuyuan2.commercial_tenants]
S3_site = [s.site for s in wuliuyuan3.commercial_tenants]
S4_site = [s.site for s in wuliuyuan4.commercial_tenants]
#定义每个物流园商户具有的价格列表
S1_price = [s.price for s in wuliuyuan1.commercial_tenants]
S2_price = [s.price for s in wuliuyuan2.commercial_tenants]
S3_price = [s.price for s in wuliuyuan3.commercial_tenants]
S4_price = [s.price for s in wuliuyuan4.commercial_tenants]
#定义了每个物流园商户对应的地点和价格字典
S_P1 = dict(zip(S1_site,S1_price))
S_P2 = dict(zip(S2_site,S2_price))
S_P3 = dict(zip(S3_site,S3_price))
S_P4 = dict(zip(S4_site,S4_price))
#定义总地点列表
S_site = [S1_site,S2_site,S3_site,S4_site]
#定义总地点价格对应列表
S_P = [S_P1,S_P2,S_P3,S_P4]
for s , m in zip(S_site,S_P):

if set(s) & set(V) != []:

intersection = list(set(s) & set(V))

for i in intersection:

if i == 'nanyang':

row = 0

col = S_site.index(s)

value = m[i]

table[row][col] = value

elif i == 'changsha':

row = 1

col = S_site.index(s)

value = m[i]

table[row][col] = value

elif i == 'chengdu':

row = 2

col = S_site.index(s)

value = m[i]

table[row][col] = value

else:
pass
else:

pass
print(table)

缺陷

  • 数据结构简单,为列表,导致逻辑过于繁杂
  • 代码死板,无法实现自动化

根据老师建议,做出如下调整:

  • 数据结构替换为DataFrame
  • 重构代码,实现自动化

Models

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

#初始化货物类
class Goods:

def __init__(self,destination,deadline,weight,volume):
#定义了该批货品的目的地
self.destination = destination
#定义了货品的发货截止日期
self.deadline = deadline
#定义了货品的重量
self.weight = weight
#定义了货品的体积
self.volume = volume

#初始化物流园类
class Logistics:

def __init__(self,name,Latitude_and_longitude,rates):
#定义了物流园的名称
self.name = name
#定义了经纬度
self.Latitude_and_longitude = Latitude_and_longitude
#定义了物流园中的商户(多个,类型为列表)
self.commercial_tenants = []
#定义了物流园的进场费
self.rates = rates

def add_commercial_tenant(self,commercial_tenant):
#定义添加物流园专线的方法
self.commercial_tenants.append(commercial_tenant)

#初始化物流园专线
class Commercial_tenant:

def __init__(self,site,price,time_consuming,interval):
#定义了物流园的目的地
self.site = site
#定义了发货单价
self.price = price
#定义了发货耗时
self.time_consuming = time_consuming
#定义了发货间隔
self.interval = interval

#创建两个物流商户实例
chengdu_site1 = Commercial_tenant('chengdu',15,4,3)
changsha_site1 = Commercial_tenant('changsha',12,4,2)
wuhan_site1 = Commercial_tenant('wuhan',8,3,2)
nanchang_site1 = Commercial_tenant('nanchang',15,3,2)

chengdu_site2 = Commercial_tenant('chengdu',7,4,3)
changsha_site2 = Commercial_tenant('changsha',16,4,2)
luoyang_site2 = Commercial_tenant('luoyang',8,3,2)
zhenzhou_site2 = Commercial_tenant('zhenzhou',15,3,2)

chengdu_site3 = Commercial_tenant('chengdu',41,4,3)
changsha_site3 = Commercial_tenant('changsha',17,4,2)
nanyang_site3 = Commercial_tenant('nanyang',8,3,2)
hefei_site4 = Commercial_tenant('heifei',15,3,2)

chengdu_site4 = Commercial_tenant('chengdu',21,4,3)
changsha_site4 = Commercial_tenant('changsha',13,4,2)
beijin_site4 = Commercial_tenant('beijin',8,3,2)
nancahng_site4 = Commercial_tenant('nanchang',15,3,2)

#创建一个物流园实例
wuliuyuan1 = Logistics(1,'13.173;31.321',15)
wuliuyuan2 = Logistics(2,'12.125;35.321',10)
wuliuyuan3 = Logistics(3,'13.553;34,321',15)
wuliuyuan4 = Logistics(4,'12.123;34.111',10)

#将物流园专线添加至实例中
wuliuyuan1.add_commercial_tenant(chengdu_site1)
wuliuyuan1.add_commercial_tenant(changsha_site1)
wuliuyuan1.add_commercial_tenant(wuhan_site1)
wuliuyuan1.add_commercial_tenant(nanchang_site1)

wuliuyuan2.add_commercial_tenant(chengdu_site2)
wuliuyuan2.add_commercial_tenant(changsha_site2)
wuliuyuan2.add_commercial_tenant(luoyang_site2)
wuliuyuan2.add_commercial_tenant(zhenzhou_site2)

wuliuyuan3.add_commercial_tenant(chengdu_site3)
wuliuyuan3.add_commercial_tenant(changsha_site3)
wuliuyuan3.add_commercial_tenant(nanyang_site3)
wuliuyuan3.add_commercial_tenant(hefei_site4)

wuliuyuan4.add_commercial_tenant(chengdu_site4)
wuliuyuan4.add_commercial_tenant(changsha_site4)
wuliuyuan4.add_commercial_tenant(beijin_site4)
wuliuyuan4.add_commercial_tenant(nancahng_site4)

Sizer2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

from Models import *
import math
import pandas as pd


def create_df():

table = [[math.inf for i in range(4)] for j in range(len(destination))]

df = pd.DataFrame(table,columns=['P1','P2','P3','P4'],index=destination)

return df




if __name__ == "__main__":

#添加货物实例destination,deadline,weight,volume
destination = input(str('请输入您此次货物的目的地,用英文,分隔:''请输入您此次货物的目的地,用英文,分隔:')).split(',')

deadline = input(str('请输入对应货物的截止日期,格式形如:2023/3/21,用英文,分隔:')).split(',')

weight = input(str('请输入货物对应的重量,单位kg,以英文,分隔:')).split(',')

volume = input(str('请输入货物的体积,单位m³,以英文,分隔:')).split(',')

#循环创建动态对象
for a , b , c , d , goods_name in zip(destination,deadline,weight,volume,destination):

locals()[goods_name] = Goods(a,b,c,d)

df = create_df()

#每个物流园商户具有的地点列表
S1_site = [s.site for s in wuliuyuan1.commercial_tenants]
S2_site = [s.site for s in wuliuyuan2.commercial_tenants]
S3_site = [s.site for s in wuliuyuan3.commercial_tenants]
S4_site = [s.site for s in wuliuyuan4.commercial_tenants]
#定义每个物流园商户具有的价格列表
S1_price = [s.price for s in wuliuyuan1.commercial_tenants]
S2_price = [s.price for s in wuliuyuan2.commercial_tenants]
S3_price = [s.price for s in wuliuyuan3.commercial_tenants]
S4_price = [s.price for s in wuliuyuan4.commercial_tenants]
#定义了每个物流园商户对应的地点和价格字典
S_P1 = dict(zip(S1_site,S1_price))
S_P2 = dict(zip(S2_site,S2_price))
S_P3 = dict(zip(S3_site,S3_price))
S_P4 = dict(zip(S4_site,S4_price))
#定义总地点列表
S_site = [S1_site,S2_site,S3_site,S4_site]
#定义总地点价格对应列表
S_P = [S_P1,S_P2,S_P3,S_P4]
for s in S_site:

intersection = list(set(s) & set(destination))

if intersection != []:

for p , num in zip(['P1','P2','P3','P4'],S_P):

for i in intersection:

df[p][i] = num.get(i)

else:

pass
print(df)