谓词逻辑这章说真的是不少人离散数学里的分水岭。前面命题逻辑玩得再花到了这里要是没转过弯后面图论、代数结构都会受影响。很多同学觉得难点不在计算而在“抽象”——明明每个符号都认识连在一起就不知道在说什么。其实谓词逻辑并不难难的是你还没适应“把自然语言翻译成形式语言”这套思维。这篇东西我就按我当初复习和后来带课的经验把这章的核心脉络、常见坑、以及怎么做好推理证明尽量讲透一点。1. 为什么要从命题逻辑走到谓词逻辑一个“所有人”引发的思考1.1 命题逻辑解决不了的问题命题逻辑里一个命题就是一个有真假的陈述句比如“小明是学生”“天在下雨”。我们能用 ∧、∨、¬、→ 把它们组合起来研究推理关系。但命题逻辑有个天然的短板它把命题当成一个不可拆分的整体看不到内部结构。举个例子你就明白了。所有人都会死。 苏格拉底是人。 所以苏格拉底会死。这个三段论在命题逻辑里怎么表示你只能设P所有人都会死Q苏格拉底是人R苏格拉底会死然后推理形式就是 P ∧ Q → R。这个形式对吗显然不对因为P和Q的内容里明明有联系但命题逻辑完全无视这种联系它只看三个原子命题的真假组合。如果P为真、Q为真、R也为真这个蕴含式确实为真可万一某天P真、Q真、R假命题逻辑没法告诉你这个赋值“不可能出现”因为它丢失了“所有人”和“苏格拉底”之间的关系。这就是命题逻辑的局限它只能描述静态、孤立的事实没法表达“所有”“存在”“某个”这类量词结构。而计算机科学里到处是这种结构比如“所有进程都能被调度”“存在一个文件无法删除”所以你必须升级工具。1.2 谓词逻辑的基本零件个体词、谓词、量词谓词逻辑在命题逻辑的基础上把句子拆得更细主要引入三类东西个体词指代对象可以是具体的“苏格拉底”“ss”也可以是变量 x, y, z。相当于对象或者变量。谓词描述对象性质或对象之间关系的词一般用大写字母表示比如 P(x) 表示“x是人”G(x,y) 表示“x大于y”。谓词自身不是命题只有把变量代入具体对象后才能变成命题。量词全称量词 ∀读作“任意”存在量词 ∃读作“存在”。用来限定变量的取值范围。有了这三个零件“所有人都会死”就能写成∀x( P(x) → D(x) )P(x)x是人D(x)x会死。这个公式读作“对所有x如果x是人那么x会死”。注意这里用的是“→”不是“∧”很多初学者就是在这里开坑的。如果用 ∀x(P(x) ∧ D(x))那就成了“所有人都是人并且会死且不存在非人的东西”这语义完全变了。具体为什么下面翻译技巧里细说。“有人是学生”则写成∃x( S(x) ∧ Student(x) )这里的逻辑是“存在一个xx是人且x是学生”。有的同学会问为什么这里用“∧”而全称用“→”这是谓词逻辑翻译里最核心的一个规则一定要记牢全称量词后面常跟蕴含存在量词后面常跟合取。原因很简单全称量词描述的是“所有满足前件的对象”限制在某个范围内而存在量词只需要“存在一个同时满足多个条件的对象”。2. 谓词公式的结构辖域、约束变元与自由变元2.1 变量是“绑定”的不是乱跑的在谓词公式里量词后面紧跟着的那个变量以及它作用的范围都有严格规定。看这个公式∀x( P(x) → Q(x) ) ∧ R(x)前面那个 x 是在 ∀x 的辖域内也就是说在括号里面出现的 x 都被这个全称量词绑定叫做约束变元。而括号外面 R(x) 里的 x 没有被任何量词约束叫做自由变元。自由变元的真值不是固定的取决于你给 x 赋予什么值。类似程序里的局部变量和全局变量一个受到作用域保护一个暴露在外面。判定辖域其实很简单量词后面最近的那个公式往往是一对括号括起来的部分就是它的辖域。如果量词后面没有括号那它只管紧跟的那个原子公式或子公式。有一个高频考点是“改名”当公式里有约束变元和自由变元同名时为了语义清晰或做前束范式需要把约束变元改成另一个名字。比如上面的例子可以把约束 x 改成 y变成∀y( P(y) → Q(y) ) ∧ R(x)改名规则有两条硬性要求一要换的是约束变元量词内和辖域内所有同名的二不能和公式里其他自由变元重名。说白了就是别把局部变量改到全局里面去。2.2 解释与赋值公式怎么才有真假命题逻辑里一个命题的真假是给定的谓词逻辑里一个谓词公式的真假需要给出一个“解释”才能判断。解释通常包含几部分个体域论域变量可以取的值的范围比如整数集、全体人、全体程序。每个谓词符号的语义P(x) 具体表示什么性质或者关系。常量符号具体指代哪个个体。举个例子公式 ∃xP(x) 如果给定个体域是{1,2}并且 P(1)为真P(2)为假那么在这个解释下公式为真。如果所有个体代入后都不成立那公式为假。这个“解释”的概念有点像编程里的“环境”或“上下文”。同一个公式在不同解释下真假不同。所以谓词逻辑里的“永真式”不再是“真值表全真”而是指在所有解释下都为真。这个概念后续学形式语言与自动机的时候会反复出现现在打好底子。量词的否定规律也是本章重点直接给结论¬∀xA(x) ⇔ ∃x¬A(x)¬∃xA(x) ⇔ ∀x¬A(x)翻译成大白话就是并非所有x都满足性质等价于存在某个x不满足性质不存在x满足性质等价于所有x都不满足性质。这个规律很容易理解但做题时很多人会错在“否定量词时忘了否定后面的量词辖域整体”。比如 ¬∀x(P(x)→Q(x))是 ∃x¬(P(x)→Q(x))而不是 ∃x(¬P(x)→Q(x))。这个时候还要用到命题逻辑里的否定等价式¬(P→Q) ⇔ P∧¬Q。把量词和蕴含的否定叠在一起是绝对高频的考题。3. 等值式与蕴含式谓词逻辑里的“运算律”3.1 量词分配律哪些能分哪些不能分谓词逻辑除了量词否定还有一组重要的等值式叫量词分配律。很多学生背了又背还是出错因为没搞懂分配的本质。先看全称量词对合取的分配∀x( A(x) ∧ B(x) ) ⇔ ∀xA(x) ∧ ∀xB(x)这很好理解所有x同时满足A和B等于所有x都满足A并且所有x都满足B。再看待称量词对析取的分配∃x( A(x) ∨ B(x) ) ⇔ ∃xA(x) ∨ ∃xB(x)也存在一个x满足A或B等于存在x满足A或者存在x满足B。这两个都可以放心用。但反过来就不行了∀x( A(x) ∨ B(x) ) 不能等价于 ∀xA(x) ∨ ∀xB(x)∃x( A(x) ∧ B(x) ) 不能等价于 ∃xA(x) ∧ ∃xB(x)为什么举个例子。设个体域是全班同学A(x)x会唱歌B(x)x会跳舞。∀x(A(x)∨B(x)) 表示“每个同学要么会唱歌、要么会跳舞”这完全允许一部分同学只会唱歌、另一部分只会跳舞。但∀xA(x)∨∀xB(x) 表示“要么全班都会唱歌要么全班都会跳舞”这个语义强太多了显然不等价。再比如 ∃x(A(x)∧B(x)) 表示“存在一个同学既会唱歌又会跳舞”而 ∃xA(x)∧∃xB(x) 表示“存在会唱歌的同学也存在会跳舞的同学”这两个同学可以不是同一个人。所以前后意义完全不同。这一对“不能分配”的量词就是考卷上最爱挖的坑。牢记一个规律∀对∧可分配∃对∨可分配反之不行。3.2 前束范式把量词都提到前面前束范式是谓词逻辑公式的“标准形”要求所有量词都移到公式最前面并且它们的作用域延伸到公式末尾。为什么要学前束范式后面用到推理规则、归结法时都需要这种规范形式。考试里也常出“把公式化为前束范式”的题步骤固定属于送分题前提是别在改名和换等价式时出错。求前束范式的标准流程如下消去公式里的蕴含连接词。利用 A→B ⇔ ¬A∨B把 → 去掉。将否定符号 ¬ 往里移动使之只作用于原子公式。可以用量词否定、双重否定律、德摩根律。约束变元改名。让每个量词后面的约束变元都不同并且和自由变元不重名。把所有量词按顺序移到公式最前面得到前束范式。举个例子把公式 ∀xP(x) → ∃yQ(y) 化为前束范式。第一步消去蕴含¬∀xP(x) ∨ ∃yQ(y)第二步否定移动∃x¬P(x) ∨ ∃yQ(y)这里两个量词一个是∃x一个是∃y名字不重复不需要改名。直接把量词往前移∃x∃y( ¬P(x) ∨ Q(y) )如果量词名字重复了比如 ∃xP(x) → ∃xQ(x)处理时会先变成 ¬∃xP(x) ∨ ∃xQ(x)然后否定移动得 ∀x¬P(x) ∨ ∃xQ(x)。这里两个x一个受∀约束一个受∃约束不对此时同一个变元名出现两次语义混淆需要把其中一个改成 y变成 ∀x¬P(x) ∨ ∃yQ(y)再提前得到 ∀x∃y(¬P(x) ∨ Q(y))。实际做题时很多人会漏掉“改名”这一步最后量词提前时辖域乱串式子就废了。3.3 常用蕴含式做题时直接拿来用除了等值式还有一些蕴含式也经常在推理题中使用。比如∀xA(x) → ∃xA(x)当个体域非空时如果所有x都满足A那肯定存在一个x满足A。这很好理解。注意如果个体域是空集情况会不一样离散数学默认个体域非空所以这个式子可以直接用。还有一个∃x∀yA(x,y) → ∀y∃xA(x,y)这个叫量词交换的蕴含式。它说的是“存在一个x对所有y都有A关系”那么“对任意y都存在x使A关系成立”。前者更强后者更弱。反过来 ∀y∃xA(x,y) 推不出 ∃x∀yA(x,y)。这个逻辑类似于“有人是所有人的祖先”可以推出“每个人都有一个祖先”但反推不行。考试里偶尔会用这个做选择题。4. 谓词逻辑的推理理论US、UG、ES、EG四板斧4.1 四条推理规则的含义谓词逻辑的推理在命题逻辑推理规则如假言三段论、析取三段论之上增加了和量词相关的四条规则。不同教材记法略有差异但本质一样。US全称特指由 ∀xA(x) 推出 A(c)c为任意确定的个体。意思是既然所有x都满足A那随便挑一个具体的对象也满足。UG全称推广由任取一个个体 c推出 A(c)且c是任意的则可推出 ∀xA(x)。要求 c 不能带任何额外的假设必须是“随便抓的”一个。ES存在特指由 ∃xA(x) 推出 A(c)其中 c 是“某个满足A的个体”但这个个体不能是之前已经确定的任意个体必须选用没有出现过的新常项。EG存在推广由 A(c) 推出 ∃xA(x)。只要有某个个体c满足A那自然存在x满足A。很多书里还有附加条件比如 US 和 UG 在公式里没有自由变元时使用ES 引出的个体常项不能出现在前提或结论中EG 里个体常项若是 ES 引出的则不能直接用于带额外约束的结论等。这些规则单独看都懂放在一起推理时就容易出错。4.2 经典例子苏格拉底三段论的完整证明我们用谓词逻辑推理规则证明开头那个三段论。前提∀x( P(x) → D(x) )其中 P(x)x是人D(x)x会死。P(s)s表示苏格拉底。结论D(s)证明过程步骤1∀x( P(x) → D(x) )前提步骤2P(s)前提步骤3P(s) → D(s)由步骤1使用US把x换成s步骤4D(s)由步骤2和步骤3使用假言推理这就是标准的谓词逻辑推理步骤简单但每一步用哪个规则必须写清楚。考试中经常要求写出推理规则不能跳步。再看一个稍复杂的例子前提∀x(S(x)→M(x))∃x(S(x)∧H(x))结论∃x(M(x)∧H(x))意思所有学生都要参加考试有些学生是男生所以有些参加考试的是男生。推理步骤∃x(S(x)∧H(x))前提S(a)∧H(a)由1使用ESa是新引入的常项∀x(S(x)→M(x))前提S(a)→M(a)由3使用USS(a)由2使用化简M(a)由4和5使用假言推理H(a)由2使用化简M(a)∧H(a)由6和7使用合取引入∃x(M(x)∧H(x))由8使用EG这里最关键的是第2步的ES引入新常项 a 之前公式里已经有前提中的变量 x所以 a 必须是从未出现过的新名字。假如乱用一个已经在其他前提里出现的常项推理就可能失效。4.3 推理时最容易犯的错学谓词逻辑推理几乎每个人都会经历一段“以为对了但规则不允许”的时期。最典型的错误有两个第一个错误用 ES 引出的个体去替代 UG 中的任意个体。比如你已经从 ∃xF(x) 推出了 F(a)这里的 a 是那个“特别的存在”不是任意的。如果你随后用 UG 推出 ∀xF(x)就相当于把一个特殊个体的性质推广到了所有个体这显然是错的。规则明确规定ES 引入的常项不能出现在后续 UG 的证明路径中除非有额外条件。第二个错误ES 和 US 混用顺序。正确的套路一般先 ES 再 US或者对全称前提直接 US。但如果你先把一个全称前提 US 到某个常项 a然后又对存在前提 ES 也用同一个 a不行吗很多教材说不允许因为存在前提中的那个个体可能是别的你还没确定它和 a 是同一个所以 ES 必须用新常项。实操时可以这样记先使用 ES 引入新的常项再对这个常项使用 US这样就不会冲突。另外还有一个经典谬误叫“存在量词分配错误”。比如已知 ∀x(P(x)∨Q(x)) 和 ∀x¬P(x)要证 ∀xQ(x)。证明时可以直接对第一个前提 US 得到 P(c)∨Q(c)再用第二个前提 US 得到 ¬P(c)然后析取三段论得到 Q(c)最后 UG 得到 ∀xQ(x)。这是合规的。但如果你试图先对 ∀x(P(x)∨Q(x)) 使用“分配律”拆成 ∀xP(x)∨∀xQ(x)那就不行前面我们说过这个分配不成立。5. 从公式到自然语言翻译题的实战方法论5.1 常见语句的翻译模板谓词逻辑做题最考验基本功的是自然语言和形式语言互译。这块没有捷径但有一些常见的套路可以套。翻译成谓词公式时看到这些词要条件反射“所有”“任意”“每个” → 全称量词 ∀后面核心结构多为“→”“存在”“有的”“至少有一个” → 存在量词 ∃后面核心结构多为“∧”“不存在”“没有” → 量词否定也就是 ¬∃ 或 ∀¬举个例子“没有鸟会游泳”怎么翻先想语义不存在一只鸟它还会游泳。设 B(x)x是鸟S(x)x会游泳。可以写成 ¬∃x(B(x)∧S(x))也可以改写成 ∀x(B(x)→¬S(x))。两者等价。再比如“每个学生都学过数学或计算机”翻译成 ∀x(S(x)→(M(x)∨C(x)))S(x)x是学生M(x)x学过数学C(x)x学过计算机。不要翻成 ∀x(S(x)∧(M(x)∨C(x)))那表示“所有东西都是学生且学过数学或计算机”明显不对。反过来把谓词公式翻译成自然语句也要小心∃x(Student(x) ∧ ¬Pass(x))意思是“存在一个学生他没有及格”不是“所有学生都不及格”。这两个意思差远了。还有一类题让你在给定论域下判断公式真值。比如论域是{1,2}P(1)为真P(2)为假问 ∀xP(x) 和 ∃xP(x) 真假。这种题本质就是枚举仔细把每个个体代入算一遍即可。5.2 带函数和关系的翻译高职或计算机专业的离散数学还会出现带多个谓词、甚至带函数的题目。比如“对于任意整数x都存在整数y使得 xy”翻译成∀x∃y( G(x,y) )其中 G(x,y) 表示 xy论域为整数。注意量词顺序在这里非常关键。∀x∃y 和 ∃y∀x 语义不同。前者是“对每个x都能找到一个y可以随x变化比x大”这是真的后者是“存在一个固定的y比所有x都大”在整数论域里为假。所以翻译时量词顺序必须严格按照原来句子里“任意”和“存在”出现的逻辑关系来排不能随意调换。5.3 翻译题的检查技巧我自己做题的习惯翻完一个公式后会立刻把公式“读回”自然语言看是不是和原句意思一致。这叫“回译检查”。比如原句“所有学生都讨厌有的作业”如果你翻译成 ∀x(S(x)→∃y(Hw(y)∧Tate(x,y)))读回去是“对于每个学生都存在一个作业他讨厌这个作业”意思跟原句差不多注意这里那个“有的作业”表示每个学生都讨厌某个可以不同的作业。而 ∃y∀x(S(x)→(Hw(y)∧Tate(x,y))) 则变成“存在一个作业所有学生都讨厌它”语义不同。考试里这就是一个经典的坑状语“有的作业”位置不同量词顺序不同翻译也不同。另外一定要区分“有的”在中文里是“至少一个”的意思不含“至少两个”或“全部”的意思而很多初学者不自觉地认为“有的”包含“全部”造成理解偏差。6. 学习与备考中的常见陷阱与刷题策略6.1 四个高频坑点提前避开第一个坑把“∀x(A(x)→B(x))”当“∀x(A(x)∧B(x))”理解。前者是“所有A都是B”后者是“所有x都是A且B”。比如“所有学生都带手机”应该翻成 ∀x(S(x)→M(x))不是 ∀x(S(x)∧M(x))。后者等价于“所有东西都是学生且带手机”在正常论域下通常是假的。第二个坑否定量词时忘了括号。比如对 ¬∀x(P(x)→Q(x)) 变换时很多同学直接写 ∀x¬(P(x)→Q(x))量词类型倒是变了但后面 ¬(P(x)→Q(x)) 没有继续化简。正确做法是继续化为 ∃x(P(x)∧¬Q(x))。第三个坑处理多重量词时顺序颠倒。前面已经举过例子∀x∃y 和 ∃y∀x 有本质区别。做题时遇到多重量词推荐先用自然语言完整读一遍再判断哪个量词在外层、哪个在内层。翻译顺序和量词顺序一一对应小心“任给一个x存在一个y”和“存在一个y任给一个x”的区别。第四个坑推理中 ES 和 UG 用法不当。这个在推理题里是重灾区。原则很简单ES引出的一定是特定的、新出现的常项UG使用的一定是任意选取的常项不能带特殊假设。如果一条证明路径里前面用了 ES后面就不能再用 UG 作用在那同一个常项上除非你额外证明了这个常项在相关性质上具有任意性。6.2 题型速览与应对策略谓词逻辑这一章的题型无非就是以下几类判断题/选择题判断公式真假、公式等值、前束范式是否正确。这类题考概念辨析重点看量词辖域、分配律、否定变换。翻译题自然语言和谓词公式互译。先确定个体词和谓词再定量词顺序最后注意用∧还是→。求前束范式题按“消蕴含、移否定、改名、提量词”四步走每一步都要写出来。推理证明题给出前提和结论要求构造推理过程。策略是先看结论的量词类型结论是全称量词一般最后用UG结论是存在量词一般最后用EG。中间需要用到 ES 时优先把存在前提拿出来引入新常项。刷题的时候我建议你准备一个小本子把每次错的点浓缩成一句话记下来。比如“∀对∨不可分配”“ES句必须用新常项”“否定量词要连谓词一起否定”。考前只看这个小本子效率比从头翻书高得多。6.3 把谓词逻辑“用起来”的个人体会可能有些同学觉得这章学完考试一过就丢了。其实谓词逻辑在后续课程中无处不在。学过数据库的都知道SQL里的关联子查询、EXISTS和NOT EXISTS本质就是存在量词和量词否定学人工智能、知识表示时一阶逻辑更是基础哪怕是程序里“所有对象满足某个不变量”“存在一个元素满足条件”这种描述背后也是谓词逻辑的思维。我个人觉得学习这章最好的方式不是死记硬背公式而是每遇到一个实际场景都试着用谓词公式写一遍。比如你写代码时想表达“列表中所有元素都不为空”你会写成 ∀x(IsElement(x, list) → NotEmpty(x))想判断“存在一个用户是管理员”写成 ∃x(IsUser(x) ∧ IsAdmin(x))。这种用形式语言思考的习惯一旦养成后面的离散数学和编程都会顺很多。最后再分享一个小技巧做推理题时先把题目里所有前提用自己习惯的符号列出来再在草稿纸上写出“目标结论的量词类型”。如果结论是全称通常最后一步要UG那你就得确保前面推出来的条件是“对任意个体都成立”而不是“只对某个特殊个体成立”。如果结论是存在最后一步EG那你必须在前面构造出一个满足性质的个体。整个过程就像写程序先看返回值类型再倒推实现逻辑思路就会清晰很多。