-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathordinals.v
986 lines (844 loc) · 26.9 KB
/
ordinals.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
From Stdlib Require Import Arith.
From Stdlib Require Import Eqdep_dec.
From Stdlib Require Import Peano_dec.
From Stdlib Require Import List.
From Stdlib Require Import Recdef.
(**
Arithmétique
*)
(* Sur la soustraction (entière) *)
Lemma minus_Sn_n : forall (n:nat), (minus (S n) n) = (S 0).
induction n; auto.
Qed.
Lemma lt_S_r : forall (n1 n2:nat),
(lt n1 n2) -> exists (n:nat), n2 = (S n).
destruct n2.
intro. exfalso. apply (Nat.nlt_0_r n1). assumption.
intro. exists n2. trivial.
Qed.
Lemma minus_lt_S : forall (n1 n2:nat),
(lt n1 n2) -> exists (n:nat), (minus n2 n1) = (S n).
intros. elim (lt_S_r n1 n2 H). intros n H1. rewrite H1.
exists (minus n n1). rewrite Nat.sub_succ_l.
trivial.
apply le_S_n. rewrite H1 in H. auto.
Qed.
(* Sur l'ordre strict 'lt' *)
Lemma lt_1_0 : forall (n:nat), (lt n 1) -> (n=0).
destruct n.
auto.
intro. inversion H. exfalso. apply (Nat.nle_succ_0 (S n)). assumption.
Qed.
Lemma lt_S_case : forall (m n:nat), (lt m (S n)) -> (lt m n) \/ (m=n).
intros m n. generalize m. induction n.
intros. rewrite (lt_1_0 m0 H). tauto.
destruct m0.
intro. auto with arith.
intro. elim IHn with (m:=m0); auto with arith.
Qed.
Lemma not_lt_Sn_n : forall (n:nat), not (lt (S n) n).
induction n.
auto with arith.
intro. auto with arith.
Qed.
(* Sur l'ordre large 'le' *)
Lemma not_le_Sn_n : forall (n:nat), not (le (S n) n).
induction n.
auto with arith.
intro. auto with arith.
Qed.
(* Cas sur les entiers *)
Lemma nat_compare_case : forall (n1 n2:nat),
(lt n1 n2) \/ (n1=n2) \/ (lt n2 n1).
induction n1.
destruct n2.
tauto.
left. auto with arith.
destruct n2.
right. right. auto with arith.
elim (IHn1 n2).
intro. left. auto with arith.
intro. elim H.
intro. right. left. auto.
intro. right. right. auto with arith.
Qed.
(**
Sur les listes
*)
(* Sur la longueur. *)
Lemma length_0_nil : forall (w:(list nat)),
(length w)=0 -> w=nil.
destruct w.
auto.
intro. discriminate H.
Qed.
Lemma length_Sn_cons : forall (w:(list nat)) (n:nat),
(length w)=(S n) -> exists (a:nat) (w':(list nat)), w = (cons a w').
destruct w.
intros. discriminate H.
intros. exists n. exists w. trivial.
Qed.
(* Principe d'induction sur la longueur des listes *)
Lemma list_length_ind_S : forall (P: (list nat) -> Prop),
(P nil)
-> (forall (n:nat), (forall (xs:(list nat)), (lt (length xs) (S n)) -> (P xs))
-> forall (xs:(list nat)), (length xs)=(S n) -> (P xs))
-> forall (n:nat) (xs:(list nat)), (lt (length xs) (S n) -> (P xs)).
intros P P0 Plt. induction n.
intros. assert (xs=nil).
apply length_0_nil. apply lt_1_0. assumption.
rewrite H0. assumption.
intros. elim (lt_S_case (length xs) (S n) H).
auto.
intro. apply (Plt n); auto.
Qed.
Lemma list_length_ind : forall (P: (list nat) -> Prop),
(P nil)
-> (forall (n:nat), (forall (xs:(list nat)), (lt (length xs) (S n)) -> (P xs))
-> forall (xs:(list nat)), (length xs)=(S n) -> (P xs))
-> forall (xs:(list nat)), (P xs).
intros. apply list_length_ind_S with (n:=(length xs)).
assumption.
assumption.
auto with arith.
Qed.
(* Extension d'une liste avec des 0 (en tête) *)
Fixpoint zs (n:nat) : (list nat) :=
match n with
0 => nil
| (S n) => (cons 0 (zs n))
end.
Lemma zs_len: forall (n:nat), (length (zs n))=n.
induction n.
auto.
simpl. rewrite IHn. trivial.
Qed.
(* Complétion d'une liste en fonction d'une autre.
Le résultat est une liste de la longueur de la
plus grande. *)
Definition dist (w1:(list nat)) (w2:(list nat)) :=
(minus (length w1) (length w2)).
Definition padd (w1:(list nat)) (w2:(list nat)) :=
(app (zs (dist w2 w1)) w1).
Lemma padd_len_lt_cons : forall (w1 w2:(list nat)),
(lt (length w1) (length w2))
-> exists (w:(list nat)), (padd w1 w2)=(cons 0 w).
intros. unfold padd. unfold dist.
elim (minus_lt_S (length w1) (length w2) H).
intros. rewrite H0. simpl. exists (app (zs x) w1). trivial.
Qed.
Lemma padd_len_le_len : forall (w1 w2:(list nat)),
(le (length w1) (length w2))
-> (length (padd w1 w2)) = (length w2).
intros. unfold padd. unfold dist. rewrite length_app.
rewrite zs_len.
rewrite Nat.sub_add by (exact H); reflexivity.
Qed.
Lemma padd_cons_0 : forall (w1 w2:(list nat)) (a:nat),
(length w1) = (length w2) -> (padd w1 (cons a w2)) = (cons 0 w1).
intros. unfold padd. unfold dist. rewrite H. simpl length.
rewrite (minus_Sn_n (length w2)). simpl. trivial.
Qed.
(**
Sur l'accessibilité.
Tribute to P. Casteran:
http://www.labri.fr/perso/casteran/Cantor/HTML/AccP.html#AccElim3
*)
Theorem AccElim2 :
forall (A B:Set)
(RA: A -> A -> Prop) (RB: B -> B -> Prop),
forall (P : A -> B -> Prop),
(forall x y,
(forall (t : A), RA t x -> forall y', Acc RB y' -> P t y') ->
(forall (t : B), RB t y -> P x t) ->
(P x y)) ->
forall x y, Acc RA x -> Acc RB y -> P x y.
Proof.
intros A B RA RB P H x y Ax; generalize y; clear y.
elim Ax. clear Ax x; intros x HAccx Hrecx y Ay.
elim Ay. clear Ay y. intros y HAccy Hrecy. apply H.
auto.
auto.
Qed.
(**
Relation d'ordre sur les listes d'entiers considérés comme des
ordinaux (formes normales de Cantor à exposants finis).
*)
Inductive wlt : (list nat) -> (list nat) -> Prop :=
wlt_nil : forall (a:nat)(w:(list nat)), (wlt nil (cons (S a) w))
| wlt_0_w : forall (w1 w2:(list nat)), (wlt w1 w2) -> (wlt (cons 0 w1) w2)
| wlt_w_0 : forall (w1 w2:(list nat)), (wlt w1 w2) -> (wlt w1 (cons 0 w2))
| wlt_len : forall (w1 w2:(list nat)) (a1 a2:nat),
(length w1 < length w2) -> (wlt (cons (S a1) w1) (cons (S a2) w2))
| wlt_lt : forall (w1 w2:(list nat)) (a1 a2:nat),
(length w1 = length w2) -> (lt a1 a2)
-> (wlt (cons (S a1) w1) (cons (S a2) w2))
| wlt_wlt : forall (w1 w2:(list nat)) (a:nat),
(length w1 = length w2) -> (wlt w1 w2)
-> (wlt (cons (S a) w1) (cons (S a) w2)).
(* 'nil' est minimal *)
Lemma not_wlt_nil : forall (w:(list nat)),
not (wlt w nil).
induction w.
intro. inversion H.
case a.
intro. inversion H. auto.
intro. intro. inversion H.
Qed.
(* Lemmes d'inversion *)
Lemma wlt_0_w_inv: forall (w1 w2:(list nat)),
(wlt (cons 0 w1) w2) -> (wlt w1 w2).
induction w2.
intros. absurd (wlt (cons 0 w1) nil).
apply (not_wlt_nil (cons 0 w1)).
assumption.
intro. inversion H.
assumption.
apply wlt_w_0. auto.
Qed.
Lemma wlt_w_0_inv: forall (w1 w2:(list nat)),
(wlt w1 (cons 0 w2)) -> (wlt w1 w2).
induction w1.
intros. inversion H. assumption.
intros. inversion H.
apply wlt_0_w. auto.
assumption.
Qed.
(* Autres résultats négatifs *)
Lemma not_wlt_len_left : forall (w1 w2:(list nat)) (a:nat),
(le (length w2) (length w1)) -> not (wlt (cons (S a) w1) w2).
induction w2.
intros. apply not_wlt_nil.
intros. destruct a.
intro. absurd (wlt (cons (S a0) w1) w2).
apply IHw2.
apply Nat.le_trans with (m:=(length (cons 0 w2))).
auto with arith.
assumption.
apply wlt_w_0_inv. assumption.
intro. inversion H0.
assert (lt (length (cons (S a) w2)) (length w2)).
apply Nat.le_lt_trans with (m := (length w1)); assumption.
apply (not_lt_Sn_n (length w2)). assumption.
rewrite H4 in H. apply (not_le_Sn_n (length w2)); assumption.
rewrite H4 in H. apply (not_le_Sn_n (length w2)); assumption.
Qed.
Lemma not_wlt_Sn_0 : forall (w1 w2:(list nat)) (a:nat),
(length w1) = (length w2) -> not (wlt (cons (S a) w1) (cons 0 w2)).
intros. intro. inversion H0.
apply (not_wlt_len_left w1 w2 a).
rewrite H. auto with arith.
apply wlt_w_0_inv. assumption.
Qed.
Lemma not_wlt_len: forall (w1 w2:(list nat)) (a:nat),
(length w2 <= length w1) -> not (wlt (cons (S a) w1) w2).
induction w2.
intros. intro. exfalso. apply (not_wlt_nil (cons (S a) w1)). assumption.
intro. case a.
intro. intro. apply IHw2 with (a:=a0).
apply Nat.le_trans with (m:=(length (cons 0 w2))).
simpl. auto with arith.
assumption.
apply wlt_w_0_inv. assumption.
intros. intro. inversion H0.
apply (Nat.lt_irrefl (length w1)).
simpl in H. apply Nat.lt_trans with (m:=(length w2)); assumption.
rewrite H4 in H. apply (Nat.nle_succ_diag_l (length w2)). assumption.
rewrite H4 in H. apply (Nat.nle_succ_diag_l (length w2)). assumption.
Qed.
(* Invariance de 'wlt' pour la complétion à 0 (en tête) *)
Lemma wlt_wlt_zs_right : forall (n:nat) (w1 w2:(list nat)),
(wlt w1 w2) -> (wlt w1 (app (zs n) w2)).
induction n.
auto.
intros. simpl. apply wlt_w_0. auto.
Qed.
Lemma wlt_zs_wlt_right : forall (n:nat) (w1 w2:(list nat)),
(wlt w1 (app (zs n) w2)) -> (wlt w1 w2).
induction n.
auto.
simpl. intros. apply IHn. apply wlt_w_0_inv. assumption.
Qed.
Lemma wlt_wlt_zs_left : forall (n:nat) (w1 w2:(list nat)),
(wlt w1 w2) -> (wlt (app (zs n) w1) (w2)).
induction n.
auto.
intros. simpl. apply wlt_0_w. auto.
Qed.
(* Caractérisation en fonction de la longueur:
si '(wlt w1 w2)' et '#w2 < #w1' alors 'w1' commence par des 0 *)
Lemma wlt_gt_length : forall (w1 w2:(list nat)),
(wlt w1 w2) -> (lt (length w2) (length w1))
-> exists (n:nat) (w:(list nat)),
(w1 = (app (zs n) w))
/\ (length w)=(length w2)
/\ (wlt w w2).
induction w1 as [| a w1 IHw1]; [intros w2 _ []%Nat.nlt_0_r |].
intros w2 H Hl; simpl in Hl; apply <-Nat.succ_le_mono in Hl.
destruct a as [| a].
- apply Nat.le_lteq in Hl as [Hl | Hl].
+ apply wlt_0_w_inv in H; specialize (IHw1 w2 H Hl) as [n [w' [H'1 [H'2 H'3]]]].
now exists (S n); exists w'; split; [rewrite H'1 | split].
+ exists (S 0); exists w1; split; [reflexivity | split]; [now symmetry |].
exact (wlt_0_w_inv _ _ H).
- now exfalso; apply not_wlt_len_left with (2 := H).
Qed.
(**
Restriction de l'ordre aux listes de même longueur.
(avec complémentation possible à 0):
c'est l'ordre lexicographique.
*)
(* La relation sur les listes de même longueur *)
Inductive wlt_pad : (list nat) -> (list nat) -> Prop :=
wlt_pad_len : forall (a:nat) (w1 w2:(list nat)),
(le (length w1) (length w2)) ->
(wlt_pad (padd w1 (cons (S a) w2)) (cons (S a) w2))
| wlt_pad_lt : forall (a1 a2:nat) (w1 w2:(list nat)),
(length w1) = (length w2) -> (lt a1 a2) ->
(wlt_pad (cons (S a1) w1) (cons (S a2) w2))
| wlt_pad_wlt_pad : forall (a:nat) (w1 w2:(list nat)),
(length w1) = (length w2) -> (wlt_pad w1 w2) ->
(wlt_pad (cons a w1) (cons a w2)).
(* Relations entre l'ordre sur toute liste et l'ordre restreint. *)
Lemma wlt_wlt_pad : forall (w1 w2:(list nat)),
(length w1) = (length w2) -> (wlt w1 w2)
-> (wlt_pad w1 w2).
intros w1 w2. generalize w1. clear w1. induction w2.
intros. exfalso. apply (not_wlt_nil w1). assumption.
destruct w1.
intros. discriminate H.
intros. inversion H0.
(* 1: wlt_0_w *)
destruct a.
apply wlt_pad_wlt_pad.
auto.
apply IHw2.
auto.
apply wlt_w_0_inv. assumption.
rewrite <- (padd_cons_0 w1 w2 a).
apply wlt_pad_len. injection H. intro. rewrite H5. auto with arith.
auto.
(* 2: wlt_w_0 *)
destruct n.
apply wlt_pad_wlt_pad.
auto with arith.
apply IHw2.
auto with arith.
apply wlt_w_0_inv. apply wlt_0_w_inv. rewrite <- H1 in H0. assumption.
exfalso. apply (not_wlt_Sn_0 w1 w2 n).
auto with arith.
rewrite <- H1 in H0. assumption.
(* 3 *)
exfalso. apply (Nat.lt_irrefl (length w2)). injection H.
intro. rewrite H6 in H2. assumption.
(* 4 *)
apply wlt_pad_lt.
auto with arith.
assumption.
(* 5 *)
apply wlt_pad_wlt_pad.
auto with arith.
apply IHw2.
auto with arith.
assumption.
Qed.
Lemma wlt_wlt_pad_zs : forall (w1 w2:(list nat)),
(length w1) < (length w2) -> (wlt w1 w2)
-> (wlt_pad (padd w1 w2) w2).
intros. apply wlt_wlt_pad.
apply padd_len_le_len. auto with arith.
apply wlt_wlt_zs_left. assumption.
Qed.
(**
Accessibilité pour l'ordre restreint.
*)
Lemma Acc_wlt_pad_ind : forall (n:nat),
(forall (w:(list nat)), (lt (length w) (S n)) -> Acc wlt_pad w)
-> forall (w:(list nat)), (length w)=(S n) -> Acc wlt_pad w.
intros. elim (length_Sn_cons w n H0). intros a H1. elim H1. clear H1.
intros w' H1. rewrite H1. rewrite H1 in H0. clear H1. generalize H0.
pattern a, w'.
apply AccElim2 with (RA:=lt) (RB:=wlt_pad).
intros a' w'' H1 H2 H3. apply Acc_intro. intros w''' H4.
inversion H4.
elim (padd_len_lt_cons w1 (cons (S a0) w'')).
intros w0 H9. rewrite H9. apply H1.
rewrite <- H5. auto with arith.
apply H.
assert (lt (length (cons 0 w0)) (S (S n))).
rewrite <- H9. rewrite padd_len_le_len.
rewrite H5. rewrite H3. auto with arith.
simpl. auto with arith.
auto with arith.
rewrite <- H9. rewrite padd_len_le_len.
rewrite H5. assumption.
simpl. auto with arith.
simpl. auto with arith.
apply H1.
rewrite <- H5. auto with arith.
apply H.
rewrite H8. rewrite <- H3. auto with arith.
simpl. rewrite H8. auto.
apply H2.
assumption.
simpl. rewrite H8. auto.
apply lt_wf.
apply H.
rewrite <- H0. auto with arith.
Qed.
Lemma Acc_wlt_pad_nil : (Acc wlt_pad nil).
apply Acc_intro. intros. inversion H.
Qed.
Lemma Acc_wlt_pad : forall (w:(list nat)), (Acc wlt_pad w).
induction w using list_length_ind.
apply Acc_wlt_pad_nil.
apply Acc_wlt_pad_ind with (n:=n); assumption.
Qed.
(**
De l'accessibilté pour l'ordre restreint à l'accessibilité
pour l'ordre sur tout liste.
*)
Lemma Acc_wlt_zs_Acc_wlt : forall (n:nat) (w:(list nat)),
(Acc wlt (app (zs n) w)) -> (Acc wlt w).
intros. apply Acc_intro. intros w' H0. apply H.
apply wlt_wlt_zs_right. assumption.
Qed.
Lemma Acc_wlt_Acc_wlt_zs : forall (n:nat) (w:(list nat)),
(Acc wlt w) -> (Acc wlt (app (zs n) w)).
intros. apply Acc_intro. intros w' H0. apply H.
apply wlt_zs_wlt_right with (n:=n). assumption.
Qed.
Lemma Acc_wlt_pad_Acc_wlt : forall (w:(list nat)),
(Acc wlt_pad w) -> (Acc wlt w).
intros. elim H. intros w' H0 H1. apply Acc_intro.
intros w'' H2. elim (nat_compare_case (length w'') (length w')).
(* #w'' < #w' *)
intro. apply Acc_wlt_zs_Acc_wlt with (n:=(dist w' w'')).
apply H1. apply wlt_wlt_pad_zs; assumption.
(* #w'' = #w4 \/ #w' < #w'' *)
intro. elim H3.
(* #w'' = #w' *)
intro. apply H1. apply wlt_wlt_pad; assumption.
(* #w' < #w'' *)
intro. elim (wlt_gt_length w'' w' H2 H4). intros a H5.
elim H5. intro w0. intro. decompose [and] H6.
rewrite H7. apply Acc_wlt_Acc_wlt_zs. apply H1.
apply wlt_wlt_pad; assumption.
Qed.
(**
L'ordre sur toute liste est bien fondé !
*)
Theorem Acc_wlt : forall (w:(list nat)), (Acc wlt w).
intro. apply Acc_wlt_pad_Acc_wlt.
apply Acc_wlt_pad.
Qed.
(**
Sur wlt
*)
Lemma wlt_len_gen : forall (w1 w2:list nat) (a:nat),
(lt (length w1) (length (cons (S a) w2))) -> (wlt w1 (cons (S a) w2)).
induction w1.
intros. apply wlt_nil.
intros. destruct a.
apply wlt_0_w. apply IHw1. apply Nat.lt_trans with (m:=(length (cons 0 w1))).
auto with arith.
assumption.
apply wlt_len. auto with arith.
Qed.
Lemma wlt_lt_gen : forall (a1 a2:nat) (w1 w2:list nat),
(length w1) = (length w2) -> (lt a1 a2)
-> (wlt (cons a1 w1) (cons a2 w2)).
intros. destruct a2.
exfalso. apply (Nat.nlt_0_r a1). assumption.
destruct a1.
apply wlt_0_w. apply wlt_len_gen. rewrite H. auto with arith.
apply wlt_lt; auto with arith.
Qed.
Lemma wlt_wlt_gen : forall (a:nat) (w1 w2:list nat),
(length w1) = (length w2) -> (wlt w1 w2)
-> (wlt (cons a w1) (cons a w2)).
destruct a.
intros. apply wlt_0_w. apply wlt_w_0. assumption.
intros. apply wlt_wlt; assumption.
Qed.
Lemma wlt_wf_ind : forall (P: (list nat) -> Prop),
(forall (w1:list nat), (forall (w2:list nat), (wlt w2 w1) -> P w2) -> P w1)
-> forall (w:list nat), P w.
intros. apply well_founded_ind with (R:=wlt).
unfold well_founded. apply Acc_wlt.
intros. apply H. assumption.
Qed.
(* Utilitaire pour la définition des ordres *)
Definition make_mwlt (A:Set) (m : A -> list nat) (a1 a2:A) :=
(wlt (m a1) (m a2)).
(** Un ordre basé sur une mesure ordinale est bien fondé *)
Lemma Acc_wlt_eq :
forall (A:Set) (m: A -> list nat) (w:list nat) (x:A) ,
w = (m x) -> (Acc (fun x1 x2 : A => wlt (m x1) (m x2)) x).
induction w using wlt_wf_ind. intros. apply Acc_intro. intros.
apply H with (w2:=(m y)).
rewrite H0. assumption.
trivial.
Qed.
Lemma Acc_mwlt : forall (A:Set) (m: A -> list nat),
forall (x:A), (Acc (fun x1 x2 => (wlt (m x1) (m x2))) x).
intros. apply Acc_wlt_eq with (w:=(m x)). trivial.
Qed.
(**
Applications avec Program Fixpoint
*)
From Stdlib Require Program.Wf.
(* Tactique pour les preuves de bonne fondation. *)
Ltac by_Acc_mwlt mwlt :=
unfold Wf.MR; unfold well_founded; intros; unfold mwlt; apply Acc_mwlt.
(* Ordre lexicographique sur les entiers *)
Definition wm_natxnat (xy:nat*nat) :=
match xy with
(x,y) => (cons x (cons y nil))
end.
Definition lex_natxnat :=
(make_mwlt (nat*nat) wm_natxnat).
Lemma lex_natxnat_fst : forall (x1 y1 x2 y2:nat),
(lt x1 x2) -> (lex_natxnat (x1,y1) (x2,y2)).
intros. unfold lex_natxnat. unfold make_mwlt. simpl.
apply wlt_lt_gen; auto.
Qed.
Lemma lex_natxnat_snd : forall (x y1 y2:nat),
(lt y1 y2) -> (lex_natxnat (x,y1) (x,y2)).
intros. unfold lex_natxnat. unfold make_mwlt. simpl.
apply wlt_wlt_gen.
auto.
apply wlt_lt_gen; auto.
Qed.
Program Fixpoint ack_like (xy:nat*nat) {wf lex_natxnat xy} : nat :=
match xy with
(0, y) => (S y)
| (S x, 0) => (ack_like (x, S 0))
| (S x, S y) => (ack_like (x, (x + y))) + (ack_like (S x, y))
end.
Obligation 1.
apply lex_natxnat_fst.
auto with arith.
Qed.
Obligation 2.
apply lex_natxnat_fst.
auto with arith.
Qed.
Obligation 3.
apply lex_natxnat_snd.
auto with arith.
Qed.
Obligation 4.
by_Acc_mwlt lex_natxnat.
Defined.
Program Fixpoint ack (xy:nat*nat) {wf lex_natxnat xy} : nat :=
match xy with
(0, y) => (S y)
| (S x, 0) => (ack (x, S 0))
| (S x, S y) => (ack (x, ack (S x, y)))
end.
Obligation 1.
apply lex_natxnat_fst.
auto with arith.
Qed.
Obligation 2.
apply lex_natxnat_snd.
auto with arith.
Qed.
Obligation 3.
apply lex_natxnat_fst. inversion Heq_xy. auto with arith.
Qed.
Obligation 4.
by_Acc_mwlt lex_natxnat.
Defined.
(* Ordre lexicographique sur les longueurs des listes *)
Definition wm_listxlist (A:Set) (xys: list A * list A) :=
match xys with
(xs,ys) => (wm_natxnat (length xs, length ys))
end.
Definition lex_listxlist (A:Set) :=
(make_mwlt (list A * list A) (wm_listxlist A)).
Parameter ltb : nat -> nat -> bool.
Program Fixpoint merge (xys: list nat * list nat) {wf (lex_listxlist nat) xys} : list nat :=
match xys with
(nil, ys) => ys
| (xs, nil) => xs
| (cons x xs, cons y ys) =>
if (ltb x y) then (cons x (merge (xs, (cons y ys))))
else (cons y (merge ((cons x xs), ys)))
end.
Obligation 1.
unfold lex_listxlist. unfold make_mwlt. simpl.
apply wlt_lt_gen; auto with arith.
Qed.
Obligation 2.
unfold lex_listxlist. unfold make_mwlt. simpl. apply wlt_wlt_gen.
auto.
apply wlt_lt_gen; auto with arith.
Qed.
Obligation 4.
by_Acc_mwlt lex_natxnat.
Defined.
(* Ordre sur les listes d'entiers:
ordre lexicographique sur la taille et le premier élément *)
Definition m_list (xs:list nat) :=
match xs with
nil => nil
| (cons x xs) => (cons (length (cons x xs)) (cons x nil))
end.
Definition lt_list :=
(make_mwlt (list nat) m_list).
Program Fixpoint sum_list (xs:list nat) {wf lt_list xs} : nat :=
match xs with
nil => 0
| (cons 0 xs) => (sum_list xs)
| (cons (S x) xs) => S (sum_list (cons x xs))
end.
Obligation 1.
unfold lt_list. unfold make_mwlt. simpl. destruct xs.
simpl. apply wlt_nil.
simpl. apply wlt_lt_gen; auto with arith.
Qed.
Obligation 2.
unfold lt_list. unfold make_mwlt. simpl. apply wlt_wlt_gen.
auto.
apply wlt_lt_gen; auto with arith.
Qed.
Obligation 3.
by_Acc_mwlt lex_natxnat.
Defined.
(* Analogue sur les listes de listes *)
Definition m_listlist (A:Set) (xss : list (list A)) :=
match xss with
nil => nil
| (cons xs _) => (cons (length xss) (cons (length xs) nil))
end.
Definition lt_listlist (A:Set) (xss yss : list (list A)) :=
(wlt (m_listlist A xss) (m_listlist A yss)).
Parameter A:Set.
Program Fixpoint list_concat (xss : list (list A))
{wf (lt_listlist A) xss} : list A :=
match xss with
nil => nil
| (cons nil xss) => (list_concat xss)
| (cons (cons x xs) xss) => (cons x (list_concat (cons xs xss)))
end.
Obligation 1.
unfold lt_listlist. destruct xss.
simpl. apply wlt_nil.
simpl. apply wlt_lt_gen; auto with arith.
Qed.
Obligation 2.
unfold lt_listlist. simpl. apply wlt_wlt_gen.
auto.
apply wlt_lt_gen; auto with arith.
Qed.
Obligation 3.
by_Acc_mwlt lex_natxnat.
Defined.
(* Sur la longueur des listes *)
Definition mw_list (A:Set) (xs: list A) :=
(cons (length xs) nil).
Definition lt_len_list (A:Set) :=
(make_mwlt (list A) (mw_list A)).
Program Fixpoint bubble (xs:list nat) {wf (lt_len_list nat) xs} : list nat :=
match xs with
nil => nil
| (cons x nil) => (cons x nil)
| (cons x1 (cons x2 xs)) =>
if (ltb x1 x2) then (cons x1 (bubble (cons x2 xs)))
else (cons x2 (bubble (cons x1 xs)))
end.
Obligation 1.
unfold lt_len_list. unfold make_mwlt. unfold mw_list. simpl.
apply wlt_lt_gen; auto with arith.
Qed.
Obligation 2.
unfold lt_len_list. unfold make_mwlt. unfold mw_list. simpl.
apply wlt_lt_gen; auto with arith.
Qed.
Obligation 3.
by_Acc_mwlt lt_len_list.
Defined.
(* Le peigne *)
Inductive btree (A:Set) : Set :=
Empty : (btree A)
| Node : (btree A) -> A -> (btree A) -> (btree A).
Arguments Empty {A}.
Arguments Node [A] _ _ _.
Fixpoint btree_size (A:Set) (bt:btree A) :=
match bt with
Empty => 0
| (Node bt1 x bt2) => S (plus (btree_size A bt1) (btree_size A bt2))
end.
Definition m_btree (A:Set) (bt:btree A) :=
match bt with
Empty => nil
| (Node bt1 x bt2) => (cons (btree_size A bt) (cons (btree_size A bt1) nil))
end.
Definition lt_btree (A:Set) (bt1 bt2:btree A) :=
(wlt (m_btree A bt1) (m_btree A bt2)).
Program Fixpoint to_list (bt:btree A)
{wf (lt_btree A) bt} : list A :=
match bt with
Empty => nil
| (Node Empty x bt) => (cons x (to_list bt))
| (Node (Node bt1 x1 bt2) x2 bt3) => (to_list (Node bt1 x1 (Node bt2 x2 bt3)))
end.
Obligation 1.
unfold lt_btree. destruct bt.
simpl. apply wlt_nil.
simpl. apply wlt_lt_gen; auto with arith.
Qed.
Obligation 2.
unfold lt_btree. simpl. rewrite <-Nat.add_succ_comm. simpl.
rewrite Nat.add_assoc. apply wlt_wlt_gen.
auto.
apply wlt_lt_gen; auto with arith.
Qed.
Obligation 3.
by_Acc_mwlt lt_btree.
Defined.
(* Theory *)
Axiom g1 : nat -> nat.
Axiom g2 : nat -> nat -> nat.
Axiom g3 : nat -> nat -> nat.
Axiom g4 : nat -> nat -> nat.
Axiom g5 : nat -> nat -> nat -> nat.
Axiom g6 : nat -> nat -> nat -> nat.
Axiom g7 : nat -> nat -> nat -> nat.
Axiom h1 : nat -> nat -> nat -> nat.
Axiom h2 : nat -> nat -> nat -> nat.
Axiom h3 : nat -> nat -> nat -> nat -> nat -> nat.
Definition wm_nat3 (xyz:nat * nat * nat) :=
match xyz with
(0, y, 0) => nil
| (0, y, S z) => (cons (S z) nil)
| (S x, 0, z) => (cons (S x) (cons 0 nil))
| (S x, S y, z) => (cons (S x) (cons (S y) nil))
end.
Definition rlex_nat3 :=
(make_mwlt (nat * nat * nat) wm_nat3).
Program Fixpoint f (xyz : nat * nat * nat) {wf rlex_nat3 xyz} : nat :=
match xyz with
(0, y, 0) => (g1 y)
| (0, y, S z) => (h1 y z (f (0, (g2 y z), z)))
| (S x, 0, z) => (h2 x z (f (x, (g3 x z), (g4 x z))))
| (S x, S y, z) =>
(h3 x y z (f (x, (g5 x y z), (g6 x y z)))
(f (S x, y, (g7 x y z))))
end.
Lemma rlex_nat3_1 : forall (y z m : nat),
(rlex_nat3 (0, y, z) (0, m, S z)).
intros. unfold rlex_nat3. unfold make_mwlt. destruct z.
simpl. apply wlt_nil.
simpl. apply wlt_lt; auto with arith.
Qed.
Lemma rlex_nat3_2 : forall (x z m1 m2 : nat),
(rlex_nat3 (x, m1, m2) (S x, 0, z)).
unfold rlex_nat3. unfold make_mwlt. destruct x.
destruct m2.
simpl. apply wlt_nil.
simpl. apply wlt_len; auto with arith.
intros. destruct m1.
simpl. apply wlt_lt; auto with arith.
simpl. apply wlt_lt; auto with arith.
Qed.
Lemma rlex_nat3_3 : forall (x y z m1 m2 : nat),
(rlex_nat3 (x, m1, m2) (S x, S y, z)).
unfold rlex_nat3. unfold make_mwlt. destruct x.
intros. destruct m2.
simpl. apply wlt_nil.
simpl. apply wlt_len; auto with arith.
intros. destruct m1.
simpl. apply wlt_lt; auto with arith.
simpl. apply wlt_lt; auto with arith.
Qed.
Lemma rlex_nat3_4 : forall (x y z m : nat),
(rlex_nat3 (S x, y, m) (S x, S y, z)).
unfold rlex_nat3. unfold make_mwlt. destruct y.
intros. simpl. apply wlt_wlt.
auto with arith.
simpl. apply wlt_0_w. apply wlt_nil.
intros. simpl. apply wlt_wlt.
auto with arith.
apply wlt_lt; auto with arith.
Qed.
Obligation 1.
apply rlex_nat3_1.
Qed.
Obligation 2.
apply rlex_nat3_2.
Qed.
Obligation 3.
apply rlex_nat3_3.
Qed.
Obligation 4.
apply rlex_nat3_4.
Qed.
Obligation 5.
by_Acc_mwlt wm_nat3.
Defined.
(* Bootstrap *)
Parameter eqb : nat -> nat -> bool.
Program Fixpoint listordi (xsys : list nat * list nat) {wf (lex_listxlist nat) xsys} : bool :=
match xsys with
(_, nil) => false
| (xs, (cons 0 ys)) => (listordi (xs, ys))
| (nil, (cons (S y) ys)) => true
| ((cons 0 xs), (cons (S y) ys)) => (listordi (xs, (cons (S y) ys)))
| ((cons (S x) xs), (cons (S y) ys)) =>
(orb (ltb (length xs) (length ys))
(andb (eqb (length xs) (length ys))
(orb (ltb x y) (listordi (xs, ys)))))
end.
Obligation 1.
unfold lex_listxlist. unfold make_mwlt. simpl.
apply wlt_wlt_gen.
auto.
apply wlt_lt_gen; auto with arith.
Qed.
Obligation 2.
unfold lex_listxlist. unfold make_mwlt. simpl.
apply wlt_lt_gen; auto with arith.
Qed.
Obligation 3.
unfold lex_listxlist. unfold make_mwlt. simpl.
apply wlt_lt_gen; auto with arith.
Qed.
Obligation 4.
by_Acc_mwlt lex_natxnat.
Defined.
(* Dershowitz/Manna: "counting tips of binary trees" *)
Fixpoint list_btree_size (A:Set) (bts:list (btree A)) : nat :=
match bts with
nil => 0
| (cons bt bts) => (plus (btree_size A bt) (list_btree_size A bts))
end.
Definition wm_list_btree (A:Set) (bts:list (btree A)) : (list nat) :=
(cons (list_btree_size A bts) (cons (length bts) nil)).
Definition lt_list_btree (A:Set) :=
(make_mwlt (list (btree A)) (wm_list_btree A)).
Program Fixpoint count_tips (bts:(list (btree A)))
{wf (lt_list_btree A) bts} : nat :=
match bts with
nil => 0
| (cons Empty bts) => S (count_tips bts)
| (cons (Node bt1 x bt2) bts) => (count_tips (cons bt1 (cons bt2 bts)))
end.
Obligation 1.
unfold lt_list_btree. unfold make_mwlt. unfold wm_list_btree.
simpl. apply wlt_wlt_gen.
auto.
apply wlt_lt_gen; auto with arith.
Qed.
Obligation 2.
unfold lt_list_btree. unfold make_mwlt. unfold wm_list_btree.
apply wlt_lt_gen.
auto.
simpl. rewrite Nat.add_assoc. auto with arith.
Qed.
Obligation 3.
by_Acc_mwlt lt_list_btree.
Defined.
Print Assumptions count_tips.