数学建模七件武器:把现实翻译成能算的模型,再证明它靠得住

1 阅读24分钟

翻译现实、算出答案、证明靠得住——数学建模的七件武器,以及一次完整复现里挖出的三处书中错误。

仓库租金每月都在涨,签长约还是短约?生产线 24 小时不断,几点该排多少人?面包店开几家、几点开门?

这些问题都不是数学问题,但答案得用数学算出来。这就是数学建模。

而它真正难的,从来不是「用哪个求解器」。难在两件事:把一个说不清的现实问题,翻译成一个能算的模型;再证明算出来的结果靠得住。

这两件事,正好对应数学建模的七件武器。

我把《数学建模算法与应用(第 3 版)》前 3 章的 16 道例题全部用 Python 复现了一遍,运行时自动与书中答案逐项比对,共 93 项断言全部一致。副产物是:独立发现了书里的 3 处问题。

配套工程(16 个脚本 + 93 项答案比对 + 10 张教学图,全部可一键跑通): github.com/CurrenWong/…

下面把七件武器和那三处问题拆开讲。

一、建模到底在干什么

一句话:把一个说不清的现实问题,翻译成数学(一个能算的模型),算出结果后再翻译回现实,并且证明这个结果靠得住。

建模是一个闭环:现实问题 → 数学模型 → 解 → 决策 → 验证 → 验证不过就回到模型重想。

绝大多数人的作业停在「解」这一步——右边那两格才是建模真正的产出。求解器给你一个数字,和你能不能对这个数字负责,是两件事。

书里给了五步法,这也是这份材料的骨架:

  1. 提出问题:我要决定什么?有哪些已知量?写不出目标等于没有目标。
  2. 选方法:这问题的结构像哪一类?线性?带整数?非凸?这一步决定了后面七招的顺序。
  3. 建模型:设变量、写目标、写约束。核心是把「现实里的限制」翻译成式子。
  4. 求解:用算法把它算出来。这一步最省心,也最容易骗人。
  5. 回答 + 验证 + 灵敏度:翻译回现实、证明靠得住、参数变了会怎样。

贯穿全书的一句话:建模 = 翻译 → 计算 → 翻译 → 验证与解释。

只会前半段的人叫「会调求解器」,会后半段的人才叫「会建模」。

二、武器一:把现实翻译成线性规划

什么时候用:目标是一次式、约束是一次式、能写成「资源不超过上限」的场景。

三要素只有三个:变量、目标、约束。

min  c1*x1 + c2*x2 + ... + cn*xn
s.t. a11*x1 + ... + a1n*xn <= b1
     a21*x1 + ... + a2n*xn <= b2
     x1, ..., xn >= 0

翻译的关键是找到「变量」。变量 = 你能决定的东西。

例如例 1.4 捷运公司仓库租赁:设 xij = 第 i 个月初签订的、租期 j 个月的合同面积。注意它不是「第 i 个月在用的面积」——差一个字,模型全错。

线性规划的几何图像

把所有约束画成半平面,交出来的那块就是可行域;目标函数是一族平行线,往「值最大」的那条推,撞上约束的地方就是最优解。

这里有个几何事实决定了 LP 求解器为什么快:最优解几乎总是落在顶点上,因为顶点就是约束的交点。

LP 还有三个「天然性质」,直接决定你该怎么检验它:

  • 可行域是凸的 → 最优解唯一,或者是一整条边/面上的多个点;
  • 最优解在顶点 → 解对不对,看它是不是约束的交点;
  • 解对系数线性敏感 → 改了参数解的变化是分段线性的 → 天然能做灵敏度分析。

纸上建模型的通用套路:列一张变量表(名字、含义、单位、范围)→ 写目标(max 还是 min、单位是什么)→ 逐条写约束并注明「现实依据」→ 检查非负性和单位一致性。

写不出依据的约束,要么删掉,要么你还没想清楚。

例 1.4 仓库租赁(第 1 章):各月所需面积 15、10、20、12(单位 100m²),租期 1/2/3/4 个月的每 100m² 月租为 2800 / 4500 / 6000 / 7300 元,5 月起不再需要仓库。求总租借费用最小的签约方案。

书中答案:x11 = 3, x31 = 8, x14 = 12,其余为 0,最优值 z = 118400 元。

落地到 Python 有三件事必须记住:

