Skip to content

Releases: anticipate218/math-modeling-skill

math-modeling-skill v1.11.0

Choose a tag to compare

@anticipate218 anticipate218 released this 22 Sep 17:46

math-modeling-skill v1.11.0

面向数学建模竞赛的 AI 助手技能包。这一版把重心放在算法层:公开函数从 222 个扩到 260 个(净增 38 个),自测断言键从 875 条增至 1361 条,并对 17 个算法模块做了一轮逐函数对抗性复核,修掉 20 处真实缺陷。当一个"看着能跑"的实现和一个"能被独立复算"的实现冲突时,本版一律选后者。


新增:38 个公开算法函数(222 → 260)

模块 新增
optimization lp_sensitivity(影子价格 + 基不变区间)、interior_point_lp(原始-对偶内点法,带对偶变量与间隙历史)
graphs bellman_ford(含负环检出)、topological_sort、critical_path(CPM 关键路径 + 松弛时间)
heuristics benchmark_functions(7 个标准测试函数 + 解析最优点/最优值/标准搜索盒)、benchmark_optimizers(同预算同种子横向对比协议)、artificial_bee_colony(ABC)
statistics mann_whitney_u、wilcoxon_signed_rank、kruskal_wallis、anova_oneway、newey_west_se(HAC 标准误)、bca_bootstrap_ci(偏差校正加速自助区间)
evaluation rsr_evaluation(秩和比 + 概率单位分档)、promethee_ii_ranking、kendall_w_concordance(含并列修正)
clustering kmedoids(PAM BUILD + 精确 SWAP)
differential euler_maruyama(批量向量化的 SDE 路径模拟)
stochastic mmck_metrics(M/M/c/K 有限容量排队)、geometric_brownian_motion(对数增量精确抽样)
geometry sutherland_hodgman_clip
game iterated_elimination、ess_check、correlated_equilibrium_lp
timeseries kalman_smoother_linear(RTS 平滑器)
ml pca_fit / pca_transform、pr_curve、average_precision_score
multicriteria electre_ii
multiobjective moead、igd_metric、spacing_metric、knee_points
sensitivity sobol_second_order、impute_mice
spatial moran_i(空间自相关,含置换检验)

另外 forecasting.adf_test / mackinnon_crit 新增 regression="ctt"(含常数项与趋势项)。

修复:20 处真实缺陷

高危 branch_and_bound_ilp 把「松弛无界」误判为 infeasible;interior_point_lp 对偶残差符号写反导致不收敛甚至发散;bellman_ford 遇负自环时 has_negative_cycle=True 却返回 negative_cycle=None;simulated_annealing 几何降温下溢成精确 0.0 后 exp(-delta / T) 抛 ZeroDivisionError;garch11_forecast 均值回复指数 off-by-one。

中危 ml._pairwise_sq_dist 用 ‖a‖²+‖b‖²-2a·b 展开,同点自距离出现灾难性抵消而变成正数;multiobjective.crowding_distance 在退化目标上把并列点误标边界 inf;_parse_box / _parse_bounds 的一维简写 (lo, hi) 绕过全部校验((5, 3)、(nan, 5) 都当合法盒);mann_whitney_u 两个单侧尾共用同一个连续性修正量;rank_sum_ratio 文档写「并列取平均秩」而实现用竞赛名次;_spearman 声称支持并列却直接对原值做 Pearson;benchmark_functions 的最优值自测只在 dim=3 点测、容差又用相对口径(在 schwefel 处宽到 4.2e-7,而实测偏差仅 4.5e-13),断言近乎不设防且 bm_opt_dev 会被误当成上界——本版改为绝对容差 1e-9 · dim 并扫遍 dim=2..6 全部 35 个组合。

低危与其他 rank_consensus 复杂度、ml.confusion_matrix / roc_auc / decision_tree_fit、multiobjective.knee_points 的 scores 下标对齐、tsp_two_opt 文档、ant_colony_tsp 单城市路径 history 长度,以及若干文档/自测守卫口径问题。同时纠正一批「声明与实现不符」(不改变任何数值)。

heuristics 有 1 处故意不修:tabu 在既有测试权重下的最优回路长度牵动黄金键,按"黄金基线冻结"的验收规则保留,改法与影响已写在模块注释里,留待下一次大版本。

文档

  • README.md 新增**「提示词模板」板块**:T0–T8 共 9 个可直接套用的实战提示词样例(从开局赛题解读、模型选型与算法落地、数据清洗与检验,到论文写作自检与评委视角挑刺),每个都写清适用场景、可直接粘贴的正文与预期产出。
  • references/algorithm-details.md 按 __all__ 顺序补齐 38 个函数的六段式条目(数学形式 / 步骤 / 复杂度 / 参数 / 陷阱 / 怎么检验),条目里的"怎么检验"都给出可独立复算的对拍方案。
  • references/algorithm-implementations.md 分族速查表随新增函数扩写。
  • 工程修复:examples/run_algorithms.py --update-golden 补 newline="\n",Windows 上重建基线不再把整个 JSON 写成 CRLF。

验证

  • python examples/run_algorithms.py:17 个模块 / 1361 个断言键,失败 0 个模块;每个模块跑两遍结果逐位一致,黄金值比对 rtol=atol=1e-09。
  • 每个模块都有模块外的独立参照:scipy.stats(非参数检验、分布尾概率、Spearman/PPF)、sklearn(PCA、PR 曲线、树/森林)、statsmodels(Newey-West、logit 插补)、networkx(最短路、负环、拓扑序)、fractions.Fraction(精确有理参照)等;数值本身另有手算闭式解或文献常数对拍。
  • CI:validate_skill.py . --strict、check_paper.py --self-test、install_skill.py --self-test、导入白名单 AST 扫描、反向路径扫描、check_palette.py --quiet、make_figures.py --self-test、LaTeX 模板编译检查。

诚实的边界

  • 「黄金值零漂移」只证明以后的改动不会悄悄改变结果,不证明数值本身正确;正确性由那些独立断言负责。
  • 实现是教学透明版:优先可读、可手算复核与零重依赖,不与生产级数值库比性能。
  • ml 模块有 12 个公开函数(random_forest_* / gradient_boosting_* / gaussian_nb_* / lda_* / permutation_importance / class_weight_balanced / decision_tree_predict)缺少仓库外的交叉核对,仅由不变量与手算小例覆盖。
  • impute_mice 默认 max_iter=10, tol=1e-6 在多数数据上会如实返回 converged=False,这是收敛状态的诚实报告而非静默错误。
  • 博弈论部分仍有已知缺口:iterated_elimination 不做混合策略占优、ess_check 的 |B|>14 分支未端到端跑过、correlated_equilibrium_lp.n_constraints 未经独立核对、退化 Nash 均衡集不完整。

安装

对助手说一句话即可(详见 INSTALL.md):

把 https://raw.githubusercontent.com/anticipate218/math-modeling-skill/main/INSTALL.md 读一下,然后按里面的说明把 math-modeling-skill 装好。

或直接下载下方的 math-modeling-skill-v1.11.0.zip 解压到你的技能目录。四个 LaTeX 模板压缩包供手动下载使用。

完整变更:见 CHANGELOG.md。

math-modeling-skill v1.10.0

Choose a tag to compare

@anticipate218 anticipate218 released this 22 Sep 06:55

v1.10.0

一句话

新增第四套完整文档类模板:2026 华为杯「严格格式版」full/hwcup2026/。 现有的国赛 / 研赛 / 美赛三套模板一个字节都没动,full/gmcm/ 那 43.7 MiB 随包字体也原封不动——华为杯现在两套并存,按需取用。

为什么会有这一套

full/gmcm/ 是通用的华为杯模板:字号、页边距、页眉页脚都按往届通行的做法排,好处是灵活、能套各种论文结构。但每年官方会随赛题发一份 Word 附件模板(2026 年那份在「附件 3」),把封面、编号、摘要页、页边距、章节字号全部钉死。用通用模板去套,格式上总有几处对不上,而研赛对格式的判罚是机械执行的。

full/hwcup2026/ 就是把那份附件逐项复刻成 LaTeX:

  • \LoadClass[UTF8,zihao=-4,a4paper,fontset=none]{ctexart},XeLaTeX 专用(非 XeTeX 会直接 \ClassError 报错,而不是编出一份错的 PDF);
  • 页边距 top=30.02mm, bottom=18.49mm, left=22.51mm, right=22.47mm——不是整数毫米,因为照抄的是 Word 里那些 twip 换算出来的值;
  • 封面和摘要页的标题排版直接以图片形式固定。原因很直接:官方那几块是 Word 艺术字 / 特定字体的固定版式,任何「用字体凑」的做法在不同机器上都会漂,索性用官方原件截图,所见即所得;
  • 页脚是居中的阿拉伯数字页码(fancypagestyle{hwmain}),无页眉;
  • 章节标题居中、四号黑体(\titleformat{\section}{\centering\hwhei\zihao{4}});
  • 提供 hwabstract(摘要环境)与 notation(符号说明)两个环境,\makehwcover 出封面;
  • 参考文献用内联 thebibliography,不依赖 bibtex——和另外三套一致,编译就是「引擎跑三遍」。

⚠️ 这套不是官方模板。 它是本仓库作者对官方 Word 附件版式的手工复刻,官方从未发布过 LaTeX 版本。请以当年官方下发的原文件为最终依据。

