当我尝试使用默认逻辑标签 LoopEntry 和 LoopCurrent 时,我遇到了一些麻烦。这是一个简单的示例,我使用的不同证明者(alt-ergo、coq、cvc3、z3)无法证明:
/*@ requires n > 0;*/
void f(int n){
int i = 0;
/*@ loop invariant \at(i,LoopEntry) == 0;
@ loop invariant \at(i,LoopCurrent) >= \at(i,LoopEntry);
@ loop invariant 0 <= i <= n;
@ loop assigns i;
@ loop variant n-i;
*/
while(i < n){
i++;
}
}
特别是,第一和第二不变量没有被证明(其他没有问题)。现在,如果我通过在 i 的声明/定义之后添加标签“label”来修改这个简单的示例,并且如果我引用该标签,并通过 Here 更改 LoopCurrent (这给出了这个片段:
/*@ requires n > 0;*/
void f(int n){
int i = 0;
label : ;
/*@ loop assigns i;
@ loop invariant \at(i,label) == 0;
@ loop invariant \at(i,Here) >= \at(i,label);
@ loop invariant 0 <= i <= n;
@ loop variant n-i;
*/
while(i < n){
i++;
}
}
)
现在一切都被证明了。
我发现有关 Acsl 默认逻辑标签的文档很容易理解,并且我希望第一个示例被证明为第二个示例。你能解释一下问题出在哪里吗?
袋鼠
PS1:在循环子句中使用 Pre 时指的是什么?第一次循环迭代或上一次迭代之前的状态??
PS2:我正在使用 Frama-C Fluorine,但也许我没有为每个小更新进行升级