在验证两个阵列添加期间超时

时间:2016-05-05 19:42:35

标签: c frama-c

我正在尝试验证添加两个2d数组,但无论我使用哪个求解器,我都会不断发出超时错误。

我要验证的代码如下:

typedef struct{
  float mem[3];
}BaseMatrix3x1;


/*@ requires \valid(b1) && \valid(b2);
  @ ensures A: \forall integer i; 0 <= i < 3 ==>
                b1->mem[i] == \old(b1)->mem[i] + b2->mem[i];
  @ assigns b1->mem[0..2];
@*/
void baseMatrixAssignAdd3x1(BaseMatrix3x1 *b1, BaseMatrix3x1 *b2){
    /*@ loop invariant 0 <= i <= 3;
      loop invariant \forall integer k; 
      0 <= k < i ==>
        \at(b1->mem[k], LoopCurrent) ==
            \at(b1->mem[k], LoopEntry) + \at(b2->mem[k], LoopEntry);
      loop assigns i, b1->mem[0..2];*/ 
    for(unsigned int i=0; i<3; i++){
        b1->mem[i] += b2->mem[i];
  }
}

第二个循环不变量是导致所有求解器超时的循环。

你有什么建议吗?

修改: 我修复了分配错误(虽然这不是问题)。

我还没有在某个地方调用此函数,我只是想证明循环不变量。根据我的理解,为了验证函数,我们不关心调用此函数的方式。我们只关心我们拥有的前后条件。

1 个答案:

答案 0 :(得分:4)

首先,代码中的错误/缺失:

  • 您从未提及b1b2是指向不同矩阵的指针。没有此信息,您的循环分配不正确,因为b2->mem[0..2]也会被分配。您需要添加requires \separated(b1, b2);假设
  • 你的后置条件不正确,因为\old仅适用于指针 b1(在函数中保持不变),而它应该适用于{{1} }。您应该改为编写b1->mem
  • 您错过了一个重要的循环不变量,即\old(b1->mem[i])尚未修改(尚未)。由于您的循环指定在每次迭代时都可以分配所有b1->mem[i..2],因此您需要在未更改的部分上添加不变量。

接下来,WP插件的一个明显限制是阻止完整的证明:

  • 对标签b1->mem的支持似乎不足。但是,在循环不变量中,LoopCurrent是默认标签。因此,您始终可以LoopCurrent替换\at(P, LoopCurrent)

以下是WP插件能够使用Alt-Ergo作为证明者证明的代码的完全注释版本。

P