数理逻辑02 一阶逻辑

\(\newcommand{\I}{\mathfrak{I}}\newcommand{\A}{\mathfrak{A}}\)逻辑系统的表达能力是和其符号数量、语法、语义的定义的复杂性成正相关的。因为命题逻辑符号数量少,语法语义的定义简单,所以其表达能力也有限。从命名也可以看出来,命题逻辑是把“命题”作为原子对象来处理的,这就使得它无法触及语言中更细节的东西,比如“自然数”、“函数”、“...是...”、“存在...”等等。

所以,人们引入定义了一套更复杂因而也更精细的逻辑系统,称为谓词逻辑(Predicate Logic)系统。谓词逻辑是一个逻辑系统族,包含一阶谓词逻辑、二阶谓词逻辑、高阶谓词逻辑等等。弗雷格(Frege)是谓词逻辑的奠基人。相比于命题逻辑,他引入了量词符号“存在”与“任意”,这使得逻辑系统可以处理复杂的数学表述,是逻辑学发展史上的里程碑。本文讨论一阶谓词逻辑,简称一阶逻辑(First Order Logic, FOL)。

一阶逻辑的语法

一阶逻辑的字母表包含以下内容:

  • 变量符号(variable symbols):与命题逻辑完全相同,变量符号有\(v_0,v_1,\cdots\),变量总数是至多可数的,为了方便也可以记为\(x,y,z,\cdots\)\(a,b,c,\cdots\)
  • 连接符号(connectives):非(\(\neg\)),与(\(\land\)),或(\(\lor\)),推出(\(\to\)),等价(\(\leftrightarrow\));
  • 量词(quantifiers):存在(\(\exists\)),任意(\(\forall\));
  • 等号(equality symbol):(\(\equiv\));(注意不是算术中常用的(\(=\)))
  • 括号(parentheses):(\((\)),(\()\))。用来区分优先级;
  • 关系符号(relation symbols):对于任意一个\(n\in \mathbb{N}\),有一组“\(n\)元关系符号”(也可以没有);
  • 函数符号(function symbols):对于任意一个\(n\in \mathbb{N}\),有一组“\(n\)元函数符号”(也可以没有);
  • 常数符号(constant symbols),\(c_0,c_1,\cdots\),或者也可以用特殊的字母表示;

因为一阶逻辑引入了\(\equiv\)作为符号,所以我们从现在开始不再用\(\equiv\)表示语义等价关系。

以上分类中的最后三类比较特殊。前面五类在所有场合都相同,而后三类则通常在需要时再引入,甚至如果讨论中不涉及的话可以为空。我们把后三类符号统称为符号集(symbol set),记为\(S\)。前五类符号记为\(\mathcal{A}\)。整个字母表记为\(\mathcal{A}_S\)。所以,在一阶逻辑中我们通常会在不同的场合会使用“不同”的字母表,这些不同的字母表只在符号集上有差异。所以在讨论一阶逻辑时,必须首先指明符号集是什么。

虽然我们还没有定义一阶逻辑的语法和语义,但我们可以先简略地讨论一下为什么要使用符号集。因为我们要描述更细节的数学对象,所以必须在逻辑系统中有专门的符号来代表运算符、函数、关系、常数等等。而在形式化不同的数学表达时,我们需要不同的符号。例如如果我们想用一阶逻辑形式化自然数上的定理,那么我们就可能需要二元关系“整除”,二元函数“加法”,以及常量“\(0\)”。而如果我们想要形式化群论上的定理,则不需要整除或加法这些符号,而需要群元素间的运算(二元函数),“逆元”(一元函数),“单位元”(常量)等等。只有确定要形式化的对象之后我们才能确定字母表,字母表确定了以后所有一阶逻辑写出的命题就只能包含字母表中的字符了。

