用Gurobi+python求解设施选址问题(facility location)

news/2024/11/18 12:45:30/

参考: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 IiI: 超市(顾客)位置的索引和集合.

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

(2)参数

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

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

ci,j∈R+c_{i,j} \in \mathbb{R}^+ci,jR+: 候选设施地点 j∈Jj \in JjJ 和客户点 i∈Ii \in IiI 的运输成本. 假设成本和距离成比例. 因此 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 JjJ 修建,值为1; 否则为0

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

(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 .

http://www.ppmy.cn/news/4152.html

相关文章

turbo编码原理

一、原理 Turbo的编码器由两个并行的分量编码器组成。分量编码器的选择一般是卷积码。在Turbo码中&#xff0c;输入序列在进入第二个编码器时须经过一个交织器 &#xff0c;用于将序列打乱。两个编码器的输出共同作为冗余信息添加到信息序列之后&#xff0c;对抗信道引起的错误…

基于场景的数据集------明厨亮灶数据集

为了和各位开发爱好者深入合作交流&#xff0c;特此准备分批次开放数据集拱大家交流学士研究使用&#xff0c;整理的非常细腻&#xff0c;有些是专业队伍标注的&#xff0c;主要是菲律宾那边的团队进行标注的。依据众多算法搭建的算法平台主体算法包括 人脸识别&#xff0c;人…

Web(十)JavaScript语言基础-JS条件语句

第1关&#xff1a;if-else类型 编程要求 本关的编程任务是补全右侧代码片段中Begin至End中间的代码&#xff0c;具体要求如下&#xff1a; 根据分数a&#xff08;百分制&#xff09;返回考试结果&#xff1b; a小于60分返回unpass&#xff0c;否则返回pass&#xff1b; 本题…

哈希表及其与Java类集的关系

目录 1.哈希表的概念 2.哈希冲突 3.如何避免哈希冲突? 3.1哈希函数设计 3.2 负载因子的调节 4.解决哈希冲突 4.1闭散列 4.1.1线性探测 4.1.2二次探测 4.2开散列(哈希桶) 5.HashMap 6.HashSet 1.哈希表的概念 假设有一组数据,要让你去搜索其中的一个关键码,这种场…

【AIOT】蓝牙调研

经典蓝牙模块&#xff08;BT&#xff09;&#xff1a;泛指支持蓝牙协议在4.0以下的模块&#xff0c;一般用于数据量比较大的传输&#xff0c;如&#xff1a;语音、音乐等较高数据量传输。经典蓝牙模块可再细分为&#xff1a;传统蓝牙模块和高速蓝牙模块。传统蓝牙模块在2004年推…

高通平台开发系列讲解(DSI篇)DSI函数的内部逻辑

文章目录 一、dsi_start_data_call函数二、dsi_get_pkt_stats函数三、dsi_stop_data_call函数四、回调流程沉淀、分享、成长,让自己和他人都能有所收获!😄 📢DSI层最上层函数位于dsi_netctrl.c中,该.c位于apps_proc/data/dsi_netctrl目录中,现对部分主要函数的调用流程进…

智慧物流|Springboot+Vue+Nodejs实现智慧物流系统

作者主页&#xff1a;编程千纸鹤 作者简介&#xff1a;Java、前端、Pythone开发多年&#xff0c;做过高程&#xff0c;项目经理&#xff0c;架构师 主要内容&#xff1a;Java项目开发、毕业设计开发、面试技术整理、最新技术分享 收藏点赞不迷路 关注作者有好处 文末获得源码 …

【链表面试题】——剑指 Offer : 复杂链表(带随机指针)的复制

文章目录前言1.题目介绍2. 题目分析3. 思路讲解思路1思路24. 分析图及源码展示前言 这篇文章&#xff0c;我们一起来解决一道与链表相关的经典面试题&#xff1a;复杂链表&#xff08;带随机指针&#xff09;的复制。 1.题目介绍 我们先来一起了解一下这道题&#xff1a; 这道…