En suivant l'exemple donné dans le chapitre GeneralRec du livre Chlipala, j'essaye d'écrire l'algorithme de fusion.Écrire des programmes bien établis en Coq en utilisant Fix ou Program Fixpoint
Voici mon code
Require Import Nat.
Fixpoint insert (x:nat) (l: list nat) : list nat :=
match l with
| nil => x::nil
| y::l' => if leb x y then
x::l
else
y::(insert x l')
end.
Fixpoint merge (l1 l2 : list nat) : list nat :=
match l1 with
| nil => l2
| x::l1' => insert x (merge l1' l2)
end.
Fixpoint split (l : list nat) : list nat * list nat :=
match l with
| nil => (nil,nil)
| x::nil => (x::nil,nil)
| x::y::l' =>
let (ll,lr) := split l' in
(x::ll,y::lr)
end.
Definition lengthOrder (l1 l2 : list nat) :=
length l1 < length l2.
Theorem lengthOrder_wf : well_founded lengthOrder.
Admitted.
Le problème est qu'il est impossible d'écrire la fonction mergesort avec la commande Fixpoint
puisque la fonction ne diminue pas structurellement:
Fixpoint mergeSort (l: list nat) : list nat :=
if leb (length l) 1 then l
else
let (ll,lr) := split l in
merge (mergeSort ll) (mergeSort lr).
Au lieu de cela, un peut utiliser la commande Program Fixpoint
ou Definition
avec le terme Fix
(comme dans le livre de Chlipala).
Cependant, si je vous écris ce
Definition mergeSort : list nat -> list nat.
refine (Fix lengthOrder_wf (fun (l: list nat) => list nat)
(fun (l : list nat) => (fun mergeSort : (forall ls : list nat, lengthOrder ls l -> list nat)=>
if leb (length l) 1 then
let (ll,lr) := split l in
merge (mergeSort ll _) (mergeSort lr _)
else
l))).
je reçois des objectifs impossibles:
2 subgoals, subgoal 1 (ID 65)
l : list nat
mergeSort : forall ls : list nat, lengthOrder ls l -> list nat
ll, lr : list nat
============================
lengthOrder ll l
subgoal 2 (ID 66) is:
lengthOrder lr l
C'est pourquoi Chlipala suggère de modifier la définition de mergesort cette façon:
Definition mergeSort : list nat -> list nat.
refine (Fix lengthOrder_wf (fun _ => list nat)
(fun (ls : list nat)
(mergeSort : forall ls' : list nat, lengthOrder ls' ls -> list nat) =>
if Compare_dec.le_lt_dec 2 (length ls)
then let lss := split ls in
merge (mergeSort (fst lss) _) (mergeSort (snd lss) _)
else ls)).
qui génère les objectifs suivants:
2 subgoals, subgoal 1 (ID 68)
ls : list nat
mergeSort : forall ls' : list nat, lengthOrder ls' ls -> list nat
l : 2 <= length ls
lss := split ls : list nat * list nat
============================
lengthOrder (fst lss) ls
subgoal 2 (ID 69) is:
lengthOrder (snd lss) ls
Cette nouvelle définition me semble magique. Donc je me demande:
- A partir de la première définition, est-il encore possible de prouver le bien-être de la fonction?
- Sinon, pourquoi la première définition ne peut pas fonctionner?
- Comment un utilisateur de base peut-il passer facilement de la première définition à la seconde?
'longueur (fst (split l)) lengthOrder (fst (split ls)) ls'. –