I tried to use Frama-c to prove the occurrence of true value in an array that is the same as a integer which used to record the number of true values. But the prove failed if I want to change some values false to true. Is there any method to solve this problem? (Frama-c 25.0 / Alt-Ergo 2.4.2 / CVC4 1.8 / Z3 4.8.6)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define SIZE 150
bool table[SIZE] = {true};
int true_counter;
/*@
logic integer count_true(integer idx) =
idx<=0 ? 0 :
(table[idx-1]==true ? count_true(idx-1) + 1 : count_true(idx-1));
*/
/*@
requires table[0] == false;
requires true_counter == count_true(SIZE);
assigns table[0], true_counter;
ensures table[0] == true;
ensures true_counter == \old(true_counter) + 1;
*/
void ATEST(void) {
int countBF = 0;
int countAF = 0;
/*@
loop invariant 0 <= idx <= SIZE;
loop invariant 0 <= countBF == count_true(idx) <= idx;
loop assigns idx, countBF;
loop variant SIZE - idx;
*/
for(int idx=0; idx<SIZE; idx++) {
if(table[idx] == true) countBF += 1;
}
//@ assert true_counter == countBF;
table[0] = true;
true_counter += 1;
/*@
loop invariant 0 <= idx <= SIZE;
loop invariant 0 <= countAF == count_true(idx) <= idx;
loop assigns idx, countAF;
loop variant SIZE - idx;
*/
for(int idx=0; idx<SIZE; idx++) {
if(table[idx] == true) countAF += 1;
}
//@ assert true_counter == countAF;
//@ assert countAF == countBF + 1;
}
[kernel] Parsing test.c (with preprocessing)
[rte:annot] annotating function ATEST
[wp] 33 goals scheduled
[wp] [Failed] Goal typed_ATEST_assert_2
Z3 4.8.6: Unknown (Qed:8ms) (cached)
CVC4 1.8: Timeout (Qed:8ms) (10s) (cached)
Alt-Ergo 2.4.2: Timeout (Qed:8ms) (10s) (cached)
[wp] [Cache] found:17
[wp] Proved goals: 32 / 33
Qed: 26 (0.84ms-7ms-24ms)
Alt-Ergo 2.4.2: 6 (7ms-13ms-27ms) (629) (interrupted: 1) (cached: 7)
CVC4 1.8: 4 (20ms-28ms-30ms) (11375) (interrupted: 1) (cached: 5)
Z3 4.8.6: 4 (10ms-20ms) (46252) (unknown: 1) (cached: 5)