当前位置: 首页 > news >正文

Capacitated Facility Location Problem

文章目录

  • Capacitated Facility Location Problem
    • [更多技术博客 http://vilins.top/](http://vilins.top/)
    • 题目
    • 分析
    • 实验工具
    • 解决算法
      • 模拟退火法
      • 禁忌搜索
    • 算法局部设计细节
      • 模拟退火法
      • 禁忌搜索
    • 结果整理
    • 两种做法的对比
    • 原始输出结果
    • 程序运行说明
    • 源码
    • github
    • [更多技术博客 http://vilins.top/](http://vilins.top/)

Capacitated Facility Location Problem

更多技术博客 http://vilins.top/

题目

分析

选址问题在生产生活,物流,甚至军事中都有这非常广泛的应用,以成为运筹学中经典的问题之一,其目的是确定一个或者多个设施的地址,使得判断标准获得优化的同时,及时向顾客提供其所需的产品和服务。工厂选址问题不仅影响到工厂的利润和市场竞争力,甚至决定了工厂的生死存亡。所以,工厂选址的研究具有重要意义。
这类问题在论文中出现得比较多,而网上现成的以实现的办法几乎没有,很多都是从理论层面上分析解决这类问题的可行性,而没有实操去证明其可行性。由于这类问题属于优化类问题,在线性时间很难求得其最优解,所以我们选择算法的时候一般选择优化类算法,动态规划之类的算法是行不通的,一般用于解决这类问题的办法有蚁群算法,遗传算法,贪婪算法,模拟退火法,禁忌搜索算法,近似算法等。
具体到这个题目,我们首先分析其限制的条件,这是一类有容量限制的工厂问题,具体限制如下:

总花费(total cost) = 工厂开放花费(opening cost) + 顾客分配到某个工厂以后的路程花费(assginment cost)

实验工具

语言:python
工具:Pycharm

解决算法

模拟退火法

禁忌搜索

算法局部设计细节

模拟退火法

初始解的产生,采用完全随机化选择部分工厂开放,但不让所有的工厂开放,符合一般最优化表现形式,表现最好。

def init_solution(self): for i in range(self.customer_num): self.current_state_of_customer.append(-1) for i in self.demand: self.total_demand += i self.current_capacity = self.capacity.copy() total_cost = 0 temp = [] while total_cost < self.total_demand: r = random.randint(0, self.facility_num - 1) if r not in temp: temp.append(r) total_cost += self.capacity[r] index = 0 for i in range(self.customer_num): if self.current_capacity[temp[index]] - self.demand[i] >= 0: self.current_capacity[temp[index]] -= self.demand[i] self.current_state_of_customer[i] = temp[index] else: index += 1 i -= 1 # self.current_state_of_customer[i] = index # self.current_capacity[index] -= self.demand[i] self.current_cost = self.calculate_cost(self.current_state_of_customer) self.new_capacity = self.current_capacity.copy() self.new_state_of_customer = self.current_state_of_customer.copy()

初始化解,利用局部贪婪,可以调节贪婪的比例,但效果不太好

def init_solution(self): for i in range(self.customer_num): self.current_state_of_customer.append(-1) for i in self.demand: self.total_demand += i self.current_capacity = self.capacity.copy() for i in range(self.customer_num): ran_select = random.random() if ran_select > 0.2: min = 100000 index = 0 for j in range(self.facility_num): if min > self.assignment[j][i]: min = self.assignment[j][i] index = j if self.current_capacity[index] >= self.demand[i]: self.current_capacity[index] -= self.demand[i] self.current_state_of_customer[i] = index else: tag = True while tag: ran = random.randint(0, self.facility_num - 1) if self.current_capacity[ran] >= self.demand[i]: self.current_capacity[ran] -= self.demand[i] self.current_state_of_customer[i] = ran tag = False else: tag_out = True while tag_out: ran = random.randint(0, self.facility_num - 1) if self.current_capacity[ran] >= self.demand[i]: self.current_capacity[ran] -= self.demand[i] self.current_state_of_customer[i] = ran tag_out = False self.current_cost = self.calculate_cost(self.current_state_of_customer) self.new_capacity = self.current_capacity.copy() self.new_state_of_customer = self.current_state_of_customer.copy() print('cost ', self.current_cost) print('current cap ', self.current_capacity) print('current cu ', self.current_state_of_customer)

产生新解的方式

def gen_new_solution(self): tag = True self.new_capacity = self.current_capacity.copy() self.new_state_of_customer = self.current_state_of_customer.copy() while tag: ran_customer = random.randint(0, self.customer_num - 1) ran_facility = random.randint(0, self.facility_num - 1) # print("ran ", ran_facility, ran_customer) if self.new_capacity[ran_facility] >= self.demand[ran_customer]: tag = False self.new_capacity[ran_facility] -= self.demand[ran_customer] origin = self.new_state_of_customer[ran_customer] self.new_state_of_customer[ran_customer] = ran_facility if origin == -1: break self.new_capacity[origin] += self.demand[ran_customer] else: continue

退火过程

def simulated_annealing(self): global fp_anneal time_start = time.time() while self.T > 0.01: i = 0 while i < self.repeat: i += 1 self.gen_new_solution() self.current_cost = self.calculate_cost(self.current_state_of_customer) new_cost = self.calculate_cost(self.new_state_of_customer) if new_cost < self.current_cost: self.current_capacity = self.new_capacity.copy() self.current_state_of_customer = self.new_state_of_customer.copy() # print("current cost ", new_cost) else: num = math.exp((self.current_cost - new_cost) / self.T) ran = random.random() # print("num ", num) # print("ran ", ran) if num >= ran: self.current_capacity = self.new_capacity.copy() self.current_state_of_customer = self.new_state_of_customer.copy() # print("current cost ", new_cost) self.T *= self.cooling_rate time_end = time.time() used_time = time_end - time_start fp_anneal.write('time ' + str(used_time) + '\n') fp_anneal.write('cost ' + str(self.current_cost) + '\n') temp = [] result_state = [] for i in range(self.customer_num): if self.current_state_of_customer[i] not in temp: temp.append(self.new_state_of_customer[i]) temp.sort() for i in range(self.facility_num): result_state.append(0) for i in temp: result_state[i] = 1 # print('cost ' + str(self.current_cost)) # print(result_state) # print(self.current_state_of_customer) # print(self.current_capacity) fp_anneal.write('facility state ' + str(result_state) + '\n') fp_anneal.write('current state of customer ' + str(self.current_state_of_customer) + '\n\n')

禁忌搜索

新解产生与模拟退火类似
邻居的产生

def gen_nei_solution(self): tag = True self.nei_capacity = self.current_capacity.copy() self.nei_state_of_customer = self.current_state_of_customer.copy() ran_customer = 0 origin = 0 while tag: ran_customer = random.randint(0, self.customer_num - 1) ran_facility = random.randint(0, self.facility_num - 1) # print("ran ", ran_facility, ran_customer) if self.nei_capacity[ran_facility] >= self.demand[ran_customer]: tag = False self.nei_capacity[ran_facility] -= self.demand[ran_customer] origin = self.nei_state_of_customer[ran_customer] self.nei_state_of_customer[ran_customer] = ran_facility if origin == -1: break self.nei_capacity[origin] += self.demand[ran_customer] else: continue return ran_customer, origin

禁忌搜索过程

def tabu_search(self): global fp_tabu self.nei_state_of_customer = self.current_state_of_customer.copy() self.nei_capacity = self.current_capacity.copy() # print(self.current_state_of_customer) # print(self.nei_capacity) self.tabu_list = [[0 for i in range(self.customer_num)]for i in range(self.facility_num)] # print(tabu_list) repeat = 30000 count = 0 nei_count = int(self.customer_num/4) best_solution_customer = self.current_state_of_customer.copy() best_solution_capacity = self.current_capacity.copy() best_cost = self.calculate_cost(best_solution_customer) time_start = time.time() while count < repeat: count += 1 i = nei_count self.gen_new_solution() new_cost = self.calculate_cost(self.new_state_of_customer) ran_customer = 0 origin = 0 while i > 1: i -= 1 ran_customer, origin = self.gen_nei_solution() nei_cost = self.calculate_cost(self.nei_state_of_customer) # print("nei ", nei_cost) # print("new ", new_cost) if nei_cost < new_cost: self.new_state_of_customer = self.nei_state_of_customer.copy() self.new_capacity = self.nei_capacity.copy() new_cost = nei_cost if new_cost < best_cost: # print("new ", new_cost) best_solution_customer = self.new_state_of_customer.copy() best_solution_capacity = self.new_capacity.copy() best_cost = new_cost if self.tabu_list[origin][ran_customer] < count: self.tabu_list[origin][ran_customer] = count + 20 self.current_state_of_customer = self.new_state_of_customer.copy() self.current_capacity = self.new_capacity.copy() time_end = time.time() used_time = time_end - time_start temp = [] result_state = [] for i in range(self.customer_num): if best_solution_customer[i] not in temp: temp.append(best_solution_customer[i]) temp.sort() for i in range(self.facility_num): result_state.append(0) for i in temp: result_state[i] = 1 fp_tabu.write('time ' + str(used_time) + '\n') fp_tabu.write('cost ' + str(best_cost) + '\n') fp_tabu.write('facility state ' + str(result_state) + '\n') fp_tabu.write('customer state ' + str(best_solution_customer) + '\n\n') print(best_cost) print(result_state) print(best_solution_customer) print(best_solution_capacity)

结果整理

fileresulttimeresulttime
模拟退火法模拟退火法禁忌搜索禁忌搜索
p190335.12332606315612889859.848682165145874
p280055.52882313728332579409.718816757202148
p393145.13923668861389296789.466161012649536
p4116285.307790279388428109549.69756555557251
p591315.344730377197266913710.06436276435852
p677815.39656233787536679079.97243070602417
p795775.525223731994629962510.066269397735596
p8114395.5332002639770511143310.113304615020752
p985934.83005332946777390318.910385608673096
p1076484.93875694274902377249.172668695449829
p1192265.14822697639465390628.851669073104858
p12110334.917876720428467102778.693775177001953
p1393125.169209718704224960410.038275718688965
p1471645.242977142333984820410.189182996749878
p1589645.441417932510376103359.89920711517334
p16119255.371662139892578124969.891655445098877
p1792785.45040369033813597959.87352442741394
p1877815.39055061340332826510.18008804321289
p1992675.236989974975586104089.878618240356445
p20117585.060497522354126125939.863529920578003
p2192954.85899639129638791039.683191061019897
p2277385.12528634071350180889.918416261672974
p2396545.08836030960083100709.597949266433716
p24112634.70444393157959118009.354219436645508
p251228112.8904881477355961358967.44565677642822
p261162313.5537416934967041125470.20729756355286
p271357413.0281190872192381337766.27394366264343
p281572913.245565891265871757267.49193954467773
p291351013.50685191154481368372.6292462348938
p301189413.906796693801881179772.82930493354797
p311482313.6664142608642581441272.44930481910706
p321773312.950354576110841670872.29048991203308
p331253612.9812731742858891234367.8763542175293
p341158213.5367550849914551114269.67934989929199
p351448713.4699332714080811309968.77509903907776
p361568813.1477956771850591732067.9144344329834
p371220012.650130748748781224867.00625324249268
p381128313.4859235286712651117067.53133893013
p391348013.1727778911590581286265.43386697769165
p401568213.0899877548217771556964.73360013961792
p4170088.108281373977661790624.470109462738037
p4269327.624598264694214631221.45367980003357
p4365296.635222673416138673317.159975051879883
p4472068.201093912124634819727.290011882781982
p4573847.414166450500488748921.240010738372803
p4661666.826710224151611720817.667112588882446
p4764348.080354928970337724925.64135766029358
p4862997.8948752880096436643822.5309157371521
p4963296.82571268081665676417.12479257583618
p5093138.6319098472595211088029.890727758407593
p5179138.980969190597534893931.077434062957764
p5293478.536164283752441972633.53241181373596
p5399469.4257862567901611114132.7076473236084
p5491788.4992961883544921056033.5239634513855
p5584659.157528400421143831832.04251146316528
p562271321.77771425247192423903144.6936798095703
p573358119.87682652473449730914142.13889384269714
p585650118.7248744964599646049138.9957413673401
p593273820.6597051620483438781140.89498019218445
p602320123.38042521476745624435128.45606589317322
p613144618.32096123695373529426122.40536570549011
p626351816.8770191669464138882126.1437463760376
p633202718.30001544952392634958120.8425030708313
p642334721.73286342620849624081118.14805221557617
p652848317.2887492179870632030115.24073910713196
p664080915.93437194824218838021116.89702320098877
p672990717.8990929126739529351125.08517384529114
p6
http://www.zskr.cn/news/1448917.html

相关文章:

  • 3步快速上手:Cursor Pro永久免费破解方案终极指南
  • 别再折腾了!保姆级教程:在VMware Ubuntu虚拟机里调用Windows主机摄像头(含Cheese/FFmpeg测试)
  • 基于BERT与CNN的智能交互装置:情绪分析与手势识别的软硬件实现
  • 7-Zip-zstd:当压缩工具遇见现代算法,你的文件处理体验将彻底改变
  • 告别YUV图片转换烦恼:在Ubuntu 22.04上从源码编译libjpeg-turbo 2.1.5的完整指南
  • 目标检测框回归的“进化史”:从IOU到CIOU,我们到底在优化什么?(附PyTorch实现对比)
  • 别再傻傻重做U盘了!Win10安装报错install.wim,用一条DISM命令10分钟搞定
  • 保姆级教程:在Ubuntu 20.04上管理多版本CUDA(11.0/11.4/12.1),用软链接自由切换
  • WuWa-Mod:鸣潮游戏模组全面解析与实战指南
  • Smithbox终极指南:从零开始掌握魂系游戏修改工具
  • AI工程师全景解析:岗位分类、核心职责与薪资体系
  • 3分钟掌握苹果平方字体:免费PingFangSC完整使用教程
  • 基于MOSFET的LED流水灯制作:无稳态多谐振荡器电路详解
  • 用Arduino和光敏电阻模块DIY一个天黑自动亮的小夜灯(附完整代码)
  • SMUDebugTool:如何免费解锁AMD Ryzen处理器的终极性能潜力
  • 别再乱设Content-Type了!Spring Boot接口传参失败的3个常见坑点与排查指南
  • 【超简单易懂的教程】桌面 AI 自动化 OpenClaw 2.7.8 部署实操分享(含安装包)
  • 基于ATtiny85与MAX30102的心率监测可穿戴设备开发全流程解析
  • 从‘网络打架’到‘双网协同’:手把手教你用Linux Bonding聚合双网卡(附CentOS/Ubuntu配置)
  • Android 13系统源码里给三方App“开后门”:一个Shell脚本搞定预装与静默安装
  • 3步搭建专业级跨平台音乐播放器:LX Music桌面版完全指南
  • 新手必看:用泡沫胶和热熔胶枪搞定你的第一架固定翼无人机(附详细工具清单)
  • 基于树莓派的智能称重系统:从传感器到Web全栈物联网实践
  • 用ShaderGraph给你的独立游戏加把火:低成本实现风格化火焰与篝火交互
  • 用OpenCV给图片里的形状‘体检’:紧致度、圆度、偏心率到底怎么看?附Python代码
  • 怎样免费获取全网最高品质音乐?洛雪音乐音源完全指南
  • Stable Diffusion提示词工程师的必修课:玩转CLIP Text Encoder,让你的描述精准控制AI出图
  • 2026豆包GEO服务商全维度评测:技术避坑与商业盈利指南 - 品牌报告
  • 为什么Mermaid Live Editor是技术文档可视化的最佳选择?
  • 别再只调参了!深入MAE源码,手把手教你如何将它适配到自己的主干网络(以ResNet为例)