Projet Coq
Vous pouvez lire ce document dans sa version HTML mais l'idéal est de le compiler
au fur et à mesure pour lire les messages renvoyés par Coq.
Lien vers la page du projet:
http://www.lsv.ens-cachan.fr/~hirschi/enseignements/projet_coq/projet_coq.php
Ce projet est constitué de deux parties pratiquement indépendantes. La première
section est assez facile mais demande d'écrire pas mal de preuves.
La seconde section demande plus de réflexion. Essayez de l'aborder en TP pour que
je puisse vous aider.
Et, s'il vous plait, ne copiez pas les uns sur les autres: ça se verra (trop) facilement (il y a beaucoup
de façon d'aborder une preuve).
L'axiomatisation de base de Coq ne permet que de prouver des preuves en logique
intuitioniste (et non classique). La conséquence (voulue) est que toutes les preuves
sont constructives (i.e., à chaque preuve correspond un terme calculant une fonction
totale du type de la proposition prouvée).
Si l'on veut travailler dans une logique classique, on doit alors déclarer un
"axiome classique" dans Coq. On peut ajouter le raisonnement par l'absurde, ou ajouter
la loi de Peirce par exemple. L'objectif de la première partie du projet est de montrer
que les logiques induites par cinq axiomes différents ont la même expressivité.
Definition peirce := forall P Q:Prop, ((P->Q)->P)->P.
Definition classic := forall P:Prop, ~~ P -> P.
Definition excluded_middle := forall P:Prop, P \/ ~P.
Definition de_morgan_not_and_not := forall P Q:Prop, ~(~P/\~Q)->P\/Q.
Definition implies_to_or := forall P Q:Prop, (P->Q)->(~P\/Q).
Prouvez que les logiques induites par ces propriétés ont la même
expressivité. Le plus simple est de choisir un ordre (par exemple
classic => peirce => implies_to_or => ... => classic) et prouvez une série de lemmes de la forme:
Lemma peirce_classic : forall P, (classic -> P) -> (peirce -> P).
Je choisis l'ordre de définition.
Lemma ax_peirce_classic : peirce -> classic.
unfold peirce; unfold classic.
intros H P.
intro NNP.
apply (H (P) False).
intros NP.
apply False_ind.
apply NNP.
unfold not.
apply NP.
Qed.
unfold peirce; unfold classic.
intros H P.
intro NNP.
apply (H (P) False).
intros NP.
apply False_ind.
apply NNP.
unfold not.
apply NP.
Qed.
J'écris une fois le lemme qui prouve qu'on obtient la même
expressivité et ensuite je ne prouve que les lemmes
qui prouvent que les 5 axiomes s'impliquent mutuellement.
Lemma peirce_classic : forall P, (classic -> P) -> (peirce -> P).
intros P HP C.
apply HP.
apply ax_peirce_classic;auto.
Qed.
Lemma ax_peirce_emd : peirce -> excluded_middle.
intro PE.
unfold excluded_middle. intros P.
unfold peirce in *.
apply (PE (P\/~P) False).
intro PONP.
right. intro.
apply PONP.
left.
auto.
Qed.
Lemma emd_morgan : excluded_middle -> de_morgan_not_and_not.
intro.
unfold excluded_middle in *.
unfold de_morgan_not_and_not in *.
intros P Q NNPQ.
destruct (H (P\/ Q)); auto.
apply False_ind.
apply NNPQ.
split;intro; apply H0;tauto.
intros P HP C.
apply HP.
apply ax_peirce_classic;auto.
Qed.
Lemma ax_peirce_emd : peirce -> excluded_middle.
intro PE.
unfold excluded_middle. intros P.
unfold peirce in *.
apply (PE (P\/~P) False).
intro PONP.
right. intro.
apply PONP.
left.
auto.
Qed.
Lemma emd_morgan : excluded_middle -> de_morgan_not_and_not.
intro.
unfold excluded_middle in *.
unfold de_morgan_not_and_not in *.
intros P Q NNPQ.
destruct (H (P\/ Q)); auto.
apply False_ind.
apply NNPQ.
split;intro; apply H0;tauto.
joli ;)
Qed.
Lemma morgan_imp : de_morgan_not_and_not -> implies_to_or.
unfold de_morgan_not_and_not in *.
unfold implies_to_or in *.
intros MOR P Q PIQ.
apply MOR.
intro.
destruct H.
apply H.
intro.
tauto.
Qed.
Lemma imp_peirce : implies_to_or -> peirce.
unfold implies_to_or.
unfold peirce.
intros IMP P Q H.
destruct (IMP P P);tauto.
Qed.
Lemma morgan_imp : de_morgan_not_and_not -> implies_to_or.
unfold de_morgan_not_and_not in *.
unfold implies_to_or in *.
intros MOR P Q PIQ.
apply MOR.
intro.
destruct H.
apply H.
intro.
tauto.
Qed.
Lemma imp_peirce : implies_to_or -> peirce.
unfold implies_to_or.
unfold peirce.
intros IMP P Q H.
destruct (IMP P P);tauto.
Qed.
Prouvez la dualité classique entre exists et forall.
Theorem forallExists : forall A, forall P : A -> Prop,
peirce -> (~ (forall x : A, P x) <-> (exists x : A, ~ P x)).
intros A P CL; split; intro H.
assert ((~(exists x:A, ~P x) -> (exists x:A, ~P x)) -> (exists x:A, ~P x)).
apply CL.
apply H0.
intro NE.
apply False_ind.
apply H.
intro x.
assert (((~P x) -> (P x)) -> P x).
apply CL.
apply H1; intro NP.
apply False_ind.
apply NE.
exists x; auto.
intro F.
destruct H.
apply H.
apply F.
Qed.
peirce -> (~ (forall x : A, P x) <-> (exists x : A, ~ P x)).
intros A P CL; split; intro H.
assert ((~(exists x:A, ~P x) -> (exists x:A, ~P x)) -> (exists x:A, ~P x)).
apply CL.
apply H0.
intro NE.
apply False_ind.
apply H.
intro x.
assert (((~P x) -> (P x)) -> P x).
apply CL.
apply H1; intro NP.
apply False_ind.
apply NE.
exists x; auto.
intro F.
destruct H.
apply H.
apply F.
Qed.
Et le symétrique? As-t-on besoin de la logique classique?
Theorem existsForall : forall A, forall P : A -> Prop,
(~ (exists x : A, P x) <-> (forall x : A, ~ P x)).
intros A P. split.
intros NE x Px.
apply NE.
exists x; auto.
intro Fx.
intro Ex.
destruct Ex.
apply (Fx x);auto.
Qed.
(~ (exists x : A, P x) <-> (forall x : A, ~ P x)).
intros A P. split.
intros NE x Px.
apply NE.
exists x; auto.
intro Fx.
intro Ex.
destruct Ex.
apply (Fx x);auto.
Qed.
Dans cette section, on va formaliser le prédicat "relation bien fondée" et on va prouver,
entre autre, l'implication et la réciproque entre:
- (i) une relation est bien fondée (selon notre formalisation),
- (ii) une relation n'admet pas de suite infinie décroissante.
Le sens direct est prouvable en logique intuitionniste. On introduira donc
pas d'axiome supplémentaire. On prouvera par contre la réciproque en logique classique (avec l'un
des axiomes de la section II) + un axiome magique.
Il faut commencer par formaliser cette propriété (i) en Coq. Commençons par les relations.
On se limitera dans ce projet aux relations entre un même ensemble. Le type des relations sur un
ensemble A s'écrit donc R : A -> A -> Prop. Regardez par exemple la relation "<" sur les
entiers:
Check (lt: nat -> nat -> Prop).
Pour formaliser qu'une relation est bien fondée (i) on va définir un prédicat Acce sur les
éléments x d'un ensemble A tel que:
- les éléments minimaux pour R vérifient le prédicat,
- si tous les éléments y plus petits que x vérifient le prédicat alors x le vérifie aussi.
Inductive Acce (A:Set) (R:A->A->Prop) : A->Prop :=
Accessible : forall x:A, (forall y:A, R y x -> Acce A R y) -> Acce A R x.
Accessible : forall x:A, (forall y:A, R y x -> Acce A R y) -> Acce A R x.
Intuitivement, Acce A R x est prouvable si vous avez une preuve (et donc un objet fini
mais qui peut contenir des inductions)
qui explore tous les éléments plus petits que x. Ce prédicat est donc prouvable uniquement
pour les éléments qui n'appartiennent à aucune chaîne infinie décroissante.
On peut donc formaliser le prédicat "bien fondée":
Definition bienFonde (A:Set) (R:A->A->Prop) : Prop := forall a:A, Acce A R a.
Cette présentation est plus effective que (ii), si vous prouvez qu'une relation
est bienFondé alors vous construisez une fonction qui pour tout élément de A
explore toutes les chaînes descendantes à partir de cet élément. C'est un outil
essentiel pour pouvoir définir des fonctions récursives bien fondées mais non
structurellement décroissantes.
Ecrivez le prédicat sur les relations "la relation n'admet
pas de suite infinie décroissante". Ecrivez l'énoncé du sens direct).
Lemma bienFonde_pasDecr : forall (A:Set) (R:A -> A -> Prop),
bienFonde A R ->
forall suite:nat->A, ~(forall n:nat, R (suite (S n)) (suite n)).
Voir l'énoncé dans la preuve plus bas.
Pour vous échauffer, prouver les deux lemmes suivants qui pourront
vous servir dans la suite.
Lemma nonAcce_uneEtape : forall (A:Set) (R : A -> A -> Prop) (a b:A),
R a b -> ~ Acce A R a -> ~ Acce A R b.
intros A R a b H H0 H1.
absurd (Acce A R a); auto.
generalize a H.
elim H1; auto.
Qed.
Lemma acce_uneEtape : forall (A:Set) (R : A -> A -> Prop) (a b:A),
R a b -> Acce A R b -> Acce A R a.
intros A R a b H H0.
generalize a H.
elim H0; auto.
Qed.
R a b -> ~ Acce A R a -> ~ Acce A R b.
intros A R a b H H0 H1.
absurd (Acce A R a); auto.
generalize a H.
elim H1; auto.
Qed.
Lemma acce_uneEtape : forall (A:Set) (R : A -> A -> Prop) (a b:A),
R a b -> Acce A R b -> Acce A R a.
intros A R a b H H0.
generalize a H.
elim H0; auto.
Qed.
Prouvez maintenant le lemme suivant permettant de réaliser des inductions
en exploitant une relation bien fondée (notez que c'est le but premier des relations bien
fondées: permettre d'aller au delà des fonctions récursives structurellement décroissantes).
Lui aussi pourra vous être utile. Pensez bien au lemme d'induction généré par la définition
inductive du prédicat Acce.
Lemma bienFonde_ind : forall (A : Set) (R : A -> A -> Prop),
bienFonde A R ->
forall P : A -> Prop,
(forall x : A, (forall y : A, R y x -> P y) -> P x) ->
forall a : A, P a.
intros.
Check Acce_ind.
apply (Acce_ind A R).
intros.
apply H0.
auto.
apply H.
Qed.
bienFonde A R ->
forall P : A -> Prop,
(forall x : A, (forall y : A, R y x -> P y) -> P x) ->
forall a : A, P a.
intros.
Check Acce_ind.
apply (Acce_ind A R).
intros.
apply H0.
auto.
apply H.
Qed.
On montre que la relation < : nat -> nat -> Prop est bien fondée
(conseil: vous aurez besoin d'un lemme d'induction forte).
Definition induction_forte : forall P : nat -> Prop,
(forall n, (forall k, k < n -> P k) -> P n) -> forall n, P n.
Proof. Require Import Arith.
intros P IH n.
cut (forall k, k <= n -> P k).
intros stronger; apply stronger; auto.
induction n; intros k Hk.
inversion Hk; apply IH; intros ? H0; inversion H0.
destruct (le_lt_eq_dec _ _ Hk).
apply IHn; auto with arith.
subst; apply IH; intros p Hp; apply IHn; auto with arith.
Qed.
Lemma lt_bienFonde : bienFonde nat lt.
unfold bienFonde.
apply induction_forte; apply Accessible; intros y H;inversion H.
Qed.
(forall n, (forall k, k < n -> P k) -> P n) -> forall n, P n.
Proof. Require Import Arith.
intros P IH n.
cut (forall k, k <= n -> P k).
intros stronger; apply stronger; auto.
induction n; intros k Hk.
inversion Hk; apply IH; intros ? H0; inversion H0.
destruct (le_lt_eq_dec _ _ Hk).
apply IHn; auto with arith.
subst; apply IH; intros p Hp; apply IHn; auto with arith.
Qed.
Lemma lt_bienFonde : bienFonde nat lt.
unfold bienFonde.
apply induction_forte; apply Accessible; intros y H;inversion H.
Qed.
Ecrivez le prédicat lex qui prend deux relations et qui formalise
la relation lexicographique sur ces deux relations. Prouvez maintenant que si deux relations
sont bien fondées alors la relation lexicographique de ces deux relations l'est aussi.
Et maintenant, prouvez le sens direct de l'implication.
Lemma pas_decroissante : forall (A:Set) (R:A -> A -> Prop),
bienFonde A R ->
forall suite:nat->A, ~(forall n:nat, R (suite (S n)) (suite n)).
bienFonde A R ->
forall suite:nat->A, ~(forall n:nat, R (suite (S n)) (suite n)).
Todo: des commentaires pour les étaps principales.
intros A R WF suite.
unfold not; intro dec.
cut (forall a:A, (exists i:nat, suite i = a) -> ~ Acce A R a).
intro H.
absurd (Acce A R (suite 0)).
apply H.
exists 0; trivial.
apply WF.
intro a; pattern a in |- *.
apply (bienFonde_ind A R);auto.
intros x Hx H.
elim H.
intros i egi.
cut (R (suite (S i)) (suite i)).
intro H1.
rewrite <- egi.
apply nonAcce_uneEtape with (suite (S i)); auto.
apply Hx.
rewrite <- egi; auto.
exists (S i); auto.
auto.
Qed.
unfold not; intro dec.
cut (forall a:A, (exists i:nat, suite i = a) -> ~ Acce A R a).
intro H.
absurd (Acce A R (suite 0)).
apply H.
exists 0; trivial.
apply WF.
intro a; pattern a in |- *.
apply (bienFonde_ind A R);auto.
intros x Hx H.
elim H.
intros i egi.
cut (R (suite (S i)) (suite i)).
intro H1.
rewrite <- egi.
apply nonAcce_uneEtape with (suite (S i)); auto.
apply Hx.
rewrite <- egi; auto.
exists (S i); auto.
auto.
Qed.
On s'attaque maintenant à la réciproque!
La réciproque n'est pas prouvable en logique intuitionniste (des intuitions? écrivez-les).
On introduit donc un axiome classique que l'on pourra utiliser dans la suite. La syntaxe est
"Axiom [nom_axiome] : P.".
Axiom classique: forall P Q:Prop, ((P->Q)->P)->P.
Tentez de prouver la réciproque sur papier en logique classique.
De quoi avez-vous besoin ?
Est-ce que c'est prouvable dans Coq (avec l'axiome classique) ?
Vous avez le droit d'ajouter un axiome tant qu'il appartient à la
théorie des ensembles de Zermelo-Fraenkel
(cf.Wikipedia).
Axiom axiomeChoix : forall (A:Set)(R:A->A->Prop),
(forall x, exists y, R x y )->
exists f, forall x, R x (f x).
(forall x, exists y, R x y )->
exists f, forall x, R x (f x).
Et maintenant, muni de ces deux axiomes, prouvez la réciproque.
Lemma bienfonde : forall (A:Set) (R:A -> A -> Prop) ,
~ bienFonde A R ->
exists suite:nat->A, forall n:nat, R (suite (S n)) (suite n).
intros A R NWF.
~ bienFonde A R ->
exists suite:nat->A, forall n:nat, R (suite (S n)) (suite n).
intros A R NWF.
1. >>> En invoquant l'axiome du choix, on montre que si x n'est pas accessible alors il
existe une fonction de A vers A qui choisit un prédécesseur y de x qui n'est pas accessible
(ce y existe car sinon x serait accessible).
assert (exists f:A->A, forall x, ~Acce A R x -> ~ Acce A R (f x) /\ R (f x) x).
destruct (axiomeChoix A (fun x y => Acce A R x \/ R y x /\ ~ Acce A R y)) as [f].
intro x.
destruct (axiomeChoix A (fun x y => Acce A R x \/ R y x /\ ~ Acce A R y)) as [f].
intro x.
Deux cas: soit x est accessible (et alors on conclut avec left) soit x ne l'est pas
et dans ce cas on sait qu'il existe un élément plus petit qui ne l'est pas
non plus (par contraposée) et on conclut avec right.
assert (MD: Acce A R x \/ ~ Acce A R x).
apply ax_peirce_emd.
unfold peirce;apply classique.
destruct MD as [Ax | NAx].
apply ax_peirce_emd.
unfold peirce;apply classique.
destruct MD as [Ax | NAx].
a) >> x est accessible
exists x.
left;auto.
left;auto.
b) >> x n'est pas accessible
assert (Pred: exists y, ~ Acce A R y /\ R y x).
assert(Contra: ~~ exists y : A, ~ Acce A R y /\ R y x).
intro NE.
apply NAx.
apply Accessible.
intros y Ryx.
assert (Contra: ~~ Acce A R y).
intro NAy.
apply NE.
exists y.
tauto.
apply ax_peirce_classic.
unfold peirce; apply classique;auto. auto.
apply ax_peirce_classic.
unfold peirce. apply classique;auto. auto.
destruct Pred.
exists x0. right. tauto.
exists f. intros x NAx.
destruct (H x) as [HA | [Rfx NAx2]].
tauto.
tauto.
destruct H as [f].
assert(Contra: ~~ exists y : A, ~ Acce A R y /\ R y x).
intro NE.
apply NAx.
apply Accessible.
intros y Ryx.
assert (Contra: ~~ Acce A R y).
intro NAy.
apply NE.
exists y.
tauto.
apply ax_peirce_classic.
unfold peirce; apply classique;auto. auto.
apply ax_peirce_classic.
unfold peirce. apply classique;auto. auto.
destruct Pred.
exists x0. right. tauto.
exists f. intros x NAx.
destruct (H x) as [HA | [Rfx NAx2]].
tauto.
tauto.
destruct H as [f].
2. >>> On montre qu'il existe un élément non accessible puisque la relation
n'est pas bien fondée.
assert (ENA : exists a:A, ~ Acce A R a).
Check forallExists.
apply -> forallExists;auto.
unfold peirce; apply classique.
destruct ENA as [x0].
Check forallExists.
apply -> forallExists;auto.
unfold peirce; apply classique.
destruct ENA as [x0].
3. >>> On construit une suite de points de A en itérant la fonction f en partant de x0.
(cette suite sera notre candidat).
pose (F := (fix F (n:nat) : A :=
match n with
| 0 => x0
| S p => f (F p)
end)).
exists F.
assert (forall n : nat, R (F (S n)) (F n) /\ ~ Acce A R (F (S n))).
induction n.
match n with
| 0 => x0
| S p => f (F p)
end)).
exists F.
assert (forall n : nat, R (F (S n)) (F n) /\ ~ Acce A R (F (S n))).
induction n.
On montre que la suite est un bon candidat par induction sur n.
simpl.
destruct (H x0);tauto.
destruct IHn as [RE NAFSn].
change (F (S (S n))) with (f (F (S n))).
destruct (H (F (S n)));auto.
intro n; apply H1.
Qed.
destruct (H x0);tauto.
destruct IHn as [RE NAFSn].
change (F (S (S n))) with (f (F (S n))).
destruct (H (F (S n)));auto.
intro n; apply H1.
Qed.
This page has been generated by coqdoc