和命题逻辑相比,有了符号集以后我们可以用一个符号来表示一个命题(一张真值表),还可以用符号表示函数。可见,尽管我们还没有定义谓词逻辑的语法和语义,但我们已经感受到其复杂性。为什么把这样的逻辑系统称为“谓词逻辑”,其实有复杂的由来。这部分内容可以参考我[关于弗雷格语言哲学的笔记],弗雷格用带空洞的语词来表示谓词,而把量词“任意”和“存在”还原为了二阶谓词。而一阶逻辑就是量词之后的空洞只能填入原子对象的谓词逻辑系统。例如,我们可以说“对于任意一个自然数\(n\),…”,但不能直接说“对于任意一个自然数的子集\(S\),……”。因为自然数\(n\)是原子对象,而自然数集的一个子集已经是一个一元关系了。一阶逻辑只接受把原子对象放进量词中,而不接受把一元关系放进量词中。如果接受把一元关系放进量词中,我们就来到了二阶逻辑。如果接受把一元关系的集合放进量词中,就来到了三阶逻辑(比如“对于任意自然数子集的集合\(Q\),…”。依次类推,人们还定义了\(\omega\)阶逻辑,接受把无穷阶对象放进量词中。

为什么我们要着重讨论一阶逻辑呢?首先,逻辑系统越复杂,表达能力就越强,但是越复杂的对象研究起来就越困难,一阶逻辑是这些系统中最简单的;其次,我们将会看到哥德尔证明了越复杂的逻辑系统越可能产生缺陷;最重要的是,人们证明了:通过一些基于集合论的转化,我们原则上可以用一阶逻辑表达当今世界上的所有数学定理。也就是说本质上对一阶逻辑的讨论就是对所有数学定理的讨论,我们之后会看到如何做到这一点。

Terms & Formulas

对于特定的符号集\(S\),我们归纳地定义\(S\)下的一阶逻辑的项(称为\(S\)-term):

  • 单个变量\(v_i\)是一个\(S\)-term;

  • 单个常数\(c_i\)是一个\(S\)-term;

  • 对于\(n\geq 1\),如果\(t_1,\cdots,t_n\)都是\(S\)-term,那么对于任意\(n\)元函数符号\(f\)\(ft_1t_2\cdots t_n\)也是一个\(S\)-term;

基于term的定义,我们归纳地定义\(S\)下的一阶逻辑的公式(称为\(S\)-formula):

  • 如果\(t_1\)\(t_2\)是两个\(S\)-term,那么\(t_1\equiv t_2\)是一个\(S\)-formula;
  • 对于\(n\geq 1\),如果\(t_1,\cdots,t_n\)都是\(S\)-term,那么对于任意\(n\)元关系\(R\)符号,\(Rt_1t_2\cdots t_n\)也是一个\(S\)-formula;
  • 如果\(\varphi\)\(S\)-formula,\(x\)是一个变量,\(\neg \varphi\)也是\(S\)-formula;
  • 如果\(\varphi,\psi\)\(S\)-formula,\((\varphi \land \psi)\)\((\varphi\lor\psi)\)\((\varphi\to \psi)\)\((\varphi \leftrightarrow \psi)\)也是\(S\)-formula。
  • 如果\(\varphi\)\(S\)-formula,\(x\)是一个变量(不是一般的term),\(\forall x\varphi\)\(\exists x\varphi\)也是\(S\)-formula;

符号集\(S\)下全体一阶逻辑formula称为符号集\(S\)下一阶逻辑的语言,记为\(L^S\)。这里的\(L\)就是指language。全体\(S\)-term的集合也有一个记号\(T^S\)

我们要求一阶逻辑的term和formula都是有限长的字符串。

\(\newcommand{\var}{\text{var}}\)我们可以基于结构归纳法,定义语法意义下关于term或formula的函数。例如,一个重要的基于结构归纳的函数\(\text{var}\)用来指明term中出现的所有变量的集合,这个函数可以定义如下:

  • \(\var(v_i):=\{v_i\}\)
  • \(\var(c_i):=\varnothing\)
  • \(\var(ft_1\cdots t_n):=\var(t_1)\cup\cdots\cup\var(t_n)\)

Sentences

量词是一阶逻辑中最核心也最复杂的问题。在数学语言中,出现在量词后面的变量是很特殊的。比如,“对于任意正整数\(n\)\(n\)不是奇数就是偶数”这句话的\(n\)出现在全称量词中,那么完全可以用另一个变量名替换之而完全不改变句子的含义:“对于任意正整数\(m\)\(m\)不是奇数就是偶数”。然而,如果变量不出现在量词中,那么不可以随意改名:“存在变量\(x\)使得\(f(x)= a\)”,不能替换成“存在变量\(x\)使得\(f(x)= b\)”。

这有点类似程序语言中的局部变量与全局变量。在一阶逻辑中我们把前者称为受限变量(bound variables),后者称为自由变量(free variables)。我们利用结构归纳严格地定义formula中的自由变量列表(受限变量就是所有不是自由变量的变量):\(\newcommand{\free}{\text{free}}\)

  • \(\free(t_1\equiv t_2):=\var(t_1)\cup \var(t_2)\)
  • \(\free(Rt_1\cdots t_n):=\var(t_1)\cup \cdots \cup \var(t_n)\)
  • \(\free(\neg \varphi):=\free(\varphi)\)
  • \(\free( (\varphi\ast\psi) ):=\free(\varphi)\cup \free(\psi)\),其中\(\ast\)表示\(\land\),\(\lor\),\(\to\),\(\iff\)
  • \(\free(\forall x\varphi):=\free(\varphi)\setminus \{x\}\)
  • \(\free(\exists x\varphi):=\free(\varphi)\setminus \{x\}\)

我们注意到根据定义,\(\free((Ryx\to \forall y\neg y\equiv z))=\{x,y,z\}\),即便\(y\)曾出现在某个\(\forall\)后过。这是合理的,因为如果某个变量在小的层面是临时的,如果它又在更大的层面充当全局的,则应当被理解为是全局的。这就好像程序语言中局部变量可以与全局变量重名,但不影响全局变量依然具有全局性。

如果一个formula中没有自由变量,也即如果所有变量都是局部的,那么这个formula一定描述了一些重要的性质,这性质不依赖于某些特定的变量,而是所讨论的数学对象本身的性质。比如“群中的任意元素总是存在逆元”,这是群这一代数结构本身的特性,而与群中某几个元素之间的关系如何无关。我们把没有自由变量的formula称为一个sentence。通常,我们会把公式集\(L^S\)中只包含\(v_0,\cdots,v_{n-1}\)作为自由变量的子集记为\(L_n^S\)\(L_n^S:=\{\varphi\mid \varphi\in L_n^S\)\(\free(\varphi)\subseteq \{v_0,\cdots,v_n \} \}\),这样所有sentence的集合就可以记为\(L_0^S\)。Sentence是一阶逻辑中的一个核心概念。

Remark: 仅通过语法我们就能判断出一个formula中的var, free列表,可以判断一个formula是否是sentence,与“语义”无关。

一阶逻辑的语义

在命题逻辑中,只需给出所有原子命题的真值指派,就可以确定任何命题的真值。在一阶逻辑中,我们依然坚持这种从原子出发向上的语义构成规则。但由于现在的原子对象不再是命题,所以语义解释不再是指派“真值”,而需要为变量指派某一特定的数学对象,为函数符号、关系符号、常量符号指派数学含义。在所有这些指派完成了之后,符合语法的一阶逻辑term和formula就会自动产生“意义”。对于formula来说,它将会结合组成它的term的含义以及逻辑连接词的含义(这一部分再次与命题逻辑重合)而产生真值。再一次我们强调,由此得到的formula的真值是客观、唯一的,只有在承认指派的客观唯一性以及数学规则的客观唯一性的前提下才能讨论一阶逻辑的语义。

就像命题逻辑中同一个变量\(a\)有可能被指派为真也有可能被指派为假,一阶逻辑中同一个符号也可能被指派多种含义。例如,对于\(\forall v_0Rv_0v_0\),我们可以为它赋予一种语义,将其解读为“任何自然数都能整除自己”,这就是一个“真命题”;也可以赋予它另一种语义,将其解读为“任何实数都小于自己”,就变成了一个“假命题”。

Structures

\(\newcommand{\R}{\mathbb{R}}\newcommand{\N}{\mathbb{N}}\)在一阶逻辑中,由于量词的存在,首先需要确定我们讨论的数学对象的“范围”。因为这关系到当你说“对于任意\(x\)”时,你究竟说的对于任意实数,还是对于任意整数,还是对于任意平面,等等。因此,我们首先要指定一个集合,这个称为论域(universe),记为\(A\)。指定论域之后,符号集的论域也随之确定。一个\(n\)元关系就是某个\(A^n\)的子集,例如当我们说实数\(a,b\)满足小于关系,就是指有序对\((a,b)\)落在\(\R^2\)的子集\(\{(a,b)\mid a,b\in \R,a<b\}\)当中;同理,一个\(n\)元函数就是某个\(A^n\to A\)的映射。每个常数符号对应\(A\)中某个特定的元素。

指定论域以后,我们需要指定符号集中每个符号的数学含义。我们把这个从符号到其具体含义的映射记为\(\mathfrak{a}\),根据定义\(\mathfrak{a}(R)\subseteq A^n\)\(\mathfrak{a}(f):A^n\to A\)\(\mathfrak{a}(c_i)\in A\)。例如,如果我们指定符号\(R\)表示实数上的小于关系,那么\(\mathfrak{a}\)就会把\(R\)映射到\(\mathbb{R}^2\)的子集\(\{(x,y)\mid x<y\}\)

指定了\(A\)\(\mathfrak{a}\)以后,所有sentence(不含自由变量的formula)的语义就已经被完全解释了。虽然我们还没有通过结构归纳法严格定义如何从\(A\)\(\mathfrak{a}\)确定语义,但我们可以通过例子看到这一点:假设我们已经指定\(A\)为实数集\(\mathbb{R}\)\(R\)为实数上的小于关系,那么\(\forall v_0Rv_0v_0\)的语义就是“对于任意实数\(x\),我们有\(x<x\)”。

由此可见,二元组\((A,\mathfrak{a})\)本身已经为很大一部分一阶逻辑formula赋予了语义(并且根据我们对sentence的理解,是“重要的”那部分)。我们把二元组\((A,\mathfrak{a})\)记为\(\mathfrak{A}\),称为一个\(S\)上的结构(\(S\)-structure)。\(\A\)确定了所有变量的“定义域”和符号集中每个符号的数学含义。为了方便,常把\(\mathfrak{a}(f)\)简记为\(f^\mathfrak{A}\)

例如,对于符号集\(S=\{+,\cdot,<,\)\(0,1\}\),其中\(+,\cdot\)是二元函数符号,\(<\)是二元关系符号,\(0,1\)是常数符号。取\(A=\N\)\(\mathfrak{a}(+)\)为自然数的加法运算,\(\mathfrak{a}(\cdot)\)为自然数的乘法运算,\(\mathfrak{a}(<)\)为自然数的序关系;\(\mathfrak{a}(0),\mathfrak{a}(1)\)为自然数上的加法单位元和乘法单位元这两个常数。这样\(\mathfrak{A}=(\N,\mathfrak{a})\)就是一个自然数算数的structure,常记为\(\mathfrak{N}^<\),为了方便也可以展开写作\((\N,+^\N,\cdot^\N,<^\N,0^\N,1^\N)\)

Interpretations

在确定了structure以后,我们给变量赋值。我们给出一个\(v_i\to A\)的映射\(\beta\),这个映射称为赋值(assignment)。有了\(\mathfrak{A}\)\(\beta\),我们就应当可以确定每个term和formula的语义。所以,我们把一个\(S\)-structure和一个\(S\)-assignment的二元组称为一个\(S\)下的解释(\(S\)-interpretation),记为\(\I=(\mathfrak{A},\beta)\)

基于结构归纳,定义term的语义为:

  • \(\I(v_i)=\beta(v_i)\)
  • \(\I(c_i)=c_i^\mathfrak{A}\)
  • \(\I(ft_1\cdots t_n)=f^\A(\I(t_1),\cdots,\I(t_n))\)

formula的语义定义如下:(我们用\(\I(\varphi)=true\)来表示\(\varphi\)的语义为真,\(\I(\varphi)=false\)来表示\(\varphi\)的语义为假。)

  • \(\I(t_1\equiv t_2)=true\)当且仅当“\(\I(t_1)\)\(\I(t_2)\)是论域当中的同一个元素”为真;
  • \(\I(Rt_1\cdots t_n)=true\)当且仅当“\(n\)元关系\(R^\A(\I(t_1),\cdots,\I(t_n))\)成立”为真;
  • \(\I(\neg\varphi)=true\)当且仅当“\(\I(\varphi)=false\)”;
  • \(\I(\varphi\land \psi)=true\)当且仅当“\(\I(\varphi)\)并且\(\I(\psi)=true\)”为真;
  • \(\I(\varphi\land \psi)=true\)当且仅当“\(\I(\varphi)=true\)或者\(\I(\psi)=true\)”为真;
  • \(\I(\varphi\to \psi)=true\)当且仅当“\(\I(\varphi)=false\),或者\(\I(\psi)=true\)\(\I(psi)=true\)”为真;
  • \(\I(\varphi\leftrightarrow\psi)=true\)当且仅当“\(\I(\varphi)=true\)\(\I(\psi)=true\),或者\(\I(\varphi)=false\)\(\I(\psi)=false\)”为真;

当变量出现在量词中时,我们实际上并不关心该变量的赋值。\(\I(\forall x\varphi)=true\)想表达的是,用论域中的每个元素代入\(\varphi\)中出现的所有\(x\),同时保持其它的变量的赋值不变,都有\(\varphi\)始终为真。为此,我们需要一个描述为formula中的某个特定变量赋特殊的值的方便的符号。对于变量\(x,y\)\(a\in A\),定义\(\beta \frac{a}{x}(y):=\begin{cases}\beta(y) & ,y\neq x\\a&,y=x\end{cases}\),表示在原赋值\(\beta\)中把变量\(x\)的赋值强制修改为\(a\)。相应地,\(\I\dfrac{a}{x}:=(\A,\beta\dfrac{a}{x})\)。这样,我们就可以给出带量词的formula的语义的定义:

  • \(\I(\forall x\varphi)=true\)当且仅当“对于任意\(A\)中的元素\(a\)都有\(\I\dfrac{a}{x}(\varphi)=true\)”为真;
  • \(\I(\exists x\varphi)\)当且仅当“存在\(A\)中的元素\(a\)使得\(\I\dfrac{a}{x}(\varphi)=true\)”为真;

Remark: 对于sentence,我们在讨论语义时给出structure就足够了。此时我们可以把\(\I(\varphi) =true\)简写为\(\A(\varphi)=true\)

和命题逻辑中一样,我们可以定义语义性质和语义关系:

\(S\)-formula \(\varphi\)是永真式,如果在任何解释\(\I\)下都有\(\I(\varphi)=true\),用符号“\(\models \varphi\)”来表示;例如\(\forall x(x\equiv x)\)

\(S\)-formula \(\varphi\)是可满足的,如果存在解释\(\I\)使得\(\I(\varphi)=true\),用符号“\(\text{Sat }\varphi\)”来表示;

在选定符号集\(S\)以后,对于两个\(S\)-formula \(\varphi,\psi\),如果对于任何一个解释\(\I\)都成立“只要\(\I(\varphi)=true\),就有\(\I(\psi)=true\)”,就称\(\psi\)\(\varphi\)的语义后承,记为\(\varphi \models \psi\)

\(\Phi\)是一个\(S\)-formula集合,\(\psi\)是一个\(S\)-formula。如果对于任何一个解释\(\I\)都成立“只要满足‘所有\(\varphi\in \Phi\)都有\(\I(\varphi)=true\)’,就有‘\(\I(\psi)=true\)’”,就称命题\(\psi\)是命题集合\(\Phi\)的语义后承,用同样的符号记为\(\Phi \models \psi\)

对于两个\(S\)-formula \(\varphi,\psi\),如果对于任何一个解释\(\I\)都成立“\(\I(\varphi)=true\)当且仅当\(\I(\psi)=true\)”,就称\(\varphi,\psi\)是语义等价的。

由结构归纳以及真值表可以证明:

  • \(\varphi\to\psi\)等价于\(\neg \varphi \lor \psi\)
  • \(\varphi \leftrightarrow \psi\)等价于\(\neg(\varphi\lor \psi)\lor \neg(\neg \varphi \lor \neg\psi)\)
  • \(\forall x \varphi\)等价于\(\neg \exists x\neg \varphi\)

由此可见,一阶逻辑中符号\(\{\neg,\lor,\exists\}\)有功能完全性。在之后做formula的结构归纳时,我们只需对这三个符号做归纳。

The Coincidence Lemma

对于两个不同的interpretation \(\I_1,\I_2\),什么时候它们对一个term \(t\)的解释是相同的?自然,如果\(\I_1\)\(\I_2\)本身有相同的universe,对符号集的交集有相同的解释, 对\(t\)中的每个变量有相同的解释,那么就一定满足\(\I_1(t)=\I_2(t)\)

什么时候两个不同的interpretation \(\I_1,\I_2\)对一个formula \(\varphi\)有相同的解释?是相同的?自然,如果\(\I_1\)\(\I_2\)本身有相同的universe,对符号集的交集有相同的解释,对\(\varphi\)中的自由变量有相同解释,那么就一定满足\(\I_1(\varphi)=\I_2(\varphi)\)

我们把以上两点总结成一条引理,称为The Coincidence Lemma:如果\(\I_1\)\(\I_2\)有相同的universe \(A\),在符号集的交集\(S_1\cap S_2\)上对符号都有相同的解释,那么:

  • 如果\(\I_1\)\(\I_2\)在所有\(t\)的变量上有相同解释,就成立\(\I_1(t)=\I_2(t)\)
  • 如果\(\I_1\)\(\I_2\)\(\varphi\)的所有自由变元上有相同解释,就成立\(\I_1(\varphi)=\I_2(\varphi)\)

通过简单的结构归纳即可证明。

The Isomorphism Lemma

现在考虑\(\varphi\)是sentence,此时\(\I_1(\varphi)=\I_2(\varphi)\)只需要更弱的条件。首先,对于sentence我们只需退回到structure层面做讨论。其次,我们可以定义structure之间的同构关系(isomorphism),而不再要求universe和符号集的解释完全相同。两个同构的structure本质上是完全相同的,只是元素和符号的名称不同。定义如下:

对于两个\(S\)-structure \(\A\)\(\mathfrak{B}\),如果它们对应的universe \(A,B\)存在一个\(A\to B\)的双射\(\pi\),并且对于\(S\)中的任何\(n\)元关系符号\(R\)成立\((a_1,\cdots,a_n)\in R^\A\) \(\iff (\pi(a_1),\cdots,\pi(a_n))\)\(\in R^\mathfrak{B}\),对于\(S\)中的任何\(n\)元函数符号\(f\)成立\(\pi(f^\A(a_1,\cdots,a_n))\) \(=f^\mathfrak{B}(\pi(a_1),\cdots,\pi(a_n))\),对于\(S\)中的任何常数符号\(c\)成立\(\pi(c^\A)=c^\mathfrak{B}\),就称\(\A,\mathfrak{B}\)是同构的,记为\(\A\cong \mathfrak{B}\)。容易证明isomorphism关系是一种等价关系,也即满足自反、对称、传递三条性质。

如果\(\A\cong \mathfrak{B}\),那么对于任意\(S\)-sentence \(\varphi\),成立\(\A(\varphi)=true\iff \mathfrak{B}(\varphi)=true\),这称为The Isomorphism Lemma。

这一引理可以通过对formula的结构归纳严格证明(注意,不能对sentence归纳,因为sentence是基于formula定义的对变量有特殊限制的formula,不存在对sentence的归纳定义)。

特别需要指出的一点是,The Isomorphism Lemma的逆命题是错误的。“\(\A(\varphi)=true\iff \mathfrak{B}(\varphi)=true\)对任意\(S\)-sentence \(\varphi\)成立”不能推出\(\A,\mathfrak{B}\)是同构的。然而这一点在符号集\(S\)是有限的时候是正确的,因为此时我们可以构造一个sentence,使得满足这个sentence的structure一定具有唯一的结构。然而当\(S\)是无限集的时候,就无法用同样的方法构造出这样的sentence了(因为sentence必须是有限长的)。严格的证明这里就不写出了。

The Substitution Lemma

在数学上,我们经常会用到代入(substitution)这一操作:代入操作是指对于某个term \(t\)或formula \(\varphi\),将其中的某个变量\(x\)替换为某个term \(t'\)

term的代入操作是简单的,应当就是在字符串意义上把所有\(x\)出现的地方简单地替换为\(t'\)。对于term \(t\),把“同时把\(t\)中的\(x_1\)代换为\(t_1\)\(\cdots\)\(x_n\)代换为\(t_n\)”这一操作记为\([t]\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\),定义:(这里的中括号和横线并不是一阶逻辑符号,只是一个“记号”,在不会引起歧义的场合可以省略)

  • \(x\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}:=\begin{cases}t_i & ,x=x_i\\ x&,\text{otherwise}\end{cases}\)

  • \(c\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}:=c\)

  • \([ft_1'\cdots t_n']\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}:=f[t_1']\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\cdots [t_n']\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\)

