程序验证(十):演绎验证(上)
基础路径(Basic Approach)
给定一个程序c,由以下specification注解:
{P}c{Q}
为了证明这个三元组,我们构造一个验证条件(verification condition, VC)的集合
- 每个VC都是某个理论的一阶公式
- 如果所有的VC都是永真的,那么{P}c{Q}就是永真的
谓词转换器
给定一个断言Q和一个程序c,一个谓词转换器(predicate transformer)是一个函数,输出另一个断言
最弱前置条件(weakest precondition)谓词转换器产生一个wp(c,Q),使得
- [wp(c,Q)]c[Q]是永真的,且
- 对于任何满足[P]c[Q]的P,P⇒wp(c,Q),也就是说,wp(c,Q)是这种断言中最弱的。
广义最弱前置条件(weakest liberal precondition)谓词转换器产生一个wlp(c,Q),使得
- {wlp(c,Q)}c{Q}是永真的,且
- wlp(c,Q)是这种断言中最弱的
wlp为我们提供了一种逆向的思路,这也符合我们的直觉。
wlp的定义
我们用霍尔三元组来定义wlp
比如wlp(y:=x+1,(∀x.x<z→x<y)→x+1≤y)=?
注意,答案并不是(∀x.x<z→x<x+1)→x+1≤x+1
因为当我们用x+1替换y以处理(∀x.x<z→x<y)时,变量x是被捕获的(captured)
捕获避免代入(capture-avoiding substitution)
当我们扩展P[a/x]时,我们需要:
- 只代入x的自由形式(free occurence)
- 将a中不自由的变量重命名以避免捕获
数组赋值规则
数组赋值的霍尔规则可以表示为:
AsgnArr {Q[x⟨a1◃a2⟩/x]}x[a1]:=a2{Q}
相应的转换器即为
wlp(x[a1]:=a2,Q)=Q[x⟨a1◃a2⟩/x]
举例:
计算wlp(b[i]:=5,b[i]=5)
wlp(b[i]:=5,b[i]=5)=(b⟨◃5⟩[i]=5)=(5=5)=true
计算wlp(b[n]:=x,∀i.1≤i<n→b[i]≤b[i+1])
进行代入
wlp(b[n]:=x,∀i.1≤i<n→b[i]≤b[i+1])=∀i.1≤i<n→(b⟨◃x⟩)[i]≤(b⟨n◃x⟩)[i+1]=(b⟨n◃x⟩)[n−1]≤(b⟨n◃x⟩)[n]∧∀i.1≤i<n−1→(b⟨n◃x⟩)[i]≤(b⟨n◃x⟩)[i+1]
序列(sequencing)
依据霍尔规则
Seq {P}c1;c2{Q}{P}c1{P′}{P′}c2{Q}
相应的谓词转换器即为
wlp(c1;c2,Q)=wlp(c1,wlp(c2,Q))
条件
依据霍尔规则
If {P}if b then c1 else c2{Q}{P∧b}c1{Q}{P∧¬b}c2{Q}
相应的转换器即为
wlp(if b then c1 else c2,Q)=(b→wlp(c1,Q))∧(¬b→wlp(c2,Q))
while循环
依据等价关系
while b do c≡if b then c;while b do c else skip
相应的wlp即为
此处略,最后转了个圈又回来了。
近似最弱前置条件
一般来说,我们无法总是算出循环的wlp,比如上面的情况。
但是,我们可以借助于循环不变式来近似它
下面,我们使用这种方式表示循环:
while b do{I}c
这里I是由程序员提供的循环不变量
最为直观的想法是令
wlp(while b do{I}c,Q)=I
但此时I可能不是最弱的前置条件
如果我们草率地认为wlp(while b do{I}c,Q)=I,我们漏了两件事情:
- 没有检查I∧¬b得到Q
- 我们不知道I是否真的是一个循环不变式
所以我们需要构造一个额外的验证条件(verification condition)的集合,
vc(while b do{I}c,Q)={I∧¬b⇒QI∧b⇒wlp(c,I)
为了在执行循环后确保Q能够实现,需要满足两个条件:
- vc(while b do{I}c,Q)中的每一个公式都是永真的
- wlp(while b do{I}c,Q)=I一定是永真的
构造vc
while是唯一一个引入额外条件的命令,但是其他的声明可能也包含循环,所以:
- vc(x:=a,Q)=∅
- vc(c1;c2,Q)=vc(c1,wlp(c2,Q))∪vc(c2,Q)
- vc(if b then c1 else c2,Q)=vc(c1,Q)∪vc(c2,Q)
综合
综上,我们得到验证{P}c{Q}的通用方法:
- 计算P′=wlp(c,Q)
- 计算vc(c,Q)
- 检查P→P′的永真性
- 检查每个F∈vc(c,Q)的永真性
若3,4检验均通过,那么{P}c{Q}是永真的,但反之不一定成立,因为循环不变式可能不是最弱的前置条件。