01 数学建模中M的取值影响及分析

在应急物资调度常涉及条件性约束(如:若启动某储备点,则需满足最低物资储备量;若发生重大灾害,则运输车辆需优先保障)。这类逻辑约束需通过大 M 法转化为线性约束,而 M 的取值直接影响约束的 "生效强度"。

直观的理论分析

设二进制变量y∈0,1y \in {0,1}y∈0,1表示 "是否触发某条件"(如y=1表示启动应急储备点),连续变量x表示决策变量(如物资调出量)。常见逻辑为:

  • 若y=1y=1y=1(触发条件),则x≥Lx \geq Lx≥L(需满足最低要求,如最低调出量);
  • 若y=0y=0y=0(不触发),则x=0x=0x=0(不调出物资)。

上述表达形式可转化为如下线性约束:
(1)x≥L⋅y−M⋅(1−y)(1) \quad x \geq L⋅y−M⋅(1−y)(1)x≥L⋅y−M⋅(1−y)
(2)x≤M⋅y(2) \quad x \leq M⋅y(2)x≤M⋅y

其中,MMM为足够大的常数。当y=1y=1y=1时,约束 (2) 变为x≤Mx \leq Mx≤M(不影响,因MMM足够大),约束 (1) 变为 x \\geq L(生效);当(生效);当(生效);当y=0时,约束(1)变为时,约束 (1) 变为时,约束(1)变为x \\geq −M(不影响,因(不影响,因(不影响,因x≥0),约束(2)变为),约束 (2) 变为),约束(2)变为x \\leq 0(生效,即x=0)。

M 取值的影响:

  • M 过小:若M<L,当y=1时,约束 (2) 可能限制x≤M<L,与约束 (1) 的x≥L矛盾,导致可行域为空;
  • M 过大:线性松弛问题的可行域范围膨胀,可能导致求解效率下降(如分支定界树过深),甚至数值不稳定;
  • 最优 M:取变量x的理论最大可能值(如储备点最大库存量),确保M≥L且不冗余。

一个简单的案例

问题背景:某地发生地震,需从两个储备点(A 和 B)向灾区调运医疗物资(如绷带)。决策目标是最小化总运输成本,同时满足:

  • 若启动储备点(yA=1y_A=1yA=1或yB=1y_B=1yB=1),则该点调出量xAx_AxA(或xBx_BxB)不得低于 50 单位(确保灾区基本需求);
  • 若不启动储备点(yA=1y_A=1yA=1或yB=1y_B=1yB=1),则调出量为 0;灾区总需求为 100 单位,需完全满足。

模型参数:A 到灾区的运输成本为单价8元/单位,B到灾区运输成本为单价10元/单位;储备点最大库存量,A为80单位,B为100单位;最低调出量L=50单位,在启动时需满足。

完整模型

决策变量:
xAx_AxA:从 A 调出的物资量,连续变量,xA≥0x_A\geq 0xA≥0;
xBx_BxB:从B调出的物资量,连续变量,xB≥0x_B \geq 0xB≥0;
yAy_AyA:是否启动 A,二进制变量,yA∈{0,1}y_A \in \{0,1\}yA∈{0,1};
yBy_ByB:是否启动 B,二进制变量,yB∈{0,1}y_B \in \{0,1\}yB∈{0,1}.

目标函数(最小化运输成本):
minz=8xA+10xBmin z=8x_A + 10x_Bminz=8xA+10xB

约束条件:
xA+xB==100x_A + x_B == 100xA+xB==100 必须满足灾区总需求

x_A \\geq 50y_A - M(1-y_A) A启动

x_B \\geq 50y_B - M(1-y_B) B启动

x_A \\leq 80 $ A的调出量

x_B \\leq 100 B的调出量
xA≥0,xB≥0x_A \geq 0, x_B \geq 0xA≥0,xB≥0 连续变量界
yA,yB∈{0,1}y_A, y_B \in \{0,1\}yA,yB∈{0,1}二进制变量界

