写点什么

【数梦工场】【智慧航空 AI 大赛】比赛分享

作者:阿里云天池
  • 2024-08-12
    浙江
  • 本文字数:5103 字

    阅读完需:约 17 分钟

关联比赛:  智慧航空AI大赛

先介绍一下团队,我们这几个人也是在天池众智赛【广东大赛】机场停机位资源分配优化】中互掐认识的,也算不打不相识,大家都有一些 IP 问题的建模经验

我们是前三里面唯一的一支没有专业背景的队伍,人员也是比较杂,具体如下:

    数梦达文西:    数梦工场 码农

    终结卡尔斯:    西安电子科技大学 在读研究生

    绿洲520:         飞友科技 码农

    Robo:            飞友科技 码农

    麦芽的香气:    阿里妈妈 码农

数梦达文西 和 终结卡尔斯 是 Carry 位;绿洲 520、Robo、麦芽的香气是辅助位。(嗯,没有打野)

由于没一个好看的,照片就不贴了,以免辣眼睛~

---------------------------------------------------------------

---------------------------------------------------------------

言归正传,说一下比赛历程

第一赛季拿到问题,我们就判断这是一个比较难的问题,其复杂度会比广东机场停机位资源分配优化大赛的问题高很多。大家都没有经验,大家都没底。

总体方案的选取上马上就出现分歧,终结卡尔斯相对激进,主张用比较先进的列生成;数梦达文西主张用传统的大领域搜索框架;绿洲 520、Robo、麦芽的香气选择用相对传统的分析和小规模建模方式。最终没谈拢,结果就是前面两人做列生成,后面三人按照自己的想法做。(事后来看,终结卡尔斯的方向无疑是正确的,但继续坚持也可能是万劫不复,具体情况后面会说)

题目比较复杂,第一赛季时间过得很快,看看题目,读读文档,不知不觉已经到了第一赛季的尾声。最终结果是 终结卡尔斯 和 数梦达文西 一起做的列生成失败做失败了,虽然大致的原理了解了,代码框架也搭出来了,但有个地方没有搞定,那就是主问题的求解。随着列的增多,原来天真的以为主问题求解也就是建个 model 给求解器跑一下,结果发现完全跑不动。。。。(关于列生成的介绍,相信同济梁哲教授会分享,在此就不展开了);最终是绿洲 520、Robo、麦芽的香气给了一个结果,62 万多点,虽然离 57.x 有很大的 gap,但好歹也保证我们进入复赛了。对于这个 62 万的解,由于结果不算很优秀,在此也就不分享具体实现了,大致思路就是把两头时间的航班定死,只调整中间的航班,多个航班打包。


第一赛季结束,总体效果不满意,数梦达文西 和 终结卡尔斯 交流后,决定只能放弃列生成算法,转用大领域搜索框架+整数规划建模。第一赛季结束后,中间大约空了一周的时间,由于之前已经对问题比较了解了,用这一周的时间,数梦达文西 和 终结卡尔斯写了一下大领域搜索+整数规划的代码,跑了一下,得到一个 578626.58 的结果,这个结果算然比不上排行榜上同济梁哲教授的成绩,但也还算不错了,要是之前提交了也能在排行榜上排第二了。大家在心底默默想要把终结卡尔斯吊打一顿的同事,又觉得找到了一点希望。


于是第二赛季我们就坚定地贯彻大领域搜索的框架,怀着“只要功夫深,铁棒磨成针”的美好愿景,积极开展数据分析,努力优化各种细节,几乎每天晚上 达文西 和 卡尔斯 都 QQ 语音+teamviewer 暧昧到深夜,就这么苦逼地把成绩逐步提升上去,说多了都是泪


总结一下,比赛感悟:

大方案的选择很重要,事实证明列生成方法是优秀的,但比赛中尝试使用新方法同样存在风险,风险与机会并存;

只要足够用心,相对土鳖的方法也能出不错的解,不过速度可能会慢很多


---------------------------------------------------------------

---------------------------------------------------------------