然而我们发现,formula中的代入操作并不应当只是在字符串意义上把所有\(x\)出现的地方替换为\(t\)。这是由量词引发的问题,考虑这样一个例子:\(\exists z \ z+z\equiv x\),在自然数运算的解释\((\mathfrak{N},\beta)\)下这个formula的语义是“\(\beta(x)\)是偶数”。所以我们期待如果我们把任何变量\(y\)“代入”\(x\),它的语义都是“\(\beta(y)\)是偶数”。然而,如果我们把出现在量词中的\(z\)代入\(x\),得到的是\(\exists z \ z+z\equiv z\),这个formula的语义显然不是“\(\beta(z)\)是偶数”而是“存在自然数与自己的和等于自身”,也即“\(0\)是自然数”。如果替换新的存在量词,\(\exists u \ u+u\equiv z\),语义就满足了。所以,我们在代入时应当对量词中的变量做一些特别的关照。对于formula \(\varphi\),把“同时把\(\varphi\)中的\(x_1\)代换为\(t_1\)\(\cdots\)\(x_n\)代换为\(t_n\)”这一操作记为\([\varphi]\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\),定义:(有了语义等价,我们可以减少一些归纳的情况了)

  • \([t_1'\equiv t_2']\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}:=[t_1']\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\equiv [t_2']\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\)
  • \([Rt_1'\cdots t_n']\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}:=R[t_1']\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\cdots [t_n']\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\)
  • \([\neg \varphi]\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}:=\neg [\varphi]\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\)
  • \([ (\varphi \lor \psi)]\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}:=\left([\varphi]\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\lor [\psi] \dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\right)\)
  • 对于\([\exists x\varphi]\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}\),取出\(x_1,\cdots,x_r\)中那些属于\(\free(\exists x\varphi)\)\(x_i\neq t_i\)的变量构成一个子列\(x_{i_1},\cdots,x_{i_s}\)。如果\(x\)不在\(t_{i_1},\cdots,t_{i_s}\)当中出现,那么\([\exists x\varphi]\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}:=[\exists x\varphi]\dfrac{t_{i_1},\cdots,t_{i_s}}{x_{i_1},\cdots,x_{i_s}}\) ;否则,\([\exists x\varphi]\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r}:=[\exists u\varphi]\dfrac{t_{i_1},\cdots,t_{i_s},u}{x_{i_1},\cdots,x_{i_s},x}\),其中\(u\)是不在\(t_{i_1},\cdots,t_{i_s},\varphi\)中出现的变量,且是\(v_0,v_1,\cdots\)中下标最小的那个;

