Files
MCM-ICM_Toolkit/docs/03-roadmap.md
T
guzhujushi b70a96dd0c refactor(core): 统一入口 as_array —— 六处手抄的入参处理收成一处(决策 44/45)
## 新增
- `core.validate.as_array(x, *, numeric_only=True, dtype=float, ndim=None) -> (arr, kind)`:
  一次做完"类型白名单 + 转 ndarray + 报告原来是什么容器"。`kind` 是 `"frame"` / `"series"` / `"array"`。
- **还原不代做**(用户拍的板):`describe` / `correlation_*` / `confidence_interval` / `t_test` 的
  输出天生与输入不同形,统一还原只会重演易错点 14;所以只报告 `kind`,调用方自己手写三行。
- `core/__init__.py` 导出 `as_array`;`check_array`(L1 未实现)的 docstring 注明实现时复用它。
- 入口三条硬规矩:**默认绝不摊平**(要摊平显式 `ndim=1`);**不删缺失值**;
  `numeric_only` 按"输出是否与输入同形"选,不按喜好选。

## 去重
- `normalize` / `standardize` / `log_transform` / `zscore` / `confidence_interval` / `t_test`
  六处手抄的 `isinstance(x, pd.DataFrame)` / `select_dtypes` / `np.asarray` 全部删掉,各剩 1 行入口。
- `data/transform.py` 的 `_NUMERIC_TYPES` 白名单连同 3 份副本一起删除 ——
  这类判断原来散在 **5 个文件 31 处**。
- `transform` 的三个函数走 `numeric_only=False`:它们的输出必须与输入同形,跳过非数值列会少列。

## 修掉
- `zscore` / `normalize` / `standardize` / `log_transform` 的 Series 分支**补回 `name`** ——
  此前 `pd.Series(result, index=...)` 会把 `name` 丢掉,管道里 `concat` 会变成无名列。
- "容器对、内容转不成 float"的错误类型,由 numpy 的 `ValueError` 统一成 `TypeError`(决策 45,**待确认**)。

## 测试与文档
- `tests/test_core.py` 新增 `TestAsArray` 8 条:五种容器的 kind、默认只取数值列、
  `numeric_only=False` 遇文本报错、默认不摊平、`ndim=2` 只校验不重塑、白名单外一律 TypeError、
  **保留 NaN**、`dtype=None` 保持原 dtype;`tests/test_stats.py` 新增 1 条(Series 保住 index/name)。
- 全量 **171 条:134 passed / 37 skipped / 0 xfail**;ruff 0,pyright 0;`examples/01` 跑通(exit 0)。
- `docs/02-architecture.md` 新增 §4.8「入口只有一个:`core.validate.as_array`」,目录树补 `as_array`;
  `docs/03-roadmap.md` 的 L1 表下补说明;`docs/dev/personal-pitfalls.md` 新增第 16 条并把索引补到 16。
- `STATUS.md`:决策 44 / 45,E 节记 as_array,「下一步」第 7 条列 3 个待拍板口径。

## 待用户拍板(Codex 一律未代选)
- `int` / `float` 标量是否继续留在白名单(现在会产出 0 维数组,`axis=0` 的算法照样炸)。
- "内容转不成 float" 该用 `TypeError`(现状)还是 `ValueError`。
- 要不要让 `as_array` 顺带返回选中的列(改三元组),省掉 `frame` 分支重写 `select_dtypes`。
2026-10-03 19:17:22 +08:00

5.5 KiB
Raw Blame History

路线图与开发纪律

依据:01-suggestion-review.md §6–§8。 进度看根目录 STATUS.md,本文件只定义"做什么、做到什么程度、什么不做"。


一、功能清单分级

L0 —— 第一周必做(12 个)

没有这 12 个,工具箱根本跑不起来;有了这 12 个,已经能应付大部分题目。

函数 所在模块 档位
Result core/result.py A
get_rng / set_seed core/random.py A
load_table data/io.py A
clean_missing data/clean.py A
detect_outliers data/clean.py S
normalize data/transform.py A
standardize data/transform.py A
describe stats/descriptive.py A
correlation_matrix stats/inference.py A
bootstrap_ci stats/bootstrap.py S
monte_carlo solve/simulate.py S
save_figure viz/export.py A

correlation_matrix 有两个伴随函数(决策 41):correlation_pvalues 给 p 值矩阵、 correlation_table 给"系数 + 星标"的论文表格。三者共用同一套入参守卫与成对删缺失口径。

