news 2026/10/22 7:12:55

深入cn-math-taxonomy诊断引擎:921行纯函数代码实现拓扑排序、自适应出题与根因回溯

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入cn-math-taxonomy诊断引擎:921行纯函数代码实现拓扑排序、自适应出题与根因回溯

【免费下载链接】cn-math-taxonomy

中小学知识图谱 + 前置诊断:数学(一–九年级、高中必修与选择性必修)+ 小学英语,课标对齐、人教版,999 知识点、4143 题、自适应诊断

项目地址:https://gitcode.com/gh_mirrors/cn/cn-math-taxonomy
点击查看免费下载

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 为 0data/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 算法),关键在两点——

  1. 确定性:所有「入度为 0、可以出队」的节点里,永远先取在 topics.json 里排最前的那个。同样的数据,永远得到同样的顺序;
  2. 环检测:如果排出的数量少于节点数,直接抛出「子图存在环」的错误——数据坏了会立刻报错,而不是死循环。

诊断开始时,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.js

tests/test_engine.js 无需任何依赖,459 处断言,除了拓扑序、两题判定、小学回溯、旧 id 别名(data/id-aliases.json)等用例外,还包含一个性质测试:对任意「一致学生」(不会的集合对祖先封闭),题量不受限时,引擎诊断出的薄弱集合恰好等于学生不会的点,根因恰好是「自己不会、先修都会」的点——用随机数据反复验证核心算法的正确性。

相关文件与入口

文件作用
diagnose/engine.js核心算法与判题:921 行纯函数,本文主角
diagnose/app.js界面:数据加载、三个页面、localStorage、导出与打印
diagnose/README.md完整算法说明、URL 参数、判题规则、已知局限
tests/test_engine.jsNode 引擎测试(无依赖)
docs/questions.md题库格式、核验方法与统计
scripts/screenshot.js无头 Chrome 冒烟测试 + 截图

最后提醒:图谱数据、先修边和题库均为 AI 生成的初稿,未经教师审核;诊断结果是学习「线索」而非「结论」,每个知识点最多只问 2 题。想深入细节,diagnose/README.md 是最完整的一手资料。

【免费下载链接】cn-math-taxonomy

中小学知识图谱 + 前置诊断:数学(一–九年级、高中必修与选择性必修)+ 小学英语,课标对齐、人教版,999 知识点、4143 题、自适应诊断

项目地址:https://gitcode.com/gh_mirrors/cn/cn-math-taxonomy
点击查看免费下载

相关推荐

上一篇:种子速度 0 人卡三小时?trackerslist 一份 tracker 列表让 BT 下载重新跑起来
下一篇:ZotCard终极指南:如何用Zotero卡片笔记插件终结文献笔记混乱

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 7:12:49

VRCX 完整指南:把 VRChat 好友、世界收藏和通知一次管起来

VRCX 完整指南:把 VRChat 好友、世界收藏和通知一次管起来 【免费下载链接】VRCX Friendship management tool for VRChat 项目地址: https://gitcode.com/GitHub_Trending/vr/VRCX VRCX 是一款开源的 VRChat 好友管理工具:盯住好友在线状态、管理…

作者头像 李华
网站建设 2026/10/22 7:12:23

ORACLE操作同义词语句

1.创建同义词 create (or replace)(public) synonym name (同义词名字) for target(目标名称); 示例:A用户data表,要给B用户使用,再赋予B用户权限后,B用户使用data表需要加前缀&…

作者头像 李华
网站建设 2026/10/22 7:08:48

网盘直链下载助手:8 家网盘免费解析直链,3 步装完直接下载

网盘直链下载助手:8 家网盘免费解析直链,3 步装完直接下载 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / …

作者头像 李华
网站建设 2026/10/22 7:08:23

饭松闹钟app第一个我自己设计的广告片记录

我平时喜欢看电视,所以我积累了很多素材的:请看VCR:-----------------------------饭松闹钟 40秒分两段终极剧本(纯剧本、不自动生成)第一段视频 20s|女高考生剧情(全程画面慢放、标语旁白慢速)…

作者头像 李华