用Gurobi+python求解设施选址问题(facility location)
创始人
2024-04-24 18:50:40

参考:Gurobi 官方资源

设施选址(Facility Location)

1.背景介绍

设施选址问题在许多工业领域如物流,通信等都有应用,在本案例中展示如何解决设施选址问题,决策出仓库的数量和地点,为一些超市供应。求解思路:问题建模成混合整数规划问题,用python调用Gurobi求解器实现。

设施选址问题也称为选址分析(location analysis),是运筹优化领域的一个重要分支,要求选出设施的最佳位置,从而减小运输成本,同时考虑一些其它因素,如安全(避免在靠近居民地的地方存储有害物质)和竞争者的设施位置。

设施选址问题在很多领域都有应用,对于供应链和物流管理,这个问题可以用来找到商店,工厂和仓库的最佳位置,其它应用如公共策略(在城市中部署警局),通信(网络中的手机信号塔),甚至是粒子物理学(排斥电荷之间的间隔距离),天然气输送装备的选址等。最后,可以将设施点位置问题应用于聚类分析。

2.问题描述

一个大型的超市连锁店想要为它的一些超市修建仓库,超市的位置都已知,但是仓库的位置还没决定。
仓库选址有几个候选地,需要决定出修建几个仓库和确定这些仓库的位置。
修建仓库越多,就能减少卡车从仓库到超市的运输距离,因此减少运输成本,但是开设一个仓库有一个固定成本。
优化目标是最小化总成本=开始仓库固定成本+仓库到超市运输成本。

3.MIP模型

建立数学规划模型用gurobi求解,一个数学优化模型有5个部分:

  • 集合和索引(Sets and indices)
  • 参数(Parameters)
  • 决策变量(Decision variables)
  • 目标函数(Objective function(s))
  • 约束条件(Constraints)

接下来为设施选址问题构建MIP模型

(1)集合和索引

i∈Ii \in Ii∈I: 超市(顾客)位置的索引和集合.

j∈Jj \in Jj∈J: 候选仓库(设施)位置的索引和集合.

(2)参数

fj∈R+f_{j} \in \mathbb{R}^+fj​∈R+: 修建设施 j∈Jj \in Jj∈J 的固定成本.

di,j∈R+d_{i,j} \in \mathbb{R}^+di,j​∈R+: 设施 j∈Jj \in Jj∈J 和客户 i∈Ii \in Ii∈I 的距离.

ci,j∈R+c_{i,j} \in \mathbb{R}^+ci,j​∈R+: 候选设施地点 j∈Jj \in Jj∈J 和客户点 i∈Ii \in Ii∈I 的运输成本. 假设成本和距离成比例. 因此 ci,j=α⋅di,jc_{i,j} = \alpha \cdot d_{i,j}ci,j​=α⋅di,j​, α\alphaα 是单位运输成本.

(3)决策变量

selectj∈{0,1}select_{j} \in \{0, 1 \}selectj​∈{0,1}: 如果在候选设施点 j∈Jj \in Jj∈J 修建,值为1; 否则为0

0≤assigni,j≤10 \leq assign_{i,j} \leq 10≤assigni,j​≤1: 非负连续变量,表明客户 i∈Ii \in Ii∈I 从设施 j∈Jj \in Jj∈J 接收需求的比例.

(4)目标函数

在这里插入图片描述

(5)约束条件

在这里插入图片描述

4.python调用gurobi实现

本例中考虑2个超市和9个候选仓库,每个超市的位置坐标如下

Coordinates
Supermarket 1(0,1.5)
Supermarket 2(2.5,1.2)

下面的表格是候选仓库的坐标和修建固定成本,单位millions GBP

coordinatesfixed cost
Warehouse 1(0,0)3
Warehouse 2(0,1)2
Warehouse 3(0,2)3
Warehouse 4(1,0)1
Warehouse 5(1,1)3
Warehouse 6(1,2)3
Warehouse 7(2,0)4
Warehouse 8(2,1)3
Warehouse 9(2,2)2

每mile的运输成本是1 million GBP

现在导入gurobi和其它python库,初始化给定数据的数据结构

from itertools import product
from math import sqrtimport gurobipy as gp
from gurobipy import GRBcustomers = [(0,1.5), (2.5,1.2)]
facilities = [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2)]
setup_cost = [3,2,3,1,3,3,4,3,2]
cost_per_mile = 1

(1)预处理

