混合贪心算法求解地铁线路调度
一、问题描述
城市轨道交通的繁荣发展,带来了车辆资源需求的日益增加。如何兼顾运营服务水平和运营成本,以最少的车底优质地完成运输任务成为一大严峻问题。本题在后续的描述中将由多辆动车和拖车组合而成的车组称为车底。在日常的运营组织中,车底运用计划指导着所有的车底有序的完成运输任务,是运输计划中非常重要一项。较多的车底运用数可以从容的面对各种客流压力,深受乘客的欢迎却往往不能发挥车底的运输能力,导致运营成本骤升;而车底过少又极易引起车底超负荷运转,缩短设备寿命,面对大客流情况还有可能出现运营紊乱,乘客体验差。因此,车底运用计划对协调运营质量和运营成本意义重大。基于列车运行时刻表,结合列车车底数量、车辆段或停车场(以下统称为车场)的数量、车场的分布状况及容纳能力等,对每一车底在何时何地驶出车场、担当哪些车次以及返回车场作出合理的安排;同时,根据车底检修相关规程,对每一车底的检修时间、检修地点、检修级别等作出具体安排,保证安全、高效、有序的完成日常运营任务。
现在假设有一个地铁运营线,该线网由 20 座车站构成, 本线路全周转时间:120min30s;共有 35 组,停车场的存车能力为 25,车辆段的存车能力为 20;列车运行间隔:早高峰 3min(7点到9点),平峰 8min,晚高峰3min25s(17点到20点),其中,大交路 1-20,小交路1-15,早晚高峰的追踪间隔均指小交路的追踪间隔;列车通过 9 号车站进出车辆段,出入段时间为 2min40s;1,15,20 号车站具备折返能力,其最短折返时间分别为:6min、4min30s、4min30s;1号车
站连接停车场,停车场的出入时间 2min。
简而言之,要求就是使用最少的车底完成所有车次的牵引计划,同时每辆车的牵引时长要尽量均衡。
二、数据介绍
车次数据分位上行车次和下行车次,上行车次表示从编号较大的站到编号较小的站,下行车次从编号较小的站到编号较大的站,流入从1到20是下行车次,从20到1是上行车次。每天的上、下行车次数各为244。
三、算法求解
在这一小节中主要介绍两部分内容,第一部分内容是如何获得使用车底尽量少的车底牵引方案,第二部分是如何在保证车底数量不变的前提下,使得每个车底的牵引时间更加均衡。
3.1 车底数量求解
贪心算法
对于此类问题,一个直观的想法采用贪心的策略,对于每一个车底,都使得牵引尽量多的车次,直到所有的车次完成牵引,这个时候用到的车底数量就是贪心算法得到的最少车底数量,基本算法流程如下:
step1、初始化使用车底集合为C={},当前车底牵引车次集合D={},剩余车次集合P为上下行全量车次;
step2、按照时空接续关系生成所有可行车次集合,如果可行车次为空,转step4;
step3、随机选择可行接续车次作为车底即将牵引的车次d,D=D+d,P=P-d,转step2;
step4 、如果剩余车底集合P为空,转step6,否则转step5;
step5、更新使用车底集合C,新增车底,转step2;
step6、输出车底牵引计划;
step7、结束。
其中,step2中的时空接续关系是指车底前后牵引的两趟车次在时间和空间上都必须是能够衔接的,在空间上前车的终点站必须是后撤的起点站,在时间上前车的到达时间必须早于后车的出发时间,且时间间隔要满足特定要求。
贪心算法最终结果为使用车底数量41,由于step3中随机选择当前车底的可行车次,导致每个车底的牵引车辆数相对有限,考虑结合整数规划模型来获得当前车底的最优解决方案。
混合贪心算法
step1、初始化使用车底集合为C={},当前车底牵引车次集合D={},剩余车次集合P为上下行全量车次;
step2、计算剩余所有车次的前序车次数量和后续车次数量;
step3、按照车辆的前序车次数和后续车次数进行排序;
step4、将前序车次数和后续车次数量最少的车辆作为必选车次,建立整数规划模型,获取最优路径,最大化彻底服务车次数;
step5、将车底牵引计划添加到车底集合中,更新剩余车次,如果所有列车牵引完成,转step6,否则转step2;
step6、输出车底牵引计划;
step7、结束。
混合贪心算法最终使用的车底数量为36,相比于贪心算法,混合贪心算法主要在两个方面有所改进。一个是优先选择车前序和后续车次少的车次进行分配,这是由于到了算法后期,这样的车次往往一个车次就要完全占据一个车底。另外一个改进的点是采用整数规划,能够真正意义上获取每个车底当前的最优选择。
从上述甘特图中也可以明显看出贪心策略的一些特征,排序靠前的车底,由于有比较大的选择空间,牵引路径都比较长,牵引负载比较大,排序靠后的车底,由于选择空间急剧收缩,往往一个车底只能服务一两趟车次。
3.2 负载均衡调整
由于贪心策略产生的结果会出现负载极度不均衡的情况,考虑采用局部调整策略对产生的方案进行调整。调整的思路很简单,将负载比较高的车底服务的车次重新分配给负载比较低的车底即可,其对应的基本流程如下:
调整过后的结果如下,从图上可以看出来调整之后的结果变得更加均衡了。
四、代码实现
4.1 贪心算法
def get_path(all_trains,from_trains,to_trains):used_trains=[]all_path=[]cnt=0max_length=22max_num=[randint(18,22) for i in range(1000)]while len(set(used_trains))!=len(all_trains):route_length=min(max_length,max_num[cnt])for i in range(route_length,0,-1):result=solver_route(all_trains,from_trains,to_trains,used_trains,i)if result:breakelse:max_length=i-1used_trains+=resultall_path.append(result)cnt+=1return all_path
4.2 整数规划
def solver_route(all_trains,from_trains,to_trains,used_trains,route_length):train_num=len(all_trains)# 创建模型model = gp.Model('train_scheduling')# 数据处理new_from_trains=deepcopy(from_trains)new_to_trains=deepcopy(to_trains)for train in all_trains:new_from_trains[train]=list(set(new_from_trains[train])-set(used_trains))new_to_trains[train]=list(set(new_to_trains[train])-set(used_trains))io_num={}for i in range(len(all_trains)):train=all_trains[i]io_num[i]=len(new_from_trains[train])+len(new_to_trains[train]) dff=pd.DataFrame(io_num.items(),columns=['key','value'])sort_trains=dff.sort_values(by=['value'],ascending=False)['key'].valuesfix_train=-1for train in sort_trains:if not train in used_trains:fix_train=trainbreak# 是否将站点i放置在位置jx = {}for i in range(train_num):for j in range(route_length):x[i,j] = model.addVar(vtype=GRB.BINARY, name=f'x_{i}_{j}')# 目标函数obj=0for i in range(train_num):for j in range(route_length):obj+=io_num[i]*x[i,j]model.setObjective(obj,GRB.MINIMIZE)# 每个位置最多有一个节点for j in range(route_length):expr=0for i in range(train_num):expr+=x[i,j]model.addConstr(expr==1)# 节点之间要有连关系for j in range(route_length-1):for i in range(train_num):expr=0train=all_trains[i]for ii in from_trains[train]:expr+=x[ii,j]model.addConstr(expr>=x[i,j+1])# 遍历过的车次不再选择for i in used_trains:expr=0for j in range(route_length):expr+=x[i,j]model.addConstr(expr<=0)# fix train一定要满足expr=0for j in range(route_length):expr+=x[fix_train,j]model.addConstr(expr==1)# 求解model.setParam('OutputFlag', 0)model.setParam(GRB.Param.TimeLimit, 60)model.optimize()# 检查求解器状态status = model.Statusif status == GRB.INFEASIBLE:return []else:return get_result(x,train_num,route_length)
局部调整
paths=[]
for idx,row in result.iterrows():path=eval(row[0])paths.append(path)for i in range(len(paths)):path=paths[i]remove_trains=[]path_duration=get_path_duration(path)print(path_duration)for train in path:if path_duration<=avg:breakfor j in range(i+1,len(paths)):add_path=paths[j]add_path_duration=get_path_duration(add_path)if add_path_duration>avg:continueidx=get_insert_index(train,add_path)if idx>0:add_path.insert(idx,train)remove_trains.append(train)path_duration-=(train_info.end_time-train_info.start_time)breakfor train in remove_trains:paths[i].remove(train)
相关文章:

