数学建模竞赛供应链优化:多阶段随机规划与滚动时域控制实战 📅 发布时间:2026/8/23 1:44:37 👁 浏览次数: 1. 项目概述一次高强度的策略博弈实战复盘2021年的全国大学生数学建模竞赛C题题目是“生产企业原材料的订购与运输”。当时拿到这个题目很多队伍的第一反应可能是“这不就是个供应链优化问题吗”。但真正上手后才发现它远不止于此。这道题本质上是一个在复杂约束和不确定需求下的多阶段动态决策问题融合了运筹学、统计学、时间序列分析甚至博弈论的思维。它模拟了一个生产企业面对数百家供应商、每周波动的原材料需求和运输能力限制时如何制定最优的订购与运输计划以最小化成本包括订购、库存和转运成本。我当年作为指导老师带着队伍完整地走了一遍解题、建模、求解到写作的全过程踩了不少坑也积累了一些非常实在的心得。今天我就以从业者的视角把这套思路、方法和避坑指南系统地拆解一遍无论你是正在备赛的学生还是对运筹优化感兴趣的朋友相信都能从中获得可以直接“抄作业”的实战经验。2. 赛题核心与解题思路总览2.1 问题本质带约束的多阶段随机动态规划首先我们必须跳出“简单优化”的思维定式。C题给出的数据包括402家供应商过去240周的供货数据供货量、供货量对应的周数以及一家生产企业每周的产能上限和需求。你需要为未来24周题目中可能是未来一段时间具体周数需根据赛题说明确定这里以24周为例进行阐述制定订购与运输方案。它的难点和核心在于不确定性供应商的供货量是随机的、有波动的你无法精确预测未来每一家供应商每周能提供多少原材料。这引入了风险。多阶段性决策不是一次性的而是需要每周做一次订购哪些供应商、订多少并且本周的决策库存会直接影响下一周的决策空间。复杂约束供应商能力约束每家供应商每周有最大供应量。企业库存能力约束企业自身的仓库有容量上限。运输能力约束每周的运输总量有上限这是题目中非常关键且容易忽略的约束。满足需求约束每周生产消耗的原材料必须得到满足不能缺货通常题目要求必须满足或允许缺货但惩罚极高。多目标权衡目标是最小化总成本而成本由三部分构成原材料成本向供应商采购的费用。库存持有成本原材料放在仓库里会产生资金占用和仓储费用。转运/运输成本将原材料从供应商运到企业的费用。这部分成本可能与距离、运输量相关题目会给出具体计算规则。所以这绝不是一个简单的线性规划。一个可行的总体思路是“预测优化滚动调整”。即先基于历史数据预测未来各供应商的供货能力概率分布或期望值然后建立一个以总成本最小化为目标、以未来多周为规划期的优化模型进行求解最后在实际执行中采用滚动时域控制的方法每周根据实际到货和库存情况重新求解优化模型更新后续计划。2.2 解题流程框架设计基于以上理解一个稳健的解题流程可以设计如下数据预处理与探索性分析EDA这是所有工作的基石。清洗402家供应商240周的数据处理缺失值、异常值。计算每家供应商供货量的基本统计特征均值、方差、变异系数、分布形态分析其供货稳定性。通过可视化如时间序列图、分布直方图发现规律例如是否存在季节性、趋势性或者某些供应商供货量恒为0可能是无效供应商。供货能力建模与预测这是处理不确定性的核心。对于每家供应商基于其历史供货序列建立预测模型。常用的方法包括简单统计法直接使用历史均值和方差作为未来期望和波动估计。适用于数据平稳、无趋势的供应商。时间序列模型如ARIMA、指数平滑等适用于有明显时间依赖性的供应商序列。概率分布拟合检验历史供货量服从何种分布如正态分布、泊松分布、伽马分布等用拟合的分布来描述未来供货的不确定性。分类处理对于供货极不稳定或长期为0的供应商可以归类为“不可靠供应商”在模型中赋予极低的订购优先级或更高的风险成本。优化模型建立这是解题的主体。我们需要建立一个数学规划模型。决策变量通常是二元变量是否选择某供应商在某周供货和连续变量从某供应商在某周的订购量、每周的库存量。目标函数最小化总成本 Σ原材料采购成本 库存持有成本 运输成本。约束条件将上述提到的供应商能力、企业库存、运输能力、需求满足等约束全部用数学公式表达。关键点如何处理预测的不确定性这里有两种主流思路确定性等价模型用预测的期望值代替随机变量将随机规划转化为确定性规划。这是最常用、最易实现的方法但忽略了风险。随机规划或鲁棒优化更高级的方法。随机规划会考虑多种可能场景Scenario目标是最小化期望成本鲁棒优化则考虑最坏情况下的成本最小化。这两种方法模型复杂求解难度大但论文中若能合理简化并实现会是极大的亮点。模型求解与算法设计建立的优化模型通常是一个大规模的混合整数线性/非线性规划MILP/MINLP。直接调用商业求解器如Gurobi, CPLEX或开源求解器如SCIP, OR-Tools可能是最直接的方式。但如果问题规模太大或模型非线性导致求解困难就需要设计启发式算法如贪婪算法每周优先选择“性价比”单位运输成本低、供货稳定最高的供应商直到满足需求或耗尽运输能力。遗传算法GA将订购方案编码为染色体以总成本为适应度函数进行进化迭代。模拟退火SA通过引入随机扰动来跳出局部最优寻找全局较优解。方案评估与灵敏度分析得到一套订购运输方案后不能直接提交。需要用历史数据或随机模拟的方法去评估这个方案的表现。例如用蒙特卡洛模拟根据你预测的概率分布随机生成大量组可能的未来供货序列然后看你的方案在这些不同情境下的平均成本和成本波动风险。同时进行灵敏度分析如果运输能力上调10%总成本能下降多少如果某主要供应商的供货均值下降备用方案是什么这部分分析能极大地提升论文的深度和说服力。3. 核心环节深度解析与实操要点3.1 数据预处理别在第一步埋雷402家供应商240周数据近10万条记录。第一步处理不好后面全盘皆输。实操要点缺失值处理供货量为空或0不能简单删除或填0。要结合上下文判断如果该供应商在其他周有稳定供货唯独这几周为0可能是数据缺失可用前后周均值或插值填充如果该供应商240周里绝大部分都是0只有零星几次供货那它很可能就是一个“偶尔供货”的供应商在建模时应将其供货量视为一个稀疏的随机变量如服从0-1分布与一个供货量分布的混合。异常值识别利用箱线图或3σ原则找出远高于正常范围的供货量。这些点可能是记录错误也可能是真实的“大单”。需要结合业务逻辑判断该供应商平时供货量很小突然有一周暴增合理吗如果不合理应视为异常值并进行修正如用盖帽法。供应商分类这是提升模型效率的关键。不要对402家供应商一视同仁。我建议至少分为三类核心稳定型历史供货均值高、方差小变异系数低。它们是方案的基石。波动风险型均值尚可但方差很大。它们能提供潜在的低价或补充货源但需要风险对冲。边缘偶发型长期供货量为0或极小。可以在模型中设置一个极低的固定订购成本仅在极端缺货时考虑。注意分类的标准需要量化并在论文中明确给出。例如定义“稳定型”为历史供货量大于0的周数占比超过80%且变异系数小于0.5。3.2 预测模型选择在简单与复杂间权衡预测的目的是为优化模型提供输入参数如下一周供货量的期望值。在这个赛题中预测的绝对精度并非首要预测的稳定性和可解释性更重要。方案对比预测方法适用场景优点缺点实操建议移动平均/指数平滑数据平稳无明显趋势周期简单计算快易于理解无法捕捉复杂模式对突变反应滞后对大多数平稳供应商的首选用过去4-8周的加权平均作为预测值。ARIMA模型数据非平稳有明显趋势或自相关理论完备能处理一定的时间依赖参数调优复杂对402家供应商逐一建模工作量巨大且未来24周预测可能发散选择几家最具代表性的核心供应商进行ARIMA建模以展示深度。其余大量供应商仍用简单方法。概率分布拟合关注供货量的随机性而非时间序列能直接给出未来供货的概率分布便于后续随机规划建模忽略了时间顺序可能包含的信息非常契合本题需求。对每家供应商的历史供货量数据进行分布检验如K-S检验拟合一个最佳分布如正态分布N(μ, σ²)μ和σ即为预测参数。我的心得在时间有限的比赛中我强烈推荐“概率分布拟合”为主“移动平均”为辅的策略。对于稳定型供应商拟合正态分布对于波动型可以拟合伽马分布或对数正态分布对于偶发型直接用一个伯努利分布有货/无货加一个条件分布来描述。这样你的优化模型可以直接利用这些分布参数期望、方差来构建目标函数或约束逻辑上更自洽。3.3 优化模型构建从理想模型到可解模型这是整个比赛最硬核的部分。我们直接构建一个理想化的多阶段随机规划模型然后讨论如何简化求解。1. 理想模型多阶段随机规划决策变量( x_{it} )第t周向供应商i的订购量连续变量。( I_t )第t周结束时的库存量连续变量。( y_{it} )0-1变量第t周是否选择供应商i如果题目有固定订购成本或运输有固定费用。目标函数 [ \min E[\sum_{t1}^{T} (\sum_{i1}^{N} (c_i x_{it} f_i y_{it} trans_cost(x_{it})) h I_t)] ] 其中( c_i )是单价( f_i )是固定订购费( trans_cost )是运输成本函数可能是线性或分段函数( h )是单位库存持有成本( E )表示数学期望因为( x_{it} )可能受随机供货量影响。约束条件库存平衡( I_t I_{t-1} \sum_i \xi_{it} x_{it} - d_t )。这里( \xi_{it} )是随机变量表示供应商i在第t周的实际供货率可能≤1这是不确定性的核心来源。需求满足( I_{t-1} \sum_i \xi_{it} x_{it} \ge d_t )。供应商能力( x_{it} \le Cap_{it} )。库存容量( I_t \le I_{max} )。运输能力( \sum_i x_{it} \le Trans_{max} )。变量非负、整数等。这个模型非常完美但直接求解几乎不可能随机变量嵌套在约束中。2. 可解模型两阶段近似与滚动时域控制为了求解我们必须简化。最实用的方法是“两阶段决策 滚动时域控制Receding Horizon Control, RHC”。两阶段决策思想将每周的决策视为两个阶段。第一阶段“此时此地”决定本周的订购量( x_{it} )。第二阶段“未来”考虑到本周订购的货物存在不确定性实际到货是( \xi_{it} x_{it} )我们需要有一个应对策略。在模型中我们用一个惩罚项来近似第二阶段的成本。例如如果到货不足导致缺货风险增加我们就在目标函数中对订购量( x_{it} )的方差或风险值CVaR进行惩罚。滚动时域控制流程在初始时刻第1周初基于当前库存( I_0 )和对未来24周的预测求解一个规划周期为N周例如N4或8的确定性优化模型将随机量( \xi_{it} )用其期望值( \bar{\xi}_i )代替。得到未来N周的订购计划。只执行第一周第1周的订购决策。进入第2周初观测第1周的实际到货情况更新库存( I_1 )。同时用最新的数据可能包括第1周的实际供货数据更新对未来第2周到第N1周的预测。基于新的状态( I_1 )和新的预测重新求解一个未来N周的优化模型时间窗口向前滚动一周。重复步骤2-4直至覆盖所有周。这样做的好处将一个复杂的多阶段随机问题分解为一系列可求解的、较短周期的确定性规划问题。同时RHC具有反馈机制能根据实际情况调整计划鲁棒性更强。3.4 算法实现与求解工具选型与技巧模型建立后需要编程求解。这里以Python生态为例。工具链选择建模语言PuLP或OR-Tools是Python下优秀的线性规划建模库语法直观。对于更复杂的问题Pyomo功能更强大。求解器CBC开源与PuLP集成好适合中等规模的MILP。SCIP开源性能强劲支持更复杂的约束类型。Gurobi/CPLEX商业求解器性能顶尖。学生可以申请免费学术许可证。如果问题规模大强烈建议使用它们。启发式算法实现如果需要自己写遗传算法可以用DEAP框架模拟退火可以自己实现也不复杂。一个基于PuLP和滚动时域的代码框架示例import pulp import numpy as np def solve_one_period(current_inventory, demand_forecast, supplier_cap_mean, cost_dict, trans_cap, horizon4): 求解一个滚动窗口内的确定性优化问题 current_inventory: 当前库存 demand_forecast: 未来horizon周的需求预测列表 supplier_cap_mean: 各供应商未来horizon周的预计最大供应量矩阵 (N_suppliers x horizon) cost_dict: 包含单价、运输费率、库存成本等的字典 trans_cap: 每周运输能力 horizon: 规划周期长度 prob pulp.LpProblem(Material_Ordering, pulp.LpMinimize) N_suppliers supplier_cap_mean.shape[0] weeks range(horizon) # 定义决策变量 order pulp.LpVariable.dicts(order, ((i, t) for i in range(N_suppliers) for t in weeks), lowBound0) inventory pulp.LpVariable.dicts(inv, (t for t in weeks), lowBound0) # 目标函数最小化总成本采购库存 prob pulp.lpSum([cost_dict[price][i] * order[i, t] for i in range(N_suppliers) for t in weeks]) \ pulp.lpSum([cost_dict[holding_cost] * inventory[t] for t in weeks]) # 约束条件 # 1. 库存平衡约束 (t0时期初库存为current_inventory) for t in weeks: if t 0: prob inventory[t] current_inventory pulp.lpSum([order[i, t] for i in range(N_suppliers)]) - demand_forecast[t] else: prob inventory[t] inventory[t-1] pulp.lpSum([order[i, t] for i in range(N_suppliers)]) - demand_forecast[t] # 2. 满足需求约束库存非负隐含了满足需求但更严格的写法是 for t in weeks: prob inventory[t] 0 # 或 safety_stock # 3. 供应商能力约束 for i in range(N_suppliers): for t in weeks: prob order[i, t] supplier_cap_mean[i, t] # 4. 运输能力约束 for t in weeks: prob pulp.lpSum([order[i, t] for i in range(N_suppliers)]) trans_cap # 求解 prob.solve(pulp.GUROBI_CMD(msgFalse)) # 使用Gurobi求解安静模式 # prob.solve(pulp.PULP_CBC_CMD(msgFalse)) # 使用CBC求解 # 提取第一周的决策 week0_order {i: pulp.value(order[i, 0]) for i in range(N_suppliers) if pulp.value(order[i, 0]) 1e-5} return week0_order, pulp.value(prob.objective) # 滚动时域主循环 current_inv initial_inventory all_orders [] total_cost 0 for week in range(total_weeks): # 1. 获取未来N周的需求预测和供应商能力预测基于当前时间点 demand_fcst get_demand_forecast(week, horizon4) supplier_cap_fcst get_supplier_capacity_forecast(week, horizon4) # 这里使用期望值 # 2. 求解当前窗口的优化问题 week_order, period_cost solve_one_period(current_inv, demand_fcst, supplier_cap_fcst, cost_dict, trans_cap, horizon4) # 3. 记录本周决策 all_orders.append(week_order) total_cost period_cost # 注意这是计划成本不是实际成本 # 4. 模拟本周实际到货根据随机性并更新库存 actual_arrival simulate_actual_arrival(week_order) # 一个模拟函数根据随机供货率生成实际到货 current_inv current_inv actual_arrival - demand_real[week] # 5. 确保库存非负如果模拟出现缺货可能需要额外处理如紧急采购这里简化 current_inv max(current_inv, 0)注意事项上述代码是高度简化的框架实际中需要处理更多细节如运输成本函数的线性化、固定订购费用的引入需要0-1变量等。simulate_actual_arrival函数是关键它实现了从“计划订购量”到“实际到货量”的随机映射。这里可以根据之前拟合的概率分布进行随机抽样。目标函数中的period_cost是计划成本。真正的总成本需要在所有周模拟结束后根据实际发生的订购、库存和运输情况重新计算。4. 论文写作要点与独家心得数学建模竞赛三分靠模型七分靠表达。一个清晰、严谨、美观的论文是获奖的关键。4.1 论文结构编排摘要重中之重采用“问题重述-模型方法-主要结果-结论特色”的结构。用精炼的语言说明你们用了什么方法如“基于概率预测和滚动时域随机规划”建立了什么模型设计了什么算法得到了什么结果关键数值如总成本比基线方案降低了XX%以及模型的优点如鲁棒性强、能处理不确定性。问题重述与分析不要照抄题目。用自己的话梳理问题的要素、目标、约束和难点。画出流程图来展示你们的整体解题思路非常加分。模型假设与符号说明假设要合理、必要并说明理由。符号表格要清晰、完整。模型建立与求解这是核心章节。分节论述4.1 数据预处理与供应商分类4.2 供货不确定性建模预测4.3 优化模型确定性/随机的建立4.4 基于滚动时域的求解算法设计4.5 可能用到的启发式算法如遗传算法细节。多用公式和图表重要的约束和目标函数必须用公式列出。图表如供应商分类结果图、预测效果图、算法流程图、滚动时域示意图等能极大提升可读性。模型求解与结果分析给出具体方案以表格形式展示部分周期如前8周、后8周的详细订购方案供应商编号、订购量。核心结果报告最终的总成本并与其他简单策略如恒定订购策略、仅向最便宜供应商订购策略进行对比用数据证明你们模型的优越性。灵敏度分析改变关键参数如运输能力±20%库存成本±15%观察总成本的变化趋势用折线图展示。分析哪个参数对结果最敏感并给出管理启示。蒙特卡洛模拟评估用你们得到的方案在随机生成的大量未来场景下运行计算平均成本、成本方差、缺货次数等风险指标。这能有力证明方案的鲁棒性。模型评价与推广客观评价模型的优点考虑全面、鲁棒性强、实用和缺点计算复杂度高、对预测精度依赖等。提出改进方向并简要说明模型可推广到其他类似场景如能源调度、物流配送。4.2 独家避坑指南与心得坑1忽视运输能力约束。这是题目中最容易设置陷阱的地方。很多队伍只关注订购和库存忘了每周运进来的原材料总量是有限的。一旦忽略你的“最优解”可能根本无法实施。务必在模型和论文中突出强调对此约束的处理。坑2追求预测模型的复杂度而本末倒置。花三天时间调一个完美的LSTM预测模型结果优化模型没时间建了这是最常见的失败案例。记住本题的核心是优化决策预测是为优化服务的。一个简单稳健的预测如指数平滑或分布拟合结合一个考虑不确定性的优化模型远胜于一个复杂预测加一个简单优化。坑3模型“大而全”无法求解。一开始就想建立一个完美的24周随机规划模型结果变量成千上万约束复杂任何求解器都跑不动。一定要有“简化-求解-验证-迭代”的思想。先从最简单的确定性模型、短周期开始确保流程能跑通得到基础解。然后再逐步增加随机性、延长周期、添加复杂约束。坑4结果分析停留在表面。只给出一个总成本数字就完了。评委想看的是你的方案为什么好好在哪对比实验和灵敏度分析是展示思考深度的最好机会。设计2-3个对比策略如“我的opic策略”、“仅选Top-10供应商策略”用图表清晰对比成本。分析当关键参数变化时你的方案稳定性如何。坑5论文可读性差。公式编号混乱图表没有标题和编号文字描述和图表脱节。写作时要时刻想着读者。每一个公式、每一张图在正文中都要有明确的引用和解释。使用专业的排版工具LaTeX能极大提升论文的“颜值”和专业感。我的一个关键心得引入“安全库存”概念。在库存平衡约束中不要只满足I_t 0。可以设置为I_t safety_stock_t。安全库存量可以根据未来几周需求预测的波动性标准差来计算例如safety_stock_t z * σ_demand其中z是服务水平系数。这简单的一步就能将需求不确定性也纳入考虑显著增强方案的鲁棒性而且非常容易在模型中实现是性价比极高的亮点。5. 常见问题与排查技巧实录在实际编程和调试过程中你一定会遇到各种问题。这里记录几个典型问题及解决思路。问题1模型求解速度极慢甚至无法得到可行解。可能原因1问题规模太大。402家供应商*24周仅0-1变量就有近万个。直接求解混合整数规划确实困难。排查先求解一个简化版如只取前50家供应商规划4周看是否能快速求解。如果能说明是规模问题。解决供应商聚合将地理位置相近、供货特性相似的供应商合并为“虚拟供应商”减少变量数。滚动时域这正是解决大规模多阶段问题的标准方法将24周问题分解为多个4-8周的小问题。启发式算法如果必须求全局解转向遗传算法、模拟退火等它们能在大规模问题上找到满意解不一定是最优。可能原因2约束条件存在矛盾导致无可行域。排查逐一检查约束。最常见的是运输能力Trans_max设置得过小即使所有供应商满负荷供货也无法满足单周需求。或者初始库存为0而第一周的需求大于第一周的最大可能到货量供应商总能力*运输能力上限。解决检查题目给出的数据确认约束参数是否合理。如果问题本身在极端情况下就是无解的需要在模型中引入“缺货惩罚”或“紧急采购”选项将硬约束放松。问题2滚动时域控制的结果不稳定每周计划波动很大。可能原因1预测模型波动大。如果使用的预测方法如简单移动平均对近期数据异常敏感会导致每周的预测输入剧烈变化从而影响优化结果。解决采用更平滑的预测方法如指数平滑给历史数据赋予衰减权重或使用更长期的均值。或者在优化模型的目标函数中增加一个“计划平滑性”惩罚项例如惩罚相邻两周订购量之和的剧烈变化。可能原因2规划周期Horizon太短。如果只规划未来2周模型会非常“短视”容易做出激进调整。延长规划周期如到6-8周能让模型更兼顾中长期利益计划会更平稳。解决尝试不同的规划周期长度观察总成本和平稳性的 trade-off选择一个平衡点。问题3蒙特卡洛模拟显示方案风险很高成本方差大。可能原因模型过于追求期望成本最小而忽略了风险。确定性等价模型或只考虑期望值的随机规划都有此问题。解决在优化模型的目标函数中引入风险度量。最常用的是条件风险价值CVaR。可以在目标中最小化期望成本 λ * CVaR其中λ是风险厌恶系数。这样得到的方案会在成本和风险之间取得平衡。在论文中实现并分析不同λ下的方案表现是一个高级亮点。问题4论文中的图表很多但看起来不专业。解决统一风格所有图表使用一致的配色方案如Set2, Tab20c色系、字体如Times New Roman, Arial、线型和标记点。信息完整每个图必须有编号、标题坐标轴必须有清晰的标签和单位。图例要清晰。突出重点折线图的关键转折点可以标注数值柱状图的数据标签可以显示具体值热力图要选择合适的色彩映射。工具推荐Python的matplotlib和seaborn库可以做出出版级的图表。记得调整dpi到300以上保存为矢量图格式如.pdf,.svg嵌入论文这样放大不会模糊。最后再强调一点团队协作的心得三个人一定要有明确分工但又要紧密沟通。通常一人主攻模型与算法编程能力强一人主攻数据与预测统计学好一人主攻论文写作与整合文字和逻辑能力强。每天至少开两次短会同步进度遇到卡点及时讨论。论文写作一定要尽早开始不要等所有结果都出来再写模型描述、假设、符号说明等部分可以提前撰写。用Git或网盘做好代码和文档的版本管理避免最后时刻合并冲突。这场竞赛比拼的不仅是智力更是体力、毅力和团队协作的综合能力。