☰
大M法+Excel:从单纯形表手工迭代到规划求解全流程解析
2026/10/17 3:26:58 网站建设 项目流程

做排产方案的时候,线性规划是个绕不开的模型,而单纯形法里的“大M法”又是最劝退新人的一关。前阵子我用Excel把一个小排产模型完整算了两遍:第一遍是用单纯形法(大M法)纯公式直接求解,手搭单纯形表逐步迭代;第二遍是用Excel自带的“规划求解”功能一键出结果,再回来校验手算的每一步。整个过程走下来,我觉得这两种方式不是替代关系,而是互补关系。这篇文章就把案例建模、表格布局、检验数公式、迭代消元、规划求解设置、结果对账、常见坑位一次说清楚,适合运筹学刚入门、或者工作中偶尔要做优化决策但不想被黑箱工具糊弄的朋友。

1. 大M法与Excel结合,到底要解决什么

1.1 大M法解决的核心痛点

单纯形法需要一个初始可行基,也就是一堆现成的单位列向量。但实际问题一旦出现“等式约束”或者“大于等于约束”,情况就麻烦了。比方说某个约束是x1 + x2 = 4,你没法靠松弛变量“松出一个”变量来当初始基;再比方说x1 + 3x2 >= 6,标准形化完之后是x1 + 3x2 - s1 = 6,这里的-s1系数是-1,也不是单位向量。这时候初始可行基从哪来?大M法的办法很直接:强行往这两个约束里塞人工变量,让它们补成单位列向量。

人工变量补出来的基,本身不代表真实资源,所以不能让它们留在最优解里“白占便宜”。办法是在目标函数里给它们设一个极大的惩罚系数:求最大值时,人工变量系数用-M;求最小值时,用+M。这个M是一个远远大于其他系数的正数,只要人工变量还在基里,目标函数就会承受巨大损失,迭代过程就会想方设法把它们换出去。等到最终表里人工变量全部出基,或者即使还在基里但取值为0,原问题就还原成真实的优化问题;如果人工变量还在基里且取值大于0,说明原问题根本无可行解。这一套逻辑清晰,但手算容易错,尤其是有多个M项混在一起的时候,正负判断很容易翻车。

1.2 为什么选Excel而不是写程序

很多人觉得,手算太麻烦,写个Python用现成库不就行了?但就我个人的体会,Excel在这个场景下有一个不可替代的优点:每一步迭代都看得见、摸得着。你改动一行公式,整张单纯形表立刻刷新,检验数、比值、目标值的变化全部可视化。写程序更像是一个黑箱:你调用一个函数,它给你一个结果,中间过程如果不专门加日志,基本是看不见的。而Excel的公式天然就是“日志”,你完全可以把每一次迭代复制成一个新工作表,保留完整的演算痕迹。

另外,Excel不用装额外环境,几乎每台办公电脑都有。遇到急事,没有规划求解加载项,没有Python环境,你靠一张空表也能把所有迭代步骤算出来。这正是“直接求解”路线的价值:它不是效率最高的方案,却是最透明的方案。等搞懂原理、验证过结果之后,再用规划求解去处理更大规模的问题,心里会踏实很多。

2. 案例建模:从排产问题到标准形

2.1 一个适合演示的排产模型

为了把大M法的细节完整展示出来,我构造了一个两个变量、两个约束的小案例,故意同时包含等式约束和大于等于约束。某车间要安排两种产品的产量,产品A每件利润2万元,产品B每件利润1万元。市场部门要求两种产品总产量恰好等于4件;车间的瓶颈工序要求总加工时间至少达到6小时,其中A每件耗1小时,B每件耗3小时。两种产品产量都不能为负,问怎么排产利润最大。

设x1为A的产量,x2为B的产量,模型就是:

max z = 2*x1 + x2 约束: x1 + x2 = 4 x1 + 3*x2 >= 6 x1 >= 0, x2 >= 0

这个模型很小,但很有代表性。第一个约束是等式,没有现成的松弛变量;第二个约束是大于等于,化成标准形后会出现-s1,同样不能直接当基。两个约束凑在一起,恰好就是需要大M法出场的情况。如果题目全是小于等于约束,直接加松弛变量就能出初始基,根本不需要人工变量,也看不到大M法的妙处。

2.2 变量改造的三步走

把原问题转为标准形,需要做三个动作。第一个动作,给“大于等于”约束减去一个剩余变量s1,让不等式变成等式:x1 + 3*x2 - s1 = 6。这里的s1 >= 0,它的经济含义是实际加工时间超出最低要求的那部分。