from scipy.optimize import linprog
# scipy 的 linprog 只做最小化,且不等式只接受 <=
res = linprog(c, A_ub=A, b_ub=b, A_eq=Beq, b_eq=beq, bounds=[(0, None)] * n)
  • 要最大化,先把目标取负,别去改求解器;
  • 模型的 >= 约束整体乘 −1 变成 <=,这是最容易错、报错又最迷惑的地方;
  • 多重最优解是常态,例 1.4 里书中方案和求解器给的方案不同但成本都是 118400,检验要看目标值和可行性,不要逐元素比对解向量。

三、武器二:线性化

什么时候用:目标或约束里出现了 |x|、max、分段函数、乘积——凡是「看起来不像线性」的,先想能不能变过去。

为什么这么重要?线性问题有又快又准的求解器,而非线性问题只能靠局部方法,慢,而且可能给错答案。能线性化就线性化,永远是首选。

绝对值线性化

左:原问题的目标是 V 形曲线,最优解在「尖底」。右:把 x 拆成 u−v(u, v ≥ 0)后,目标 u+v 的等高线变成一组平行直线。

三招及其适用条件:

招式怎么做注意
绝对值x = u − v(u, v ≥ 0),则 abs(x) = u + vu、v 的非负约束绝不能漏。漏了不会报错,会静悄悄给出目标值 0 的错答案
目标里的 maxmax_i abs(eps_i) → 引入 v,约束 -v <= eps_i <= v只把真正该自由的量设成变量。例 1.8 里 eps 是给定的,若把 x 也放开,求解器会让 x = y 使 v = 0
分段函数按段拆开,段之间用 0-1 变量切换这就把整数规划引进来了;段数 > 3 就要考虑别的办法

例 1.7:求 min |x1| + 2|x2| + 3|x3| + 4|x4|,约束为三条线性不等式(x1-x2-x3+x4 <= -2、x1-x2+x3-3x4 <= -1、x1-x2-2x3+3x4 <= -0.5)。书中答案 x = (-2, 0, 0, 0),z = 2。

例 1.8:已知 y 与 x 的各分量,求 min max_i |eps_i|,其中 eps_i = x_i - y_i 是已给定的量,不是待决策量,所以只需对 v 这一个变量求解。

线性化失败之后,判断顺序是:不能线性化 → 判断是否凸 → 又不能又不是凸 → 多起点 + 独立验证。

一个容易混的点:凹 ≠ 非凸

例 3.2 彩电定价(第 3 章)是线性化失败的典型。19 英寸与 21 英寸零售价 339 / 399 美元,成本 195 / 225 美元,固定成本 400000 美元;每多卖一台同型号均价降 1 美分,交叉影响是每卖一台 21 英寸使 19 英寸均价降 0.3 美分、每卖一台 19 英寸使 21 英寸均价降 0.4 美分。

把利润写成 x 的函数:

f = -0.01*x1^2 - 0.007*x1*x2 - 0.01*x2^2 + 144*x1 + 174*x2 - 400000

这个线性化不了,但它的 Hessian 是 [[-0.02, -0.007], [-0.007, -0.02]],特征值 −0.027、−0.013,负定,所以目标函数是严格凹的。无约束下严格凹函数的最大点唯一,令梯度为零就能解析求解:

x* = (4735.04, 7042.74)      f* = 553641

与书中答案一致,误差 1.2×10⁻⁹。

求最大化时,凹目标恰好是好消息:凹函数求最大 ≡ 负的凹函数求最小 = 凸问题。所以判据要看方向——最小化看 Hessian 正定,最大化看负定。

四、武器三:整数性

什么时候用:人、厂、设备、班次、选不选——决策量本身必须是整数。

先忽略整数约束解一次 LP(松弛解),最优点常常落在网格缝隙里:x = 2.4 台机器、y = 4.8 个人,现实里根本不存在。

整数松弛与分支定界

LP 松弛解落在网格缝隙里,整数规划要在附近的格点里挑最好的。

由此得到一个实用技巧:先把 integrality 全关掉跑一次 LP,如果它恰好是整数,那就是整数规划的最优解,可以直接收工。

求解器怎么干活?分支定界——把它拆成一堆好解的小问题。

分支定界

松弛解不满足整数约束,就加一条 x <= 2 或 x >= 3 把它切成两半,各解一次;每支都给一个下界,下界已经不优于当前最优解的,整棵子树直接砍掉。

例 2.5 生产线排班:一条生产线 24 小时不间断,划分 6 个 4 小时班次,各需 35 / 40 / 50 / 45 / 55 / 30 人;每名工人连续工作 8 小时(跨两个班次),只能在某个班次开始时报到。求至少需要多少人。

