<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>图论 on Veno's Blog</title><link>https://v3n0.com/tags/%E5%9B%BE%E8%AE%BA/</link><description>Recent content in 图论 on Veno's Blog</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><lastBuildDate>Thu, 20 Aug 2026 19:22:04 +0800</lastBuildDate><atom:link href="https://v3n0.com/tags/%E5%9B%BE%E8%AE%BA/index.xml" rel="self" type="application/rss+xml"/><item><title>学习效率的矛盾分析与学习路线的数学建模</title><link>https://v3n0.com/post/2026/learning-route-hypergraph/</link><pubDate>Thu, 20 Aug 2026 19:22:04 +0800</pubDate><guid>https://v3n0.com/post/2026/learning-route-hypergraph/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;本文 LLM 使用成分声明&lt;/strong&gt;：LLM 使用场景在本文主要在数学模型的推演验证和严谨化，现有论文的查询和解析。本篇使用的加权有向 B-超图相关结论验证过程主要使用 claude-opus-5。本文除最后大章的数学论证（AI 编写，人工审核）以外的全部文字叙述，包括数学模型的重构思路，由人工编写，无生成。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a class="link" href="https://v3n0.com/post/2026/everything-is-concept/" target="_blank" rel="noopener"
&gt;上一篇的模型&lt;/a&gt;远远不够完善，并且 gpt-5.6-sol 撰写的文章也并没有讲清楚我的思路和心路历程。因而有了改进之后的建模，以及这篇文章。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;在 &lt;a class="link" href="https://v3n0.com/post/2026/learning-method/" target="_blank" rel="noopener"
&gt;《逃离应试教育，重新学会怎么思考》&lt;/a&gt;那篇文章中我提到，学习一个知识体系的过程，本质上是在寻找它的“最小生成元 + 生成规则”，不断压缩信息的过程。&lt;/p&gt;
&lt;p&gt;在我自己的学习经历和观察体会的现象当中，我反复认识到，&lt;strong&gt;学习路线才是学习效率的决定性因素&lt;/strong&gt;。不同学习路线带来的学习成本差距是数量级上的差距，远远大于学生个人理解能力、教师面对同一教纲的教学能力、或其他的什么因素。关于这点，我个人的经历可以参考&lt;a class="link" href="https://v3n0.com/post/2026/everything-is-concept/" target="_blank" rel="noopener"
&gt;上篇文章的开头&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;经历这些事情之后，我经常沉迷于思考这样的一个问题：&lt;/p&gt;
&lt;p&gt;怎样才能做到把优质的学习路线的生产和消费转化为社会化的规模？&lt;/p&gt;
&lt;p&gt;换句话说，怎样把优质的学习路线从小部分高知群体偶尔个人手工产出，转变为使用机器批量的产出？怎样把定制化的优质学习路线从师徒制的私塾里解放到全社会的学习者触手可及的地方？&lt;/p&gt;
&lt;p&gt;既然学习路线才是学习效率的决定性因素，于是我又不得不思考：为什么现代的教育体系中，一般使用的学习路线如此低效呢？在学习目标确定的情况下，如何以更低的成本、更快地获得目标知识呢？&lt;/p&gt;
&lt;h2 id="学习效率的矛盾"&gt;学习效率的矛盾
&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;在复杂事物的发展过程中，存在许多矛盾，其中必有一种是主要的矛盾。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在“学习路线是学习效率的决定性因素”这一前提下，那么提高学习效率的关键就在于学习路线的优化了。&lt;/p&gt;
&lt;p&gt;如果实际思考过怎样优化自己的学习路线，实际上会很容易发现下面这些现象。&lt;/p&gt;
&lt;h3 id="课程编排不因材施教"&gt;课程编排不因材施教
&lt;/h3&gt;&lt;p&gt;学生能接触到的学习路径，通常由学校的课程编排、教材章节或授课老师等外部因素决定。但每个人知识的掌握程度不同，适合的学习路径各不相同，学习目标也不相同，这导致他们实际能接触到的路径往往不符合自己当前的状态的最优解。&lt;/p&gt;
&lt;p&gt;同时，为了了解某些具体的现实实用概念的工科学生，却不得不跟着教授编排的教纲，按照理科的标准学完课程参与考试，被迫理解非常多必要之外的知识，就像学习打螺丝，大多数时候并不需要理解螺丝的历史和生产流程。&lt;/p&gt;
&lt;h3 id="祖宗之法不可不变"&gt;祖宗之法不可不变
&lt;/h3&gt;&lt;p&gt;学术界的总体知识在不断进步，新理论的引入能够极大简化知识体系。比如算子理论和希尔伯特空间极大简化了高校工科数学的推导路径，有潜力大幅缩短各类科目的学习路径。&lt;/p&gt;
&lt;p&gt;然而学校的教材和教纲往往是祖宗之法，不可变动。这导致实际的教学路径往往明显落后于潜在的最佳路径。&lt;/p&gt;
&lt;p&gt;从义务教育到高中到大学，相信读者一定亲身体会过学习了新知识新概念之后，这些新内容对于先前的考试的降维打击。如果在既有上下文一定的情况下，理解相同的新信息需要的成本视作理解能力的话，上面说的这种升年级之后的降维打击并不能体现任何学生理解能力的进步，反而事实上证明了学习路线设计的不合理。&lt;/p&gt;
&lt;h3 id="少学反而更慢"&gt;少学反而更慢
&lt;/h3&gt;&lt;p&gt;有时候，少学点知识反而学的更慢。在引入更多知识的情况下，有时反而大幅提高学习效率。看似反直觉，但例子其实相当多，也相当显然。关于这一点我觉得非常值得单独列出来举几个例子说一下，因为它带来的问题可能比前面两个会更大：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;一种情况：假设学习目标是 $A, B, C$ ，传统课程可能只会安排 $A \to B \to C$ 。但实际上存在一个目标外概念 $X$，可以 $A \to X \to B \to C$，乍看多学了一个东西，似乎更慢。但如果：$$w(A, B) = 10, \qquad w(A, X) = 2, \qquad w(X, B) = 1$$直接学 $B$，成本是 10，先 $X$ 后 $B$ ，学习成本是 $2 + 1 = 3$ 。于是 $A \to X \to B \to C$ 反而是更高效的路径：$$w(A \to X) + w(X \to B) &amp;lt; w(A \to B)$$ 然而，继承优秀传统八股文化的考试、面向这样的考试而设立的课程、种种社会压力，无疑会阻止学生学习课纲外的内容，老师们给出的原因无非是高考或是什么的考试里，写这个洛必达不给分云云。有些极端的地方甚至早已形成了嘲讽自行学习微积分等课纲外的高校内容的中学生的歪风邪气，称这些求知的学生为做题区嘉豪，这样的事情在某些高考压力大的省份发生的尤为频繁，有些读者相信会感同身受。至于为什么本该在传说中自我调节的市场经济社会却产生了这样的考试和这样的课程，我们就不深入思考了。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;另一种情况：大学的课程往往反复教了同一个东西很多遍，但每一门课都把它伪装成一个全新的技巧。假设学习目标是 $A, B, C$ ，大多中国的学校往往会喜欢这样教：$$\varnothing \to X_1 \to A, \qquad \varnothing \to X_2 \to B, \qquad \varnothing \to X_3 \to C$$ 其中 $w( \varnothing \to X_n )$ 非常大，不同的 $X_n$ 却使用结构类似的推演流程。往往老师这时就喜欢说：“这就是数学之美，冥冥之中存在着联系。” 台下学生不明觉厉，深以为然。但是，如果首先进一步发现 $X$ 本身就是一个更高层次的共同结构，此时由 $X$ 可以衍生的概念的学习效率会发生质变。进而可以以极低的成本：$$X \to {X_1, X_2, X_3}$$ 那么再找到 $A, B, C$ 等特例的成本也极低。因为 $X$ 作为一次抽象产生的知识，可以作为多个后续节点的共同前置条件：$$w(\lbrace X, X_1\rbrace \to A) &amp;lt; w(X_1 \to A)$$ 以我的学校的课程编排举例，具体编排可能忘了，可能大概是：$$高数→线性代数→概率论→离散数学→信号与系统$$ 到了信号与系统，学生会突然被要求学习傅立叶级数、傅立叶变换、拉普拉斯变换、Z 变换、卷积、频域、系统函数。可能自动化学院在自动控制里面，又要学一遍拉普拉斯，极点零点，频率响应，到了数字信号处理，把 Z 变换、DTFT、DFT、FFT 又学了一遍。这很容易有一种强烈的错觉，这些都是不同课程里的不同形式，我得分别记住它们的公式和推导和性质。但如果你稍微越过传统工科教纲一步，先引入一个更高层次的概念，只要有非常入门级的算子理论，理解函数空间上的内积与正交展开，把求导变成作用在函数空间上的算子 $D$ ，立刻可以复用线性代数的知识，就像特征向量一样，因为 $De^{i\omega t} = ie^{i\omega t}$ ，自然就知道它是微分算子的特征函数，所以傅立叶分析的核心思想自然而然就成为了：找到一组在某个算子作用下行为特别简单的基函数。换成 $e^{st}$ ，变成复平面，就成了拉普拉斯变换，微分算子换成移位算子，就变成了 Z 变换。如果进一步引入算子谱定理，立刻就知道，微分变换成乘法是来自微分算子的谱表示，卷积变成乘法来自平移算子及其谱表示，各种逆变换来自谱表示的可逆重构，频域求解微分方程本质上是把算子变换到更容易求逆的表示中。例子太多，再说就扯远了，但足以证明，有些教学路线为了避免让本科生提前接触函数空间、算子和谱理论，看起来少学了一些抽象数学，却不得不让学生在后续课程中反复证明同一类性质、反复记忆不同变换的公式。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;上面这种类型的类似错误教学方式还有很多，它们已经在事实上荼毒学生的思维。因为它们扼杀了学生的求知欲，转而又进一步封锁了从感性认识上升到理性认识的通道。&lt;/p&gt;
&lt;p&gt;“冥冥之中万物有联系”，终究是停留在冥冥之中的感性认识，就像是中医。不去上升到理性认识，反而是不断强化形而上学的规律，最终沉沦于题海之中，把学生当成大模型，把题目当成语料去训练，拟合考试题目。最终并不会真正习得背后的规律，结局反而是过拟合，丢失理解规律背后本质的能力。相当多的学生仍然蒙在鼓里，把重复反复推演的痛苦等同为学习的痛苦，在以后的自学道路上也这样做，百害而无一利。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="真正的主要矛盾"&gt;真正的主要矛盾
&lt;/h3&gt;&lt;p&gt;上面这三条现象可以被分别概括为这三条矛盾：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;外部决定的路径与个体适配路径的矛盾&lt;/li&gt;
&lt;li&gt;固定教学大纲与学术界知识演进的矛盾&lt;/li&gt;
&lt;li&gt;学习内容最小化与学习成本最小化之间的矛盾&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我们不难发现它们总是存在的共同点。现代教育系统能够让学生接触的路径是预先划定范围的、静态的、标准化的路径，而学习本身却是不限范围的、动态的、个人化的过程。因此我们总结：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;学习效率的主要矛盾，是既定学习路线自身的局部静态与最优学习路线的全局动态之间的矛盾&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;事物矛盾的法则，是对立统一的法则。既定学习路线和最优学习路线，相互对立，又相互统一；互为依赖，又相互制约。&lt;/p&gt;
&lt;p&gt;既定学习路线要沿着当前路线走，找到最优路线要不断重新选择路线，这体现了二者的对立。&lt;/p&gt;
&lt;p&gt;但如果完全没有既定路线，每学一个概念都重新搜索整个知识体系；反过来，如果不去寻找全局动态最优，你永远执行第一次制定的路线，那么你又无法利用时刻产出的新知识。&lt;/p&gt;
&lt;p&gt;因此，“如何提高学习效率”这一核心问题，现在变成了：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如何在全局知识和已有知识不断变化的过程中，持续找到通往目标知识的最优路径&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;2026.8.25 编辑：&lt;/p&gt;
&lt;p&gt;思路差不多说完了，打个广告，对这个话题感兴趣的可以加群一块讨论：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://v3n0.com/post/2026/learning-route-hypergraph/DerivonResearch-QGroup.jpg"
width="1284"
height="2289"
srcset="https://v3n0.com/post/2026/learning-route-hypergraph/DerivonResearch-QGroup_hu_c915ac0f78753217.jpg 480w, https://v3n0.com/post/2026/learning-route-hypergraph/DerivonResearch-QGroup_hu_33ce0a66ef9f9216.jpg 1024w"
loading="lazy"
alt="Q-group"
class="gallery-image"
data-flex-grow="56"
data-flex-basis="134px"
&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="学习路线的建模历程"&gt;学习路线的建模历程
&lt;/h2&gt;&lt;p&gt;最开始，我还没有意识到这是个动态优化问题。三个月前我最开始其实只是想做一个优质教程共享平台，让任何人都可以写教程，把优质的教程放在平台上，辅以 AI 帮助教学和检验理解，引入交互式的可视化的教学元素。希望这样一来，优质的教程自然会被用户选择，进而被热门推送。&lt;/p&gt;
&lt;p&gt;首先是尝试我一直惯用的套路，直接去列几个对象，再给对象列字段等等，准备拿它做数据库表。大概分了 Course, Chapter, Concept 等层级，尝试让 AI 判断用户是否真正理解概念，其实还是受现有的教学逻辑限制，是一套形而上学的思路。&lt;/p&gt;
&lt;p&gt;这时我发现，我的教程仍然是一个线性的固定的教程，问题随之暴露出来：概念学习并没有唯一顺序。学习信号与系统时，欧拉公式只需要在第一次使用前掌握，并不天然属于某一章的固定位置。因此教程不一定非得是线性的，但模型限制了这一点。&lt;/p&gt;
&lt;p&gt;于是我把教程变成了图，章节是点。但不同章节各种概念有相互依赖，有包含，有相关等关系，只好把章节之间的关系分成多种类别。&lt;/p&gt;
&lt;p&gt;我被逼到开始用图表达知识，却仍然被限制在传统的科目、教材、章节、小节的框架里。最后我才意识到问题。既然核心问题是找到最优路径，事实上为什么我不直接对知识本身进行建模？&lt;/p&gt;
&lt;p&gt;能否把学习路径变成一个可以被建模、计算和优化的问题？形象一点的说，能不能把知识体系变成地图，在这张地图上做导航软件？&lt;/p&gt;
&lt;p&gt;我们不得不需要一个可靠的参照来指导我们软件的代码实现，于是我重新开始尝试建模。&lt;/p&gt;
&lt;p&gt;任何的要学习的知识都是一个“概念”，我要学数学，数学是个概念，线性代数是一个概念，行列式又是一个概念，同一层级的概念可以相互推演，概念又可以被拆分为更小的概念，可以组合成更大的概念。似乎所有要学习的内容都是一个概念。抱着这样的想法我开始尝试把之前的概念画成不区分教程、章节等层级的，可以嵌套的思维导图，一切都只是概念。&lt;/p&gt;
&lt;p&gt;在草稿纸上画了半天，我发现这些逻辑用自然语言或是图形语言是根本描述不清楚的：它容易漏掉一些情况，会在一定程度上导致模糊的行为。我指的“漏掉情况”，并不只是漏掉边界条件这么简单，而是指那些会直接影响整个模型是否可以稳定写成代码，找到路径的算法是否可实现的关键情况。我不希望在付出代码实现成本之后，回头才发现这些问题。&lt;/p&gt;
&lt;p&gt;所以为了必须做到这种精度的建模需求，我选择引入数学工具来描述数据模型，这就是我为什么需要用数学。数学从来都不是被用来伪装思路正确的东西，数学是一个帮助人把问题抽象化的工具，帮人把问题真正理清楚。&lt;/p&gt;
&lt;h3 id="上一版-and--or-dag-的模型问题"&gt;上一版 AND / OR DAG 的模型问题
&lt;/h3&gt;&lt;p&gt;上一篇&lt;a class="link" href="https://v3n0.com/post/2026/everything-is-concept/" target="_blank" rel="noopener"
&gt;《万物皆概念：如何最大化学习速度？》&lt;/a&gt;中，我已经正在着手做一个“万物皆概念”版本的知识图谱数学模型。&lt;/p&gt;
&lt;p&gt;我先大概简述一下上一篇所建立的模型经历的过程：我把概念视为点，相邻概念之间的推导视作有向边，把无环作为模型的公理，尝试构建一个概念的 DAG 图（有向无环图）。当时引入无环公理是为了避免教程里出现循环论证，真的有环的话，打算让用户另外起一个 Wiki 图，因为当时认为应当不属于同一份教程。在此基础上，定义如何把某一概念拆分成更细的 DAG 图，定义如何封装 DAG 子图为更大概念。通过给边加权，权用来代表学习成本，进而实现动态规划最优路线。&lt;/p&gt;
&lt;p&gt;然后我发现，推导并不是简单的一个概念指向另一个概念，推导可能是由众多概念推出来下一个概念。因此我把每一个概念的入边进行了分组，属于同一个推导流程的分为一个 AND 组，同一个概念的入边 AND 组之间的关系是 OR。&lt;/p&gt;
&lt;p&gt;然后我发现我漏掉了一件事，每个概念的推导过程等属性还被我落在边上，而不是 AND 组上。于是在上篇文章结尾，我在 2026.8.19 补了一处修正：问题引入、推导解答和理解材料，不属于单条边，而属于整个 AND 组。&lt;/p&gt;
&lt;p&gt;当时以为是一个小修正，写完发现实际上这引导出了 AND / OR DAG 这个模型体系的一些固有问题。AND / OR 似乎是一个描述太过复杂的对象，不便推演。同时，我使用了太多教学和学习领域专有的内容作为名词，并没有把它当成一个真正的数学模型，这会导致并不能专注于模型本身。&lt;/p&gt;
&lt;p&gt;但这次数学建模的尝试真真确确已经带来了相当多的好处，也让我坚定了数学建模这条路。建立模型之后，通过套用前人的数学结论，往往可以得到一些之前从来没考虑到的优秀性质，可以立刻察觉到之前从来没考虑到的逻辑疏漏，可以帮我提前排出一些技术实现的风险。&lt;/p&gt;
&lt;p&gt;当我愿意把模型当作纯数学对象进行处理时，也才能意识到这样的数学对象事实上不止可以适用于规划学习路线，事实上可以用于规划任何路线，典型的例子就是硬件仿真路线的优化。这在透过现象看本质之前，是不可能实现的。一旦把具体对象抽象成它背后的关系结构，原本只存在于一个领域中的规律，才有可能被迁移到另一个领域。&lt;/p&gt;
&lt;p&gt;借助这些探索，我也从数学推演中反应过来一些之前从没考虑到的问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;知识并不是以 DAG 的形式存在的，有些知识恰恰就是可以以环的形式存在，相互推演得到的。例如通过欧拉公式，我们可以从指数函数得到正弦函数，也可以从正弦函数得到指数函数。我想避免的只是同义反复，例如线性和叠加原理。如果一个教程里说，线性就是满足叠加原理，叠加原理是线性系统的性质，那等于是什么都没说，相当于引入了一条公理而不是定理。&lt;/li&gt;
&lt;li&gt;概念不是可以随意拆分的，也不是可以随意封装的。它远远不只是把其中一段 DAG 在纸上画一个圈标出来这么简单。这导致之前想象的概念的拆分和封装的预估难度骤然变大。但也不是说不可实现，因为概念的封装和拆分显然是现实中存在，并且高度有价值的。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我反思。当时试图把它做成一个 DAG，引入无环这一模型中的公理，是为了避免教程中出现循环论证。可是我的初衷却是对知识进行建模。教程只会是知识的一个子图，我却让教程的性质变成了知识的公理。我只需要教程是无环的即可，不需要让知识也是无环的。我又一次被做教程的思维限制住了思路。&lt;/p&gt;
&lt;p&gt;之后我尝试重构了这个模型。上一版模型最严重的几个问题反而不是上篇文章末尾的几个问题了，实际上最大的问题总结如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;没有专注于数学本身。&lt;/li&gt;
&lt;li&gt;为了弥补多条件的知识推导而引入了 AND / OR ，不论从代码实现还是数学论证时的观感上都像是补丁的东西，又把推导成本，这个权重给粘在了 AND 组上面。&lt;/li&gt;
&lt;li&gt;把知识图谱限制为无环，限制了表达的上限，不同教程无法在同一张知识图谱存在，违背时刻计算新学习路线的初衷。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此，如何改进这个模型也是明确的：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;专注于数学对象本身。&lt;/li&gt;
&lt;li&gt;把 AND 组单独作为对象，而放弃边。&lt;/li&gt;
&lt;li&gt;验证，如果不限制无环，模型是否还能成立。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="加权有向-b-超图"&gt;加权有向 B-超图
&lt;/h2&gt;&lt;p&gt;上面三条改进目标，最后收敛成了一个数学对象：&lt;strong&gt;加权有向 B-超图&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;它的全部内容是：一堆点，和一堆「多个前提共同推出一个结论」的带权连接。没有概念，没有教程，没有 AND 组，没有 OR 组，也不要求无环。&lt;/p&gt;
&lt;p&gt;定义就这么点，但立完之后能推出来的东西超出我的预期。为了避免读者在后面七节里迷路，先把结论摆出来：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AND 组和 OR 组可以被完全消掉。&lt;/strong&gt; 不是绕过去，是能构造双射证明它们不携带任何独立信息。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;权只能挂在超边上，边级权在数学上无解。&lt;/strong&gt; 这是上一篇结尾那处修正的完整版本。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无环公理可以删掉，而且删掉后模型比原来更宽松。&lt;/strong&gt; 欧拉公式那种好环得以保留，线性与叠加原理那种同义反复自动失效。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可达性判定是线性时间的。&lt;/strong&gt; 因为它和 Horn 子句的最小模型是同一件事。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我真正想要的那个成本口径是 NP-hard 的，而且不可近似。&lt;/strong&gt; 这是整个模型里最坏的消息。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;但它被夹在两个多项式可算的界之间，而且上界自带一条真实可走的路径。&lt;/strong&gt; 于是任何时刻都有可推荐的路线，外加一个「最多差多少」的证明上界。实测还要好：随机图上区间有 97~99% 直接闭合，连搜索都不用启动。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;区间宽度本身又是一个知识图质量的诊断指标。&lt;/strong&gt; 代价是它同时也是难度指标：&lt;strong&gt;图越接近我们想要的样子，就越靠近难解那一端。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;「理解倍率」不能定义为路线计数。&lt;/strong&gt; 那是计数困难问题，上一篇里的那个设想可以判死刑了。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;概念封装只在两个严格条件下保真&lt;/strong&gt;，而上一版凭直觉立的「禁止递归交集」，恰好就是其中之一。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下面七节先把这个对象定义清楚，再逐条给出上面这些结论的证明或反例，并说明它们解决了上一版的哪些问题、又留下了哪些新问题。&lt;/p&gt;
&lt;p&gt;下面每一条结论我都要求自己要么给出证明、要么给出反例，能写成代码对拍的一律对拍。全部代码在 &lt;a class="link" href="https://github.com/derivon-research/paper" target="_blank" rel="noopener"
&gt;derivon-research/paper&lt;/a&gt;，无第三方依赖。根目录的 &lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/derivon_core.py" target="_blank" rel="noopener"
&gt;&lt;code&gt;derivon_core.py&lt;/code&gt;&lt;/a&gt; 是参考实现（线性时间闭包、两个多项式界、集合成本的分支定界），&lt;code&gt;verification/&lt;/code&gt; 下是各条结论的机器验证。后文每处实测数据都会链到对应的那段代码。&lt;/p&gt;
&lt;h3 id="阅读前的数学补充"&gt;阅读前的数学补充
&lt;/h3&gt;&lt;p&gt;这一节是给数学基础不好的读者准备的。全文真正用到的工具只有四类：集合、函数、逻辑连接词、求最小值。另有三个稍专门的概念：最小不动点、超图、计算复杂度。熟悉的读者可以直接跳到下一节。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;符号速查。&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;符号&lt;/th&gt;
&lt;th&gt;读作&lt;/th&gt;
&lt;th&gt;意思&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$p \in P$&lt;/td&gt;
&lt;td&gt;$p$ 属于 $P$&lt;/td&gt;
&lt;td&gt;$p$ 是集合 $P$ 里的一个元素&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$T \subseteq P$&lt;/td&gt;
&lt;td&gt;$T$ 包含于 $P$&lt;/td&gt;
&lt;td&gt;$T$ 的每个元素都在 $P$ 里&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$U \cup V$ / $U \cap V$&lt;/td&gt;
&lt;td&gt;并 / 交&lt;/td&gt;
&lt;td&gt;合起来 / 公共部分&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\varnothing$&lt;/td&gt;
&lt;td&gt;空集&lt;/td&gt;
&lt;td&gt;没有任何元素的集合&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\lvert U \rvert$&lt;/td&gt;
&lt;td&gt;$U$ 的势&lt;/td&gt;
&lt;td&gt;集合里元素的个数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$2^{P}$&lt;/td&gt;
&lt;td&gt;$P$ 的幂集&lt;/td&gt;
&lt;td&gt;$P$ 的&lt;strong&gt;所有子集&lt;/strong&gt;组成的集合；若 $\lvert P \rvert = n$ 则共 $2^{n}$ 个&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$f : U \to V$&lt;/td&gt;
&lt;td&gt;$f$ 从 $U$ 映到 $V$&lt;/td&gt;
&lt;td&gt;一个函数，输入取自 $U$，输出落在 $V$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\wedge$ / $\vee$&lt;/td&gt;
&lt;td&gt;且 / 或&lt;/td&gt;
&lt;td&gt;逻辑连接词&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\Rightarrow$ / $\iff$&lt;/td&gt;
&lt;td&gt;推出 / 当且仅当&lt;/td&gt;
&lt;td&gt;单向蕴含 / 双向等价&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$C^{*}$&lt;/td&gt;
&lt;td&gt;$C$ 星&lt;/td&gt;
&lt;td&gt;上标星号表示「最优值」&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$O(n)$&lt;/td&gt;
&lt;td&gt;大 O&lt;/td&gt;
&lt;td&gt;耗时随规模增长的量级&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;集合语言。&lt;/strong&gt; 三个集合贯穿全文：$P$ 是全体点，$S$ 是学习者已经掌握的点，$K$ 是推导过程中的当前状态。学习的过程就是 $K$ 从 $S$ 开始不断变大。「$T$ 里所有点都已掌握」这句话，写成集合语言就是 $T \subseteq K$——不需要逐个检查，一个符号就说完了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;双射。&lt;/strong&gt; 要证明「换一种写法没有丢信息」，标准做法是构造一个来回都能走通、且走一圈回到原处的对应，叫双射。能构造出来，就说明两种写法携带完全相同的信息，删掉一边不损失任何东西。后面「AND / OR 组可以被完全消掉」就是这么证的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;两种范式。&lt;/strong&gt; 同一个逻辑条件有两种标准写法。&lt;strong&gt;合取范式&lt;/strong&gt;是「若干个『或』用『且』连起来」，例如 $(I_1 \vee I_2) \wedge (I_3 \vee I_4)$；&lt;strong&gt;析取范式&lt;/strong&gt;是把它展开成「若干个『且』用『或』连起来」，即 $(I_1 \wedge I_3) \vee (I_1 \wedge I_4) \vee (I_2 \wedge I_3) \vee (I_2 \wedge I_4)$。两者逻辑等价，但长度可以差很多：左边 4 个条件，右边 4 项；若有 $k$ 组这样的「或」，左边是 $2k$ 个条件，右边却有 $2^{k}$ 项。这个爆炸后面会在概念封装那里原样出现。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;最小不动点。&lt;/strong&gt; 「不动点」指对某个操作而言输入等于输出的东西。本文的操作是「扫一遍所有连接，把前提已经齐了的那些的结论加进来」。算法上就是最朴素的做法：从 $S$ 出发反复扫描，直到某一轮没有任何新东西可加。因为点的总数有限、集合只增不减，这个过程一定会停——这就是「一定存在且唯一」的工科版理由，Knaster–Tarski 定理&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;只是把它严格化。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;图与超图。&lt;/strong&gt; 有向图是点加带箭头的边。&lt;strong&gt;路径&lt;/strong&gt;是一串首尾相接的点，走成一条线，既不分叉也不汇合。&lt;strong&gt;超边&lt;/strong&gt;把「一条边只能一个起点」的限制放开：$(\lbrace A,B \rbrace, D)$ 表示 $A$ 和 $B$ 都有了才能得到 $D$，画出来是两条线汇进一个箭头。&lt;strong&gt;B-超图&lt;/strong&gt;指每条超边只有一个终点，「尾」指前提集合，「头」指结论。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;复杂度。&lt;/strong&gt; $O(n)$ 表示耗时大致随规模线性增长。&lt;strong&gt;NP-hard&lt;/strong&gt; 的实践含义是：不要指望写出一个在所有输入上都快的精确算法。&lt;strong&gt;归约&lt;/strong&gt;记作 $\Pi_1 \le_{p} \Pi_2$，含义是「如果我能快速解 $\Pi_2$，就能拿它快速解 $\Pi_1$」，所以 $\Pi_2$ 不会比 $\Pi_1$ 容易。&lt;strong&gt;不可近似&lt;/strong&gt;比 NP-hard 更强一层：不但精确解算不出来，连「保证结果不超过最优解若干倍」的打折算法也不存在。&lt;/p&gt;
&lt;h3 id="分层与核心对象"&gt;分层与核心对象
&lt;/h3&gt;&lt;p&gt;上一版最大的毛病是「没有专注于数学本身」。要治它，得先有一条硬判据，否则「学习」相关的词还会不断渗回来。&lt;/p&gt;
&lt;p&gt;我定的判据只有一条：&lt;strong&gt;一个字段只有在被核心算法读取时，才能进入核心层。&lt;/strong&gt; 核心算法只有三个——可达性判定、最低成本求解、可执行序生成。按这条筛，上一版的 &lt;code&gt;definition&lt;/code&gt;、&lt;code&gt;question&lt;/code&gt;、&lt;code&gt;answer&lt;/code&gt;、&lt;code&gt;materials&lt;/code&gt; 全部出局，它们从不被这三个算法读取；权留下，因为求解器读它。&lt;/p&gt;
&lt;p&gt;于是分成三层，下层不知道上层的存在：&lt;/p&gt;
&lt;pre class="mermaid"&gt;
flowchart TB
APP[&amp;#34;应用层：学习路线规划 · 硬件仿真迭代 · Agent 任务规划&amp;#34;]
MOD[&amp;#34;模块层：概念的封装与展开（可选，可以整体不要）&amp;#34;]
CORE[&amp;#34;核心层：点 · 超边 · 图 · 成本&amp;#34;]
APP --&amp;gt;|依赖| MOD
MOD --&amp;gt;|依赖| CORE
APP -.-&amp;gt;|&amp;#34;标定权重&amp;#34;| CORE
&lt;/pre&gt;
&lt;p&gt;核心层一共七个名字，其中只有前三个需要持久化：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;名称&lt;/th&gt;
&lt;th&gt;记号&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Point&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$p \in P$&lt;/td&gt;
&lt;td&gt;基本对象。核心层不假设它有内部结构，也不承诺它代表什么&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hyperedge&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$h = (T, y, w)$&lt;/td&gt;
&lt;td&gt;一个推导&lt;strong&gt;步骤&lt;/strong&gt;。$T \subseteq P$ 是尾（前提集），$y \in P$ 是头（结论），$w \ge 0$ 是完成这一步的成本&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Graph&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$G = (P, H)$&lt;/td&gt;
&lt;td&gt;加权有向 B-超图&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;State&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$K \subseteq P$&lt;/td&gt;
&lt;td&gt;当前已获得的点集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Derivation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$R \subseteq H$&lt;/td&gt;
&lt;td&gt;见证目标可从起点得出的&lt;strong&gt;一整组&lt;/strong&gt;超边&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Query&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$(S, t)$&lt;/td&gt;
&lt;td&gt;起点集与目标点&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$C(R)$&lt;/td&gt;
&lt;td&gt;Derivation 的成本&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这里有个容易混的地方要先说清：&lt;strong&gt;Hyperedge 是一个步骤，Derivation 是一整组步骤。&lt;/strong&gt; 相应地 $\lvert T(h) \rvert$ 说的是「某一步需要几个前提」，$\lvert R \rvert$ 说的是「这次推导一共有几步」。另外，$T$ 取自 tail（尾），不是 target；目标一律用小写 $t$。&lt;/p&gt;
&lt;p&gt;一步推导的规则简单到有点无聊：&lt;/p&gt;
&lt;p&gt;$$h = (T, y, w) \ \text{可执行于} \ K_i \iff T \subseteq K_i, \qquad K_{i+1} = K_i \cup \lbrace y \rbrace$$&lt;/p&gt;
&lt;p&gt;尾集为空是合法的。$T = \varnothing$ 时 $T \subseteq K_i$ 恒成立，所以 $(\varnothing, y, w)$ 在任何状态下都可执行，语义上是「无条件起点」：不问学习者已经会什么，付出 $w$ 就直接获得 $y$。这和「点落在 $S$ 里」不是一回事——$S$ 描述的是&lt;strong&gt;学习者&lt;/strong&gt;（因人而异，不计成本），空尾超边描述的是&lt;strong&gt;图本身&lt;/strong&gt;（对所有人一样，要付成本）。一张没有任何空尾超边的知识图，零基础学习者什么都学不了，因为没有任何一步能起步。&lt;/p&gt;
&lt;p&gt;走一遍就清楚了。设起点 $S = \lbrace A \rbrace$，目标 $Z$：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;K₀ = {A}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ({A}, B, 3) 可执行，因为 {A} ⊆ K₀ → K₁ = {A, B}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ({B}, D, 1) 可执行 → K₂ = {A, B, D}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ({B}, E, 1) 可执行 → K₃ = {A, B, D, E}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ({D,E}, Z, 1) 可执行，因为 {D,E} ⊆ K₃ → K₄ = {A, B, D, E, Z}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 没有新的可执行超边，停止
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;$K$ 的全部作用就是回答「现在够不够」。最后那一步 $\lbrace D,E \rbrace \to Z$ 需要两个前提，两个都有才能走——&lt;strong&gt;这就是上一版要靠 AND 组才能表达的东西，现在只是尾集大小的问题。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="四条化简"&gt;四条化简
&lt;/h3&gt;&lt;p&gt;有了上面的定义，上一版那些让我别扭的东西可以一条条被证明为多余。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一、AND 组和 OR 组都不需要存在。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;上一版里，同一概念的入边被分组，组内是 AND、组间是 OR，还得维护「一条边可以属于多套方案」这种多对多关系。整套结构在超边表示下是空的。&lt;/p&gt;
&lt;p&gt;$\lvert T(h) \rvert &amp;gt; 1$ 就是 AND，尾集本身就是合取；两条头相同的超边并存就是 OR，它们彼此独立，不需要任何分组结构管理。严格地说，上一版的方案集合 $\mathcal{P}(v)$ 与「头为 $v$ 的超边集合」之间存在双射：一条边由 $(\text{source}, \text{target})$ 唯一标识，所以方案 $P$ 与其源点集一一对应，取 $\Phi(P) = (\lbrace \text{source}(e) : e \in P \rbrace,\ v)$，逆映射把超边展开回逐条边，两者互逆。既然是双射，删掉一边不损失任何信息。&lt;/p&gt;
&lt;p&gt;顺带地，上一版那个「投影边」对象也一起没了——它只是超边在有向图上的展开视图，随时可以重算。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;二、权只能定义在超边上，边级权在数学上无解。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这条正是上一篇结尾那处修正的完整版本。我当时的直觉是权不可能挂在边上，但说不出为什么。反例比我想的干脆：&lt;/p&gt;
&lt;p&gt;$$(\lbrace A,B \rbrace, D, 1), \qquad (\lbrace A \rbrace, D, 5), \qquad (\lbrace B \rbrace, D, 5)$$&lt;/p&gt;
&lt;p&gt;它描述的情形很常见——$A$ 和 $B$ 各自单用都很贵，合起来却有极强的组合效应。若权可以拆到边上，则必须同时满足&lt;/p&gt;
&lt;p&gt;$$w_e(A \to D) + w_e(B \to D) = 1, \qquad w_e(A \to D) = 5, \qquad w_e(B \to D) = 5$$&lt;/p&gt;
&lt;p&gt;也就是 $10 = 1$。这个方程组的最小二乘残差是 $5.196 &amp;gt; 0$，确认无解（&lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/verification/verify_v6b.py#L15" target="_blank" rel="noopener"
&gt;&lt;code&gt;test_no_edge_weights&lt;/code&gt;&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;更根本的是，即使不存在竞争方案，把一个整体成本拆成各前提的份额也&lt;strong&gt;没有典范选择&lt;/strong&gt;——任何和等于总数的拆分都同样合法；而一条被两套方案共享的边会被迫同时取两个值。结论是&lt;strong&gt;权和载荷同源&lt;/strong&gt;：二者都是定义在整个推导步骤上的函数。既然同源，「方案」和「边」就没有理由并存为两个对象。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;三、无环公理可以直接删掉。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这正是我前面反思的那条：我只需要教程无环，不需要让知识无环。数学上给出的答案比我预期的更干脆——&lt;strong&gt;这条公理根本不必存在。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;闭包是最小不动点，由 Knaster–Tarski 定理&lt;sup id="fnref1:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;保证存在且唯一，与图里有没有环无关。而循环支撑的点永远不会进入闭包：假设 $A$ 要靠 $B$ 推出、$B$ 又要靠 $A$ 推出，且两者都没有别的来源，那么第一轮扫描时 $A$ 的前提 $B$ 不在集合里，$B$ 的前提 $A$ 也不在，两条超边都不触发；此后集合再没变过，所以永远不会触发。&lt;strong&gt;没有源头的循环不会自己启动&lt;/strong&gt;。同一张图上换个有根的起点，那两个点就都推得出来了（&lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/verification/verify_v6.py#L87" target="_blank" rel="noopener"
&gt;&lt;code&gt;test_cycle_safety&lt;/code&gt;&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;四、载荷退化为不透明字段。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;definition&lt;/code&gt;、&lt;code&gt;question&lt;/code&gt;、&lt;code&gt;answer&lt;/code&gt;、&lt;code&gt;materials&lt;/code&gt; 都不被三个核心算法读取，统一为一个核心层不解释的字段。核心层唯一需要的是：成本 $w$ 是这些载荷的某个函数——这个函数由应用层实现和标定，核心层只接收结果。&lt;/p&gt;
&lt;p&gt;四条合起来，对象数量的变化是：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;维度&lt;/th&gt;
&lt;th&gt;上一版&lt;/th&gt;
&lt;th&gt;现在&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;持久化对象类型&lt;/td&gt;
&lt;td&gt;Concept / DerivationPlan / Derivation，另有 AND / OR 分组&lt;/td&gt;
&lt;td&gt;Point / Hyperedge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AND / OR&lt;/td&gt;
&lt;td&gt;需要专门的分组结构&lt;/td&gt;
&lt;td&gt;尾集大小与同头并存，不是对象&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;模型公理&lt;/td&gt;
&lt;td&gt;无环、禁止递归交集&lt;/td&gt;
&lt;td&gt;无（下面会说交集约束去哪了）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;权的载体&lt;/td&gt;
&lt;td&gt;AND 组&lt;/td&gt;
&lt;td&gt;超边（同一对象）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;顺序机制&lt;/td&gt;
&lt;td&gt;DAG 拓扑序&lt;/td&gt;
&lt;td&gt;可执行序，不依赖无环&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="可达性好环坏环与静默失败"&gt;可达性：好环、坏环与静默失败
&lt;/h3&gt;&lt;p&gt;把超边 $(T, y, w)$ 读作「$\bigwedge_{p \in T} p \Rightarrow y$」，起点集读作事实集，那么闭包恰好就是这个 Horn 程序的唯一最小模型。这不是类比，是同一件事——由此直接继承一个强结论：&lt;strong&gt;可达性判定可在线性时间内完成&lt;/strong&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;，具体是 $O(\sum_h (\lvert T(h) \rvert + 1))$。为每条超边维护一个「未满足前提计数」，某点首次入队时把以它为前提的超边计数减一，减到零即触发。&lt;/p&gt;
&lt;p&gt;这条对应关系也解释了经典 AND/OR 图理论&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;为什么天然适用：AND/OR 图、Horn 子句、有向超图、上下文无关文法的推导，在文献里本来就是同一结构的四种写法&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;。这一版只是选了其中最紧凑的一种当实现基底。&lt;/p&gt;
&lt;p&gt;顺序机制也随之换掉了。上一版用 DAG 的拓扑序给出「合法讲述顺序」，而拓扑序只在无环图上存在。现在改用&lt;strong&gt;可执行序&lt;/strong&gt;：$R$ 的一个排列，使得每一步在它之前那些步骤的结果之上都可执行。闭包的分轮扫描顺手就产出一个，所以任何 Derivation 至少有一个可执行序，且不需要全图无环。&lt;/p&gt;
&lt;p&gt;现在回到我前面说的那个反思：知识里有些环是合理的。数学给出的答案比「允许环」更精确——&lt;strong&gt;它区分了两种环。&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="mermaid"&gt;
flowchart TB
subgraph GOOD[&amp;#34;好环：两条边都是正当推导，互为 OR 路线&amp;#34;]
direction LR
T([&amp;#34;泰勒级数（入口）&amp;#34;]) --&amp;gt; E[&amp;#34;e^ix&amp;#34;]
G([&amp;#34;几何三角（入口）&amp;#34;]) --&amp;gt; SC[&amp;#34;sin/cos&amp;#34;]
E --&amp;gt;|&amp;#34;欧拉公式：取实部虚部&amp;#34;| SC
SC --&amp;gt;|&amp;#34;欧拉公式：反方向&amp;#34;| E
end
subgraph BAD[&amp;#34;坏环：互相定义，整组没有任何外部入口&amp;#34;]
direction LR
L[&amp;#34;线性&amp;#34;] --&amp;gt;|&amp;#34;就是满足叠加&amp;#34;| SP[&amp;#34;叠加原理&amp;#34;]
SP --&amp;gt;|&amp;#34;是线性的性质&amp;#34;| L
end
&lt;/pre&gt;
&lt;p&gt;带泰勒级数进来的学习者能到 $\sin/\cos$，带几何三角进来的能到 $e^{ix}$，两条路都通，&lt;strong&gt;环的存在对谁都没有造成任何阻碍&lt;/strong&gt;。而「线性 $\rightleftarrows$ 叠加原理」这种同义反复，无论学习者已经掌握了什么，两个点永远推不出来。&lt;/p&gt;
&lt;p&gt;所以准确的说法是：&lt;strong&gt;这一版拒绝的不是环，而是没有外部入口的环，并且把判断推迟到有具体查询的时候。&lt;/strong&gt; 上一版的无环公理是全图的结构禁令，会把上面那张图整张拒收，逼作者从 $e^{ix}$ 与 $\sin/\cos$ 之间删掉一条——而删哪条都是在丢弃一条真实的教学路线。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新问题也随之出现：环从语法错误降级成了静默失败。&lt;/strong&gt; 上一版里作者画出一个环会立刻被拒绝，现在它只表现为「目标不可达」，原因不再显然。所以核心层必须补一个诊断接口，把「声称能推出、但那条推导是循环的」点找出来。&lt;/p&gt;
&lt;p&gt;这个诊断比看上去难写。我第一版判据是「假设除它自己以外一切已知，看还能不能推出它」，看着合理，实际上&lt;strong&gt;既误报了正常入口，又漏掉了真正的坏环&lt;/strong&gt;——因为循环里的两个点会互相顶上，把检查骗过去。正确判据是从&lt;strong&gt;入度为零的点&lt;/strong&gt;（图的天然入口）出发算闭包，落在外面的才是悬空点。上面两种环的完整算例、以及错误判据作为反例，都在 &lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/verification/cycle_demo.py" target="_blank" rel="noopener"
&gt;&lt;code&gt;cycle_demo.py&lt;/code&gt;&lt;/a&gt; 里带断言保留着。&lt;/p&gt;
&lt;h3 id="成本一个坏消息和一对界"&gt;成本：一个坏消息和一对界
&lt;/h3&gt;&lt;p&gt;这一节是整个模型里唯一一处必须做有代价取舍的地方。在给出任何口径之前，先把两条公理摆出来，它们不是推出来的而是被假定的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;可加性&lt;/strong&gt;：一条推导的总成本，由各步成本按某种固定规则聚合而成。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;非负性&lt;/strong&gt;：$w \ge 0$。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;两条都不是事实。真实认知成本会被疲劳、干扰、遗忘破坏可加性；而「先学 $A$ 让后学 $B$ 变便宜」这类正迁移本应是负成本，非负性却禁止它——只能改用「新增一条以 $A$ 为前提、权更低的替代超边」来间接表达。&lt;/p&gt;
&lt;p&gt;我上一篇里写过一句当时觉得理所当然的话：&lt;strong&gt;共享的前置推导在同一子图中只计算一次。&lt;/strong&gt; 这句话是整个模型的核心主张，前面「少学反而更慢」那一节里 $X$ 作为多个后续节点的共同前置，正是靠这条才成立。如果复用要重复付费，高压缩率路线这个概念本身就不成立了。&lt;/p&gt;
&lt;p&gt;问题是，这个口径算不出来。看一个具体例子，学习者要学会 $Z$：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;从 A 学到 B 成本 3 ← B 是 D 和 E 共同的前置
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;从 B 学到 D 成本 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;从 B 学到 E 成本 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;D 和 E 一起得到 Z 成本 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;三种算法给出三个不同的数：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;口径&lt;/th&gt;
&lt;th&gt;怎么算&lt;/th&gt;
&lt;th&gt;结果&lt;/th&gt;
&lt;th&gt;对应现实&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;集合成本&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;用到的四步各算一次：$3+1+1+1$&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$B$ 只学一遍。&lt;strong&gt;这是真实的学习成本&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;展开成本&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;摊成一棵树，$D$ 和 $E$ 往回走都要经过 $B$：$(3+1)+(3+1)+1$&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;9&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;假装 $B$ 学了两遍，高估&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;深度成本&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;最长的一条链 $A \to B \to D \to Z$：$3+1+1$&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;可并行推进时的最短完成时间，低估&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;我想要的是 6，但能高效算出来的是 9 和 5。&lt;/p&gt;
&lt;p&gt;原因在于&lt;strong&gt;局部性&lt;/strong&gt;。展开成本和深度成本都能写成一条「只看直接前提」的递推式：&lt;/p&gt;
&lt;p&gt;$$d(y) = \min_h \Big[, w(h) + \sum_{p \in T(h)} d(p) ,\Big], \qquad d(y) = \min_h \Big[, w(h) + \max_{p \in T(h)} d(p) ,\Big]$$&lt;/p&gt;
&lt;p&gt;要算 $Z$ 的成本，只需知道 $D$ 和 $E$ 各自的成本，再加最后一步。这种局部性让 Dijkstra 式的贪心成立——正是 Knuth 在 1977 年推广 Dijkstra 算法时刻画的&lt;strong&gt;上位函数&lt;/strong&gt;条件&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt;：聚合结果对每个自变量单调不减，且不小于任何一个自变量。&lt;/p&gt;
&lt;p&gt;集合成本没有这个性质。$D$ 那一支到底要不要为 $B$ 付钱，&lt;strong&gt;取决于 $E$ 那一支是不是已经买过了&lt;/strong&gt;。成本不再是各分支成本的函数，而依赖于全局已经选了哪些边，贪心就此失效。&lt;/p&gt;
&lt;p&gt;而且不只是「暂时没想到好算法」，它是 NP-hard 的。由集合覆盖归约：起点 $z$、目标 $t$，每个子集 $V_j$ 对应一个点 $x_j$ 与超边 $(\lbrace z \rbrace, x_j, 1)$（选用这个子集要花 1），元素 $q_i \in V_j$ 时有 $(\lbrace x_j \rbrace, q_i, 0)$（免费得到它覆盖的元素），最后一条 $(\lbrace q_1,\dots,q_n \rbrace, t, 0)$（凑齐全部元素才能到 $t$）。要到达 $t$ 就必须得到全部 $q_i$，因而所选 $x_j$ 必须覆盖全集，总成本恰好等于所选子集的个数——于是「用最低成本到达 $t$」和「用最少的子集盖住全集」是同一个问题。而集合覆盖不但 NP-hard，还不可在 $(1-o(1))\ln n$ 因子内近似&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt;，&lt;strong&gt;连打折的算法都不存在&lt;/strong&gt;。这个归约我在 60 组随机实例上对拍过暴力集合覆盖，结果精确相等（&lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/verification/verify_v6.py#L176" target="_blank" rel="noopener"
&gt;&lt;code&gt;test_reduction&lt;/code&gt;&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;文献里其实早有这个现象的一般描述：超路径的求解代价随所选度量，可以从线性时间一直变化到 NP-hard&lt;sup id="fnref:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt;。我只是撞上了这个谱坏的一端。&lt;/p&gt;
&lt;p&gt;难受完之后我发现，这三个数之间有关系。设权非负，则&lt;/p&gt;
&lt;p&gt;$$d_{\text{depth}}(S,t) \ \le\ C^{*}&lt;em&gt;{\text{set}}(S,t) \ \le\ d&lt;/em&gt;{\text{tree}}(S,t)$$&lt;/p&gt;
&lt;p&gt;右边：取展开成本最优解所用的超边&lt;strong&gt;多重集&lt;/strong&gt;，它去重后的支撑集是一个合法解，而把重复计的账改成只计一次，总数只会变小或不变。左边：非负权下，最优解上的最长链至多用到互不相同的超边，所以链长不超过全部权之和。当所有超边都只有一个前提时，推导退化成一条链，三者重合于经典最短路径。这对不等式我在 1753 组随机可达查询上用穷举法逐一对拍过，其中 67 组出现严格不等，说明这对界不是平凡重合（&lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/verification/verify_v6.py#L109" target="_blank" rel="noopener"
&gt;&lt;code&gt;test_bracket&lt;/code&gt;&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;两头都是多项式可算的，于是求解策略就有了：&lt;strong&gt;先算两个端点，若相等则中间那个 NP-hard 的量被夹死，直接返回、根本不用搜索；不相等才启动搜索&lt;/strong&gt;，用展开成本的解当初始上界、深度成本当可采纳启发；超预算就返回区间并标记未收敛，绝不用展开成本冒充精确值。这套策略实现在 &lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/derivon_core.py" target="_blank" rel="noopener"
&gt;&lt;code&gt;min_set_cost&lt;/code&gt;&lt;/a&gt; 里，并用穷举当预言机对拍过 1325 组随机查询，结果完全一致（&lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/verification/verify_core.py" target="_blank" rel="noopener"
&gt;&lt;code&gt;verify_core.py&lt;/code&gt;&lt;/a&gt;）——分支定界快但复杂，穷举慢但不容易写错，两者对拍是唯一能防止「快但错」的东西。&lt;/p&gt;
&lt;p&gt;这里有一点值得单独强调：&lt;strong&gt;展开成本不只是个数字，它对应一条真实可走的推导。&lt;/strong&gt; 所以这不是「算不出最优就没边」，而是一个货真价实的 anytime 算法：任何时刻都有一条可推荐路径，外加一个经过证明的「最多差多少」。对一个实际产品来说，这已经够用了——学习者需要的是一条好路线，不是一个最优性证明。&lt;/p&gt;
&lt;p&gt;还有一个我没预料到的副产品：&lt;strong&gt;区间宽度 $d_{\text{tree}} - d_{\text{depth}}$ 本身就是一个可观测量&lt;/strong&gt;，它度量的正是当前知识图里共享结构的强度。如果这个宽度恒等于零，说明图退化成了一堆互不复用的线性教程——这恰好就是前面「少学反而更慢」那一节所批判的教纲形态。&lt;strong&gt;一个知识图质量的诊断指标，从一个纯粹的算法困难里掉了出来。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;那么这个区间到底有多紧？夹逼定理只保证区间存在，没说它有多宽。而宽度直接决定了上面那套策略到底值不值钱，所以我又写了一个脚本实测（&lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/verification/bracket_practice.py" target="_blank" rel="noopener"
&gt;&lt;code&gt;bracket_practice.py&lt;/code&gt;&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一组：随机超图。&lt;/strong&gt; 每组几百次可达查询，统计有多少比例需要真的启动搜索：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;尾集上限&lt;/th&gt;
&lt;th&gt;样本&lt;/th&gt;
&lt;th&gt;需搜索占比&lt;/th&gt;
&lt;th&gt;平均宽度&lt;/th&gt;
&lt;th&gt;上界高估倍数&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;678&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;0.00&lt;/td&gt;
&lt;td&gt;1.00x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;565&lt;/td&gt;
&lt;td&gt;2%&lt;/td&gt;
&lt;td&gt;0.09&lt;/td&gt;
&lt;td&gt;1.39x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;467&lt;/td&gt;
&lt;td&gt;3%&lt;/td&gt;
&lt;td&gt;0.10&lt;/td&gt;
&lt;td&gt;1.34x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;401&lt;/td&gt;
&lt;td&gt;1%&lt;/td&gt;
&lt;td&gt;0.06&lt;/td&gt;
&lt;td&gt;1.33x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;也就是说，&lt;strong&gt;97~99% 的查询里廉价上界恰好就是精确解&lt;/strong&gt;，那个 NP-hard 的量被直接夹死，根本不需要搜索。尾集上限为 1 时宽度恒为零，因为没有汇合就没有共享。&lt;/p&gt;
&lt;p&gt;但这组数据不能直接拿来乐观，因为&lt;strong&gt;随机图恰恰不具备我们关心的结构&lt;/strong&gt;。随机采样很少产生「一个点同时是多个分支的前置、而那些分支稍后又汇合」这种形态。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二组：刻意构造的枢纽结构。&lt;/strong&gt; 一个高压缩率中间概念 $X$ 被 $k$ 个分支复用，目标需要全部分支——&lt;strong&gt;正是前面「少学反而更慢」那一节鼓励的那种形态&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;分支数 $k$&lt;/th&gt;
&lt;th&gt;枢纽成本&lt;/th&gt;
&lt;th&gt;$d_{\text{depth}}$&lt;/th&gt;
&lt;th&gt;$C^{*}_{\text{set}}$&lt;/th&gt;
&lt;th&gt;$d_{\text{tree}}$&lt;/th&gt;
&lt;th&gt;宽度&lt;/th&gt;
&lt;th&gt;上界高估&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1.40x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;2.33x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;2.00x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;46&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;3.29x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;规律很清楚：&lt;strong&gt;分支越多、枢纽越贵，廉价上界越离谱。&lt;/strong&gt; 而这两个量恰恰就是「这个中间概念抽象得越好」的表现。&lt;/p&gt;
&lt;p&gt;于是得到一个反直觉的结论：&lt;strong&gt;区间宽度同时是「图质量指标」和「问题难度指标」，两者是同一个量。&lt;/strong&gt; 图越接近我们想要的样子——高复用、多条 OR 路线——它就越靠近难解那一端。&lt;/p&gt;
&lt;p&gt;所以「等规模大了再说」这个安慰实际上是「等图还足够松散、树状」，而产品做成功恰好把图推向反方向。这不是现在要担心的事，但值得记一笔：&lt;strong&gt;别指望「图小就没事」，该指望的是「分支定界在这类枢纽结构上跑得动」&lt;/strong&gt;——后者是可以实测的，不是猜的。&lt;/p&gt;
&lt;h3 id="表达力的边界"&gt;表达力的边界
&lt;/h3&gt;&lt;p&gt;定义立好之后，可以反过来问：这个对象能表达什么，不能表达什么。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;单头够不够。&lt;/strong&gt; B-超图规定每条超边只有一个头。若想表达「$T$ 共同推出 $y_1 \dots y_k$，总成本 $w$」，可以引入中间点 $p^{\star}$，写成 $(T, p^{\star}, w)$ 加上若干条零权的 $(\lbrace p^{\star} \rbrace, y_i, 0)$。这个编码在可达性和集合成本下保真，&lt;strong&gt;但在展开成本下不保真&lt;/strong&gt;——后者会把 $p^{\star}$ 按头的个数重复计费（实测：集合成本 4，展开成本 8，见 &lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/verification/verify_v6.py#L199" target="_blank" rel="noopener"
&gt;&lt;code&gt;test_multihead&lt;/code&gt;&lt;/a&gt;）。所以核心层维持单头，代价是多头场景下上界会变松。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;半环推广。&lt;/strong&gt; 把 $(\min, +)$ 换成别的半环，同一套结构立刻覆盖更多问题&lt;sup id="fnref:8"&gt;&lt;a href="#fn:8" class="footnote-ref" role="doc-noteref"&gt;8&lt;/a&gt;&lt;/sup&gt;：布尔半环给出纯可达性，计数半环给出推导条数。但广义 Dijkstra 只对上位函数成立，其他情形要退回不动点迭代。这一步我没走——首版把权类型参数化但只实现 $(\min, +)$ 就够了，过早抽象没有收益。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;计数是硬的。&lt;/strong&gt; 上一篇我提过一个「理解倍率」的设想：每完成一条不同的有效路线就增加 100% 的理解度。现在可以判它死刑了——统计极小推导的个数，稍作修改就能归约到统计最小集合覆盖的个数，属计数困难问题，而且极小推导的数量本身可以随图规模指数增长。&lt;strong&gt;理解倍率不能定义为路线计数&lt;/strong&gt;，只能换成可控的替代量，并明确标注为工程近似。&lt;/p&gt;
&lt;h3 id="模块层封装的真实代价"&gt;模块层：封装的真实代价
&lt;/h3&gt;&lt;p&gt;最后是我前面反思里的第二条：概念不是可以随意拆分和封装的。这一节给出它到底难在哪。&lt;/p&gt;
&lt;p&gt;先说一个结构上的好消息：&lt;strong&gt;封装整体被移出了核心层。&lt;/strong&gt; 核心层的三个算法都不读取包含关系，而折叠本质上是核心图上的商结构，可以独立取舍。移出之后有个直接收益——核心层不再背负「禁止递归交集」这条公理，因为核心层根本没有包含关系。&lt;/p&gt;
&lt;p&gt;折叠的定义是：把模块内部的一堆点整个捏成一个点，对外只留下一张&lt;strong&gt;价目表&lt;/strong&gt;——从哪几组入口进来、各要花多少钱。这里超图表示自动吃掉了上一版的一项条件：入口的 AND/OR 组合语义不需要专门保留，因为边界本来就是一组超边。&lt;/p&gt;
&lt;p&gt;代价是那个爆炸原样出现了：&lt;strong&gt;边界超边的条数等于边界公式的析取范式项数。&lt;/strong&gt; 取 $\bigwedge_{i=1}^{k}(I_{i,1} \vee I_{i,2})$，合取式仅 $2k$ 个文字，析取范式却有 $2^{k}$ 项——$k = 12$ 时需要 4096 条边界超边。这不是实现瑕疵，而是超图只能表达析取范式这一事实的固有代价。所以折叠必须设硬预算，超限就拒绝折叠、让子图保持展开。&lt;/p&gt;
&lt;p&gt;更有意思的是，上一版里我凭直觉立的「禁止递归交集」公理，现在有了确切身份。我做了三组实测：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;情形&lt;/th&gt;
&lt;th&gt;实测&lt;/th&gt;
&lt;th&gt;结论&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;单出口成立，模块内部超边不被外部复用&lt;/td&gt;
&lt;td&gt;精确 7，折叠后 7&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;保真&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;外部直接消费模块内部点&lt;/td&gt;
&lt;td&gt;精确 5；丢弃该外部边则目标不可达，改指向根则得 7&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;可推导性丢失&lt;/strong&gt;，单出口是必要条件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;两个模块共用内部超边&lt;/td&gt;
&lt;td&gt;精确 12，折叠后 22&lt;/td&gt;
&lt;td&gt;共享前置被&lt;strong&gt;重复计费&lt;/strong&gt;，禁止交集是必要条件&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;三组的完整算例见 &lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/verification/verify_v6b.py#L63" target="_blank" rel="noopener"
&gt;&lt;code&gt;test_folding&lt;/code&gt;&lt;/a&gt;，析取范式规模的增长见 &lt;a class="link" href="https://github.com/derivon-research/paper/blob/main/verification/verify_v6b.py#L82" target="_blank" rel="noopener"
&gt;&lt;code&gt;test_dnf_blowup&lt;/code&gt;&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;也就是说，&lt;strong&gt;「禁止递归交集」不是一条随意的工程公理，而是折叠在集合成本下保真的必要条件。&lt;/strong&gt; 同时它的适用范围被大幅收窄了：&lt;strong&gt;它只约束模块层的折叠操作，不约束核心图。&lt;/strong&gt; 核心层的点可以任意共享前提、被任意多处引用，因为核心层压根不做折叠。上一版把它写成全局公理，是分层不清导致的过度约束。&lt;/p&gt;
&lt;p&gt;图论里有个严格但很强的参考条件叫模块分解&lt;sup id="fnref:9"&gt;&lt;a href="#fn:9" class="footnote-ref" role="doc-noteref"&gt;9&lt;/a&gt;&lt;/sup&gt;：一个节点集合要能被商图节点无损替代，每个外部节点必须要么连接它的全部节点、要么一个也不连。我希望能封装的任意子图通常不满足这个条件，所以不能声称折叠在图论意义上天然无损。结论是保守的：先只提供折叠的&lt;strong&gt;校验器&lt;/strong&gt;（判定单出口、无部分交集、析取范式规模），把折叠本身留到核心求解器稳定之后。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;七节走完，回头对账。上一版三个最严重的问题都有了着落：&lt;strong&gt;没有专注数学本身&lt;/strong&gt;，靠核心层准入判据解决；&lt;strong&gt;AND / OR 像补丁&lt;/strong&gt;，被双射证明为可完全消除；&lt;strong&gt;无环限制表达上限&lt;/strong&gt;，被最小不动点语义证明为多余，而且新语义比原来更宽松——好环得以保留，坏环自动失效。&lt;/p&gt;
&lt;p&gt;但账不是白结的。新问题一并列出来：&lt;strong&gt;语义正确的成本口径 NP-hard 且不可近似&lt;/strong&gt;，只能靠一对上下界夹逼；&lt;strong&gt;环从语法错误降级为静默失败&lt;/strong&gt;，必须补诊断层，而诊断判据本身容易写错；&lt;strong&gt;理解倍率不能定义为路线计数&lt;/strong&gt;；&lt;strong&gt;封装的边界公式可能指数爆炸&lt;/strong&gt;；&lt;strong&gt;尾头相同但载荷不同的超边会被静默合并&lt;/strong&gt;，超边必须带稳定身份；以及上一节那条反直觉的——&lt;strong&gt;图越接近想要的样子，就越靠近难解那一端&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;至于上一篇里我当成头号未决问题的那个——&lt;strong&gt;权到底用什么可观测量来度量&lt;/strong&gt;——现在回头看，我当时把它放错了层。&lt;/p&gt;
&lt;p&gt;按前面立的准入判据，核心层只&lt;strong&gt;接收&lt;/strong&gt; $w$、不产生它，那么「$w$ 怎么算出来」按定义就在应用层。我却把它写成「模型的头号未决问题」，等于一边说它不属于模型、一边又说它是模型最大的洞。&lt;strong&gt;模型本身是完整的，它不需要关心 $w$ 从哪来。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;应用层可选的方法很多：测实际有效学习时长；让 AI 按统一 Scale 打分；最朴素的直接数推导所需解释的文本长度。它们都能产出数字，落到实现层选一个即可。&lt;/p&gt;
&lt;p&gt;真正剩下的不是「用什么可观测量」，而是「&lt;strong&gt;怎么让这些数加起来仍然有意义&lt;/strong&gt;」——模型要对它们求和、并跨路线比较总和，这要求它们落在同一个可加的标度上。学习时长会被疲劳、动机、中断污染，而且你只观测得到走过的那条路，看不到反事实；AI 打分的分数通常非线性，「7 分」不是「1 分」的七倍；文本长度天然可加、但只是代理量，而且恰好撞上了上一篇警告过的陷阱：画一条没有论证的直线，文本很短、权很低，实际上根本没有推导。&lt;/p&gt;
&lt;p&gt;但这件事自带反馈闭环：预测成本和实际结果可以对账，所以 $w$ 是可以被学出来、校准出来的。&lt;strong&gt;这是个机器学习问题，不是数学缺口。&lt;/strong&gt; 冷启动用文本长度或 AI 打分当先验就够。&lt;/p&gt;
&lt;p&gt;所以它应该被降级为：&lt;strong&gt;应用层的标定问题，有明确的解决路径&lt;/strong&gt;。模型那一层现在是闭合的。&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;A. Tarski. &lt;em&gt;A lattice-theoretical fixpoint theorem and its applications&lt;/em&gt;. Pacific Journal of Mathematics, 5(2):285–309, 1955. 保证单调算子在完全格上的最小不动点存在且唯一，是闭包良定义、且循环支撑自动失效的依据。&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref1:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;W. F. Dowling and J. H. Gallier. &lt;em&gt;Linear-time algorithms for testing the satisfiability of propositional Horn formulae&lt;/em&gt;. Journal of Logic Programming, 1(3):267–284, 1984. 给出 Horn 公式可满足性的线性时间算法，本文的可达性判定即其计数式前向链接实现。&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;A. Martelli and U. Montanari. &lt;em&gt;Additive AND/OR graphs&lt;/em&gt;. IJCAI 1973, pp. 1–11. 经典 AND/OR 图求解：AND 节点要求所有子问题共同解决，OR 节点从替代方案中选择，解是最低成本的解图而非路径。&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;G. Gallo, G. Longo, S. Pallottino, and S. Nguyen. &lt;em&gt;Directed hypergraphs and applications&lt;/em&gt;. Discrete Applied Mathematics, 42(2–3):177–201, 1993. 有向超图的系统性处理，包括连通性、路径与割的定义，以及与命题逻辑、AND/OR 图的对应关系。&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;D. E. Knuth. &lt;em&gt;A generalization of Dijkstra&amp;rsquo;s algorithm&lt;/em&gt;. Information Processing Letters, 6(1):1–5, 1977. 提出上位函数（superior function）条件，把 Dijkstra 推广到超图上的最小成本推导，是展开成本与深度成本可高效求解的依据。&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;U. Feige. &lt;em&gt;A threshold of ln n for approximating set cover&lt;/em&gt;. Journal of the ACM, 45(4):634–652, 1998. 证明 $(1-o(1))\ln n$ 是集合覆盖近似的下界门槛，本文集合成本的不可近似性由归约传递而来。&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:7"&gt;
&lt;p&gt;G. Ausiello, G. F. Italiano, and U. Nanni. &lt;em&gt;Hypergraph traversal revisited: Cost measures and dynamic algorithms&lt;/em&gt;. MFCS 1998, LNCS 1450. 指出超路径的最优化代价随所选度量函数，可以从线性时间一直变化到 NP-hard。&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:8"&gt;
&lt;p&gt;J. Goodman. &lt;em&gt;Semiring parsing&lt;/em&gt;. Computational Linguistics, 25(4):573–605, 1999. 把推导的聚合统一到半环上，布尔半环给出可达性、$(\min,+)$ 给出最短推导、计数半环给出推导数量。&amp;#160;&lt;a href="#fnref:8" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:9"&gt;
&lt;p&gt;M. Habib and C. Paul. &lt;em&gt;A survey of the algorithmic aspects of modular decomposition&lt;/em&gt;. Computer Science Review, 4(1):41–59, 2010. 模块分解给出「子图可被商图节点无损替代」的严格条件，本文用它说明任意子图的折叠不能默认无损。&amp;#160;&lt;a href="#fnref:9" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>[outdated] 万物皆概念：如何最大化学习速度？</title><link>https://v3n0.com/post/2026/everything-is-concept/</link><pubDate>Wed, 19 Aug 2026 01:32:48 +0800</pubDate><guid>https://v3n0.com/post/2026/everything-is-concept/</guid><description>&lt;p&gt;我们怎样才能最大化学习速度？&lt;/p&gt;
&lt;p&gt;我最初对这个问题产生兴趣，源于我做后端启蒙直播课的经历。在教学过程中，我发现自己对于不管是对于自身的学习，还是对于教学，都乐在其中。后来，在跟随我的导师学习“信号与系统”这门通常被认为难度较高的工科基础课时，我的一些观察得到了进一步印证。&lt;/p&gt;
&lt;p&gt;我在学校基本不上课，期末才速通，但信号与系统是真的黔驴技穷。我的导师通过引入算子理论和希尔伯特空间，以通过考试为目标，重新构造了给我定制的教学路径，教学顺序和学校课程有非常大差异。结果，一门通常需要学习一学期还不一定能过的课程，在这一教学路径下我只用了 3 天的学习时间，从什么是信号都不知道的程度，最后实现了在期末考试中考到了 60 分的水平，最终成绩 71 分。&lt;/p&gt;
&lt;p&gt;记忆犹新的是，我甚至拿到试卷才知道信号与系统用英语考，最后五分钟才发现试卷有一整面没被我搓开，那两道大题只写了五分钟，几乎只拿了前几步的分。&lt;/p&gt;
&lt;p&gt;更令人惊讶的是，在他进一步改进教学线路，以集合论为起点之后，另一位有一定数学和理论物理基础的同学仅用半天就建立了对这门课主干理论的整体理解，并能够进入后续实践。这套“集合论版本”的教程实实在在地以集合论为起点，逐步推演到算子谱定理，再把卷积、微分等运算理解为在另一组基下的乘法，由此统一理解信号与系统中的各种变换。他并不以通过考试为目标，短短时间后已经能够在团队中编写高效的硬件优化算法。&lt;/p&gt;
&lt;p&gt;这些经历让我得出一个暂时性的结论：&lt;strong&gt;学习路径才是学习速度的关键因素。它的影响可能远大于个人能力、同一学习路径上的教师教学能力、或其他的什么因素。学习路径才是学习过程中的主要矛盾。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我在上一篇相关文章&lt;a class="link" href="https://v3n0.com/post/2026/learning-method/" target="_blank" rel="noopener"
&gt;《逃离应试教育，重新学会怎么思考》&lt;/a&gt;里提出，学习一个知识体系，本质上是在寻找它的“最小生成元 + 生成规则”。但那个说法仍然停留在方法论层面。这篇文章想再向前走一步：能否把学习路径变成一个可以被建模、计算和优化的问题？&lt;/p&gt;
&lt;p&gt;基于这一观察，我最终构思了一个核心问题：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我们如何从学习者已经掌握的概念出发，找到能够推出目标概念定义的最低成本学习路线？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如果将概念视为点、概念之间的推导视为边，那么：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;给定学习者已掌握的概念和目标概念，可以计算一张满足全部必要条件的最低成本推导子图。&lt;/li&gt;
&lt;li&gt;当知识图中加入新的概念和有效推导时，可以重新计算可选路线，进一步压缩学习成本。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这篇文章将围绕这一核心逻辑展开，尝试讨论如何通过数据建模和路径优化，实现学习效率的飞跃。&lt;/p&gt;
&lt;p&gt;目前它仍处于理论思考阶段，本人也并非有专业的数学素养，有许多定义尚不严密，也有待读者批评。下面我们进入正文。&lt;/p&gt;
&lt;h2 id="我想做的产品"&gt;我想做的产品
&lt;/h2&gt;&lt;p&gt;上面提出的问题并不只是这篇文章中的理论假设。我正在尝试把这套思路做成一个产品，目前仍处于开发初期。后文从 v0 到 v5 的模型演进，正是这个产品核心数据模型的演进。&lt;/p&gt;
&lt;p&gt;我想做的是一套让知识能够被共同建模、共同教学、共同验证的基础设施。它首先要同时降低三件事的成本：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;帮助有教学意愿的人，用更低的成本写出更好的教程。&lt;/strong&gt; 教程作者不必从一页空白文档开始线性写作，而可以复用已有概念，以及推导边所携带的理解材料，把精力放在真正缺失或高成本的推导上。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;帮助学习者用更低的成本学习一个目标概念。&lt;/strong&gt; 系统根据学习者已经掌握的概念，即时生成通向目标概念的最低成本学习路线，而不是让所有人从同一份固定教程的第一页开始。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;帮助任何人在记录和梳理知识时，同时创作教程。&lt;/strong&gt; 一个人写下概念的定义、它解决的问题以及自己如何从旧概念抵达它时，实际上已经在贡献教程节点和推导边，而不只是在保存一份私人笔记。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这三件事可以形成一个闭环：&lt;/p&gt;
&lt;pre class="mermaid"&gt;
flowchart TB
A[记录和梳理个人知识] --&amp;gt; B[形成概念与推导]
B --&amp;gt; C[按学习者状态生成路线]
C --&amp;gt; D[学习者沿路线学习]
D --&amp;gt; E[产生理解与验证证据]
E --&amp;gt; F[发现缺失或高成本的边]
F --&amp;gt; B
&lt;/pre&gt;
&lt;script type="module"&gt;
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11.14.0/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true, theme: 'neutral' });
&lt;/script&gt;
&lt;p&gt;如果这个闭环能够实现，学习者面对的教程就不再是传统教学方式中写死的教纲内容。我们可以随时根据整个知识体系，针对学生的当前理解状态以及学习目标，生成一条定制化的路线。学习者的卡点、回答和实践结果会成为反馈，系统需要据此识别哪些边经常失败、哪些概念缺少前置条件、哪些新路线确实降低了学习成本，再让作者、学习者或 Agent 继续补充和优化。&lt;/p&gt;
&lt;p&gt;在我最终的愿景中，它能形成一种新一代的教育体系：教程的生产能力不再被少数教育机构垄断，而是分布给社会中所有愿意学习、解释、记录和验证知识的人。群众消费教程的同时，也在使用教程的过程中共同生产和改进教程。&lt;/p&gt;
&lt;p&gt;要让这个闭环成立，个人的笔记、知识导图，和教程所使用的学习路线、章节划分，就不能继续使用彼此割裂的数据结构。它们必须能够被同一个模型表达。这是我最近总结出的模型的出发点。&lt;/p&gt;
&lt;h2 id="万物皆概念"&gt;万物皆概念
&lt;/h2&gt;&lt;h3 id="只有一种对象概念"&gt;只有一种对象：概念
&lt;/h3&gt;&lt;p&gt;要计算学习路径，首先必须回答什么是知识体系里的“点”。&lt;/p&gt;
&lt;p&gt;我最初仍然沿用了课程、章节、概念、问题等传统层级。但继续推演后会发现，这种分层并不自洽：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一门课程可以被拆成若干章节；&lt;/li&gt;
&lt;li&gt;一个章节可以被拆成若干概念；&lt;/li&gt;
&lt;li&gt;一个足够大的概念同样需要一整套教程；&lt;/li&gt;
&lt;li&gt;一门课程本身也可以被视作一个更大的概念。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;既然“课程”“章节”和“概念”都可以继续拆分，也都可以作为更大讨论对象的一部分，那么它们在数据结构上并没有本质区别。因此，与其维护一套固定层级，不如只保留一种对象：&lt;strong&gt;概念&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这里的概念不是一个术语或标签，而是一条客观的、默认成立的定义或陈述。例如“傅里叶变换”是一个概念，“信号与系统”也是一个概念；后者可以继续展开为一张以自身定义为目标、由多个子概念及其推导关系构成的知识图。&lt;/p&gt;
&lt;p&gt;任何概念都同时具有两种性质：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;它可以和其他概念组合，在满足封装条件时形成一个更大的概念。&lt;/li&gt;
&lt;li&gt;它可以被继续展开，记录一张以它为目标、包含一条或多条有效推导路线的有向无环图。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此，“万物皆概念”并不是说所有东西都要被塞进同一个扁平列表，而是说：&lt;strong&gt;知识体系中的每一层都使用同一种递归结构。&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Concept
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── definition # 这个概念最终应当能够被重新推导出的定义
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── children[] # 内部推导图引用的直接子概念
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── derivations[] # 子概念之间的推导边
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── derivation_plans[] # 由若干入边组成的推导方案
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Derivation
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── source
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── target
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── question # 为什么需要从 source 推进到 target
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── answer # 完成这一步的推导和论证
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── materials[] # 帮助学习者完成这条推导的材料
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里唯一的知识节点类型仍然是概念。&lt;code&gt;Derivation&lt;/code&gt; 是概念之间的关系，&lt;code&gt;derivation_plans&lt;/code&gt; 则是对若干条边的组合，不是另一种知识节点。&lt;/p&gt;
&lt;p&gt;子概念应当使用引用，而不是直接内嵌。为了让每个概念在所属知识体系中拥有确定的递归位置，本文暂时增加一条强约束：同一知识体系内，递归概念之间禁止部分交集；除父概念完整包含子概念的情况外，不同递归分支必须彼此分离。如果两个递归结构必须发生交集，暂时把它们放进不同的知识体系。这是一条为了换取结构稳定性而引入的模型公理，不是知识天然满足的事实；它的收益和代价将在文末继续讨论。&lt;/p&gt;
&lt;p&gt;理解材料明确属于推导边，而不属于概念节点。概念陈述“是什么”，材料则服务于“如何从一个概念推导到另一个概念”；同一个目标概念可以由不同路线抵达，每条路线需要的解释和证据也可能不同。&lt;/p&gt;
&lt;h3 id="边是概念之间的推导"&gt;边是概念之间的推导
&lt;/h3&gt;&lt;p&gt;如果节点是概念，那么边是什么？&lt;/p&gt;
&lt;p&gt;我最初把边称为 Prompt，也就是“进入下一个概念的问题引入”。但这一定义并不完整。如果边只提出问题，却不包含如何回答问题，那么它仍然没有说明两个概念之间为什么能够连接。&lt;/p&gt;
&lt;p&gt;因此，一条从 $a$ 指向 $b$ 的边，应当表示&lt;strong&gt;概念 $a$ 对推导概念 $b$ 所作的贡献&lt;/strong&gt;。当它单独构成一套推导方案时，这条边承载从 $a$ 到 $b$ 的完整过程；当它属于一个 AND 方案时，多条边共同构成推出 $b$ 的完整过程。每条边至少包含三部分：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;问题引入&lt;/strong&gt;：旧概念遇到了什么局限，或者现实中出现了什么新问题？&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;问题解答&lt;/strong&gt;：通过什么论证、构造或抽象，可以从旧概念得到新概念？&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;理解材料&lt;/strong&gt;：为了完成这一步推导，可以阅读、观察、操作或验证什么？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;例如，“行列式”不应该通过“把这一串运算命名为什么”来引入。这只是在复述定义，没有推进认识。更合理的边可能是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我们需要判断一个线性变换是否把空间压扁，也就是它是否可逆。能否构造一个在行变换下行为明确、又能表示有向体积缩放的标量？由这一需求构造出行列式。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;一条合理的边通常至少满足以下一种条件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;解决前一个概念的局限；&lt;/li&gt;
&lt;li&gt;触碰前一个概念的表达边界；&lt;/li&gt;
&lt;li&gt;回答现实中遇到的具体问题；&lt;/li&gt;
&lt;li&gt;将若干重复出现的推理压缩为一个可复用概念。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这也为“新增边”设置了约束。我们不能为了让图上的距离变短，就画一条没有论证的直线。&lt;strong&gt;边的长度可以短，但边所承载的推导不能被省略。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="把学习成本写成有效推导子图的成本"&gt;把学习成本写成有效推导子图的成本
&lt;/h3&gt;&lt;p&gt;设学习者已经掌握的概念集合为 $S$，目标概念为 $t$。记 $\mathcal{R}(S,t)$ 为所有能够从 $S$ 推出 $t$ 的有效推导子图集合。每个 $R \in \mathcal{R}(S,t)$ 都必须递归选择一套 OR 方案，并完整包含该方案内的全部 AND 边；递归遇到 $S$ 中已经掌握的概念时停止。&lt;/p&gt;
&lt;p&gt;在无权模型中，可以先把一条路线的结构成本定义为其中包含的推导边数：&lt;/p&gt;
&lt;p&gt;$$
C_0(R) = |E_R|
$$&lt;/p&gt;
&lt;p&gt;于是当前知识图中的最低结构成本为：&lt;/p&gt;
&lt;p&gt;$$
C_0^*(S,t) = \min_{R \in \mathcal{R}(S,t)} |E_R|
$$&lt;/p&gt;
&lt;p&gt;若每条边有不同成本，则可以把边权定义为完成该推导所需的时间、认知负荷或材料长度：&lt;/p&gt;
&lt;p&gt;$$
C_u^*(S,t) = \min_{R \in \mathcal{R}(S,t)} \sum_{e \in E_R} w_u(e)
$$&lt;/p&gt;
&lt;p&gt;这里的 $w_u(e)$ 是学习者 $u$ 完成推导边 $e$ 的成本，共享的前置推导在同一子图中只计算一次。当所有推导方案都只有一条边时，有效推导子图退化成普通路径，这个公式也就退化成通常的最短路径问题。&lt;/p&gt;
&lt;p&gt;因此，本文继续使用“最短学习路径”这个直观说法，但严格的求解对象应当是&lt;strong&gt;最低成本有效推导子图&lt;/strong&gt;。它的任意拓扑序都可以形成一种合法讲述顺序；尤其对于同一个 AND 方案中的独立前置分支，先学习哪一个不会改变路线的成立性和总成本。&lt;/p&gt;
&lt;h3 id="一个概念可以被理解多次"&gt;一个概念可以被理解多次
&lt;/h3&gt;&lt;p&gt;同一个定义可能由多条不同路线推出，理解并不必在第一次抵达后停止。&lt;/p&gt;
&lt;p&gt;本文把理解的最终判据定义为：&lt;strong&gt;学习者完成一张有效推导子图后，能够重新推出目标概念的定义&lt;/strong&gt;。但“能够推出”仍然需要证据，不能由图上的可达性直接替代。对知识的深度理解，是解决真实问题的前提；而能否解决真实问题，才是本文所讨论的学习路径最终要优化的目标。&lt;/p&gt;
&lt;p&gt;一个可能的处理方式，是为每个概念维护置信度 $m_u(c) \in [0,1]$，并根据回答、实践、遗忘和迁移表现不断更新。已掌握集合 $S$ 不再是固定集合，而是从连续状态中按当前任务要求投影出来的结果。&lt;/p&gt;
&lt;p&gt;在理论模型之外，或许可以把每完成一条不同的有效路线视为增加 $100\%$ 的理解倍率；如果学习者完整掌握两条路线，又完成第三条路线的一半，就可以记作 $250\%$。这里的百分比不是概念本体的一部分，也不是传统意义上封顶于 $100\%$ 的完成度，只是对“能够从多少条路线重新生成同一概念”的一种投影。这样可能看起来会更有成就感(x&lt;/p&gt;
&lt;p&gt;存在 AND 条件时，这里说的“一条路线”指一张完整的有效推导子图，而不是任取一条忽略其他必要前提的简单路径。同一张推导子图的不同拓扑序只改变一个概念的独立前置条件学习先后顺序，不会增加理解倍率。&lt;/p&gt;
&lt;p&gt;此外，两张有效推导子图可能只相差一条边，也可能使用完全不同的生成规则。前者是否足以在现实意义上算作一条新的理解路线，不能只靠“边集合不相等”来判断。&lt;/p&gt;
&lt;p&gt;这也会影响前文的理解倍率：如果对知识图中的每条简单路径机械计数，少量分支就可能组合出指数级路线，重复或近似相同的推导也会虚增理解程度。这实际上是知识图谱的构建存在问题，最终可能只能靠真正理解知识的人类来评估实际知识图谱的质量如何。更合理的如何判定两条路线的重合度，可能需要进一步讨论。&lt;/p&gt;
&lt;h3 id="通过新增点和边压缩学习路径"&gt;通过新增点和边压缩学习路径
&lt;/h3&gt;&lt;p&gt;在已有图中寻找最低成本有效路线，解决的是“如何使用现有知识结构”。更重要的问题是：&lt;strong&gt;能不能改造知识图本身？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;新的路线不一定来自一条直连目标的边。我们也可以引入一个压缩率更高的中间概念，再建立它与已有概念和目标概念之间的推导边。只要所有路线的并集仍然无环，旧路线和新路线就可以同时保留，成为可随时选择的不同 OR 方案。&lt;/p&gt;
&lt;p&gt;一个高度抽象的统一理论确实能缩短后续路线，但学习这个统一理论本身也需要成本。如果为了少学五条边，先引入一个成本相当于二十条边的新概念，整体上反而更慢。&lt;/p&gt;
&lt;p&gt;因此增加新的点和边时必须计算整张有效推导子图的总成本，而不能只比较边数。所谓“更短路线”必须经过实际学习结果验证，而不能只在图形上看起来更短。&lt;/p&gt;
&lt;p&gt;假设当前最低成本路线包含 18 条边。加入新的概念和推导方案后，另一张有效推导子图只包含 3 条边。现实中的意义就是：学习者不必再依次记忆 18 个彼此松散的终态，而可以通过 3 个高压缩率的生成规则推出同一目标。&lt;/p&gt;
&lt;p&gt;优化过程可以写成一个循环：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;根据学习者已掌握的概念集合 $S$ 和目标 $t$，计算当前最低成本有效推导子图。&lt;/li&gt;
&lt;li&gt;检查其中成本最高、跳跃最大或重复推理最多的位置。&lt;/li&gt;
&lt;li&gt;尝试寻找或构造新的中间概念，并补充相应的推导边与推导方案。&lt;/li&gt;
&lt;li&gt;验证新增推导包含完整论证，AND/OR 关系明确，并且整张图仍然无环。&lt;/li&gt;
&lt;li&gt;将新的点和边加入知识图，重新计算 $C_u^*(S,t)$。&lt;/li&gt;
&lt;li&gt;比较优化前后的学习成本，并通过实际学习结果修正边权。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid"&gt;
flowchart TD
A[给定已掌握概念 S] --&amp;gt; B[选择目标概念 t]
B --&amp;gt; C[计算最低成本有效推导子图]
C --&amp;gt; D{成本是否过高}
D -- 否 --&amp;gt; E[输出一种合法拓扑序]
D -- 是 --&amp;gt; F[定位高成本推导]
F --&amp;gt; G[寻找或构造新的点和边]
G --&amp;gt; H{推导有效且整图无环}
H -- 否 --&amp;gt; F
H -- 是 --&amp;gt; I[加入知识图并更新方案]
I --&amp;gt; C
&lt;/pre&gt;
&lt;p&gt;这也证明了&lt;strong&gt;一条优秀的学习路线用更少的生成规则覆盖更多结论&lt;/strong&gt;。它减少的是重复、悬空和无法复用的认知工作。&lt;/p&gt;
&lt;h3 id="每个概念都可以展开为一张-dag"&gt;每个概念都可以展开为一张 DAG
&lt;/h3&gt;&lt;p&gt;设全体概念构成集合 $C$。对任意概念 $c \in C$，它拥有一个直接子概念集合：&lt;/p&gt;
&lt;p&gt;$$
\operatorname{children}(c) \subseteq C
$$&lt;/p&gt;
&lt;p&gt;这些子概念、目标概念本身以及它们之间的推导关系，构成概念 $c$ 的内部图：&lt;/p&gt;
&lt;p&gt;$$
G_c = (V_c, E_c), \qquad V_c = \operatorname{children}(c) \cup {c}
$$&lt;/p&gt;
&lt;p&gt;这里的 $c$ 是整张内部图最终要推出的目标，而不是它自己的子概念。我暂时要求 $G_c$ 是一张&lt;strong&gt;有向无环图&lt;/strong&gt;，也就是 DAG。&lt;/p&gt;
&lt;p&gt;有向，意味着推导有方向：“已知 A，如何得到 B”和“已知 B，如何得到 A”不是同一个过程。&lt;/p&gt;
&lt;p&gt;无环，意味着不能用待学习的概念反过来证明它自己的前提。一个环通常代表循环论证，或者说明当前概念边界划分得不合理。&lt;/p&gt;
&lt;p&gt;DAG 至少存在一个入度为 0 的节点，因此每个知识图都存在学习入口。但“存在一条指向目标的边”还不足以描述真实推导，因为一个概念可能需要多个前置条件共同推出。&lt;/p&gt;
&lt;p&gt;对任意目标节点 $v$，记它的入边集合为 $\operatorname{In}(v)$。概念 v 的推导方案集合，是它所有非空入边组合中的一部分。因此再定义推导方案集合：&lt;/p&gt;
&lt;p&gt;$$
\mathcal{P}(v) \subseteq 2^{\operatorname{In}(v)} \setminus {\varnothing}
$$&lt;/p&gt;
&lt;p&gt;每个 $P \in \mathcal{P}(v)$ 都是一套能够推出 $v$ 的完整方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同一个 $P$ 内的所有边是 AND，必须全部完成；&lt;/li&gt;
&lt;li&gt;不同的 $P$ 之间是 OR，只需完成其中一套；&lt;/li&gt;
&lt;li&gt;一条边可以同时属于多套方案，因此推导方案与边是多对多关系；&lt;/li&gt;
&lt;li&gt;不需要合取条件的单条入边，可以自然地构成一个只包含自身的方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如，若 $v$ 可以由“$A$ 与 $B$ 共同推出”，也可以单独由 $C$ 推出，那么：&lt;/p&gt;
&lt;p&gt;$$
P_1 = \lbrace A \to v, B \to v \rbrace, \qquad
P_2 = \lbrace C \to v \rbrace
$$&lt;/p&gt;
&lt;p&gt;$$
\mathcal{P}(v) = \lbrace P_1, P_2 \rbrace
$$&lt;/p&gt;
&lt;p&gt;这对应 $(A \land B) \lor C \Rightarrow v$。AND 和 OR 不需要变成新的概念类型，它们只是推导边之间的组合语义。&lt;/p&gt;
&lt;p&gt;当学习者选择一个 AND 方案时，方案内各个前置分支的先后顺序没有语义上的影响。只要各分支分别满足自身依赖，先理解 $A$ 再理解 $B$，或者先理解 $B$ 再理解 $A$，最终都完成同一套推导方案。DAG 的拓扑序只给出合法顺序，不规定独立前置条件之间唯一的学习次序。&lt;/p&gt;
&lt;p&gt;因此，从已有概念到目标概念的一条有效学习路线，在一般情况下并不是图论中的单条简单路径，而是一张递归选择 OR 方案、同时展开其中全部 AND 条件的推导子图。它可以存在多种等价的拓扑排序，并被线性地讲述，但其底层结构仍然可能分叉。&lt;/p&gt;
&lt;p&gt;这里也不再需要预先固定一份教程。给定学习者已掌握的概念和目标概念之后，才从完整知识图中选择一张有效推导子图。真正理解目标概念的判据，是学习者完成其中的必要推导，并最终能够重新推出 $\operatorname{definition}(c)$。&lt;/p&gt;
&lt;p&gt;递归展开必须满足约束。这里所说的“展开”并不是把概念当成一个集合，再声称它在本体上等于所有子概念之和。内部 DAG 表达的是&lt;strong&gt;怎样从若干入口重新生成这个概念&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;设 $I$ 是内部图 $G_c$ 声明的入口条件，$F_{G_c}(I)$ 表示按照图中的 AND/OR 方案完成一张有效推导子图。一次有效展开首先只承诺：&lt;/p&gt;
&lt;p&gt;$$
F_{G_c}(I) \Rightarrow \operatorname{definition}(c)
$$&lt;/p&gt;
&lt;p&gt;也就是说，完成这张图足以推出概念 $c$。反方向不必成立：$c$ 还可以存在其他尚未记录或属于其他知识体系的推导路线。因此，$G_c$ 是一组&lt;strong&gt;充分推导&lt;/strong&gt;，而不是对概念全部含义和全部理解方式的穷尽。&lt;/p&gt;
&lt;p&gt;为了让递归展开不制造错误路线，本文暂时要求它满足以下约束：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;目标固定&lt;/strong&gt;：展开前先有概念 $c$ 及其定义，$c$ 是内部图唯一要推出的目标；不能先框选一批相关知识，再倒过来假定它们自然定义了某个概念。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;节点相关&lt;/strong&gt;：每个内部节点都必须位于某条通向 $c$ 的有效推导中。只与主题相关却不参与推导的材料，不应仅凭相关性成为子概念。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;方案完整&lt;/strong&gt;：任何被选中的 AND 方案都必须包含全部必要边，不能通过拆分概念省略一半前提。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内部闭包&lt;/strong&gt;：除明确声明的入口外，每个内部节点都必须至少拥有一套完整的内部推导方案；所有外部假设都必须通过入口暴露出来。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;推导可靠&lt;/strong&gt;：每张被声明为有效的内部推导子图，都必须真的足以重新推出 $\operatorname{definition}(c)$，而不只是让学习者记住同一个结论。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不要求穷尽&lt;/strong&gt;：一张内部图可以只记录目前已知的若干充分路线。以后发现的新路线可以作为新的 OR 方案加入，而不意味着旧展开曾经定义了概念的全部本质。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;掌握关系单向&lt;/strong&gt;：沿某张有效内部子图完成推导，可以成为掌握 $c$ 的证据；但已经掌握 $c$，不代表学习者掌握了图中所有子概念和所有替代路线：&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;$$
\operatorname{mastered}(c)
\not\Rightarrow
\bigwedge_{v \in \operatorname{children}(c)} \operatorname{mastered}(v)
$$&lt;/p&gt;
&lt;ol start="8"&gt;
&lt;li&gt;&lt;strong&gt;内部细节不自动导出&lt;/strong&gt;：外部关系仍然以 $c$ 明确承诺的定义为准。不能因为某个内部节点出现在 $G_c$ 中，就假定掌握 $c$ 的人必然能够使用这个内部节点的全部外部关系。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;成本不会因折叠消失&lt;/strong&gt;：当学习者需要沿内部图推出 $c$ 时，实际完成的边仍然计入学习成本；把整张图显示成一个概念节点，不会把多步理解变成一步。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;递归结构仍须合法&lt;/strong&gt;：展开后的整张推导图必须保持无环，并继续满足本文暂定的禁止部分交集约束。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;用自然语言来说，这些条件是在避免几种看似“拆开了”、实际却不成立的解释：不能把一串相关名词当成概念的组成；不能把隐藏的基础知识留在图外；不能少学一个必要前提却得到同一个结论；不能把目前记录的一条路线冒充概念唯一的本质；也不能因为一个人会使用父概念，就宣称他已经理解其内部每一种理论细节。&lt;/p&gt;
&lt;p&gt;这也解释了展开与封装为什么不完全对称。展开已有概念时，父概念 $c$ 和它原有的外部关系仍然存在，新增内部图只需要证明一条单向的充分推导 $F_{G_c}(I)\Rightarrow c$。封装则要创造一个新父概念，并让它在外部替代整张子图；这要求更强的边界对应，接近证明父概念与内部条件在允许的查询范围内能够双向替代。展开同样会出错，只是当它被限制为增加充分推导而非重写概念本体时，影响范围更容易被约束。&lt;/p&gt;
&lt;h3 id="把一段-dag-封装成更大的概念"&gt;把一段 DAG 封装成更大的概念
&lt;/h3&gt;&lt;p&gt;前文说概念既可以被继续拆分，也可以和其他概念组合。这两个性质结合起来还有一个重要设想：当一段 DAG 满足必要的封装条件时，可以把它封装成一个新的父概念。原来从外部指向子图边缘节点的关系，可以投影为指向父概念的关系；原来从边缘节点指向外部的关系，也可以投影为从父概念出发的关系。父概念展开时仍然保留原来的内部推导，折叠时则成为一个可以继续参与更大 DAG 的普通节点。&lt;/p&gt;
&lt;pre class="mermaid"&gt;
flowchart LR
subgraph EXPANDED[展开视图]
direction LR
X1[外部概念 X]
Z1[外部概念 Z]
subgraph MODULE[可封装推导模块 H]
direction TB
A[入口 A] --&amp;gt; B[内部概念 B]
C[入口 C]
B --&amp;gt;|方案 Q1| D[唯一目标 r_H&amp;lt;br/&amp;gt;Q1：B AND C]
C --&amp;gt;|方案 Q1| D
end
Y1[外部概念 Y]
X1 --&amp;gt; A
Z1 --&amp;gt; C
D --&amp;gt; Y1
end
subgraph FOLDED[折叠视图]
direction TB
X2[外部概念 X] --&amp;gt;|方案 QP| P[父概念 P&amp;lt;br/&amp;gt;F_H = X AND Z]
Z2[外部概念 Z] --&amp;gt;|方案 QP| P
P --&amp;gt; Y2[外部概念 Y]
end
D -. 封装映射 pi_H .-&amp;gt; P
style MODULE fill:#eff6ff,stroke:#1d4ed8,stroke-width:2px
style P fill:#f0fdf4,stroke:#15803d,stroke-width:2px
style D fill:#fff7ed,stroke:#c2410c,stroke-width:2px
&lt;/pre&gt;
&lt;p&gt;图中两条标为 $Q_1$ 的入边属于同一套 AND 方案，因此只有 $B$ 与 $C$ 都完成，才能推出唯一目标 $r_H$。折叠后，两条标为 $Q_P$ 的边仍属于同一套 AND 方案，父概念保留边界条件 $F_H=X\land Z$；虚线 $\pi_H$ 表示封装映射，不是新的推导边。这样，展开和折叠表达的是同一个推导条件，而不是两张碰巧长得相似的图。&lt;/p&gt;
&lt;p&gt;但不是任意框选的一段 DAG 都能成为概念。设候选子图为 $H=(V_H,E_H)$，本文暂时把能够封装的子图限制为一种&lt;strong&gt;可封装推导模块&lt;/strong&gt;。它必须满足以下条件：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;单一目标&lt;/strong&gt;：$H$ 有且只有一个代表其结论的目标节点 $r_H$，并且每个内部节点都位于某条通向 $r_H$ 的路径上。若干节点之间不存在共同目标，它们只能构成一个集合或视图，不能仅凭被同时框选就成为概念。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;推导方案完整&lt;/strong&gt;：任何被 $H$ 使用的 AND 方案都必须被完整包含，不能只截取其中一部分边；不同完整方案仍然可以作为 OR 方案同时存在。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内部推导闭包&lt;/strong&gt;：除明确声明的入口节点外，每个参与内部推导的节点都必须至少拥有一套完全位于 $H$ 内部的有效推导方案，不能暗中依赖未被接口表达的外部条件。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;入口明确&lt;/strong&gt;：所有从外部进入 $H$ 的边只能抵达声明过的入口节点；这些边之间原有的 AND/OR 组合必须作为整体保留，不能在投影后被拆成若干互相独立的单边方案。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;单一出口&lt;/strong&gt;：所有从 $H$ 指向外部的推导边都必须从 $r_H$ 出发。若外部推导必须直接使用某个内部节点，那么这个节点仍然属于模块的外部接口，当前子图还不能被完整封装成一个概念。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;边界条件可表达&lt;/strong&gt;：从外部前提推出 $r_H$ 的条件必须能够汇总为一个关于入口的 AND/OR 公式 $F_H$。例如 $F_H=(I_1 \land I_2)\lor I_3$，封装后的父概念必须保留这套组合语义，而不是只保留三条扁平入边。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;成本语义可保持&lt;/strong&gt;：父概念必须能够表示从不同入口组合完成内部有效推导的最低成本，以及共享前置是否重复计费。若无法定义这种对应关系，父概念就不能替代原子图参与最低成本路线计算。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不产生部分交集&lt;/strong&gt;：$V_H$ 与已有递归概念的范围必须完整包含或完全分离，不能只重叠其中一部分。这沿用本文暂时采用的“禁止递归交集”公理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;存在统一定义&lt;/strong&gt;：图结构只能说明 $H$ 在形式上可以被收拢，不能自动证明它在语义上构成一个概念。新的父概念还必须拥有明确的定义或焦点问题，并说明内部 DAG 为什么恰好生成这个定义。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此，本文所说的可封装概念，暂时是指一张&lt;strong&gt;推导方案完整、内部依赖闭合、具有显式入口和单一语义出口的有根子 DAG&lt;/strong&gt;。这些是为了避免明显语义错误而采用的一组保守条件，不代表所有条件都已经被证明为必要。&lt;/p&gt;
&lt;p&gt;用自然语言来说，这些限制是在避免几种现实意义上显然不合理的“概念”：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;不能把一堆恰好放在一起、却没有共同结论的知识命名成一个新概念。&lt;/strong&gt; 单一目标和统一定义要求这个概念最终必须说清楚“它究竟是什么”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不能省略一半必要条件，然后宣称完整概念已经被推出。&lt;/strong&gt; 方案完整和内部闭包要求所有必要前提都真实存在；如果一个结论需要 $A$ 与 $B$，只框选 $A$ 不能算完成封装。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不能在展开时要求多个条件共同成立，折叠后却变成满足任意一个条件都可以。&lt;/strong&gt; 显式入口和边界公式要求 AND/OR 语义在封装前后保持一致。上图中只知道 $X$ 或只知道 $Z$，都不能宣称已经掌握 $P$。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不能说自己掌握了父概念，就默认掌握了它内部任意一个没有被导出的细节。&lt;/strong&gt; 单一出口要求外部只能使用父概念真正承诺的结论；如果后续推导必须直接依赖内部细节，这个细节就不能被藏起来。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不能通过把十步推导折叠成一个节点，就假装学习成本从十步变成一步。&lt;/strong&gt; 封装改变的是抽象尺度，不会让内部推导成本凭空消失。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不能让两个概念各自只包含同一结构的一半，却都声称完整拥有这段知识。&lt;/strong&gt; 禁止部分交集要求递归边界清楚；否则展开其中一个概念时，很难判断另一半究竟属于哪里。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不能只因为图形上可以收拢，就断言它在语义上是一个概念。&lt;/strong&gt; 最终仍然需要一个能够被解释、推导和检验的定义。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果边界投影能够在这些约束下保持原图中的可推导性和成本语义，知识图就可以在不同抽象尺度之间切换：封装一个子图时，可以根据原边界得到它与外部概念的关系；这个新父概念还可以继续和其他概念组合，递归形成更大的 DAG。图中只展示了边的直观投影，这些条件是否已经足够、哪些条件还可以放宽，将在文末继续讨论。&lt;/p&gt;
&lt;h2 id="用信号与系统验证路径优化"&gt;用信号与系统验证路径优化
&lt;/h2&gt;&lt;p&gt;有了上面的模型之后，我们再回头看开头的信号与系统案例。这里把三条教学路线视为三张近似线性的有效推导子图，观察新增概念和推导如何改变路线成本。x&lt;/p&gt;
&lt;p&gt;传统教学很容易把学习速度归因于某种固定的个人属性：聪明、记忆力好、数学基础强，或者足够努力。这些因素当然存在，但它们并不能解释一个现象：&lt;strong&gt;同一个人面对同一个知识体系，仅仅更换概念的引入顺序和推导方式，学习速度就可能发生数量级的变化。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我学习信号与系统的经历就是如此。我把三天内形成的理解记录在尚未完成的&lt;a class="link" href="https://v3n0.com/post/2026/signals_and_systems/" &gt;《信号与系统速通：现代视角下的信号与系统理论体系》&lt;/a&gt;中。它并不是一份严格完成的教材，但可以还原当时实际走过的学习线路。&lt;/p&gt;
&lt;p&gt;学校课程往往按照公式和题型平铺展开：先给出若干信号，再介绍系统性质，然后依次学习卷积、傅里叶变换、拉普拉斯变换和 Z 变换。每一种变换看起来都像一套新的公式，需要分别记忆。学校教纲本身并不涉及函数空间、内积或算子理论。&lt;/p&gt;
&lt;p&gt;我最初三天走过的路线从系统与微分方程逐步向上抽象：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先把系统理解成从输入信号到输出信号的映射；&lt;/li&gt;
&lt;li&gt;追问为什么微分方程适合描述一类连续时间系统，并把问题限制到 LTI 系统；&lt;/li&gt;
&lt;li&gt;从常系数微分方程中发现 $e^{st}$ 是微分算子的特征函数；&lt;/li&gt;
&lt;li&gt;用冲激响应与冲激分解理解卷积为什么能够描述 LTI 系统；&lt;/li&gt;
&lt;li&gt;再引入函数空间、内积和希尔伯特空间的视角，把信号理解成函数空间中的向量；&lt;/li&gt;
&lt;li&gt;最后回到傅里叶、拉普拉斯和 Z 变换，理解它们如何在各自适用的条件下，把卷积、微分或差分等运算转化为更容易处理的代数运算。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;导师后来构造的“集合论版本”并不是我三天内实际走过的路线。它从集合论出发，建立集合、映射、空间与基，再推演到算子谱定理；得到谱与特征方向的视角后，把原本复杂的卷积、微分等运算理解为在另一组基下的乘法，最后将各种变换放回同一个模型中。&lt;/p&gt;
&lt;p&gt;因此，从学校教纲到我的三天路线，就已经不是单纯调整顺序，而是为知识图引入函数空间、内积、希尔伯特空间和算子理论等新点，并建立它们与原有内容之间的新边。后来的集合论版本又在这张图上继续引入“集合论”“空间与基”“算子谱定理”等高压缩率中间节点；从这些节点建立到各种变换的新推导边后，原本需要逐个抵达的结论可以从统一结构中生成。&lt;/p&gt;
&lt;p&gt;这样一来，许多原本彼此孤立的公式，变成了同一个生成规则在不同条件下的结果。需要记忆的终态变少了，可以从已有概念重新生成的内容变多了。&lt;/p&gt;
&lt;h3 id="三条学习路线的长度对比"&gt;三条学习路线的长度对比
&lt;/h3&gt;&lt;pre class="mermaid"&gt;
flowchart LR
subgraph T[常见教材路线]
direction TB
T1[公式与题型] --&amp;gt; T2[卷积]
T2 --&amp;gt; T3[傅里叶变换]
T3 --&amp;gt; T4[拉普拉斯与 Z 变换]
end
subgraph P1[我的三天路线：20 个节点 / 19 条边]
direction TB
A0[已有数学基础] --&amp;gt; A1[系统]
A1 --&amp;gt; A2[输入输出映射]
A2 --&amp;gt; A3[微分方程]
A3 --&amp;gt; A4[线性化]
A4 --&amp;gt; A5[时不变性]
A5 --&amp;gt; A6[LTI 系统]
A6 --&amp;gt; A7[特征方程]
A7 --&amp;gt; A8[e^st 特征函数]
A8 --&amp;gt; A9[冲激函数]
A9 --&amp;gt; A10[冲激响应的线性组合]
A10 --&amp;gt; A11[卷积]
A11 --&amp;gt; A12[函数空间]
A12 --&amp;gt; A13[内积]
A13 --&amp;gt; A14[希尔伯特空间]
A14 --&amp;gt; A15[傅里叶变换]
A15 --&amp;gt; A16[拉普拉斯变换]
A16 --&amp;gt; A17[算子视角]
A17 --&amp;gt; A18[算子谱]
A18 --&amp;gt; A19[统一理解各种变换]
end
subgraph P2[集合论版本：6 个节点 / 5 条边]
direction TB
B0[已有数学基础] --&amp;gt; B1[集合论]
B1 --&amp;gt; B2[空间与基]
B2 --&amp;gt; B3[算子谱定理]
B3 --&amp;gt; B4[运算在另一组基下变成乘法]
B4 --&amp;gt; B5[统一理解各种变换]
end
T -. 新增点与边 ① .-&amp;gt; P1
P1 -. 新增点与边 ② .-&amp;gt; P2
style T fill:#fff7ed,stroke:#c2410c,stroke-width:2px
style P1 fill:#eff6ff,stroke:#1d4ed8,stroke-width:2px
style P2 fill:#f0fdf4,stroke:#15803d,stroke-width:2px
&lt;/pre&gt;
&lt;p&gt;这三条线路展示了两次连续发生的学习路线优化，也就是两次对图结构本身的改造。图中只保留了各条线性路线主干上的概念和推导边。&lt;/p&gt;
&lt;p&gt;需要说明的是，这仍然是一张示意图。尤其是集合论版本，我没有亲自沿这条路线学习，节点可能存在遗漏或表述偏差；这里能够确定的是，它事实上使用了比我的路线更短的主干路径。&lt;/p&gt;
&lt;p&gt;第一次改造从学校教纲出发，引入函数空间、内积、希尔伯特空间和算子理论，并建立这些新概念与微分方程、LTI、冲激、卷积和各种变换之间的推导边。这次改造形成了我的三天路线。&lt;/p&gt;
&lt;p&gt;为了让两条路线能够直接比较，图中为它们设置了相同的起点“已有数学基础”和相同的目标“统一理解各种变换”。按照当前的抽象粒度，我的路线包含 20 个节点和 19 条推导边；集合论版本由 6 个高压缩率节点和 5 条推导边组成。由于两者在示意图中都是线性特例，所以结构成本与路径距离相同：&lt;/p&gt;
&lt;p&gt;$$
C_0(R_{\text{我的路线}}) = d_{\text{我的路线}} = 19
$$&lt;/p&gt;
&lt;p&gt;$$
C_0(R_{\text{集合论版本}}) = d_{\text{集合论版本}} = 5
$$&lt;/p&gt;
&lt;p&gt;$$
\Delta C_0 = 5 - 19 = -14
$$&lt;/p&gt;
&lt;p&gt;也就是说，在这张无权示意图上，重构后的路线减少了 14 条边，结构成本约为原路线的 $26%$。另一位同学半天内建立整体理解，可以被看作第二次图结构改造的一次实际教学结果。&lt;/p&gt;
&lt;p&gt;这里比较的是当前建模粒度下的无权结构成本，并不意味着学习时间一定与边数线性对应。每条边的真实成本仍可能不同，因此上文进一步给出了加权模型。但如果不把节点和推导边拆开，连结构成本的变化都无法被观察，更不可能进一步估计边权。&lt;/p&gt;
&lt;p&gt;在不改变图时，模型仍然可以从现有 OR 方案中寻找最低成本有效路线；但这里的两次教学改进都不是单纯换一个拓扑顺序，而是同时引入了新的点、边和推导方案。&lt;/p&gt;
&lt;p&gt;这并不意味着微分方程、卷积等概念不再需要学习，而是它们不再作为互不相干的终点被依次灌输。统一模型提供了更高压缩率的索引，使具体结论能够在需要时被推导出来。&lt;/p&gt;
&lt;h2 id="这个模型是怎样演进出来的"&gt;这个模型是怎样演进出来的
&lt;/h2&gt;&lt;p&gt;上文先给出了当前的 v5 模型，但“万物皆概念”并不是它的起点。它是我在不断尝试定义课程、章节、概念和问题时，被前一版模型的矛盾逐步逼出来的结果。&lt;/p&gt;
&lt;p&gt;这里回过头保留从 v0 到 v5 的推理链。每一版都不是简单增加字段，而是在回答上一版无法回答的问题。&lt;/p&gt;
&lt;pre class="mermaid"&gt;
flowchart LR
V0[v0 词条罗列] --&amp;gt;|对象之间是什么关系| V1[v1 分层对象]
V1 --&amp;gt;|概念是否属于章节| V2[v2 全局概念与子图]
V2 --&amp;gt;|三类边无法统一| V3[v3 Prompt 唯一边]
V3 --&amp;gt;|教学顺序从哪里来| V4[v4 DAG 与拓扑序]
V4 --&amp;gt;|章节与概念并不同构| V5[v5 递归概念模型]
&lt;/pre&gt;
&lt;h3 id="v0把所有东西列成词条"&gt;v0：把所有东西列成词条
&lt;/h3&gt;&lt;p&gt;最初的模型只是在罗列产品里可能存在的对象：Course、Chapter、Concept、Prompt、Misconception、Interaction、Evidence 和 UserWikiGraph。每个对象都有一张字段表，但对象之间没有统一结构。&lt;/p&gt;
&lt;p&gt;在这个版本中，Course 拥有 Chapter，Chapter 拥有一个线性的 &lt;code&gt;problem_chain&lt;/code&gt;，Concept 则是另一种独立对象。教程知识和用户自己的 Wiki 甚至使用两套模型。&lt;/p&gt;
&lt;p&gt;v0 解决的是“系统里有什么”，却没有回答“这些东西为什么以这种方式连接”。概念与章节是什么关系、问题怎样推进概念、不同知识之间如何复用，都还是空白。&lt;/p&gt;
&lt;h3 id="v1从字段表进入分层对象"&gt;v1：从字段表进入分层对象
&lt;/h3&gt;&lt;p&gt;v1 开始为对象补充业务语义和生命周期。章节被定义为围绕目标概念形成过程的学习单元；概念被定义为对一类问题解决路径的封装；Prompt 也被区分为诊断、推进、纠偏、检验和总结等教学意图。&lt;/p&gt;
&lt;p&gt;这一步让模型从“有什么字段”进入“对象是什么、如何流转”，但整体仍然是 Course → Chapter → Concept 的固定层级，学习过程仍被默认成章节内部的线性流程。&lt;/p&gt;
&lt;p&gt;问题随之暴露出来：概念学习并没有唯一顺序。学习信号与系统时，欧拉公式只需要在第一次使用前掌握，并不天然属于某一章的固定位置。同时，Prompt 被分成过多类型，各类型边界模糊，因为我还没有回答 Prompt 的本质是什么。&lt;/p&gt;
&lt;h3 id="v2全局概念章节子图与三类边"&gt;v2：全局概念、章节子图与三类边
&lt;/h3&gt;&lt;p&gt;为了解决“概念是否属于章节”，v2 把 Concept 提升为全局实体：同一个概念可以被多个章节引用，Chapter 则被改写为整张教程图谱中的一个子图。&lt;code&gt;problem_chain&lt;/code&gt; 也从列表变成了允许分支和跳转的图。&lt;/p&gt;
&lt;p&gt;这一版第一次明确引入三类边：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;requires&lt;/code&gt;：依赖关系，有向；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;contains&lt;/code&gt;：包含关系，有向；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;relates&lt;/code&gt;：相关关系，无向。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;v2 的进步是终于开始用图表达知识，但三种边并不属于同一种语义：依赖、包含和相关无法用统一规则解释，也很难回答一条边究竟承载了什么教学内容。图虽然出现了，边的本质仍然没有被找到。&lt;/p&gt;
&lt;h3 id="v3prompt-成为唯一的有向边"&gt;v3：Prompt 成为唯一的有向边
&lt;/h3&gt;&lt;p&gt;v3 的关键收敛是：&lt;strong&gt;概念之间真正值得存储的关系只有推导问题本身，Prompt 就是有向边。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一条边从 source concept 指向 target concept，表达“A 遇到了什么局限，为什么需要 B”。&lt;code&gt;requires&lt;/code&gt; 不再作为独立边存储：如果存在从 A 到 B 的有向路径，就可以推导出 B 依赖 A；&lt;code&gt;relates&lt;/code&gt; 同样可以由可达性投影出来。&lt;/p&gt;
&lt;p&gt;Chapter 此时被定义为概念图中的连通子图，教程与用户 Wiki 也开始使用同一模型。这一步用“一种基础关系 + 图算法推导”取代了边类型枚举。&lt;/p&gt;
&lt;p&gt;但新的问题也出现了：如果 Chapter 仍要保存一条显式教学路径，那么它和图本身给出的顺序是什么关系？既然已经有一张有向图，为什么还需要另一份容易冲突的 &lt;code&gt;problem_chain&lt;/code&gt;？&lt;/p&gt;
&lt;h3 id="v4顺序完全由-dag-推导"&gt;v4：顺序完全由 DAG 推导
&lt;/h3&gt;&lt;p&gt;v4 删除了 Chapter 中显式保存的教学路径。概念的先后顺序不再由作者手写，而由 DAG 的拓扑序给出。只要一个概念所需的前置条件已经满足，它就可以被学习，不需要所有人走同一条线性目录。&lt;/p&gt;
&lt;p&gt;无环也在这一版成为强制约束：环意味着循环论证。v4 只确定了依赖关系应当组成 DAG，并由拓扑序给出合法学习顺序；多条入边究竟是必须同时满足的前置条件，还是可以任选的不同推导，当时还没有被区分。直到 v5，我才通过推导方案补全这层语义：同一方案内是 AND，不同方案之间是 OR。&lt;/p&gt;
&lt;p&gt;为了继续保留传统教学结构，v4 曾把 Chapter 定义成概念集合的划分：每个概念属于且仅属于一章，章节之间不重叠。但这恰好暴露了最后一个根本矛盾：如果一个章节可以被封装成一个节点，它本身就是概念；如果一个概念足够复杂，需要单独展开成教程，它又和章节没有区别。&lt;/p&gt;
&lt;p&gt;Chapter 的“划分”只是人为施加的语义，并不是知识结构本身的要求。&lt;/p&gt;
&lt;h3 id="v5取消层级万物皆概念"&gt;v5：取消层级，万物皆概念
&lt;/h3&gt;&lt;p&gt;因此，我进一步演进出了上文我提出的模型。&lt;/p&gt;
&lt;h2 id="不只优化学习路径"&gt;不只优化学习路径
&lt;/h2&gt;&lt;p&gt;这个模型最初来自学习方式问题，但它真正描述的对象也许更一般：&lt;strong&gt;从已有状态出发，通过一系列需要付出成本并接受验证的推导，到达目标状态&lt;/strong&gt;。只要一个领域能够被近似表示成这样的有向图，路径优化就可能有意义。&lt;/p&gt;
&lt;p&gt;硬件设计是一个对路径长度尤其敏感的例子。假设我们把一次设计过程抽象成一张迭代 DAG：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;节点是已经被明确提出并实现的设计概念，例如一种数据通路、缓存结构或时钟方案；&lt;/li&gt;
&lt;li&gt;边是从当前设计到下一设计的工程推导，包括为什么要修改、修改了什么，以及预期解决什么约束；&lt;/li&gt;
&lt;li&gt;验证结果是边成立的证据，包括功能仿真、时序分析、功耗评估，乃至上板和流片结果；&lt;/li&gt;
&lt;li&gt;边权是完成实现、仿真、定位失败和返工所需的综合成本。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="mermaid"&gt;
flowchart LR
A[已有设计] --&amp;gt; B[设计概念 v1]
B --&amp;gt; C[实现 RTL v1]
C --&amp;gt; D[仿真验证 v1]
D --&amp;gt;|满足约束| E[已验证设计 v1]
D --&amp;gt;|不满足约束| F[失败证据]
F --&amp;gt; H[修订设计概念 v2]
H --&amp;gt; I[实现 RTL v2]
I --&amp;gt; J[仿真验证 v2]
E --&amp;gt; G[目标设计]
J --&amp;gt;|满足约束| G
&lt;/pre&gt;
&lt;p&gt;为了达到目标设计，每提出一个新的设计概念，通常都需要至少一次实现与仿真验证。路径越长，需要经历的迭代和验证通常越多，工程成本也越高。若一条设计路径为 $p$，可以先把它的成本粗略写成：&lt;/p&gt;
&lt;p&gt;$$
C(p) = \sum_{e \in p} \left(C_{\mathrm{design}}(e) + C_{\mathrm{simulation}}(e) + C_{\mathrm{rework}}(e)\right)
$$&lt;/p&gt;
&lt;p&gt;此时，优化设计路径并不是跳过验证，而是寻找或构造更高价值的中间设计概念，让更少的有效迭代排除更大的设计空间。工程师或 Agent 可以优先选择信息增益更高、验证成本更低、通向目标约束概率更大的下一条边，并把每次仿真的结果反过来更新图和边权。&lt;/p&gt;
&lt;p&gt;当然，真实硬件研发不总是一张预先已知的 DAG。目标可能变化，失败分支会大量出现，不同方案也可能并行收敛。因此更完整的模型可能是一张随验证结果动态生长的设计图，甚至需要概率图、决策过程或搜索树。但核心问题没有改变：&lt;strong&gt;不要只优化单次设计，而要优化从当前设计抵达目标设计的整条验证路径。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;同样的抽象也可能进入软件架构、科学研究、药物筛选等领域。它们的共同点不是“都有概念”，而是中间步骤昂贵、每次推进都需要证据，并且路径选择会显著改变到达目标的总成本。&lt;/p&gt;
&lt;h2 id="尚未解决的问题"&gt;尚未解决的问题
&lt;/h2&gt;&lt;p&gt;这套模型并不是从零开始的猜想，它的若干组成部分已经在不同领域分别出现。已有研究不能证明本文提出的完整组合正确，也没有直接“认可”一篇尚未发表和验证的博客；但它们能够说明，这个方向与一些成熟理论相容，并为其中若干结构提供独立依据。&lt;/p&gt;
&lt;h3 id="哪些部分已有理论依据"&gt;哪些部分已有理论依据
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://www.aleks.com/about_aleks/knowledge_space_theory" target="_blank" rel="noopener"
&gt;知识空间理论（Knowledge Space Theory）&lt;/a&gt;把一个领域表示为知识项目及其可行知识状态，并根据学习者当前状态进行自适应评估。它支持“学习者不是都从同一个固定起点出发”和“知识存在可计算的前置结构”这两个基本方向，但它的知识项目不等于本文携带定义的递归概念，也没有直接规定推导边应当怎样承载解释材料。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.ijcai.org/Proceedings/73/Papers/001.pdf" target="_blank" rel="noopener"
&gt;经典 AND/OR 图研究&lt;/a&gt;为本文的推导方案和最低成本有效推导子图提供了最直接的形式基础：AND 节点要求所有子问题共同解决，OR 节点从替代方案中选择，解不一定是一条路径，而可以是一张具有最低成本的解图。当所有方案都只含一个前置条件时，问题才退化为普通最短路径。因此，本文从“最短路径”转向“最低成本有效推导子图”，不是单纯创造了一套新说法，而是在知识建模场景中重新使用了已有的求解结构。不过，共享前置子图如何计费、路线规模扩大后如何求解，仍然不能直接套用最短路径算法。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://cmap.ihmc.us/docs/theory-of-concept-maps" target="_blank" rel="noopener"
&gt;Novak 和 Cañas 的概念图理论&lt;/a&gt;支持用概念节点和带明确语义的关系组织知识，也强调层级结构取决于当前试图回答的焦点问题。这为“概念之间的关系不能只是无意义连线”提供了依据，但概念图会区分概念和命题，也没有要求每个概念都能递归展开为同构 DAG。因此，“万物皆概念”仍然是本文自己的统一建模选择。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://link.springer.com/article/10.1007/BF02505024" target="_blank" rel="noopener"
&gt;Merrill 的教学首要原理&lt;/a&gt;强调围绕真实问题组织学习，并经历激活已有知识、示范、应用和整合。它支持本文从已有概念出发、通过问题推进、最终回到实际应用的教学方向；但它是一套教学设计原则，不会自动推出本文的图数据结构。&lt;a class="link" href="https://www.nationalacademies.org/read/13398/chapter/8" target="_blank" rel="noopener"
&gt;美国国家研究委员会关于深层学习与迁移的综述&lt;/a&gt;进一步把迁移视为深层学习的定义性特征。这意味着“能够重新推出定义”可以作为理解证据之一，却不足以单独证明模型达到了最终目标；学习者还应当能够把底层原理迁移到新的问题中。&lt;/p&gt;
&lt;p&gt;所以，目前可以较强地获得外部支持的是：用有向结构表达前置关系、用 AND/OR 表达共同条件与替代方案、寻找最低成本解图，以及把解决真实问题和迁移作为最终检验。只有部分理论支持的是递归概念和带语义的关系。仍然缺乏直接依据的，则包括把全部教学材料只放在推导边上、任意子图的自动封装、理解倍率，以及“禁止递归交集”是否应当成为普遍约束。已有理论支持的是这些组成部分，而不是整套模型已经被证明。&lt;/p&gt;
&lt;h3 id="子图封装怎样才能不改变语义"&gt;子图封装怎样才能不改变语义
&lt;/h3&gt;&lt;p&gt;前文关于封装的示意图隐藏了一个关键问题：图论中的“把若干节点缩成一个节点”，不等于教学语义上的无损封装。普通边的可达性也许仍然存在，但 AND/OR 方案可能已经被改变。&lt;/p&gt;
&lt;p&gt;上图中的目标必须由 $B$ 和 $C$ 共同推出：外部概念 $X$ 通过入口 $A$ 支持 $B$ 分支，$Z$ 通过入口 $C$ 支持另一条分支。如果折叠后只是机械地生成 $X \to P$ 和 $Z \to P$ 两条普通入边，并分别把它们当成单边方案，原来的 $X \land Z$ 就会被错误地改写成 $X \lor Z$。同理，一条从内部节点出发的边，也未必意味着只要“理解了父概念”就一定拥有使用这条出边所需的具体内部结论。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.irif.fr/~habib/Documents/HP10.pdf" target="_blank" rel="noopener"
&gt;图的模块分解理论&lt;/a&gt;提供了一个严格但很强的参考条件：在通常的无向图定义中，如果一个节点集合是 module，那么每个外部节点要么连接它的全部节点，要么一个也不连接；模块内各节点从外部看来无法区分，因此可以被一个商图节点替代。对应到本文的有向推导图，还必须分别保持外部入邻接和出邻接的一致。本文希望封装的任意子 DAG 通常不满足这种一致邻接条件，所以不能直接声称它在图论意义上天然无损。&lt;/p&gt;
&lt;p&gt;因此，上文已经把可封装对象限制为有根、方案完整、内部闭合、入口明确、单一出口且不与已有范围部分重叠的子 DAG，并要求父概念继续保存入口的 AND/OR 公式和内部成本语义。这些限制能够排除上面的直接反例，但它们目前仍然只是一组保守的候选充分条件，还需要一个更严格的语义保持定义来检验。&lt;/p&gt;
&lt;p&gt;设被封装的子图为 $H$，折叠映射为 $\pi_H$。至少对于模型允许查询的外部已知集合 $S$ 和目标 $t$，封装前后应当保持可推导性：&lt;/p&gt;
&lt;p&gt;$$
\mathcal{R}(G;S,t) \neq \varnothing
\quad \Longleftrightarrow \quad
\mathcal{R}(G/H;\pi_H(S),\pi_H(t)) \neq \varnothing
$$&lt;/p&gt;
&lt;p&gt;如果还声称封装不影响路径优化，就要进一步证明封装前后的最低成本如何对应。即使可推导性保持不变，边界公式在展开时是否产生指数级方案、共享前置在折叠后是否仍然只计费一次，也可能要求更强的限制。只有满足这些语义保持条件，边界关系才适合自动投影；否则，封装后的节点不能替代原子图参与严谨的路线计算。&lt;/p&gt;
&lt;p&gt;这里仍然没有解决两个问题：上文九项限制是否真的足以保证这种等价，以及其中哪些只是方便定义边界的强约束而非必要条件。未来也许可以允许多个显式出口、多个父概念或更一般的接口公式，但每放宽一项，都必须重新证明它不会改变有效推导子图的集合与成本。&lt;/p&gt;
&lt;h3 id="禁止递归交集换来了什么又失去了什么"&gt;禁止递归交集换来了什么，又失去了什么
&lt;/h3&gt;&lt;p&gt;本文暂时要求同一知识体系中的递归分支只能完整包含或完全分离。若用 $A$、$B$ 表示两个概念所包含的后代集合，这条公理要求：&lt;/p&gt;
&lt;p&gt;$$
A \cap B \in \lbrace \varnothing, A, B \rbrace
$$&lt;/p&gt;
&lt;p&gt;它使递归包含关系成为一种层状结构。这样做的收益很具体：每个概念拥有唯一位置和唯一父级链；展开、折叠、版本管理、缓存和权限边界更容易定义；封装时也不会出现同一个内部节点只被两个父概念各自包住一部分的情况。对于需要稳定编辑和计算的产品数据模型，这些都是真实的工程收益。&lt;/p&gt;
&lt;p&gt;代价也同样明显。现实知识经常允许一个概念同时属于多个分类，或者让多个知识域共享同一段子结构。&lt;a class="link" href="https://protege.stanford.edu/publications/ontology_development/ontology101-noy-mcguinness.html" target="_blank" rel="noopener"
&gt;Stanford 的本体工程指南&lt;/a&gt;指出，多数知识表示系统允许一个类拥有多个父类；Novak 和 Cañas 则把不同知识域之间的 cross-links 视为理解关系、甚至产生创造性认识的重要结构。严格禁止交集会迫使建模者复制共享概念，或者把存在交集的分支拆到不同知识体系。前者可能带来身份、版本和证据同步问题，后者则可能把本来重要的跨域关系藏到体系边界之外。&lt;/p&gt;
&lt;p&gt;这里必须区分&lt;strong&gt;递归包含&lt;/strong&gt;与&lt;strong&gt;推导关系&lt;/strong&gt;。即使继续要求包含结构彼此分离，不同分支之间也应当允许建立推导边；否则模型会失去描述跨领域迁移的能力。真正尚未决定的是：共享概念能否被多个父概念同时包含。如果坚持唯一父级，就应当把“层状包含 + 跨分支推导”明确为一项有意的工程取舍；如果允许多个父级，就需要把包含关系从层状结构放宽为 DAG，并重新解决节点身份、局部展开和子图封装的歧义。&lt;/p&gt;
&lt;p&gt;因此，禁止递归交集不能被表述成知识本身的普遍规律。它更适合被视为当前模型为了换取可计算性和稳定边界而采用的公理，并通过真实知识体系的建模实践检验：它究竟消除了多少复杂度，又制造了多少重复和割裂。&lt;/p&gt;
&lt;h3 id="还需要继续回答的问题"&gt;还需要继续回答的问题
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;什么才是稳定、可判定的概念边界？“概念”与命题、任务、技能和证据之间是否需要更明确的区分？&lt;/li&gt;
&lt;li&gt;如何判断一条新边或一套新方案是真正的推导，而不是省略了关键步骤？解释一组 AND 条件如何共同起作用的材料，是否还需要属于整套方案，而不只属于其中某一条边？&lt;/li&gt;
&lt;li&gt;无环是否应当是所有知识关系的全局约束？面对互相定义、反馈系统和迭代理解时，应该重新划分概念，还是把强连通部分封装为一个更大的概念？&lt;/li&gt;
&lt;li&gt;什么证据足以说明学习者不但能够重新推出定义，还能够把知识迁移到新问题并解决真实问题？&lt;/li&gt;
&lt;li&gt;共享前置子图、个体边权和大量替代方案同时存在时，最低成本解图能否在可接受时间内算出？需要精确算法、启发式搜索，还是近似解？&lt;/li&gt;
&lt;li&gt;如何处理学习后的遗忘、复习，以及概念在不同任务之间的迁移？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果我们能够把概念、推导方案、验证证据和主体状态放进同一个可计算模型，那么“怎样更快地学习”，或者说，“怎样更快认知到目标概念”就不必永远停留在经验和方法论口号上。我们可以寻找现有的最低成本有效推导子图，也可以构造新的概念、边和方案，再用真实结果检验它是否真的降低了成本。&lt;/p&gt;
&lt;p&gt;最后还有一件很有意思的事：&lt;strong&gt;如果把 v0 到 v5 的每一个版本都视为一个概念，那么这篇文章本身也在使用它所描述的理论组织我的认知。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;v0 暴露“对象之间没有结构”的局限，于是推导出 v1；v1 暴露“固定层级和线性流程”的局限，于是推导出 v2。此后的每一次演进也都由一个明确问题引入，并由对这个问题的回答抵达下一个版本。每一版是节点，版本之间“问题 + 解答”的演进过程是边，整条建模史就是一张认知 DAG。&lt;/p&gt;
&lt;p&gt;而写下这篇博客，又是在把这张图递归地封装成一个更大的概念。它既记录模型的结论，也记录结论如何从旧模型中生长出来；既在解释“万物皆概念”，又把自己作为这个理论的一个实例。&lt;/p&gt;
&lt;p&gt;这也许才是“万物皆概念”最终有价值的地方：它不仅试图描述知识是什么，也试图描述认知如何演进，以及我们应该怎样以更低成本抵达下一个可验证的概念。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="2026819-修正推导载荷属于-and-组而不是单条边"&gt;2026.8.19 修正：推导载荷属于 AND 组，而不是单条边
&lt;/h2&gt;&lt;p&gt;上文把问题引入、推导解答和理解材料都放在推导边上。在把这套模型整理成最终版本时，我发现这个归属在 AND 方案下并不成立。它不改变模型的主体结构，但改变了“推导的最小单元究竟是什么”，所以这里补一处修正。&lt;/p&gt;
&lt;p&gt;问题出在 AND 方案。如果推出 $v$ 需要 $A$ 与 $B$ 共同成立，那么单独一条 $A \to v$ 并不足以证成 $v$；“旧概念遇到了什么局限、为什么需要 $v$”只有对整组前提才有意义。把它写在某一条边上，另一条边就会显得没有动机，或者被迫复述同一段话。&lt;/p&gt;
&lt;p&gt;更严重的是边与方案是多对多的。若载荷挂在边上，一方面同一方案内各边必须给出同一个问题引入，另一方面同一条边又可能属于两套动机完全不同的方案，于是这两套方案也被迫共享同一个问题引入。把这两条约束的传递闭包展开，结论是：**只要两套方案共享一条边，它们就必须共用同一个“为什么”。**这显然不是知识的实际形态。&lt;/p&gt;
&lt;p&gt;因此正确的归属是方案本身。问题引入、推导解答和理解材料都是定义在推导方案上的函数，而不是定义在边上的函数：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Concept
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── definition # 这个概念最终应当能够被重新推导出的定义
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── children[] # 内部推导图引用的直接子概念
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── derivation_plans[] # 以本图内节点为目标的推导方案
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;DerivationPlan # AND 组：推导的最小单元，唯一的内容载体
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── target # 本方案要推出的目标概念
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── premises[] # 必须全部完成的前提概念（AND）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── question # 旧概念遇到什么局限，为什么需要 target
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── answer # 由这组前提共同推出 target 的完整论证
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── materials[] # 完成这一步推导所需的材料
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Derivation # 投影视图，由方案导出，不单独存储教学内容
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── source
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── target
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── plan_ref
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样一来，模型正好变成一张 AND/OR 超图：一套方案就是一条超边，前提集合是尾、目标是头；推导边退化为超边在有向图上的投影，只用来判断无环、给出拓扑序和可达性。回过头看，我在 v3 得到的那个结论——“Prompt 就是有向边”——只在每套方案都只有一个前提时才成立。&lt;/p&gt;
&lt;p&gt;这处修正是保守的。单前提方案下方案与边一一对应，所以上文关于有效推导子图、无环性、拓扑序、递归展开约束和子图封装条件的结论全部不变，信号与系统案例中的 19 条边、5 条边、$\Delta C_0 = -14$ 和 $26%$ 也不变。&lt;/p&gt;
&lt;p&gt;唯一的实质变化是成本口径：结构成本应当数的是需要完成的推导方案数，也就是推导步数，而不是边数。&lt;/p&gt;
&lt;p&gt;$$
C_0(R) = |\operatorname{sel}(R)|, \qquad
C_u^*(S,t) = \min_{R \in \mathcal{R}(S,t)} \sum_{P \in \operatorname{sel}(R)} w_u(P)
$$&lt;/p&gt;
&lt;p&gt;其中 $\operatorname{sel}(R)$ 是这张有效推导子图所选中的方案集合，$w_u(P)$ 是完成整套方案的成本；$|E_R|$ 退居为“前提总数”这个辅助指标。当所有方案都只有一个前提时，$|\operatorname{sel}(R)| = |E_R|$，两种口径重合。另外还有一个附带好处：$R$ 本身就是一组方案，不必再从边集合反推当初选了哪套方案。&lt;/p&gt;
&lt;p&gt;这也顺带回答了上一节遗留问题中的一半：解释一组 AND 条件如何共同起作用的材料，确实属于整套方案，而不属于其中某一条边。剩下没有解决的是，方案成本 $w_u(P)$ 应该用什么可观测量来度量，以及封装前后方案成本如何对应。&lt;/p&gt;
&lt;p&gt;最后，这处修正本身也是一条边：v5 暴露出“载荷归属与 AND 语义冲突”的局限，由此推导出 v5.1。按照本文的说法，它同样是一次“问题引入 + 解答”，并被记录进了那张仍在生长的认知 DAG。&lt;/p&gt;</description></item></channel></rss>