混合贪心算法求解地铁线路调度
一、问题描述 城市轨道交通的繁荣发展,带来了车辆资源需求的日益增加。如何兼顾运营服务水平和运营成本,以最少的车底优质地完成运输任务成为一大严峻问题。本题在后续的描述中将由多辆动车和拖车组合而成的车组称为车底。在日常的运营组织中࿰…...

vue项目:关闭页面,删除本地登录信息
vue项目:关闭页面,删除本地登录信息 代码 代码 import { removeToken } from /utils/auth //区分关闭和刷新页面,关闭时退出登录 window.onload ()>{if(!window.sessionStorage["tempFlag"]){removeToken();location.reload()…...

获奖案例回顾|基于卫星遥感和无人机的水稻全流程风险减量项目
引言 在现代农业保险领域,技术创新是推动行业进步的关键。珈和科技与太平财险的合作,旨在利用先进的卫星遥感和无人机技术,解决传统农业保险面临的诸多挑战,从而提升保险效率和服务质量。本次分享的项目案例获得了《金融电子化》…...

全栈 Discord 克隆:Next.js 13、React、Socket.io、Prisma、Tailwind、MySQL笔记(一)
前言 阅读本文你需要有 Next.js 基础 React 基础 Prisma 基础 tailwind 基础 MySql基础 准备工作 打开网站 https://ui.shadcn.com/docs 这不是一个组件库。它是可重用组件的集合,您可以将其复制并粘贴到应用中。 打开installation 选择Next.js 也就是此页面…...