min z = x1 + x2 + x3 + x4 + x5 + x6
s.t. x1+x6 >= 35,  x1+x2 >= 40,  x2+x3 >= 50
     x3+x4 >= 45,  x4+x5 >= 55,  x5+x6 >= 30
     x_i >= 0 且为整数

书中答案 x = (35, 5, 45, 0, 55, 0),z = 140 人。

什么时候用精确方法:变量几十个以内、目标是线性的、需要证明最优——用 scipy.optimize.milp(HiGHS 分支定界),能混合整数与连续变量。

什么时候用随机方法:变量上百个、目标非线性、能接受「大概最优」。

蒙特卡洛撒网

蒙特卡洛:不列方程,改成随机撒点、数比例。

精度的规律值得记住:误差约等于 1/√N。样本量翻 100 倍,误差只缩小 10 倍。便宜、稳健,但收敛慢。

例 2.9 非线性整数规划是「精确枚举不可能」的题:5 个变量各取 0~99,精确枚举要算 100⁵ = 10¹⁰ 个点。目标是

max z = x1^2 + x2^2 + 3*x3^2 + 4*x4^2 + 2*x5^2 - 8*x1 - 2*x2 - 3*x3 - x4 - 2*x5
s.t. x1+x2+x3+x4+x5 <= 400
     x1+2*x2+2*x3+x4+6*x5 <= 800
     2*x1+x2+6*x3 <= 200
     x3+x4+5*x5 <= 200

书中答案是蒙特卡洛(10⁶ 采样)得 z = 50273,Lingo 精确全局最优 x = (50, 99, 0, 99, 20)、z = 51568。

工程里的打法是组合拳:蒙特卡洛全局撒网 → 局部搜索在好解附近精修 → 多次重启 → 有条件再用 milp 校验,最终精确复现了 51568(10 次重启命中 9 次)。

关键细节:爬山邻域要设计成「单变量 ±1 + 两变量联动 ±1」。只做单变量会卡在 50898——因为约束把变量耦合了,从 (49, 96, 1) 走到 (50, 99, 0) 必须同时动两个变量。

五、武器四:凸性

什么时候用:目标或约束含平方、乘积、三角函数——也就是线性化不了的时候。

先说清一个口径:下面的「碗 / 山地」是最小化问题的画面。求最大化时画面上下颠倒。

凸与非凸

左:目标曲面像碗,不管从哪个点出发往下滚,最后都停在同一个碗底。右:像起伏山地,到处是坑,随初值不同停在不同的坑里,有的坑还不是最深的那个。

凸问题(碗)非凸问题(山地)
初值任何初值收敛到同一个解解依赖初值
最优性局部最优 = 全局最优好几个局部最优,可能陷在坑里
结论解唯一、结果可解释、能做灵敏度无法证明全局最优
对策直接求解必须多起点 + 独立验证

怎么判断凸不凸?算目标函数的 Hessian,看特征值。

你要做的事Hessian 结论得到
最小化 f(x)半正定(特征值全 ≥ 0)凸问题
最小化 f(x)正定(特征值全 > 0)严格凸 → 解唯一
最大化 f(x)半负定(特征值全 ≤ 0)凹
最大化 f(x)负定(特征值全 < 0)严格凹 → 仍是凸问题,解唯一

一行代码搞定:np.linalg.eigvalsh(H)。

「凹 ⇒ 解唯一」只在严格凹时成立。

严格凹与半负定

左:例 3.2 的利润函数,特征值 −0.027、−0.013,负定 → 唯一最优点。右:f = -(x-y)^2,特征值 −4 和 0,半负定 → 出现一个平坦方向,整条对角线上的点全都是最优解。

多出一个 0 特征值,解就从「一个点」变成「一条线」。

回到例 3.2:Hessian 特征值 −0.027、−0.013,负定 → 严格凹 → 无约束下最大点唯一。实测 200 个随机初值,目标值的散布只有 0.11(相对 2×10⁻⁷);解的坐标有 ±5 的抖动纯粹是函数太平坦(曲率仅 0.013)导致优化器提前停下,不是多解。

判断不出来怎么办?多起点跑 + 看结果是否一致 + 用 K-T 验算。标准工作流是:

  1. 构造几个物理上合理的初值(不是随机数!比如「让某架飞机不动」「让料场落在工地上」);
  2. 每个初值解一次,逐个检查可行性(求解器说成功 ≠ 可行);
  3. 取最好的那个,并报告结果对初值的敏感性;
  4. 找一个不依赖求解器的办法独立复核。

