Exercice 2 : Logique de Hoare et vérification
Problème : Vérification formelle d’algorithmes par la Logique de Hoare
Section titled “Problème : Vérification formelle d’algorithmes par la Logique de Hoare”Matière : Informatique - Filière MPI
Chapitre: Automates, langages et logique (Thème : Logique de Hoare et correction de programmes)*
Introduction et Objectifs
Section titled “Introduction et Objectifs”La logique de Hoare permet de prouver formellement la correction d’un programme impératif. Un triplet de Hoare est noté où est la précondition, une commande (programme) et la postcondition.
L’objectif de ce problème est d’étudier la correction partielle et totale d’algorithmes classiques, d’introduire formellement la notion d’invariant de boucle, et d’implémenter un vérificateur de conditions de verification en Python.
Partie I : Rappels et Règles de Base
Section titled “Partie I : Rappels et Règles de Base”Soit un langage impératif simple muni des constructions usuelles : affectation, séquence, conditionnelle et boucle while.
- Règle de l’affectation : où désigne la formule dans laquelle toute occurrence libre de la variable est remplacée par l’expression .
- Règle de la composition (séquence) :
- Règle de la boucle
while: où est l’invariant de la boucle.
Question 1 (Application directe)
Section titled “Question 1 (Application directe)”Appliquer la règle de l’affectation pour trouver la plus faible précondition telle que le triplet suivant soit valide :
Corrigé :
En appliquant la règle de l’affectation, on substitue par dans la postcondition :
Le triplet le plus général est donc .
Partie II : Étude d’un algorithme de calcul par additions successives
Section titled “Partie II : Étude d’un algorithme de calcul par additions successives”On considère le programme suivant, destiné à calculer le produit de deux entiers naturels et à l’aide d’additions itérées :
x := 0;y := 0;while y < b do x := x + a; y := y + 1;doneOn souhaite prouver le triplet de Hoare :
Question 2
Section titled “Question 2”Proposer un invariant pour la boucle while permettant de prouver la correction partielle de ce programme.
Corrigé :
À chaque tour de boucle, compte le nombre d’itérations effectuées et accumule la somme (soit ). L’invariant de boucle doit lier les variables du programme aux données d’entrée tout en restant stable. On choisit :
Question 3
Section titled “Question 3”Démontrer que l’invariant est vérifié avant l’entrée dans la boucle, qu’il est inductif (préservé par le corps de la boucle), et qu’à la sortie de la boucle, il garantit la postcondition.
Corrigé :
-
Initialisation (avant la boucle) :
Juste après les affectations et , et en supposant la précondition :- (car )
L’invariant est donc vrai initialement.
-
Conservation (Induction) :
On suppose vrai avant le corps de la boucle, avec .
Montrons que est valide.
En appliquant la règle de l’affectation à rebours sur puis :- Postcondition :
- Ce qui donne : .
Or, l’hypothèse de boucle nous assure que et . - .
- .
L’invariant est donc préservé.
-
Terminaison et Postcondition :
À la sortie de la boucle, on a , c’est-à-dire : Puisque et , on en déduit .
En remplaçant dans la seconde partie de l’invariant, on obtient , ce qui correspond exactement à la postcondition .
Partie III : Vérification Automatisée (Implémentation Python)
Section titled “Partie III : Vérification Automatisée (Implémentation Python)”Pour s’assurer de la correction, on souhaite écrire un petit vérificateur en Python qui manipule des expressions logiques sous forme d’arbres de syntaxe abstraite (AST).
Question 4
Section titled “Question 4”Écrire une fonction Python substitution(expr, var, val) qui remplace une variable par une expression dans une chaîne représentant une condition (simplifiée à des comparaisons arithmétiques basiques).
Corrigé :
def substitution(expr: str, var: str, val: str) -> str: """Remplace la variable 'var' par 'val' dans la chaîne 'expr'.
Implémentation naïve par remplacement de sous-chaînes (adaptée pour l'-AST textuel). """ # En pratique, on utiliserait un parser d'expression pour un vrai compilateur. # Ici, on simule la substitution syntaxique. return expr.replace(var, f"({val})")
# Exemple de test :# print(substitution("x > 5", "x", "x + 1"))# Affiche: "(x + 1) > 5"Analyse Critique des Résultats
Section titled “Analyse Critique des Résultats”-
Limites de la logique de Hoare classique :
La méthode présentée ici prouve la correction partielle (si le programme termine, alors le résultat est correct). Pour prouver la correction totale, il est indispensable d’associer à chaque boucle une fonction de variant (ou fonction de termination) à valeurs dans un ensemble bien fondé (par exemple muni de l’ordre usuel) qui décroît strictement à chaque itération. -
Complexité de la vérification :
L’écriture d’invariants de boucle non triviaux ne peut pas être entièrement automatisée (conséquence du théorème de Rice et de l’indécidabilité générale de l’arrêt). Les vérificateurs de programmes modernes (comme Frama-C ou Why3) reposent sur l’aide interactive de l’utilisateur (fourniture d’invariants) et délouent les conditions de vérification (VCs) à des solveurs SMT (Z3, CVC4).