【Unity】制作简易计时器
一、创建计时器相关的变量 我们需要创建三个变量,分别是:计时时长、计时剩余时长、是否处于计时状态。 public float duration;//计时时长 public float remain; //计时剩余时长 public bool isCount; //是否处于计时状态 二、初始化变量 我们可以直…...

TDesign组件库日常应用的一些注意事项
【前言】Element(饿了么开源组件库)在国内使用的普及率和覆盖率高于TDesign-vue(腾讯开源组件库),这也导致日常开发遇到组件使用上的疑惑时,网上几乎搜索不到其文章解决方案,只能深挖官方文档或…...

51单片机7(点亮第一个LED)
一、LED简介 1、LED,它是一个发光二极管,它具有单向导电性,那么通过5毫安的一个电流,就可以使它发光,那么电流越大,它的发光也就越强,但是电流不能过大,过大会把这个发光二极管给烧…...

基于Vue和UCharts的前端组件化开发:实现高效、可维护的词云图与进度条组件
基于Vue和UCharts的前端组件化开发:实现高效、可维护的词云图与进度条组件 摘要 随着前端技术的迅速发展和业务场景的日益复杂,传统的整块应用开发方式已无法满足现代开发的需求。组件化开发作为一种有效的解决方案,能够将系统拆分为独立、…...

CentOS 系统监控项
在维护和优化 CentOS 系统时,实时监控硬件和资源的使用情况非常重要。为了满足工作需要,可以定时采集 CentOS 系统相关的监控数据,并将其推送到 Prometheus 进行集中监控和管理。以下是日常采集项及对应的 shell 命令,并附上每项命…...

连锁直营店小程序赋能多店如何管理
如商超便利店卖货线下场景,也有不少品牌以同城多店和多地开店经营为主,获取店铺周围客户和散流,如今线上重要性凸显,品牌电商发展是经营的重要方式之一,也是完善同城和外地客户随时便捷消费的方式之一。 多个门店管理…...

决策树算法入门到精通:全面解析与案例实现
1. 介绍决策树算法 决策树的基本概念和原理 决策树是一种基于树形结构的分类和回归方法,通过对数据集进行递归地划分,每个内部节点表示一个属性上的判断,每个叶节点代表一种类别或者数值。 决策树在机器学习中的应用场景 分类问题…...

LangChain —— 多模态大模型的 prompt template
文章目录 一、如何直接将多模态数据传输给模型二、如何使用 mutimodal prompts 一、如何直接将多模态数据传输给模型 在这里,我们演示了如何将多模式输入直接传递给模型。对于其他的支持多模态输入的模型提供者,langchain 在类中提供了内在逻辑来转化为期…...

ssh升级
文章目录 ssh升级一、解包ssh、ssl二、更新安装ssl三、手动更新手动复制库文件四、创建符号链接五、更新库路径六、验证库文件七、设置库路径环境变量八、配置、编译、安装OpenSSH:意外:缺少 zlib 的开发库解决方法: 九、刷新ssh服务、查看ss…...

51单片机10(蜂鸣器介绍)
一、蜂鸣器介绍: 1、蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于电子产品中作为发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器。 (1)压电式蜂鸣器,它主要由多谐的一个增胀器…...

Python爬虫:基础爬虫架构及爬取证券之星全站行情数据!
爬虫成长之路(一)里我们介绍了如何爬取证券之星网站上所有A股数据,主要涉及网页获取和页面解析的知识。爬虫成长之路(二)里我们介绍了如何获取代理IP并验证,涉及了多线程编程和数据存储的知识。此次我们将在…...

T113-i 倒车低概率性无反应,没有进入倒车视频界面
背景 硬件:T113-i + emmc 软件:uboot2018 + linux5.4 + QT应用 分支:longan 问题 T113-i系统倒车时偶发无反应,没有进入倒车视频界面。 倒车无反应问题排查 先在倒车驱动的中断检测接口里添加打印,以确定倒车无反应时系统是否检测到中断状态,如下图所示。 static int ca…...

【AI大模型】李彦宏从“卷模型”到“卷应用”的深度解析:卷用户场景卷能给用户解决什么问题
文章目录 一、理解李彦宏的发言1.1 李彦宏的核心观点1.2 背景分析 二、技术发展:从辨别式到生成式2.1 辨别式AI技术2.2 生成式AI技术2.3 技术发展的挑战 三、“卷应用”:聚焦实际应用与价值3.1 应用为王3.2 技术落地的关键 四、“卷场景”:多…...