例 3.9 两料场选址:6 个建筑工地,位置与水泥日用量分别为 (1.25, 1.25) 3t、(8.75, 0.75) 5t、(0.50, 4.75) 4t、(3.75, 5.00) 7t、(3.00, 6.50) 6t、(7.25, 7.75) 11t,总需求 36 t;拟建 2 个料场,每个日储量 20 t。

料场位置是连续变量,但目标对 (x, y) 非凹,所以是局部方法,必须多起点。书中答案是料场 (7.25, 7.75) 与 (3.2942, 5.1790),总吨千米 72.6303。

工程里的实测:12 个随机初值全部收敛到同一个解,总吨千米 71.9352,比书上那个好。而书上那个 72.6303 的运料方案里,工地 1 被两个料场分供(料场 1 给 0.0329、料场 2 给 2.9671)。

这不是书错了,是随机初值不够好时就会发生的事。

六、武器五:最优性证明

什么时候用:结果要拿去说服人(老板、评委、审稿人)的时候。

求解器返回「收敛成功」,只说明它自己觉得找到了驻点。在凸问题上,有一个严格的判据能证明你找到的就是全局最优——K-T 条件。

K-T 条件

K-T 条件的几何图像:在最优点处,目标函数的梯度方向必须与起作用的约束的切线方向一致。某条约束不起作用(lambda = 0),就不该画它的切线。

三条条件:

grad f(x*) + sum_i lambda_i * grad g_i(x*) = 0     (平稳性)
lambda_i >= 0,   lambda_i * g_i(x*) = 0              (互补松弛)
g_i(x*) <= 0,   x* >= 0                             (可行性)

凸问题里这三个条件是充要的 → 验算通过,就等于证明了「这是全局最优解」。

例 3.1:min f(x) = x1^2 + x2^2 - 4x1 + 4,约束 g1 = -x1 + x2 - 2 <= 0、g2 = x1^2 - x2 + 1 <= 0、x >= 0。书中答案 x* = (0.5536, 1.3064),f* = 3.7989。

工程里的实测:求解器给的结果与书一致,且独立验算了三条 K-T 条件——平稳性残差 1.4×10⁻⁹、互补松弛 lambda = 2.6129 >= 0 且 lambda*g = 1.7×10⁻¹⁰、可行性只有 g₂ 起作用。全部通过。

「独立复核」有四种手段,从弱到强:

  1. 换初值再跑一遍(结果一样 → 大概率对);
  2. 换算法重算(LP 松弛 vs IP、解析解 vs 数值解);
  3. 手算 / 穷举小规模(工程里例 1.4 就是把书上的方案拿回来自己验证可行性和成本);
  4. 仿真 / 几何还原(最硬,见武器七)。

注意:只有独立于求解器的复核才有意义,再跑一次同一个求解器不叫复核。

还有一个反直觉但重要的事实:在凸问题上 K-T 是充要条件,验算它比「多跑几个初值」硬得多;在非凸问题上 K-T 只是必要条件,验算通过也只说明「是个局部最优」。所以先花五分钟判断凸不凸,往往比多跑一百次求解器更省事。

七、武器六:灵敏度分析

什么时候用:永远。答案如果只在某个参数取一个值时成立,那它其实没有答案。

现实里的数据从来不精确。价格弹性可能是 0.006 也可能是 0.02,风险上限可能估错了 10%。灵敏度分析回答的是「我的结论对参数有多敏感」——这是把「一个数」变成「一个决策依据」的关键一步。

灵敏度曲线

彩电定价的真实灵敏度曲线(19 英寸每多卖一台降 a 美元)。左:a 越大,19 英寸减产、21 英寸增产。右:利润和利润率一起走低。

例 1.9 投资的收益与风险(1998 全国数学建模竞赛 A 题)是经典双目标案例:4 种风险资产与银行存款,平均收益率 ri、风险损失率 qi、交易费率 pi、按 ui 计价的阈值 ui 已知,资金 M 相当大,要求净收益尽可能大、总体风险尽可能小。

建模关键有三点:

  1. 总体风险用「所投资产中最大的风险」度量 max_i q_i x_i,这是个 max,引入变量才能线性化;
  2. 交易费是分段函数,因 ui 相对 M 很小,净收益可近似为 (r_i - p_i) x_i;
  3. 这是双目标问题,模型一固定风险上限 a 求最大收益,模型二固定盈利水平 k 求最小风险,模型三按权重 w 加权求和(仍需线性化)。

