我需要根据给定的规范构造并证明循环不变性:
{n > 0} P {q = | {j: a[j]=x and 0 <= j < n} |}
其中 | A | 是集合A的元素数量。这意味着 q 等于数组 a 等于 x 。
代码 P 指定为:
{
int i = 0, q = 0;
while (i != n){
if (a[i] == x)
q = q + 1;
i = i + 1;
}
我知道循环不变性必须为真:
但是我不知道如何找到正确的循环不变式,这将使我随后显示P的部分正确性。我已经尝试查看循环的每个迭代以及随机 n , x 和 a [0 ... n-1] 以查看在循环运行时组合的哪些值是恒定的,但没有帮助。
答案 0 :(得分:1)
仔细查看您的代码。刚开始时,q
为0,并且仅在找到== x
的新元素时才会增长。所以
q = | {j: a[j]=x and 0 <= j < i} |
是您不变式的一部分。请注意,在您的规范中,您使用的是< n
而不是< i
。还请注意,在循环终止时,i == n
。因此,一开始它也是有效的。两者之间的任何时候也都是如此:到目前为止,很好。还有其他东西吗?是的,我们也应该声明
0 <= i <= n
-因为它描述了i的值的范围(否则i
可以自由地在数组之外冒险)。
这就是全部吗?是的-没有其他循环状态可以描述。因此,您的完整不变式看起来像
q = | {j: a[j]=x and 0 <= j < i} | and 0 <= i <= n
解决这些练习时,您可以尝试以下两个步骤:
i
从0扫描到n-1,在n处停止,每时每刻,我将q
保持在{我在数组中找到的x
中的“”。必须提及循环中涉及的所有变量!。n
)来代替i
li>
作为思想实验,请尝试使用等效循环(但从末尾开始重复)来编写不变量:
{
int i = n-1, q = 0;
while (i >= 0){
if (a[i] == x)
q = q + 1;
i = i - 1;
}
将鼠标悬停以寻找答案(但请先找出答案)。
q = | {j: a[j]=x and i < j < n} | and -1 <= i < n
注意不同的限制,反映出i
的扫描范围不同; 但整体结构相同