简介:这份资源面向城市轨道交通运营管理领域的研究人员、工程师及高校师生,围绕列车延误场景下的跳站与多车站客流控制协同优化问题,提供了一套双层线性规划模型的完整实现方案。上层以列车总延误最小为目标并考虑载客能力约束,下层以上车客流量最大为目标兼顾控流率均衡,采用灵敏度分析算法求解,并以北京地铁亦庄线为例验证,结果显示延误列车行程时间缩短5.2%、车站进站率方差降低97.8%。资源包共1个docx文件,约54KB,内含模型构建思路、可运行代码复现、关键算法实现、模型扩展分析、实际应用建议及系统性能评估等内容,便于读者对照案例修改参数、探索不同场景下的优化效果。目前已有61人学习,适合希望将理论模型与代码实践结合、深入理解延误恢复策略与客流控制协同机制的读者参考。1. 跳站与限流为什么要一起算:一个被低估的耦合问题早高峰的轨道交通线上,前序列车晚点三分钟,后车跟着吃红灯,站台乘客越积越多。很多调度员的直觉反应是两件事分开做:先让某些车跳站追点,再对客流大的站做限流。但真跑过仿真的人都知道,这两件事分开调,经常越调越糟——跳站把乘客甩给后续车,后续车更挤,限流又把乘客堵在站厅,换乘通道跟着堵。轨道交通延误条件下列车跳站与客流控制协同优化模型,要解决的就是这个耦合问题:把「车怎么跳」和「站怎么限」放进同一个优化框架里同时求解,而不是各调各的。这套模型适合谁?一是做行车调度算法的人,想找一个能落地的协同优化建模思路;二是做客流管控的产品或研究人员,手里有 AFC 刷卡数据和时刻表,想验证限流策略;三是带学生做课程设计或论文的导师,需要一个结构完整、代码可复现的案例。它不追求全网最优,而是在给定延误扰动下,找一个跳站方案加限流强度的组合,让乘客总等待时间和列车运行恢复时间都可接受。下面从建模、数据、求解到排错,一步步拆开讲。2. 协同优化模型怎么建:决策变量、目标函数与约束2.1 先明确两类决策变量协同优化的核心是把跳站和限流写成同一组决策变量。常见做法是定义两个矩阵:一个是跳站决策矩阵 (x_{i,k}),表示列车 (i) 在车站 (k) 是否停靠,取 0 或 1;另一个是限流强度矩阵 (r_{k,t}),表示车站 (k) 在时段 (t) 的进站客流控制比例,取值在 0 到 1 之间。注意这里的时间粒度要和时刻表对齐,一般用 30 秒或 1 分钟一格,太粗会让限流失去意义,太细会让求解规模爆炸。我一般会把跳站变量做成整数规划里的 0-1 变量,限流变量做成连续变量,这样模型是一个混合整数非线性规划。如果嫌非线性难解,可以把乘客等待时间做分段线性化,退化成混合整数线性规划,用现成求解器就能跑。2.2 目标函数:别只盯一个指标目标函数通常写成加权和:[ \min Z = \alpha \cdot T_{wait} + \beta \cdot T_{recover} + \gamma \cdot C_{fair} ]其中 (T_{wait}) 是乘客总等待时间,(T_{recover}) 是列车运行恢复时间(实际运行图偏离计划运行图的累计量),(C_{fair}) 是公平性惩罚项,防止某些站被限流限得太狠。权重 (\alpha)、(\beta)、(\gamma) 需要根据线路特点调。通勤线一般 (\alpha) 给大一点,因为乘客最在意等车时间;如果是机场线或旅游线,(\beta) 可以适当提高,优先保证运行秩序恢复。这里有个血泪经验:公平性项千万别省。早期我只用前两项,结果求解器为了压总等待时间,把某个小站的限流比例压到接近 0.1,乘客在站外排了二十分钟,投诉电话直接打爆。加上公平性惩罚后,模型会自动把限流强度摊匀一些。2.3 约束条件:跳站和限流必须互相牵制约束分三类。第一类是列车运行约束:跳站后列车区间运行时间不变,但停站时间省了,所以到达下一站的时间要重新推算;同时要保证跳站后相邻两站的乘客仍能通过后续列车或换乘到达,不能出现某个站被完全孤立。第二类是客流约束:限流后的进站人数不能超过站台承载能力,也不能低于一个最低服务比例,否则等于变相封站。站台等待人数要满足动态平衡方程:[ Q_{k,t+1} = Q_{k,t} + A_{k,t} \cdot r_{k,t} - B_{k,t} ]其中 (A_{k,t}) 是原始到达率,(B_{k,t}) 是实际上车人数,受列车剩余容量限制。第三类是耦合约束:如果列车 (i) 在车站 (k) 跳站,那么该站该时段的上车人数要重新分配给后续停靠列车,这会影响后续列车的载客量和限流需求。这条约束是协同优化的灵魂,少了它,模型就退化成两个独立问题。2.4 一个最小可跑的建模代码骨架下面用 Python 加 PuLP 写一个简化版模型骨架,只保留核心变量和约束,方便先跑通再扩展。import pulp # 参数设定:3 列车、4 个车站、2 个时段 num_trains = 3 num_stations = 4 num_periods = 2 # 原始到达率 A[k][t],单位:人/分钟 A = [[30, 25], [40, 35], [20, 18], [15, 12]] # 站台容量上限 cap_station = [120, 150, 100, 80] # 列车定员 cap_train = 200 # 决策变量 x = pulp.LpVariable.dicts("skip", (range(num_trains), range(num_stations)), cat="Binary") r = pulp.LpVariable.dicts("limit", (range(num_stations), range(num_periods)), lowBound=0.1, upBound=1.0) # 目标:最小化等待时间近似(用限流比例反比表示) prob = pulp.LpProblem("coop_opt", pulp.LpMinimize) prob += pulp.lpSum([(1 - r[k][t]) * A[k][t] for k in range(num_stations) for t in range(num_periods)]) # 约束1:每个站至少有一列车停靠 for k in range(num_stations): prob += pulp.lpSum([1 - x[i][k] for i in range(num_trains)]) >= 1 # 约束2:限流后进站人数不超过站台容量 for k in range(num_stations): for t in range(num_periods): prob += A[k][t] * r[k][t] <= cap_station[k] # 约束3:跳站列车不能连续跳超过两站 for i in range(num_trains): for k in range(num_stations - 2): prob += x[i][k] + x[i][k+1] + x[i][k+2] <= 2 prob.solve() print("求解状态:", pulp.LpStatus[prob.status]) for k in range(num_stations): for t in range(num_periods): print(f"车站{k} 时段{t} 限流比例: {r[k][t].varValue:.2f}")这段代码的逻辑说明:x是跳站变量,1 表示跳站;r是限流比例,下界设 0.1 防止完全封站。目标函数用(1 - r) * A近似等待时间,实际项目中要换成基于排队论的精确表达式。约束 1 保证每个站至少有一列车停,约束 2 控制站台人数,约束 3 防止连续跳站导致乘客无车可上。参数方面,cap_station和cap_train要根据实际线路查设计文件,A从 AFC 数据按 15 分钟粒度聚合后再插值到分钟级。3. 数据准备与求解流程:从 AFC 到可执行方案3.1 数据来源与清洗要点协同优化需要三类数据:列车时刻表和运行图、AFC 刷卡进出站记录、线路拓扑和车站容量。时刻表一般从调度系统导出,注意要区分计划运行图和实际运行图,延误分析用实际图。AFC 数据量很大,常见做法是按车站、按 15 分钟聚合进出站人数,再根据列车到站时间插值成分钟级到达率。清洗时重点处理三件事:一是剔除刷卡异常记录,比如进站后超过 4 小时才出站的;二是补齐缺失时段,用前后时段均值填充;三是把换乘站的多线路客流分开,否则限流会算错。我一般会写一个校验脚本,检查每个站每个时段的到达率是否超过历史峰值,超过就人工复核。3.2 求解器选型与参数设置小规模问题(3 到 5 列车、10 个站以内)用 PuLP 加 CBC 就能秒解。规模上去以后,比如整条线 20 列车、30 个站,建议换 Gurobi 或 CPLEX,或者用启发式算法先给初始解再局部搜索。参数设置上,混合整数规划的 gap 一般设 1% 到 3%,太大了解的质量没保证,太小了求解时间不可控。时间限制设 300 秒,超时就用当前最优解。如果非线性太强,可以用遗传算法或模拟退火做外层搜索,内层用线性规划求限流比例。这种双层结构在论文里很常见,工程上也好实现。3.3 从求解结果到调度指令求解出来的是跳站矩阵和限流比例,但调度员需要的是可执行指令:哪趟车在哪个站不停,哪个站从几点到几点限流百分之多少。中间要加一个后处理模块,把连续限流比例离散成几档,比如 30%、50%、70%,方便站务执行。跳站方案要检查是否和既有运行图冲突,比如两趟跳站车之间的间隔不能太大,否则被跳站的乘客等太久。后处理完还要做一次仿真验证,用实际客流数据跑一遍,看站台等待人数和列车满载率是否在可接受范围。这一步不能省,模型解和实际执行之间经常有偏差。4. 避坑与排查:协同优化里最容易翻车的五个点4.1 跳站变量和限流变量量纲不一致导致求解器罢工现象:模型跑起来报 infeasible 或者求解时间异常长。原因:跳站是 0-1 变量,限流是 0 到 1 的连续变量,如果目标函数里两项权重没归一化,求解器会在两个尺度差异巨大的项之间反复震荡。解决:把等待时间除以一个基准值(比如无延误时的总等待时间),把恢复时间也做同样处理,让两项都在 0 到 1 附近。4.2 AFC 数据时间粒度和时刻表对不上现象:算出来的限流比例在某些时段突然跳到 1.0 或 0.1。原因:AFC 聚合粒度和列车到站时间没对齐,导致某个分钟到达率被严重高估或低估。解决:统一用 1 分钟粒度,AFC 数据按到站时间前后 30 秒窗口聚合,再做滑动平均平滑。4.3 公平性惩罚项权重给太小现象:求解结果里某个小站限流比例长期低于 0.2,乘客投诉。原因:公平性项权重 (\gamma) 太小,模型只顾总等待时间。解决:把 (\gamma) 调到总目标的 10% 到 15%,或者直接给每个站设限流比例下界,比如不低于 0.3。4.4 跳站后后续列车容量约束没更新现象:仿真时发现被跳站的乘客挤不上后续车,站台人数爆表。原因:模型里只算了跳站决策,没把跳站甩下来的客流加到后续列车的载客量约束里。解决:在耦合约束里显式写出客流再分配方程,确保后续列车剩余容量能吸收被跳站客流。4.5 求解结果直接下发导致站务执行不了现象:调度员反馈限流比例 0.47 这种数没法执行。原因:模型输出是连续值,站务需要离散档位。解决:加后处理模块,把限流比例映射到 30%、50%、70% 三档,跳站方案也要检查是否和既有规章冲突,比如某些特殊车站不允许跳站。5. 进阶技巧:用滚动时域把协同优化做成在线可用的版本前面讲的是一次性求解,实际调度是滚动的。每来一批新延误数据,就要重新算未来 15 到 30 分钟的跳站和限流方案。我一般用滚动时域框架:每 5 分钟触发一次,取未来 30 分钟作为优化窗口,只执行前 5 分钟的方案,然后窗口往前推。这样既能应对延误变化,又不会让求解规模太大。滚动时域的关键是热启动。每次求解时,把上一轮的解作为初始值传给求解器,能显著减少求解时间。下面是一个滚动触发的伪代码骨架:import time window_size = 30 # 优化窗口,单位:分钟 step_size = 5 # 滚动步长,单位:分钟 current_time = 0 while current_time < simulation_end: # 截取当前窗口内的客流和延误数据 window_data = get_data(current_time, current_time + window_size) # 用上一轮解做热启动 init_solution = last_solution if current_time > 0 else None # 求解协同优化模型 solution = solve_coop_model(window_data, init_solution) # 只执行前 step_size 分钟的方案 execute(solution, current_time, current_time + step_size) last_solution = solution current_time += step_size time.sleep(1) # 模拟实际调度间隔这段代码的逻辑:window_size决定看多远,step_size决定多久调一次。热启动通过init_solution传入,能省 30% 到 50% 的求解时间。执行时只取前 5 分钟,保证方案不会因为新数据到来而完全作废。参数方面,窗口太小会短视,太大求解慢,15 到 30 分钟是比较稳的范围。验证滚动方案好不好,看两个指标:一是方案切换频率,如果每 5 分钟跳站方案大变一次,站务和乘客都受不了,可以加一个平滑约束,限制相邻两次方案的跳站站数变化不超过 1;二是实际执行后的恢复时间,和一次性求解的结果比,如果差 10% 以内就算合格。我自己的习惯是,每次上线新线路前,先用历史延误数据跑一周的滚动仿真,把求解时间、方案切换次数、乘客等待时间分布都打出来看一遍。有一次发现某个换乘站的限流比例在滚动中反复震荡,查了半天是 AFC 数据里换乘客流没拆干净,导致到达率估计忽高忽低。后来加了一个换乘分配模块才稳住。做这类协同优化,模型本身不难,难的是数据链路和工程细节,希望帮到你。本文还有配套的精品资源,点击获取
简介:这份资源面向城市轨道交通运营管理领域的研究人员、工程师及高校师生,围绕列车延误场景下的跳站与多车站客流控制协同优化问题,提供了一套双层线性规划模型的完整实现方案。上层以列车总延误最小为目标并考虑载客能力约束,下层以上车客流量最大为目标兼顾控流率均衡,采用灵敏度分析算法求解,并以北京地铁亦庄线为例验证,结果显示延误列车行程时间缩短5.2%、车站进站率方差降低97.8%。资源包共1个docx文件,约54KB,内含模型构建思路、可运行代码复现、关键算法实现、模型扩展分析、实际应用建议及系统性能评估等内容,便于读者对照案例修改参数、探索不同场景下的优化效果。目前已有61人学习,适合希望将理论模型与代码实践结合、深入理解延误恢复策略与客流控制协同机制的读者参考。1. 跳站与限流为什么要一起算:一个被低估的耦合问题早高峰的轨道交通线上,前序列车晚点三分钟,后车跟着吃红灯,站台乘客越积越多。很多调度员的直觉反应是两件事分开做:先让某些车跳站追点,再对客流大的站做限流。但真跑过仿真的人都知道,这两件事分开调,经常越调越糟——跳站把乘客甩给后续车,后续车更挤,限流又把乘客堵在站厅,换乘通道跟着堵。轨道交通延误条件下列车跳站与客流控制协同优化模型,要解决的就是这个耦合问题:把「车怎么跳」和「站怎么限」放进同一个优化框架里同时求解,而不是各调各的。这套模型适合谁?一是做行车调度算法的人,想找一个能落地的协同优化建模思路;二是做客流管控的产品或研究人员,手里有 AFC 刷卡数据和时刻表,想验证限流策略;三是带学生做课程设计或论文的导师,需要一个结构完整、代码可复现的案例。它不追求全网最优,而是在给定延误扰动下,找一个跳站方案加限流强度的组合,让乘客总等待时间和列车运行恢复时间都可接受。下面从建模、数据、求解到排错,一步步拆开讲。2. 协同优化模型怎么建:决策变量、目标函数与约束2.1 先明确两类决策变量协同优化的核心是把跳站和限流写成同一组决策变量。常见做法是定义两个矩阵:一个是跳站决策矩阵 (x_{i,k}),表示列车 (i) 在车站 (k) 是否停靠,取 0 或 1;另一个是限流强度矩阵 (r_{k,t}),表示车站 (k) 在时段 (t) 的进站客流控制比例,取值在 0 到 1 之间。注意这里的时间粒度要和时刻表对齐,一般用 30 秒或 1 分钟一格,太粗会让限流失去意义,太细会让求解规模爆炸。我一般会把跳站变量做成整数规划里的 0-1 变量,限流变量做成连续变量,这样模型是一个混合整数非线性规划。如果嫌非线性难解,可以把乘客等待时间做分段线性化,退化成混合整数线性规划,用现成求解器就能跑。2.2 目标函数:别只盯一个指标目标函数通常写成加权和:[ \min Z = \alpha \cdot T_{wait} + \beta \cdot T_{recover} + \gamma \cdot C_{fair} ]其中 (T_{wait}) 是乘客总等待时间,(T_{recover}) 是列车运行恢复时间(实际运行图偏离计划运行图的累计量),(C_{fair}) 是公平性惩罚项,防止某些站被限流限得太狠。权重 (\alpha)、(\beta)、(\gamma) 需要根据线路特点调。通勤线一般 (\alpha) 给大一点,因为乘客最在意等车时间;如果是机场线或旅游线,(\beta) 可以适当提高,优先保证运行秩序恢复。这里有个血泪经验:公平性项千万别省。早期我只用前两项,结果求解器为了压总等待时间,把某个小站的限流比例压到接近 0.1,乘客在站外排了二十分钟,投诉电话直接打爆。加上公平性惩罚后,模型会自动把限流强度摊匀一些。2.3 约束条件:跳站和限流必须互相牵制约束分三类。第一类是列车运行约束:跳站后列车区间运行时间不变,但停站时间省了,所以到达下一站的时间要重新推算;同时要保证跳站后相邻两站的乘客仍能通过后续列车或换乘到达,不能出现某个站被完全孤立。第二类是客流约束:限流后的进站人数不能超过站台承载能力,也不能低于一个最低服务比例,否则等于变相封站。站台等待人数要满足动态平衡方程:[ Q_{k,t+1} = Q_{k,t} + A_{k,t} \cdot r_{k,t} - B_{k,t} ]其中 (A_{k,t}) 是原始到达率,(B_{k,t}) 是实际上车人数,受列车剩余容量限制。第三类是耦合约束:如果列车 (i) 在车站 (k) 跳站,那么该站该时段的上车人数要重新分配给后续停靠列车,这会影响后续列车的载客量和限流需求。这条约束是协同优化的灵魂,少了它,模型就退化成两个独立问题。2.4 一个最小可跑的建模代码骨架下面用 Python 加 PuLP 写一个简化版模型骨架,只保留核心变量和约束,方便先跑通再扩展。import pulp # 参数设定:3 列车、4 个车站、2 个时段 num_trains = 3 num_stations = 4 num_periods = 2 # 原始到达率 A[k][t],单位:人/分钟 A = [[30, 25], [40, 35], [20, 18], [15, 12]] # 站台容量上限 cap_station = [120, 150, 100, 80] # 列车定员 cap_train = 200 # 决策变量 x = pulp.LpVariable.dicts("skip", (range(num_trains), range(num_stations)), cat="Binary") r = pulp.LpVariable.dicts("limit", (range(num_stations), range(num_periods)), lowBound=0.1, upBound=1.0) # 目标:最小化等待时间近似(用限流比例反比表示) prob = pulp.LpProblem("coop_opt", pulp.LpMinimize) prob += pulp.lpSum([(1 - r[k][t]) * A[k][t] for k in range(num_stations) for t in range(num_periods)]) # 约束1:每个站至少有一列车停靠 for k in range(num_stations): prob += pulp.lpSum([1 - x[i][k] for i in range(num_trains)]) >= 1 # 约束2:限流后进站人数不超过站台容量 for k in range(num_stations): for t in range(num_periods): prob += A[k][t] * r[k][t] <= cap_station[k] # 约束3:跳站列车不能连续跳超过两站 for i in range(num_trains): for k in range(num_stations - 2): prob += x[i][k] + x[i][k+1] + x[i][k+2] <= 2 prob.solve() print("求解状态:", pulp.LpStatus[prob.status]) for k in range(num_stations): for t in range(num_periods): print(f"车站{k} 时段{t} 限流比例: {r[k][t].varValue:.2f}")这段代码的逻辑说明:x是跳站变量,1 表示跳站;r是限流比例,下界设 0.1 防止完全封站。目标函数用(1 - r) * A近似等待时间,实际项目中要换成基于排队论的精确表达式。约束 1 保证每个站至少有一列车停,约束 2 控制站台人数,约束 3 防止连续跳站导致乘客无车可上。参数方面,cap_station和cap_train要根据实际线路查设计文件,A从 AFC 数据按 15 分钟粒度聚合后再插值到分钟级。3. 数据准备与求解流程:从 AFC 到可执行方案3.1 数据来源与清洗要点协同优化需要三类数据:列车时刻表和运行图、AFC 刷卡进出站记录、线路拓扑和车站容量。时刻表一般从调度系统导出,注意要区分计划运行图和实际运行图,延误分析用实际图。AFC 数据量很大,常见做法是按车站、按 15 分钟聚合进出站人数,再根据列车到站时间插值成分钟级到达率。清洗时重点处理三件事:一是剔除刷卡异常记录,比如进站后超过 4 小时才出站的;二是补齐缺失时段,用前后时段均值填充;三是把换乘站的多线路客流分开,否则限流会算错。我一般会写一个校验脚本,检查每个站每个时段的到达率是否超过历史峰值,超过就人工复核。3.2 求解器选型与参数设置小规模问题(3 到 5 列车、10 个站以内)用 PuLP 加 CBC 就能秒解。规模上去以后,比如整条线 20 列车、30 个站,建议换 Gurobi 或 CPLEX,或者用启发式算法先给初始解再局部搜索。参数设置上,混合整数规划的 gap 一般设 1% 到 3%,太大了解的质量没保证,太小了求解时间不可控。时间限制设 300 秒,超时就用当前最优解。如果非线性太强,可以用遗传算法或模拟退火做外层搜索,内层用线性规划求限流比例。这种双层结构在论文里很常见,工程上也好实现。3.3 从求解结果到调度指令求解出来的是跳站矩阵和限流比例,但调度员需要的是可执行指令:哪趟车在哪个站不停,哪个站从几点到几点限流百分之多少。中间要加一个后处理模块,把连续限流比例离散成几档,比如 30%、50%、70%,方便站务执行。跳站方案要检查是否和既有运行图冲突,比如两趟跳站车之间的间隔不能太大,否则被跳站的乘客等太久。后处理完还要做一次仿真验证,用实际客流数据跑一遍,看站台等待人数和列车满载率是否在可接受范围。这一步不能省,模型解和实际执行之间经常有偏差。4. 避坑与排查:协同优化里最容易翻车的五个点4.1 跳站变量和限流变量量纲不一致导致求解器罢工现象:模型跑起来报 infeasible 或者求解时间异常长。原因:跳站是 0-1 变量,限流是 0 到 1 的连续变量,如果目标函数里两项权重没归一化,求解器会在两个尺度差异巨大的项之间反复震荡。解决:把等待时间除以一个基准值(比如无延误时的总等待时间),把恢复时间也做同样处理,让两项都在 0 到 1 附近。4.2 AFC 数据时间粒度和时刻表对不上现象:算出来的限流比例在某些时段突然跳到 1.0 或 0.1。原因:AFC 聚合粒度和列车到站时间没对齐,导致某个分钟到达率被严重高估或低估。解决:统一用 1 分钟粒度,AFC 数据按到站时间前后 30 秒窗口聚合,再做滑动平均平滑。4.3 公平性惩罚项权重给太小现象:求解结果里某个小站限流比例长期低于 0.2,乘客投诉。原因:公平性项权重 (\gamma) 太小,模型只顾总等待时间。解决:把 (\gamma) 调到总目标的 10% 到 15%,或者直接给每个站设限流比例下界,比如不低于 0.3。4.4 跳站后后续列车容量约束没更新现象:仿真时发现被跳站的乘客挤不上后续车,站台人数爆表。原因:模型里只算了跳站决策,没把跳站甩下来的客流加到后续列车的载客量约束里。解决:在耦合约束里显式写出客流再分配方程,确保后续列车剩余容量能吸收被跳站客流。4.5 求解结果直接下发导致站务执行不了现象:调度员反馈限流比例 0.47 这种数没法执行。原因:模型输出是连续值,站务需要离散档位。解决:加后处理模块,把限流比例映射到 30%、50%、70% 三档,跳站方案也要检查是否和既有规章冲突,比如某些特殊车站不允许跳站。5. 进阶技巧:用滚动时域把协同优化做成在线可用的版本前面讲的是一次性求解,实际调度是滚动的。每来一批新延误数据,就要重新算未来 15 到 30 分钟的跳站和限流方案。我一般用滚动时域框架:每 5 分钟触发一次,取未来 30 分钟作为优化窗口,只执行前 5 分钟的方案,然后窗口往前推。这样既能应对延误变化,又不会让求解规模太大。滚动时域的关键是热启动。每次求解时,把上一轮的解作为初始值传给求解器,能显著减少求解时间。下面是一个滚动触发的伪代码骨架:import time window_size = 30 # 优化窗口,单位:分钟 step_size = 5 # 滚动步长,单位:分钟 current_time = 0 while current_time < simulation_end: # 截取当前窗口内的客流和延误数据 window_data = get_data(current_time, current_time + window_size) # 用上一轮解做热启动 init_solution = last_solution if current_time > 0 else None # 求解协同优化模型 solution = solve_coop_model(window_data, init_solution) # 只执行前 step_size 分钟的方案 execute(solution, current_time, current_time + step_size) last_solution = solution current_time += step_size time.sleep(1) # 模拟实际调度间隔这段代码的逻辑:window_size决定看多远,step_size决定多久调一次。热启动通过init_solution传入,能省 30% 到 50% 的求解时间。执行时只取前 5 分钟,保证方案不会因为新数据到来而完全作废。参数方面,窗口太小会短视,太大求解慢,15 到 30 分钟是比较稳的范围。验证滚动方案好不好,看两个指标:一是方案切换频率,如果每 5 分钟跳站方案大变一次,站务和乘客都受不了,可以加一个平滑约束,限制相邻两次方案的跳站站数变化不超过 1;二是实际执行后的恢复时间,和一次性求解的结果比,如果差 10% 以内就算合格。我自己的习惯是,每次上线新线路前,先用历史延误数据跑一周的滚动仿真,把求解时间、方案切换次数、乘客等待时间分布都打出来看一遍。有一次发现某个换乘站的限流比例在滚动中反复震荡,查了半天是 AFC 数据里换乘客流没拆干净,导致到达率估计忽高忽低。后来加了一个换乘分配模块才稳住。做这类协同优化,模型本身不难,难的是数据链路和工程细节,希望帮到你。本文还有配套的精品资源,点击获取