书中答案:模型一在 a ≈ 0.006 附近出现转折,Q ≈ 2019;模型三 w ≤ 0.7 时收益 2673.27、风险 247.52,w = 1.0 时全存银行(收益 500、风险 0)。

风险—收益曲线的读法不是「哪个点最好」,而是「哪一段性价比最高」:风险从 247 降到 59(降 76%),收益只从 2673 降到 2016(降 25%),这一段就是「买保险」最划算的地方。

三种常见的灵敏度形式:

形式怎么做读出什么
参数扫描让某个参数从 a 扫到 b,每个值解一次 LP/NLP「降价更狠还赚不赚?」
目标扫描反过来固定一个目标值(如收益 ≥ 0.15),求另一个的最优「想要收益 15%,最少得承担多少风险?」
有效前沿用权重 w 把两个目标合成一个,w 从 0 扫到 1所有「不亏」的组合的边界,决策者自己挑

交付形式有两种:一张表(参数 → 目标值)适合放进报告;一条曲线适合让人一眼看出「转折点在哪」——转折点就是决策点。彩电定价里 a = 0.010 附近是转折,投资组合里风险 59–92 之间是转折。

别忘了「模型假设的敏感性」:上面所有分析都在同一个模型假设下变参数。还有一类更重要的问题——如果模型的假设本身错了怎么办(比如「售价随销量线性下降」在极端销量下显然不成立)。这时要回到第一步改模型,而不是做灵敏度分析。

八、武器七:验证

什么时候用:永远,尤其是结论「看起来不太对劲」的时候。

例 3.10 飞行管理避免碰撞(1995 全国数学建模竞赛 A 题):边长 160 km 的正方形空域内若干架飞机水平飞行,速度均为 800 km/h。一架飞机进入区域边缘时,需要立即判断是否会与区域内飞机碰撞;若会碰撞,要计算各机(含新进入的那架)方向角的调整量,使调整幅度尽量小。

条件是:两机距离始终大于 8 km、方向角调整不超过 30°、速度 800 km/h、新进入飞机进入时距区域内飞机 60 km 以上、最多 6 架、不考虑飞出区域后。

书中答案是 delta_theta_5 = 2.7979°、delta_theta_6 = 0.9330°,总调整角 3.7310°。

飞行管理仿真

左:按书上的答案调整后,两架机在 (75, 85) 附近直接穿过,最小间距 2.927 km,远小于 8 km 的安全线。右:本工程的解,两机刚好擦过 8.000 km。

这个差别只有把轨迹真跑一遍才看得出来。

三层验证,逐层加码:

  1. 代回约束——把解代回每一条约束,逐条检查有没有违反;
  2. 独立复算——换算法、换初值、手算小规模、用别的公式重算一遍;
  3. 仿真 / 还原成现实——把解放进时间轴、放进地图、放进生产线,看它到底长什么样。

仿真为什么是最硬的验证?因为它不依赖模型本身,只是按模型的解去执行。模型说「这样调完就不撞了」,仿真把六架机按调完的方向飞一遍,最小间距 8.000 km——这就是现实,不是推论。

反过来,仿真也能抓出模型的漏洞。

不报错 ≠ 对

工程里最有价值的三个发现,全部来自验证,而不是来自跑求解器。

静默出错的典型原因表现
漏写变量的非负 / 上下界目标值跑到 −10¹⁵,或解出负产量
不等式方向写反模型 infeasible(至少会报错,属于好的失败)
单位重复换算4 度变成 229 度
解析梯度漏了因子求解器立刻罢工(会报错)
约束写错但恰好可行最难发现:结果看着合理,其实算的是另一个问题

九、三个书中错误

这就是前面说的副产物。三处问题,全部是不报错的——求解器都给出了一个数。

① 例 3.10 飞行管理:标准答案不满足它自己的约束

按书上给的方向角调整量仿真,六架机里两架在 (75, 85) 附近直接穿过,最小间距只有 2.927 km,而安全线是 8 km。

在「代回约束」这一层就能露馅:机对 (3, 新进入) 的 |beta + s| = 0.777° 小于 alpha = 2.125°,不满足条件。

本工程给出的可行解是 delta_theta_3 = 2.558°、delta_theta_6 = 1.072°,仿真最小间距恰好 8.000 km。

② 例 3.9 两料场选址:书上的连续解是局部最优

书上给的总吨千米 72.6303,而 12 个随机初值全部收敛到 71.9352,更优。书上的解之所以是局部的,是因为它的运料方案里工地 1 被两个料场分供。

