Jean-Marc Talbot et Emmanuel Beffara
9 ou 16 avril 2019
\[ \color{red} \text{correction} = \text{correction partielle} + \text{terminaison} \]
« Correct au regard de ce qu’on attend de lui » ? Spécification : propriété des sorties de l’algorithme
Exemple: la sortie est le quotient de \(a\) par \(b\)
La propriété désirée/spécification porte :
Ces valeurs à cet endroit dépendent :
État: associer à chaque variable une valeur ou non-défini “\(\_\)”
\[ (a \mapsto 17, b \mapsto 3, \text{résultat} \mapsto \_ ) \]
Spécification = propriété de l’état atteint à la fin (du déroulement) de l’algorithme
Inst
, son exécution depuis un état \(e\) mène à l’état \(\texttt{Inst}(e)\).Tester une condition change le flot de contrôle mais ne change pas l’état (des variables).
Propriété d’un état :
x, y, z, a, b
Les propriétés sont décrites / données par des assertions définies:
\[ A : (x > y \ \wedge y \ge y_0) \vee (z>0) \]
Pour une assertion \(A\), \(A(e)\) signifie que \(A\) est vraie pour l’état \(e\).
Si \(y_0 = 0\), alors
Soit Inst
une instruction (ou un bloc d’instructions), {Pre} et {Post} deux assertions
\[ \{Pre\} \texttt{Inst} \{Post\} \qquad \begin{tikzpicture}[baseline=(current bounding box.east),->,>=stealth'] \node (A) {\{Pre\}} ; \node[state, below of=A] (B) {\tt Inst}; \node[below of=B] (C) {\{Post\}} ; \path (A) edge[->] (B); \path (B) edge[->] (C); \end{tikzpicture} \]
Pour tous les états \(e\) satisfaisant l’assertion {Pre}, après l’exécution de Inst
, si celle-ci termine, \(\texttt{Inst}(e)\) satisfait l’assertion {Post}.
{Pre} est la pré-condition, {Post} est la post-condition
En généralisant à un bloc d’instruction BInst
,
Algo
entrées : x1,..., xn
sortie : y
début
BInst;
fin
Algo
Si Pre(x1,...,xn
) et que l’exécution de BInst
termine pour x1,...,xn
alors Post(y
).
L’algorithme est correct sous la pré-condition Pre(x1,...,xn
), si celui-ci termine et si Post(y
) est (ou implique) la spécification de Algo
.
\(\{x \ge 0\}\) x = x+1
\(\{x > 0\}\)
\(\{x \ge 0\}\) x = x+1
\(\{x \ge 0\}\)
\(\{x \ge 0\}\) x = x+1
\(\{x \text{~est un entier}\}\)
Noter que: \(\{x > 0\}\) implique que \(\{x \ge 0\}\) implique que \(\{x \text{~est un entier}\}\)
\(A\) implique \(B\): tout état qui satisfait \(A\) satisfait aussi \(B\).
\(\{x \ge 0 \text{~et~} y > 0 \}\) x = x+1
\(\{x > 0 \text{~et~} y > 0 \}\)
On n’a pas \(\{x \ge 0 \text{~et~} y > x \}\) x = x+1
\(\{x > 0 \text{~et~} y > x \}\)
Mais \(\{x \ge 0 \text{~et~} y > x \}\) x = x+1
\(\{x > 0 \text{~et~} y \ge x \}\)
\(\{x \ge 0 \text{~et~} y \ge x \}\) x = x+1
\(\{x > 0 \text{~et~} y \ge x-1 \}\)
De manière générale,
\(\{A\}\) x = expression
\(\{B\}\)
si \(\{A\}\) implique \(\{B[x \leftarrow expression]\}\)
Note: \(\{B[x \leftarrow expression]\}\) est \(\{B\}\) dans lequel tous les \(x\) ont été remplacés par \(expression\)
Exemple: \(\{x \ge 0 \text{~et~} y > x \} \texttt{ x = x+1 } \{x > 0 \text{~et~} y \ge x \}\)
car \(\{x > 0 \text{~et~} y \ge x \}[x \leftarrow x+1] = \{x+1 > 0 \text{~et~} y \ge x+1\}\)
qui est équivalent à (et donc, impliqué par) \(\{x \ge 0 \text{~et~} y > x \}\)
Une pré-condition calculée possible pour le bloc est alors \(\{2(x+1) = y+2\}\),
qui est équivalent et donc impliqué par \(\{2x = y\}\).
\[ \text{\{Pre\} } \ \texttt{si (cond) alors Inst1 sinon Inst2 finsi} \ \text{\{Post\}} \]
La valeur absolue est un entier positif
si (x>=0) alors
abs = x
sinon
abs = -x
finsi
OK car \(\{abs > 0\}\) implique \(\{abs \ge 0\}\)
Un invariant de boucle
tant que (condition) faire
BInst
fintantque;
est une assertion \(A\) telle que pour tout état \(e\) à l’entrée de la boucle,
si \(A(e) \wedge \texttt{condition}(e)\) est vraie et \(\texttt{BInst}(e)\) termine alors \(A(\texttt{BInst}(e))\)
Considérons une boucle dont la condition est (condition)
et \(A\) un invariant de cette boucle.
Si \(A\) est vraie avant l’exécution de la boucle alors l’assertion \(A\land \lnot(\texttt{condition})\) est vraie après l’exécution de la boucle.
Montrons tout d’abord par récurrence sur \(n \ge 0\), que si pour l’état \(e_0\) à l’entrée de la boucle, on a \(A(e_0)\) alors pour tout état \(e_n\) obtenu après \(n\) itérations de la boucle, on a \(A(e_n)\) :
Lorsque la boucle termine (après un certain nombre \(m\) d’itérations) dans un état \(e\), on a alors \(A(e) \wedge \neg \texttt{condition(e)}\).
Graphiquement,
Le but est d’annoter le graphe de flot de contrôle avec des assertions, vraies pour tous les états qui y peuvent apparaitre dans une exécution et cela, pour n’importe quelles entrées. L’assertion finale devra impliquer la spécification souhaitée.
Comment garantir la correction partielle d’un algorithme ?