我们来理解我们对量词替换的修正。首先,对非自由变量的替换没有意义,把自己替换成自己也没有意义;其次,应当保证新的量词变量不在替换后的项中出现,如果不需要修改量词变量就不修改,否则就修改为从未出现过的一个变量,为了定义的确定性我们规定选择下标最小的那个。

以上替换规则是基于我们想让“替换后语义得以保持”的愿望定义的一系列字符串变换操作。简而言之它会把term中所有想要替换的变量替换成新的项,把formula中的想要替换的自由变量替换成新的项。我们需要验证,这样的变换确实“保持了语义”。而对语义的保持与否体现在用于解释这些term和formula的interpretation中赋值函数\(\beta\)是否发生了“合理的变化”。首先,我们推广赋值函数上“替换”的概念:定义\(\beta \dfrac{a_1,\cdots,a_r}{x_1,\cdots,x_r}(y):=\begin{cases}\beta(y) & ,y\neq x_1,\cdots,y\neq x_r\\a_i&,y=x_i\end{cases}\)\(\I\dfrac{a_1,\cdots,a_r}{x_1,\cdots,x_r}:=\left(\A,\beta\dfrac{a_1,\cdots,a_r}{x_1,\cdots,x_r}\right)\)。对于任意interpretation \(\I\),我们想要验证以下两件事成立:

  • 对于任意term \(t\),始终成立\(\I(t\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r})=\)\(\I\dfrac{\I(t_1),\cdots,\I(t_r)}{x_1,\cdots,x_r}(t)\)
  • 对于任意formula \(\varphi\),始终成立\(\I(\varphi\dfrac{t_1,\cdots,t_r}{x_1,\cdots,x_r})= \I\dfrac{\I(t_1),\cdots,\I(t_r)}{x_1,\cdots,x_r}(\varphi)\)

再一次,我们可以用结构归纳说明以上两点确实成立。这称为The Substitution Lemma。这说明以上定义的“语法”上的替换方案确实达到了我们想在“语义”上达成的目的。


我在Lean中形式化了以上定义和定理:

import Mathlib
namespace FirstOrderLogic
open Classical

structure SymbolSet where
  RelSymbol : Nat → Type
  FuncSymbol : Nat → Type
  ConstSymbol : Type

inductive Term (S : SymbolSet) where
  | Var (i : Nat) : Term S
  | Const (c : S.ConstSymbol) : Term S
  | Func (n : Nat) (f : S.FuncSymbol n) (args : Fin n → Term S) : Term S

inductive Formula (S : SymbolSet) where
  | Eq (t1 t2 : Term S) : Formula S
  | Rel (n : Nat) (R : S.RelSymbol n) (args : Fin n → Term S) : Formula S
  | Neg (φ : Formula S) : Formula S
  | And (φ ψ : Formula S) : Formula S
  | Forall (x : Nat) (φ : Formula S) : Formula S

def Formula.Or {S : SymbolSet} (φ ψ : Formula S) : Formula S :=
  Formula.Neg (Formula.And (Formula.Neg φ) (Formula.Neg ψ))

def Formula.Imply {S : SymbolSet} (φ ψ : Formula S) : Formula S :=
  Formula.Neg (Formula.And φ (Formula.Neg ψ))

def Formula.Iff {S : SymbolSet} (φ ψ : Formula S) : Formula S :=
  Formula.And (Formula.Imply φ ψ) (Formula.Imply ψ φ)

def Formula.Exists {S : SymbolSet} (x : Nat) (φ : Formula S) : Formula S :=
  Formula.Neg (Formula.Forall x (Formula.Neg φ))

def VarOfTerm (S : SymbolSet) (t : Term S) : List Nat :=
  match t with
  | Term.Var i => {i}
  | Term.Const _ => ∅
  | Term.Func _ _ args => (List.ofFn (fun i => VarOfTerm S (args i))).flatten

def ConstOfTerm (S : SymbolSet) (t : Term S) : Set S.ConstSymbol :=
  match t with
  | Term.Var _ => ∅
  | Term.Const c => {c}
  | Term.Func _ _ args => { x | ∃ i, x ∈ ConstOfTerm S (args i) }

def FuncOfTerm (S : SymbolSet) (t : Term S) : Set (Σ n, S.FuncSymbol n) :=
  match t with
  | Term.Var _ => ∅
  | Term.Const _ => ∅
  | Term.Func n f args => { ⟨n, f⟩ } ∪ { x | ∃ i, (x ∈ (FuncOfTerm S (args i))) }

def ConstOfFormula (S : SymbolSet) (φ : Formula S) : Set S.ConstSymbol :=
  match φ with
  | Formula.Eq t1 t2 => (ConstOfTerm S t1) ∪ (ConstOfTerm S t2)
  | Formula.Rel n _ args => { x | ∃ (j : Fin n), x ∈ (ConstOfTerm S (args j))}
  | Formula.Neg φ => ConstOfFormula S φ
  | Formula.And φ ψ => (ConstOfFormula S φ) ∪ (ConstOfFormula S ψ)
  | Formula.Forall _ φ => ConstOfFormula S φ

def FuncOfFormula (S : SymbolSet) (φ : Formula S) : Set (Σ n, S.FuncSymbol n) :=
  match φ with
  | Formula.Eq t1 t2 => (FuncOfTerm S t1) ∪ (FuncOfTerm S t2)
  | Formula.Rel n _ args => { x | ∃ (j : Fin n), x ∈ (FuncOfTerm S (args j))}
  | Formula.Neg φ => FuncOfFormula S φ
  | Formula.And φ ψ => (FuncOfFormula S φ) ∪ (FuncOfFormula S ψ)
  | Formula.Forall _ φ => FuncOfFormula S φ

def RelOfFormula (S : SymbolSet) (φ : Formula S) : Set (Σ n, S.RelSymbol n) :=
  match φ with
  | Formula.Eq _ _ => ∅
  | Formula.Rel n R _ => {⟨n, R⟩}
  | Formula.Neg φ => RelOfFormula S φ
  | Formula.And φ ψ => (RelOfFormula S φ) ∪ (RelOfFormula S ψ)
  | Formula.Forall _ φ => RelOfFormula S φ

def Freevar (S : SymbolSet) (φ : Formula S) : List Nat :=
  match φ with
  | Formula.Eq t1 t2 => (VarOfTerm S t1) ++ (VarOfTerm S t2)
  | Formula.Rel _ _ args => (List.ofFn (fun i => VarOfTerm S (args i))).flatten
  | Formula.Neg ψ => Freevar S ψ
  | Formula.And ψ ξ => (Freevar S ψ) ++ (Freevar S ξ)
  | Formula.Forall x ψ => (Freevar S ψ).filter (fun y => y != x)

