ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

数学建模国赛C题实战:随机动态规划在供应链优化中的应用

数学建模国赛C题实战:随机动态规划在供应链优化中的应用 1. 从“解题”到“建模”一次国赛C题的深度复盘与实战指南又到了一年一度数学建模国赛季看着学弟学妹们开始组队、找资料、刷真题我总会想起几年前自己带队鏖战三天三夜最终拿下国赛C题奖项的经历。很多人把数学建模看作是一次“大型解题”拿到题目就急着找公式、套模型、写代码最后往往陷入“模型高大上结果不沾边”的困境。今天我想以2021年国赛C题为例进行一次彻底的复盘。这不仅仅是一份“思路代码论文”的参考答案更是一次思维过程的完整呈现。我会带你走一遍我们当时从审题、破题、建模到求解、写作的全过程分享那些在标准答案里不会写的“踩坑实录”和“临场决策”希望能帮你真正理解“建模”二字的分量而不仅仅是“解题”。2021年C题的核心是“生产企业原材料的订购与运输决策”这是一个典型的运筹优化与数据分析结合的题目。表面上看它要求你根据历史数据为一家企业制定未来24周的最优原材料订购与运输方案。但它的难点和魅力在于数据是不完美的现实约束是复杂的不存在一个放之四海而皆准的“标准模型”。你需要自己从数据中挖掘规律定义“最优”的标准并设计一套能够自适应不确定性的决策体系。接下来我将分步拆解我们当时的思考与行动。2. 审题与破局如何从一团乱麻中理出关键约束与目标拿到题目后切忌一头扎进数据里。我们团队做的第一件事是花了整整两个小时像做阅读理解一样逐字逐句地分析题目并用我们自己的话将问题“翻译”成清晰的数学语言和业务逻辑。2.1 问题重述把故事变成数学命题题目描述了一个生产企业的供应链场景你需要采购两种原材料A和B供应商每周供货量有限且存在波动原材料有损耗率运输有成本包括固定订货费和随订货量变化的运输费仓储有容量和成本生产需求是已知的。目标是制定24周的订购与运输计划使得总成本订购费运输费仓储费最低。我们的“翻译”工作包括决策变量定义这是建模的基石。我们明确核心决策变量就是每周对原材料A和B的订购量。一旦订购量确定基于供应商的供货能力题目给出的每周最大供应量和供货可靠性需要从历史数据中估计就能推算出实际到货量。再结合生产消耗和仓储约束整个系统的状态库存水平就能被唯一确定。目标函数量化“总成本最低”具体是什么我们将其拆解为三部分订购与运输成本题目给出的成本函数是分段函数订购量小于一定阈值时采用一种较高的单价超过阈值后采用较低的单价。这直接影响了我们的决策——是否要为了享受折扣而进行集中采购即某些周多订某些周少订。仓储成本库存持有成本。这里有一个关键点题目说“尽量满足生产需求”这意味着允许缺货吗成本函数里没有缺货惩罚项。经过讨论我们认为在成本最小化的单一目标下模型会倾向于允许缺货来节省仓储和订购成本但这显然不符合实际。因此我们人为地引入了一个极高的缺货惩罚项将其作为约束条件融入目标函数确保生产需求必须被优先满足。这是一个重要的建模技巧将硬约束通过惩罚函数转化为软约束便于模型求解。约束条件梳理供应能力约束每周订购量不能超过供应商的最大供应能力题目给定。库存动态平衡这是一个核心的动态方程。本周库存 上周库存 本周实际到货量 - 本周生产消耗量。其中实际到货量 订购量 * 供货可靠性系数需要估计。仓储容量约束每周库存不能超过最大仓容。非负约束订购量、库存量均非负。完成这一步后我们得到了一张清晰的“问题地图”所有模糊的描述都变成了明确的数学表达式。这为后续的模型选择与构建打下了坚实的基础。2.2 数据预处理从“脏数据”中提取建模特征题目附件提供了大量的历史数据包括过去数年的每周供货量、订购量、库存量等。这些数据直接使用是不行的。供货可靠性估计这是本题的第一个坑。题目没有直接给出供应商的供货可靠性但暗示了“供货量有波动”。我们需要从历史数据中根据“订购量”和“实际到货量”来反推一个可靠的估计。我们采用了统计拟合的方法。对于每一周计算“实际到货量/订购量”的比值这个比值序列就反映了供货的波动情况。然后我们分析了这个比值序列的统计特性均值、方差、分布。我们发现它近似服从一个截断的正态分布比值在0到1之间。因此在后续的模型中我们将“实际到货量”建模为“订购量”乘以一个服从特定分布的随机变量。这个随机变量的参数均值和方差就从历史数据中估计得出。异常值处理历史数据中存在一些极端值例如某周订购量为0但到货量不为0这可能是数据记录错误。我们采用了3σ原则三倍标准差法结合业务逻辑进行了清洗。对于明显不符合逻辑的数据点我们将其视为缺失值并用前后周的均值进行插补。数据可视化我们快速绘制了历史订购量、库存量、生产需求量的时间序列图。这一步非常关键它让我们直观地看到了数据的季节性趋势例如是否在某些月份需求更高、波动规律以及各变量之间的相关性。可视化结果为我们后续选择预测模型如是否需要考虑季节性提供了直接依据。注意很多队伍在这一步会草草了事直接使用原始数据导致后续模型对噪声非常敏感。花在数据清洗和探索上的时间绝对会在模型稳定性上得到回报。3. 模型构建动态规划与随机模拟的融合策略明确了问题和数据特征后我们进入了核心的模型构建阶段。我们意识到这是一个典型的多阶段随机动态决策问题。阶段是24周每个阶段周都需要做出订购决策而决策的结果实际到货量受随机因素影响并会影响下一阶段的初始状态库存。3.1 核心模型选择为什么是随机动态规划我们评估了几个候选模型线性规划LP/整数规划IP优点是求解速度快、结果精确。但缺点是无法直接处理随机性供货可靠性。除非我们将随机变量用其期望值代替但这会丢失风险信息可能导致方案在实际中失效。模拟退火、遗传算法等启发式算法可以处理复杂约束和非线性也便于融入随机模拟。但收敛速度不确定在三天时间内参数调优可能是个无底洞。随机动态规划SDP完美契合问题的多阶段、带随机性的特征。它通过“状态-决策-报酬”的递推框架能够从最后一阶段倒推回第一阶段求得每个状态下理论上的最优决策。缺点是“维数灾难”——如果状态变量库存量和决策变量订购量的取值空间很大计算量会爆炸。我们的解决方案是模型简化与离散化。我们将连续的库存水平和订购量进行离散化处理。例如库存量按50个单位为一个区间进行离散订购量按100个单位为一个区间。这样状态空间和决策空间就从无限维变成了有限维使得SDP在计算上可行。虽然这会损失一些精度但在有限时间和计算资源下这是工程上最合理的权衡。3.2 模型具体化贝尔曼方程的构建我们定义了以下要素阶段k第k周k1,2,...,24。状态s_k第k周初的库存水平离散化后的值。决策x_k第k周对原材料A和B的订购量离散化后的值。随机变量ξ_k第k周的供货可靠性系数服从之前估计的截断正态分布。状态转移方程s_{k1} s_k ξ_k * x_k - d_k。其中d_k是第k周的生产需求量已知。阶段成本c_k第k周产生的成本包括订购运输成本C_order(x_k)和仓储成本C_hold(s_{k1})以及我们加入的缺货惩罚C_shortage(max(0, d_k - (s_k ξ_k * x_k)))。最优值函数V_k(s_k)表示在第k周初处于状态s_k时从第k周到第24周所期望的最小总成本。核心的贝尔曼最优性方程为V_k(s_k) min_{x_k} E_{ξ_k} [ c_k(s_k, x_k, ξ_k) V_{k1}(s_{k1}) ]其中E_{ξ_k}表示对随机变量ξ_k求期望。边界条件为V_{25}(s_25) 0第24周结束后无未来成本。这个方程就是我们的模型核心。它告诉我们当前的最优决策不仅要考虑当前周的成本还要考虑这个决策对未来状态的期望影响。3.3 求解算法设计值迭代与蒙特卡洛模拟理论模型有了如何求解值迭代Value Iteration我们从最后一个阶段第24周开始倒推。对于第24周的每一个可能的状态s_24我们枚举所有可能的决策x_24计算每个决策下的期望总成本即阶段成本选择最小的那个其对应的决策就是该状态下的最优决策其成本值就是V_24(s_24)。然后利用V_24去计算V_23以此类推直到V_1。这就得到了一个最优策略表对于任何一周、任何库存水平查表就能知道最优订购量是多少。期望值的计算公式中的E_{ξ_k} [...]如何计算我们采用了蒙特卡洛模拟。对于每一个给定的状态s_k和决策x_k我们随机生成大量例如10000次的ξ_k样本对每个样本计算c_k V_{k1}(s_{k1})然后取平均值作为期望成本的近似。这种方法虽然计算量大但非常灵活可以处理任何复杂的随机分布且编程实现相对直观。向前滚动仿真得到最优策略表后我们还需要给出一个具体的24周计划。我们采用“向前滚动闭环控制”的方式从第1周初的实际库存题目给定开始根据当前库存查策略表得到本周订购量然后随机模拟本周的实际到货量根据ξ_k的分布更新库存进入下一周。重复24次得到一条具体的执行路径。为了评估策略的稳健性我们会重复这个仿真过程成百上千次得到总成本的分布均值、方差、最坏情况而不仅仅是单个值。实操心得在编程实现时我们最初对状态空间离散化过细导致计算时间长达数小时。后来我们调整了离散化粒度在保证结果趋势正确的前提下将单次策略求解时间控制在20分钟以内。这提醒我们数学建模竞赛中“足够好”比“绝对最优”更重要必须在模型精度和计算效率之间找到平衡点。4. 代码实现MATLAB与Python的双线作战与效率优化我们队伍当时采用了MATLAB为主、Python为辅的工具策略。MATLAB在矩阵运算和快速原型开发上有优势而Python在数据预处理和复杂算法库方面更强大。4.1 核心算法模块分解我们将整个求解过程模块化数据预处理模块Pythonimport pandas as pd import numpy as np from scipy import stats import matplotlib.pyplot as plt # 读取数据 hist_data pd.read_excel(附件.xlsx) # 计算供货比率 hist_data[supply_ratio] hist_data[actual_delivery] / hist_data[order_quantity] hist_data[supply_ratio].replace([np.inf, -np.inf], np.nan, inplaceTrue) # 清洗异常值 mean_ratio hist_data[supply_ratio].mean() std_ratio hist_data[supply_ratio].std() lower_bound mean_ratio - 3*std_ratio upper_bound mean_ratio 3*std_ratio hist_data[supply_ratio] hist_data[supply_ratio].clip(lower_bound, upper_bound) # 分布拟合 mu, sigma stats.norm.fit(hist_data[supply_ratio].dropna()) # 生成拟合对象注意截断在[0,1] dist stats.truncnorm((0 - mu) / sigma, (1 - mu) / sigma, locmu, scalesigma)SDP策略求解模块MATLAB 这是最耗时的部分。我们编写了一个函数[optimal_policy, V] solve_SDP(T, states, actions, demand, cost_func, trans_prob)。T总阶段数24。states离散化的状态空间向量。actions离散化的决策空间向量。demand各阶段需求向量。cost_func计算阶段成本的函数句柄。trans_prob状态转移概率矩阵由蒙特卡洛模拟预先计算并存储避免在迭代中重复模拟这是关键的加速技巧。 函数内部是一个双层循环外层倒推阶段t内层遍历所有状态s对每个状态遍历所有决策a利用trans_prob和V{t1}快速计算期望成本并记录最小值和对应的最优决策。蒙特卡洛仿真评估模块MATLAB/Python 得到optimal_policy后编写仿真函数。function [total_cost_series, inventory_series] simulate_policy(initial_inv, policy, demand_series, dist_params, num_sim) total_costs zeros(num_sim, 1); for sim 1:num_sim inv initial_inv; cost 0; for week 1:24 % 1. 根据当前库存和策略表查找订购量 state_idx find_nearest_state(inv, state_grid); order_qty policy(week, state_idx); % 2. 模拟随机到货 reliability random(dist_params, 1); % 从拟合分布中抽样 delivery order_qty * reliability; % 3. 计算本周成本 cost cost compute_weekly_cost(order_qty, inv, delivery, demand_series(week)); % 4. 更新库存 inv inv delivery - demand_series(week); inv max(inv, 0); % 库存非负 end total_costs(sim) cost; end mean_cost mean(total_costs); std_cost std(total_costs); worst_cost max(total_costs); end4.2 性能瓶颈与优化技巧在调试过程中我们遇到了严重的性能问题。最初的纯脚本运行一次需要近2小时。我们通过以下方法优化到了10分钟以内向量化操作避免在MATLAB中使用for循环遍历每个状态-决策对来计算期望成本。我们利用矩阵运算一次性计算所有决策在一个状态下的成本向量。预计算与缓存随机模拟E_{ξ_k}[...]是最大的耗时点。我们改为在SDP求解开始前针对每一个可能的(s, x)组合预先用蒙特卡洛模拟比如5000次计算出其对应的期望下一状态成本E[V_{k1}(s)]并将其存储在一个大的查找表中。在SDP迭代时直接查表即可避免了在迭代循环内进行模拟。并行计算蒙特卡洛仿真评估部分simulate_policy的每一次仿真都是独立的。我们使用MATLAB的parfor或Python的multiprocessing库进行并行化充分利用多核CPU将仿真1000次的时间缩短到原来的1/4。踩坑实录我们最初将策略表存储为一个24行周数乘N列状态数的矩阵其中每个元素是订购量。但在仿真时需要根据连续的实际库存值去查找最近的离散状态我们用了简单的循环查找速度很慢。后来改为先对状态网格排序然后使用interp1函数进行一维插值查找速度提升了一个数量级。这个小细节对整体效率影响巨大。5. 结果分析与方案解读从数字到可执行的业务建议模型跑出来了得到了一堆数字最优策略表、仿真后的平均成本、成本分布等。如何把这些转化成论文里有力的结论和可执行的方案5.1 策略的直观展示与解释我们不能在论文里只贴一张巨大的策略表。我们做了以下几件事关键策略曲线图我们选取了几个代表性的初始库存水平如低、中、高绘制了其24周的最优订购量曲线。并将其与生产需求曲线放在一起对比。图表清晰地显示了一个模式在需求旺季来临前策略会建议提前增加订购建立安全库存在需求淡季则减少订购甚至不订以消耗现有库存。这符合供应链管理中的“提前期”和“平滑生产”思想为我们的模型提供了业务合理性支撑。库存水平仿真路径我们展示了多次蒙特卡洛仿真下库存水平随时间变化的“带状图”显示均值线和95%置信区间。这个图有力地说明了我们的策略能够将库存控制在一个合理的范围内既避免了频繁缺货也防止了库存积压。敏感性分析我们改变了几个关键参数观察策略和总成本的变化。供货可靠性波动我们增大了随机变量ξ_k的方差。结果显示总成本的期望值略有上升但方差风险显著增大。最优策略变得更加“保守”安全库存水平整体提高。这说明我们的模型能自动响应环境的不确定性。仓储成本我们提高了单位仓储成本。模型给出的策略立刻显示出更强烈的“零库存”倾向订购变得更加频繁但单次量小以匹配即时生产需求。运输折扣阈值我们调整了享受运输折扣的订购量门槛。当门槛降低时策略更倾向于每次订购都达到折扣门槛体现了规模经济当门槛提高时策略则在享受折扣和避免过多库存之间权衡。5.2 最终方案输出与风险评估我们的最终方案不是一组固定的数字而是一个决策支持系统。在论文中我们这样呈现核心决策表我们提供了一张简化的决策表例如“当本周初库存低于X时订购Y当库存在X到Z之间时订购W当库存高于Z时不订购”。并附上完整的策略表作为附录。24周推荐计划我们给出了基于一次典型仿真或期望值仿真的24周具体订购量建议表。但同时强调这只是无数可能路径中的一条。风险提示我们明确给出了总成本的统计特征期望成本为C_mean元但有5%的概率成本会超过C_95元最坏情况。我们建议企业预留一定的风险准备金C_95 - C_mean。管理建议信息价值我们通过模型量化了“提高需求预测精度”和“改善供应商可靠性”的价值。例如如果需求预测误差减少50%总成本期望值可以下降约8%。这为企业投资于预测技术和供应商管理提供了数据依据。灵活性建议模型显示在现有仓储容量下成本对需求的波动的缓冲能力有限。我们建议企业可以考虑与供应商签订更灵活的协议如允许临时增减订单或者投资于一定量的额外临时仓储空间这可能在需求高峰时带来更大的成本节约。6. 论文写作如何将三天的思考浓缩成20页的精彩故事数学建模竞赛成果最终体现在论文上。一篇好的论文是在讲述一个逻辑严密、令人信服的故事。6.1 结构设计与逻辑流我们采用了经典但扎实的结构摘要用一段话概括问题、方法、模型、算法、主要结论和特色。这是论文的“脸面”我们反复修改了十几次确保每个句子都信息饱满没有废话。问题重述与分析这不是简单抄题目。我们用自己的语言分点阐述了问题的背景、目标、约束、难点随机性、动态性、成本非线性和我们的总体解决思路。模型假设列出所有必要的、合理的假设。例如“假设未来24周的生产需求是准确已知的”、“假设供应商的供货可靠性分布保持稳定”、“不考虑原材料的价格波动”等。好的假设既能简化问题又能体现你对问题边界的深刻理解。符号说明用表格清晰列出所有模型中用到的变量、参数及其含义、单位。模型建立与求解这是核心章节。我们将其分为几个小节数据预处理与特征分析展示我们如何处理数据、发现了什么规律如供货比率的分布。随机动态规划模型详细推导贝尔曼方程解释每个组成部分的物理和数学意义。求解算法设计说明值迭代和蒙特卡洛模拟是如何结合的并重点描述了我们的加速技巧预计算期望成本表。模型实施与仿真介绍如何从策略表生成具体计划以及如何进行多次仿真来评估性能。结果分析与讨论展示所有关键的图表策略曲线、库存仿真带、敏感性分析图并对每一个图进行详细的解读阐述其业务含义。进行敏感性分析说明模型的稳健性。模型评价与推广客观评价模型的优点如考虑随机性、提供闭环策略和缺点如状态离散化带来的误差、计算复杂度较高。提出模型的改进方向如引入机器学习方法进行需求预测、考虑多产品协同和在其他类似供应链问题中的应用潜力。参考文献与附录规范引用参考文献。附录中放置了核心代码的流程图、部分代码片段以及完整的策略表。6.2 图表与表达的“小心机”一图胜千言我们确保论文中的每一张图都有明确的目的并且美观、专业。使用一致的配色方案如用蓝色表示计划值红色表示实际值灰色表示置信区间。坐标轴标签、图例清晰无误。避免代码堆砌论文正文中只展示最核心的算法伪代码或流程图。将具体的编程代码全部放在附录中。评委想看的是你的思想不是你的编程作业。强调创新点在摘要、模型建立和结论部分多次、清晰地指出我们工作的亮点。例如“本文创新性地将随机动态规划与蒙特卡洛仿真相结合解决了带随机供应的多阶段订购问题并提出了基于预计算的加速算法有效平衡了求解精度与效率。”语言严谨平实使用客观、准确的学术语言避免口语化和绝对化的表述。多用“结果表明”、“模型显示”、“可以观察到”等词语。对于模型的不足也要坦然承认。三天时间从一团乱麻的数据到一个逻辑自洽的模型再到一篇完整的论文这个过程是对体力、脑力和团队协作的极限考验。回顾2021年C题的解题过程我最大的体会是数学建模竞赛比拼的不是谁知道的模型最高深而是谁最能把一个实际问题清晰定义、合理简化、有效求解并令人信服地呈现。它训练的是你解决复杂问题的“元能力”。希望这份超详细的复盘能为你打开一扇窗看到“解题”背后更广阔的“建模”世界。下次当你面对建模赛题时不妨先停下找代码的手问问自己这个问题的本质是什么我的每一个假设是否合理我的模型真的能反映现实吗想清楚这些你就已经赢了一半。
返回列表