簡體   English   中英

合成一個保留循環不變量和變量的循環程序

[英]Synthesize a loop program that preserves the loop invariant and variant

我想創建一個具有以下先決條件的程序:不變:

y = x ∗ x ∧ z = y ∗ x ∧ x ≤ n

變體:

n − x

程序結構如下:

while<cond>
   <invariant specification>
   <body>

程序應該如何看起來像用 frama-c 或why3 編寫的?

編輯:我通過刪除乘法並添加加法來修改您的程序。 通過這樣做,我使用了兩個循環。 我運行了我的程序,但我收到了警告。 這是程序:

#include <limits.h>

/*@ requires n < INT_MAX; // avoids overflow in computing z
*/
void f(unsigned long n) {
    unsigned long x = 0, y = 0, z = 0, contor, aux_x, aux_y;
    /*@ loop assigns x, y, z, contor, aux_x, aux_y;
      @ loop invariant y == x * x && z == y * x && x <= n;
      @ loop variant n - x;
      @ */
    while (x < n) {
        x++;
        contor = 1;
        aux_x = 0;
        aux_y = 0;
        /* @ loop assings contor, aux_x, aux_y;
           @ loop invariant 1 <= contor <= x;
           @ loop variant x - contor, x, y;
           @*/
        while (contor <= x) {
            aux_x += x;
            aux_y += y;
            contor++;
        }
        y = aux_x;
        z = aux_y;
    }
}

這些是警告:

[kernel] Parsing loop.c (with preprocessing)
[rte] annotating function f
[wp] loop.c:20: Warning: Missing assigns clause (assigns 'everything' instead)
[wp] 6 goals scheduled
[wp] [Alt-Ergo 2.4.1] Goal typed_f_loop_assigns_part2 : Timeout (Qed:6ms) (10s) (cached)
[wp] [Alt-Ergo 2.4.1] Goal typed_f_loop_variant_decrease : Timeout (Qed:16ms) (10s) (cached)
[wp] [Alt-Ergo 2.4.1] Goal typed_f_loop_invariant_established : Timeout (Qed:3ms) (10s)
[wp] [Alt-Ergo 2.4.1] Goal typed_f_loop_invariant_preserved : Timeout (Qed:11ms) (10s)
[wp] [Cache] found:2, updated:2
[wp] Proved goals:    2 / 6
  Qed:               2  (7ms)
  Alt-Ergo 2.4.1:    0  (interrupted: 4) (cached: 2)
[wp:pedantic-assigns] loop.c:5: Warning: 
  No 'assigns' specification for function 'f'.
  Callers assumptions might be imprecise.

你能解釋一下為什么即使我為內循環指定了不變量和變體,我也會收到那些討厭的警告嗎?

目前還不清楚你想要實現什么,但這里有一個 C 程序,可以用frama-c -wp loop.c證明,並具有適當的不變量和變體:

/*@ requires n < 2097152; // avoids overflow in computing z
 */
void f(unsigned long n) {
  unsigned long x = 0, y = 0, z = 0;
  /*@ loop invariant y == x * x && z == y * x && x <= n;
      loop assigns x,y,z;
      loop variant n - x;
  */
  while (x < n) {
    x++;
    y = x * x;
    z = y * x;
  }
}

注意: requires並不是在計算z時避免溢出的最通用的方法,但計算2^21比取2^64-1的三次根更容易。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM