离散数学——递归

离散数学——递归

数学归纳法

数学归纳法证明的是 ∀ n P ( n ) \forall n P(n) nP(n) 的成立,其中 P ( n ) P(n) P(n) 是一个谓词,数学归纳法有两个步骤:

  1. 基础步骤:证明 P ( 1 ) P(1) P(1) 成立。
  2. 归纳步骤:证明 ∀ n ( P ( n ) → P ( n + 1 ) ) \forall n (P(n) \to P(n+1)) n(P(n)P(n+1)) 成立。

为了证明第二点,我们先假设 P ( k ) P(k) P(k) 成立,这个技巧叫做归纳假设。

在数学归纳中,还有一类称为强归纳的数学归纳法:

  1. 基础步骤:证明 P ( 1 ) P(1) P(1) 成立。
  2. 归纳步骤:证明 ∀ n ( ⋂ i = 1 n P ( n ) → P ( n + 1 ) ) \forall n (\bigcap_{i=1}^{n} P(n) \to P(n+1)) n(i=1nP(n)P(n+1)) 成立。

强归纳也称第二类数学归纳法,完全归纳法。可以证明,强归纳和第一类数学归纳法是等价,即可以用数学归纳法证明的也可以用强归纳证明,反之也一样。

良序原理是数学归纳法的原理和基础,良序原理说明,一个非空的非负整数集合,都有一个最小元素。

关于欧几里得算法的证明

  1. 基础步骤: gcd ⁡ ( a , 0 ) = a \gcd(a,0) = a gcd(a,0)=a ,正确性显然。
  2. 归纳步骤: gcd ⁡ ( a , b ) = gcd ⁡ ( b , a m o d    b ) \gcd(a,b) = \gcd(b,a \mod b) gcd(a,b)=gcd(b,amodb)

对于归纳步骤来说,如果我们能够证明 ( a , b ) (a,b) (a,b) 的任何一个公因子和 ( b , r ) (b,r) (b,r) 一样,那么归纳步骤得证。

其中 r = a − n b r = a-nb r=anb 其中 n n n 是商数,如果 ( a , b ) (a,b) (a,b) 存在公因子 d d d ,那么 ( a − n b ) / d (a - nb) / d (anb)/d 一定是整数,那么 r / d r / d r/d 一定是整数,因此 d d d ( b , r ) (b,r) (b,r) 的一个公因子。

其中 a = r + n b a = r + nb a=r+nb ,如果 ( b , r ) (b,r) (b,r) 存在公因子 d d d 那么 a / d a / d a/d 也是一个整数,因此 ( a , b ) (a,b) (a,b) 也有公因子 d d d

递归定义

递归定义函数包括一下两步:

  1. 基础步骤:指定函数在 0 0 0 处的函数值。
  2. 递归步骤:给定一个规则,能够通过 0 0 0 k k k 的函数值计算出 k + 1 k+1 k+1 的函数值。

上述定义称为递归定义或者归纳定义,递归定义是良定义的,这也就是说,在 k k k 处的函数值是唯一定义的且没有歧义的。

除了递归定义的函数,还有递归定义的离散结构。

递归定义的离散结构同样包括两个步骤:

  1. 基础步骤:指定了一个离散结构中的初始元素。
  2. 递归步骤:由离散结构中的已知元素构造出更多元素的规则。

递归定义有时也包含排除规则,指出了离散结构除了基础步骤和递归步骤定义的元素外,不包含的元素。

字符串是一种递归定义的离散结构。

定义: 集合 ∑ ∗ \sum^* 是在 ∑ \sum 上定义的字符串集合,递归定义为:

基础步骤: λ ∈ ∑ ∗ \lambda \in \sum^* λ 其中 λ \lambda λ 是空字符串。

递归步骤:如果 ω ∈ ∑ ∗ \omega \in \sum^* ω 并且 x ∈ ∑ x \in \sum x ,那么 ω x ∈ ∑ ∗ \omega x \in \sum^* ωx

合法形式是一种递归定义的离散结构。

例如合法括号序列的定义:

基础步骤:() 和空序列是一个合法的括号序列。
归纳步骤:如果 A 和 B 都是合法的括号序列,那么 (A) 是合法的括号序列, AB 也是合法的括号序列。

结构化归纳

结构化归纳是一种证明离散结构中某些元素具有某种性质的证明方法:

  1. 基础步骤:证明在递归定义中的基础元素都满足该性质。
  2. 归纳步骤:证明通过递归步骤得出的新元素也满足性质。

递归算法

我们说一个算法是递归的,当一个算法将问题通过解决相同实例的更小的子问题解决。

递归算法是一个自顶向下的过程,而迭代算法是一个自底向上的过程。

程序正确性

程序正确性指的是每一个合法输入,程序都会给出一个正确的结果,这是程序正确性的感性定义。

而程序正确性分为两个部分:

  1. 部分正确性:给出一个合法输入,如果程序能终止,那么程序的结果一定是正确的。
  2. 完全正确性:给出一个合法输入,程序总是是终止。

为了证明一个程序是满足正确性的,我们需要两个断言,第一个断言称为初始断言,指出了输入值所需要的属性,和最终断言,指出如果程序按照预期执行,那么一定有输出结果。

定义:如果一个程序 S S S 是相对于初始断言 p p p 和最终断言 q q q 是部分正确的,如果 p p p 是真的对于 S S S 的输入来说,并且 S S S 也能正常终止,那么 q q q 就是正确的对于 S S S 的输出来说。记为 p { S } q p\{S\}q p{S}q

记号 p { S } q p\{S\}q p{S}q 称为霍尔三元组。

部分正确性是好证明的,本节我们讨论部分正确性的证明,完全正确性不在本章的讨论范围内。

组合推导过程

有时候,使用推导规则能够简化程序的正确性证明:

如果 p { S 1 } q p\{S_1\}q p{S1}q 并且 q { S 2 } r q\{S_2\}r q{S2}r 那么 p { S 1 ; S 2 } r p\{S_1;S_2\}r p{S1;S2}r

条件推导过程

证明程序:

if cond then S

也就是证明:

( p ∧ c o n d ) { S } q ( p ∧ ¬ c o n d ) → q (p \wedge cond)\{S\}q \\ (p \wedge \neg cond) \to q (pcond){S}q(p¬cond)q

同样的证明程序:

if cond then S1 else S2

也就是证明:

( p ∧ c o n d ) { S 1 } q ( p ∧ ¬ c o n d ) { S 2 } q (p \wedge cond)\{S_1\}q \\ (p \wedge \neg cond)\{S_2\}q (pcond){S1}q(p¬cond){S2}q

循环不变式

下一步,证明我们讨论如何证明循环程序的正确性。

while cond
    S

注意这个程序是一个循环程序,直到 c o n d cond cond 为假时结束,可以看着是多次 if 条件语句,因此我们引出循环不变式。

循环不变式指的是一个断言,每次执行完 S S S 之后,该断言保持为真。换句话说,如果 p p p 是一个循环不变式,即 i f ( p ∧ c o n d ) { S } p if(p \wedge cond)\{S\}p if(pcond){S}p 是真的。

证明一个循环程序的正确性,也就是证明:

( p ∧ c o n d ) { S } p (p \wedge cond) \{S\}p (pcond){S}p

那么

p { w h i l e ( c o n d ) S } ( ¬ c o n d ∧ p ) p\{while(cond) S\}(\neg cond \wedge p) p{while(cond)S}(¬condp)

成立。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值