数学建模竞赛实战:基于线性规划与需求预测的定价补货决策模型
2026/8/27 9:28:55 网站建设 项目流程

1. 项目概述:一次高强度的解题思维拉练

每年九月的全国大学生数学建模竞赛,对于参赛学生而言,不亚于一场为期三天的“学术马拉松”。2023年的C题,延续了该赛事一贯的风格:题目背景贴近现实,数据看似庞杂,目标明确但路径开放。它不是一道有标准答案的数学题,而是一个需要你综合运用数学工具、编程能力和领域洞察力去构建、求解并诠释的“项目”。拿到“蔬菜类商品的自动定价与补货决策”这个题目时,很多队伍的第一反应可能是懵的——既有时间序列的销售预测,又有复杂的库存优化,还要考虑定价策略,感觉每个部分都能单独写一篇论文。但数学建模的魅力恰恰在于此:它考验的是你如何将一个复杂的现实问题,拆解、抽象、整合成一系列可量化、可计算的模型,并最终给出一个逻辑自洽、有说服力的解决方案。本文将基于2023年C题,进行一次深度的思路拆解与实战推演,重点不在于给出一个“标准答案”,而在于分享一套面对此类综合性赛题时,如何构建解题框架、选择技术路线、规避常见陷阱的系统性思考方法。无论你是即将参赛的新手,还是希望提升建模思维的老手,相信这些从实战中沉淀下来的经验,能为你提供直接的参考。

2. 核心问题拆解与建模总览

面对一个多目标、多约束的复杂问题,最忌讳的就是一头扎进细节。首先必须站在高处,看清全貌。2023年C题的核心诉求非常清晰:根据历史销售数据,为商超制定未来一周(2023年7月1-7日)的单品定价与日补货计划。但“清晰”的背后,是几个环环相扣的子问题。

2.1 问题结构的四层递进关系

我们可以将整个问题分解为四个具有逻辑依赖关系的层次:

  1. 数据理解与特征工程层:这是所有工作的基石。题目提供了六个品类的蔬菜在2023年6月24-30日的销售流水、批发价格以及损耗数据。你需要首先理解每个字段的含义(如单品编码、销量、售价、成本价),识别数据的特性(是否是面板数据?是否存在缺失或异常?),并从中提取对预测和决策有用的特征。例如,每个单品前几天的销量趋势、是否周末、批发价的波动情况、历史损耗率等。

  2. 需求预测层:这是定价和补货的前置输入。你必须预测未来七天(7月1-7日)每个单品每天的销量。预测的准确性直接决定了后续决策的质量。这里面临的核心挑战是:历史数据只有一周(7天),样本量极少,这对传统时间序列模型(如ARIMA)是巨大考验。因此,如何利用有限数据、结合品类特性进行有效预测,成为第一个技术难点。

  3. 定价决策层:在预测销量的基础上,结合成本(批发价)和可能的损耗,以商超盈利为目标,为每个单品制定每日售价。定价不是孤立的,它会影响销量(需求弹性),而销量又反过来影响库存和损耗。因此,定价模型需要与需求预测进行某种形式的耦合或迭代。

  4. 补货决策层:在给定定价和预测销量的前提下,决定每天每个单品的补货量。目标是满足需求的同时,最小化总成本(包括进货成本、库存持有成本和损耗成本)。补货决策受到保鲜期、库存容量、每日销量波动等多重约束。

这四个层次并非完全串联,而是存在反馈。例如,一个激进的定价策略可能抑制需求,导致预测销量下降,进而影响补货量。在简化模型中,我们通常采用“先预测,再定价,最后补货”的序贯决策流程;在更精细的模型中,则可能需要建立联合优化模型。

2.2 模型选型的核心考量:在简单与复杂间权衡

