fix(solve): 审查 mm1_metrics + 第二批入口改动(工程侧收口 + 6 条测试)
用户本轮改了 markov_simulate / markov_steady_state 的入口校验,并写完 mm1_metrics,
三处算法本体都正确(mm1 的 5 个公式经探针与闭式解逐位对拍通过,含 W = Wq + 1/mu)。
Codex 只动工程侧:
Fixed
- mm1_metrics 的稳定性分界 "<" 应为 "<="(docstring 与既有测试的口径都是 lambda >= mu 不稳定):
lambda == mu 原先掉进 try、rho == 1.0 触发 ZeroDivisionError,被 except 吞成 success=False。
两个分支的可观测输出完全相同(success=False / metrics={} / data=None),只有 message 不同,
故按决策 31 直接修并加回归测试,未改动任何口径。
- 三处报错文案的参数名抄错:markov_steady_state 的 max_iter <= 0 写成 "tol 必须是正数",
mm1_metrics 的 service_rate 两条报错都写成 "tol";半角逗号统一为全角。
Changed
- mm1_metrics 的 docstring 补 Raises 与 data 说明;call_params = {...} 补空格;
ruff 6 条(W293 x5 / F541 f-string 无占位符 / W292 文件末尾无换行)。
- markov_steady_state 的 try 前 3 个空行 -> 1;"异常: " -> "异常:"。
- tests/test_solve.py:摘掉 2 条 mm1_metrics 的 skip,新增 4 条(lambda == mu 的回归、
非负校验回归、max_iter=3 未收敛判 success=False)。
- STATUS.md 决策 56 / 57 更新办结项 + 新增决策 58(mm1 的 4 条待拍板);CHANGELOG;易错点 29。
校验:pytest 202 passed / 28 skipped(230 收集);ruff 0;pyright 0
This commit is contained in:
1 parent
0955890010
commit
953e988983
5 files changed
+311
-72
No files matched your search
@@ -487,3 +487,22 @@
|
||||
有限性(`np.isfinite`,挡 NaN / inf)、取值区间**;② 同一函数里同类参数(`max_iter` / `tol` / `n` / `tol`)
|
||||
用**同一套模板**写,别一个查 `bool` 一个不查;③ 校验"概率/权重"这类输入时,除了和为 1,还要问一句"有没有可能是负数/NaN"。
|
||||
- 首次:2026-10-09|复发:0
|
||||
|
||||
### 29. 同一个校验里的两把尺子:一个宽容、一个精确
|
||||
|
||||
- 现象:`markov_simulate` / `markov_steady_state` 校验转移矩阵时有两条:
|
||||
`if not np.allclose(arr.sum(axis=1), 1.0)`(**宽容**,默认 `atol=1e-8`)和 `if np.any(arr < 0)`(**精确**)。
|
||||
实测 `[[1.0, -1e-16], [0.5, 0.5]]`:行和都是 1.0,但左边那行有个 `-1e-16` 的归一化残渣 →
|
||||
被判"含负元素"直接报错。**这个矩阵在数学上没问题,是校验太严**。
|
||||
- 为什么会错:两条校验是分两次、照着不同念头写的 —— 行和那条想着"浮点比较不能写 `==`",
|
||||
非负那条想着"概率怎么能为负"。各自都对,**放在一起就成了一严一宽**。建模时矩阵常常是
|
||||
`df / df.sum()` 归一化出来的,这类 `-1e-17` 残渣非常常见,比赛现场会直接卡住。
|
||||
- 同族(同一轮里一起犯的):① 边界比较与文档口径不一致 —— `mm1_metrics` 写 `service_rate < arrival_rate`,
|
||||
而 docstring 与测试都写 `λ >= μ` 不稳定,于是 `λ == μ` 掉进正常计算分支、`rho = 1` →
|
||||
`ZeroDivisionError`(结果碰巧对,message 却是"计算失败:ZeroDivisionError");
|
||||
② 一批报错文案是复制粘贴的,**参数名忘了改** —— 同一轮里 `max_iter` 的文案写 "tol"、
|
||||
`service_rate` 的两条文案也都写 "tol"。两条都是"看着像对的、跑起来也行、但口径/文案是错的"。
|
||||
- 以后怎么防:① 同一个量的多条校验,**先把容差定下来再写**(要么都用 `np.allclose` / 小 `eps`,要么都精确),
|
||||
写完回头对一眼"这几条的严格程度一致吗";② 阈值类比较(`<` / `<=`)**对着 docstring 读一遍**,
|
||||
特别是 == 落在哪边;③ 复制粘贴报错文案时,逐个把参数名念出来。
|
||||
- 首次:2026-10-09|复发:0
|
||||
Reference in new issue
Block a user