仓库选址问题.Python实例操作

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

目录

前言

一、题目

二、解题思想

2.1 问题1

2.2  问题2

2.3  问题3

总结


先更新部分~~需要数据集可以私信我


前言

        近段时间,训练了一道仓库选址问题研究建模,在这里详细分享给大家我的结题过程.

PS:有错误欢迎指出


一、题目

不多说了,直接上题目


二、解题思想


2.1 问题1

        网上的订货需要在一天内送达,求至少建多少的仓库。这是一道集合覆盖问题。覆盖模型适用于一些特殊场景,例如消防中心、救护车、巡逻车等应急设施的区位选址问题

Step1:处理数据Data_1.xlsx,下面给数据集的预览

 首先,对每个城市按表中数据按1-50进行编号,再将系数矩阵进行补全(这里通过Excel可以手动几步解决)得到下图

 因为题目的要求是一天内送达,所以我们系数矩阵保留所有两城市距离为一天的数据,其余数据都替换为0

# 读取数据
data = pd.read_excel("数据位置")
# 将 Nan 替换为  0
data[1:50].fillna(0,inplace=True)
#删掉无用的列 具体按个人数据实例进行操作
del data['Unnamed: 0']
del data['到达']
data.drop([0],axis=0,inplace=True)
data[1:50].fillna(0,inplace=True)
#大于1的距离进行删除
reachable = data.values #将Excel表中数据存储到数组中
reachable[reachable > 1] = 0

Step2:建立0-1整数规划模型,需要对每个城市建仓库可能性进行尝试

x_i        代表城市i

reachable_{ij}        代表城市间的距离(也可以理解为城市i送达城市j只要一天的集合)

限制条件:\sum x_i\cdot reachable_{ij} \geq 1        即每个城市都可覆盖

目标函数:min\; \sum x_i        求至少需要建立几个仓库

代码实现:

#写问题
SetCoverLP = pulp.LpProblem("SetCover_problem_for_Warehouse", sense=pulp.LpMinimize)
#建立变量x
Zones = list(range(50))
x = pulp.LpVariable.dicts("Zone",Zones,cat="Binary") 
#目标函数    
SetCoverLP += pulp.lpSum(x[i] for i in range(50))
#限制条件
for j in range(50):
    SetCoverLP += (pulp.lpSum([x[i] * reachable[i][j] for i in range(50)]) >= 1)
    
SetCoverLP.solve()

print(SetCoverLP.name)
# 格式化输出
temple = "区域 %(zone)d 的决策是:%(status)s"  
# 获得最优解
y = np.array(range(50))
if pulp.LpStatus[SetCoverLP.status] == "Optimal":  
        for i in range(50):
            if x[i].varValue:#将建仓位置存储到数组中
                y[i] = 1
            else:
                y[i] = 0
            output = {'zone': i+1, 'status': '建仓' if x[i].varValue else '--'}
            print(temple % output)
        print("需要建立 {} 个仓库。".format(pulp.value(SetCoverLP.objective)))

Step3:运行结果得到答案

2.2  问题2

        从第二个问题中,我们知道有两个目的:建尽量少的仓库,最低的消费税负担。

Step1:消费税负担的计量:对于消费者来说他们关心的是购买商品时 需要承担额外的消费税,所以我们使用人均消费税来衡量消费者承担的消费税负担。假设仓库建在第i个城市仓库,计算人均消费税:

XF_i = (fz_i\cdot s1_i+yl_i \cdot s2_i)/rk_i

Step2:加权法系数,标准化统一量纲:通过加权平均法引入系数w,对仓库数量和仓库平均消费税两者进行标准化处理(此处标准化处理我采用的是最大最小法),进行统一,将多目标函数转化为单目标函数:

w_{max}=50                修建仓库的最大数量

w_{min}=18                修建仓库的最小数量

 z_1=\frac{\sum x_i-w_{min}}{w_{max}-w_{min}}                仓库目标

z_2=\frac{\sum XF_i\cdot x_i }{XF_{max} - XF_{min}}                人均消费税目标

目标函数:min\: T=w\cdot z_1+(1-w)\cdot z_2

代码实现:

data1['总税金'] = data1['服装消费']*data1['服装消费税率']*1000 + data1['娱乐设施消费'] * data1['消费税率']*1000
data1['人均税'] = data1['总税金'] / data1['人口']

# print(type(data1['人均消费税']))

m = np.array(data1['人均税'])
reachable = data2.values

Warehouse_max = 50
Warehouse_min = 18

SetCoverLP = pulp.LpProblem("SetCover_problem_for_Warehouse", sense=pulp.LpMinimize)

w=0.8 #可以修改系数
#list1是题一中的建立的仓库,目的计算最小值y[i]*m[i] 即人均消费税
list1=[0,1,0,1,1,1,0,1,0,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1]

y = np.array(list1,dtype="int")

Zones = list(range(50))
x = pulp.LpVariable.dicts("Zone",Zones,cat="Binary") 

Z_1 = (pulp.lpSum(x[i] for i in range(50)) - Warehouse_min) / (Warehouse_max - Warehouse_min)

Z_2 = (pulp.lpSum(x[i]*m[i] for i in range(50)) - pulp.lpSum(y[i]*m[i] for i in range(50)))  / (pulp.lpSum(m[i] for i in range(50)) - pulp.lpSum(y[i]*m[i] for i in range(50)))

SetCoverLP += (w * Z_1 + (1 - w) * Z_2)

for j in range(50):
    SetCoverLP += (pulp.lpSum([x[i] * reachable[i][j] for i in range(50)]) >= 1)


SetCoverLP.solve()



print(SetCoverLP.name)


temple = "区域 %(zone)d 的决策是:%(status)s" 
n = 0
y = np.array(range(50))
if pulp.LpStatus[SetCoverLP.status] == "Optimal":  
        for i in range(50):
            if x[i].varValue:
                n += 1
                y[i] = 1
            else:
                y[i] = 0
            output = {'zone': i+1, 'status': '建仓'   if x[i].varValue  else '--'}
            print(temple % output)
        print("目标函数全局最优解为:{}。".format(pulp.value(SetCoverLP.objective)))
        print("共建仓数:",n,"个")

Step3:运行结果得到答案:

2.3  问题3

总结

多进行实战练习,多总结才是提升自己的良好途径

物联沃分享整理
物联沃-IOTWORD物联网 » 仓库选址问题.Python实例操作

发表评论