n : nat m : nat
H : (Le (S n) m) mon_exemple0 : nat mon_exemple1 : nat mon_exemple2 : n0=n mon_exemple3 : (S m0)=m mon_exemple4 : (Le n m0)
============================
(P n (S m0))
Ainsi quelques soient les noms présents dans le contexte local, (pourvu qu'il ne contienne pas déjà l'identicateur mon_exemple), les noms d'hypothèses introduits par inversion sont les mêmes.
Autres problèmes
On rencontre ici aussi les deux problèmes récurrents de nos outils, les faiblesses dûes à l'utilisation des variables existentielles et des procédures de décision automatiques.
On peut essayer d'étendre le processus de lemmication à des sous-buts contenant des variables existentielles. Pour lemmier un sous-but contenant des variables existentielles, la démarche est la même que dans le cas sans variable existentielle mais, il faut en plus réintroduire une quantication existentielle sur un objet du même type que la variable et remplacer toutes les instances de la variable dans le sous-but par cet objet. Par exemple si on veut lemmier sur le sous-but(S (S (plus?77 (0))))=(5)on le transforme en(Ex
[x:nat](S (S (plus x (0))))=(5))et on introduit en tête du scriptEApply ex_intro.
Mais cela est possible que si la variable existentielle n'est pas contrainte par une tactique de rang inférieur à celle que l'on sélectionne pour la lemmication. Sinon on ne retrouvera pas forcément la même contrainte en rejouant le script issu de la lemmication.
Les problèmes lies à la sensibilité au contexte des procédures de décision automatique sont traités au chapitre 9. Disons simplement ici que dans de très rares cas où le script du sous-but lemmié contient des opérateurs non monotones comme Orelse utilisés en liaison avec des procédures de décision automatique, il est possible que le script du résultat lemmié ne puisse pas être rejoué.
5.2. FACTORISATION DE LEMME 85 la sous-preuve et l'utiliserait ensuite dans tous les sous-buts où cela est nécessaire. Nous détaillons cela sur un exemple trivial.
Exemple 5.4
On considère le lemme trivial ci-dessous:
Lemma factor : A\/A-> A/\A.
qui peut être prouvé par le script suivant
L1 Intros.
L2 Elim H.
L3 Split.
L4 Exact H0.
L5 Exact H0.
L6 Split.
L7 Exact H0.
L8 Exact H0.
Et qui correspond au
-terme suivant:factor < Show Proof.
LOC:
Subgoals
Proof: [H:A\/A]
(or_ind A A A/\A [H0:A]<(A),(A)>{H0,H0} [H0:A]<(A),(A)>{H0,H0}
H)
et à l'arbre de preuve suivant:
Intros.
Elim H.
Exact H0 Split.
Exact H0 Exact H0
Split.
Exact H0
B1 B2
}
En fait les sous-buts résolus par les branches B1 et B2sont identiques et ont été générés par la tactique de la ligne 2: Elim H. Ils correspondent tous deux à:
H : A\/A
============================
A->A/\A
Le terme de preuve incomplet correspondant à cet état est:
factor < Show Proof.
LOC:
Subgoals
1092 -> A\/A->A->A/\A 1093 -> A\/A->A->A/\A
Proof: [H:A\/A](or_ind A A A/\A (?1092 H) (?1093 H) H)
Après résolution de la branche B1, le terme de preuve est:
factor < Show Proof.
LOC:
Subgoals
1162 -> A\/A->A->A/\A
Proof: [H:A\/A](or_ind A A A/\A [H0:A]<(A),(A)>{H0,H0} (?1162 H) H)
Le sous terme correspondant à cette branche est:
[H0:A]<(A),(A)>{H0,H0}
5.2. FACTORISATION DE LEMME 87 On constate qu'il est indépendant de H. On n'a donc pas besoin d'abstraire l'hypothèse
H. Le lemme à introduire est donc:
Lemma intermédiaire : A->A/\A.
On devrait pouvoir le prouver par le script suivant, correspondant à la branche B1.
L3 Split
L4 Exact H0
L5 Exact H0
Mais comme il n'y pas d'hypothèseHdans l'environnement local au moment duSplit, il introduit une hypothèse H au lieu deH0 et par conséquent les lignes 4 et 5 échouent. Si on a pris soin de sécuriser le nommage des hypothèses on aura
3: Intros H0;Split 4: Exact H0
5: Exact H0
Qui repasse sans problème.
En fait, pour ne pas perdre de temps à rejouer la preuve, on enverra au système, le sous terme de preuve isolé plus haut:
Coq < Lemma intermédiaire : A->A/\A.
1 subgoal
============================
A->A/\A
intermédiaire < Proof [H0:A]<(A),(A)>{H0,H0}.
intermédiaire is defined
En remplaçant les deux branches identiques par un Exact intermédiaire, le script de preuve du lemme principal (factor) devient
Intros.
Elim H;Exact intermédiaire.
Le terme de preuve correspondant est alors
factor < Show Proof.
LOC:
Subgoals
Proof: [H:A\/A](or_ind A A A/\A intermédiaire intermédiaire H)
Si nous ne voulons pas surcharger l'environnement, en ajoutant un lemme comme
intermédiaire nous pourrons ajouter un Cut. Pour cela, il faut remonter à l'ancêtre commun aux deux sous-buts SG et le précéder d'un Cut SG; la preuve de SGest à faire à la n. Pour notre exemple cela donne le script:
Intros.
Cut A->A/\A.
Intros.
Elim H.
Exact H0.
Exact H0.
Intros H0;Split. (* *)
Exact H0 (* *)
(* ou réutiliser le sous-terme *)
Exact H0 (* *)
5.2.1 Principe de fonctionnement
La gure 5.1 montre le principe de fonctionnement de la factorisation une fois que l'on a detecté deux sous-buts semblables
S
1 etS
2, etS
1 etant prouver.5.2. FACTORISATION DE LEMME 89
P
Deux sous buts identiques
P
s1 s2s1
P
Ajouté dans l’environnement comme un lemme LP
Factorisation avec enrichissement de l’environnement
Factorisation avec ajout d’un Cut
Ancêtre commun
La preuve de s1
On fait Cut s1 avant l’ancêtre ça ajoute une hypothèse Hi:s1 et génère un but s1
Juste Exact LP
Juste Exact Hi Preuve incomplète, au moment
ou l’on constate la similitude des buts a prouver.
On pourrait la finir en recopiant la preuve P de s1 en s2
Fig.5.1 Illustration du principe de factorisation
En pratique détecter deux sous-buts identiques dans une grosse preuve est beaucoup trop coûteux puisque, dès que l'on aura plus d'une branche dans l'arbre de preuve, il faudra comparer deux à deux chacun des n÷uds. Par contre si l'on sait qu'un résultat a déjà été prouvé, il est facile de le retrouver et de l'exploiter. C'est aussi l'objet de la tactique Similardécrite ci-dessous.
La tactique Similar
La tactique Similar vise, comme son nom l'indique, à exploiter les similarités de cer-taines sous preuves. Pour une question de coût, ces similarités qui se limitent pour l'instant à une convertibilité ne sont pas détectées systématiquement, c'est à l'utilisateur de se dire
"tiens j'ai déjà prouvé quelque chose comme ça!", et d'appliquer alors Similar. On par-court alors l'arbre de preuve à la recherche d'un but convertible avec le but courant. Si un tel but existe on calcule quelles hypothèses ont été nécessaires à sa preuve. Si ces
hypo-thèses sont satisfaites dans le contexte courant, on peut réutiliser la preuve qui est alors mise en facteur.