第二个动作,给没有单位列向量的约束补人工变量。第一个等式约束x1 + x2 = 4里没有任何松弛变量,直接补一个人工变量A1,变成x1 + x2 + A1 = 4。第二个约束已经减了s1但系数是-1,无法作为初始基,所以再补一个人工变量A2,变成x1 + 3*x2 - s1 + A2 = 6。人工变量的本质是“造假出来的初始基”,后续必须被迭代出基。

第三个动作,改造目标函数。因为这是在求最大值,人工变量每留在基里一个单位,目标函数就要被扣掉M:

max z = 2*x1 + x2 - M*A1 - M*A2

写到这里,标准形就完整了。这里有个新手很容易忽略的点:人工变量进入目标函数后,它的系数会被计入单纯形表的检验数计算。如果目标函数里漏掉-M*A1 - M*A2,后面算出来的检验数全都不对。

2.3 M值的选取逻辑

大M法里的M不是真的要写成无穷大,在Excel里我们需要给它一个具体数值。取值太小,惩罚不到位,人工变量可能赖在基里不走,最后给你一个“假最优解”;取值太大,Excel浮点运算在多次消元之后会积累微小误差,有时候甚至出现-0.0000000001这种噪声,影响最优性判断。

我的习惯是把M放在一个独立单元格里,比如命名成M,数值设为目标函数系数的100到1000倍左右,同时不要低于约束右端项的数量级。这个案例里目标系数最大是2,右端项最大是6,所以取M = 10000完全够用。如果问题规模大一点,右端项到几千、几万,M就要相应放大到百万级别,否则惩罚力度会不够。把M单独放单元格还有一个好处,就是后续想对比不同M值的影响时,只改一个单元格就能重新算完,不用到处替换公式。

3. 方案A:直接求解——手把手搭单纯形表

3.1 表格布局与通用公式

我在Excel里把单纯形表按这样的结构排布,算是比较标准的一种参考布局。第一行放各个变量的目标系数Cj,第二行放变量名和基变量信息,中间是约束系数矩阵,右侧是右端项RHS,最后一行放检验数。实际Excel布局会根据你的习惯微调,但核心公式是一致的。

以我的案例为例,初始表可以理解成下面这样:

Cj210-M-M
CB基变量x1x2s1A1A2RHS
-MA1110104
-MA213-1016
检验数2+2M1+4M-M00

注意这张表里,Cj行中A1、A2对应的位置不是写一个字母M,而是引用存放M的单元格。比如M放在某个单元格里,A1的Cj就是=-M单元格,A2的Cj同样是=-M单元格。Excel里怎么方便怎么来,但不要直接在公式里写-M,Excel不认识这种东西。

检验数的计算是整套方案的核心。对每一列来说,检验数公式是:

检验数 = 该列的Cj - SUMPRODUCT(当前基变量对应的CB列, 该列的系数列)

用Excel函数表达就是=Cj单元格 - SUMPRODUCT($CB列区域, 当前列区域)。SUMPRODUCT在这里做的是矩阵乘法:把基变量各自的目标系数,和当前变量列里对应行上的约束系数乘起来累加,得到的就是“如果当前变量入基一单位,目标函数会变化的量”。用原来的Cj减掉这个变化量,就是检验数。

我在实际搭建时,会把“检验数”那一行所有列都用同一个公式拖出来,这样既快又不容易错。因为SUMPRODUCT里的两个区域,一个用绝对引用锁定,一个随列变化,拖拽填充后天然形成每一列各自的检验数。

3.2 初始表检查与第一次迭代

初始表的基变量是A1和A2,对应的Cj都是-M,RHS是4和6。初始基本身是单位矩阵,所以初始解是A1 = 4, A2 = 6, x1 = x2 = s1 = 0,此时目标函数值等于-M*(4+6) = -100000,显然是个“天价亏损”的起始点,后续迭代就是要尽快逃离它。

计算初始检验数:

x1列的检验数 = 2 - [(-M)*1 + (-M)*1] = 2 + 2M x2列的检验数 = 1 - [(-M)*1 + (-M)*3] = 1 + 4M s1列的检验数 = 0 - [(-M)*0 + (-M)*(-1)] = -M

M取10000时,2+2M = 20002,1+4M = 40001,都是正数,说明目标函数还有提升空间。按最大检验数原则,x2入基,因为1+4M明显大于2+2M。

