Corrig exercice 1 de feuille de TD2

publicité
M1 Info
UFR d’IEEA – USTL
AAC-TP
2008–2009
Correction Diviser pour Régner
Exercice 1 Recherche d’une valeur encadrée
//A4;
int m;
int g:=0;
int d:=n-1;
while (g <= d){
m:=(g+d)/2;
if (T[m] >= b) d:=m-1;
else if (T[m] <= a) g:=m+1;
else return true;
}
return false;
Preuve de correction partielle
Précondition et post-conditions
Pour prouver que l’algorithme est correct s’il termine, il faut d’abord déterminer les deux
post-conditions qui doivent être vérifiées si l’algorithme retourne true et s’il retourne false, et
établir une précondition que l’on peut déduire des données et des initialisations auxquelles on
procéde sur d et g.
1. Pour qu’il soit correct de retourner true il faut prouver qu’il existe bien un indice i tel que
a < T[i] < b, on défini donc :
Qt = ∃ i tq. a < T[i] < b
2. Pour qu’il soit correct de retourner false il faut prouver que toutes les cases du tableau
contiennent un entier soit supérieur ou égal à b, soit inférieur ou égale à a, on défini :
Qf = ∀ i ∈ 0..n-1, T[i] leq a ou T[i] geq b
3. on défini finalement la post condition globale de l’algorithme : Q = Qt ou Qf
Au début de l’algorithme on ne connaît que d et g, la précondition va dépendre de ces deux
variables. Tout ce que l’on sait, c’est que g=0 et d=n-1, c’est-à-dire que g est l’indice de la
première case du tableau et d l’indice de la dernière case. On définit la précondition :
P = g=0 et d=n-1
Invariant de boucle
Pour prouver qu’une boucle effectue bien le calcul souhaité, il faut trouver un invariant I :
une assertion qui reste vraie quelle que soit l’itération de la boucle considérée.
Ici la boucle se termine soit par le cas où on retourne true et il faut prouver que Qt est vraie,
soit par le cas oùn on retourne false et il faut alors prouver Qf . On essaie donc de s’inspirer de
Qt et Qf pour orienté notre recherche de I.
Les deux post-conditions portent sur la relation entre les/une case du tableau et a et b, on
étudie un peu l’algorithme pour voir si on sait dire quelque chose qui impliquerait a, b, g et d et
pourrait être déduit de la précondition P . Comme le tableau est trié, on déduit de l’algorithme
que au début de chaque itération on doit avoir (il faut encore le prouver !) : ∀ i < g, T[i] ≤
a et ∀ j > d, T[j] ≥ b, c’est ce qu’on prend pour invariant I.
1
Preuve partielle
//A4;
int m;
int g:=0;
int d:=n-1;
{P}
while (g <= d){
{I}
_
m:=(g+d)/2;
if (T[m] >= b) d:=m-1;
else if (T[m] <= a) g:=m+1;
else
{Qt}
return true;
|
|
|
|
|
|
_|
A
}
{Qf}
return false;
En suivant ce qui est indiqué dans le cours, on doit prouver plusieurs choses pour arriver à la
conclusion P Algorithme Q, c’est-à-dire que partant de P soit on trouve un indice qui marche,
soit on est certain qu’il n’y en a aucun.
Précondition → Invariant On doit commencer par vérifier : P et (g ≤ d)) ⇒ I.
Comme g et d sont respectivement la première et la dernière case du tableau, il n’y a aucune
case d’indice < g ou d’indice > d, donc l’invariant n’est pas faux : il est vrai.
Invariant → Qf On sort de la boucle lorsque g > d, mais l’invariant est (on le prouve juste
après) vrai. On doit déduire de tout celà que Qf est vraie, ie que I et (g > d) ⇒ Qf :
I = ∀ i < g, T[i] ≤ a et ∀ j > d, T[j] ≥ b
donc, si g > d ∀ i ∈ 0..n-1, T[i] ≤ a ou T[i] ≥ b, ce qui est exactement Qf .
Invariant → A → invariant On doit montrer que l’invariant de boucle reste vrai après avoir
executé le corps de la boucle (A) lorsque la condition d’arret du tant que n’est pas encore fausse.
Comme la partie A de l’algorithme a une structure conditionnelle on doit prouver trois choses :
g+d
1. {I et (g ≤ d) et (T[ g+d
2 ] ≥ b)} d ←
2 − 1 {I} : comme le tableau est trié par
]
≥ b) que ∀ i ≥ g+d
ordre croissant on peut déduire de (T[ g+d
2
2 , T[i] ≥ b, ainsi après
g+d
l’affectation d ← 2 − 1 on a ∀ i > d, T[i] ≥ b. La seconde moitié de I concernant g n’est
pas modifiée, donc I est toujours vraie.
g+d
g+d
2. {I et (g ≤ d) et (T[ g+d
2 ] < b) et (T[ 2 ] ≤ a)} g ←
2 +1 {I} : comme le tag+d
bleau est trié par ordre croissant on peut déduire de (T[ 2 ] ≤ a) que ∀ i ≤ g+d
2 , T[i]
g+d
≤ a, ainsi après l’affectation g ← 2 + 1 on a ∀ i < g, T[i] ≤ a. La seconde moitié de I
concernant d n’est pas modifiée, donc I est toujours vraie.
2
g+d
3. {I et (g ≤ d) et (T[ g+d
2 ] < b) et (T[ 2 ] > a)} ⇒ {Qt } : on déduit directement
g+d
g+d
g+d
Qt de (T[ 2 ] < b) et (T[ 2 ] > a) : 2 est un indice du tableau (on peut le prouver en
alourdissant encore l’invariant avec (0≥g) et (d≥n-1), la condition (g≤d) et les affectations
effectuées font le reste) qui marche.
Conclusion : en partant de P on arrive soit à Qt soit à Qf , donc s’il termine l’algorithme est
correct.
3
Téléchargement