定义一个函数,用于计算每个设施和客户之间的欧式距离,获取MIP模型需要的关键参数

# 计算两个地方的欧式距离
def compute_distance(loc1, loc2):dx = loc1[0] - loc2[0]dy = loc1[1] - loc2[1]return sqrt(dx*dx + dy*dy)num_facilities = len(facilities)
num_customers = len(customers)
cartesian_prod = list(product(range(num_customers), range(num_facilities)))# 每对客户和设施的运输成本
shipping_cost = {(c,f):cost_per_mile * compute_distance(customers[c], facilities[f]) for c,f in cartesian_prod}shipping_cost
{(0, 0): 1.5,(0, 1): 0.5,(0, 2): 0.5,(0, 3): 1.8027756377319946,(0, 4): 1.118033988749895,(0, 5): 1.118033988749895,(0, 6): 2.5,(0, 7): 2.0615528128088303,(0, 8): 2.0615528128088303,(1, 0): 2.773084924772409,(1, 1): 2.5079872407968904,(1, 2): 2.6248809496813377,(1, 3): 1.9209372712298547,(1, 4): 1.5132745950421556,(1, 5): 1.7,(1, 6): 1.3,(1, 7): 0.5385164807134504,(1, 8): 0.9433981132056605}

(2)模型部署

现在定义设施选址问题的MIP模型,包括决策变量,约束和目标函数。然后开始优化过程,Gurobi找到能最小化总成本的修建方案

# 模型
m = gp.Model('facility_location')# 两个决策变量
select = m.addVars(num_facilities, vtype=GRB.BINARY, name='select')
assign = m.addVars(cartesian_prod, ub=1, vtype=GRB.CONTINUOUS, name='assign')# 两个约束条件
m.addConstrs((assign[c,f] <= select[f] for c,f in cartesian_prod), name='Setup2ship')
m.addConstrs((gp.quicksum(assign[c,f] for f in range(num_facilities)) == 1 for c in range(num_customers)),name='demand')# 目标函数
m.setObjective(select.prod(setup_cost) + assign.prod(shipping_cost), GRB.MINIMIZE)# 优化
m.optimize()
Set parameter Username
Academic license - for non-commercial use only - expires 2023-10-24
Gurobi Optimizer version 9.5.2 build v9.5.2rc0 (mac64[rosetta2])
Thread count: 8 physical cores, 8 logical processors, using up to 8 threads
Optimize a model with 20 rows, 27 columns and 54 nonzeros
Model fingerprint: 0x0939f503
Variable types: 18 continuous, 9 integer (9 binary)
Coefficient statistics:Matrix range     [1e+00, 1e+00]Objective range  [5e-01, 4e+00]Bounds range     [1e+00, 1e+00]RHS range        [1e+00, 1e+00]
Presolve time: 0.01s
Presolved: 20 rows, 27 columns, 54 nonzeros
Variable types: 18 continuous, 9 integer (9 binary)
Found heuristic solution: objective 6.0385165Root relaxation: objective 4.723713e+00, 15 iterations, 0.00 seconds (0.00 work units)Nodes    |    Current Node    |     Objective Bounds      |     WorkExpl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time*    0     0               0       4.7237129    4.72371  0.00%     -    0sExplored 1 nodes (15 simplex iterations) in 0.03 seconds (0.00 work units)
Thread count was 8 (of 8 available processors)Solution count 2: 4.72371 6.03852 Optimal solution found (tolerance 1.00e-04)
Best objective 4.723712908962e+00, best bound 4.723712908962e+00, gap 0.0000%

5.结果分析

优化模型结果显示最小成本是4.72 million GBP

(1)仓库修建计划

接下来看一下仓库修建选址决策:在位置4修建一个仓库

for facility in select.keys():if (abs(select[facility].x) > 1e-6):print(f"\n Build a warehouse at location {facility + 1}.")
 Build a warehouse at location 4.

(2)运输计划

运输计划表明了从每个修建的设施运送到每个客户的比例:两个超市都由仓库4供货

for customer, facility in assign.keys():if (abs(assign[customer, facility].x)) > 1e-6:print(f"\n Supermarket {customer + 1} receives {round(100*assign[customer, facility].x, 2)} % of its demand  from Warehouse {facility + 1} .")
 Supermarket 1 receives 100.0 % of its demand  from Warehouse 4 .Supermarket 2 receives 100.0 % of its demand  from Warehouse 4 .

相关内容

热门资讯

猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...