前序的链接:元组关系演算
六. 蕴含式 ===》
1. 什么是“蕴含式”===》
设p、q为两个命题。复合命题“如果p,则q”称为p与q的蕴含式,记作p→q,并称p为蕴含式的前件,q为后件。定义中规定p→q为假当且仅当p为真q为假。
或许有同学会问:我发现这个“蕴含式”好像我们高中时所学的“命题”。自信一点,把“好像”去掉,只不过“蕴含式”比高中时所学的“命题”的范围更广一些。
2. “蕴含式”的意义 ===》
不难发现,“蕴含式”的逻辑关系为:q是p的必要条件,p是q的充分条件。也就是说诸如“只要p就q”、“p仅当q”、“只有q才p”...等,都可以符号化为p→q的形式。
3. “蕴含式”的真值表(True Table) ===》
4. 理解的误区 ===》
在我们平时遇到的“p→q”要么是p与q之间存在着一定的联系,要么是在前件p为真的前提下作出的判断。就比如我们在高中时学过的“命题”,它的形式是“若p,则q”,形式与“蕴含式”一模一样,但是细心的同学就会发现,我们在研究问题的时候通常将前件p视为真命题,然后再来研究后件q的真假性,从而判断“命题”真假性。所以说我们用以前高中的的思路是很难理解这个真值表(True Table)的。
但是要是真想理解起来倒也不是很难,举个栗子:这里存在着一个蕴含式“如果我当上了班长,我将提高同学的福利”。所以不妨设,前件p为“我当上了班长”,后件q为“我将提高同学的福利”,那么这个蕴含式就可以符号化为p→q,记为I。
所以问题就是判断I的真假,也就是说我有没有撒谎。
很显然当p为真,q为假的时候,我并没有履行我的诺言,故此时I为"False"。当p为假的时候,不管我有没有提高同学们的福利,你都不能说我没有履行我的诺言,因为我就没有当上班长。
5. 蕴含式中的等价式 ===》
( i). “蕴含式” && 德摩根律 ===》
--(1). 普通(我愿称之为常量)“蕴含式” && 德摩根律 的等价式===》
1st. p→q ⇔ ¬p∨q ;
2nd. 德摩根律:¬(p∨q) ⇔ ¬pΛ¬q ;
--(2). 自由元组变量在 “蕴含式” && 德摩根律 的等价式 ===》
1st. p(x)→q(x) ⇔ ¬p(x)∨q(x);
2nd. 德摩根律:¬(p(x)∨q(x)) ⇔ ¬p(x)Λ¬q(x);
--(3). 约束元组变量在 “蕴含式” && 德摩根律 的等价式 ===》
1st. ∀xp(x)→∃xq(x) ⇔ ¬∀xp(x)∨∃xq(x);
2nd. 德摩根律:¬(∀xp(x)∨∃xq(x)) ⇔ ¬∀xp(x)Λ¬∃xq(x);
( ii). 量词转换律 ===》
--(1). “存在量词∃”转换为“全称量词∀”:¬∀xp(x) ⇔ ∃x¬p(x);
--(2). “全称量词∀”转换为“存在量词∃”:¬∃xq(x) ⇔ ∀x¬q(x);
(iii). 量词辖域的扩张和收缩(八个等价式) ===》
--(1). 若量词的辖域中是合取式(Λ)或者析取式(∨),那么对于不受约束的谓词公式(q)可以直接进入或者退出该辖域 ===》
1st. ∀x(p(x)Λq) ⇔ ∀xp(x)Λq,同样的对于∀x(p(x)∨q) ⇔ ∀xp(x)∨q也成立;
2nd. ∃x(p(x)∨q) ⇔ ∃xp(x)∨q, 同样的对于∃x(p(x)Λq) ⇔ ∃xp(x)Λq也成立;
--(2). 若量词的辖域中是“蕴含式”的前件,那么作为后件的不受约束的谓词公式不可以直接进入或者退出该辖域 ===》
1st. ∀xp(x) → q ⇔ ¬(∀xp(x))∨q ⇔ ∃x¬p(x)∨q ⇔ ∃x(¬p(x)∨q) ⇔ ∃x(p(x) → q);
2nd. ∃xp(x) → q ⇔ ¬(∃xp(x))∨q ⇔ ∀x¬p(x)∨q ⇔ ∀x(¬p(x)∨q) ⇔ ∀x(p(x) → q);
--(3). 若量词的辖域是“蕴含式”的后件,则作为前件的不受约束的谓词公式可以直接进入或者退出该辖域 ===》
1st. q → ∀xp(x) ⇔ ¬q∨∀xp(x) ⇔ ∀x(¬q∨p(x)) ⇔ ∀x(q → p(x));
2nd. q → ∃xp(x) ⇔ ¬q∨∃xp(x) ⇔ ∃x(¬q∨p(x)) ⇔ ∃x(q → p(x));
所以,约束元组变量在 “蕴含式” && 德摩根律 的等价式 ===》
1st. ∀xp(x)→∃xq(x) ⇔ ¬∀xp(x)∨∃xq(x) ⇔ ∃x¬p(x)∨∃xq(x);
2nd. 德摩根律:¬(∀xp(x)∨∃xq(x)) ⇔ ¬∀xp(x)Λ¬∃xq(x);
(iv). 含量词的合取式、析取式的等价式 ===》
--(1). “全称量词∀”对合取式的分配:∀x(p(x)Λq(x)) ⇔ ∀xp(x)Λ∀xq(x);
--(2). “存在量词∃”对析取式的分配:∃x(p(x)∨q(x)) ⇔ ∃xp(x)∨∃xq(x);
【注意:】
1. “全称量词∀”可以对合取式进行分配,但是不能对析取式进行分配;这句话从另一角度上来说:
∀xp(x) ⇔ p(a1)Λ...Λp(an);
2. “存在量词∃”可以对析取式进行分配,但是不能对合取式进行分配;这句话从另一角度上来说:
∃xp(x) ⇔ p(a1)∨...∨p(an);
(v). 说了这么多,我到底想要表达什么? ===》
当某一个命题为条件命题(也就是“蕴含式”)的时候,记为p→q。这所表达的意思就是:当p为真并且p→q也为真的情况下(这一前提常常被人们忽略,认为这是理所当然的),发生了p事件就一定能发生q事件。我们将p和q视为两个集合,不难理解,这时就能得到p⊆q。
所以当要表示两个集合是父子集合的时候,我们可以用“蕴含式”这样来表述:∀x{p(x)∈P → ∃y[q(y)∈QΛp(x)=q(y)]}。我们可以这样来分析一下 ===》
step_1: ∀x{Condition} —— 对于任意的x都要满足某个条件,这个条件用Condition来代指;
step_2: Condition:p(x)∈P → ∃y[q(y)∈QΛp(x)=q(y) —— 这个条件是:只要p(x)属于P集合中,那么总能找到某一个y,使得q(y)属于Q集合,并且有p(x)=q(y)成立;
很好理解吧,但是这里我并只是bb离散数学,而是要将这玩意儿和SQL的实际情况相结合。在SQL中有一个很巧妙但是让人们感到十分蛋疼的一个机制:没有“全称量词∀”。这是我们就需要运用上面所学到的相关知识,将这些“全称量词∀”转换为“存在量词∃”。怎样表述命题之间的关系、怎样转换为不含“全称量词∀”的命题,这都已经了解了,那我们来看下面一个实例 ===》
诉求:查询选修了全部课程的学生的姓名和学号。
元组关系运算的表达式 ===》
{new_s(2) |
∃s【 # 总是存在一个s满足条件:
s(S) Λ # s∈S
∀c【c(C) → # 对于任意的c满足条件:只要c∈C,那么一定有存在某个sc满足条件:
∃sc【sc(SC) Λ sc.sno = s.sno Λ sc.cno = c.cno】
# sc∈SC,并且使得sc.sno = s.sno和sc.cno = c.cno同时成立 —— 意思就是C.CNo集合是SC.CNo集合的子集,并且将这个集合连接起来;
】
】 Λ
new_s[1] = s[1] Λ
new_s[2] = s[2]
}
但是终究不能元组关系演算来进行筛选,还得转换为SQL标准语言。这里就要用到一开始的几个公式了 ===》
step_1: 首先将元组关系演算分解、简化:∃s, s(S) Λ p,即为存在s满足条件:s∈S,并且p;
注:其中的p为“∀c【c(C) → ∃sc【sc(SC) Λ sc.sno = s.sno Λ sc.cno = c.cno】】”。
step_2: 将归属关系p(P)尽量去掉,进一步简化,因为归属关系在SQL统一用“SELECT 字段名 FROM 表”来表述;
注:p为“∀c【c(C) → ∃sc【sc.sno = s.sno Λ sc.cno = c.cno】】”。
step_3: 灵活运用“蕴含式”公式,将能合并的合并,使得最后的形式为:
∃p1【Conditions Λ ∃p2【Conditions Λ 【...∃pn【Conditions】】】】;
p = ∀c【¬c(C) ∨ ∃sc【sc.sno = s.sno Λ sc.cno = c.cno】】;
= ∀c【∃sc【sc.sno = s.sno Λ sc.cno = c.cno】】;
= ¬ 【∃c ¬【∃sc【sc.sno = s.sno Λ sc.cno = c.cno】】】;
step_4: 所以最后的形式为:∃s ¬【∃c ¬【∃sc【sc.sno = s.sno Λ sc.cno = c.cno】】】;
SELECT SNo, SN
FROM S
WHERE
NOT EXISTS (
SELECT *
FROM C
WHERE
NOT EXISTS (
SELECT *
FROM SC
WHERE CNo = C.CNo AND SNo = S.SNo
)
)
这里其实有一个很容易弄错的地方:误以为连接SC表和S表的元组变量要单独写一个“∃sc【sc(SC) Λ sc.sno = s.sno】”,也就是说将两个表间的连接独立开,各连各的。这个想法非常的幼稚,为什么这样说呢,打一个形象的比方:S表相当于左边的一个岸,C表相当于右边的一个岸,SC表显然就是连接两岸的桥,如果说想要用SC表将C表和S表连起来,那么肯定就需要找到同一个SC表中的元组sc,让它左手牵S表的元组s,同时右手牵着C表的元组c;如果这不是同时牵的话,就很可能导致桥不是同一个桥,即不是同一个sc元组。下面我们是可以通过简单的逻辑证明来表述的。如果我们将这两个连接独立,则会得到 ===》
1st. p = ∃sc【sc.sno = s.sno】;
2nd. q = ∀c【¬c(C) ∨ ∃sc【sc.cno = c.cno】】;
= ∀c【∃sc【sc.cno = c.cno】】;
= ¬ 【∃c ¬【∃sc【sc.cno = c.cno】】】;
3st. 现在的形式为:∃s【p Λ q】,但是并不是“存在量词∃”的迭代形式,还需要进一步合并;
4th. 由德摩根律得:p Λ q = ¬(¬p ∨ ¬q) = ¬(p → ¬q);
5th. 将p、q代入得:¬{∃sc【sc.sno = s.sno】 → ∃c ¬【∃sc【sc.cno = c.cno】】}
6th. 由“量词辖域的扩张和收缩”的第三点,前件不受∃c的辖域,所以可以等价为:
¬【∃c【∃sc【sc.sno = s.sno】】 → ¬【∃sc【sc.cno = c.cno】】】) ⇔
¬【∃c ¬【∃sc【sc.sno = s.sno】】 ∨ ¬【∃sc【sc.cno = c.cno】】】) ⇔
¬【∃c ¬【∃sc【sc.sno = s.sno】】 Λ ∃sc【sc.cno = c.cno】】)
7th. 很多同学就会将这个等价与“¬【∃c ¬【∃sc【sc.sno = s.sno Λ sc.cno = c.cno】】】”结果好像是一模一样,但是这里其实是有一个很大的逻辑错误:由“含量词的合取式、析取式的等价式”的注意事项,我们知道“存在量词∃”只能对析取式进行分配、不能对合取式进行分配。这是因为“∃xp(x) Λ ∃xq(x)”和“∃x【p(x) Λ q(x)】”之间的关系是“蕴含式”:
“∃x【p(x) Λ q(x)】 → 【∃xp(x) Λ ∃xq(x)】”
我们可以简单的来证明一下 ===》
1. 从左到右:假设前件“∃x【p(x) Λ q(x)】”为真,那么存在一个x=c,使得p(c)Λq(c)为真,即存在一个x=c使得p(c)为真,存在一个x=c使得q(c)也为真;故而后件“∃xp(x) Λ ∃xq(x)”为真;
2. 从右到左:假设后件“∃xp(x) Λ ∃xq(x)”为真,那么我们只能得到,存在一个x=c使得p(c)为真,存在一个x=b使得q(b)为真,并不能保证b=c,所以由后件得不到前件;
总结 ===》
1. 掌握“蕴含式”,以及什么时候运用;
提示:等价式、德摩根律、收缩与扩张,当表示一个集合是另一个集合的子集时运用“蕴含式”。
2. 充分理解“含量词的合取式、析取式的等价式”,从而得出结论:不能将连接操作分开写,必须写在一起,这里的一起是指:保证连接时的元组是同一个。具体表现为:写在靠后的WHERE语句中,因为要包含较多的SELECT语句(本质上是表),使得选择元组是同一个;
提示:“全称量词∀”只可以对合取式进行分配;“存在量词∃”只可以对析取式进行分配。
内部链接:
一. 案例 ===》
2. 案例_02_以'李力'老师教授的课程为准,学生的5种选课情况
3. 案例_03_以'数据库'和'JAVA'_教师姓名、编号为准,老师授课的4种选课情况
4. 案例_04_以全部学生为准,课程被选的4种选课情况(只列举出2种)
二. 前序 ===》
(对不起,HTML+CSS+JAVASCRIPT还木有学完,所以排版很难看,请各位道友们海涵)