在三天竞赛的高压环境下,模型选型的首要原则是“可实现性”“可解释性”,而非一味追求复杂。

  • 对于需求预测:由于数据量极小,指数平滑法(Exponential Smoothing)移动平均法这类简单稳健的方法往往是首选。它们对短期趋势有较好的捕捉能力,且计算简单。更高级的思路是引入外部特征,例如将“星期几”作为哑变量,或者利用同类单品(同品类)的销售数据建立聚合-分解模型(先预测品类总销量,再按历史比例分解到单品),这可以有效缓解数据稀疏问题。强行使用LSTM、XGBoost等复杂模型,很可能因数据不足而导致严重过拟合。

  • 对于定价与补货:这是一个典型的运筹学优化问题。核心是定义决策变量(每日售价、补货量)、目标函数(总利润最大化或总成本最小化)和约束条件(如售价范围、库存上下限、保鲜期约束)。可以直接建立线性规划(LP)整数规划(IP)模型。目标函数可以细化为:总利润 = 销售收入 - 采购成本 - 损耗成本。其中,销售收入依赖于“售价 × 销量”,而销量又受售价影响(需求弹性)。这里一个关键的简化处理是:假设在短期(一周)内,需求弹性不变,即销量与售价呈简单的线性或对数线性关系,其参数可以从历史数据中粗略估计。这样,整个优化模型就可以线性化或近似线性化,方便用MATLAB的linprog或Python的PuLPSciPy库求解。

注意:很多队伍在建立优化模型时,忽略了损耗成本的计算。损耗不是简单的“没卖完就扔掉”,题目给出了损耗率数据。在模型中,损耗成本应体现为:损耗成本 = 采购单价 × 补货量 × 损耗率。更精细的模型可以考虑损耗率随库存时间增加而升高。

3. 分步实战:从数据到决策的完整推演

下面,我们以一个具体品类(例如“花叶类”)中的某个单品为例,演示一个完整的、可操作的建模流程。

3.1 第一步:数据清洗与探索性分析(EDA)

拿到数据,不要急着建模。用Python的Pandas进行初步探索:

import pandas as pd import matplotlib.pyplot as plt # 假设已加载销售流水表`sales`和批发价表`cost` print(sales.head()) print(sales.describe()) print(sales.isnull().sum()) # 检查单一单品(例如编码101)的历史销售趋势 single_item = sales[sales['单品编码'] == 101].sort_values('日期') plt.figure(figsize=(10, 5)) plt.plot(single_item['日期'], single_item['销量(千克)'], marker='o') plt.title('单品101过去一周销量趋势') plt.xlabel('日期') plt.ylabel('销量(千克)') plt.grid(True) plt.show() # 计算每日毛利率 single_item['毛利率'] = (single_item['销售单价(元/千克)'] - single_item['批发价格(元/千克)']) / single_item['销售单价(元/千克)'] print(single_item[['日期', '销量(千克)', '销售单价(元/千克)', '批发价格(元/千克)', '毛利率']])

实操心得:这短短一周的数据中,周末(6月24-25日)的销量往往有明显峰值。务必通过可视化确认这一模式,并在特征工程中将其作为一个关键哑变量(is_weekend)加入。此外,观察批发价是否稳定。如果波动大,在预测未来成本时,不能简单使用历史均值,可能需要考虑使用最近一日的价格或一个保守的估计值。

3.2 第二步:需求预测模型构建

鉴于数据只有7个时间点,我们采用霍尔特-温特斯指数平滑法(Holt-Winters),因为它能同时捕捉水平、趋势和季节性。虽然我们只有一周数据,但可以假设存在“周内”季节性(以7天为周期)。实际上,由于数据仅包含一个周期,我们更多是利用其平滑思想。

一个更务实且可解释的做法是加权移动平均结合星期特征