华为杯两套怎么选

你的情况 用哪套
想严格贴官方附件 3 的版式,不在意模板是否可改 full/hwcup2026/
想按自己习惯调版面,或要复用往届结构 full/gmcm/
就想交一份格式不出错的 两套都能过;hwcup2026 更省心

hwcup2026 不随包字体(所以只有约 1.1 MB);gmcm 随包 5 个 .ttf(约 43.7 MiB),所以体积差两个数量级,这是预期的。

字体:两套模板的回落目标不是一回事

这是本版最容易踩的坑,CI 里现在有专门的断言守着:

模板 首选字体 回落目标 需要装的系统字体
hwcup2026 SimSun / SimHei / Times New Roman Noto Serif CJK SC / Noto Sans CJK SC / Liberation Serif fonts-noto-cjk + fonts-liberation
gmcm / cumcm 随包 .ttf / fandol fandol + TeX Gyre 无(随包或 TeX Live 自带)

hwcup2026.cls 里用 \IfFontExistsTF{SimSun} / \IfFontExistsTF{Times New Roman} 做探测:Windows 上直接命中系统字体,Linux 上回落到 Noto CJK 与 Liberation。两族字体名字完全不同,所以 CI 的 Ubuntu 作业里新增了 fonts-noto-cjk、fonts-liberation 两个包,并在 kpsewhich 预检后面加了三条 fc-list 断言——少一个家族,CI 直接红。

验证记录

本版在 Windows + MiKTeX 25.12 上对四套模板做了真编译(xelatex ×3,美赛 pdflatex ×3),并额外模拟了「无 Windows 字体」的 Linux 环境:

模板 原样编译 模拟无 Windows 字体 页数 Overfull/Underfull
hwcup2026 662 371 B 652 715 B 3 0 / 0
gmcm 395 954 B 391 121 B 8 1 / 1(既有,见下)
cumcm 452 166 B 538 968 B 12 1 / 0(既有)
mcm 279 394 B 不适用(纯英文) 11 0 / 1(既有)

hwcup2026 唯一的警告是 LaTeX Warning: You have requested release '2026/06/01' of LaTeX(TeX Live 版本比要求的新,无害)。CI 上因发行版差异,PDF 字节数与本地不同属正常,判据是页数与体积容差。

本版资产

文件 大小(字节) SHA-256
math-modeling-skill-v1.10.0.zip 31 246 859 77268b2da2d23c4fec3eac81a76b6bfb13acae6cf5497096fb339fe29effccf8
hwcup2026-template.zip 1 145 850 9cc250eec302ff6a411badeb23398e39f3c91e7a2b99946ab52ed52052d86b0f
gmcm-template.zip 25 688 648 209f94c6b0625081b29d1ce5aaeef63f42b1340363832fddddba37e52ff0d4c7
cumcm-template.zip 841 300 752e03d4e2f804e1e885223b5267b3bc128db5181f5c0b14d813040a1e1382d5
mcm-template.zip 602 952 fa568cf1ca53426e02f8d3d4c0ace29d7c19629ce207d14a96bc814e43aea784

源码层面的差异只有 mcm/README.md 一处(把「唯一有自由许可的模板」这个说法写准)。gmcm-template.zip 与 cumcm-template.zip 的内容与 v1.9.1 完全一致,但 sha256 仍然不同——--mtime 跟着提交时间走,这是刻意的(保证出包可重现)。

SHA-256 同样不写进仓库里的任何追踪文件:写了就成自引用,提交一变哈希即失效。只放在本页。

