霍尔逻辑的概念
对于这个新概念,我们首先要知道什么是霍尔逻辑,霍尔逻辑能用来做些什么?
摘抄一下百度百科的原句:
霍尔逻辑(英语:Hoare Logic),又称弗洛伊德-霍尔逻辑(Floyd–Hoare logic),是英国计算机科学家东尼·霍尔开发的形式系统,这个系统的用途是为了使用严格的数理逻辑推理来替计算机程序的正确性提供一组逻辑规则。
简要来说霍尔逻辑是一种用于验证程序正确性的逻辑规则。
霍尔逻辑表示为一个三元组,可以称之为“Hoare Triples”,它表示为如下形式:
{
ϕ
}
P
{
ψ
}
\{\phi\}P\{\psi\}
{ϕ}P{ψ}
ϕ \phi ϕ被称为前置条件,P是程序片段, ψ \psi ψ称为后置条件
用自然语言描述一下它的含义就是,如果程序片段P在满足条件 ϕ \phi ϕ的情况下开始,那么P的执行会在满足 ψ \psi ψ的状态下结束。
我们用一个实际的例子填上去
{ x ≥ 0 } x = x + 1 { x ≠ 0 } \{x\ge 0\}x=x+1\{x\ne 0\} {x≥0}x=x+1{x=0}
也就是说,该程序以x≥0的情况下开始执行,并且运行x=x+1这条语句,程序运行结束时要求满足x≠0这个条件。
部分正确与完全正确
看看上面的程序片段P,我们考虑一种情况,如程序片段P一直执行下去不终止会发生什么?例如,现在程序片段P里面有个类似于while(true)的东西,而且循环里面又没有break语句,这种情况下压根没有P结束这个概念,所以后置条件 ψ \psi ψ在这种情况下是真是假都是无所谓的,所以也可以使后置条件 ψ \psi ψ为假来表示程序P不会终止。
在不能保证程序终止的情况下,我们称为程序部分正确(partial correctness),如果我们能够保证程序一定终止,并且满足在 ϕ \phi ϕ成立的情况下执行P后 ψ \psi ψ成立,那么我们称为完全正确(total correctness)
所以部分正确与完全正确的区别就在于是否要求程序终止。
规则(Rules)
空语句(Empty statement axiom schema)
{ P } s k i p { P } ‾ \overline{\{P\}skip\{P\}} {P}skip{P}
空语句不会更改程序的状态,所以程序执行前成立的条件,在空语句执行之后也成立
赋值语句(Assignment axiom schema)
{ P [ E / x ] } x : = E { P } ‾ \overline{\{P[E/ x]\}x:=E\{P\}} {P[E/x]}x:=E{P}
如果前置条件的变量没有经过赋值的修改,那么该变量条件可以直接放到后置条件上
相关例子:
{
x
+
1
=
43
}
y
:
=
x
+
1
{
y
=
43
}
{
x
+
1
≤
N
}
x
:
=
x
+
1
{
x
≤
N
}
\{x+1=43\}y:=x+1\{y=43\} \\ \{x+1\le N\}x:=x+1\{x\le N\}
{x+1=43}y:=x+1{y=43}{x+1≤N}x:=x+1{x≤N}
合成规则(Rule of composition)
{
P
}
S
{
Q
}
,
{
Q
}
T
{
R
}
{
P
}
S
;
T
{
R
}
\dfrac{\{P\}S\{Q\} , \{Q\}T\{R\}}{\{P\}S;T\{R\}}
{P}S;T{R}{P}S{Q},{Q}T{R}
其中Q称为中间条件
例如
{
x
+
1
=
43
}
y
:
=
x
+
1
{
y
=
43
}
a
n
d
{
y
=
43
}
z
:
=
y
{
z
=
43
}
\{x+1=43\}y:=x+1\{y=43\} \\ and \\ \{y=43\}z:=y\{z=43\}
{x+1=43}y:=x+1{y=43}and{y=43}z:=y{z=43}
根据合成规则,可以合并为
{
x
+
1
=
43
}
y
:
=
x
+
1
;
z
:
=
y
{
z
=
43
}
\{x+1=43\}y:=x+1;z:=y\{z=43\}
{x+1=43}y:=x+1;z:=y{z=43}
条件规则(Conditional rule)
{
B
∧
P
}
S
{
Q
}
,
{
¬
B
∧
P
}
T
{
Q
}
{
P
}
if B then S else T endif
{
Q
}
\dfrac{\{B\wedge P\}S\{Q\} , \{\lnot B\wedge P\}T\{Q\}}{\{P\}\text{if B then S else T endif}\{Q\}}
{P}if B then S else T endif{Q}{B∧P}S{Q},{¬B∧P}T{Q}
推导规则(Consequence rule)
P
1
→
P
2
,
{
P
2
}
S
{
Q
2
}
,
Q
2
→
Q
1
{
P
1
}
S
{
Q
1
}
\dfrac{P_{1}\rightarrow P_{2},\{P_{2}\}S\{Q_{2}\},Q_{2}\rightarrow Q_{1}}{\{P_{1}\}S\{Q_{1}\}}
{P1}S{Q1}P1→P2,{P2}S{Q2},Q2→Q1
这个规则允许加强前置条件 P 2 P_{2} P2,或者削弱后置条件 Q 2 Q_{2} Q2
说到强弱条件这个概念,我们来举个例子:
x
<
3
x<3
x<3这个条件强于
x
<
5
x<5
x<5这个条件,因为
x
<
3
x<3
x<3这个条件的范围更小,它对变量的约束力更强
循环规则(While rule)
{
P
∧
B
}
S
{
P
}
{
P
}
while B do S done
{
¬
B
∧
P
}
\dfrac{\{P\wedge B\}S\{P\}}{\{P\}\text{while B do S done}\{\lnot B \wedge P\}}
{P}while B do S done{¬B∧P}{P∧B}S{P}
规则应用
证明阶乘
证明求证阶乘的程序工作正确
( ∣ T ∣ ) y = 1 ; z = 0 ; w h i l e ( z ! = x ) { z = z + 1 ; y = y ∗ z } ( ∣ y = x ! ∣ ) (|T|)y=1;z=0;while(z != x)\{z=z+1; y=y*z\}(|y=x!|) (∣T∣)y=1;z=0;while(z!=x){z=z+1;y=y∗z}(∣y=x!∣)
证明过程
{
1
=
1
}
y=1
{
y
=
1
}
{
⊤
}
y=1
{
y
=
1
}
i
(
y
=
1
∧
0
=
0
)
z
=
0
(
y
=
1
∧
z
=
0
)
(
y
=
1
)
z
=
0
(
y
=
1
∧
z
=
0
)
i
(
⊤
)
y
=
1
;
z
=
0
(
y
=
1
∧
z
=
0
)
c
\dfrac{\dfrac{\{1=1\}\text{y=1}\{y=1\}}{\{\top\}\text{y=1}\{y=1\}}i\text{ }\dfrac{(y=1\wedge0=0)z=0(y=1\wedge z=0)}{(y=1)z=0(y=1\wedge z=0)}i}{(\top)y=1;z=0(y=1\wedge z=0)}c
(⊤)y=1;z=0(y=1∧z=0){⊤}y=1{y=1}{1=1}y=1{y=1}i (y=1)z=0(y=1∧z=0)(y=1∧0=0)z=0(y=1∧z=0)ic
\\
( y ⋅ ( z + 1 ) = ( z + 1 ) ! ) z = z + 1 ( y ⋅ z = z ! ) ( y = z ! ∧ z ≠ x ) z = z + 1 ( y ⋅ z = z ! ) i ( y ⋅ z = z ! ) y = y ∗ z ( y = z ! ) ( y = z ! ∧ z ≠ x ) z = z + 1 ; y = y ∗ z ( y = z ! ) c ( y = z ! ) while (z!=x){z=z+1;y=y*z} ( y = z ! ∧ z = x ) w ( y = 1 ∧ z = 0 ) while(z!=x){z=z+1;y=y*z}(y=x!) i \dfrac{\dfrac{\dfrac{\dfrac{(y·(z+1)=(z+1)!)z=z+1(y·z=z!)}{(y=z!\wedge z\neq x)z=z+1(y·z=z!)}i\qquad (y·z=z!)y=y*z(y=z!)}{(y=z!\wedge z\neq x)z=z+1;y=y*z(y=z!)}c}{(y=z!)\text{while (z!=x)\{z=z+1;y=y*z\}}(y=z!\wedge z=x)}w}{(y=1\wedge z=0)\text{while(z!=x)\{z=z+1;y=y*z\}(y=x!)}}i (y=1∧z=0)while(z!=x){z=z+1;y=y*z}(y=x!)(y=z!)while (z!=x){z=z+1;y=y*z}(y=z!∧z=x)(y=z!∧z=x)z=z+1;y=y∗z(y=z!)(y=z!∧z=x)z=z+1(y⋅z=z!)(y⋅(z+1)=(z+1)!)z=z+1(y⋅z=z!)i(y⋅z=z!)y=y∗z(y=z!)cwi
由上面的两式,经过合成规则推倒后,可以得出最原始的程序是正确的
再证明另外一个阶乘程序:
这个程序就相当于上面的那个程序反着来,比较难的点就是从什么地方开始证明
( y ⋅ ( x − 1 ) = ( x − 1 ) ! ∧ x > 0 ) x = x − 1 ( y ⋅ x = x ! ∧ x > 0 ) ( y = ( x − 2 ) ! ∧ x ≠ 1 ∧ x > 0 ) x = x − 1 ( y ⋅ x = x ! ∧ x > 0 ) i ( y ⋅ x = x ! ∧ x > 0 ) y = y ∗ x ( y = x ! ∧ x > 0 ) ( y = ( x − 2 ) ! ∧ x ≠ 1 ∧ x > 0 ) x = x − 1 ; y = y ∗ x ( y = x ! ∧ x > 0 ) c ( y = ( x − 2 ) ! ∧ x > 0 ) while (x!=1)do{x=x-1;y=y*x} ( y = z ! ∧ z = x ∧ x > 0 ) w ( y = 1 ∧ x = n ) while(x!=1)do{x=x-1;y=y*x} ( y = n ! ∧ n > 0 ) ( x = n ) y = 1 ( y = 1 , x = n ) i ( x = n ) y=1,while (x!=1) do {x=x-1;y=y*x} ( y = n ! ∧ n > 0 ) c \dfrac{\dfrac{\dfrac{\dfrac{\dfrac{(y·(x-1)=(x-1)!\wedge x>0)x=x-1(y·x=x!\wedge x>0)}{(y=(x-2)!\wedge x\neq 1\wedge x>0)x=x-1(y·x=x!\wedge x>0)}i\qquad (y·x=x!\wedge x>0)y=y*x(y=x!\wedge x>0)}{(y=(x-2)!\wedge x\neq 1\wedge x>0)x=x-1;y=y*x(y=x!\wedge x>0)}c}{(y=(x-2)!\wedge x>0)\text{while (x!=1)do\{x=x-1;y=y*x\}}(y=z!\wedge z=x\wedge x>0)}w}{(y=1\wedge x=n)\text{while(x!=1)do\{x=x-1;y=y*x\}}(y=n!\wedge n>0)\qquad (x=n)y=1(y=1,x=n)}i}{(x=n)\text{y=1,while (x!=1) do \{x=x-1;y=y*x\}}(y=n!\wedge n>0)}c (x=n)y=1,while (x!=1) do {x=x-1;y=y*x}(y=n!∧n>0)(y=1∧x=n)while(x!=1)do{x=x-1;y=y*x}(y=n!∧n>0)(x=n)y=1(y=1,x=n)(y=(x−2)!∧x>0)while (x!=1)do{x=x-1;y=y*x}(y=z!∧z=x∧x>0)(y=(x−2)!∧x=1∧x>0)x=x−1;y=y∗x(y=x!∧x>0)(y=(x−2)!∧x=1∧x>0)x=x−1(y⋅x=x!∧x>0)(y⋅(x−1)=(x−1)!∧x>0)x=x−1(y⋅x=x!∧x>0)i(y⋅x=x!∧x>0)y=y∗x(y=x!∧x>0)cwic
( y ⋅ ( x − 1 ) ! = n ! ∧ x > 0 ) x = x − 1 ( y ⋅ x ! = n ! ∧ x > 0 ) ( y ⋅ x ! = n ! ∧ x > 0 ) y = y ∗ x ( y ⋅ ( x − 1 ) ! = n ! ∧ x > 0 ) ( y ⋅ x ! = n ! ∧ x > 0 ) x = x − 1 ; y = y ∗ x ( y ⋅ x ! = n ! ∧ x > 0 ) c ( y ⋅ x ! = n ! ∧ x > 0 ∧ x ≠ 1 ) x = x − 1 ; y = y ∗ x ( y ⋅ x ! = n ! ∧ x > 0 ) i ( y ⋅ x ! = n ! ∧ x > 0 ) w h i l e ( x ≠ 1 ) { x = x − 1 ; y = y ∗ x } ( y ⋅ x ! = n ! ∧ x = 1 ∧ x > 0 ) w ( y ⋅ x ! = n ! ∧ x > 0 ) w h i l e ( x ≠ 1 ) { x = x − 1 ; y = y ∗ x } ( y ⋅ x ! = n ! ∧ x > 0 ) ( x ! = n ! ) y = 1 ( y ⋅ x ! = n ! ∧ x > 0 ) i ( x ! = n ! ) y = 1 ; w h i l e ( x ≠ 1 ) { x = x − 1 ; y = y ∗ x } ( y ⋅ x ! = n ! ∧ x > 0 ) } c ( x = n ) y = 1 ; w h i l e ( x ≠ 1 ) { x = x − 1 ; y = y ∗ x } ( y ⋅ x ! = n ! ∧ n > 0 ) } \dfrac{\dfrac{\dfrac{\dfrac{\dfrac{\dfrac{(y·(x-1)!=n!\wedge x>0)x=x-1(y·x!=n!\wedge x>0)\qquad (y·x!=n!\wedge x>0)y=y*x(y·(x-1)!=n!\wedge x>0)}{(y·x!=n!\wedge x>0)x=x-1;y=y*x(y·x!=n!\wedge x>0)}c}{(y·x!=n!\wedge x>0\wedge x\neq 1)x=x-1;y=y*x(y·x!=n!\wedge x>0)}i}{(y·x!=n!\wedge x>0)while(x\neq 1)\{x=x-1;y=y*x\}(y·x!=n!\wedge x=1\wedge x>0)}w}{(y·x!=n!\wedge x>0)while(x\neq 1)\{x=x-1;y=y*x\}(y·x!=n!\wedge x>0) \qquad(x!=n!)y=1(y·x!=n!\wedge x>0) }i}{(x!=n!)y=1;while(x\neq 1)\{x=x-1;y=y*x\}(y·x!=n!\wedge x>0)\}}c}{(x=n)y=1;while(x\neq 1)\{x=x-1;y=y*x\}(y·x!=n!\wedge n>0)\}} (x=n)y=1;while(x=1){x=x−1;y=y∗x}(y⋅x!=n!∧n>0)}(x!=n!)y=1;while(x=1){x=x−1;y=y∗x}(y⋅x!=n!∧x>0)}(y⋅x!=n!∧x>0)while(x=1){x=x−1;y=y∗x}(y⋅x!=n!∧x>0)(x!=n!)y=1(y⋅x!=n!∧x>0)(y⋅x!=n!∧x>0)while(x=1){x=x−1;y=y∗x}(y⋅x!=n!∧x=1∧x>0)(y⋅x!=n!∧x>0∧x=1)x=x−1;y=y∗x(y⋅x!=n!∧x>0)(y⋅x!=n!∧x>0)x=x−1;y=y∗x(y⋅x!=n!∧x>0)(y⋅(x−1)!=n!∧x>0)x=x−1(y⋅x!=n!∧x>0)(y⋅x!=n!∧x>0)y=y∗x(y⋅(x−1)!=n!∧x>0)ciwic
优点
- 能够证明程序的正确性
- 具有一般Logic的特点,包括可靠性和完备性等
- 直观
缺点
- 手工证明
- 高代价
- 不能处理很多程序特征,例如指针等类型