def predict_demand(historical_sales, future_dates): """ historical_sales: 单品过去7天的销量列表 future_dates: 未来7天的日期列表,用于判断星期几 """ predictions = [] # 计算历史日均销量作为基线 base_demand = np.mean(historical_sales) # 计算历史数据中周末(假设周六、周日)相对于工作日的平均增幅 # 这里需要根据历史日期判断周末,简化演示 weekend_boost = 1.2 # 假设周末销量比平日高20%,该值应从历史数据中计算得出 for date in future_dates: # 判断未来日期是否是周末 if date.weekday() in [5, 6]: # 5=周六, 6=周日 pred = base_demand * weekend_boost else: pred = base_demand # 可以加入一个简单的衰减趋势,例如,认为一周后期需求可能略有下降(保鲜期影响) # 这里仅为示例,更复杂的趋势需要更多假设 predictions.append(pred) return predictions

关键点解析:对于数据极度短缺的情况,“基于规则的预测”往往比复杂的“黑箱模型”更可靠。上述方法的核心逻辑是:1. 确定一个基础需求量(历史平均)。2. 根据星期几施加一个调整系数(从历史数据中统计得出)。3. 可以考虑加入一个随时间缓慢衰减的因子(模拟蔬菜新鲜度下降导致的需求减弱)。这种方法虽然简单,但所有参数都有明确来源和解释,在论文中易于阐述。

3.3 第三步:定价与补货联合优化模型

这是整个赛题最核心的部分。我们建立一个以最大化未来七日总利润为目标的线性规划模型。

决策变量

  • p[i]: 第i天(i=1..7)的销售单价(元/千克)
  • q[i]: 第i天的补货量(千克)
  • s[i]: 第i天的预测销量(千克),这是一个由p[i]决定的变量,需要建立关系。

模型假设与公式化

  1. 需求函数:假设销量与价格呈线性关系s[i] = a - b * p[i]。其中ab为需求弹性系数。如何估计?可以利用历史7天的(价格,销量)数据点,做一元线性回归,粗略得到a_hatb_hat注意:这只是一个高度简化的估计,实际中需求弹性可能很复杂。
  2. 损耗:假设每日末未售出的商品会按一个固定比例loss_rate(从题目给出的损耗数据中计算)产生损耗,损耗成本按采购价c[i]计算。
  3. 库存动态I[i] = I[i-1] + q[i] - s[i],其中I[0]为初始库存(题目给出)。
  4. 目标函数:最大化总利润。总利润 = Σ ( p[i]*s[i] - c[i]*q[i] - c[i]*loss_rate*max(0, I[i-1]+q[i]-s[i]) )其中第三项是损耗成本,我们假设只有当天未售出的部分(即补货后库存减去销量)才产生损耗。
  5. 约束条件
    • 售价范围:p_low <= p[i] <= p_high(可根据历史售价的上下浮动一定百分比设定)。
    • 补货量非负:q[i] >= 0
    • 库存容量限制:I[i] <= I_max(题目可能给出或需假设)。
    • 销量非负且不超过可用库存:0 <= s[i] <= I[i-1] + q[i]
    • 需求函数关系:s[i] = a_hat - b_hat * p[i](这是一个将定价和销量关联的关键约束)。

使用Python PuLP库求解示例

from pulp import LpProblem, LpVariable, LpMaximize, lpSum, value # 初始化问题 prob = LpProblem("Vegetable_Pricing_Replenishment", LpMaximize) # 参数定义 days = range(1, 8) a = 100 # 需求函数截距,示例值 b = 2 # 需求函数斜率,示例值 c = [5.0]*7 # 未来七天采购成本,示例值(假设不变) loss_rate = 0.05 # 日损耗率 I0 = 50 # 初始库存 I_max = 200 # 最大库存容量 p_low, p_high = 8.0, 15.0 # 售价上下限 # 定义决策变量 p = LpVariable.dicts("Price", days, lowBound=p_low, upBound=p_high) # 售价 q = LpVariable.dicts("Replenish", days, lowBound=0) # 补货量 s = LpVariable.dicts("Sales", days, lowBound=0) # 销量 I = LpVariable.dicts("Inventory", days, lowBound=0, upBound=I_max) # 库存 # 设置初始库存 I[0] = I0 # 目标函数:总利润最大化 profit_expr = lpSum([p[i]*s[i] - c[i-1]*q[i] - c[i-1]*loss_rate*(I[i-1] + q[i] - s[i]) for i in days]) prob += profit_expr # 约束条件 for i in days: # 库存动态平衡约束 prob += I[i] == I[i-1] + q[i] - s[i] # 需求函数约束(线性近似) prob += s[i] == a - b * p[i] # 销量不能超过可用库存 prob += s[i] <= I[i-1] + q[i] # 求解问题 prob.solve() # 输出结果 for i in days: print(f"Day {i}: Price={value(p[i]):.2f}, Replenish={value(q[i]):.2f}, Sales={value(s[i]):.2f}, Inventory={value(I[i]):.2f}") print(f"Total Profit: {value(prob.objective):.2f}")

