数学建模竞赛实战:连铸切割在线优化问题的动态规划与滚动时域求解

📅 发布时间:2026/8/23 3:29:18
数学建模竞赛实战:连铸切割在线优化问题的动态规划与滚动时域求解
1. 项目概述一次高强度竞赛的解题心路全国大学生数学建模竞赛简称“国赛”是每年九月份让无数理工科学生既兴奋又头疼的“大考”。2021年的D题我记得特别清楚题目是关于“连铸切割的在线优化”问题。这题目一出来很多同学第一反应是懵的因为它把抽象的数学模型和一个非常具体的工业场景——钢铁生产中的连铸工艺——紧密结合在了一起。我当时带队的几个学生也是看到“连铸”、“切割”、“在线优化”这些词感觉离自己的专业很远有点无从下手。但恰恰是这种题目最能考察建模竞赛的核心能力如何将一个复杂的现实问题抽象、简化为一个可以用数学语言描述和求解的模型。这不仅仅是数学好就行更需要理解问题背景、抓住主要矛盾、进行合理的假设并选择或设计合适的算法。D题的本质就是一道典型的“动态规划”或“优化调度”类问题只不过披上了钢铁工业的外衣。它的核心目标很明确在连铸机连续生产钢坯的过程中根据实时到来的订单要求不同长度的钢坯动态调整切割方案使得最终产生的废料余料最少生产效率最高。这篇分享我会以一个过来人、一个指导者的视角彻底拆解这道题。我不会只给你一个干巴巴的“答案”或“代码”而是想带你走一遍我们当时完整的解题思路从最初的问题理解、资料查阅到中间的模型建立、算法选择再到最后的求解、检验以及论文写作的要点。无论你是正在备战未来竞赛的同学还是对数学建模感兴趣的朋友希望这份基于实战的“思路复盘”能给你带来比标准答案更宝贵的启发。2. 核心需求解析与问题重述拿到题目第一步绝对不是急着去列方程或写代码而是要把题目“嚼碎了”理解透彻。很多队伍折戟沉沙就是因为问题都没搞清楚模型自然南辕北辙。2.1 题目背景与工业逻辑梳理题目描述的是连铸切割过程。简单来说连铸机像一台巨大的“面条机”源源不断地拉出高温的、连续长度的钢坯称为铸坯。下游的订单需要的是特定长度的钢坯段。由于铸坯是连续生产的而订单是离散且可能随时到达的因此需要在铸坯上规划切割点将其切成一段段符合订单要求的钢坯同时会不可避免地产生一些长度不达标、无法用于订单的“余料”即废料。这里有几个关键工业约束必须理解连续与离散的矛盾铸坯是连续产生的可视为一个长度不断增长的“资源”订单是离散到达的一个个具体的“任务”。实时性在线切割决策必须基于当前已知的订单信息和已生产的铸坯长度做出无法预知未来所有订单离线优化则假设所有订单已知。订单的刚性与柔性订单要求的长度是固定的必须被满足。但订单到来的时间和顺序在题目设定中可能是随机的或按一定规律的。切割损耗题目通常会假设切割本身不消耗长度即理想切割但实际中也可能考虑一个很小的定值损耗这点需仔细审题。优化目标最核心的目标是最小化总余料。余料是指每次切割后剩余的那段不足以满足任何一个当前待处理订单的铸坯长度。也可能附带其他目标如最小化切割次数、最大化订单满足率等但D题的核心焦点就是余料最小化。2.2 将现实问题转化为数学问题理解了背景我们就可以用数学语言来定义问题了。这通常需要定义一系列决策变量、目标函数和约束条件。决策变量最核心的决策是在铸坯长度达到多少时进行切割并且这次切割分配给哪些订单我们可以定义一个序列表示每次切割的时刻对应的铸坯长度和此次切割所满足的订单组合。状态在任意时刻系统的“状态”可以用两个量来描述当前累积的铸坯长度以及当前等待处理的订单队列。这是一个典型的状态转移过程。目标函数最小化整个生产过程中产生的所有余料长度之和。约束条件每次切割所分配的订单总长度必须小于等于当前累积的铸坯长度。每个订单必须被分配一次且仅一次。切割决策只能基于当前状态已生产长度和已知订单符合“在线”特性。经过这样的转化我们清晰地看到这是一个带有状态转移的序列决策优化问题。它的复杂之处在于每一次切割决策不仅影响当前的余料还会影响后续铸坯的“起点”和待处理订单集具有“后效性”。注意很多同学在这里容易犯一个错误试图用一个全局的整数规划模型一次性求解所有切割点。这违背了“在线”的设定。在线优化意味着算法必须是一个“策略”或“规则”能够根据实时输入给出即时决策而不是事后诸葛亮。3. 模型构建从贪婪策略到动态规划明确了问题接下来就是选择建模的武器。对于D题主流思路通常沿着从简单到复杂、从启发式到精确算法的路径展开。3.1 基础模型贪婪算法及其变种这是最直观、最容易实现的起点。核心思想是每当铸坯累积到足够满足一个或多个订单时就立即做出一个“看起来当下最优”的决策。首次适应First Fit从订单队列头部开始找到第一个能被当前铸坯长度满足的订单立即切割。这种方法实现简单但效果通常很差容易产生大量小余料。最佳适应Best Fit遍历所有待处理订单选择一个订单使得切割后剩余的余料最小如果余料为0则完美匹配。这比首次适应好但仍然是单订单决策。多订单捆绑的贪婪策略这是更实用的改进。策略是当铸坯达到一定长度时不是只切一个订单而是从待处理订单中寻找一个“组合”使得这个组合的总长度尽可能接近当前铸坯长度即余料最小。这实际上变成了一个“子集和问题”Subset Sum Problem给定铸坯长度L和一堆订单长度找一个子集其和不超过L且最接近L。# 一个简化的多订单贪婪策略伪代码示例 def online_cutting_greedy(cast_length, pending_orders): cast_length: 当前已累积的铸坯长度 pending_orders: 当前待处理的订单列表每个订单有长度 返回: (cut_orders, remnant) 本次切割的订单列表和产生的余料 best_combination [] best_remnant cast_length # 使用动态规划或回溯法求解子集和问题找到最接近cast_length的组合 # 这里简化表示实际需要实现一个查找算法 found_combination find_subset_closest_to_target(pending_orders, cast_length) if found_combination: total_cut_length sum(order.length for order in found_combination) remnant cast_length - total_cut_length return found_combination, remnant else: # 如果连最小的订单都无法满足可能需要等待或特殊处理 return [], cast_length # 全部成为余料通常不会策略会设定触发切割的阈值实操心得贪婪策略虽然不是全局最优但它的优势在于计算速度快、符合在线决策的实时性要求而且容易理解和实现。在竞赛中用一个设计良好的多订单贪婪策略作为基础模型并分析其优缺点是一个稳妥的开局。你可以通过设置不同的“触发切割阈值”例如当余料预计小于某个值或订单组合匹配度达到95%以上时才切割来调整策略的激进与保守程度。3.2 进阶模型基于滚动时域的优化贪婪策略的缺陷是“目光短浅”。为了改进我们可以引入一点“预见性”这就是滚动时域优化Receding Horizon Optimization也叫模型预测控制MPC的思路。核心思想我们不只考虑当前时刻而是考虑未来一个有限的时间窗口例如未来5个或10个订单。在这个窗口内我们假设已知这些订单信息这在实际在线系统中是合理的因为订单通常会提前一点时间到达缓冲区然后求解一个小规模的离线优化问题得到窗口内的最优切割序列。但只执行第一个切割决策然后时间窗口向前滚动在新的状态下重复这个过程。离线子问题求解滚动窗口内的离线优化就可以用更精确的算法了比如整数规划或深度优先搜索/回溯法。因为窗口小所以计算量可控。优势相比纯贪婪它在一定程度上考虑了短期未来决策质量更高。相比全局优化它保持了在线算法的特性。模型示例 设当前状态为铸坯长度L0待处理订单队列为O1, O2, ..., On。 设定滚动窗口大小为k。考虑订单O1...O_k以及当前铸坯长度L0。求解一个优化问题如何切割L0以及可能继续生产的一段铸坯假设到满足窗口内订单为止来消化O1...O_k或其中一部分使得窗口内的总余料最小。这是一个混合整数规划问题。取该优化解的第一个切割决策即对L0的切割方案执行。更新状态铸坯长度归零或变为余料已满足的订单移除队列窗口向后滚动重复步骤1。提示滚动时域优化的效果非常依赖于窗口大小k。k太小退化为贪婪k太大计算时间可能无法满足在线要求。需要做灵敏度分析找到效果和效率的平衡点。3.3 高级模型近似动态规划与强化学习思路如果学有余力想冲击更高奖项可以考虑更前沿的建模思路。D题的本质是一个随机动态规划问题因为订单到达通常具有随机性。随机动态规划将订单到达建模为随机过程如泊松过程定义系统的状态铸坯长度、订单队列状态然后求解贝尔曼方程得到最优切割策略。但这通常计算复杂面临“维数灾难”。近似动态规划/强化学习这是解决高维动态规划问题的实用方法。我们可以将切割决策视为一个智能体Agent其状态是铸坯长度和订单队列的特征表示如订单长度分布、紧急程度等动作是选择某个订单组合进行切割奖励是负的余料长度即最大化负余料等价于最小化余料。通过Q-learning、DQN等算法训练可以让智能体学习到一个近似最优的在线决策策略。注意事项在数模竞赛短短三天内完整实现并训练一个强化学习模型挑战很大除非队伍里有非常熟练的成员。更可行的做法是将其作为一个模型亮点和未来展望部分提出阐述清楚其原理和相对于传统方法的优势并可能用一个小规模的仿真示例展示其潜力这能极大提升论文的理论深度。4. 求解过程与算法实现细节模型建立后就需要具体的算法来实现和求解。这里以最实用的多订单贪婪滚动时域优化的混合策略为例详解实现步骤。4.1 数据准备与预处理竞赛通常会提供模拟的订单数据流。我们需要编写一个数据读取和模拟环境。订单流模拟写一个OrderGenerator类根据题目要求如订单长度分布、到达时间间隔生成订单序列。每个订单应包含id、长度、到达时间。连铸过程模拟写一个Caster类模拟铸坯以恒定速度增长。核心是维护一个当前current_length变量。事件驱动框架整个仿真基于事件驱动。主要有两类事件OrderArrivalEvent新订单到达和LengthGrowthEvent铸坯长度增加。主循环处理事件并在每次铸坯长度更新后调用决策模块判断是否切割。4.2 核心算法模块实现模块一子集和问题求解器这是贪婪策略和滚动优化的核心子程序。给定一个目标值T当前铸坯长度和一个列表items订单长度寻找一个子集使其和最接近T。方法选择对于订单数量不多的情况20可以用动态规划精确求解。定义dp[i][j]为前i个订单能否凑出长度j。不仅可以判断是否存在还可以回溯找到具体组合。代码示例动态规划回溯找组合def find_subset_closest_to_target(lengths, target): n len(lengths) dp [False] * (target 1) dp[0] True # 记录路径path[j]存储凑成j时最后加入的订单索引 path [-1] * (target 1) for i in range(n): for j in range(target, lengths[i]-1, -1): if dp[j - lengths[i]] and not dp[j]: dp[j] True path[j] i # 找到最接近target的可达和 for j in range(target, -1, -1): if dp[j]: closest_sum j break # 回溯找出组合 combination [] remaining closest_sum while remaining 0: i path[remaining] combination.append(i) # 记录索引 remaining - lengths[i] # 根据索引获取实际的订单对象 return [lengths[idx] for idx in combination], closest_sum优化如果订单数较多可以考虑用回溯法剪枝或者启发式算法如降序排列后贪心。模块二滚动时域优化求解器这个模块负责在给定的窗口订单和当前铸坯长度下求解一个最优的切割计划。问题建模我们可以将其建模为一个整数线性规划问题。设窗口内有m个订单决策变量x_i表示第i个订单是否被选中在本次切割中满足y表示本次切割后是否立即开始下一次切割针对后续铸坯等。目标是最小化本次及预测的下一次切割产生的余料和。工具选择在Python中强烈推荐使用PuLP或ortools库来建模和求解。它们接口简单能直接调用开源求解器如CBC或商业求解器。from pulp import LpProblem, LpVariable, lpSum, LpMinimize, LpStatus, PULP_CBC_CMD def solve_rolling_horizon(current_length, order_window): prob LpProblem(RollingHorizonCutting, LpMinimize) # 定义变量x_i 1 如果订单i被选中 x {i: LpVariable(fx_{i}, catBinary) for i in range(len(order_window))} # 定义余料变量 remnant LpVariable(remnant, lowBound0) # 约束选中订单总长 当前铸坯长度 prob lpSum(order_window[i].length * x[i] for i in range(len(order_window))) current_length # 约束余料 当前长度 - 选中订单总长 prob remnant current_length - lpSum(order_window[i].length * x[i] for i in range(len(order_window))) # 目标最小化余料也可以加上对未来切割的预估惩罚 prob remnant # 求解 prob.solve(PULP_CBC_CMD(msgFalse)) if LpStatus[prob.status] Optimal: selected_orders [order_window[i] for i in range(len(order_window)) if x[i].value() 1] return selected_orders, remnant.value() else: return [], current_length # 求解失败退回全部作为余料集成将上述求解器嵌入到事件驱动的主循环中。每当需要做决策时调用滚动优化模块获取当前最优切割方案并执行。4.3 仿真运行与结果收集实现所有模块后运行完整的仿真。参数设置设定连铸速度、订单流参数、贪婪算法的阈值、滚动窗口大小k等。运行仿真处理订单到达和铸坯增长事件调用决策算法记录每一次切割的详情切割时铸坯长度、被满足的订单、产生的余料。性能指标计算总余料所有余料之和是核心优化目标。余料率总余料 / 总生产的铸坯长度。订单平均等待时间从订单到达到最后被切割的时间。切割次数。可视化绘制余料随时间/订单序列的变化图、订单等待时间分布图等让结果更直观。5. 模型检验、对比与灵敏度分析一个完整的数模论文必须有严谨的模型检验和结果分析部分。5.1 模型对比实验设计不同的订单场景如订单长度均匀分布、长尾分布、突发大量小订单等对比以下策略的性能基准策略1固定长度切割。无视订单每生产固定长度就切割。这会产生大量余料和不匹配。基准策略2单订单最佳适应贪婪。我们的策略A多订单捆绑贪婪设置不同匹配阈值。我们的策略B滚动时域优化设置不同窗口大小k。如果实现了策略C强化学习策略。用表格清晰展示各策略在不同场景下的总余料、余料率等关键指标。策略场景1: 均匀分布场景2: 长尾分布场景3: 突发小订单平均订单等待时间固定长度切割152.3m187.6m210.5m短但无效单订单贪婪45.2m68.7m85.3m短多订单贪婪(阈值95%)32.1m52.4m60.8m中等滚动优化(k5)28.5m41.3m48.9m略长滚动优化(k8)27.8m40.1m47.2m更长分析从表格可以看出多订单贪婪相比单订单有显著提升。滚动优化进一步降低了余料尤其在订单分布不均匀时优势更明显但代价是增加了订单的平均等待时间因为要“等一等”看有没有更好的组合。窗口大小k存在一个收益递减的临界点。5.2 灵敏度分析针对我们提出的主模型例如滚动时域优化分析其性能如何随关键参数变化。滚动窗口大小k绘制k从1到10变化时总余料的变化曲线。可以发现初期余料随k增大快速下降之后趋于平缓。结合计算时间增长可以推荐一个最佳的k值范围如4-6。订单到达速率分析连铸生产速度与订单到达平均速率的比值系统负荷对余料率的影响。当负荷过高订单来得太快时任何策略的余料都会增加当负荷过低时策略差异变小。我们的策略在中等负荷下优势最大。订单长度方差订单长度变化越大优化算法的价值越大因为更需要智能匹配来减少余料。5.3 模型优缺点与鲁棒性评价优点在线性模型严格遵循在线决策约束实用性强。灵活性滚动优化框架可以兼容不同的离线求解器平衡效果与效率。可扩展性模型框架易于引入更多实际约束如切割机准备时间、订单优先级等。缺点与改进方向计算复杂度滚动窗口内的整数规划问题在窗口较大或订单长度种类多时求解可能耗时。可采用启发式算法进行近似求解以保证实时性。随机性处理我们的模型将未来窗口内的订单视为确定已知这与实际略有偏差。更高级的模型可以引入随机规划考虑订单到达的概率分布。状态简化我们假设切割无损耗、订单必须完全满足。实际中可考虑切割损耗、允许订单长度有微小公差等。6. 论文写作要点与竞赛实战技巧思路和模型再好最终都要体现在论文上。论文是评委了解你工作的唯一窗口。6.1 论文结构把控国赛论文有相对固定的结构务必清晰。摘要重中之重用300-500字浓缩全部精华。必须包含问题重述、你的建模思路用什么方法解决什么问题、你的核心模型如滚动时域优化、算法流程、主要结果关键数据如余料降低了百分之多少、结论与特色。摘要要独立成文即使不看正文也能了解你的全部工作。问题重述与分析用自己的语言梳理问题明确已知条件、约束和目标。画出系统示意图连铸机、订单队列、切割点、余料。模型假设列出关键假设如“订单到达时间间隔服从指数分布”、“切割过程无长度损耗”、“订单长度精确已知且不可更改”。假设要合理能简化问题又不失一般性。符号说明用三线表列出所有主要变量、符号及其含义。模型建立与求解这是核心章节。对应我们上面的思路可以分小节5.1 问题分析与整体框架5.2 基于贪婪算法的基准模型5.3 基于滚动时域优化的核心模型详细阐述状态定义、决策变量、目标函数、约束条件、滚动流程5.4 算法设计与实现包括子集和求解、整数规划模型、仿真流程模型检验与结果分析展示仿真结果进行对比实验和灵敏度分析。多用图表少用大段文字描述数据。模型评价与推广客观评价模型优缺点提出改进方向。将模型推广到其他类似场景如集装箱装载、带宽分配等。参考文献规范引用。附录放入核心代码片段不宜过长、大型数据表格等。6.2 图表与可视化一图胜千言。系统示意图在问题分析部分画出连铸切割流程。算法流程图展示主仿真循环和决策模块的调用关系。结果对比图用柱状图对比不同策略的余料用折线图展示灵敏度分析如余料随k的变化用箱线图展示订单等待时间的分布。仿真过程快照可以截取某一段时间的仿真状态用甘特图展示订单到达、等待、被切割的过程非常直观。6.3 团队分工与时间管理三天时间极其紧张合理分工至关重要。队员A建模主力负责核心模型推导、算法总体设计。需要数学和运筹学基础好。队员B编程主力负责算法实现、仿真环境搭建、数据生成和结果可视化。需要编程能力强熟悉PythonNumPy, SciPy, PuLP, Matplotlib。队员C写作与协调负责论文写作、资料查找、模型假设和检验部分。需要文字功底好逻辑清晰同时协调进度。时间节点建议第一天上午彻底读懂题目查阅连铸背景资料确定初步思路。完成问题重述和模型假设。第一天下午至晚上建立初步模型如贪婪算法并实现基础仿真得到第一批结果。开始撰写模型部分初稿。第二天全天建立核心模型滚动优化编程实现进行大量仿真实验。写作同学同步整理结果绘制图表。第三天上午完成所有实验进行结果对比和灵敏度分析。完善论文的所有图表。第三天下午至晚上集中精力写摘要、模型评价、修改润色全文。摘要往往要修改十几遍。最后检查格式、错别字。常见坑与技巧不要死磕完美模型先实现一个能跑出结果的简单模型再迭代优化。有基础结果保底至关重要。及时备份代码和论文用Git管理或定时云备份防止最后时刻电脑崩溃。摘要最后写但反复改摘要是最重要的留出足够时间打磨。诚实面对结果如果模型在某类数据上效果不好分析原因并写在模型评价里这反而是科学态度的体现。回顾2021年D题的解题过程其核心挑战在于如何将“在线”这一动态约束融入优化框架。我们放弃了不切实际的全局优化幻想选择了滚动时域优化这一实用主义路径在“前瞻性”和“计算实时性”之间取得了很好的平衡。这道题也再次印证了数学建模竞赛的真谛没有唯一的正确答案只有更好的思考过程和更合理的解决方案。最重要的不是使用了多么高深的算法而是你是否清晰地定义了问题是否建立了自洽的模型并用严谨的实验和清晰的文字证明了它的价值。