T2-2 · 内存与断言

断言常见形式和分离合取的常用性质

从前面的例子中已经可以看到,QCP的断言语言中可以使用逻辑连接词&&与*,前者表示通常意义上的“且”,而后者是分离合取,具体而言,“P * Q”表示当前内存可以分为互不相交的两部分,其中一部分满足P另一部分满足Q。我们可以用这些逻辑连接词将多个子句连接起来,从而表述一些复杂的概念。

从前面的例子中已经可以看到,QCP的断言语言中可以使用逻辑连接词&&*,前者表示通常意义上的“且”,而后者是分离合取,具体而言,“P * Q”表示当前内存可以分为互不相交的两部分,其中一部分满足P另一部分满足Q。我们可以用这些逻辑连接词将多个子句连接起来,从而表述一些复杂的概念。

假如p是一个逻辑变量,它的值是一个内存地址,那么

exists v, v >= 0 && store_int(p, v)

就表示地址p上存储了一个非负数。

假如pq都是逻辑变量,它们的值都是内存地址,那么

exists v, store_int(p, v) * store_int(q, v)

就表示pq是不同的地址,但是两个地址上存储了一个相同的数。

当然,我们也可以写出更复杂一些的断言:

exists v, store_int(p, v) * store_int(q, v)

这就表示就表示pq是不同的地址,但是两个地址上存储了一个相同的非负数。

前面已经介绍,分离合取(“*”)具有交换律与结合律,换言之

P * Q       <----> Q * P
P * (Q * R) <----> (P * Q) * R

它还有以下两条重要性质:

  • &&*的结合律:如果P是一个与内存无关的命题(如大小比较v >= 0等),那么(P && Q) * R <----> P && (Q ** R)。这个等价式的左边说的是内存空间可以分为两部分,其中之一满足P && Q而另一个满足R。由于P是一个与内存无关的命题,因此这也就相当于说P成立,并且内存可以分为两部分,分别满足QR,这也就是等价式右边所描述的性质。 由于此性质的原因,当&&连接的P是与内存无关的式子时,P && Q * R这样的式子可以不加括号说明&&*之间的结合顺序。

  • exists*的结合律:(exists x, P(x)) * Q <----> exists x, (P(x) * Q)。由于此性质的原因,我们总是可以把分离合取子句中的exists提到最外侧。