📈 第3章 最优化
📄 一句话概括

最优化问题的标准写法只有三行:决策变量、目标函数、约束条件。写不出这三行,就别开软件。 浴盆玩具厂每天做多少只橡皮鸭、多少条鱼,这是两个能拧的旋钮;产能和原料是旋钮拧到头的地方。 这一篇先把这三个东西认清楚,尤其要分清「变量」和「约束」——很多人一开始就把它们搞反。

📝 本章和前面几章的关系

第 1 章拆解、第 2 章判断因果,都是「看清已经发生的事」。 这一章开始换方向:在有限条件下找最好的做法。 最优化是全书唯一一个「给你一个最优解」的工具,也是唯一一个「假设一错答案全废」的工具, 两件事都得记住。

一、厂长的问题里藏着三样东西

「一天做多少鸭子、多少鱼,赚得最多」——这句话里,能拧的、想要的、受限的,各有一个。 能拧的是产量,想要的是利润,受限的是产能和原料。 分析的第一动作还是翻译:把这句话翻译成变量、目标、约束三行。

二、决策变量:你真正能决定的数

x = 一天做多少百只橡皮鸭,y = 一天做多少百条橡皮鱼。 为什么用「百只」而不是「只」?因为数字小一点,图上好看,算起来也不容易错。 单位是自由选择,但要在开头说清。 工人数、机器台数、原料价格都不是决策变量——你说了不算。把它们写进变量里,模型就跑不动了。

三、约束条件:旋钮拧到头的地方

三条硬约束:注塑工时、装配工时、原料。每一条都能写成一个不等式。

资源 单耗(鸭/鱼) 日上限 约束
注塑工时 2/4 分钟 400 2x + 4y ≤ 400
装配工时 3/2 分钟 420 3x + 2y ≤ 420
原料 1/1 公斤 180 x + y ≤ 180

再加上「产量不能是负数」,一共五条。五条一起圈出一块地,就叫可行区域。

四、撞墙的组合不是坏组合

拿几个组合代进去,看谁会撞墙:

鸭, 鱼 注塑 装配 原料 判定
0, 0 0 0 0 可行
100, 50 400 400 150 可行
140, 30 400 480 170 撞墙

撞墙只是说明「做不出来」。做不出来的方案,利润算得再高也没有意义。

五、三行写不出来就别开软件

写在纸上就三行:变量、目标、约束。写不出来,说明你对这门生意还没想明白。 这时候打开 Excel 的 Solver,只会得到一个「看起来很像答案的东西」。 模型不会替你判断该建什么模型——这句听着像废话,是这一章后面所有坑的根源。

六、动手 Demo:浴盆玩具:先弄清能拧哪几个旋钮

四个候选组合,逐个代进三条约束,看谁可行。 这段代码没有优化,它只做一件事:把「可行」这两个字算出来。

def check(x, y):
    inj = 2 * x + 4 * y      # 注塑工时
    asm = 3 * x + 2 * y      # 装配工时
    mat = x + y              # 原料
    ok = inj <= 400 and asm <= 420 and mat <= 180
    print('%3d, %3d | %3d/400 %3d/420 %3d/180 | %s'
          % (x, y, inj, asm, mat, 'ok' if ok else 'blocked'))

for x, y in ((0, 0), (100, 50), (140, 30), (60, 60)):
    check(x, y)

实跑输出:

--------------------------------------------------------------------
浴盆玩具:先弄清能拧哪几个旋钮
--------------------------------------------------------------------

  ① 厂长的原话
  --------------------------------------------------------------------
  我们厂做橡皮鸭和橡皮鱼,两条线共用一个注塑车间。
  厂长问:一天做多少只鸭子、多少条鱼,赚得最多?
  这句话里已经藏好了三样东西:旋钮、目标、限制。

  ② 决策变量:能拧的旋钮
  --------------------------------------------------------------------
  这个厂里,你真正能决定的是两个数:
    x = 一天做多少百只橡皮鸭
    y = 一天做多少百条橡皮鱼
  别的数——工人数、机器台数、原料价格——你说了不算,那些是约束,不是变量。

  ③ 约束条件:旋钮拧到头的地方
  --------------------------------------------------------------------

| 资源 | 约束 |
|---|---|
| 注塑工时(分钟) | 2x + 4y ≤ 400 |
| 装配工时(分钟) | 3x + 2y ≤ 420 |
| 原料(公斤) | 1x + 1y ≤ 180 |

  再加上常识:x 和 y 都不能是负数。

  ④ 试三个组合,看谁会撞墙
  --------------------------------------------------------------------

| 鸭, 鱼 | 注塑 | 装配 | 原料 | 判定 |
|---|---|---|---|---|
| 0, 0 | 0/400 | 0/420 | 0/180 | 可行 |
| 100, 50 | 400/400 | 400/420 | 150/180 | 可行 |
| 140, 30 | 400/400 | 480/420 | 170/180 | 撞墙 |
| 60, 60 | 360/400 | 300/420 | 120/180 | 可行 |

  「撞墙」的组合不是坏组合,它只是不可行——做不出来,利润再高也没用。

  ⑤ 变量、目标、约束三件套
  --------------------------------------------------------------------
  最优化问题的标准写法就三行:
    决策变量:x、y
    目标函数:最大化 3x + 5y
    约束条件:上面那三条加非负
  写不出这三行,说明问题还没想清楚,这时候去开软件是浪费时间。

140, 30 这个组合,注塑刚好用满 400,装配要 480——超了 60 分钟的活,干不出来。 注意「刚好用满」和「超出」只差一步:约束是硬边界,不是建议。

30 秒实验

  1. 找出一个让三条约束全部用满的组合。它能存在吗?为什么?
  2. 把原料上限从 180 改成 140,哪几个组合会从可行变不可行?
  3. 想一想:如果厂里能加一班,该加给注塑还是装配?先别算,凭直觉猜,下一节验证。

常见误区

  1. 把约束当变量:把「工人数」也放进决策变量,模型会给你一个「招 37.4 个人」的答案。
  2. 漏掉非负约束:不加 x ≥ 0、y ≥ 0,最优解可能落在负数上,业务上毫无意义。
  3. 单位混用:工时用分钟、原料用公斤、产量用只,三套单位混着算,结果一定错。
  4. 先开软件再想模型:Solver 不会告诉你少写了一条约束,它只会给你一个错的答案。
自测三问(点开对答案) 1. 最优化问题的三行标准写法是什么? —— 决策变量、目标函数、约束条件。三行写不出来,说明问题还没想清。 2. 为什么「撞墙」的组合不代表它不好? —— 撞墙只是不可行,做不出来。可行性是硬门槛,跟好坏是两个维度。 3. 为什么要有非负约束? —— 产量不能是负数。没有这条,数学上的最优解可能落在负数区间,业务上没有意义。

变量和约束认清了,还差一个「想要什么」。下一篇把「赚得最多」写成一个能算的式子。

相关笔记