⚠️ hwcup2026-template.zip 里的 5 张 assets/*.png 是官方附件 3 版式的渲染件,版权归竞赛主办方所有,不在本仓库 MIT 授权范围内;和研赛随包的那 5 个商用 .ttf 是同一种情况。

四套模板的溯源与授权(只陈述来源)

模板 来源 许可证情况
华为杯 2026 hwcup2026 本仓库作者自己构建:对 2026 年官方附件 3 Word 模板的严格复刻(官方未发布过 LaTeX 版) 代码部分随本仓库 MIT;封面/摘要的 5 张 PNG 为官方版式渲染件,版权归主办方,不在 MIT 范围内
华为杯(研赛)gmcm 本仓库作者自己构建(参考谱系 springli07/GMCM_LaTeX_overleaf → zhanwen/MathModel) 两处参考上游均未附 LICENSE;随包 5 个 .ttf 为商用字体,不在 MIT 范围内
国赛 cumcm latexstudio/CUMCMThesis @ 38d1f21,文档类 cumcmthesis.cls v2.9 上游无 LICENSE,未收录 CTAN
美赛 mcm latexstudio-org/mcmthesis @ 8ac05e2,文档类 mcmthesis.cls v6.3.3 LPPL 1.3c or later

美赛是 LPPL,因此随包保留了 mcmthesis.dtx / mcmthesis.ins(LPPL 要求分发以「原始源文件同属一份分发」为前提)。美赛模板本身未作任何改动。

校验

项目 结果
CI(本版提交) check + latex 两个作业全绿
真编译(check_latex_full.py --require) 7/7 通过(四套模板 × 原样/模拟)
ZIP 条目 vs git cat-file blob 技能包 134/134 相同,CRLF 转换 0 个
出包可重现性 连编两次字节完全相同
check_latex_full.py --self-test 29/29 通过(新增 3 条:模板表覆盖 full/ 全部目录、模拟字体族分两类的断言、\IfFontExistsTF{SimSun.ttf} 不被误伤)
validate_skill.py . --strict 0 错误 / 0 警告
install_skill.py --self-test / --from-zip / --into 25/25 / 装上并 validate_skill --strict 通过 / 技能根自动补层正确
check_paper / check_latex / run_algorithms 自检 3 套骨架 FAIL=0 / 26/26 / 17 模块 875 键 0 失败

已知的无害警告(沿用,未修)

  • gmcmthesis.cls:\ClassError{mcmthesis} 类名写错(不影响编译);\newif\if@gmcm@preface 缺 \fi。
  • gmcm 1 个 Overfull + 1 个 Underfull hbox;cumcm 1 个 Overfull hbox + multiply-defined labels;mcm 1 个 Underfull hbox。均为既有上游问题。

要更新吗

  • 只要新模板:直接下 hwcup2026-template.zip,解压 cd hwcup2026 && xelatex main.tex(跑三遍)。
  • 只想刷新技能包:下 math-modeling-skill-v1.10.0.zip,或 git pull 后重跑 python scripts/install_skill.py --target auto --force。
  • 已经在用 full/gmcm/ 的:不用换。 两套并存,gmcm 没动。

完整改动见 CHANGELOG.md;
四套模板怎么选、怎么在 Overleaf 上跑、Ubuntu 依赖怎么装,见 assets/latex/full/README.md。

math-modeling-skill v1.9.1

Choose a tag to compare

@anticipate218 anticipate218 released this 21 Sep 19:23

v1.9.1

一句话

纯补丁版:模板源码一个字节都没改。 修掉 v1.9.0 发布后才暴露的两个问题——CI 在 Ubuntu 上编译不过(两轮才修完),以及 v1.9.0 打出的 ZIP 有 97/125 个文本条目被换行符转换污染。已经在用 1.9.0 的人不更新也不影响使用。

为什么会有这个版本

v1.9.0 的 Release 发出去之后,CI 才在 Ubuntu 上跑到 latex 任务,红了。查下来两批原因,一批比一批深:

轮次 报错 真因 修法
第一轮 ! LaTeX Error: File 'ulem.sty' not found. / 'berasans.sty' not found. Ubuntu 的 TeX Live 是按 Debian 包切分的,texlive-latex-extra 并不含这两个文件 补 texlive-plain-generic、texlive-fonts-extra、fonts-texgyre,并加 kpsewhich 预检
第二轮 ! Font TS1/ntxtlf/m/n/12=ts1-qtmr at 12.0pt not loadable: Metric (TFM) file not found (只有美赛 pdflatex 挂) newtxtext 把 TS1 编码映射到 TeX Gyre Termes 的度量(TFM)文件,而 fonts-texgyre 装的是 OTF 字体,不含 TFM 补 tex-gyre

第二轮这个坑值得单说:fonts-texgyre 和 tex-gyre 是两个毫不相干的 Debian 包。前者给 /usr/share/fonts/ 下的 .otf;后者给 /usr/share/texmf/fonts/tfm/public/tex-gyre/ 下的 .tfm。装了前者最容易让人以为字体齐了,实际 pdflatex 到 ts1-qtmr 就断。

这五条包名不是猜的,是反查出来的:把 Ubuntu noble 的 dists/noble/Contents-amd64.gz(51 301 092 B)下下来,按文件名反查归属包:

缺的文件 归属包 备注
ulem.sty texlive-plain-generic TDS 路径在 tex/generic/,所以不在 latex-extra
berasans.sty texlive-fonts-extra
newtxtext.sty texlive-fonts-extra
texgyretermes-regular.otf fonts-texgyre OTF
ts1-qtmr.tfm tex-gyre TFM,全索引仅 1 处命中,确认无 texlive-* 包携带
lmodern.sty lmodern

CI 的 <!-- 漏了就红 --> 注释里现在逐条写着这五条映射,kpsewhich 预检清单也扩到 6 个文件名。再少一个,CI 立刻红给你看,不会再等到用户那边才发现。

第二个修复:ZIP 是「从 git blob 出的包」

v1.9.0 的 ZIP 里,125 个跟踪文件中有 97 个被写成了 CRLF——本机 core.autocrlf=true,git archive 老老实实按这个设置做了换行转换,而 blob 里存的是 LF。

这不是"看起来一样"的问题:validate_skill.py 之类的脚本、以及任何做哈希比对的安装链路都会对不上。

本版出包时显式关掉:

git -c core.autocrlf=false -c core.eol=lf archive --format=zip --prefix=<name>/ --mtime=<HEAD 提交时间> HEAD:assets/latex/full/<name>

顺手还发现并消掉了另一个不确定性:git archive --format=zip 不传 --mtime 时会用墙上时钟给每个条目盖时间戳(实测两次构建相隔 3 秒,ZIP 里有 72 个字节不同)。现在时间戳固定成 HEAD 的提交时间,连编两次字节完全相同。

出包脚本现在会断言三件事,任一不成立就直接失败:

  1. ZIP 条目清单 == git ls-tree -r HEAD:<dir>;
  2. 每一个条目都与 git cat-file 取出的 blob 逐字节相同;
  3. 连编两次结果字节一致。

顺带解释一个会让人困惑的现象:v1.9.1 的三个模板 ZIP 和 v1.9.0 的 sha256 必然不同,哪怕模板源码没改——因为 --mtime 跟着提交时间走,而且 v1.9.0 那份本来就被换行符污染了。源码层面的差异只有 gmcm/README.md 和 cumcm/README.md 两个文件,且都是这次的文档修正。

也因此,SHA-256 故意不写进仓库里的任何文件:写了就等于自己引用自己,提交一变哈希就失效。校验值只放在本 Release 页上。

还改了两处「说得太满」的说法

  • 原文写编译产物 PDF "与样张逐字节相同"。复核后:gmcm / mcm 确实逐字节相同;cumcm 前 444 862 字节相同,末尾的元数据对象流差 1 字节(/Length 3866 vs 3867,XMP/Info 元数据)。已在文档里写明。
  • README 里的 Release 链接原本钉死版本号,改成 latest,不然每次发版都得改一次文档。

本版资产

文件 大小(字节) SHA-256
math-modeling-skill-v1.9.1.zip 30 090 644 707398b78e6f48a38edce4dca3c10d93ffd1bf558e2697ec3395136e78b7f44a
gmcm-template.zip 25 688 648 11d719a54bc3f7f18107ff7d05d6a1fd15f0ed20ad05e1b7d7dd3c9f19f32156
cumcm-template.zip 841 300 e2586710efd1901a7673e559f80a9d30600cd92a3206a714c51ef94ed72eff63
mcm-template.zip 602 926 cf1221532d0ea4ed550045dd2a2f2643a64cc740d09c6ac12142952f63db1097

三个模板 ZIP 的哈希与 v1.9.0 那份不同是预期的(原因见上)。gmcm-template.zip 之所以大,是因为里面带了 5 个 .ttf(约 43.7 MiB 未压缩)。

三套模板的溯源与授权(只陈述来源)

模板 来源 许可证情况
华为杯(研赛)gmcm 本仓库作者自己构建(参考谱系 springli07/GMCM_LaTeX_overleaf → zhanwen/MathModel) 两处参考上游均未附 LICENSE
国赛 cumcm latexstudio/CUMCMThesis @ 38d1f21,文档类 cumcmthesis.cls v2.9 上游无 LICENSE,未收录 CTAN
美赛 mcm latexstudio-org/mcmthesis @ 8ac05e2,文档类 mcmthesis.cls v6.3.3 LPPL 1.3c or later

美赛是 LPPL,因此随包保留了 mcmthesis.dtx / mcmthesis.ins(LPPL 要求分发以"原始源文件同属一份分发"为前提)。美赛模板本身未作任何改动。

研赛随包的 5 个 .ttf(SimSun / SimHei / KaiTi / LiSu / STXinwei)是中易 / 华文的商用字体,不在本仓库 MIT 授权范围内,仅为字形与 Word 一致而附带;删掉即可,\IfFontExistsTF 会回落到 fandol 继续编过。

校验

项目 结果
CI(本版提交) check + latex 两个作业全绿
ZIP 条目 vs git cat-file blob 技能包 125/125 相同,CRLF 转换 0 个
出包可重现性 连编两次字节完全相同
install_skill.py --self-test / --from-zip / --into 25/25 / 装上并 validate_skill --strict 通过
validate_skill.py . --strict 0 错误 / 0 警告
check_latex_full.py --require(真编译) 5/5 通过
check_paper / check_latex / run_algorithms 自检 26/26 / 26/26 / 17 模块 875 键 0 失败

要更新吗

模板内容完全没变,只动了文档、CI 配置和出包方式。

  • 只想拿模板:不用更新,直接下 gmcm-template.zip / cumcm-template.zip / mcm-template.zip。
  • 想刷新技能包:下 math-modeling-skill-v1.9.1.zip,或 git pull 后重跑 python scripts/install_skill.py --target auto --force。

完整改动见 CHANGELOG.md;
模板怎么选、怎么在 Overleaf 上跑见 assets/latex/full/README.md。

math-modeling-skill v1.9.0

Choose a tag to compare

@anticipate218 anticipate218 released this 21 Sep 18:31

一句话

把三套竞赛的原版文档类模板整套收进技能包,改掉两处「没装 Windows 字体就编不过」的字体加载——现在华为杯(研赛)/ 国赛 / 美赛的官方 LaTeX 模板在 Overleaf 和 Linux 上也能直接编,不用再自己配字体。三套模板的 ZIP 随本 Release 一起发布。

装什么,用什么

技能包现在是两层,用途不同:

层 位置 干什么用
轻量自包含版 assets/latex/{cumcm,yjs,mcm}/main.tex 自写的入口文件,用来跑 check_latex.py 的合规自检(页数、AI 声明、盲审匿名)
完整文档类版(新) assets/latex/full/{gmcm,cumcm,mcm}/ 原版 *.cls 全套,直接拿来写论文、直接交

完整版三套:

赛事 目录 主文件 引擎
华为杯(研赛) full/gmcm/ MathModel.tex XeLaTeX
国赛(CUMCM) full/cumcm/ example.tex XeLaTeX
美赛(MCM/ICM) full/mcm/ mcmthesis-demo.tex pdfLaTeX

注意:三套都是「引擎跑 3 遍」,不需要 bibtex。 参考文献是内联 thebibliography。

为什么要改上游的字体加载

模板原样在「Windows + Word 字体齐备」的机器上没问题,换到 Overleaf / Linux / macOS 会直接失败:

  • gmcmthesis.cls(研赛):上游写 \ifx\lishu\undefined \setCJKfamilyfont{zhli}{LiSu.ttf} ... \fi。可 ctex 宏包早就定义过 \lishu,这个条件永远不成立,随包的 LiSu.ttf 从未被注册——编译到封面「摘 要」那一行必然:

    ! Package fontspec Error: The font "LiSu" cannot be found
    

    已改成「先 \providecommand* 兜底、再 \renewcommand* 绑到随包字体」,\xinwei 同样处理。

  • gmcmthesis.cls / cumcmthesis.cls:\setmainfont{Times New Roman} 这类调用是无条件的,缺字体就报错。改成 \IfFontExistsTF{...}:有就用,没有回落到 TeX Gyre Termes / Heros / Cursor——Times / Arial / Courier 的度量兼容开源克隆,随 TeX Live 与 MiKTeX 分发,任何平台都有。

除此之外没有别的改动。 example.tex、mcmthesis-demo.tex、mcmthesis.dtx、cumcm2026.sty、figures/* 都与上游逐字节一致;美赛模板完全未改。

真机编译结果(Windows + MiKTeX 25.12,引擎各跑 3 遍)

模板 引擎 原样(随包字体 / 系统 Windows 字体) 模拟无 Windows 字体
gmcm xelatex 8 页 / 395 954 B 8 页 / 391 121 B
cumcm xelatex 12 页 / 452 166 B 12 页 / 538 970 B
mcm pdflatex 11 页 / 279 394 B 不适用(不含中文)

5/5 通过:每次退出码 0、0 条硬错误、0 个缺字形、0 处未解析引用。两列页数完全一致——换字体只改字形与嵌入体积,不改分页。

「模拟无 Windows 字体」不是碰运气:脚本把临时副本的 ctex 字体集钉成 fandol、把探测的字体名换成一定不存在的名字、并删掉随包 .ttf,所以在任何平台上这一遍走的都是真实的回落分支。顺带一个佐证:cumcm 两列体积差 86 804 B,正是 TeX Gyre 替掉 Times New Roman / Arial 后嵌入字体变大的量。

字体:研赛随包带 5 个 .ttf(约 44 MB)

full/gmcm/ 带 SimSun.ttf / SimHei.ttf / KaiTi.ttf / LiSu.ttf / STXinwei.ttf,目的是让字形和 Word 里看到的完全一致。

  • 可以删掉,删了照样编得过——\IfFontExistsTF 会检测到文件不在,自动回落到 ctex 字体集(Windows 用系统字体,Linux / Overleaf 用自由的 fandol),只是字形变了。
  • ⚠️ 但千万别把它们挪进 fonts/ 子目录。文档类是按裸文件名引用的,挪走后 fontspec 只警告不报错,整篇中文被悄悄排成西文字体(实测丢 1503 个字形),而编译照样退出码 0、PDF 照样 8 页——极其隐蔽。留在原地,或者直接删掉。

授权提示:这 5 个是中易 / 华文的商用字体,不是自由字体。随包携带只为让你零配置编译。要再分发或商用请自行确认授权,或删掉改用 fandol。

三套模板的溯源与授权

模板 上游 许可证
gmcm 本仓库作者自制(参考谱系 springli07/GMCM_LaTeX_overleaf → zhanwen/MathModel) 上游均未附 LICENSE
cumcm latexstudio/CUMCMThesis @ 38d1f21 上游无 LICENSE、未收录 CTAN
mcm latexstudio-org/mcmthesis @ 8ac05e2 LPPL 1.3c or later

美赛是 LPPL,所以随包保留了 mcmthesis.dtx(LPPL 要求分发以「原始源文件属于同一分发」为前提);要定制请另存为别的文件名。逐套详情见 assets/latex/full/THIRD-PARTY.md。

新增 scripts/check_latex_full.py(544 行,仅标准库)

python scripts/check_latex_full.py                 # 编全部:模板 ×(原样 + 无 Windows 字体)
python scripts/check_latex_full.py --only gmcm     # 只编研赛
python scripts/check_latex_full.py --no-simulate   # 只按原样编
python scripts/check_latex_full.py --keep          # 保留临时目录,方便翻 .log / .pdf
python scripts/check_latex_full.py --self-test     # 不需要装 TeX,只测改写逻辑

它把整个模板目录拷到系统临时目录再编译(不在仓库内产生 .aux/.log/.pdf),并先删掉预编译的样张 PDF——否则编译失败时旧 PDF 还在,体检就被骗过去了。然后核对硬错误、未解析引用、Font "…" cannot be found、页数下限,以及 cumcm / mcm 的「AI 声明 vs 参考文献」顺序合规。--require = 没装引擎就报错退出,不允许静默跳过。

CI 的 latex 任务加了两步:先跑 --self-test(不依赖 TeX),装好 TeX Live 后再跑 --require。Ubuntu 上没有 Windows 字体,那一遍天然就是回落路径。

修了一个会被这三个新 ZIP 触发的坑(install_skill.py,1089 → 1164 行)

原来 --download 取 releases/latest 里的第一个 .zip。这个 Release 要挂 gmcm-template.zip / cumcm-template.zip / mcm-template.zip,谁排在前面谁就会劫持 --download——用户想装技能,结果装进来一个模板。

新增 pick_release_asset():只认文件名以 math-modeling-skill 开头的 ZIP;一个都不匹配时列出实际资产名并提示改用 --from-zip,绝不瞎猜。自检 21 → 25 项。

换句话说:Release 页上那几个 *-template.zip 是给人手动下载的,--download 不会碰它们。

校验

项目 结果
validate_skill.py . --strict 0 错误 / 0 警告
check_latex_full.py --require 5/5 通过(真编译,含无 Windows 字体回落路径)
check_latex_full.py --self-test 26/26 通过(不需要 TeX)
install_skill.py --self-test 25/25 通过
check_latex.py --self-test / download_templates.py --self-test 26/26 / 26/26
check_paper.py --self-test / check_palette.py --quiet 全过 / 通过
run_algorithms.py 17 模块 / 875 断言键 / 0 失败
ZIP 条目集合 vs git 跟踪集合 0 缺 0 多;.ttf 与 git blob 逐字节一致
CI(check + latex) 全绿

下载

  • 技能包:math-modeling-skill-v1.9.0.zip(下面的 Assets 里,用它配 --from-zip)
  • 三套模板单独下载:gmcm-template.zip / cumcm-template.zip / mcm-template.zip
  • 一句话安装见 README;面向助手的安装流程见 INSTALL.md
  • 模板怎么选、怎么用、怎么在 Overleaf 上跑:assets/latex/full/README.md

完整改动见 CHANGELOG.md。

math-modeling-skill v1.8.3

Choose a tag to compare

@anticipate218 anticipate218 released this 19 Sep 10:11

一句话

--download(安装脚本里唯一联网的动作)以前是一次性请求,遇到 GitHub 的偶发 TLS 断流就整条命令失败;现在它会自动退避重试 4 次,并把"连上了但传到一半断掉"也算进去——因为那才是实测里最常见的那种失败。

怎么发现的

不是猜的。发布 v1.8.2 之后我用 --download 做端到端复验,现场撞上:

错误:下载 math-modeling-skill-v1.8.2.zip 失败:
      <urlopen error [SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol>

留下一个空目录。而报错给的出路是"改用 --from-zip"——可用户选 --download,恰恰是因为手上没有包。

修了什么

  • --download 全流程重试:查 releases/latest 与下载 ZIP 两步都带指数退避(4 次,退避 1.5s / 3s / 6s),重试时打印 …第 2/4 次尝试(1.5s 后重试,上次失败:…),让你看得见它在自救。
  • 重试的是整个下载动作(连接 + 读响应体 + 写文件),不只是建立连接;写盘用覆盖模式,不会把两次的部分内容拼成坏 ZIP。另有 0 字节兜底检查。
  • 失败信息给两条出路:① 这是网络问题,原样重跑一次通常就好;② 到 Releases 页手工下载 ZIP,再用 --from-zip。

真机验证

项目 结果
修复前 [SSL: UNEXPECTED_EOF_WHILE_READING],目标目录为空
修复后 同一条命令下载 2,915,975 字节(与 v1.8.2 资产字节数一致),装完 validate_skill.py --strict 通过,读出的 metadata.version 是 1.8.2

顺带

  • --self-test 由 18 项扩到 21 项:新增「联网动作重试后成功」(注入假 opener/假 sleeper,断言退避时长正是 1.5s / 3s)、「一直失败时报可执行的错」、「重试次数必须为正」——全程不联网、不碰真实技能目录。
  • --from-zip 示例里的版本号不再写死(v1.8.0 → vX.Y.Z),免得每次发版都变成过期示例。

校验

项目 结果
validate_skill.py --strict 0 错误 / 0 警告
install_skill.py --self-test 21/21 通过
check_paper.py --self-test / check_latex.py --self-test 全过 / 26 项全过
run_algorithms.py 17 模块 / 875 断言键 / 0 失败
check_palette.py --quiet / make_figures.py --self-test 全部达标 / 退出码 0
CI(check + latex) 全绿
ZIP 条目集合 vs git 跟踪集合 84 文件,0 缺 0 多

配套文档:一句话安装说明见 README;面向助手的安装流程见 INSTALL.md。

完整改动见 CHANGELOG.md。

math-modeling-skill v1.8.2

Choose a tag to compare

@anticipate218 anticipate218 released this 19 Sep 10:01

一句话

没有任何运行时代码变化——scripts/、references/、examples/、templates/ 与 v1.8.1 逐字节相同(scripts/install_skill.py 的 SHA-256 两版一致)。本版只是把 main、标签、Release 资产重新对齐到一个 CI 两个任务全绿的提交上。

为什么会有这一版

v1.8.1 的 Release 资产是在提交 3426e28 上打的,而那次推送的 CI 是红的——红的原因不在代码、也不在文档里的路径,而是我在 CHANGELOG 的验证记录里逐字抄了「Windows 风格路径」检查用的那条正则:判据文本本身命中了判据(受管目录名后面紧跟一个反斜杠),文档把自己举报了。修法记录在 1.8.1 的 CHANGELOG 末尾「一条自曝」里。

f5e8468 改掉措辞、并在 ci.yml 里加了注释提醒别再逐字引用;CI 随即全绿。本版在它之上只动版本号与 CHANGELOG。

没有为了让 CI 变绿而放宽检查:判据、扫描范围(全部 *.md)、失败行为全部原样。

已经装了 1.8.1?不用重装

技能内容与 1.8.2 完全一致。想严格对齐 Release 包的话,覆盖一次即可:

python scripts/install_skill.py --force --target auto

本版包含的安装器行为(与 1.8.1 相同)

  • --into 给技能根(如 ~/.agents/skills)时自动补一层 math-modeling-skill,不再把技能平铺进技能根;
  • --into 指向别人的技能目录时直接拒绝,一个字节都不写;
  • 自校验失败时给出最常见原因(技能目录名不是 math-modeling-skill);
  • SKILL.md 带 UTF-8 BOM 时也能正确识别,--force 不再莫名失效。

校验

项目 结果
validate_skill.py --strict 0 错误 / 0 警告
install_skill.py --self-test 18/18 通过
check_paper.py --self-test / check_latex.py --self-test 全过 / 26 项全过
run_algorithms.py 17 模块 / 875 断言键 / 0 失败
check_palette.py --quiet / make_figures.py --self-test 全部达标 / 退出码 0
CI(check + latex) 全绿
ZIP 条目集合 vs git 跟踪集合 84 文件,0 缺 0 多

配套文档:一句话安装说明见 README;面向助手的安装流程见 INSTALL.md。

完整改动见 CHANGELOG.md。

math-modeling-skill v1.8.1

Choose a tag to compare

@anticipate218 anticipate218 released this 19 Sep 09:50

math-modeling-skill v1.8.1

一句话就能装。 把这句话发给你正在用的 AI 助手,它会自己下载、找到技能目录、装好,再向你汇报:

请阅读并按 https://raw.githubusercontent.com/anticipate218/math-modeling-skill/main/INSTALL.md 的说明,把 math-modeling-skill 这个技能安装到我当前使用的助手环境里;装完告诉我装到了哪个路径、是哪个版本、以及怎么开始用。

English:

Read and follow https://raw.githubusercontent.com/anticipate218/math-modeling-skill/main/INSTALL.md to install the math-modeling-skill agent skill into the environment I'm using. When done, tell me the install path, the version, and how to start using it.

不想用助手也行——下载本页的 math-modeling-skill-v1.8.1.zip,解压后把里面的 math-modeling-skill 整个文件夹放进你的技能目录(目录名不要改)。各宿主技能目录与更多装法见 README 的「下载与安装」。


本版修了什么

v1.8.0 上线后我实机复验安装器,踩到一个自己挖的坑:

--into 给"技能根"时会把技能平铺进去。 旧行为是"原样使用、不追加技能名",而用户(或助手)很自然会写成 --into ~/.agents/skills——于是 SKILL.md、references/、scripts/ 等二十多个条目被直接倒进技能根。宿主按 <技能根>/<name>/SKILL.md 扫描,结果是扫不到;技能根还被污染。更糟的是随后那条自校验只说"技能可能不完整",把真实原因(目录名不是 math-modeling-skill)藏住了。

现在:

  • --into 两种写法都对。 给技能根 → 自动补一层 math-modeling-skill;给技能目录本身 → 原样使用。动手前会把真实安装路径打印出来。
  • 指向别人的技能目录时直接拒绝。 那个目录里若已有 SKILL.md 且 name 不是本技能,复制前报错并给出正确写法,一个字节都不写。
  • 自校验失败说人话。 补上最常见的原因:目录名不是 math-modeling-skill。
  • 顺手修掉一个会让 --force 莫名失效的隐患:UTF-8 BOM。 Windows 记事本/部分 IDE 会给文件加 BOM,带着 BOM 时 frontmatter 整块读不出来,安装器会把你自己的旧安装误判成"别人的技能",于是更新时被安全闸门拒之门外。现在解析前先剥 BOM。

变更清单

文件 变化
scripts/install_skill.py 860 → 962 行;新增 resolve_into();read_frontmatter() 增加 BOM 容错;提示语与 --help 同步
--self-test 13 → 18 项(新增 --into 四种情形 + BOM 识别)
INSTALL.md 第 2C 节改为"两种写法都对",新增常见问题「校验报 name…必须与技能目录名…一致」
README.md 第 3 节补 --into 说明与示例,第 7 节自检期望值改 18/18,「质量保障」表同步

本版验证记录

项目 方式 结果
安装器固件测试 install_skill.py --self-test 18/18 通过(不联网、不碰真实技能目录)
--into 给技能根 指向一个空目录 目标自动变成 <空目录>/math-modeling-skill,校验通过,退出码 0
覆盖约定 同一位置再跑一次 / 加 --force 第二次拒绝并退出码 1;--force 后覆盖成功 + 校验通过
--into 指向别人的技能 放入 name: other-skill 的 SKILL.md 复制前报错、退出码 1,该目录内容未被改动
BOM 容错(端到端) 给已安装副本的 SKILL.md 加 BOM 再 --force 正确识别为本技能旧安装并覆盖成功(修复前会被拒绝)
技能结构 validate_skill.py . --strict 0 个错误,0 个警告
算法回归 examples/run_algorithms.py 17 个模块 / 875 个断言键,失败 0
随包自检 check_paper.py / download_templates.py / check_latex.py / check_palette.py / make_figures.py 全部通过
发布包自检 用本页 ZIP 走一遍 --from-zip 安装 安装成功、结构校验通过、无 .git/
CI GitHub Actions(check + LaTeX 真编译) 两个作业全绿

怎么升级

# 从仓库升级(推荐)
cd math-modeling-skill && git pull
python scripts/install_skill.py --target auto --force

# 或者用本页的 ZIP
python scripts/install_skill.py --from-zip math-modeling-skill-v1.8.1.zip --target auto --force

--force 只会覆盖本技能的旧安装(目标目录里必须有 name: math-modeling-skill 的 SKILL.md),别的目录它一律不动。

已经装了 v1.8.0 的话建议升到本版:v1.8.0 的安装器里还是旧行为。用 v1.8.0 安装器时请把 --into 写成 <技能根>/math-modeling-skill。


技能遵循 Agent Skills 开放标准:目录名必须与 SKILL.md 里的 name 一致;纯文件、无后台进程、不写注册表。卸载就是删掉那个目录。

math-modeling-skill v1.8.0

Choose a tag to compare

@anticipate218 anticipate218 released this 19 Sep 09:40

这一版只做一件事:把「怎么装」从"用户读说明书、照着敲命令"改成"用户对助手说一句话,助手自己装"。

前几版把内容、算法、模板都补齐了,但安装这一步一直假定用户会读 README、会判断自己的技能根目录在哪、会敲对路径——而这恰恰是最容易劝退、也最容易装错的一环。


一句话安装(本版的主入口)

把下面这句话连同链接一起发给你正在用的 AI 助手,它会自己下载、找到技能目录、装好、再向你汇报:

请阅读并按 https://raw.githubusercontent.com/anticipate218/math-modeling-skill/main/INSTALL.md 的说明,把 math-modeling-skill 这个技能安装到我当前使用的助手环境里;装完告诉我装到了哪个路径、是哪个版本、以及怎么开始用。

English:

Read and follow https://raw.githubusercontent.com/anticipate218/math-modeling-skill/main/INSTALL.md to install the math-modeling-skill agent skill into the environment I'm using. When done, tell me the install path, the version, and how to start using it.

那条 raw 链接现在是 CI 的一部分:INSTALL.md 必须存在、README 里这行链接必须逐字符正确、SKILL.md 必须提到它——链接写错或文件没推上去就会在 CI 红掉。本版发布时实测该链接返回 HTTP 200 / 10,158 字节。


新增

INSTALL.md(277 行)——写给 AI 助手看,不是写给用户看

  • 第 1 步:拿到技能包,按"有 shell / 用户已下载 ZIP / 只能读网页"分三种情况。第三种明确不要硬装,改为把话术交给用户。
  • 第 2 步:确定技能根目录,给三条路——跑脚本探测(推荐)/ 自己找(查宿主配置、看已有技能的父目录、直接问用户)/ --into 精确指定,并列一张只包含可核实路径的宿主-技能目录对照表。
  • 第 3 步:安装,脚本安装与纯手工复制(含"记得删 .git/")各一版,Windows/NT 分开。
  • 第 4 步:校验,三条独立命令与期望输出,SKILL.md 只有一层、目录名与 name 必须一致。
  • 第 5 步:汇报,规定必须包含五项(装到哪个绝对路径、哪个版本、校验结果、怎么开始用、目录名不要改)。
  • 另有「不要做」清单(不要改目录名、不要覆盖别人的技能、不要装进 references/ 这类子目录、不要为了"验证装好没"去跑算法或下载模板、不要编造宿主路径、不要 git clone 进技能目录),以及 Troubleshooting / 更新 / 卸载。

scripts/install_skill.py(860 行,纯标准库,非交互)

python scripts/install_skill.py --list-targets   # 每个候选根的绝对路径 / 是否已存在 / 已装版本
python scripts/install_skill.py --target auto    # 自动挑位置
python scripts/install_skill.py --dry-run        # 只看会做什么,不动磁盘
python scripts/install_skill.py --from-zip math-modeling-skill-v1.8.0.zip
python scripts/install_skill.py --download       # 拉最新 Release 的 ZIP 再装(唯一联网的动作)
python scripts/install_skill.py --self-test      # 13 项固件测试,不联网、不碰真实技能目录

--target auto 按 项目级 DSH → 项目级 Agent Skills → 用户级 DSH → 用户级 Agent Skills 取第一个已存在的技能根;都不存在时落到 ~/.agents/skills。

三条安全约定(都有固件测试兜住):

  1. 默认拒绝覆盖已存在的技能目录;
  2. --force 只肯删"确实是本技能"的目录(目标里必须有 name: math-modeling-skill 的 SKILL.md)——这道闸门是防 --into 手滑指到家目录的;
  3. 复制时丢掉 .git/ 与各种缓存,装完自动跑包内的 validate_skill.py --strict,不通过就报错退出。

变更

  • README.md(471 → 575 行):「快速开始」第 0 步改为先给中英两版一句话提示词,再给 git clone 与安装器两条备选;「下载与安装」由 5 小节重排为 9 小节,新增「最省事:一句话让你的 AI 助手自己装」「装到哪里(各宿主的技能目录)」「用自带安装器装(推荐)」「怎么更新、怎么卸载」「装完没生效?按这个顺序查」。「质量保障」表加一行「安装器」,结构树补 INSTALL.md 与 scripts/install_skill.py。
  • 改掉一条不准确的说明:旧 README 的排查清单写着"③ 宿主是否需要重启或重新扫描"。DSH 会持续监视技能根目录,新增/改名/删除技能在下一个技能目录快照就生效,不需要重启。已按此改写,并把排查扩成单列的一节。
  • 不猜路径:README 只列能核实的六个位置(DSH 项目级/用户级、Agent Skills 通用约定的项目级/用户级、Claude Code 项目级/用户级)。Codex、Cursor、Gemini CLI、OpenCode 等的技能目录各不相同,本仓库故意不写死猜测值——猜错的代价是"装成功了但永远不会被扫描",比装不上更难查。
  • SKILL.md 升 1.8.0,索引加一行"用户要装/更新/换宿主重装时读 INSTALL.md";compatibility 把 install_skill.py 并入"仅用标准库"的脚本清单。
  • CITATION.cff 同步 1.8.0。
  • CI 新增两步:install_skill.py --self-test;以及"安装入口文档存在且被 README 引用"。

本版验证记录

项目 方式 结果
安装器固件测试 install_skill.py --self-test 13/13 通过
真装一遍 --into <临时目录> / 再装一次 / 加 --force 首次"安装完成"+ 校验通过;第二次拒绝、退出码 1;--force 后"覆盖完成"+ 校验通过;装出 97 个条目、无 .git/
从发布包装 --from-zip 自动剥掉 math-modeling-skill/ 前缀,装完校验通过
联网取包 --download 查到最新 Release 并下载成功(2,887,266 字节,与附件记录一致)
技能结构 validate_skill.py . --strict 0 个错误,0 个警告(30 个文件引用)
全量算法回归 examples/run_algorithms.py 17 个模块 / 875 个断言键 / 失败 0 个模块
其余随包自检 check_paper / download_templates / check_latex / check_palette / make_figures 全部通过
文档路径风格 扫全部 23 个 *.md 找反斜杠路径 命中 0

本版的 ZIP 附件是从提交 bdd272e 用 git archive 打出来的,并且把解压后的副本完整跑了一遍:结构校验、安装器固件测试、模板清单、论文自检、LaTeX 检查逻辑、全量算法回归,再从那个 ZIP 用 --from-zip 真装一次。附件与仓库内容一一对应(84 个文件,缺 0 多 0)。


怎么升级

git pull
python scripts/install_skill.py --target auto --force

或者下载本页的 ZIP 附件后:

python scripts/install_skill.py --from-zip math-modeling-skill-v1.8.0.zip --target auto --force

--force 只会覆盖本技能的旧安装,别的目录一律不动。

math-modeling-skill v1.7.0

Choose a tag to compare

@anticipate218 anticipate218 released this 19 Sep 05:18

math-modeling-skill v1.7.0

数学建模竞赛全流程技能包 · 算法补全 + 创新手册 + 模板下载 + 安装体验

本版回应四件事:README 里要能查到"LaTeX 模板怎么下载"、算法要做到"每个类别的每个算法都有详细实现"、要讲清"怎么创新、哪些参数可以动"、以及下载之后怎么把这个技能跑起来要顺。前两件是内容缺口(仓库里有模板但不讲怎么拿;算法只覆盖 11 个模块、部分函数只有名字没有细节),第三件是知识缺口,第四件是体验缺口。


这一版做了什么

项 v1.6.0 v1.7.0
算法模块 11 17
公开名称(函数 + 常量) 97 224(函数 222 + 常量 2)
黄金值断言键 324 875
逐算法详解文档 无 references/algorithm-details.md(2332 行,223 个条目)
参数创新手册 无 references/innovation-playbook.md(371 行,17 族)
LaTeX 模板获取 手动复制文件 scripts/download_templates.py 一条命令 + 可选 zip
README 安装指引 散在各处 「下载与安装」专章(5 小节)

一、怎么把它装起来(本版重点优化过)

技能遵循 Agent Skills 开放标准:一个目录 + 一个 SKILL.md,目录名必须等于 frontmatter 里的 name(本仓库已满足)。所以安装动作就是"把目录放对地方",没有构建、没有安装器、不联网。

方式 A:下载本页的 Release ZIP(推荐给不想装 git 的人)

本 Release 附带 math-modeling-skill-v1.7.0.zip(2,887,266 字节 ≈ 2.8 MB,含完整技能包 + 三套 LaTeX 模板)。

  1. 下载并解压,解压出来的顶层目录就叫 math-modeling-skill/——不用改名,这正是宿主需要的目录名。

  2. 把整个 math-modeling-skill/ 丢进你的技能根目录(见下表)。

  3. 核验完整性:解压后在该目录里跑

    python scripts/validate_skill.py . --strict

    期望输出 0 个错误,0 个警告。

方式 B:git clone(推荐给想跟更新的人)

# 通用 Agent Skills 目录(跨工具)
git clone https://github.com/anticipate218/math-modeling-skill.git ~/.agents/skills/math-modeling-skill

# Claude Code
git clone https://github.com/anticipate218/math-modeling-skill.git ~/.claude/skills/math-modeling-skill
# DeepSeek Harness —— 用户级(所有项目可用)
git clone https://github.com/anticipate218/math-modeling-skill.git "$env:USERPROFILE/.dsh/skills/math-modeling-skill"

# DeepSeek Harness —— 项目级(只对当前仓库生效)
git clone https://github.com/anticipate218/math-modeling-skill.git .dsh/skills/math-modeling-skill

装完的正确形态是 <技能根目录>/math-modeling-skill/SKILL.md 存在。宿主重启或重新扫描技能目录后,用一句中文触发,例如"帮我看看这道数学建模题该怎么建模"。

依赖

用途 需要什么
文档、自检脚本(scripts/、references/、assets/) 只有 Python 3.9+,纯标准库
跑自带算法(examples/algorithms/) 额外 numpy;不需要 scipy / sklearn / pandas / statsmodels
真编译 LaTeX 模板(可选) 本机 TeX 发行版(MiKTeX / TeX Live)+ xelatex / pdflatex / bibtex

拿到 LaTeX 模板(本版新增)

仓库自带三套可直接编译的自包含模板,每套只有 main.tex + refs.bib:

竞赛 模板目录 引擎 特点
国赛 CUMCM assets/latex/cumcm/ xelatex 中文;摘要页起排;AI 使用声明排在参考文献之前
研赛(华为杯) assets/latex/yjs/ xelatex 中文;摘要页即第 1 页;无承诺书/编号页;禁止页眉
美赛 MCM/ICM assets/latex/mcm/ pdflatex 英文;Summary Sheet 独占第 1 页;含 Report on Use of AI
python scripts/download_templates.py --contest cumcm --out my_paper         # 拷出国赛模板
python scripts/download_templates.py --contest all --out papers --zip p.zip # 三套一起,并打包
python scripts/download_templates.py --list                                 # 只看清单

会连编译命令和注意事项一起打印给你。目标文件已存在时默认拒绝覆盖(要覆盖加 --force)。中文模板默认写 fontset=windows,脚本在非 Windows 平台会自动改写成 fontset=fandol(Overleaf/Linux 用它),可用 --fontset {auto,keep,fandol} 控制。


二、算法:从"点到为止"补成"逐个交代"

新增 6 个模块(公开名称 +70),原有 11 个模块全部扩写(+57):

模块 名称数 关键内容
optimization.py 9 单纯形、对偶、整数/0-1 规划、指派、运输、最短路网络流
graphs.py 20 最短路、最小生成树、最大流/最小割、二部匹配、着色、PageRank
heuristics.py 8 模拟退火、遗传、禁忌搜索、粒子群、蚁群、贪心/局部搜索
forecasting.py 19 移动平均/指数平滑、回归、灰色、组合预测、误差度量
statistics.py 23 描述统计、区间估计、假设检验、方差分析、相关、回归诊断、bootstrap
evaluation.py 11 熵权、AHP、TOPSIS、灰色关联、模糊综合、秩和比
clustering.py 12 K-means、层次聚类、DBSCAN、GMM、轮廓系数、手肘法
differential.py 15 Euler/RK4、隐式、刚性、边值问题、SIR、Lotka-Volterra
stochastic.py 16 蒙特卡洛、MCMC、排队论、随机游走、期权定价、置信区间
geometry.py 13 凸包、Haversine、多边形面积、IDW、克里金、泰森多边形
game.py 8 纳什均衡、混合策略、零和、演化博弈、Shapley 值
timeseries.py 12 GM(1,1)+后验差、差分、ARIMA 定阶/拟合/预测、SARIMA、GARCH、卡尔曼滤波、Ljung-Box
ml.py 23 划分/标准化/混淆矩阵/ROC-AUC/K 折、KNN、决策树、随机森林、梯度提升、高斯 NB、LDA、置换重要性、SMOTE、类别权重
multicriteria.py 8 PROMETHEE II、ELECTRE I/III、秩和比、Borda、Copeland、排序一致性
multiobjective.py 9 Pareto 支配/快速非支配排序/拥挤距离、加权和、ε 约束、NSGA-II、2D 超体积、理想点距离
sensitivity.py 11 OAT、弹性系数、Morris 筛选、Sobol 一阶/总效应、均值/KNN/回归插补、Z 分数/IQR/MAD 异常检测
spatial.py 7 一维热传导(显式/隐式)、二维 Poisson SOR、森林火灾元胞自动机、NaSch 交通流、Buckingham π、相似缩放

约束仍然只有 numpy + 标准库(CI 用 AST 扫描禁止 scipy/sklearn/pandas/statsmodels/torch/tensorflow/cvxpy/pulp/sympy/matplotlib),Python 3.9+,无交互、无网络、随机种子显式。

每个算法的细节都写进了 references/algorithm-details.md:数学形式 → 步骤 → 复杂度 → 参数表 → 陷阱 → 怎么检验。最后一栏给的是独立于本实现的检验手段(闭式解、与独立实现对拍、极限行为),可以直接搬进论文的"模型检验"一节。文档条目顺序与代码 __all__ 一致,分节 §3.1–§3.17 与 algorithm-implementations.md、innovation-playbook.md 完全对齐。


三、怎么创新:哪些参数能动

新增 references/innovation-playbook.md。核心观点是改数值 ≠ 创新,并把"调参"分成三个层级:

  • ⚪ 调参:只在别人给的取值附近试数——审稿人不会认为是创新;
  • 🔶 结构化:改参数的形式(把常数换成函数、把标量换成向量/矩阵、把固定权重换成数据驱动的权重)——能写成创新点;
  • 🔴 假设层:改模型假设本身(放宽独立性、加入时变/空间相关、改目标函数族)——最有分量。

手册给 17 个算法族逐族列出:可动参数、常规取值、创新方向、创新度分档;再给出把"改参数"升级成真创新的四步法(机制假设 → 可辨识化 → 消融实验 → 结论边界)、实验设计速查、论文写法三件套、12 条伪创新反面模式和定稿自查清单。手册里每个反引号标识符都能落到代码上(发布时用脚本核对了 795 个函数名/形参名白名单,未解析项 0)。


实现说明(几个真踩到的点)

  • CI 抓到一个本机永远碰不到的 numpy 兼容性缺陷。 工作流装的是 numpy>=1.24(即最新版),本机是 2.1.3。timeseries.py 的卡尔曼平滑里写了 float(H @ cov @ H.T),结果是 (1, 1) 数组;numpy 2.1 允许"单元素数组转标量",numpy 2.5 直接报 TypeError: only 0-dimensional arrays can be converted to Python scalars。改成显式取 [0, 0] 后本机与 CI 双双全绿。教训:本地跑通 ≠ CI 跑通,声明"依赖 numpy"就必须在最新 numpy 上再跑一遍。
  • 长程迭代的连续指标不能当黄金值。 NSGA-II 跑 150 代后与 ZDT1 解析前沿的最大偏差,本机 0.005040、Linux CI 0.005923。先排除了版本与随机性:本机 numpy 2.1.3 与 2.5.3 结果逐位相同(front_size 60、history_len 151、偏差 0.005039580307475866),rng(seed) 比特流相同,代码里没有字符串哈希依赖的排序、argsort 用 kind="stable"。当时判断是混沌放大,于是先把这两个键降级成"分档到 2% 的布尔指纹"——结果第二轮 CI 立刻把这个折中方案也否掉了:同一个提交在两次 Linux 运行里 g_max 分别是 1.008497 与 (1.02, 1.05],分档键直接翻档。真正的推手是不同 runner 的 CPU 指令集/BLAS 让 np.sum 的成对求和差几个 ULP,换成同一平台的另一台机器就会漂。最终做法是彻底不碰连续量:删掉分档指纹键,也删掉模块内 dev <= 0.05、g_max <= 1.05 这两条绝对阈值断言(后者在实测已到 1.02 时只剩 1.5 倍余量,本身就是潜伏的脆弱断言),改为断言四类结构/相对性质:① 数学不变量 g >= 1;② 前沿内部两两互不支配(独立于本模块 pareto_dominates 的手写比较);③ history 长度恒为 n_gen + 1 且取值落在 [1, pop_size](顺带纠正一处想当然:history 记的是"当前种群内的第一前沿规模",并不单调,实测 ZDT1 出现过下降,原计划的单调性断言已撤掉);④ 相对改进——与同一 RNG 产生的随机初始种群相比,最终前沿偏差小一个量级以上(实测比值 7.0e-4,判据 0.1;随机基线自己会随平台一起漂,比的是比值,不是绝对值)。黄金值只留 front_size / history_len 这类整数结构量,键数仍是 875。教训:能用相对判据就别用绝对阈值;能让随平台漂移的量同时出现在比值两边,就别让它单独站在阈值一边。 这条经验已写进 algorithm-details.md 的 NSGA-II 条目和 CHANGELOG.md。
  • 逐算法文档的覆盖率必须能被脚本判定。 文档里的函数名是手写的,很容易"文档有、代码没有"。发布时把 #### \名字(...)`标题与 17 个模块的all双向比对,得到 224 个公开名称 / 223 个条目(含Z95` 一个常量条目)/ 缺失 0 / 多余 0 / 重复标题 0。
  • 模块头 docstring 会和 __all__ 对不上。 扩写时新增了函数,但模块开头的"本模块包含……"还停在旧清单(例如 optimization.py 头只列 5 个、实际 9 个)。本版把 17/17 个模块的头部清单补全为分组枚举并写明条数。
  • 文档里的数字必须与实测一致。 spatial.py 里 Poisson 截断误差一处写 ≈2.8e-3、一处写 ≈2.9e-3;实算(n=16, h=1/17:最大误差 2.826e-3,解析量级 π²h²/12 = 2.846e-3)确认 2.8e-3 才对,已统一。

变更

  • README.md:新增「下载与安装」专章;「算法与代码」由 11 个模块改为 17 个算法模块、222 个公开函数并指向 algorithm-details.md;几何与空间一行改成两个模块的真实内容;「怎么做出创新点」改为引用创新手册;质量保障表算法回归一行改为 17 个算法模块、875 个断言键;结构树补三行。
  • SKILL.md:版本升至 1.7.0;索引新增 algorithm-details.md、innovation-playbook.md、download_templates.py;compatibility 补上依赖口径。
  • CITATION.cff 同步 version: 1.7.0 与 date-released: 2026-09-19。
  • examples/algorithms_golden.json:键数 324 → 875。其中 multiobjective 里两轮 CI 反复证明不可复现的 zdt1_dev_le_2pct、zdt1_g_le_2pct 两个分档指纹键已删除(相对 v1.6.0 仍是纯新增:changed 0 / removed 0 / added 551)。
  • examples/algorithms/{multiobjective,timeseries,spatial}.py:CI 逼出来的三处修正(见上)。multiobjective.py 的 ZDT1 自测段整体重写为"不变量 + 互不支配 + 结构计数 + 相对改进"四类断言。
  • references/algorithm-details.md:NSGA-II 的「怎么检验」一条按上述结论重写,明确写出"长程迭代量不要做黄金值/绝对阈值"。
  • references/algorithm-implementations.md:§2 速查表补 6 行,§3 扩到 §3.17。

验证记录

项目 方式 结果
全量算法回归 python examples/run_algorithms.py 17 个模块 / 875 个断言键,失败 0 个模块;每模块跑两遍比对确定性
跨 numpy 版本 numpy 2.1.3 与隔离环境 numpy 2.5.3 各跑一遍全量回归 两边都是 17 模块 / 875 键 / 0 失败
黄金值是否夹带回归 v1.6.0 提交态 vs 1.7.0 逐键比对 changed=0、removed=0、added=551(纯新增,原有键一个没动)
ZDT1 断言是否脆弱 同一提交连跑两轮 Linux CI + 本机 numpy 2.1.3/2.5.3 旧连续键与分档指纹键两轮均翻档(已删);决定性旁证:算法内容完全相同的 7b08141 失败、dbc488a 成功,两次只差一个 README 提交
逐算法文档覆盖 文档标题 vs 17 个模块 __all__ 双向比对 公开名称 224 / 条目 223;缺失 0、多余 0、重复标题 0
创新手册引用完整性 反引号标识符 vs 函数名/形参名白名单(795 个) 未解析 0
模块头清单与 __all__ 对齐 脚本断言"条数一致、无名称遗漏" 17/17 通过
模板导出脚本自测 python scripts/download_templates.py --self-test 26/26 通过;重复打包的 zip 逐字节一致
技能结构校验 python scripts/validate_skill.py . --strict 0 个错误,0 个警告(29 个文件引用)
依赖边界与代码纪律 CI 的 AST 扫描 无禁用依赖、无 assert、无全局 np.random、docstring 字段顺序正确
论文自检逻辑 python scripts/check_paper.py --self-test 好稿 FAIL=0;坏稿/美赛坏稿按预期报错
模板编译体检逻辑 python scripts/check_latex.py --self-test 26/26 通过(无需装 TeX)
模板真编译 GitHub Actions latex 作业(Ubuntu + TeX Live) 三套模板在 CI 上真编译通过
配图配色与数值 check_palette.py --quiet、make_figures.py --self-test 二色觉最差 ΔE 16.1;24 项配图数值与改动前一致

诚实说明

  • 本版没有并入任何第三方的论文图、表、代码。 references/paper-examples.md 仍然只给链接与出处索引;assets/gallery/ 的 16 张图全部由 make_figures.py 用固定种子原创生成。
  • "每个算法都有实现"的边界要说清:这 222 个函数是教学透明版——网格小、格式简单、中间量全部显式返回,目的是让论文能写清每一步在算什么、以及结果怎么检验。真正的生产规模问题,各模块 docstring 都写明了该换哪个成熟库(OR-Tools、Pyomo、statsmodels、sklearn、SALib、PySAL 等)。把"能跑通并对照"说成"工业级性能"是不诚实的,本版没有这么写。
  • 自测断言是独立的,不是复读实现:用的是闭式解、独立实现(如 SOR 解与直接法解对拍)、极限行为与解析值(如 Sobol 的 S1 解析值 [0.8, 0.2]、GARCH 的方差递推),而不是"实现输出等于实现输出"。
  • 黄金值的作用是防回归,不是证明正确:875 个键只保证"以后改动不会悄悄改变结果";数值本身正确性由那些独立断言负责,新增模块的黄金值是在断言全过之后才记录的。
  • 本版主动"减少"了两个断言键,这不是放宽标准。 zdt1_dev_le_2pct、zdt1_g_le_2pct 连同两条绝对阈值断言被删除,换成了不变量、互不支配、结构计数与相对改进。理由在「实现说明」里:它们的失败与代码正确性无关,只与 runner 的浮点求和顺序有关,留着只会训练出"红了就重跑"的坏习惯。这两个键的删除是显式改动、在 CHANGELOG.md 里写明了;--update-golden 在本版只用于记录新增模块的断言键,没有用来掩盖过任何一次回归。 相对 v1.6.0 发布态,875 个键仍是 chang...
Read more

v1.6.0 — LaTeX 模板真编译门禁:把"文档说能编"变成 CI 硬门禁

Choose a tag to compare

@anticipate218 anticipate218 released this 18 Sep 14:57

这一版做了什么

给三套 LaTeX 模板加了一道以前完全不存在的门禁:真编译。

assets/latex/ 下的国赛 / 研赛 / 美赛模板从 v1.4.0 起就在仓库里,README 里也一直写着"已在 Windows + MiKTeX 上实际编译通过"。但 CI 从来不编译它们——它只校验仓库结构、算法模块、配图和路径风格。也就是说:宏包改名、\cite 打错、字体装不上、\usepackage 少一个,模板可以一直悄悄地坏下去,而仓库照样全绿。文档里的"已验证"会停留在写下它的那一天;学生拿到手,第一遍编译就报错。

这不是审美问题,是覆盖缺口。本版把它补上,并且是拿真引擎去补的。


先说结论

环境 配置 结果
Windows + MiKTeX 25.12 仓库原件(fontset=windows,--keep-fontset) 3/3 通过:国赛 9 页 / 202,842 B、研赛 8 页 / 212,439 B、美赛 8 页 / 284,317 B
Windows + MiKTeX 25.12 CI 等价(临时副本换 fontset=fandol) 3/3 通过:国赛 9 页 / 341,465 B、研赛 8 页 / 366,745 B、美赛 8 页 / 284,317 B
Ubuntu + TeX Live(GitHub Actions) CI 实际配置 3/3 通过:国赛 9 页 / ≈341,040 B、研赛 8 页 / ≈366,285 B、美赛 8 页 / ≈268,965 B

页数在三套环境里完全一致(9 / 8 / 8)——同一份源码换引擎、换字体集、换操作系统都不改分页。这才是"模板能跨机器编译"的实测含义,而不是一句文档承诺。


新增

scripts/check_latex.py —— 三个模板的真编译体检(纯标准库)

  • 把每个模板的 main.tex + refs.bib 复制到系统临时目录再编译(xelatex/pdflatex → bibtex main → 引擎 → 引擎,共 4 遍),仓库里不会出现任何 .aux/.log/.pdf。
  • 解析 main.log / main.blg 判定:硬错误(^!)、未解析的 \cite 与 \ref、字体缺失(The font "..." cannot be found)、Emergency stop、交叉引用未收敛(Rerun to get cross-references right)、是否真的产出 PDF、页数是否低于下限。
  • 顺带核对两条合规顺序(直接查 .tex 源码):国赛/研赛「AI 工具使用声明」必须在参考文献之前,美赛「Report on Use of AI」必须在参考文献之后(即在 25 页正文之外)。这条顺序是硬规则,写错了往年是要扣分甚至判违规的。
  • --self-test 用合成日志跑 26 项固件测试,不需要装 TeX;--require 让"找不到引擎"判为失败而不是跳过(CI 用);另有 --only / --keep / --keep-fontset / --tex-dir 便于本地排查。
  • 退出码即结论,可直接接入任何 CI。

.github/workflows/ci.yml 新增 latex 作业

  • 独立的第二个 job:ubuntu-latest + 装 TeX Live + 跑 check_latex.py --require。
  • 先跑不需要 TeX 的 --self-test:一旦 CI 红了,能立刻分清是"脚本逻辑坏"还是"发行版缺宏包"。
  • 字体处理:国赛/研赛模板用 fontset=windows(调用 Windows 自带宋体/黑体,学生开箱即用),但 Windows 字体在 Linux 上并不存在。因此脚本在临时副本里把它换成随发行版自带的 fandol 再编译,仓库里的模板一个字节都不改。想验证仓库原件本身,在有 Windows 字体的机器上跑 --keep-fontset。

实现说明:三个真踩到的坑(都已修并写进自测)

1. 合规顺序不能直接在整篇 .tex 里搜索。
最初用整篇文本找 \bibliography{,结果命中了模板文件头第 13 行的说明文字:

% 若你暂时不想用 .bib,可把 \bibliography{refs} 换成手写 thebibliography

于是"AI 声明在参考文献之前"被误判成不合规(注释在第 13 行,AI 声明在第 429 行)。现在先剥掉注释再匹配,并加了一条对应的自测。

2. 字体集替换只能动代码行。
fontset=windows 在每个中文模板里出现 3 次,其中 2 次在说明文字里。整篇替换会把"Linux/macOS 请把 fontset=windows 换成 fontset=fandol"改成同义反复,替换计数也虚高成 3。现在按行拆出注释、只替换代码部分,计数是 1。

3. lmodern 不在任何 texlive-* 包里——第一次跑 CI 就是这么红的。
新作业首次运行结果是 2/3 通过:国赛、研赛在 Ubuntu 上顺利编出 9 页 / 8 页,美赛模板却以

! LaTeX Error: File `lmodern.sty' not found.

直接中止。原因是 lmodern.sty 由 Debian/Ubuntu 的顶层包 lmodern 提供,装再多 texlive-* 也不会有。已在安装列表里补上 lmodern,并加了一行 kpsewhich lmodern.sty 做前置断言。

这次失败本身就是这个作业的价值证明:宏包清单的窟窿,只有在真编译时才会暴露。而且脚本准确报出了缺哪个包——修的时候不需要猜。

顺带一提,判断成败也不能依赖日志里的字节数:TeX Live 写 Output written on main.pdf (9 pages, 341464 bytes).,MiKTeX 只写 Output written on main.pdf (9 pages).。把字节数当必填,会在 MiKTeX 上把明明编译成功的模板判成"没产出 PDF"。现在页数取自日志,体积以磁盘上真实文件为准。


变更

  • assets/latex/README.md §6「验证记录」改为一条命令即可复现,并把实测数据按 fontset=windows 与 fontset=fandol 两种配置分开列出(此前只记了前者,且没说明用的是哪个字体集)。§5 排查表新增 lmodern.sty not found 一行(含 Fedora 对应包名)。
  • README.md「质量保障」表新增"模板真编译"一行,仓库结构树补 scripts/check_latex.py,assets/latex/ 那条说明改为"每次 CI 都会被真正编译一遍"。
  • references/templates.md 补"模板改完后怎么验"(含 --self-test / --require / --keep-fontset 三种用法与适用场合)。
  • SKILL.md → 1.6.0,compatibility 写清 check_latex.py 的依赖(本机需有 TeX 发行版提供 xelatex/pdflatex/bibtex),参考文件索引新增一行。
  • CITATION.cff 同步版本与日期。

验证记录

项目 方式 结果
模板编译(CI 等价配置,fandol) python scripts/check_latex.py --require 3/3 通过,硬错误 0、未解析 \cite/\ref 各 0
模板编译(仓库原件,fontset=windows) python scripts/check_latex.py --keep-fontset 3/3 通过
合规顺序 同一脚本的源码检查 国赛/研赛 AI 声明在参考文献之前 ✓;美赛在其之后 ✓
解析逻辑固件测试 python scripts/check_latex.py --self-test 26/26 通过(无需装 TeX)
CI 首次运行 Actions run 35358308247 2/3:脚本准确报出缺 lmodern.sty,据此修复
CI 修复后 Actions run 35358882584 check 与 latex 两个作业全绿,latex 作业 3/3
仓库未被污染 运行前后 git status --porcelain 无输出(编译只发生在系统临时目录)
技能结构 python scripts/validate_skill.py . --strict 0 错误 0 警告
算法回归 python examples/run_algorithms.py 11 个模块 / 324 个断言键全部 PASS
配色体检 python scripts/check_palette.py --quiet 断言全部通过(二色觉最差 ΔE 16.1)

诚实说明

  • fontset=windows → fandol 的替换是尽力而为,不是保证:脚本只改临时副本里的那一行(且只改代码部分、不碰注释),仓库里的 .tex 一个字节都没动。真正的判据是编译成功 + 日志里没有 Font "…" cannot be found。在没有 fandol 的机器上这一步会失败,失败信息会直接打出缺哪个字体。
  • 页数与体积都是实测值,不是估算。PDF 体积每次编译会有几十字节抖动(来自时间戳与 PDF ID),页数则完全稳定;上表中 Ubuntu 一列写作 ≈ 就是这个原因。
  • 本版没有添加任何第三方论文截图或他人图表,理由同前几版:论文插图版权归作者/出版方,未经许可下载进仓库再分发通常不构成合规使用。仓库仍然只提供原创可复现图库 + 官方/授权来源链接索引(见 references/paper-examples.md)。
  • 脚本只做可机械校验的事。模板的排版是否美观、内容是否切题,仍然必须人工复核。