Require Arith. (* 1. Quelques preliminaires, utiles pour la suite, mais ce n'est pas grave si vous ne comprenez pas les preuves. *) (* au_plus est une function qui retourne le booleen true si m<=n, false sinon. Il s'agit d'un programme, au contraire de la relation le, qui est un predicat (de type nat -> nat -> Prop). *) Fixpoint au_plus [m,n:nat] : bool := Cases m of O => true | (S m') => Cases n of O => false | (S n') => (au_plus m' n') end end. Lemma choix_bool : (b:bool) b=true \/ b=false. Proof. Induction b. Left . Reflexivity. Right . Reflexivity. Qed. Lemma au_plus_le_1 : (n,m:nat) (au_plus m n)=true -> (le m n). Proof. Induction n. Induction m. Intro. Apply le_n. Simpl. Intros. Discriminate H0. Induction m. Intro. Apply le_O_n. Simpl. Intros. Apply le_n_S. Apply H. Assumption. Qed. Lemma au_plus_le_2 : (n,m:nat) (le m n) -> (au_plus m n)=true. Proof. Induction n. Induction m. Trivial. Intros. Elim (le_Sn_O n0 H0). Induction m. Trivial. Intros. Simpl. Apply H. Apply le_S_n. Assumption. Qed. Lemma au_plus_le_3 : (n,m:nat) (au_plus m n)=false -> ~(le m n). Proof. Unfold not. Intros. Rewrite (au_plus_le_2 n m H0) in H. Discriminate H. Qed. Lemma au_plus_le_4 : (n,m:nat) ~(le m n) -> (au_plus m n)=false. Proof. Intros. Elim (choix_bool (au_plus m n)). Intro. Elim (H (au_plus_le_1 n m H0)). Trivial. Qed. Lemma au_plus_refl : (m:nat) (au_plus m m)=true. Proof. Induction m; Trivial. Qed. Lemma au_plus_trans : (m,n,k:nat) (au_plus m n)=true -> (au_plus n k)=true -> (au_plus m k)=true. Proof. Intros. Apply au_plus_le_2. (Apply (le_trans m n k); Apply au_plus_le_1; Assumption). Qed. Lemma au_plus_total : (m,n:nat) (au_plus m n)=false -> (au_plus n m)=true. Proof. Induction m. Induction n. Trivial. Intros. Elim (au_plus_le_3 ? ? H0 (le_O_n (S n0))). Induction n0. Trivial. Intros. Simpl. Apply H. Exact H1. Qed. (* De meme, egal est le programme calculant si les deux entiers en entree sont egaux ou non. *) Fixpoint egal [m,n:nat] : bool := Cases m n of O O => true | (S m') (S n') => (egal m' n') | _ _ => false end. Lemma egal_1 : (m,n:nat) (egal m n)=true -> m=n. Proof. Induction m. Induction n. Trivial. Intros. Simpl in H0. Discriminate H0. Induction n0. Simpl. Intro. Discriminate H0. Simpl. Intros. Cut n=n1. Intro. Rewrite H2. Reflexivity. Apply H. Assumption. Qed. Lemma egal_refl : (m:nat) (egal m m)=true. Proof. Induction m; Trivial. Qed. Lemma egal_imp_au_plus : (m,n:nat) (egal m n)=true -> (au_plus m n)=true. Proof. Intros. Rewrite (egal_1 m n H). Apply au_plus_refl. Qed. Lemma non_au_plus_imp_non_egal : (m,n:nat) (au_plus m n)=false -> (egal m n)=false. Proof. Intros. Elim (choix_bool (egal m n)). Intro. Rewrite (egal_imp_au_plus m n H0) in H. Discriminate H. Trivial. Qed. (* 2. Les listes d'entiers *) Inductive liste : Set := nil : liste | cons : nat -> liste -> liste. (* 3. Analyse des proprietes des listes triees *) Fixpoint minore [x:nat; l:liste] : Prop := (* un predicat disant si x est <= a tous les elements de la liste l. *) Cases l of nil => True | (cons m l') => (au_plus x m)=true /\ (minore x l') end. Fixpoint ordonnee [l : liste] : Prop := (* un predicat disant si l est une liste ordonnee, c'est-a-dire triee en ordre croissant. *) Cases l of nil => True | (cons n l') => (minore n l') /\ (ordonnee l') end. Lemma minore_ordonnee_1 : (l:liste) (m:nat) (ordonnee (cons m l)) -> (x:nat) (au_plus x m)=true -> (minore x l). Lemma minore_ordonnee_2 : (l:liste) (m:nat) (ordonnee (cons m l)) -> (x:nat) (au_plus x m)=true -> (minore x (cons m l)). Fixpoint insere [x:nat; l:liste] : liste := Cases l of nil => (cons x nil) | (cons m l') => if (au_plus x m) then (cons x l) else (cons m (insere x l')) end. Lemma minore_insere_1 : (l:liste) (x,m:nat) (au_plus m x)=true -> (minore m l) -> (minore m (insere x l)). Lemma insere_preserve_l_ordre : (l:liste) (ordonnee l) -> (x:nat) (ordonnee (insere x l)). (* 4. Analyse des nombres d'occurrences de valeurs dans les listes *) (* Le nombre d'occurrences de x dans l est le nombre de fois ou x apparait dans l. On dira que l et l' ont les memes elements si tout x apparait dans les deux exactement le meme nombre de fois. *) Fixpoint nombre_d_occurrences [x:nat; l:liste] : nat := Cases l of nil => O | (cons m l') => if (egal x m) then (S (nombre_d_occurrences x l')) else (nombre_d_occurrences x l') end. Lemma nocc_insere_1 : (l:liste) (x:nat) (nombre_d_occurrences x (insere x l))=(S (nombre_d_occurrences x l)). Lemma nocc_insere_2 : (l:liste) (x:nat) (m:nat) (egal x m)=false -> (nombre_d_occurrences x (insere m l))=(nombre_d_occurrences x l). Definition memes_elements := [l,l':liste] (x:nat) (nombre_d_occurrences x l)=(nombre_d_occurrences x l'). Lemma memes_elements_trans : (l,l',l'':liste) (memes_elements l l') -> (memes_elements l' l'') -> (memes_elements l l''). Lemma insere_preserve_les_elements_1 : (l:liste) (x:nat) (memes_elements (cons x l) (insere x l)). Lemma memes_elements_cons : (l,l':liste) (memes_elements l l') -> (x:nat) (memes_elements (cons x l) (cons x l')). Lemma insere_preserve_les_elements_2 : (l,l':liste) (memes_elements l l') -> (x:nat) (memes_elements (cons x l) (insere x l')). (* 5. Le tri par insertion *) (* La modelisation du tri (en fait, un vrai programme de tri, essayez Eval Compute in (tri (cons (3) (cons (1) (cons (2) nil)))). par exemple.) *) Fixpoint tri [l:liste] : liste := Cases l of nil => nil | (cons x l') => (insere x (tri l')) end. (* La specification du tri, en deux parties: (tri_ordonne) le resultat du tri sur toute liste l est une liste triee; (tri_preserve_les_elements) le resultat du tri sur toute liste l a les memes elements que l. *) Lemma tri_ordonne : (l:liste) (ordonnee (tri l)). Lemma tri_preserve_les_elements : (l:liste) (memes_elements l (tri l)). (* Exercice: prouvez les lemmes de ce fichier dont les preuves n'ont pas ete donnees. Le but est de prouver que l'implementation tri ci-dessus implemente la specification, a savoir que les lemmes tri_ordonne et tri_preserve_les_elements sont valides. On peut ensuite extraire une implementation prouvee du tri par les commandes: Require Extraction. Write Caml File "tri" [ tri ]. Consultez ensuite le fichier tri.ml. (On peut faire mieux, voir la doc en http://coq.inria.fr/.) *)