def Universe := Type

structure SymbolInterp (S : SymbolSet) (A : Universe) where
  RelInterp (n : Nat) (R : S.RelSymbol n) : (Fin n → A) → Prop
  FuncInterp (n : Nat) (f : S.FuncSymbol n) : (Fin n → A) → A
  ConstInterp (c : S.ConstSymbol) : A

structure Model (S : SymbolSet) where
  A : Universe
  a : SymbolInterp S A

def Assignment (A : Universe) := Nat → A

structure Interp (S : SymbolSet) where
  𝔸 : Model S
  β : Assignment 𝔸.A

def TermEval (S : SymbolSet) (I : Interp S) (t : Term S) : I.𝔸.A :=
  match t with
  | Term.Var i => I.β i
  | Term.Const c => I.𝔸.a.ConstInterp c
  | Term.Func n f args => I.𝔸.a.FuncInterp n f (fun i => TermEval S I (args i))

def FormulaEval (S : SymbolSet) (I : Interp S) (φ : Formula S) : Prop :=
  match φ with
  | Formula.Eq t1 t2 => (TermEval S I t1) = (TermEval S I t2)
  | Formula.Rel n R args => I.𝔸.a.RelInterp n R (fun i => TermEval S I (args i))
  | Formula.Neg φ => ¬ (FormulaEval S I φ)
  | Formula.And φ ψ => (FormulaEval S I φ) ∧ (FormulaEval S I ψ)
  | Formula.Forall x φ => ∀ (d : I.𝔸.A), FormulaEval S { 𝔸 := I.𝔸, β := fun y => if y = x then d else I.β y } φ

def FormulaEval_model (S : SymbolSet) (𝔸 : Model S) (φ : Formula S) : Prop :=
  ∀ (β : Assignment 𝔸.A), FormulaEval S { 𝔸 := 𝔸, β := β } φ

theorem The_Coincidence_Lemma_term
  (S : SymbolSet)
  (A : Type)
  (a1 a2 : SymbolInterp S A)
  (β1 β2 : Assignment A)
  (t : Term S)
  (h_const : ∀ c ∈ ConstOfTerm S t, a1.ConstInterp c = a2.ConstInterp c)
  (h_func : ∀ (n : Nat) (f : S.FuncSymbol n), ⟨n, f⟩ ∈ FuncOfTerm S t → a1.FuncInterp n f = a2.FuncInterp n f)
  (h_var : ∀ x ∈ VarOfTerm S t, β1 x = β2 x)
  :
  let I1 := { 𝔸 := { A := A, a := a1 }, β := β1 }
  let I2 := { 𝔸 := { A := A, a := a2 }, β := β2 }
  TermEval S I1 t = TermEval S I2 t
:= by
  induction t with
  | Var i =>
    simp [TermEval]
    apply h_var
    simp [VarOfTerm]
    exact List.mem_of_mem_head? rfl
  | Const c =>
    simp [TermEval]
    apply h_const
    simp [ConstOfTerm]
  | Func n f args ih =>
    simp [TermEval]
    let h1 := h_func n f
    rw [h1]
    · congr
      funext i
      apply ih
      · intro c hc
        apply h_const
        simp [ConstOfTerm]
        use i
      · intro n' f' hf'
        apply h_func
        simp [FuncOfTerm]
        right
        use i
      · intro x hv
        apply h_var
        simp [VarOfTerm]
        use i
    · simp [FuncOfTerm]

theorem The_Coincidence_Lemma_formula
  (S : SymbolSet)
  (A : Type)
  (a1 a2 : SymbolInterp S A)
  (β1 β2 : Assignment A)
  (φ : Formula S)
  (h_func : ∀ (n : Nat) (f : S.FuncSymbol n), ⟨n, f⟩ ∈ FuncOfFormula S φ → a1.FuncInterp n f = a2.FuncInterp n f)
  (h_rel : ∀ (n : Nat) (R : S.RelSymbol n), ⟨n, R⟩ ∈ RelOfFormula S φ → a1.RelInterp n R = a2.RelInterp n R)
  (h_const : ∀ c ∈ ConstOfFormula S φ, a1.ConstInterp c = a2.ConstInterp c)
  (h_freevar : ∀ x ∈ Freevar S φ, β1 x = β2 x)
  :
  let I1 := { 𝔸 := { A := A, a := a1 }, β := β1 }
  let I2 := { 𝔸 := { A := A, a := a2 }, β := β2 }
  FormulaEval S I1 φ ↔ FormulaEval S I2 φ