入基变量定下来后,用最小比值规则确定出基变量。计算每一行RHS与对应入基列系数的比值,只考虑入基列系数大于0的行:

第1行:4 / 1 = 4 第2行:6 / 3 = 2

最小比值是2,所以第二行的基变量A2出基,主元位置是第2行、x2列、系数3。这一步的逻辑是:要让x2入基,就必须把目前的三个基本可行解边界往回收,最先挡路的是比值最小的那个约束,它对应的基变量先降为0,就需要出基腾位置。

3.3 第一次迭代的实际消元操作

在Excel里做高斯消元,不需要完全靠手算,用行公式就能完成。先把主元行整体除以主元系数3,得到新主元行。然后对另一行做行变换:新行等于旧行减去“新主元行乘以该行入基列系数”。

消元之后,第一轮迭代结束的单纯形表长这样:

Cj210-M-M
CB基变量x1x2s1A1A2RHS
-MA12/301/31-1/32
1x21/31-1/301/32
检验数5/3+2M/301/3+M/30-4M/3-1/3

这轮迭代后的基变量是A1和x2,函数值提高到(-M)*2 + 1*2 = -19998,比初始的-100000好多了,但逼着人工变量出基的进程还在继续。

重新算检验数:

x1列:5/3 + 2M/3,正数 s1列:1/3 + M/3,正数 A2列:-4M/3 - 1/3,负数

正的检验数还有两个,继续迭代。x1列的检验数里M的系数是2M/3,比s1列的M/3大,所以x1入基。

最小比值规则再算一遍:

第1行:2 / (2/3) = 3 第2行:2 / (1/3) = 6

最小比值是3,本轮第一行基变量A1出基,主元位置是第一行、x1列、系数2/3。这一步非常关键,因为人工变量A1终于要被换出基了。

3.4 第二次迭代与最优性判定

继续做行变换,主元行整体除以2/3,相当于乘以3/2;然后对另一行做消元。第二次迭代后的最终表:

Cj210-M-M
CB基变量x1x2s1A1A2RHS
2x1101/23/2-1/23
1x201-1/2-1/21/21
检验数00-1/2-2.5-M0.5-M

此时基变量是x1和x2,两个人造变量都离开了基。检验数行:

x1列:0 x2列:0 s1列:-1/2 A1列:-2.5 - M A2列:0.5 - M

因为M是10000,A1和A2列的检验数都是很大的负数,所有检验数全部小于等于0,满足最优性条件。最优解是x1 = 3, x2 = 1,最大利润z = 2*3 + 1 = 7万元。把结果代回去验证:

x1 + x2 = 3 + 1 = 4 x1 + 3*x2 = 3 + 3 = 6

完全吻合。

表中s1列检验数是负数,也说明剩余变量继续增大无法改善目标;A1、A2检验数被M压得死死的,说明任何试图让人工变量重新入基的行为都会大幅拉低目标函数。这就是大M法“惩罚机制”在检验数层面的直观体现。

3.5 手工消元时的几个实用习惯

整个迭代过程下来,我总结了几个非常实用的习惯。第一,每一步迭代都复制到新的工作表再操作,保留现场。不要在原表上直接覆盖,否则算到第三步想回头核对第一步的公式和数值时,你会非常痛苦。

第二,每次迭代前,在表外单独注明本轮“入基变量”和“出基基变量”。这个备注看起来不起眼,但当你隔几天回看这份表时,它能帮你快速回忆起迭代路线。

第三,Excel默认显示小数,但单纯形表中的分数其实更能看出模式。比如2/3、1/3,你可以在Excel里把这些单元格设置成分数格式,或者在旁边手动标注分数。我个人习惯保留原始小数,在纸面上另写分数推导,两边对照不容易乱。

第四,涉及M的检验数,Excel里数值显示得很夸张,比如20002、40001,但你判断正负时要想一想这背后的代数结构:哪些是真实系数,哪些是M的倍数。如果只看数值不看结构,遇到0.5-M这种负数会觉得莫名其妙,其实它就是M项的惩罚在起作用。

4. 方案B:规划求解加载项

4.1 加载与启用

交换手算验证之后,再用Excel自带的规划求解来对账。规划求解本质是一个优化求解器,背后也可以选择线性规划的单纯形法引擎。第一次使用需要先加载加载项。不同版本的Office路径略有差异,大体是:

