- 数学背景
数学背景
本章的学习目标:
- 学习基本的数学概念,如几何、函数、数字、逻辑运算符及量词、字符串和图。
- 严格地定义大表示法。
- 归纳证明法。
- 练习如何阅读数学定义、陈述与证明。
- 将直观的论证转化为严谨的证明。
“我发现,从一到十表达的每个数字,都比前一个数字多一个单位:之后,十的倍数会翻倍或增至三倍……直至一百;然后,一百的倍数会以与个位和十位相同的方式翻倍和增至三倍……以此类推,直至计数的最大极限。”,
—穆罕默德·伊本·穆萨·花拉子米(Muhammad ibn Mūsā al-Khwārizmī),820年,弗雷德里克·罗森(Fredric Rosen)译,1831年
在本章中,我们将会介绍一些将在本书中用到的数学概念。这些概念一般会在“计算机科学中的数学”或“离散数学”等课程或课本中讲解。有关这些主题的几份可在线免费获取优秀资源,请参阅“参考书目”部分(第1.9节)。
一个数学家的辩白。部分学生可能会好奇为什么这本书包含如此多的数学,这是因为数学就是一门能够简洁而精确描述概念的语言。在这本书中,我们使用数学来描述计算的概念。比如说,我们将思考诸如“是否存在一种高效算法来求取给定整数的质因数?”这样的问题(我们将看到这个问题尤为有趣,它甚至触及了从互联网安全到量子力学等跨度极大的问题!)若要精准的描述这些问题,我们需要对算法这一概念以及算法的高效性给出精准的定义。此外,由于无法通过实验证明某种算法不存在,唯一能证实算法不存在性的方式就是数学证明。
1.1 本章:读者的参考手册
基于你已有的数学背景,你有两种阅读本章的方式:
- 如果你已经学习过”离散数学“、”计算机科学中的数学“或任何类似课程,则无需阅读整章内容,只需要快速地阅读第1.2节来了解我们会用到什么数学工具与第1.7节来了解本书所用符号,便可跳转至后续章节。或者,你也可以放松心情通读本章,既熟悉本书所用的符号体系,顺便品味(或忍受)笔者融于字里行间的哲学思考与幽默尝试。
- 若相关基础较为薄弱,可以参考第1.9节中提供的学习资源。本章虽然已经涵盖了所有所需知识点,但系统性地学习相关知识点可能对你更有帮助。数学学习重在实践,通过独立完成练习才能真正掌握这些内容。
- 建议你同时开始回顾离散概率论的相关知识,本书后续章节(见第18章)将涉及这部分内容。
1.2 前置数学知识的概览
我们将使用的主要数学概念如下所示。此处仅列出这些概念,其具体定义将在本章后续部分给出。若您已熟悉所有这些内容,可以直接跳至第1.7节查看我们使用的完整符号列表。
- 证明:最重要的是,本书包含大量形式化数学推理,涵盖数学定义、陈述与证明。
- 集合及集合运算:我们将广泛使用数学集合。涉及到的集合关系包括属于()与包含(),以及集合运算,主要是并集()、交集()与差集()。
- 笛卡尔积(Cartesian product)与克林星号(Kleene star)运算:两个集合与的笛卡尔积,记作(即由所有满足且的所有有序对构成的集合),表示阶笛卡尔积(例如),而(称为克林星号)表示所有对应的的并集。
- 函数:函数的定义域和陪域,以及函数的性质(如单射函数和满射函数),还有部分函数(即不同于全函数的,对于定义域内部分元素可能存在未定义情况的函数)。
- 逻辑运算:常用操作包括逻辑与()、逻辑或()、逻辑非()等,以及存在量词()和全称量词()。
- 基础组合数学:诸如(表示大小为的集合中所有元子集的数量)等概念。
- 图论:无向图和有向图、连通性、路径和环。
- 大表示法:使用符号分析函数的渐进增长性。
- 离散概率:我们将使用概率论,特别是基于有限概率空间(如抛掷枚硬币)的概率论,包括随机变量、期望和浓度等概念。概率论仅在本书后半部分使用,我们将在第18章先行复习。然而概率推理是一项精妙(且极其实用)的技能,尽早开始掌握总是有益的。
本章后续部分将简要回顾上述概念。既是为了帮助读者重温可能已经生疏的知识,也是为了介绍我们的符号与约定——这些约定有时可能与你之前接触过的版本有所不同。
1.3 阅读数学文本
数学家使用各种专业术语的原因,与工程、法律、医学等其他众多领域并无差别:我们需要精确的术语,并为频繁使用的概念引入简洁表达。数学文本往往在单个句子中蕴含极高的信息密度,因此关键在于缓慢而仔细地阅读,逐个符号解析。
随着练习时间逐渐增长,你将发现阅读数学文本变得越来越轻松,且专业术语也不再是问题。更重要的是,数学文本阅读能力是从本书中能够获得的极具迁移价值的技能之一。我们的世界正飞速变化——这不仅体现在技术领域,更延伸至医学、经济学、法律乃至文化等人类实践的方方面面。无论你未来方向如何,都很可能会接触到包含前所未见新概念的文本(参见图1.1与图1.2中两个当代“热点领域“的例子)。掌握内化并应用新定义的能力至关重要。在数学课程相对安全稳定的学习环境中,这种技能更容易被掌握——至少你可以确信所有概念都有完整定义,并能随时向教学人员答疑解惑。
图1.1:
摘自Silver等人2017年发表于《自然》期刊的《AlphaGo Zero》论文“方法“部分片段
图1.2:
摘自Ben-Sasson等人奠定加密货币Zcash项目基础的《Zerocash》论文片段
数学文本的基本构成要素有三:定义、断言与证明。
1.3.1 定义
数学家经常在已有的概念上定义新的概念。比如,以下是一个你可能曾经见过的数学定义(并且我们很快还会再见到):
令与为集合。我们称一个函数是单射的(one-to-one或injective)当其对于任意两个元素时,若,则有。
定义1.1:单射函数阐述了一个简单的概念,但即便如此它也使用了大量符号。阅读此类定义时,一边阅读一边用笔进行标注往往很有帮助(见图1.3)。例如当看到诸如、或等符号时,务必确认其指代的对象的类别:是集合、函数、元素、数字,还是小妖怪?你可能还会发现,向朋友(或对自己)用语言解释这一定义会很有帮助。
图1.3:
定义1.1:单射函数的注释版本,标出了定义的每个对象及其关联的定义
1.3.2 断言:定理、引理、主张
定理、引理、断言等都是对已定义概念的真命题。将特定命题称为“定理“、“引理“还是“断言“属于主观判断,并不改变其数学实质——三者均指代已被证明为真的命题。区别在于:定理指代值得铭记和强调的重要结论;引理通常指技术性结论,其自身未必重要但能有效辅助其他定理的证明;断言则是为证明更重大结论而使用的“过渡性“命题,其自身价值并不受关注。
1.3.1 证明
数学证明是用以证实定理、引理及断言真实性的论证过程。我们将在下文1.5节讨论证明,其核心在于数学证明的标准极为严苛。与其他领域不同,数学证明必须是“无懈可击“的论证,确保证明对象无可置疑为真。本节涉及的数学证明示例参见习题解答1.1及1.6节。如前言所述,总体而言:理解定义比掌握定理更重要,理解定理陈述比掌握其证明过程更重要。
1.4 基础离散数学对象
在本节中,我们将快速回顾本书中所用的一些数学对象(你当然也可以把这些叫做数学中的“基本数据结构”)。
1.4.1 集合
一个集合是一些对象的无序容器。例如,表示指代一个包含数字、、的集合(我们使用来表示是中的一个元素。)注意集合与是相同的,因为它们拥有相同的元素。同时,一个集合要么包含一个元素,要么不包含一个元素,不存在“包含两次”的概念,因此我们甚至可以将同一个集合写作(尽管这样写有些奇怪)。有限集合的基数(cardinality),即一个集合包含的元素的数量,记作(基数亦可以定义在无限集上,见第1.9节的参考资料)。因此在上例中。若集合的元素都是集合的元素,则称为的一个子集,记作(我们亦可以称为的一个超集。)比如,。不包含任何元素的集合称作空集,写作。如果是的一个子集且不等于,则我们称为的一个真子集,记作。
我们可以通过将其元素全部列出来定义集合,也可以通过写下集合元素满足的一个条件来定义集合,例如: 当然,同一集合有多种表示方式,我们常会使用直观的记号列出几个示例来说明规则。例如也可将定义为: 注意集合可以是有限的(如)或无限的(如)。集合的元素不必是数字,例如英语元音的集合,或按2010年人口普查的美国百万人口城市集合。集合甚至可以包含其他集合作为元素,例如所有偶数大小子集构成的集合。
集合运算:集合与的的并集记作,包含所有属于或属于的元素。交集记作,包含同时属于和的元素。差集记作(部分文献中记作),包含属于但不属于的元素。
元组、列表、字符串、序列:元组是有序的对象容器,例如是包含四个元素的元组(称为-元组或四元组)。由于元组是有序的,该元组不同于四元组或三元组。-元组亦称为有序对。术语“元组”与“列表”可互换使用。若某个元组中的元素均来自于某个有限集(如),则称为字符串。类比集合,我们将元组的长度记作。与集合类似,元组亦有无限形式。例如由所有完全平方数组成的元组。无限的有序容器称为序列,有时亦称作“无限序列”以强调这一点。“有限序列”是元组的同义词。(可将集合中元素的序列视为函数(其中对任意满足)。类似地,可将中元素的-元组视为函数。)
笛卡尔积:若与是集合,则其笛卡尔积记作,是由所有满足且的有序对构成的集合。例如,若且,则包含六个元素:。相似的,若为集合,则为由所有满足、、的三元组构成的集合。更加一般地,对任意正整数及集合,用表示满足对每个有的有序-元组的集合。对任意集合,将记作,记作,记作,依此类推。
1.4.2 特殊集合
在本书中会反复用到数个特殊集合。集合
包含了所有的自然数,即非负整数。对于任意的自然数,定义集合为(与均从开始计数,与此同时诸多文献中这两个集合是从开始的计数的。从零开始计数只是一个约定俗成的做法,只要保持一致性,并不会产生太大差异。)
我们偶尔也会使用集合来表示所有(负的和非负的)整数,同时使用来表示所有实数(这个集合不仅包含整数,同时也包含分数与无理数,例如,包含诸如、等的数字。)我们使用来表示所有正实数的集合。这个集合有时亦写作。
字符串:另外一个我们经常会用到的集合是 这个集合包含了所有长度为(为任意自然数)的二进制字符串。换句话说,是包含所有由组成的-元组的集合。这与我们前文中的符号一致:是笛卡尔积,是笛卡尔积,依此类推。
我们将字符串简单地写作。例如, 对于所有字符串与,我们将的第个元素记作。
我们也经常会使用包含所有长度二进制字符串的集合,即 另一个表示这个集合的方式是 或者更为简洁的 集合包含了“长度为的字符串”或“空字符串”,我们将这个字符串记作(此处我们使用与大部分编程语言一致的符号,其他文献可能会使用或来表示空字符串)。
推广星号操作:对于任意集合,我们定义 例如,若,则表示字母表a-z上所有有限长度字符串的集合。
连接操作:两个字符串与的连接是指将书写在后形成的长度的字符串。具体而言,若且,则等于满足以下条件的字符串:当时,当时。
1.4.3 函数
若与为非空集合,则从到的函数(记作)会将每个元素关联到一个元素。集合称为函数的定义域,集合称为的陪域。函数的像是指集合,即由所有被映射的输入元素对应的输出元素组成的的陪域子集(有些文献使用“值域”一词表示函数的像,而另一些文献使用“值域”表示函数的陪域。因此我们将完全避免使用“值域”这一术语。)与集合类似,我们可以通过列出函数对中所有元素给出的取值表或通过规则来定义函数。例如,若且,则下表定义了一个函数。注意该函数与规则定义的函数相同。
若满足对所有均有,则称是单射(见定义1.1:单射函数,亦称为单射函数)。若满足对每个均存在某个使得,则称是满射(亦称作满射函数)。既是单射又是满射的函数称为双射函数或双射。从集合到自身的双射亦称为的排列。若是双射,则对于每个均存在唯一的使得。我们将该值记作。注意本身也是从到的双射(你能明白为什么吗?)。
给出两个集合之间的双射通常是证明集合大小相同的有效方法。事实上,“与具有相同基数”的标准数学定义就是存在一个双射。此外,若存在从到集合的双射,则定义集合的基数为。正如我们将在本书后面看到的,这个定义可以推广到无限集合的基数定义。
部分函数(又译偏函数):我们有时会关注从到的部分函数。部分函数允许在的某个子集上未定义。也就是说,若是从到的偏函数,则对每个,要么(如标准函数的情况)存在中的元素,要么未定义。例如,部分函数仅定义在非负实数上。当需要偏函数和标准(即非部分)函数时,我们称后者为全函数。当我们不加限定地说“函数”时,指的是全函数。
部分函数的概念是函数的严格推广,因此每个函数都是部分函数,但并非每个部分函数都是函数(也就是说,对于任意非空集合与,从到的偏函数集合是从到的全函数集合的真超集。)当需要强调从到的函数可能不是全函数时,我们写作。我们也可以将从到的偏函数视为从到的全函数,其中是一个特殊的“失败符号”。因此,我们可以说,而不是在处未定义。
关于函数的基本事实:验证能否证明以下结论是复习函数知识的绝佳方式:
- 若和是单射函数,则它们的复合函数(定义为)也是单射。
- 若是单射,则存在一个满射函数,使得对于每个均有。
- 若是满射,则存在一个单射函数,使得对于每个均有。
- 若与是非空有限集合,则以下条件相互等价:(a) ;(b) 存在单射函数;(c) 存在满射函数。这些等价关系实际上对无限集合和亦成立。对于无限集合,条件(b)(或等价的条件(c))是的公认定义。
图1.4:
我们可以将有限函数表示为有向图,其中从到有一条边。满射条件要求函数陪域中的每个顶点的入度至少为。单射条件要求函数陪域中的每个顶点入度至多为,上图的示例中,是满射函数,是单射函数,而既不是满射也不是单射
暂停思考:
你可以在许多离散数学教材中找到这些结论的证明,例如Lehman-Leighton-Meyer讲义中的第4.5节。但我强烈建议你尝试独立证明它们,或至少通过证明小规模情况(如)的特殊实例来确信这些结论成立。
让我们以其中一个事实为例进行证明:
若是非空集合且是单射,则存在满射函数,使得对每个均有。
证明:选择某个。我们将定义函数如下:对每个,若存在某个使得,则令(由于的单射性质,不可能有两个不同的同时映射到,因此的选择是无歧义的)。否则,令。现在对于每个,根据的定义,若,则。此外,这也表示是满射,因为这意味着对每个都存在某个(即)使得。
1.4.4 图
图在计算机科学及众多其他领域中无处不在。图可以用于建模非常多的数据类型,包括但不限于社交网络、调度约束、道路网络、深度神经网络、基因相互作用、观测值之间的相关性。几种图的正式定义将在下面给出,但如果你没有在先前的课程中了解过图,我强烈建议你从第1.9节中的资料中详细了解它们。
图有两种基本类型:无向图与有向图。
一个无向图由一个顶点集与一个边集组成。每条边都是一个的大小为2的子集。我们称两个顶点为相邻顶点,若边在中。
基于这个定义,我们可以定义关于图与顶点的几个性质。我们将的相邻节点的个数成为的度数。图中的一条路径是一个元组(其中),且满足对每个,都是的相邻节点。简单路径是指所有均不重复的路径。环是指满足的路径。若两个顶点满足或存在一条从到的路径,则称这两个顶点是联通的。当图中每对顶点都联通时,我们称该图是连通图。
下面是一些关于无向图的基本事实。我们将为它们给出一些非正式的论证,但完整证明作为练习留待读者自行完成(完整证明可以在第1.9节中的诸多资源中找到)。
在任意的无向图中,所有顶点的度数之和等于边数的两倍。
通过观察可知:每条边会对度数总和贡献两次(一次作用于,另一次作用于),由此可证明引理1.4。
连通关系具有传递性,即如果与相连,且与相连,则与也相连。
通过将路径与路径拼接,得到连接与的路径,即可证明引理1.5。
对于任意无向图及连通顶点对,从到的最短路径是简单路径。特别地,任意连通顶点对间均存在连接二者的简单路径。
通过“捷径修剪法”可证明引理1.6:若某路径中同一节点出现两次,则移除其间的循环段(见图1.6)。将这一直观论证转化为形式化证明是很好的练习:
图1.6:
若图中存在从到的路径两次经过顶点,则可移除到自身的循环段,得到仅经过一次的捷径路径。
已解答练习1.1:
证明引理1.6。
解答1.4.4:
此证明遵循图1.6所示的思路。需要注意的复杂性在于:路径中可能有多个顶点被重复访问,因此“捷径修建”不一定能直接得到简单路径。我们通过考察与之间的最短路径来解决该问题。具体如下:
设为无向图,和为中两个连通顶点。我们将证明存在连接和的简单路径。令为与之间路径的最短长度,并设为一条长度为的路径(可能存在多条此类路径,若有则任选其一)。(即,,且对任意有。)我们断言是简单路径。假设存在某个顶点在路径中出现两次:即对某些有且。此时可通过取的前个顶点(从到的首次出现)和后个顶点(从第二次出现后的顶点到),得到捷径路径。由于,和都是中的边,因此是连接和的有效路径。但的长度为,这与的最小性矛盾。
度数和连通性的概念亦可自然推广至有向图,其定义如下:
一个有向图由顶点集和边集(由的有序对构成)组成。有时将边记为。若存在边,则称是的出邻居,是的入邻居。
有向图可能同时包含边和,此时和互为入邻居和出邻居。顶点的入度是其入邻居的数量,出度是其出邻居的数量。图中的路径是指元组(其中),且对每个有是的出邻居。与无向图情形类似,简单路径是指所有均不相同的路径,环是指满足的路径。我们经常关注的一类有向图是有向无环图(Directed Acyclic Graph,DAG),顾名思义即为不含环的有向图:
若有向图中不存在顶点列使得且对每个有边,则称其为有向无环图(DAG)。
上述引理在有向图中均有对应版本。其证明(与无向图情形基本一致)将作为习题留给读者。
对于任意有向图,入度之和等于出度之和,且均等于边数。
对于任意有向图,若存在从到的路径和从到的路径,则存在从到的路径。
对于任意有向图及存在路径的顶点对,从到的最短路径是简单路径。
1.4.5 逻辑运算符与量词
如果和是可真可假的陈述,则与(记为)是一个当且仅当和同时为真时才成立的陈述;而或(记为)是一个当且仅当或为真是成立的陈述。的否定记作或,当且仅当为假时该陈述为真。
假设是一个依赖于某个参数(有时亦称为自由变量)的陈述,其特性在于:对于从集合中取值的每一个的具体赋值,都会有明确的真值。例如这个陈述本身没有固有真值,但当我们用具体实数代入时,它就会成为真或假的命题。我们用表示这样一个陈述:当且仅当对所有都有为真时,该陈述为真。用表示这样一个陈述:当且仅当存在某个使得为真时,该陈述为真。
例如下面这个形式化表达式,描述的是“存在大于100且不能被3整除的自然数”这个真命题: “对于足够大的”。本书中会反复出现“某个陈述对于足够大的成立”这样的论断,其含义是:存在整数,使得对于所有,都成立。我们可以将其形式化为。
1.4.6 求和与求积的量词
使用下列简记法来表示多个数的求和或求积往往更为便捷。若是有限集且是函数,则表示: 表示: 例如,从到的所有整数的平方和可表示为:
式 1.1 (公式1.1). 由于对整数区间求和极为常见,对此存在特殊记号。对于任意两个满足的整数,表示,其中。因此公式1.1可改写为:
1.4.7 解析公式:约束变量与自由变量
在数学中,如同在编程中一样,我们常常会遇到符号化的“变量”或“参数”。给定某个公式时,理解特定变量在该公式中是约束变量还是自由变量至关重要。例如在如下陈述中,是自由变量,而和是受存在量词约束的变量:
式 1.2 (公式1.2). 由于是自由变量,它可以被赋予任意值,因此公式1.2的真值取决于的取值。例如当时公式成立,但当时则不成立。(你能看出原因吗?)
同样的问题在解析代码时也会出现。例如在下列C语言代码片段中:
for (int i=0 ; i<n ; i=i+1) {
printf("*");
}
变量i
在for
循环块内是约束变量,而变量n
则是自由变量。
约束变量的主要特性是:我们可以对其进行重命名(只要新名称不与其他变量名冲突)而不改变语句的含义。因此以下陈述
式 1.3 (公式1.3). 与公式1.2完全等价—它们对值的真值判断完全相同。
同样地,代码:
for (int j=0 ; j<n ; j=j+1) {
printf("*");
}
与使用i
的代码段有完全相同的执行效果。
Remark 1.3 (备注1.14:数学符号与编程符号的对比).
数学符号与编程语言存在诸多相似性,这源于二者都是为精确传递复杂概念而构建的形式化体系。但两者存在文化差异:编程语言通常使用具有实际意义的变量名(如NumberOfVertices
),而数学则倾向于使用简短标识符(如)。部分原因可能源于数学证明的传统形式—手写论证与口头阐述,而非键入代码并编译执行。另一个原因是:在证明中使用错误变量名最多导致读者困惑,但在程序中使用错误变量名则可能导致飞机失事、患者死亡或火箭爆炸。
由此带来的结果是:数学中常常重复使用标识符,甚至会耗尽字母表而不得不引入希腊字母,并通过区分大小写及字体样式来扩展表示范围。同样地,数学符号体系大量使用“重载“机制——例如运算符可对应多种不同对象(实数、矩阵、有限域元素等),其具体含义需通过上下文推断。
两个领域都存在“类型“概念。在数学中,我们通常约定特定字母表示特定类型的变量:例如通常表示整数,通常表示极小正实数(相关约定详见1.7节)。阅读或撰写数学文本时,我们无法依赖“编译器“进行类型安全检查,因此必须密切关注每个变量的类型,确保所有操作都是“合法“的。
Kun的著作(Kun, 2018)对数学与编程文化的异同进行了深入探讨。
1.4.8 渐近分析与大表示法
精确描述运行时间等量通常非常繁琐,且并无必要,因为我们通常主要关注的是“高阶项”。也就是说,我们希望理解该量随输入变量增长时的缩放行为。例如,就运行时间而言,一个时间算法与一个时间算法之间的差异,远比时间算法与算法之间的差异更加显著。为此,大表示法作为一种“简化表述”的方式极为有用,它能让我们的注意力集中在真正重要的内容上。例如,使用大表示法,我们可以说和都简单的属于(可非正式地理解为“在常数因子范围内相同”),而(可非正式地理解为“远小于”)。
通常(尽管为非正式表述),若是两个将自然数映射到非负实数的函数,则“”表示在不考虑常数因子的情况下,而““表示远小于,其含义是:无论给乘以多大的常数因子,只要取足够大的,都会更大(因此,有时会将写作)。如果且,则写作,这可以理解为:若不考虑常数因子,与相同。更形式化地,我们如下定义大表示法:
设为正实数集。对于两个函数,若存在,使得对所有有,则称。若且,则称。若,则称。
若对任意,存在使得对所有有,则称。若,则称。
图1.7:
若,则当足够大时,将小于。例如,若算法的运行时间为,算法的运行时间为,那么即使在小输入时更高效,当输入足够大时,的运行速度将远快于
在大表示法中使用“匿名函数”通常很方便。例如,当我们写这样的语句时,我们的意思是,其中是定义为的函数。Jim Apsnes的离散数学笔记第七章很好地总结了大表示法;另可参阅本教程,以获得更温和且更面向程序员的介绍。
并不表示相等。在大表示法中使用等号极为常见,但这种用法其实并不准确,因为诸如的语句实际上表示属于集合。如果说有什么更合理的表示法,那就是使用不等式写作和,而将等号保留给。因此,我们有时也会使用这种表示法,但由于使用等号的习惯已经根深蒂固,我们通常也沿用此习惯。(有些文献写作而非,但我们不会使用这种表示法。)尽管等号可能引起误解,但请记住:诸如的语句表示在忽略常数的粗略意义上“至多”为,而诸如的语句表示在相同粗略意义上“至少”为。
1.4.9 关于大表示法的一些“经验法则”
在比较两个函数和时,有一些简单的经验法则可供参考:
- 在大表示法中,乘性常数不影响结果。因此,若,则。当两个函数相加时,我们只需要关注较大着。例如,在大表示法的语句下,与等价。一般而言,对于任意多项式,我们只需关注高阶项。
- 对于任意两个常数,当且仅当时,成立,当且仅当时,成立。例如,综合以上两点可知:。
- 多项式函数始终小于指数函数:对于任意两个常数和(即使远小于),都有。例如,。
- 类似地,对数函数始终小于多项式函数:对于任意两个常数,(记作)满足。例如,综合上述观察可得:。
Remark 1.4 (备注1.19:大表示法的其他应用场景(可选)).
虽然大表示法常用于分析算法的时间复杂度,但这绝非其唯一用途。我们可以用大表示法来限定任意两个从整数映射到正数的函数之间的渐近关系。无论这些函数是衡量运行时间、内存使用量,还是其他与计算无关的量,该方法均适用。以下是一个与本书无关的例子(你可选择跳过):黎曼猜想(数学领域最著名的未解问题之一)的一种表述方式是:在到之间的质数数量等于,且其加性误差至多为。
1.5 证明
许多人认为数学证明是从若干公理出发,通过逻辑推导最终得出结论的过程。事实上,某些词典也采用这种方式定义证明。这种理解并非完全错误,但从本质而言,对命题X的数学证明实质上是一个能让读者确信X为真且不容置疑的论证过程。
构建此类证明需要做到:
- 精确理解X的含义。
- 使自己确信X为真。
- 用清晰、准确、简洁的书面英语记录推理过程(仅在有助于明确性时使用公式或符号)。
多数情况下,第一步最为关键。理解命题含义往往比理解其真理性更耗费心力。在第三步中,为使读者毫无疑虑,我们常需将推理分解为若干“基本步骤“,其中每个步骤都应简单到“不言自明“的程度——所有步骤的叠加最终导出目标命题。
1.5.1 证明与程序
证明写作与程序编写具有高度相似性,且二者所需的技能也高度重合。程序编写包含:
- 理解程序需要实现的功能。
- 确信该功能可通过计算机实现(可通过在白板或记事本上规划如何拆解为子任务来实现)。
- 将规划转化为编译器或解释器可读的代码(通过将每个任务拆解为某种编程语言的基本操作序列)。
与证明过程类似,程序设计的第一步往往最为关键。核心区别在于:证明的阅读者是人类,而程序的阅读者是计算机(随着机器可验证证明形式的普及,这种差异正在逐渐消弭;此外,为确保程序的正确性与可维护性,人类可读性至关重要)。因此我们特别强调证明的逻辑流畅性与可读性(这对程序编写同样重要)。撰写证明时,应假想读者是聪明但极度多疑且挑剔的,他们会对任何未充分论证的步骤提出质疑。
1.5.2 证明的书写风格
数学证明是一种特定类型的写作形式,具有独特的惯例与偏好风格。如同所有写作类型,熟能生巧,且通过修改草稿提升清晰度至关重要。
在命题的证明中,“证明:“与”证毕“之间的所有文字都应专注于论证的真实性。题外话、示例或沉思应置于这两个标记之外,以免造成读者困惑。证明应具备清晰的逻辑流:每个句子或公式都应有明确目的,且读者能清晰理解其作用。撰写证明时,应对每个句子或公式进行审视:
- 该句子/公式是否在声明某个命题为真?
- 若是,该命题是从前述步骤推导而来,还是将在后续步骤中建立?
- 这个句子/公式起什么作用?是通向原命题证明的一步,还是为证明先前所述的中间论断而设?
- 最后,读者是否能清晰理解前三个问题的答案?若否,则需要调整顺序、重新表述或补充说明。
关于数学写作的推荐资源包括Lee的讲义、Hutching的讲义,以及斯坦福大学CS103课程中的若干优秀讲义。
1.5.3 证明的方法
正如编程一样,证明亦有数种常用的方法。以下是一些例子:
反证法:证明的一种方式是展示,若为假,则会导致导出矛盾。这种类型的证明通常由一句“假设,为了得出矛盾,为假”作为开头,并以推导出一个矛盾作为结尾(如违反定理陈述中的某个假设)。以下是一个例子:
不存在自然数使得。
证明:假设,为了得出矛盾,上述引理为假。令为满足的最小自然数(其中)。对此等式两侧平方有,即 。此式表明为偶数。由于两个奇数之积亦为奇数,这表明必须是偶数,即存在使得。将此式代入有,即,且这表明亦为为偶数。与类似,我们亦可得到为偶数。因此,与为两个满足的自然数,这与的最小性相矛盾。
全称命题的证明:我们经常需要证明形如“所有类型为的对象都具有性质”的命题。这类证明通常以“设为类型的一个对象”开始,并通过证明具有性质来结束,以下是一个简单的例子:
对于任意自然数,和中必有一个是偶数。
证明:设为任意自然数。若为整数,则,因此是偶数,证毕。否则,是整数,因此是偶数。
蕴含命题的证明:另一种常见情况是命题形如“蕴含”。这类证明通常以“假设成立“开始,并通过从导出来结束。以下是一个简单的例子:
如果,则二次方程有解。
证明:假设。则是一个非负数,因此存在平方根。于是满足:
式 1.4 (公式1.4). 整理公式1.4,我们得到: 等价命题的证明:如果命题形如“当且仅当”(通常简写为“ iff ”),那么我们需要同时证明蕴含和蕴含。我们将蕴含的方向称为“仅当”方向,将蕴含的方向称为“当”方向。
通过中间结论组合的证明:当证明较为复杂时,将其分解为多个步骤通常是有帮助的。也就是说,为了证明命题,我们可能先证明命题、和,然后证明蕴含。(注:表示逻辑与运算符。)
分情况证明:这是上述方法的一种特殊形式,即为了证明命题,我们将其分为若干情况,并证明:(a) 这些情况是穷尽的,即其中一种情况必须发生;(b) 逐一证明每种情况都能推导出我们想要的结果。
数学归纳法证明:我们将在下面的第1.6.1节中讨论数学归纳法并给出示例。我们可以将这类证明视为上述方法的变体,其中我们有无穷多个中间结论,并证明成立,且蕴含,蕴含,依此类推。卡内基梅隆大学15-251课程的网站提供了一份有用的讲义,介绍了使用数学归纳法时可能遇到的常见陷阱。
“不失一般性”(without loss of generality,w.l.o.g):这个术语最初可能令人困惑。它本质上是一种通过简化情况分析来简化证明的方法。其思想是,如果情况1和情况2在变量替换或类似变换下是相同的,那么情况1的证明也隐含了情况2的证明。但对此应始终保持怀疑态度。每当在证明中看到它时,问问自己是否理解为什么所做的假设是真正“不失一般性”的;而当使用它时,尝试确认这种使用是否确实合理。在撰写证明时,有时最简单的方法是直接重复第二种情况的证明(并添加注释说明该证明与第一种情况非常相似)。
数学证明最终是用英文散文写的。知名计算机科学家Leslie Lamport认为这是一个问题,证明应该以更形式化和严谨的方式书写。他在手稿中提出了一种结构化分层证明的方法,其形式如下:
- 对于形如“如果则”的命题,其证明是一系列编号的声明,以假设成立开始,并以声明成立结束。
- 每个声明后面都附有一个证明,展示它如何从先前的假设或声明推导出来。
- 每个声明的证明本身又是一系列子声明。
Lamport格式的优点在于,证明中每个句子的作用非常清晰。此外,这种证明也更容易转换为机器可检查的形式。缺点在于,这类证明可能读起来和写起来都很繁琐,且论证的重要部分与常规部分之间的区分不够明显。
1.6 扩展示例:拓扑排序
在本节中,我们将证明如下结论:每个有向无环图(DAG,参见定义1.9:有向无环图)都可以进行分层排列,使得对于所有有向边,顶点所在的层都大于所在的层。这一结论被称为拓扑排序,被广泛应用于任务调度、构建系统、软件包管理、电子表格单元格计算等场景(见图1.8)。事实上,在本书后续内容中我们也会用到这一结论。
图1.8:
拓扑排序示例。我们考虑某个计算机科学专业课程先修关系对应的有向图,其中边表示课程是课程的先修课程。对该图进行分层或“拓扑排序“等价于将课程映射到不同学期,使得若我们计划在学期修读课程,则已在此前的学期修完的所有先修课程(即其入邻居)
我们首先给出如下定义。有向图的分层是指为每个顶点分配一个自然数(对应其所在层)的方法,要求的入邻居处在更低编号的层,而出邻居处于更高编号的层。形式化定义如下:
Definition 1.6 (定义1.21:DAG的分层).
设为有向图,的分层是一个函数,使得对于的每条边,都有。
本节将证明:有向图是无环的当且仅当其存在有效分层。
设为有向图,则是无环的当且仅当存在的分层函数。
要证明此类定理,首先需要理解其含义。由于这是一个“当且仅当”类型的陈述,定义1.22:拓扑排序对应两个命题:
对于任意有向图,若无环,则存在对应的分层。
对于任意有向图,若其存在分层,则无环。
要证明定义1.22:拓扑排序,则需同时证明引理1.23和引理1.24。引理引理1.24的证明实际上并不困难:直观上,若包含环,则环上所有边的层数不可能全程递增—因为沿着环行进时必然会回到起点。形式化证明如下:
证明:设为有向图,是符合定义1.21:DAG的分层的分层函数。用反证法假设不是无环图,即存在环满足,且对每个都有边属于。由于是分层函数,对每个有,这意味着: 但这与导出的相矛盾。
引理1.23对应着更复杂(但更有用)的方向。要证明它,需要说明如何为任意有向无环图构造分层,使得所有边“指向上层”。
1.6.1 数学归纳
证明引理1.23存在多种方法。一种做法是:首先针对小型图(如具有1、2或3个顶点的图,参见图1.9)进行证明——这类有限情形可通过穷举法验证,随后尝试将证明推广至更大规模的图。这种证明方法的技术术语称为归纳证明。
图1.9:
具有一、二、三个顶点的有向无环图示例及顶点分层标注的有效方式
归纳法本质上是显而易见的“肯定前件“逻辑规则(Modus Ponens)的应用,该规则指出:若(a) 命题为真,且(b) 蕴含,则为真。
在归纳证明的框架中,我们通常有一个由整数参数化的命题,并通过证明以下两点来完成:(a) 为真;(b) 对任意,若均为真,则为真(尽管证明(b)通常是难点,但也存在需要巧妙处理“基础情形“(a)的案例)。通过运用肯定前件规则,我们可以从(a)和(b)推导出为真。继而基于与为真的事实,结合(b)再次运用肯定前件规则可推出为真。如此循环往复,可证得对所有均有为真。其中(a)称为“基础情形“,(b)称为“归纳步骤“,(b)中假设对成立的条件称为“归纳假设“(此处描述的归纳形式有时被称为“强归纳法“,以区别于“弱归纳法“——后者将(b)替换为“若为真则为真“;弱归纳法可视为强归纳法的特例,即不要求使用为真的条件)。
归纳证明与递归算法密切相关。两者都是通过将大规模问题转化为较小规模的同类实例来求解。在解决输入规模为的问题时,递归算法会预设“若已获得解决规模小于的问题实例的方法“;而在证明参数为的命题时,归纳法会思考“若已知对任意均有为真“。
归纳与递归都是本课程及计算机科学领域(甚至数学与其他科学领域)的核心概念。初学者可能会感到困惑,但随着实践积累将会逐渐理解。若需进一步了解归纳证明与递归,可参考斯坦福大学CS103课程讲义、MIT 6.00课程讲座或Lehman-Leighton专著节选。
1.6.2 通过归纳证明结论
通过归纳法证明引理1.23有多种方式。我们将基于顶点数量进行归纳,因此定义命题如下:
表示:“对于每个具有个顶点的有向无环图,都存在对的分层赋值。”
当(即图不含顶点)时命题显然成立。因此只需证明:对于每个,若成立则成立。
为此,我们需要找到一种方法:给定具有个顶点的图,将寻找分层的问题转化为寻找具有个顶点的其他图的分层问题。核心思路是找到的一个源点(即没有入边的顶点)。随后将顶点分配至0层,并依据归纳假设将剩余顶点分配至等层。
以上是引理1.23证明的直观思路。但在撰写正式证明时,我们将基于后见之明进行优化,将原本曲折的推理过程转化为从“证明:“开始到“证毕(QED1)”(或符号)结束的线性化逻辑流。讨论、示例和旁注虽颇具启发性,但应该置于这两个标记界定的空间之外——正如优秀的指南所述,此空间内“每个句子都必须承担论证功能“。如同编程,我们可以将证明分解为小型“子程序“或“函数“(数学中称为引理或断言),即通过辅助性小命题来证明主要结论。但证明结构必须确保读者能清晰把握论证阶段,理解每个句子的作用及所属部分。现正式证明引理1.23。
证明:设为有向无环图,为其顶点数。采用对归纳法证明。基础情形时命题显然成立。当时,归纳假设为:所有顶点数不超过的有向无环图均存在分层。
首先建立如下断言:
断言:图必存在入度为零的顶点。
断言证明:假设反之,即每个顶点都有入邻居。任取顶点,令为的入邻点,为的入邻点,依此重复步构造序列,其中每个都有是的入邻点(即存在边)。由于图仅含个顶点,该序列的个顶点中必存在重复,即存在使得。此时序列构成环,与有向无环图假设矛盾。(断言证毕)
根据该断言,取为中某个入度为零的顶点,令为移除后得到的图。含个顶点,由归纳假设存在分层函数如下: 。定义函数
需证是有效的分层赋值,即对任意边满足。分情形讨论:
- 情形1:且。此时边存在于中,由归纳假设有,故。
- 情形2:且。此时,而。
- 情形3:且。此情形不可能发生,因为没有入邻居。
- 情形4:且。此情形亦不可能,因这意味着存在自环(属于有向无环图禁止的环结构)。
故是的有效分层赋值,证明完成。
暂停思考:
阅读证明的能力与构造证明同样重要。事实上,如同理解代码,这本身就是一项高阶技能。建议重读上述证明,逐句思考:其假设是否合理?该句是否真正达成了论证目标?另一个好习惯是在阅读时对每个变量(如上述证明中的、、、等)思考以下问题:(1)变量类型是什么(数字/图/顶点/函数?);(2)已知信息有什么(是否为集合的任意元素?是否已证明其某些性质?);(3)试图论证的目标是什么?
1.6.3 最小性和唯一性
定义1.22:拓扑排序保证每个有向无环图都存在分层函数,但这种分层不一定唯一。例如,若是图的有效分层,那么定义为的函数也是有效分层。然而最小分层却是唯一的——最小分层要求每个顶点都被赋予尽可能小的层数。现正式定义最小性并陈述唯一性定理:
Theorem 1.2 (定理1.26:最小分层的唯一性).
设为有向无环图。若对每个顶点:当无入邻居时,当有入邻居时存在某个入邻居满足,则称分层函数是最小的。
对于的任意两个分层函数,若和都是最小分层,则。
定理1.26:最小分层的唯一性中的最小性定义意味着:对每个顶点,我们无法在保持分层有效性的前提下将其移至更低层。若是源点(即入度为零),则最小分层必须将其置于层;对于其他顶点,若,则由于存在满足的入邻居,我们无法将修改为或更小值。定理1.26:最小分层的唯一性表明最小分层是唯一的,即任何其他最小分层都与完全相同。
证明思路:对层数进行归纳。若和都是最小分层,则它们必然在源点处取值一致(因为都必须将源点分配至层)。接着可证明:若和在第层及以下取值一致,则最小性性质要求它们在第层也必须一致。实际证明中使用了一个简化表述的技巧:不直接证明(即对每个有),而是证明较弱的命题—对每个有(该条件弱于相等条件,因为必然蕴含)。由于和只是两个最小分层的标注符号,通过互换符号标签即可用相同证明得到对每个有,从而证得
证明:设为有向无环图,是其两个最小有效分层。我们将通过对的归纳证明:对每个有。由于除最小性外未对作任何假设,该证明同样可推出对每个有,故而对每个有,此即所需结论。
当时显然成立:此时,故至少等于。当时,根据的最小性,若则必存在某个入邻居满足。由归纳假设得,而由于是有效分层,必有,这意味着。
暂停思考:
定理1.26:最小分层的唯一性的证明虽然完全严谨,但表述较为简练。请务必仔细阅读并理解为何这是一个无懈可击的证明。
1.7 本书所用到的符号及规范
本书采用的大部分符号标记均为数学文本中的通用规范,主要差异点如下:
- 自然数集的索引从开始(尽管许多计算机科学领域的文献亦采用相同约定)
- 集合的索引从开始,因此其定义为(其他文献常定义为)。类似地,字符串索引也从开始,故字符串写作
- 若为自然数,则不表示数字,而是长度为的字符串(即连续个“1”)。同理,表示长度为的字符串
- 部分函数未必在所有输入上都有定义。符号默认表示全函数,若需强调函数为部分函数时,将采用的写法
- 本课程主要将计算问题描述为计算布尔函数,而其他教材常采用判定语言的表述。这两种视角具有等价性:对于任意集合,存在对应函数满足当且仅当。计算部分函数对应文献中的“承诺问题”(promise problem)。鉴于语言表述在其他教材中更加常见,我们将适时提醒读者注意这种对应关系
- 使用和分别表示向上取整和向下取整函数,表示除以的余数(即)。在需要整数的语境中,通常默认将数值隐式取整。例如“长度为的字符串”实际指的长度为(依据惯例采用向上取整,但多数情况下取整方式不影响结论)
- 遵循计算机科学文献惯例,默认对数以为底,即等价于
- 记号是的缩写(即存在常数使得对足够大的满足)。类似地,表示(即存在常数使得对足够大的满足)
- 依照数学文献惯例,通过添加撇号扩展标识符集:若表示某对象,则、等表示同类型的其他对象
- 为降低认知负荷,定理和习题陈述中常使用等整常数。这类“整齐“常数通常无特殊含义,仅为任意选取。例如定理“算法在长度为的输入上计算函数至多需要步“中的数值可视为足够大的任意常数,实际可用更小的常数证明的界。同理,若问题要求证明某量至少为,实际可能存在更小的常数使得该量至少为
1.7.1 变量命名规范
正如编程一样,数学中充满了各种各样的变量。当你看到一个变量时,追踪这个变量所属的类型至关重要(例如整数、字符串、函数、图等)。为了简化这一过程,我们尝试一致的为特定的类型使用特定的变量。部分命名规范在本节列出。这些命名规范并不是无法更改的法则,有时我们可能会稍微偏离这一规范。并且,这些规范并没有取代在声明新变量前明确指出其指代对象的要求。
本书中的变量命名规范:
标识符 通常指代的对象类型 自然数(即集合中的元素) 趋近于的正实数 通常表示上的字符串,有时也表示数字或其他对象。我们常将对象与其字符串表示视为同一 图。顶点集一般表示为,且通常。边集一般表示为 集合 函数。通常(非绝对)用小写标识符表示有限函数(映射关系为,常见) 无限输入函数,映射关系为或(为某定值)。根据上下文,可指函数或图 布尔电路 图灵机 程序 表示时间界限的函数,映射关系为 正数(常指未明确的常数,例如表示存在常数使得对所有满足)。有时也以来表示此类常数 有限集(通常用于表示字符串集合的字母表)
1.7.2 一些惯用表达
数学文本通常遵循特定惯例或“惯用表达”。本文使用的一些典型惯用表达包括:
- “设为…”、“令表示…”或“令”:这些都是在表达指代省略号所代表的内容。当表示某些对象的属性时我们可能会通过“若…满足…条件,则称其具有性质“的方式来定义。虽然我们尽量先定义后使用,但有时为了语句流畅会在定义前使用术语,此时会通过“其中指…”的说明来解释前述表达中的含义。
- 量词:数学文本涉及大量“对于所有”和“存在”等量词。有时我们会完整拼写为“对于所有”或“存在”,有时则直接使用符号和。必须注意每个变量的量化方式及其依赖关系。例如“对于每个,存在”意味着的选择依赖于。量词顺序至关重要:命题“对每个大于的自然数,都存在质数能整除”为真,而“存在质数能整除每个大于的自然数”则为假。
- 编号公式、定理、定义:为便于追溯已定义术语和已证明命题,我们通常为其添加(数字)标签,并在文中其他部分引用。
- (i.e.,)与(e.g.,):数学文本中常见这类拉丁缩写。当与等价时使用”(i.e., )”;当是的实例时使用“(e.g., )”,如“自然数(i.e., 非负整数)”或“自然数(e.g., 77)”。
- “因此”、“故而”、“可得”:这些词引导的句子是由前文推导得出的结论,例如“具有个顶点的图是连通的,因此它至少包含条边”。有时使用“实际上”引出的文本来论证前句主张,如“具有个顶点的图至少包含条边。实际上这是因为具有连通性。”
- 常数:在计算机科学中,我们通常关注算法资源消耗(如运行时间)随某些量(如输入长度)的变化规律。将不依赖于输入长度的量称为常数,因此常出现如下表述:“存在常数,使得对任意,算法在长度为的输入上至多运行步。”虽然严格来说“常数”这个限定词并非必要,但加上它可以强调是与无关的固定值。有时为降低认知负荷,我们会直接用10/100/1000等足够大的整数替代,或采用大表示法表述为“算法的时间复杂度为”。
本章回顾:
- 需要掌握的基本数学数据结构包括:数字、集合、元组、字符串、图和函数
- 可通过基础对象定义更复杂的概念,例如图可通过顶点对集合来定义
- 基于精确定义的对象可表述明确无歧义的命题,并通过数学证明判定真伪
- 数学证明并非形式化的仪式,而是认证命题真实性的清晰、严密且无懈可击的论证
- 大表示法是去掉次要细节、聚焦核心数量关系的极佳形式化工具
- 掌握数学概念的唯一途径是在解决问题中实践运用,预计您需要在本课程学习中反复查阅本章的定义与符号
1.8 习题
习题1.1(逻辑表达式):
a. 写出一个涉及变量以及运算符(与)、(或)和(非)的逻辑表达式,使得当多数输入为真时为真。
b. 写出一个涉及变量以及运算符(与)、(或)和(非)的逻辑表达式,使得当输入之和(将“真”视为,“假”视为)为奇数时为真。
习题1.2(量词):
使用逻辑量词(对所有)、(存在),以及和算术运算符写出以下表达式:
a. 表达式使得对每个自然数,为真当且仅当整除。
b. 表达式使得对每个自然数,为真当且仅当是的幂。
1.9 参考书目
标题“一个数学家的辩白”指的是哈代所著的经典作品(Hardy, 1941)。即便哈代的观点存在谬误,其著作仍极具阅读价值。
本书所需的数学背景知识可参考众多网络资源。其中麻省理工学院6.042课程《计算机科学数学》(Lehman, Leighton, Meyer, 2018)的讲义内容极为全面,课程视频与作业均在线公开。伯克利CS70课程《离散数学与概率论》同样提供详尽的在线讲义。
离散数学的其他参考资料包括罗森著作(Rosen, 2019)及吉姆·阿斯彭斯的在线教材(Aspens, 2018)。刘易斯与扎克斯(Lewis, Zax, 2019)以及弗莱克的在线著作(Fleck, 2018)对相同内容作了更通俗的阐释。索洛(Solow, 2014)是证明阅读与写作的优质入门指南。库恩(Kun, 2018)为具有编程背景的读者撰写了数学导论。斯坦福CS103课程提供关于数学证明技巧与离散数学的精彩讲义合集。
定义1.3:无向图中“graph“(图)一词由数学家西尔维斯特于1878年参照用于分子可视化的化学图式所创。需注意该术语与通常表示数据图表(尤其是函数相对于的图像)的“graph“存在语义混淆。二者可通过以下方式建立关联:将函数与定义在顶点集上的有向图相关联,使得对每个,都包含一条从指向的边。在此构造的有向图中,集内每个顶点的出度均为。若函数是单射,则集内每个顶点的入度至多为;若函数是满射,则集内每个顶点的入度至少为;若是双射,则集内每个顶点的入度恰好为。
卡尔·波默兰斯的引文出自多伦·齐尔伯格的个人主页。
1: QED即拉丁文quod erat demonstrandum”,意为“这被证明了”