:= by
  revert β1 β2
  induction φ with
  | Eq t1 t2 =>
    intro β1 β2 h_freevar
    simp [FormulaEval]
    apply Eq.congr
    · apply The_Coincidence_Lemma_term
      · intro c hc
        apply h_const
        simp [ConstOfFormula]
        left
        exact hc
      · intro n f hf
        apply h_func
        simp [FuncOfFormula]
        left
        exact hf
      · intro x hx
        apply h_freevar
        simp [Freevar]
        left
        exact hx
    · apply The_Coincidence_Lemma_term
      · intro c hc
        apply h_const
        simp [ConstOfFormula]
        right
        exact hc
      · intro n f hf
        apply h_func
        simp [FuncOfFormula]
        right
        exact hf
      · intro x hx
        apply h_freevar
        simp [Freevar]
        right
        exact hx
  | Rel n R args =>
    intro β1 β2 h_freevar
    simp [FormulaEval]
    let h0 := h_rel n R
    rw [h0]
    · apply Eq.to_iff
      congr
      funext i
      apply The_Coincidence_Lemma_term
      · intro c hc
        apply h_const
        simp [ConstOfFormula]
        use i
      · intro n f hf
        apply h_func
        simp [FuncOfFormula]
        use i
      · intro x hx
        apply h_freevar
        simp [Freevar]
        use i
    · simp [RelOfFormula]
  | Neg φ ih =>
    intro β1 β2 h_freevar
    simp [FormulaEval]
    apply not_congr
    apply ih
    · intro n f hf
      apply h_func
      simp [FuncOfFormula]
      exact hf
    · intro n R hR
      apply h_rel
      simp [RelOfFormula]
      exact hR
    · intro c hc
      apply h_const
      simp [ConstOfFormula]
      exact hc
    · intro x hx
      apply h_freevar
      simp [Freevar]
      exact hx
  | And φ ψ ih1 ih2 =>
    intro β1 β2 h_freevar
    simp [FormulaEval]
    apply and_congr
    · apply ih1
      · intro n f hf
        apply h_func
        simp [FuncOfFormula]
        left
        exact hf
      · intro n R hR
        apply h_rel
        simp [RelOfFormula]
        left
        exact hR
      · intro c hc
        apply h_const
        simp [ConstOfFormula]
        left
        exact hc
      · intro x hx
        apply h_freevar
        simp [Freevar]
        left
        exact hx
    · apply ih2
      · intro n f hf
        apply h_func
        simp [FuncOfFormula]
        right
        exact hf
      · intro n R hR
        apply h_rel
        simp [RelOfFormula]
        right
        exact hR
      · intro c hc
        apply h_const
        simp [ConstOfFormula]
        right
        exact hc
      · intro x hx
        apply h_freevar
        simp [Freevar]
        right
        exact hx
  | Forall x φ ih =>
    intro β1 β2 h_freevar
    simp [FormulaEval]
    apply forall_congr'
    intro a
    apply ih
    · intro n f hf
      apply h_func
      simp [FuncOfFormula]
      exact hf
    · intro n R hR
      apply h_rel
      simp [RelOfFormula]
      exact hR
    · intro c hc
      apply h_const
      simp [ConstOfFormula]
      exact hc
    · intro x' hx'
      by_cases hxeqx' :(x = x')
      · simp [hxeqx']
      · have hxeqx'' : ¬ x' = x := by tauto
        simp [hxeqx'']
        apply h_freevar
        simp [Freevar]
        tauto

structure ModelIso (S : SymbolSet) (𝔸 𝔹 : Model S) extends 𝔸.A ≃ 𝔹.A where
  map_rel : ∀ (n : Nat) (R : S.RelSymbol n) (args : Fin n → 𝔸.A), 𝔸.a.RelInterp n R args ↔ 𝔹.a.RelInterp n R (toFun ∘ args)
  map_func : ∀ (n : Nat) (f : S.FuncSymbol n) (args : Fin n → 𝔸.A), toFun (𝔸.a.FuncInterp n f args) = 𝔹.a.FuncInterp n f (toFun ∘ args)
  map_const : ∀ (c : S.ConstSymbol), toFun (𝔸.a.ConstInterp c) = 𝔹.a.ConstInterp c

def IsomorphicModel (S : SymbolSet) (𝔸 𝔹 : Model S) : Prop := Nonempty (ModelIso S 𝔸 𝔹)

lemma term_isomorphism_with_assignment
  (S : SymbolSet)
  (𝔸 𝔹 : Model S)
  (π : ModelIso S 𝔸 𝔹)
  (β : Assignment 𝔸.A)
  (t : Term S)
  :
  π.toFun (TermEval S { 𝔸 := 𝔸, β := β } t) = TermEval S { 𝔸 := 𝔹, β := π.toFun ∘ β } t
:= by
  induction t with
  | Var i =>
    simp [TermEval]
  | Const c =>
    simp [TermEval]
    apply π.map_const
  | Func n f args ih =>
    simp only [TermEval]
    rw [π.map_func]
    congr
    funext i
    apply ih

lemma formula_isomorphism_with_assignment
  (S : SymbolSet)
  (𝔸 𝔹 : Model S)
  (π : ModelIso S 𝔸 𝔹)
  (β : Assignment 𝔸.A)
  (φ : Formula S)
  :
  FormulaEval S { 𝔸 := 𝔸, β := β } φ ↔ FormulaEval S { 𝔸 := 𝔹, β := π.toFun ∘ β } φ
:= by
  revert β
  induction φ with
  | Eq t1 t2 =>
    intro β
    simp only [FormulaEval]
    rw [← term_isomorphism_with_assignment S 𝔸 𝔹 π β t1, ← term_isomorphism_with_assignment S 𝔸 𝔹 π β t2]
    exact Iff.symm (Equiv.apply_eq_iff_eq π.toEquiv)
  | Rel n R args =>
    intro β
    simp only [FormulaEval]
    rw [π.map_rel]
    apply Eq.to_iff
    congr
    funext i
    apply term_isomorphism_with_assignment S 𝔸 𝔹 π β (args i)
  | Neg φ ih =>
    intro β
    simp only [FormulaEval]
    exact not_congr (ih β)
  | And φ ψ ih1 ih2 =>
    intro β
    simp only [FormulaEval]
    exact and_congr (ih1 β) (ih2 β)
  | Forall x φ ih =>
    intro β
    simp only [FormulaEval]
    apply Equiv.forall_congr π.toEquiv
    intro a
    let ih' := ih (fun y ↦ if y = x then a else β y)
    rw [ih']
    apply Eq.to_iff
    congr
    funext y
    by_cases hcases: y = x
    · exact apply_ite π.toFun (y = x) a (β y)
    · exact apply_ite π.toFun (y = x) a (β y)

theorem The_Isomorphism_Lemma
  (S : SymbolSet)
  (𝔸 𝔹 : Model S)
  (h_iso : IsomorphicModel S 𝔸 𝔹)
  (φ : Formula S)
  :
  FormulaEval_model S 𝔸 φ ↔ FormulaEval_model S 𝔹 φ
:= by
  cases h_iso with | intro π =>
  · simp [FormulaEval_model]
    constructor
    · intro h0 β
      let hlemma := formula_isomorphism_with_assignment S 𝔸 𝔹 π (π.invFun ∘ β) φ
      specialize h0 (π.invFun ∘ β)
      rw [hlemma] at h0
      have to_inv_eq_id : π.toFun ∘ π.invFun ∘ β = β := by
        funext x
        simp
      rw [to_inv_eq_id] at h0
      exact h0
    · intro h0 β
      let hlemma := formula_isomorphism_with_assignment S 𝔸 𝔹 π β φ
      specialize h0 (π.toFun ∘ β)
      rw [← hlemma] at h0
      exact h0

def VarSubstitution (S : SymbolSet) (x : Nat) (sublist : List (Nat × Term S)) : Term S :=
  match sublist with
  | [] => Term.Var x
  | (y, t) :: res => if x = y then t else VarSubstitution S x res

def TermSubstitution (S : SymbolSet) (t : Term S) (sublist : List (Nat × Term S)) : Term S :=
  match t with
  | Term.Var x => VarSubstitution S x sublist
  | Term.Const c => Term.Const c
  | Term.Func n f args => Term.Func n f (fun i => TermSubstitution S (args i) sublist)

def ListMax (l : List Nat) : Nat := l.foldr max 0

def TermMaxVar (S : SymbolSet) (t : Term S) : Nat :=
  match t with
  | Term.Var i => i
  | Term.Const _ => 0
  | Term.Func _ _ args => ListMax (List.ofFn (fun i => TermMaxVar S (args i)))

def MaxVarInFormula (S : SymbolSet) (φ : Formula S) : Nat :=
  match φ with
  | Formula.Eq t1 t2 => max (TermMaxVar S t1) (TermMaxVar S t2)
  | Formula.Rel _ _ args => ListMax (List.ofFn (fun i => TermMaxVar S (args i)))
  | Formula.Neg φ => MaxVarInFormula S φ
  | Formula.And φ ψ => max (MaxVarInFormula S φ) (MaxVarInFormula S ψ)
  | Formula.Forall x φ => max x (MaxVarInFormula S φ)

def MaxVarInSublist (S : SymbolSet) (sublist : List (Nat × Term S)) : Nat :=
  ListMax ((sublist.map (fun p => p.2)).map (TermMaxVar S))

def FormulaRank (S : SymbolSet) (φ : Formula S) : Nat :=
  match φ with
  | Formula.Eq _ _ => 0
  | Formula.Rel _ _ _ => 0
  | Formula.Neg ψ => (FormulaRank S ψ) + 1
  | Formula.And ψ ξ => (FormulaRank S ψ) + (FormulaRank S ξ) + 1
  | Formula.Forall _ ψ => (FormulaRank S ψ) + 1

def FormulaSubstitution (S : SymbolSet) (φ : Formula S) (sublist : List (Nat × Term S)) : Formula S :=
  match φ with
  | Formula.Eq t1 t2 => Formula.Eq (TermSubstitution S t1 sublist) (TermSubstitution S t2 sublist)
  | Formula.Rel n R args => Formula.Rel n R (fun i => TermSubstitution S (args i) sublist)
  | Formula.Neg ψ => Formula.Neg (FormulaSubstitution S ψ sublist)
  | Formula.And ψ ξ => Formula.And (FormulaSubstitution S ψ sublist) (FormulaSubstitution S ξ sublist)
  | Formula.Forall x ψ =>
      let sublist' := sublist.filter (fun p => (p.1 ∈ (Freevar S (Formula.Forall x ψ))))
      if sublist'.isEmpty then
        Formula.Forall x ψ
      else
        let u := (max (MaxVarInFormula S ψ) (MaxVarInSublist S sublist')) + 1
        Formula.Forall u (FormulaSubstitution S ψ ((x, Term.Var u) :: sublist'))
termination_by FormulaRank S φ
decreasing_by
  all_goals
    simp only [FormulaRank]
    linarith

lemma substitution_preserves_formula_rank (S : SymbolSet) (φ : Formula S) (sublist: List (Nat × Term S)) : (FormulaRank S (FormulaSubstitution S φ sublist)) = (FormulaRank S φ)
:= by
  revert sublist
  induction φ with
  | Eq t1 t2 =>
    intro sublist
    simp only [FormulaSubstitution, FormulaRank]
  | Rel n R args =>
    intro sublist
    simp only [FormulaSubstitution, FormulaRank]
  | Neg φ ih =>
    intro sublist
    simp only [FormulaSubstitution, FormulaRank]
    apply Nat.succ_inj'.mpr
    apply ih
  | And φ ψ ih1 ih2 =>
    intro sublist
    simp only [FormulaSubstitution, FormulaRank]
    rw [ih1 sublist, ih2 sublist]
  | Forall x φ ih =>
    intro sublist
    simp only [FormulaSubstitution, FormulaRank]
    split_ifs with h0
    · rfl
    · simp only [FormulaRank]
      rw [ih]

def AssignmentSubstitution (S : SymbolSet) (A : Universe) (β : Assignment A) (sublist : List (Nat × A)) : Assignment A :=
  fun y =>
    match sublist with
    | [] => β y
    | (x, a) :: res => ((if x = y then a else (AssignmentSubstitution S A β res) y))

theorem The_Substitution_Lemma_term
  (S : SymbolSet)
  (I : Interp S)
  (t : Term S)
  (sublist : List (Nat × Term S))
  :
  TermEval S I (TermSubstitution S t sublist) = TermEval S { 𝔸 := I.𝔸, β := (AssignmentSubstitution S I.𝔸.A I.β (sublist.map (fun p => (p.1, TermEval S I p.2)))) } t
:= by
  induction t with
  | Var x =>
    simp only [TermSubstitution]
    induction sublist with
    | nil =>
      simp [AssignmentSubstitution, VarSubstitution]
    | cons cur res ih =>
      simp [AssignmentSubstitution, VarSubstitution]
      by_cases heq : (x = cur.1)
      · simp [heq, TermEval]
      · simp [heq, TermEval]
        split_ifs with hif
        · rw [hif] at heq
          tauto
        · apply ih
  | Const c =>
    simp only [TermSubstitution, TermEval]
  | Func n f args ih =>
    simp only [TermSubstitution, TermEval]
    congr
    funext i
    apply ih

lemma assignment_subst_empty_eq_self (S : SymbolSet) (A : Universe) (β : Assignment A) (l : List (Nat × A)) (x : Nat) (h : ∀ p ∈ l, p.1 ≠ x) : AssignmentSubstitution S A β l x = β x := by
  induction l with
  | nil =>
    simp [AssignmentSubstitution]
  | cons head tail ih =>
    simp [AssignmentSubstitution]
    have h_head_neq : head.1 ≠ x := h head (List.mem_cons_self _ _)
    rw [if_neg h_head_neq]
    apply ih
    intro p hp
    apply h p (List.mem_cons_of_mem _ hp)

lemma le_list_max (l : List Nat) (n : Nat) (h : n ∈ l) : n ≤ ListMax l := by
  induction l with
  | nil => contradiction
  | cons cur res ih =>
    simp [ListMax, List.foldr] at *
    rcases h with h1 | h2
    · left
      linarith
    · right
      apply ih
      exact h2

lemma max_var_in_sublist_le_cons (S : SymbolSet) (cur : Nat × Term S) (res : List (Nat × Term S)) :
  MaxVarInSublist S res ≤ MaxVarInSublist S (cur :: res) := by
  simp [MaxVarInSublist, ListMax, List.foldr]

lemma var_le_term_max_var (S : SymbolSet) (t : Term S) (x : Nat) :
  x ∈ VarOfTerm S t → x ≤ TermMaxVar S t := by
  induction t with
  | Var i =>
    simp [VarOfTerm, TermMaxVar]
    intro h1
    exact List.le_maximum_of_mem h1 rfl
  | Const c =>
    simp [VarOfTerm, TermMaxVar]
  | Func n f args ih =>
    simp [VarOfTerm, TermMaxVar]
    intro i h1
    have h0 := le_list_max (List.ofFn fun i ↦ TermMaxVar S (args i)) (TermMaxVar S (args i))
    trans TermMaxVar S (args i)
    · apply ih
      apply h1
    · apply h0
      simp

theorem max_var_in_term_le_sublist (S : SymbolSet)
  (t : Term S)
  (sublist : List (Nat × Term S))
  (h : ∃ k, (k, t) ∈ sublist) :
  TermMaxVar S t ≤ MaxVarInSublist S sublist
:= by
  rcases h with ⟨k, h⟩
  simp [MaxVarInSublist]
  have h0 := le_list_max (List.map (TermMaxVar S ∘ fun p ↦ p.2) sublist)
  apply h0
  simp
  use k
  use t

lemma var_le_max_var_in_formula (S : SymbolSet) (φ : Formula S) (x : Nat) :
  x ∈ Freevar S φ → x ≤ MaxVarInFormula S φ :=
by
  induction φ with
  | Eq t1 t2 =>
    simp [Freevar, MaxVarInFormula]
    intro h1
    rcases h1 with h2 | h3
    · left
      apply var_le_term_max_var
      apply h2
    · right
      apply var_le_term_max_var
      apply h3
  | Rel n R args =>
    simp [Freevar, MaxVarInFormula]
    intro i h1
    have h2 := var_le_term_max_var S (args i) x h1
    have h3 := le_list_max (List.ofFn fun i ↦ TermMaxVar S (args i)) (TermMaxVar S (args i))
    trans TermMaxVar S (args i)
    · exact h2
    · apply h3
      simp
  | Neg ψ ih =>
    simp [Freevar, MaxVarInFormula]
    exact ih
  | And ψ ξ ih1 ih2 =>
    simp [Freevar, MaxVarInFormula]
    intro h1
    rcases h1 with h2 | h3
    · left
      apply ih1 h2
    · right
      apply ih2 h3
  | Forall y ψ ih =>
    intro h1
    simp [Freevar] at h1
    rcases h1 with ⟨h2, h3⟩
    simp [MaxVarInFormula]
    right
    tauto

lemma fresh_var_subst_equivalence
  (S : SymbolSet)
  (I : Interp S)
  (d : I.𝔸.A)
  (sublist : List (Nat × Term S))
  (u1 u2 x : Nat)
  (h_u1_fresh : MaxVarInSublist S sublist < u1)
  (h_u2_fresh : MaxVarInSublist S sublist < u2)
  (h_x_u1 : x < u1)
  (h_x_u2 : x < u2)
  :
  AssignmentSubstitution S I.𝔸.A (fun y ↦ if y = u1 then d else I.β y)
    (sublist.map (fun p ↦ (p.1, TermEval S { 𝔸 := I.𝔸, β := fun y ↦ if y = u1 then d else I.β y } p.2))) x
  =
  AssignmentSubstitution S I.𝔸.A (fun y ↦ if y = u2 then d else I.β y)
    (sublist.map (fun p ↦ (p.1, TermEval S { 𝔸 := I.𝔸, β := fun y ↦ if y = u2 then d else I.β y } p.2))) x
:= by
  induction sublist with
  | nil =>
    simp [AssignmentSubstitution]
    have ne1 : x ≠ u1 := ne_of_lt h_x_u1
    have ne2 : x ≠ u2 := ne_of_lt h_x_u2
    simp [ne1, ne2]
  | cons cur res ih =>
    rcases cur with ⟨k, t⟩
    have ht1 : TermMaxVar S t < u1 := by
      simp [MaxVarInSublist] at h_u1_fresh
      have hle := le_list_max (TermMaxVar S t :: List.map (TermMaxVar S ∘ fun p ↦ p.2) res) (TermMaxVar S t)
      have h0 : (TermMaxVar S t ≤ ListMax (TermMaxVar S t :: List.map (TermMaxVar S ∘ fun p ↦ p.2) res)) := by
        apply hle
        simp
      linarith
    have ht2 : TermMaxVar S t < u2 := by
      simp [MaxVarInSublist] at h_u2_fresh
      have hle := le_list_max (TermMaxVar S t :: List.map (TermMaxVar S ∘ fun p ↦ p.2) res) (TermMaxVar S t)
      have h0 : (TermMaxVar S t ≤ ListMax (TermMaxVar S t :: List.map (TermMaxVar S ∘ fun p ↦ p.2) res)) := by
        apply hle
        simp
      linarith
    simp [AssignmentSubstitution]
    split_ifs with heq
    · apply The_Coincidence_Lemma_term
      · intro c hc
        rfl
      · intro n f hf
        rfl
      · intro x' hx'
        have h1 := var_le_term_max_var S t x' hx'
        have h2 : x' < u1 := by linarith
        have h4 : x' < u2 := by linarith
        split_ifs with h5 h6
        · rfl
        · linarith
        · linarith
        · rfl
    · apply ih
      · have hneq1 := max_var_in_sublist_le_cons S (k,t) res
        linarith
      · have hneq2 := max_var_in_sublist_le_cons S (k,t) res
        linarith

theorem The_Substitution_Lemma_formula
  (S : SymbolSet)
  (I : Interp S)
  (φ : Formula S)
  (sublist : List (Nat × Term S))
  :
  FormulaEval S I (FormulaSubstitution S φ sublist) ↔ FormulaEval S { 𝔸 := I.𝔸, β := (AssignmentSubstitution S I.𝔸.A I.β (sublist.map (fun p => (p.1, TermEval S I p.2)))) } φ
:= by
  revert I sublist
  induction φ with
  | Eq t1 t2 =>
    intro I sublist
    simp only [FormulaSubstitution]
    have hlemma1 := The_Substitution_Lemma_term S I t1 sublist
    have hlemma2 := The_Substitution_Lemma_term S I t2 sublist
    exact Eq.congr hlemma1 hlemma2
  | Rel n R args =>
    intro I sublist
    simp only [FormulaSubstitution, FormulaEval]
    apply Eq.to_iff
    congr
    funext i
    apply The_Substitution_Lemma_term
  | Neg φ ih =>
    intro I sublist
    simp only [FormulaSubstitution]
    apply not_congr
    apply ih
  | And φ ψ ih1 ih2 =>
    intro I sublist
    simp only [FormulaSubstitution]
    apply and_congr
    · apply ih1
    · apply ih2
  | Forall x φ ih =>
    intro I sublist
    simp only [FormulaSubstitution, FormulaEval]
    split_ifs with hif
    · simp only [FormulaEval]
      apply forall_congr'
      intro a
      apply The_Coincidence_Lemma_formula
      · intros
        rfl
      · intros
        rfl
      · intros
        rfl
      · intro x1 hfreevar
        by_cases hxeqx1 : x1 = x
        · simp [hxeqx1]
        · simp [hxeqx1]
          have h1 : x1 ∈ Freevar S (Formula.Forall x φ) := by
            simp only [Freevar]
            apply List.mem_filter.mpr
            constructor
            · exact hfreevar
            · exact bne_iff_ne.mpr hxeqx1
          have h2 : ∀ q ∈ sublist, q.1 ≠ x1 := by
            intro q hq
            simp at hif
            specialize hif q.1 q.2 hq
            exact Ne.symm (ne_of_mem_of_not_mem h1 hif)
          have h3 : ∀ q ∈ sublist.map (fun p => (p.1, TermEval S I p.2)), q.1 ≠ x1 := by
            intro q hq
            rw [List.mem_map] at hq
            rcases hq with ⟨a, ⟨h3, h4⟩⟩
            specialize h2 a h3
            by_contra h5
            rw [← h5] at h2
            rw [← h4] at h2
            simp at h2
          rw [assignment_subst_empty_eq_self S I.𝔸.A I.β (sublist.map (fun p => (p.1, TermEval S I p.2))) x1 h3]
    · simp only [FormulaEval]
      apply forall_congr'
      intro d
      set u := MaxVarInFormula S φ ⊔ MaxVarInSublist S (List.filter (fun p ↦ decide (p.1 ∈ Freevar S (Formula.Forall x φ))) sublist) + 1 with hu
      rw [ih]
      apply The_Coincidence_Lemma_formula
      · intros ; rfl
      · intros ; rfl
      · intros ; rfl
      · intro x1 hfreevar
        split_ifs with heq
        · simp [heq]
          rw [heq] at hfreevar
          clear x1 heq
          simp [AssignmentSubstitution, TermEval]
        · simp [AssignmentSubstitution]
          split_ifs with heq'
          · tauto
          · induction sublist with
            | nil => simp at hif
            | cons cur res ih' =>
              rcases cur with ⟨b, t⟩
              simp
              by_cases hy : b = x1
              · rw [hy]
                have h1 : x1 ∈ Freevar S (Formula.Forall x φ) := by
                  simp [Freevar]
                  rw [hy] at hif
                  constructor
                  · exact hfreevar
                  · exact heq
                rw [List.filter_cons_of_pos]
                · simp [AssignmentSubstitution]
                  apply The_Coincidence_Lemma_term
                  · intros; rfl
                  · intros; rfl
                  · intro x' h2
                    split_ifs with heq''
                    · have hxu : x' < u := by
                        rw [hu]
                        have neq1 := max_var_in_term_le_sublist S t (List.filter (fun p ↦ decide (p.1 ∈ Freevar S (Formula.Forall x φ))) ((b, t) :: res))
                        have neq2 := var_le_term_max_var S t x' h2
                        have neq3 : x' ≤ MaxVarInSublist S (List.filter (fun p ↦ decide (p.1 ∈ Freevar S (Formula.Forall x φ))) ((b, t) :: res)) := by
                          trans (TermMaxVar S t)
                          · exact neq2
                          · apply neq1
                            use b
                            simp
                            rw [hy]
                            exact h1
                        have neq4 : MaxVarInSublist S (List.filter (fun p ↦ decide (p.1 ∈ Freevar S (Formula.Forall x φ))) ((b, t) :: res)) <  MaxVarInFormula S φ ⊔ MaxVarInSublist S (List.filter (fun p ↦ decide (p.1 ∈ Freevar S (Formula.Forall x φ))) ((b, t) :: res)) + 1 := by
                          simp_arith
                        linarith
                      linarith
                    · rfl
                · simp [h1]
              · simp [AssignmentSubstitution]
                split_ifs
                by_cases hcase: (List.filter (fun p ↦ decide (p.1 ∈ Freevar S (Formula.Forall x φ))) res).isEmpty = true
                · simp at hcase
                  have hempty := assignment_subst_empty_eq_self S I.𝔸.A I.β (List.map (fun p ↦ (p.1, TermEval S I p.2)) res) x1
                  rw [hempty]
                  · have h_x1_ne_u : x1 ≠ u := by
                      have h_lt : x1 < u := by
                        rw [hu]
                        have hle := var_le_max_var_in_formula S φ x1 hfreevar
                        simp_arith
                        left
                        exact hle
                      linarith
                    by_cases h_filter_b : decide (b ∈ Freevar S (Formula.Forall x φ))
                    · simp [h_filter_b]
                      simp [AssignmentSubstitution]
                      split_ifs
                      rw [List.filter_eq_nil_iff.mpr]
                      · simp [AssignmentSubstitution]
                        intro hcon
                        tauto
                      · intro tmp
                        rcases tmp with ⟨tmp1, tmp2⟩
                        intro htmp
                        specialize hcase tmp1 tmp2 htmp
                        simp
                        exact hcase
                    · simp [h_filter_b]
                      rw [List.filter_eq_nil_iff.mpr]
                      · simp [AssignmentSubstitution]
                        intro hcon
                        tauto
                      · intro tmp
                        rcases tmp with ⟨tmp1, tmp2⟩
                        intro htmp
                        specialize hcase tmp1 tmp2 htmp
                        simp
                        exact hcase
                  · simp [Freevar] at hcase
                    simp
                    intro a' b' x' t' h1 h2 h3
                    specialize hcase x' t' h1
                    by_contra hcontra
                    rw [← hcontra] at hfreevar
                    rw [h2] at hcase
                    have h4 := hcase hfreevar
                    rw [hcontra] at h4
                    tauto
                · rw [← ih']
                  · by_cases h_filter_b : decide (b ∈ Freevar S (Formula.Forall x φ))
                    · simp [h_filter_b]
                      simp [AssignmentSubstitution]
                      split_ifs
                      have ind_h := ih' hcase
                      simp at ind_h
                      rw [ind_h]
                      set u' := MaxVarInFormula S φ ⊔ MaxVarInSublist S (List.filter (fun p ↦ decide (p.1 ∈ Freevar S (Formula.Forall x φ))) res) + 1 with hu'
                      have hfresh := fresh_var_subst_equivalence S I d (List.filter (fun p ↦ decide (p.1 ∈ Freevar S (Formula.Forall x φ))) res) u u' x1
                      rw [hfresh]
                      · exact ind_h
                      · rw [hu]
                        have hnew := max_var_in_sublist_le_cons S (b,t) (List.filter (fun p ↦ decide (p.1 ∈ Freevar S (Formula.Forall x φ))) res)
                        simp_arith
                        right
                        simp [List.filter_cons]
                        split_ifs with h0
                        · tauto
                        · tauto
                      · rw [hu']
                        simp_arith
                      · rw [hu]
                        have hneq : (x1 ≤ MaxVarInFormula S φ) := by
                          apply var_le_max_var_in_formula
                          tauto
                        simp_arith
                        tauto
                      · rw [hu']
                        have hneq : (x1 ≤ MaxVarInFormula S φ) := by
                          apply var_le_max_var_in_formula
                          tauto
                        simp_arith
                        tauto
                    · simp [h_filter_b]
                      set u' := MaxVarInFormula S φ ⊔ MaxVarInSublist S (List.filter (fun p ↦ decide (p.1 ∈ Freevar S (Formula.Forall x φ))) res) + 1 with hu'
                      have hfresh := fresh_var_subst_equivalence S I d (List.filter (fun p ↦ decide (p.1 ∈ Freevar S (Formula.Forall x φ))) res) u u' x1
                      rw [hfresh]
                      · rw [hu]
                        simp_arith
                        right
                        simp [List.filter_cons, h_filter_b]
                      · rw [hu']
                        simp_arith
                      · rw [hu]
                        have hneq : (x1 ≤ MaxVarInFormula S φ) := by
                          apply var_le_max_var_in_formula
                          tauto
                        simp_arith
                        tauto
                      · rw [hu']
                        have hneq : (x1 ≤ MaxVarInFormula S φ) := by
                          apply var_le_max_var_in_formula
                          tauto
                        simp_arith
                        tauto
                  · exact hcase
                  · rfl

end FirstOrderLogic

参考文献

[1] H.-D. Ebbinghaus, J.Flum, W. Thomas: Mathematical Logic

posted @ 2025-07-15 02:46  行而上  阅读(227)  评论(0)    收藏  举报