Projet Module INE22 Corrigé Chantal Keller 20 mai 2010 1 Première partie : mise en jambes Question 1 Une seule remarque concernant la question 5 : après intros A H; apply H., il faut choisir entre les tactiques left et right. Si on fait left, le but n'est pas prouvable. 2 Deuxième partie : types énumérés en Coq Question 7 La propriété s'énonce ainsi : forall pl1 pl2 pl3 pl4, comp (comp pl1 pl2 pl3) pl4 pl3 = comp pl1 (comp pl2 pl4 pl3) pl3 Question 8 Le prédicat peut se dénir par une analyse de cas exhaustive : Definition au_moins_deux_et (pl1 pl2 pl3: pl) : Prop := match pl1, pl2, pl3 with | ou, ou, ou => False | ou, ou, et => False | ou, et, ou => False | ou, et, et => True | et, ou, ou => False | et, ou, et => True | et, et, ou => True | et, et, et => True end. Question 9 La propriété s'énonce ainsi : forall pl1 pl2 pl3, comp pl1 pl2 pl3 = et <-> au_moins_deux_et pl1 pl2 pl3 Question 10 On a deux signaux possible, valant 0 ou 1 : Inductive signal : Type := | zero : signal | un : signal. Question 11 L'application implante les tables de vérité : 1 Definition app (pl1: match pl1 with | ou => match s1 | zero | _ => end | et => match s1 | zero | _ => end end. Question 13 pl) (s1 s2: signal) : signal := with => s2 un with => zero s2 La commutativité de app s'énonce ainsi : forall pl1 s1 s2, app pl1 s1 s2 = app pl1 s2 s1 Question 15 L'égalité extensionelle entre deux fonctions est l'égalité sur tous les arguments possibles. Ici, cela se traduit par : Definition feq (pl1 pl2: pl) : Prop := forall s1 s2, app pl1 s1 s2 = app pl2 s1 s2. Question 16 La propriété s'énonce ainsi : forall pl1 pl2, feq pl1 pl2 <-> pl1 = pl2 3 Troisième partie : spécication de programmes en Why 3.1 Division euclidienne Question 18 L'Algorithme 1 décrit l'algorithme de division euclidienne en pseudo-code. Algorithme 1 Division euclidienne Entrées: deux entiers a > 0 et b > 0 Sorties: un couple d'entiers (q, r) tel que q > 0, 0 6 r < b, et a = bq + r si a < b alors return (0, a) sinon q←0 r←a tantque r > b faire q ←q+1 r ←r−b n tantque return (q, r) nsi 2 Question 19 Cet algorithme termine car r décroît strictement à chaque itération de la boucle, et est positif ou nul. Question 20 La spécication que l'on souhaite pour l'algorithme est que le couple d'entiers (q, r) renvoyé vérie les trois propriétés suivantes : 1. q > 0 2. 0 6 r < b 3. a = b ∗ q + r L'algorithme est divisé en deux branches : 1. Si a < b, on renvoie (0, a), qui vérie bien les propriétés voulues. 2. Sinon, on observe l'invariant suivant sur la boucle tantque : (a) a = bq + r (b) r > 0 (c) q > 0 qui assure bien la spécication de notre programme (r < b est assuré par le fait que l'on est sorti de la boucle). Montrons cet invariant : Il est vrai en début de boucle car q = 0 et r = a. Montrons qu'il est vrai après chaque itération de la boucle. On suppose que l'on a a = bq + r, r > 0 et q > 0 par récurrence, et r > b car on est dans la boucle. On pose q 0 = q + 1 et r0 = r − b, et on souhaite vérier que la propriété est vraie pour q 0 et r0 . On a : bq 0 + r0 = b(q + 1) + r − b = bq + r De plus, comme r > b, r0 > 0. Enn, comme q > 0, q 0 également. On a donc bien montré la spécication de l'algorithme. Question 21 L'algorithme récursif se déduit très simplement de l'algorithme itératif, et a les mêmes spécications. 3.2 Algorithme d'Euclide Question 24 L'Algorithme 2 décrit l'algorithme d'Euclide en pseudo-code. Question 25 Cet algorithme termine car r décroît strictement à chaque itération de la boucle, et est positif ou nul. Question 26 Montrons l'invariant proposé. Montrons qu'il est vrai à l'entrée de la boucle. On a c = a et d = b, donc 0 < d 6 c. De plus, comme r = c mod d, 0 6 r < d par l'axiome 2. Enn, par l'axiome 1, c = d × quo(c, d) + r. Soit n ∈ Z tel que n > 0, d mod n = 0 et r mod n = 0. Comme d = b, b mod n = 0. De plus, comme c = d × quo(c, d) + r et c = a, par les axiomes 3 et 4, on en déduit a mod n = 0. 3 Algorithme 2 Algorithme d'Euclide Entrées: deux entiers a et b tels que 0 < b 6 a Sorties: un entier n > 0 qui divise a et b r ← a mod b si r = 0 alors return b sinon c←a d←b tantque r > 0 faire c←d d←r r ← c mod d n tantque return d nsi Montrons qu'il est vrai à chaque itération de la boucle. Récursivement, on suppose que 0 6 r < d, 0 < d 6 c et ∀n ∈ Z, si n > 0 et si d mod n = 0 et r mod n = 0 alors a mod n = 0 et b mod n = 0. On suppose également que r > 0, car on est entré dans la boucle. On pose c0 = d, d0 = r, et r0 = c0 mod d0 = d mod r. Montrons les propriétés pour c0 , d0 et r0 . Comme r0 = c0 mod d0 , par l'axiome 2, 0 6 r0 < d0 . Comme d0 = r et r > 0, d0 > 0. De plus, comme r < d et c0 = d, d0 < c0 (donc d0 6 c0 ). Enn, soit n > 0 tel que d0 mod n = 0 et r0 mod n = 0. Comme d0 = r, on en déduit que r mod n = 0. De plus, comme r0 = d mod r, on déduit de l'axiome 1 que d = r × quo(d, r) + r0 . Les axiomes 3 et 4 assurent alors que d mod n = 0. Par la propriété de récurrence appliquée à n, on en déduit que a mod n = 0 et b mod n = 0. On a donc montré l'invariant de boucle. Question 27 La spécication que l'on souhaite de cet algorithme est que l'entier n qu'il renvoie est strictement positif et divise a et b. L'algorithme est composé de deux branches : 1. Si a mod b = 0, on renvoie b. b > 0 par hypothèse, il divise bien a, et il divise bien b par l'axiome 6. 2. Sinon, l'invariant de boucle nous assure que pour tout n > 0 qui divise d et r, il divise a et b. Or d divise d par l'axiome 6, et d divise r car, en sortie de boucle, r = 0 et par l'axiome 5. Donc on en déduit que d divise a et d divise b. 4 Quatrième partie : spécication d'un programme en Coq Question 30 Il sut de suivre la dénition par récurrence : Inductive fib : nat -> nat -> Prop := | fib0 : fib 0 1 | fib1 : fib 1 1 4 | fibrec : forall n m p, fib n m -> fib (S n) p -> fib (S (S n)) (m+p). Question 31 Ici, il faut se rappeler le cours sur la preuve de pair n -> exists m, n = double m. Dans ce cours, je vous ai montré que la preuve était beaucoup plus simple par induction sur pair n que par induction sur n. C'est pareil ici : la preuve est beaucoup plus simple par induction sur fib n m que par induction sur n ou m ! Question 32 C'est l'algorithme usuel : Fixpoint fibo1 (n: nat) : nat := match n with | O => 1 | S p => match p with | O => 1 | S q => fibo1 q + fibo1 p end end. Question 33 Comme suggéré dans l'énoncé, il faut faire une récurrence sur deux rangs. Question 34 C'est l'algorithme linéaire usuel, en utilisant la syntaxe pour les couples : Fixpoint fibo2 (n: nat) : nat*nat := match n with | O => (1,1) | S n => let (a,b) := fibo2 n in (b,a+b) end. Question 35 L'énoncé du lemme est tel que cette fois, une récurrence usuelle sut. 5