十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

数学建模竞赛C题解析:动态不确定环境下的供应链成本优化模型

数学建模竞赛C题解析:动态不确定环境下的供应链成本优化模型 1. 赛题回顾与核心问题拆解2021年的全国大学生数学建模竞赛C题题目是“生产企业原材料的订购与运输”。这道题一出来很多同学的第一反应是这不就是个供应链优化问题吗看起来好像不难。但真正上手做就会发现里面坑不少远不是套个简单的EOQ经济订货批量模型就能解决的。这道题的核心在于如何在一个动态、不确定、且具有复杂约束的真实商业环境中为企业制定一套成本最优的原材料订购与运输策略。它考察的不仅仅是数学建模能力更是将实际问题抽象为数学模型并利用算法求解的综合能力。题目给出了某企业过去五年的原材料供货量数据以及未来24周两个生产周期的产能和产品需求预测。原材料由两家供应商提供每家供应商的供货特点、价格、运输方式每周一次或两周一次和运输损耗率都不同。企业需要决定每周向每家供应商订购多少原材料采用哪种运输方式目标是在满足未来24周生产需求的前提下使得总成本包括订购成本、库存持有成本、运输成本和可能的缺货惩罚成本最小。这里的关键词是“动态”和“不确定”。动态体现在每周的决策都会影响后续的库存状态和成本不确定则隐含在供货量的历史数据中——供应商的供货量并非固定值而是有波动的这意味着我们的订购策略必须具备一定的鲁棒性以应对供应风险。很多队伍一开始就栽在了这里要么把问题静态化处理要么忽略了供应商供货的随机性导致模型脱离实际结果自然不理想。2. 解题总体思路与模型框架选择面对这样一个多阶段决策问题主流的建模思路是建立一个动态规划Dynamic Programming, DP模型或随机规划Stochastic Programming模型并将其离散化后用整数规划Integer Programming或混合整数线性规划MILP来求解。这是最贴近问题本质的框架。为什么是动态/随机规划因为这是一个典型的多周期序贯决策问题。本周的订购决策会影响本周的库存而本周的库存又直接关联到下周的初始库存决策环环相扣。同时供应商供货量是一个随机变量从历史数据中可以拟合其分布我们无法提前精确知道下周供应商实际能送来多少货只能基于预测做决策。因此一个考虑未来多期期望成本的动态随机模型是更严谨的。具体模型框架可以这样构建我们将24周划分为24个决策阶段t1,2,...,24。在每个阶段t我们需要做两个决策1) 向供应商A和B分别订购多少原材料决策变量2) 选择哪种运输方式0-1决策变量。状态变量则是本周初的库存水平。目标函数是极小化24周内的总期望成本。然而直接求解一个24阶段的随机动态规划状态空间和决策空间会非常庞大“维数灾难”。因此在实际比赛中更可行的方案是采用模型预测控制Model Predictive Control, MPC的思想或者称为滚动时域优化Rolling Horizon Optimization。滚动优化策略详解我们并不需要一次性求解未来24周的所有决策。相反我们只求解未来一个较短窗口期例如4周或8周的优化问题但只执行第一周的决策。到第二周时我们根据第一周的实际供货情况这是一个已知的随机实现值更新库存状态并基于新的信息重新对接下来一个窗口期进行优化求解如此循环滚动。这种方法既考虑了未来的影响又降低了计算复杂度并且能根据实际情况进行调整非常适用于本题。在每一轮的滚动优化中我们面对的是一个多阶段的确定性优化问题因为我们将未来窗口期内的供货量用其期望值或其他预测值代替。这个确定性优化问题就可以用标准的MILP模型来描述和求解。Lingo、MATLAB的intlinprog、或Python的PuLP/Gurobi等工具都能胜任。3. 核心数学模型构建与关键细节处理确定了滚动优化的框架后我们需要构建每一轮优化所求解的核心MILP模型。以下是模型的关键组成部分也是论文中需要清晰表述的部分。3.1 参数与变量定义这是建模的基础必须严谨清晰。集合与索引t: 周次索引t 1, 2, ..., T(T为滚动窗口长度如4)。s: 供应商索引s 1 (A), 2 (B)。已知参数数据驱动Demand_t: 第t周的产品生产需求换算成原材料单位。Capacity_t: 第t周的最大产能原材料单位。Price_s: 供应商s的原材料单价。LossRate_s: 供应商s的运输损耗率例如2%意味着到货量为订购量的98%。TransportCost_weekly_s: 供应商s采用每周运输一次的固定运费。TransportCost_biweekly_s: 供应商s采用每两周运输一次的固定运费通常更低。HoldingCost: 单位原材料每周的库存持有成本。ShortageCost: 单位原材料缺货导致的惩罚成本或缺货损失。SupplyForecast_s,t: 预测的第t周从供应商s处可获得的最大供货量上限基于历史数据拟合如取历史分位数。注意这不是实际到货量实际到货量是决策订购量、供货上限和损耗共同作用的结果。决策变量Order_s,t: 连续变量第t周向供应商s的订购量。Inventory_t: 连续变量第t周末的库存水平非负。Shortage_t: 连续变量第t周的缺货量非负。y_s,t: 0-1变量表示第t周是否向供应商s发起运输。y1表示运输发生。z_s,t: 0-1变量表示第t周对供应商s采用的运输频率模式。例如可以定义z1为每周运输z0为每两周运输。更常见的做法是用y变量直接关联运输成本。3.2 约束条件设计约束条件是模型符合实际情况的保证设计时需要仔细推敲。需求与产能平衡约束核心物料流约束对于所有 t Inventory_{t-1} 实际到货量_t - Shortage_t Demand_t Inventory_t其中实际到货量_t sum_s ( Order_s,t * (1 - LossRate_s) )。这个等式是库存动态变化的核心。Inventory_{t-1}是上周库存加上本周到货减去本周缺货应等于本周满足的需求加上本周剩余库存。Shortage_t和Inventory_t通常有互斥关系不能同时为正这可以通过目标函数中的高额缺货成本来自动实现也可以显式地添加逻辑约束。供应能力约束对于所有 s, t 0 Order_s,t SupplyForecast_s,t * y_s,t这个约束非常关键。它表示只有当y_s,t 1即本周决定向供应商s要货时订购量Order_s,t才可以大于0且不能超过该供应商本周的预测供应上限。如果y_s,t 0则订购量必须为0。这完美地将订购决策和运输发起决策绑定在一起。运输频率逻辑约束本题难点之一这是体现“每周或每两周运输一次”的关键。对于供应商s我们需要建模其运输周期。一种清晰的建模方式是引入运输周期相位概念。例如假设我们规定供应商s必须每隔一周运输一次且起始周固定。但这不够灵活。更好的方法是利用y_s,t变量自身来构造约束。 我们可以这样定义如果选择“每周运输”则y_s,t可以自由为0或1但受限于是否订购。如果选择“每两周运输”则需要保证在任意连续两周内y_s,t之和小于等于1。这需要引入一个更高级的0-1变量z_s来表示选择的运输模式然后通过大M法来构造约束。例如令 z_s 1 表示供应商s采用每周运输模式z_s 0 表示采用每两周运输模式。 引入一个辅助0-1变量 w_s,t表示第t周是否是供应商s的一个“运输周”。 约束y_s,t w_s,t 运输发生周必须是“运输周” 如果 z_s 1则 w_s,t 可以全部为1。 如果 z_s 0则需要约束 w_s,t w_s,t1 1 对于所有 t。这个建模稍微复杂但逻辑严谨。在比赛时间有限的情况下很多队伍采用了简化处理先根据总成本预估一个运输频率将其作为固定模式输入模型从而避免在模型中直接处理这个复杂的逻辑约束把问题简化为一个确定运输时间表的优化问题。这虽然损失了部分最优性但极大降低了建模和求解难度是一个实用的比赛策略。库存与缺货非负约束Inventory_t 0, Shortage_t 0 对于所有 t。3.3 目标函数目标函数是极小化总成本通常包括采购成本sum_t sum_s ( Price_s * Order_s,t )运输成本sum_t sum_s ( TransportCost_s * y_s,t )。这里TransportCost_s根据z_s的取值选择每周或每两周的运费。库存持有成本sum_t ( HoldingCost * Inventory_t )缺货惩罚成本sum_t ( ShortageCost * Shortage_t )注意在滚动优化中目标函数通常只计算当前决策窗口期内的成本。但更精细的做法是在窗口期后增加一个“终端成本Terminal Cost”例如用简单策略估算窗口期结束后的库存带来的未来成本以避免模型在窗口期末尾做出短视决策如清空库存。这在高级模型中会考虑基础模型可以忽略。4. 数据预处理、预测与模型求解的实操要点有了模型下一步就是让模型“跑起来”。这里的数据处理和求解器使用直接决定了论文的结果和可信度。4.1 供货量预测SupplyForecast_s,t的生成题目只给了历史供货量没有直接给出未来的SupplyForecast_s,t。这是需要自己拟合预测的。常见方法有移动平均/指数平滑简单快捷假设未来供货量与近期历史平均水平相近。可以分别计算每家供应商每周的多年平均值作为预测值。时间序列模型如ARIMA模型。如果历史数据表现出明显的趋势或季节性可以考虑使用。但本题数据周期较短五年每年约50周且受比赛时间限制使用复杂时间序列模型性价比不高。分位数预测这是一个非常推荐且贴合题意的做法。既然供货有不确定性我们不应该只用一个均值点估计。我们可以用历史数据计算每家供应商在每个周次第1-24周的某个分位数例如75%分位数或90%分位数作为SupplyForecast_s,t。这意味着我们以较高的概率保证供应商能提供这个量的货。这实质上是将随机规划中的“机会约束”思想融入了确定性模型增强了方案的鲁棒性。在论文中阐述这种方法能显著提升模型的深度。4.2 运输频率决策的简化处理策略如前所述在模型中直接处理“每周或每两周一次”的0-1逻辑约束较为复杂。一个行之有效的比赛策略是分步优化第一阶段模式选择。忽略详细的每周订购量从宏观上估算两种运输模式的总成本。例如假设全年需求平稳用EOQ模型的思想估算在每周运输和每两周运输下大致的运输次数、平均库存水平从而比较两种模式下的总成本采购成本相同主要差在运输和库存成本。为每个供应商选择一个成本更低的模式。或者直接根据运输成本与库存成本的权衡做一个简单判断如果单位产品每周的库存持有成本 * 一周的需求量 每周运费 - 每两周运费/2则倾向于选择更频繁的每周运输否则选择每两周运输。第二阶段详细排程。将第一阶段确定的运输模式例如供应商A每周运供应商B每两周运且假设B从第一周开始运作为固定条件代入到MILP模型中。此时y_s,t变量对于供应商B来说在奇数周为1偶数周为0或反之是已知参数。模型只需要优化Order_s,t等连续变量问题大大简化求解速度飞快。4.3 模型求解与工具选择Lingo对于中小规模的MILP问题Lingo非常直接其建模语言描述起来接近数学公式。缺点是处理大规模问题或调试复杂模型时不如编程语言灵活。MATLAB Optimization Toolboxintlinprog函数可以求解MILP。需要在MATLAB中手动构建约束矩阵和向量对于新手来说矩阵构建容易出错但灵活性高便于与数据分析如拟合预测部分集成。Python PuLP/Gurobi这是目前最主流、也最推荐的选择。PuLP是一个免费的建模接口语法直观易于调试。它可以调用CBC、GLPK等开源求解器也能连接商业求解器Gurobi学术免费许可。代码可读性强易于实现滚动优化循环。# 伪代码示例 (Python PuLP) import pulp # 定义问题 prob pulp.LpProblem(RawMaterialScheduling, pulp.LpMinimize) # 定义变量 Order pulp.LpVariable.dicts(Order, ((s,t) for s in suppliers for t in weeks), lowBound0) y pulp.LpVariable.dicts(y, ((s,t) for s in suppliers for t in weeks), catBinary) # 添加目标函数 prob pulp.lpSum(Price[s] * Order[s,t] for s,t in Order) ... # 其他成本项 # 添加约束 for t in weeks: prob inventory[t-1] pulp.lpSum(Order[s,t]*(1-LossRate[s]) for s in suppliers) - shortage[t] Demand[t] inventory[t] for s in suppliers: prob Order[s,t] SupplyForecast[s][t] * y[s,t] # 求解 prob.solve(pulp.GUROBI_CMD()) # 使用Gurobi求解 # 输出结果并更新滚动窗口滚动优化的实现写一个主循环每次循环中用当前最新的库存状态和未来窗口期的需求/供应预测数据构建并求解上述MILP模型提取第一周的决策结果Order_s,1然后根据供应商供货的随机性可以从拟合的分布中随机抽样一个实现值或直接用预测值更新库存时间向前推进一周进入下一个循环。5. 灵敏度分析与模型检验——论文的加分项模型求解出结果后绝不能只给出一个数字就结束。必须对模型和结果进行检验与分析这是优秀论文的标配。关键参数灵敏度分析缺货成本ShortageCost这个参数往往难以精确估计但对结果影响巨大。可以尝试取几个不同的值如从很高到很低观察最优订购策略和总成本的变化。分析在什么成本水平下企业会愿意承受一定的缺货风险在什么水平下必须不惜一切代价保证供应。这能体现你对商业决策的理解。库存持有成本HoldingCost同样进行变化分析观察其对订购批量和运输频率选择的影响。验证模型行为是否符合经济学直觉持有成本越高越倾向于小批量高频次订购。供应预测的置信水平如果你采用了分位数预测可以变化分位数如从70%到95%分析供应保障水平提升所带来的成本增加。这能为决策者提供“多花多少钱可以降低多少供应风险”的量化依据。方案鲁棒性测试用历史数据或随机生成的多种可能的供货情景Scenario去测试你制定的最优策略。例如你可以模拟100种不同的未来供货序列基于历史数据拟合的分布然后固定你的订购策略计算在这100种情景下的平均总成本、成本方差、以及出现严重缺货的次数。这比单纯给出一个基于“期望值”的成本数字要有说服力得多。这体现了你的策略应对不确定性的能力。与简单策略的对比设计一个简单的基准策略例如固定比例策略每周按固定比例向两家供应商订购。“报童”式策略每周根据需求和当前库存用一个简单的公式计算订购量。 将你的优化模型得到的结果与这些简单策略的结果进行对比从总成本、库存水平、缺货率等多个维度展示优化模型带来的提升。这直观地证明了你们工作的价值。6. 论文写作与常见失分点规避最后再好的模型也需要通过论文来呈现。国赛评阅时间紧评委第一眼看到的就是摘要和模型。摘要重中之重必须用精炼的语言在有限篇幅内说清楚“针对什么问题、建立了什么模型、用了什么方法、得到了什么结果、有什么特色”。避免空洞的形容词直接摆出核心方法如“建立了基于滚动时域优化的混合整数线性规划模型并采用分位数预测处理供应不确定性”和关键结果如“总成本较基准策略降低了15.2%且在95%的随机测试情景下无缺货”。模型假设要合理且明确。例如“假设运输损耗发生在运输途中且与运输量成正比”、“假设每周初做出订购决策周末物料到货并满足当周生产需求”、“假设两家供应商的供货能力相互独立”。清晰的假设是模型成立的前提。符号说明建议使用三线表清晰列出所有集合、索引、参数和变量。这是论文规范性的体现。常见失分点模型过于简单或错误如忽略运输频率约束或错误地建模库存动态。务必反复检查物料平衡方程。求解不彻底或结果不合理只给出了第一周的决策没有完整的24周计划或者总成本低得不合理可能忽略了某些成本项或约束。缺乏检验与分析论文只有模型和结果没有灵敏度分析、鲁棒性测试或对比分析显得单薄。编程与建模脱节论文中描述的模型和实际编程求解的模型不一致。确保你写在纸上的模型就是代码里求解的模型。摘要空洞无物摘要里充满了“运用了先进的数学方法”、“建立了科学的模型”等套话却没有实质信息。这道C题是一个经典的运筹学问题它考验的是从实际中提炼数学问题、合理简化、严谨建模、有效求解、并合理解释结果的全链条能力。抓住“动态不确定环境下的成本优化”这个核心合理运用滚动优化和随机规划的思想在模型复杂度和求解可行性之间找到平衡点你就能交出一份有竞争力的答卷。记住在数学建模竞赛中一个清晰、合理、可求解的模型远比一个复杂但无法实现的“完美”模型更有价值。
返回列表