【免费下载链接】cn-math-taxonomy
中小学知识图谱 + 前置诊断:数学(一–九年级、高中必修与选择性必修)+ 小学英语,课标对齐、人教版,999 知识点、4143 题、自适应诊断
cn-math-taxonomy 是一个开源的中小学数学知识图谱项目,收录 802 个知识点、1299 条先修边和 3355 道题库题,对齐课程标准与人教版教材。它最核心的部分是 diagnose/ 目录下的诊断引擎——仅 921 行纯函数代码,无后端、无构建工具、无第三方依赖,却实现了拓扑排序、自适应出题与根因回溯三件难事。这篇文章带你逐层拆解这套算法,并演示如何一行命令跑通全部测试。
📌 项目速览:知识图谱 + 课标 + 题库,一次配齐
| 维度 | 规模 | 数据文件 |
|---|---|---|
| 知识点 | 802 个(小学 216 / 初中 315 / 高中必修 143 / 选择性必修 128) | data/topics.json |
| 先修边 | 1299 条(hard 1124,soft 175),全图只有一个根节点 | data/dependencies.json |
| 课标条目 | 310 条(义务教育 230 + 高中必修 48 + 选择性必修 32) | data/cn-curriculum-standards.json |
| 题库 | 3355 题,每个知识点 4–5 题,自动核验 mismatch 为 0 | data/questions.json |
整个站点是纯静态的:首页、知识图谱浏览 和 诊断工具 三个页面,页面用fetch读取data/下的 JSON,没有数据库、没有服务器端逻辑。
🔍 三步诊断流程:从「选目标」到「根因回溯」
第 1 步:选择诊断目标。你可以指定一个知识点(比如「配方法」),也可以按年级做整册筛查(默认题量上限 16 题,可调 8–30):
第 2 步:自适应出题。引擎每次出题都会告诉你「为什么现在问这个」——是目标本身,还是因为某个先修点两题都没通过而被回溯。第一题答错会再出一道同级或更容易的题复测:
第 3 步:给出根因、不稳点与学习路径。结果页把结论分成卡片:薄弱根因(直接先修里没有薄弱点的薄弱节点)、不稳知识点(一错一对,可能只是粗心)、以及按年级从低到高排列的学习路径;答错初中题,引擎会一路回溯到小学:
路径还会画成一张拓扑分层的图——小学、初中、高中分色,硬先修实线、软先修虚线,红框标出薄弱根因:
🧩 921 行纯函数:诊断引擎是怎么搭的
全部核心逻辑集中在 diagnose/engine.js。它有三个设计特点,是理解后续所有算法的前提:
- 纯函数、无 DOM:浏览器里暴露为
window.DiagEngine,Node 里require()即用,同一份代码两边跑; - 会话是可 JSON 序列化的纯数据:每个函数都「吃进旧状态、吐出新状态」,绝不修改入参,因此可以任意重放、撤销、更正;
- UI 与算法彻底分离:界面逻辑在 diagnose/app.js,只负责调用引擎和渲染。
文件头部的注释(engine.js#L1-L18)就是完整的数据流:
buildGraph 知识点 + 先修边 + 题库 -> 有向图 createSession 目标集合 -> 会话(出题栈、种子、题量上限) nextItem 会话 -> 下一道要出的题 applyAnswer 一次作答 -> 新会话(掌握 / 不稳 / 薄弱) summarize 会话 -> 根因、不稳、学习路径 layout 结果 -> 路径图分层布局 judgeQuestion 答案文本 -> 对 / 错 / 自评拓扑排序:让「先修在前」确定性地成立
buildGraph 先把知识点和先修边建成双向索引:prereqs(每个点的直接先修)和dependents(每个点被谁依赖),并规定每个点的先修按hard 在前、soft 在后排序。
真正的排序在 topoSort:经典的入度法(Kahn 算法),关键在两点——
- 确定性:所有「入度为 0、可以出队」的节点里,永远先取在 topics.json 里排最前的那个。同样的数据,永远得到同样的顺序;
- 环检测:如果排出的数量少于节点数,直接抛出「子图存在环」的错误——数据坏了会立刻报错,而不是死循环。
诊断开始时,subgraph 取「目标 + 它的全部祖先」,只对这块真正用到的子图做拓扑排序。小学、初中、高中全在同一张 DAG 里,这就是「答错高中题能问到小学」的底层原因。
自适应出题:一个知识点最多问 2 题
出题由一个出题栈驱动(applyAnswer)。初始栈里只有目标本身;每次作答后,栈的内容按下面的决策表更新:
| 作答情况 | 结论 | 引擎动作 |
|---|---|---|
| 第一题答对 | 掌握 | 该点所有祖先直接记为「掌握(推断)」,一次跳过整条链 |
| 第一题错,第二题对 | 不稳 | 放进学习路径建议自查,但不向先修回溯 |
| 两题都错(或「不会」) | 薄弱 | 把它尚未判定的直接先修压到栈顶,深度优先继续往回走 |
「第二题出什么」由 pickQuestion 决定:优先 basic,其次与第一题同难度,再其次更容易的,最后才出更难的;同档之内用种子伪随机选一道,且同一道题在一次会话中不会重复出现。题量上限按题计(默认 16),到上限后没测到的点标为「未测」,第一题错了却没来得及复测的会提示「未复测」。
根因回溯:找到真正的薄弱缺口
「薄弱」不等于「根因」。summarize 的判定规则很干净:
- 根因= 被判为薄弱、且直接先修里没有薄弱点的节点。薄弱链条的最底端就是它;
- 如果根因的先修里还有因题量用完而没测到的点,结果会明确标出「真正的根因可能更靠前」,不武断下结论;
- 学习路径= 从所有根因和不稳点出发,沿
dependents(被依赖)方向可达的节点,去掉已掌握的,最后按年级从低到高排列(同一年级内保持拓扑序,先修在前)。
可复现的诊断:种子随机与重放
引擎的随机数只用一个函数生成:mulberry32 伪随机数 + FNV-1a 字符串哈希,输入只是(seed, 知识点, 第几题)。这意味着同一种子 + 同样的作答 → 出的题完全一样,用于测试和复现;URL 里的seed=参数还能把某次诊断「存档」成链接分享。
刷新页面、撤销上一题、逐题更正答案,走的都是同一个入口——replay:从作答记录一条条重放,重建会话。状态永远由记录推导,不会出现「界面状态和记录对不上」的问题。
严格判题:宁可交给人自评,也不错判
判题部分(judgeQuestion)的态度是「只在可靠时给结论」:
- 规范化(normalizeText):NFKC 全角转半角、统一中文标点、
1又1/2转带分数、去掉「答:」前缀、千分位1,000转1000; - 精确有理数比较:用
BigInt分数比较,所以1/2≡0.5≡50%,而1/3≠0.333;坐标(1,2)里的逗号不会被拆成两个答案; - 单位别名表:
米=m、平方米=m²、度=°,一边没写单位则放行,两个不同的已知单位才判错; - 不可靠就不判:代数式、文字、证明题一律返回
manual,显示参考答案让用户自评。
路径图布局:拓扑分层 + 重心法减交叉
结果页那张图由 layout 计算节点坐标:节点取「学习路径 ∪ 目标 ∪ 根因 ∪ 实际问过的点」,边取可达关系的传递约简(中间省略的点画点线);纵向按拓扑分层(先修在上、目标在下),再用 4 轮上下交替的重心法(barycenter)排序减少边交叉。页面端交给 Cytoscape + dagre 渲染,引擎本身只产数据。
✅ 本地运行与验证:一条命令跑通全部测试
git clone https://gitcode.com/gh_mirrors/cn/cn-math-taxonomy cd cn-math-taxonomy python3 -m http.server 8000 # 浏览器打开 http://localhost:8000/diagnose/ 体验诊断 node tests/test_engine.jstests/test_engine.js 无需任何依赖,459 处断言,除了拓扑序、两题判定、小学回溯、旧 id 别名(data/id-aliases.json)等用例外,还包含一个性质测试:对任意「一致学生」(不会的集合对祖先封闭),题量不受限时,引擎诊断出的薄弱集合恰好等于学生不会的点,根因恰好是「自己不会、先修都会」的点——用随机数据反复验证核心算法的正确性。
相关文件与入口
| 文件 | 作用 |
|---|---|
| diagnose/engine.js | 核心算法与判题:921 行纯函数,本文主角 |
| diagnose/app.js | 界面:数据加载、三个页面、localStorage、导出与打印 |
| diagnose/README.md | 完整算法说明、URL 参数、判题规则、已知局限 |
| tests/test_engine.js | Node 引擎测试(无依赖) |
| docs/questions.md | 题库格式、核验方法与统计 |
| scripts/screenshot.js | 无头 Chrome 冒烟测试 + 截图 |
最后提醒:图谱数据、先修边和题库均为 AI 生成的初稿,未经教师审核;诊断结果是学习「线索」而非「结论」,每个知识点最多只问 2 题。想深入细节,diagnose/README.md 是最完整的一手资料。
【免费下载链接】cn-math-taxonomy
中小学知识图谱 + 前置诊断:数学(一–九年级、高中必修与选择性必修)+ 小学英语,课标对齐、人教版,999 知识点、4143 题、自适应诊断
相关推荐
FFmpeg-Builds函数库详解:get_stagedeps_recursive实现依赖拓扑排序
FFmpeg Builds函数库详解:get_stagedeps_recursive实现依赖拓扑排序 引言:构建系统中的依赖管理痛点 在FFmpeg Build
开发工具构建工具音视频CI/CDDatawhale vibe-vibe:AI 写代码出问题后怎么诊断——三分钟排查法与根因四象限
Datawhale vibe vibe:AI 写代码出问题后怎么诊断——三分钟排查法与根因四象限 本文基于 vibe vibe 教程中的《3.6.2 诊断问题:
教程Vibe Coding提示工程人工智能NV-Generate-MR-Brain核心突破:512×512×256超高分辨率背后的技术解析
NV Generate MR Brain核心突破:512×512×256超高分辨率背后的技术解析 NV Generate MR Brain是一款三维(3D)潜在
人工智能计算机视觉媒体生成医疗健康
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考