I want to create a program which has the following prerequisites: invariant:
y = x ∗ x ∧ z = y ∗ x ∧ x ≤ n
variant:
n − x
Program structure is as follows:
while<cond>
<invariant specification>
<body>
How the program should looks like written in frama-c or why3?
EDIT: I modified your program by removing multiplication and adding addition instead. By doing this, I used two loops. I ran my program, but I got warnings. Here is the program:
#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;
}
}
And thoose are the warnings:
[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.
Can you explain me why I got those nasty warnings even if I specified the invariant and the variant for inner loop?
It is quite unclear what you want to achieve, but here is a C program that can be proved with frama-c -wp loop.c
and has the appropriate invariant and variant:
/*@ 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;
}
}
NB: the requires
is not the most general one one can write to avoid an overflow while computing z
, but it is easier to compute 2^21
than taking the cubic root of 2^64-1
.