J'ai quelques problèmes lorsque j'essaie d'utiliser les étiquettes logiques par défaut LoopEntry et LoopCurrent. Voici un exemple simple que les différents prouveurs (alt-ergo, coq, cvc3, z3) que j'utilise ne parviennent pas à prouver :
/*@ 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++;
}
}
En particulier, les première et deuxième invariants ne sont pas prouvés (pas de problème avec les autres). Maintenant, si je modifie cet exemple simple en ajoutant une étiquette "label" après la déclaration/définition de i et si je me réfère à cette étiquette, et change LoopCurrent par Ici (ce qui donne ce extrait :
/*@ 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++;
}
}
)
maintenant tout est prouvé.
J'ai trouvé la documentation sur les étiquettes logiques par défaut d'Acsl assez facile à comprendre et je m'attendais à ce que le premier exemple soit prouvé comme le second. Pourriez-vous expliquer d'où vient le problème ?
Roo
PS1 : à quoi se réfère Pre lorsqu'il est utilisé dans une clause de boucle ? L'état avant la première itération de la boucle ou l'itération précédente ?
PS2 : J'utilise Frama-C Fluorine, mais peut-être que je n'ai pas mis à jour pour chaque mise à jour mineure