L1 —— v0.1(共约 40 个)

在 L0 基础上补齐:

模块 函数
core check_array check_same_length check_probability check_square_matrix
data impute_missing winsorize log_transform one_hot_encode train_test_split kfold_split bootstrap_sample

core.validate.as_array(统一入口,决策 44)已提前落地。它不是"多一个公开 API", | stats | zscore coefficient_of_variation confidence_interval t_test anova chi_square_test fit_distribution goodness_of_fit bootstrap_statistic | | models | rmse mae mape smape r2_score adjusted_r2 compare_models fit_linear fit_polynomial fit_nonlinear predict exponential_smoothing fit_arima forecast fit_forest fit_logistic kmeans pca cross_validate | | solve | minimize linear_program integer_program dynamic_programming knapsack_dp simulated_annealing pareto_front monte_carlo_probability monte_carlo_integral random_walk markov_simulate markov_steady_state mm1_metrics local_sensitivity one_at_a_time parameter_sweep robustness_test sobol_analyze morris_analyze | | decision | equal_weights entropy_weights critic_weights ahp_weights ahp_consistency_ratio topsis grey_relational_analysis gm11_fit_predict | | viz | mcm_style plot plot_correlation_matrix plot_residuals plot_convergence save_table |

L2 —— v0.2

  • solve/graph.py:build_graph shortest_path min_spanning_tree betweenness_centrality pagerank max_flow community_detection
  • solve/dynamics.py:solve_ode solve_system find_equilibrium local_stability

触发条件:在真题里真的用到了,或者要为 MCM A / ICM D 备赛时再写。


二、永久不做(防膨胀清单)

原文用"建议不要",这里写成硬规则。往这个清单里加东西,必须先改这份文档。

  • 不重写 SciPy 的优化器、scipy.stats 的分布、scipy.integrate 的积分器
  • 不重写 sklearn 的 estimator(fit/predict 之外一律不做)
  • 不重写 statsmodels 的时间序列框架
  • 不重写 NetworkX 的图算法
  • 不重写 SALib 的 Sobol / Morris / FAST
  • 不实现 NSGA-II / SPEA2 等完整多目标进化算法(用 pymoo)
  • 不实现符号计算引擎(用 SymPy)
  • 不实现完整离散事件仿真引擎(simulate_queue 那种)
  • 不做深度学习 / PyTorch 相关任何东西
  • 不做 GUI、不做 Web 界面、不做 CLI 之外的产品化
  • 不做自动微分、不做 GPU 后端
  • 不为"完整性"补函数——没在真题里用过三次的函数不写

三、开发纪律

3.1 文档两档制

S 档(招牌算法,自实现):完整函数卡片,模板见 dev/function-card-template.md。 覆盖:detect_outliers bootstrap_ci monte_carlo monte_carlo_probability monte_carlo_integral dynamic_programming knapsack_dp simulated_annealing local_sensitivity sobol_analyze entropy_weights topsis ahp_weights gm11_fit_predict。约 15 个。

A 档(薄封装):docstring 里一句话数学含义 + 一句话什么时候用 + 一条 pytest。

判断标准:我会不会去改它的内部实现? 会 → S 档。

3.2 每写一个函数

  1. 先想"这道题里它替代了哪段手写代码"——想不出来就先不写。
  2. 先在 tests/ 里写一条会失败的断言(测已知解析解,不测实现细节)。
    • 参数类型注解按 02-architecture.md §4.7 写全;非法类型抛 TypeError,不静默兜底。
  3. 实现到测试通过。
  4. 在 examples/ 里加一行最小用法。
  5. 更新 STATUS.md。

3.3 提交前

.venv\Scripts\python.exe -m pytest -q
.venv\Scripts\python.exe -m ruff check src tests

四、时间盒

周 目标 完成标志
1 core + data + stats;S 档先写 bootstrap_ci monte_carlo detect_outliers L0 全部通过测试
2–3 models + solve/optimize + solve/simulate compare_models 出对比表
4 solve/sensitivity + decision + viz 一条端到端 example
5–6 用一道真题走完整流程,反向补函数 problems/<年份>_<题号>/ 完成
之后 每做一题沉淀 1~3 个函数 + 对应 test 仓库自然长大

核心原则:先跑通一条完整链路,再补宽度。