点击“文件”菜单,进入“选项”,再找到“加载项”分类,在底部“管理”下拉框里选择“Excel加载项”,点“转到”,在弹出的列表里勾选“规划求解加载项”,确定。这一步完成后,“数据”选项卡右侧就会出现“规划求解”按钮。如果你在列表里找不到这个加载项,很可能当前Office安装不完整,需要修复安装或者确认电脑是否安装了完整组件。Mac版Excel通常在“工具”菜单里能找到类似加载项管理入口。

4.2 建模与参数设置

规划求解使用前,需要先把模型铺到工作表里。我习惯这样安排:用几个单元格存放目标系数,再用一片区域放约束系数矩阵,右侧放RHS和符号,最后留出一块可变单元格区域。

本例的工作表可以这样组织:

单元格区域内容
B2:C2目标函数系数,分别输入2和1
B4:C4第一个约束的系数,分别输入1和1
B5:C5第二个约束的系数,分别输入1和3
D4第一个约束右端值4
D5第二个约束右端值6
E4第一个约束符号 =
E5第二个约束符号 >=
B7:C7可变单元格,即x1和x2,可先填1
F2目标函数公式:=SUMPRODUCT($B$2:$C$2,$B$7:$C$7)
F4第一个约束左端公式:=SUMPRODUCT($B$4:$C$4,$B$7:$C$7)
F5第二个约束左端公式:=SUMPRODUCT($B$5:$C$5,$B$7:$C$7)

然后打开规划求解对话框,参数这样填:

设置目标:F2 到:最大值 通过更改可变单元格:$B$7:$C$7 添加约束1:F4 = D4 添加约束2:F5 >= D5 勾选:使不受约束的变量为非负数 选择求解方法:单纯线性规划

这里有一件很重要的事:必须在“选择求解方法”里选“单纯线性规划”,否则Excel可能用非线性引擎去尝试,速度慢不说,结果也可能偏离真正的线性最优。勾选“使不受约束的变量为非负数”等于把x1, x2 >= 0这个约束写进求解器,漏掉这个勾选是最常见的建模错误之一。

点“求解”之后,Excel会弹出一个结果窗口,通常显示找到一解。可变单元格变成x1 = 3, x2 = 1,目标单元格F2显示7,和手算结果完全一致。这说明直接求解和规划求解两套路线互相校验通过。

4.3 结果验证与敏感性报告

规划求解结果窗口里还有一个选项叫“敏感性报告”。对于线性规划模型,这份报告能提供非常有价值的边际信息。敏感性报告分两块:可变单元格部分和约束部分。

可变单元格部分会列出每个变量的“终值”和“递减成本”。本例中x1和x2的递减成本都是0,说明两个变量都已经进入最优基,目标函数值没法通过微调它们单独变得更好。如果某个非基变量的递减成本是正数,就代表在这个问题的当前最优解里,强行让它入基一单位会让目标函数损失多少。

约束部分会列出每个约束的“阴影价格”。所谓阴影价格,就是约束右端项增加1个单位时,目标函数最优值的变化量。本例第一个约束x1 + x2 = 4是等式约束,它的右端项每增加1,最优目标利润大约会增加2.5万元;第二个约束x1 + 3*x2 >= 6是大于等于约束,它的右端项每增加1,最优目标利润会减少0.5万元,因为最低工时要求提高会限制排产空间,反映在阴影价格上就是负的。这个符号问题特别容易让新手懵,建议结合具体业务场景去理解:对最大化的生产问题来说,提高最低资源消耗门槛,本身就是坏事。

5. 两条路线怎么选:直接求解与规划求解的实战对比

5.1 核心差异对比

同一道题,两种方式都能得到正确答案,但它们的脾性完全不同。放一张对比表,看一眼就明白:

对比项直接求解(手工迭代表)规划求解
原理可见性每一步检验数、比值、出基入基都明明白白黑箱,只给最终结果
学习价值高,适合理解单纯形法和大M法低,适合使用工具解决问题
操作门槛需要知道算法流程,会行变换只需要会建模和设置参数
处理规模变量约束一多就非常累几十个变量几百个约束也轻松
受环境限制不需要加载项需要加载规划求解加载项
出错点符号、比值、M值、消元计算模型区域引用错误、漏掉非负约束
交付效率低高

从这张表可以看出,直接求解最大的价值是“看得见”,规划求解最大的价值是“算得快”。如果你只是想要一个结果去交差,规划求解一分钟搞定;但如果你想知道为什么是这个结果,或者你正在学运筹学的单纯形法,那直接求解就是最好的老师。