Docplex的求解代码

python 复制代码
from docplex.mp.model import Model
import time
def solve_emergency_model(M):
    # 创建模型
    m = Model(name="应急物资调度")
    
    # 决策变量
    x_A = m.continuous_var(name="x_A", lb=0)  # 储备点A调出量
    x_B = m.continuous_var(name="x_B", lb=0)  # 储备点B调出量
    y_A = m.binary_var(name="y_A")            # 是否启动A
    y_B = m.binary_var(name="y_B")            # 是否启动B
    
    # 约束条件
    m.add_constraint(x_A + x_B == 100, "需求满足")  # 总需求100
    # A的启动约束(大M)
    m.add_constraint(x_A >= 50 * y_A - M * (1 - y_A), "A下限约束")
    m.add_constraint(x_A <= M * y_A, "A上限约束")
    # B的启动约束(大M)
    m.add_constraint(x_B >= 50 * y_B - M * (1 - y_B), "B下限约束")
    m.add_constraint(x_B <= M * y_B, "B上限约束")
    # 库存限制
    m.add_constraint(x_A <= 80, "A库存限制")
    m.add_constraint(x_B <= 100, "B库存限制")
    
    # 目标函数:最小化运输成本
    m.minimize(8 * x_A + 10 * x_B)
    
    # 求解
    sol = m.solve()
    if sol:
        print(f"当M={M}时:")
        print(f"x_A = {x_A.solution_value:.0f}, x_B = {x_B.solution_value:.0f}")
        print(f"y_A = {y_A.solution_value}, y_B = {y_B.solution_value}")
        print(f"最小总成本 = {m.objective_value:.0f}\n")
    else:
        print(f"当M={M}时,无可行解(约束矛盾)\n")

# 测试不同M值
time1 = time.time()
solve_emergency_model(M=40)    # 过小
time2 = time.time()
print(f'M=40的求解耗时为:{time2-time1}\n')
solve_emergency_model(M=80)    # 最优
time3 = time.time()
print(f'M=80的求解耗时为:{time3-time2}\n')
solve_emergency_model(M=1000000000)  # 过大
time4 = time.time()
print(f'M=1000000000的求解耗时为:{time4-time3}\n')

运行代码的结果为:

总结

大 M 的取值需严格依据变量理论边界(如库存上限):

  • 过小会导致约束矛盾,丧失可行性;
  • 过大不影响最优解,但降低求解效率;
  • 合理取值应确保 "刚好覆盖变量最大可能值",平衡约束有效性与求解效率。
相关推荐
川川菜鸟9 小时前
2025国赛获奖名单和优秀论文
数学建模
Cathy Bryant1 天前
智能模型对齐(一致性)alignment
笔记·神经网络·机器学习·数学建模·transformer
极客数模2 天前
【浅析赛题,一等奖水平】思路模型数据相关资料!2025 年“大湾区杯”粤港澳金融数学建模竞赛B 题 稳定币的综合评价与发展分析~
大数据·算法·数学建模·金融·数据挖掘·图论·1024程序员节
Big_潘大师2 天前
C# 六自由度机械臂正反解计算
数学建模·机器人·c#·六自由度机械臂
人大博士的交易之路2 天前
龙虎榜——20251031
大数据·数学建模·数据分析·缠论·缠中说禅·龙虎榜·道琼斯结构
电棍2333 天前
kaggle比赛与常用的dash board 3lc
数学建模·dash
木头左3 天前
基于VaR模型的ETF日内动态止损策略实现与理论验证
数学建模
贝塔实验室3 天前
LDPC 码的度分布
线性代数·算法·数学建模·fpga开发·硬件工程·信息与通信·信号处理
fanstuck4 天前
AI辅助数学建模有哪些优势?
人工智能·数学建模·语言模型·aigc