鸡毛蒜皮说了一堆,下面说说大家最关心的算法实现吧。(列生成方面,我们没有做成功,没有太多经验,相信同济梁教授应该会给大家一个教科书般的完美说明


我们就直接介绍一下我们的大致方案,经验也好,教训也好,供大家参考


我们的方案是大领域搜索+整数规划建模。其核心是整数规划建模。这个模型是我们的核心,相对而言,大领域搜索框架没有太大技术含量,之前也用过几次,实现起来也没啥风险

以下是之前文档里面 ctrl+c 过来了,请原谅我的懒惰

算法原理

3.1 算法框架

我们的解决方案是大领域搜索(Large Neighborhood Search,LNS)与混合整数线性规划(Mixed Integer Linear Programming,MILP)。通过 MILP 模型可以精确的表达本次竞赛的问题,但是由于问题规模较大,并且有时效性要求,直接求解是不切实际的。用 LNS 框架,每次只取一部分飞机和航班进行计算得到初始解,然后基于当前的解每次取一部分飞机和航班进行调整,改进当前解。由于每次只取一部分飞机和航班,模型较小,可以实现快速迭代,在合理时间内获得让人满意的结果。

3.2 整数规划模型

模型主要包含航班模型和乘客模型两个部分:

航班模型:给每个飞机安排航班序列,满足台风窗口约束、机场关闭约束等。

乘客模型:给每个乘客安排航班,尽量将乘客安排在原始航班上,无法安排到原始航班上时,考虑签转或取消。

在程序中设置选择考虑安排乘客或不考虑安排乘客,在 LNS 初期通过不考虑乘客模型可以快速获得一个较好的结果。


3.2.1 航班模型

我们采用离散时空网络和多商品网络流模型来表达航班模型。在离散时空网络中,每一个节点对应一个机场的一个时间点,每一条弧(Arc)对应一个航班或飞机停留在机场。飞机可以网络中的流量,飞机在网络中,从起始边界流向结束边界,流经的航班弧即为该飞机需要执行的航班任务。



网络中包含多种弧,具体定义如下:

(1)普通航班弧

对应一个没有延误或提前的航班,从该航班的起始机场预计起飞时间的时空点,指向目标机场预计降落时间加准备时间的时空点。通过在弧的指向方向加上默认的间隔时间来描述飞机过站约束。普通航班弧包含单一的航班、联程拉直航班和单独执行的联程航班的某一段,联程航班单独执行的时候只能执行其中一个航班。

(2)停机弧

飞机已经做好的了下一次飞行的准备,但是在当前时间点没有需要执行的航班,在机场的一个时间点,停留到下一个时间点。

(3)复合航班弧

复合弧为描述了多个航班一起执行的情况。通过多个航班复合在一个弧上,可以表达多个联系航班的间隔小于 50,两个联程航班同时执行的情况。

(4)平行弧

除了停机弧,以上弧通过同时修改起始时空点和结束时空点,可以描述航班时间改变的情况。

(5)调机弧

和普通航班弧类似,只是弧的权重计算不同,可以多次执行。但是在计算中发现对于本次赛题的数据可以做到不调机。在计算中,不添加调机弧。

每一个弧都满足飞机航班禁飞关系约束、机场关闭限制、台风窗口限制、最大提前和延误时间限制。

决策变量为每个弧对应的一个 01 变量,表示飞机是否执行该弧对应的航班或停机。每个弧的权重包含了负的取消损失、延误或提前损失、换飞机损失、换机型损失、拉直损失,目标函数即为每个弧的权重乘以每个弧的决策变量。


约束分为以下几种约束:

(1)流量守恒约束

在时空网络中,对于每一个时空点,进入该节点的飞机数量等于从该节点出去的飞机数量。

(2)每个航班号只能执行一次

一个航班号在网络中对应多个弧,包括普通弧和延误弧,某些航班还存在复合弧,在一个航班对应的多个弧中,只能有一个弧对应的变量为 1。两次联程航班视为一个航班,单独执行时只能执行一班,想要一起执行只能通过对应的复合弧来执行。

(3)源点、汇点平衡

对应题目中的边界调整约束,飞机需要从指定机场出发,指定机场结束。

(4)停机限制

在停机限制的时间范围内,所有停机弧都取 1 则表示停机一次,累加所有飞机的停机数量小于等于限制停机数。

(5)单位容量限制

单位时间内取的弧的数量小于等于单位容量限制的数量。


弧的生成

完整的模型需要描述航班所有的延误情况,这样会导致弧(决策变量)的数量爆炸,难以求解。我们采用动态生成弧的方法,同时在生成过程采用一些贪心的策略减少弧的数量。

首先,将飞机起始的时空点加入一个待更新的时空点集合。从集合中取出一个时空点,选择所有可以从该时空点出发的航班,生成对应的最早起飞航班弧。在生成了一个新弧之后,会产生一个结束的时空点,若该时空点没有生成过出去的弧,则加入带更新的时空点中。迭代直到不产生任何的新的时空点。

在生成弧时的一些细节如下:

(1)对于离台风窗口较远的航班,禁止时间调整,即没有平行弧。对于离台风窗口较近的航班,给定义个限制的调整范围,该范围小于题目所给出的国内 24 小时、国际 36 小时。

(2)考虑到台风窗口附近有飞机起飞降落容量限制,需要在生成 arc 时判断,如果在限制窗口内,则随机在该时间点之后多生成几条平行弧。

(3)赛题给出的数据的时间粒度是 5 分钟。在生成平行弧时,将航班的延误的时间按一定的粒度和和偏移量对齐,这个时间粒度通常大于 5 分钟,LNS 中的每次迭代随机选取时间粒度和随机偏移量进行计算。每轮迭代中每个航班的随机偏是不同的,例如,按 30 分钟的时间粒度,某航班得到的偏移量可能是 25,50,95,130...,下一轮可能是 35,55, 80,110...。这样能减少很多的情况,又能在多次迭代中消除其副作用。


3.2.2 乘客模型

乘客模型的本质是指派,即把乘客指派到航班的座位上。只不过乘客的情况存在不确定性,座位的情况也存在不确定性。通过分析梳理,最终实现了航班模型和乘客模型的统一。



(1)乘客说明

乘客分为几种情况:普通乘客、联程乘客(第一班和第二班)、第一班的中转乘客、第二班的中转乘客。

其中,按照题目的要求,联程乘客和中转第一班的乘客和航班是绑定的,即只要航班存在,就必然坐这个航班,人数确定。在航班取消时,这部分旅客也不能签转。所以这部分旅客的损失可以在生成弧的时候算入弧的权重上。

普通乘客总是存在。

第二班的中转乘客:想要乘坐第二班航班的中转乘客能否搭上飞机还要取决于他第一班的降落时间,因此不同准备时间的第二班中转乘客视为不同的乘客。当执行了带第一班的中转乘客的航班弧后,产生对应准备时间的第二班中转乘客。当所有第一班的航班弧都没有执行时,即中转失败,不产生对应的第二班的中转乘客。

(2)航班座位说明。

航班座位不需要考虑飞机 ID、机型等信息,关注的是飞机的座位数、航班号、起飞时间、是否有联程乘客。飞机有上百个,但是座位数的种类只有 8 种,按座位数区分航班座位可以减少变量个数。

当执行了一个航班弧后,对应“座位数、航班号、起飞时间、是否有联程乘客”的航班座位提供的座位数为当前飞机的座位数减去联程乘客的数量;对应的航班弧没有执行时,航班座位提供的座位数为 0。

(3)指派说明

将安排多少旅客能否安排到某一种航班座位上定义为决策变量,记为乘客安排变量,可能可以签转的情况才会产生乘客安排变量。将签转、延误损失计算在乘客安排变量在目标函数中的系数上。

乘客安排变量需满足以下约束:

(1)基本约束

所有乘客都需要被安排(乘坐航班或取消)。安排的乘客不大于原有的乘客,同一种航班座位上的乘客数小于等于航班座位当前的座位数。

(2)签转约束

只有乘客对应的原始航班对应的所有航班座位都满座的时候,才可以签转或取消。其中,当前一种航班座位对应的弧没有执行时,该航班座位的座位数为 0,乘客数也是 0,可以理解为座位数满。


具体的数学公式就不贴了,因为我自己看着都头疼~ 有具体那个约束不明白怎么搞的可以跟帖讨论。整个模型还是比较复杂的,建出来也不容易,这也是我们团队这次比赛的一个亮点。但是,这个规模直接丢进去,完全解不动,差远了。我们只要退而求其次,把模型作为一个局部求解的工具,外面套上领域搜索的启发式框架进行迭代


敲了这么多乱七八糟的,手也累了,脑子也不够用,说都不会话了(后面有时间的话再整理一下),直接说一下结论吧,:

1、直接建模还是比较复杂的,需要开动脑筋,多思考

2、直接建模还是比较 low 的,因为虽然有模型,但是解不动大规模,总体来说并没有什么 luan 用(用专业的话来降,解列生成问题的过程相当于解原始问题的拉格朗日松弛问题,而拉格朗日松弛是要比 LP 松弛优的,所以列生成方法更好)

3、大领域搜索框架+整数规划建模,由于是启发式,在前期的优化速度也是很快的,甚至可以 1 分钟出一个可行解(第二赛季的数据上,68 万左右 cost),并且能够快速迭代到 61 万左右,如果一些场景下,对时间要求特别高,对 cost 要求相对低,比如两分钟希望能有个可行解,那也是值得考虑的方案。但是到了一定的程度之后,由于启发式框架不能准确评价局部的优劣,优化效率会降低,甚至到最后,会比较接近纯随机的效果。反观列生成,每轮迭代都可以更新每种资源的影子价格,所以总能慢慢进化,确实是更胜一筹,不得不感叹数学真的是神奇


所以,总体来说,我们组的方案土鳖,实现也苦逼(要你命 3000 还是不敌高科技武器),不建议各位同学模仿。。。各位看官还是期待一下同济梁教授的分享吧~


查看更多内容,欢迎访问天池技术圈官方地址:【数梦工场】【智慧航空AI大赛】比赛分享_天池技术圈-阿里云天池

用户头像

还未添加个人签名 2024-03-12 加入

还未添加个人简介

评论

发布
暂无评论
【数梦工场】【智慧航空AI大赛】比赛分享_阿里云天池_InfoQ写作社区