5.2 我推荐的组合用法

我个人的路线一直很固定:先拿一个简单案例,自己在Excel里把大M法的迭代表完整走一遍,确定理解了每一步的逻辑;然后把同一个模型用规划求解再算一次,跟手算结果对账。对不上,就回去查表,多半是公式区域引用或者符号方向写错了;对得上,就可以放心用规划求解处理更大规模的问题。

工作中如果有业务方追问“这个最优解是怎么来的”,我也不会只说“规划求解算出来的”,而是会打开之前的手算表,把一张张迭代表翻给他们看。非技术背景的人不一定看得懂单纯形表,但看到检验数、比值、目标值一步步变化,他们会更相信这个结果不是拍脑袋得出的。这也是“直接求解”路线在真实场景里的隐藏价值,它不只是教学工具,还是沟通工具。

6. 常见问题与避坑速查

6.1 大M法手工迭代的翻车点

大M法手算最容易翻车的地方,我概括成三类。第一类是目标函数里忘了给人工变量加M惩罚。人工变量在初始表和约束里都老老实实加了,但目标函数漏了-M*A1 - M*A2,那初始检验数就少算了对应项,后续迭代的入基选择会全部乱掉,最后经常得到一个人工变量还在基里的假解。

第二类是把检验数正负判断反了。求最大值的时候,检验数大于0说明目标还能改善,要继续迭代;检验数全部小于等于0才是最优。求最小值时方向相反。很多新手在max问题里看到负数检验数就以为可以停了,结果得到一个明显不对的解。

第三类是最小比值规则用得不严谨。算比值时只考虑入基列系数大于0的行,系数小于等于0的行不能参与分母比较。如果所有入基列系数都小于等于0,说明目标函数在这个方向上可以无限增大,问题无界。实际排产场景里出现无界,通常说明建模时少写了某个资源约束。

6.2 规划求解的异常现象

规划求解虽然方便,但也不是永远顺风顺水。我遇到过几次比较典型的异常。第一,求解结果出现负数。十有八九是“使不受约束的变量为非负数”没勾上,或者勾上之后又被后续约束区域设置覆盖了。打开对话框重新检查一遍就好。

第二,弹窗提示“求解器找不到可行的解决方案”。这种情况多半是模型本身无解,也就是约束条件相互矛盾。我曾经把等式约束右端项填错了一位小数,导致模型怎么都无解。后来我会习惯性把模型先手动估算一遍,粗算发现结果不对再回查单元格,排查效率高很多。

第三,求解结果出来了,但目标值和手算不一致。这时候优先怀疑SUMPRODUCT公式的区域是否错位,其次检查约束符号里“=”和“>=”“<=”是否都准确写入。单纯形法对等号非常敏感,等于号和大于等于号在业务上含义可能相近,但在数学模型里是完全不同的约束。

6.3 一张速查表

把常见现象、原因和解决办法整理成一张速查表,排查起来会快很多:

现象常见原因处理办法
最优表里人工变量还在基内且值大于0原问题无可行解回查约束方向和右端符号
人工变量一直出不了基M取值太小,惩罚不足把M放大1到2个数量级
检验数符号判断错max和min方向搞混统一转成max问题,或简化成负系数
比值θ出现负数或不能选入基列系数可能小于等于0只取正系数行;若全为非正,问题无界
目标值与其他工具对不上模型区域引用错位用SUMPRODUCT逐区域核对
Solver结果有负值非负约束未勾选重新打开设置勾选非负
Solver提示无可行解约束冲突或RHS错误手动粗算验证可解性

这张表不一定要背下来,但建议保存在你习惯的笔记工具里。做实际决策时遇到结果可疑,从这张表里找对应现象,往往能比重新推演算法更快定位问题。

最后再分享一个小体会:我现在做这类优化,交付环节基本都用规划求解,因为它快、准、稳。但每当我拿到一个不太熟悉的模型,或者优化结果跟业务直觉差得很远时,我还是会把这几张单纯形迭代表铺开,老老实实算上一遍。这不是浪费时间,而是让Excel帮你把算法“摊开看”的过程。对刚接触大M法的朋友,我的建议是别急着背判据,先把这个案例的表格亲手做出来,感受一次从负十万到七万的迭代过程,你对单纯形法的理解会扎实很多。

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

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

立即咨询