③ 例 2.9:书里的 Matlab 代码有一处约束笔误

代码里写的是 sum(z) <= 20,而总需求是 36。这样必然不可行。

这三个 bug 全部「不报错」。所以结论只有一条:书上或别人给的答案,也要用你自己的验证链查一遍。

十、决策表:遇到问题按这张表选招

你遇到的情况用哪一招要点
目标是若干项加权和,约束都是「不超过上限」武器一 · 线性规划最快最准;解可能在顶点;多重最优解要看目标值
目标或约束里有 abs(x)、max、分段武器二 · 线性化u、v 非负约束不能漏;线性化不了再看凸性
决策量不能切一半(人、厂、班次、选不选)武器三 · 整数规划先跑 LP 松弛;变量多 + 目标非线性 → 随机方法
有平方、乘积、三角函数武器四 · 凸性 → 武器五 · K-T先判凸(特征值);凸 → 单次求解即全局最优
解要拿去说服人武器五 · 最优性证明凸问题验 K-T = 严格证明
结论要能指导行动武器六 · 灵敏度分析参数扫描 / 目标扫描 / 有效前沿;找转折点
结果看着可疑 / 要交作业 / 要上生产武器七 · 验证代回约束 → 独立复算 → 仿真,至少走两层

动手前的七步清单:决策变量是什么(名字、含义、单位、类型、范围)→ 目标是什么(max 还是 min,有没有 max 项和绝对值)→ 约束逐条列并标注现实依据 → 判断线性还是非线性 → 判断是不是凸 → 先定好验证方案再动手写代码 → 挑 1–2 个最不确定的参数做灵敏度。

八个坑(这个工程全踩过,代码里都留了注释):

  1. 不等号方向写反 → infeasible,还不说是哪条;
  2. 最大化双重取负 → 目标值符号离谱;
  3. 变量没给下界 → 目标值跑到 −10¹⁵;
  4. 等式约束漏了右端项 → 模型不可行;
  5. 解析梯度漏了 1/2 因子 → 方向全错,求解器立刻罢工;
  6. 单位重复换算 → 4 度变成 229 度;
  7. 消元交叉验证时忘了起作用的那个约束 → 得到次优解 (40, 60) 而非 (35.37, 64.63);
  8. 信任书上的答案 → 以为对了,其实书错了。

最后三句:

  1. 建模不是数学,是翻译。你的功夫全在翻译上。
  2. 先想清楚再算。80% 的错误来自模型建错,而不是求解器算错。
  3. 永远留一条独立的验证路径。能代回约束、能手算小规模、能仿真跑一遍,至少一条。

十一、配套工程

整套材料都是可运行的,不是静态文档:

材料位置
16 个例题脚本(运行时自动与书中答案比对)仓库 ch01–ch03 目录
一键回归(16 脚本 + 93 项答案比对)python run_all.py
本文的 10 张教学图(全部由工程脚本生成)report/make_figs.py → report/figs/
完整长图版报告(11 页,1080 宽)report/png/
各章学习文档(含自测题)各章目录下的 README.md
总览 + Matlab → Python API 对照表仓库根目录 README.md

仓库地址: github.com/CurrenWong/…

克隆后按 README.md 装依赖,python run_all.py 就能把 16 个脚本跑一遍,看 93 项断言是不是真的全过。

十二、怎么练

方法只有练过才是自己的。每周 1–2 小时,三周一轮:

  • 第 1 周 · 跑一遍,看图:把 16 个脚本跑一遍,重点看那 10 张图怎么生成的。改参数(降价幅度 a、风险上限、工人数),看图怎么变,理解「模型是活的」。
  • 第 2 周 · 手推一遍:挑 4 道题(例 1.7 线性化、例 2.5 排班、例 3.1 凸 NLP、例 3.10 飞行管理),遮住代码,用纸写出变量 → 目标 → 约束 → 检查,再对照。写不出来的那一题,就是你需要重读的地方。
  • 第 3 周 · 自己出一道题:把生活里的一个真问题建成线性模型(怎么排通勤、怎么选课、怎么排班)。哪怕很简单。

建模能力是练出来的,不是看会的。


本文的 16 道例题复现与全部图表均已开源。教材正文与 EPUB 因版权原因不随仓库分发,请自行获取正版。


本文首发于公众号,原始链接:github.com/CurrenWong/…

配套代码、10 张教学图与完整长图版报告,见文末 GitHub 仓库。