模型解读:这个模型将定价和补货决策统一在一个框架下。通过求解这个线性规划,我们直接得到了未来七天最优的每日售价和补货量。其中,需求函数s = a - b*p是连接定价与销量的桥梁。在实际应用中,ab的估计至关重要且非常脆弱。一个稳健的做法是进行敏感性分析:测试不同的a,b值,观察最优解的变化,并在论文中讨论这种不确定性对决策的影响。

4. 模型深化与拓展方向

上述流程提供了一个基础且可实现的框架。但要冲击更高奖项,必须在模型深度和创新性上做文章。以下是几个可行的深化方向:

4.1 需求预测的进阶策略

  • 品类层级建模:对数据极度稀疏的单品,放弃直接预测,转而采用“自上而下”的方法。先预测整个品类的日总需求量(数据更稳健),再根据每个单品历史销售额占比,将总需求分配下去。这需要对占比的稳定性进行分析,或建立占比随时间(如星期几)变化的调整模型。
  • 引入外部变量:虽然题目只给了销售数据,但可以合理假设并建模。例如,价格弹性本身可以作为变量。可以建立面板数据模型,利用不同单品在同一时间点的数据,估计出品类通用的价格弹性系数,再应用于各个单品。
  • 集成学习应对不确定性:采用多种简单模型(移动平均、指数平滑、线性回归)分别预测,然后对其结果进行加权平均或区间估计,得到一个带有置信区间的预测范围,为后续的鲁棒优化提供输入。

4.2 定价-库存联合优化模型的改进

  • 动态规划框架:将问题视为一个有限阶段的随机动态规划问题。每天是一个阶段,状态是当前库存水平,决策是定价和补货量,目标是最大化期望总利润。需求可以建模为随机变量(其分布来自预测的置信区间)。这种方法理论上更优,但建模和求解(尤其是维度诅咒)难度极大,通常需要简化(如离散化状态空间)才能实现。
  • 报童模型的扩展:经典的报童模型解决单周期、随机需求下的库存问题。本题是多周期问题,但可以借鉴其思想。对于每个单品每一天,可以计算一个“临界分位数”,作为决定补货量的依据,同时将价格作为影响需求分布参数的杠杆。
  • 鲁棒优化:考虑到需求预测的不准确性,可以采用鲁棒优化方法。即假设需求在一个不确定集合内波动(例如,预测值±20%),然后寻找一个在最坏情况下性能最好的(max-min)定价补货策略。这能极大提升方案的稳健性。

4.3 考虑现实约束的细化

  • 保鲜期与生命周期:不同蔬菜保鲜期不同。可以在模型中增加约束:商品在进货后第k天必须售出,否则全部损耗。这需要引入“商品年龄”作为状态变量,模型会急剧复杂化,但更贴近实际。
  • 捆绑销售与替代效应:题目中品类内部单品可能存在替代或互补关系。例如,菠菜价格升高,消费者可能转而购买油菜。可以在需求函数中引入交叉价格弹性,但这需要非常强的数据支持和假设,谨慎使用。
  • 多目标优化:除了利润,商超可能还关注销售额、市场占有率、客户满意度(与缺货率相关)。可以建立多目标优化模型,使用帕累托前沿来展示利润与缺货率之间的权衡。

5. 论文写作与常见陷阱规避