25秋招面试算法题 (Go版本)
文章目录 科大讯飞 0713找01不能出现太多其他 科大讯飞 0713 找01 牛牛拥有一个长度为 n 的01 串,现在他想知道,对于每个字符,在它前面的最近的不同字符的下标是多少? 输入描述 本题为多组测试数据,第一行输入一个…...

在Ubuntu 14.04上安装和保护phpMyAdmin的方法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 虽然许多用户需要像 MySQL 这样的数据库管理系统的功能,但他们可能不太习惯仅通过 MySQL 提示符与系统进行交互。 ph…...

突破与创新:Vue.js 创始人 尤雨溪 2024 年度技术前瞻
本文将深入探讨以下主题的 尤雨溪 见解:Vite 5对Vue的影响、宏、vapor模式、常见误解、新特性或功能、未来版本对Option API的支持、VitePress等。 . 2.尤大的问答环节 2.1. Vite 5如何提升Vue的性能? Vite在提高性能方面的工作通常是针对Vite本身的。然…...

LeetCode 441, 57, 79
目录 441. 排列硬币题目链接标签思路代码 57. 插入区间题目链接标签思路两个区间的情况对每个区间的处理最终的处理 代码 79. 单词搜索题目链接标签原理思路代码 优化思路代码 441. 排列硬币 题目链接 441. 排列硬币 标签 数学 二分查找 思路 由于本题所返回的 答案在区间…...

【排序 - 插入排序 和 希尔排序】
插入排序(Insertion Sort)是一种简单直观的排序算法,它的工作原理是逐步构建有序序列。在排序过程中,它将未排序的元素逐个插入到已排序的部分中,从而在每次插入时扩展已排序序列的长度。 原理介绍 插入排序的基本思…...

Java使用 MyBatis-Plus 的 OR
Java使用 MyBatis-Plus 的 OR 一、前言1. 简介2. OR 查询2.1 基础 OR 查询2.2 使用 Lambda 表达式简化 二、总结 一、前言 学习使用 MyBatis-Plus 的 OR 及高级语句是提升数据库操作效率和灵活性的关键步骤。MyBatis-Plus 是 MyBatis 的增强工具包,提供了许多便捷的…...

[Linux]CentOS软件的安装
一、Linux 软件包管理器 yum 1.Linux安装软件的方式 在linux中安装软件常用的有三种方式: 源代码安装(我们还需要进行编译运行后才可以,很麻烦) rpm安装(Linux的安装包,需要下载一些rpm包,但是…...

4000厂商默认账号密码、默认登录凭证汇总.pdf
获取方式: 链接:https://pan.baidu.com/s/1F8ho42HTQhebKURWWVW1BQ?pwdy2u5 提取码:y2u5...

RK3568笔记三十六:LED驱动开发(设备树)
若该文为原创文章,转载请注明原文出处。 记录使用设备树编写一个简单的 LED 灯驱动程序 一、编程思路 程序编写的主要内容为添加 LED 灯的设备树节点、在驱动程序中使用 of 函数获取设备节点中的 属性,编写测试应用程序。 • 首先向设备树添加 LED 设备…...

AC修炼计划(AtCoder Regular Contest 180) A~C
A - ABA and BAB A - ABA and BAB (atcoder.jp) 这道题我一开始想复杂了,一直在想怎么dp,没注意到其实是个很简单的规律题。 我们可以发现我们住需要统计一下类似ABABA这样不同字母相互交替的所有子段的长度,而每个字段的的情况有ÿ…...

云计算练习题
第一题:每周日晚上11点59分需要将/data目录打包压缩到/mnt目录下并以时间命名 #crontab -e 59 23 * * 7 /bin/tar czvf /mnt/date %F-data.tar.gz /data 59 23 * * 7 /bin/tar czvf /mnt/date %T.tar.gz /data 第二题:查找出系统中/application目录下所有…...

《战甲神兵》开发者报告:游戏崩溃问题80%发生在Intel可超频酷睿i9处理器上——酷睿i7 K系列CPU也表现出高崩溃率
在Intel持续面临第13代和第14代CPU崩溃问题的背景下,近日,《战甲神兵》(Warframe)的开发者们于7月9日披露了游戏崩溃的统计数据,并描述了诊断该问题的过程。根据开发团队的说法,一名未进行超频且使用全新PC的员工,即便…...

Postman下载及使用说明
Postman使用说明 Postman是什么? Postman是一款接口对接工具【接口测试工具】 接口(前端接口)是什么? 前端发送的请求普遍被称为接口 通常有网页的uri参数格式json/key-value请求方式post/get响应请求的格式json 接…...