为什么essential?
1.标题中的essential:仿照《Essential C++》中只介绍必要的内容、不深究细节的风格,本文也以实用为唯一标准,标题添加essential前缀,简短阐明风格。
2.集合论的essential:数学是计算的基石(暂且当作如此),而集合论则是当代数学的重要基石。集合论的多数内容在我们看来都是“显然如此”的,换言之已经是在我们漫长的数学学习过程中被默认的内容。
朴素集合论
概括公理:$P(x)$是一个命题,则$\lbrace x|P(x)\rbrace $是一个集合
解释:命题是判断语义的意思。$P(x)$可表示为一个判断,如if (x)
、if (x < 100 && x >= 0)
等,自然也可以表示为function的形式,但逻辑本质还是一个判断,返回真or假,如bool not_zero(int x) {return x;}
等。x是命题的参数,而$\lbrace x|P(x)\rbrace $则表示所有使P(x) == true
的$x$。这些$x$就组成了一个集合。
其实这里就是在定义集合,虽然并非一个严谨的定义。我们举几个具体的例子来说明。
- 不重复性:集合中的元素是唯一的。这里就比较符合
std::set
以及std::unordered_set
的定义,如$\lbrace 1,2,3\rbrace $是一个合法集合,而$\lbrace 1,1,2,3\rbrace $不是一个合法的集合。 - 外延公理:两个集合互为子集时,或者说属于一个集合的任意元素都属于另一个集合,两个集合逻辑上相等。这也限定了两个有限集合的判等方法就是,元素数一致&&枚举所有元素分别判等。
- 属性要求:集合的元素数大于等于0。如
std::size_t std::set<T>::size() const
显然返回的是unsigned整型。 - 定义要求:集合必须被明确定义。给定一个输入,它要么属于一个集合,要么不属于一个集合。一个集合可通过穷举所有元素进行定义,也可以进行完备的描述来定义,如
std::set<int> S = {1,2,3};
或者$\lbrace x|x > 0, x < 10, x\in N\rbrace $。
扩展:罗素悖论(Russell's paradox)
朴素理解(理发师悖论):一个理发师,只为“不给自己刮胡子的人刮胡子”。若一个顾客自己刮胡子,则理发师就不给他刮胡子;若一个顾客自己不刮胡子,则理发师就给他刮胡子。至此没有问题,那么理发师应不应该给自己刮胡子呢?如果应该给自己刮胡子,自己则是“自己刮胡子的顾客”,于是不应该给自己刮胡子;反之也得到相似的悖论。
集合运算
补集:在指定集合$S$之内,$X^c$表示$S$中除了$X$的集合。
交集:集合$X$与$Y$相交的范围,$X\bigcap Y$。即对于任意$x\in (X\bigcap Y)$,有$x\in X$且$x\in Y$。
并集:集合$X$与$Y$范围组合并去重,$X\bigcup Y$。即对于任意$x\in X,有$x\in (X\bigcup Y)$,且对于任意$y\in Y$,有$y\in (X\bigcup Y)$。
交并均分别满足交换律:$X\bigcap Y = Y\bigcap X$,$X\bigcup Y = Y\bigcup X$。通俗来说就是符号没有作用方向之分。
交并均分别满足结合律:$X\bigcap Y\bigcap Z = X\bigcap (Y\bigcap Z)$。通俗来说就是同类符号,运算顺序无所谓。
交并的分配律:$(X\bigcup Y)\bigcap Z = (X\bigcap Z)\bigcup (Y\bigcap Z)$,$(X\bigcap Y)\bigcup Z=(X\bigcup Z)\bigcap (Y\bigcup Z)$。没法通俗说。
直觉
集合并非是一定可以在实践上被穷举的,它可能是逻辑上有限,但实践中“近乎无限”的。
集合可以被视为“能够描述一切东西”。这么说就非常抽象了,以一种通俗的方式讲,当加入足够多的定语的时候,我们就能准确描述一个具体的东西。当然只这么说的话就没有什么用,我们说点实用的。在很多应用领域里面,我们都会说到“空间”这个概念,比如数据空间/特征空间。空间也是一种集合,集合中的每一个元素都可以视为空间中的一个数据点,所以那些“空间”都满足集合的性质。
这么一说的话,集合的概念就可以泛化了,数轴上的范围是集合,二维坐标系下的某个曲面是一个集合,等等。这些东西都可以用集合运算来考虑。