数学建模竞赛,成果最终体现在论文上。思路再巧妙,模型再复杂,如果表达不清,也会功亏一篑。

5.1 论文结构黄金法则

  1. 摘要:重中之重!用精炼的语言概括问题、方法、模型、算法、主要结果和结论。避免细节,突出亮点。例如:“针对蔬菜定价补货问题,本文构建了基于加权需求预测与线性规划联合优化的决策模型。首先,通过引入星期特征改进指数平滑法进行销量预测;进而,建立以利润最大化为目标、考虑损耗与库存约束的线性规划模型,求解得到未来七日最优定价与补货计划。最后,通过敏感性分析验证了模型鲁棒性,并为商超提供了管理启示。”
  2. 问题重述与分析:不要照抄题目!用自己的话梳理问题的背景、目标和限制条件,并画出逻辑框图,清晰地展示你对问题的分解思路(如本文2.1节所示)。
  3. 模型假设:列出所有关键假设,并说明其合理性。例如:“假设短期内单品需求与售价呈线性关系”、“假设不同单品间的需求相互独立”、“假设损耗仅发生在每日营业结束后”等。好的假设是简化问题的关键。
  4. 符号说明:用三线表清晰列出所有模型中使用的变量、参数及其含义、单位。
  5. 模型建立与求解:这是核心章节。对应你的建模步骤,分小节阐述。每一部分都应包括:动机(为什么用这个模型)、模型详细公式、参数估计方法、求解算法(用了什么软件/函数)。公式要编号,并辅以必要的文字解释。
  6. 模型检验与结果分析:展示运行结果(图表),并对结果进行深入分析。必须进行敏感性分析!改变关键参数(如需求弹性系数b、损耗率),观察结果如何变化,并讨论其管理意义。这能极大提升论文深度。
  7. 模型评价与推广:客观评价模型的优点(创新、实用、稳健)和缺点(假设较强、数据有限等),并提出可能的改进方向。将模型推广到更一般的场景。

5.2 实战中极易踩中的“坑”

  • 坑一:忽视数据量,滥用复杂模型。用LSTM预测7天数据后的未来7天,是典型的“用大炮打蚊子”,结果必然过拟合,预测曲线可能非常奇怪。评委一眼就能看出问题。
  • 坑二:模型“黑箱化”,缺乏解释。只扔出一个复杂的模型代码和结果,不解释中间参数如何得来、为什么这样设置。论文需要让一个不懂你所用算法的人,能理解你的逻辑。
  • 坑三:优化模型不考虑求解可行性。建立了一个非线性的动态规划模型,却无法在论文中给出具体的求解过程和数值结果,只能空谈理论。竞赛中,能求解并给出具体数字结果的模型,远胜于一个精美但无法实现的模型
  • 坑四:结果分析流于表面。只给出“定价提高了3%,利润增加了5%”这样的描述。深度的分析应该是:“当需求弹性系数b降低10%(即需求对价格更不敏感)时,模型给出的最优定价平均上浮了8%,总利润提升12%。这表明在当前市场环境下,消费者对价格波动容忍度较高,商超可采取更积极的定价策略。”
  • 坑五:编程与论文脱节。论文中的结果、图表必须来自你实际运行的代码。确保代码可复现,并在附录中给出核心代码片段(不宜过长)。

三天时间,从审题到成文,是对体力、脑力和团队协作的极限挑战。对于2023年C题这类综合性问题,取胜的关键往往不在于使用了多么高深的算法,而在于对问题的清晰解构、对模型的合理简化、对假设的充分论证,以及将整个思考过程清晰、严谨、有说服力地呈现出来。从数据清洗的一个简单判断,到优化模型中的一个约束条件,每一步都体现着建模者的思考深度。希望这份超详细的思路拆解,能帮助你构建起应对这类赛题的肌肉记忆,在未来的竞赛中,从容地将一个复杂的现实问题,转化为你笔下逻辑严密、闪耀着智慧光芒的解决方案。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询