-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathMultisetOrder.v
More file actions
1643 lines (1430 loc) · 50.7 KB
/
Copy pathMultisetOrder.v
File metadata and controls
1643 lines (1430 loc) · 50.7 KB
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
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(**
CoLoR, a Coq library on rewriting and termination.
See the COPYRIGHTS and LICENSE files.
- Adam Koprowski, 2004-09-06
- Solange Coupet-Grimal and William Delobel, 2005-09-19
Theory concerning extension of an relation to multisets is developed
in this file.
*)
Set Implicit Arguments.
From CoLoR Require RelUtil.
From Coq Require Import Transitive_Closure Compare_dec Relations Permutation
Setoid Morphisms Basics Lia.
From CoLoR Require Import RelExtras MultisetTheory ListPermutation MultisetCore
ListExtras AccUtil LogicUtil.
Declare Scope mord_scope.
Module MultisetOrder (MC: MultisetCore).
Module Import MSet := MultisetTheory.Multiset MC.
Section OrderDefinition.
Variable gtA : relation A.
Let ltA := transp gtA.
Let leA x y := ~gtA x y.
Let gtA_trans := clos_trans gtA.
Let geA x y := gtA x y \/ eqA x y.
Hint Unfold ltA leA gtA_trans : sets.
Notation "X >A Y" := (gtA X Y) (at level 50).
Notation "X <A Y" := (ltA X Y) (at level 50).
Notation "X <=A Y" := (leA X Y) (at level 50).
Notation "X >=A Y" := (geA X Y) (at level 50).
Notation "X >*A Y" := (gtA_trans X Y) (at level 50).
(* ------------------------------------------------------------------
Definition of multiset order
------------------------------------------------------------------ *)
(* MultisetRed expresses the ordering on multisets that can be
achieved in one step. *)
Inductive MultisetRedGt (A B: Multiset) : Prop :=
| MSetRed: forall X a Y,
A =mul= X + {{a}} ->
B =mul= X + Y ->
(forall y, y in Y -> a >A y) ->
MultisetRedGt A B.
(* Then multiset order is just a transitive closure of this
reduction *)
Definition MultisetGt := clos_trans MultisetRedGt.
(* Less than part of an order *)
Definition MultisetRedLt := transp MultisetRedGt.
Definition MultisetLt := transp MultisetGt.
(* Alternative definition of an order *)
Inductive MultisetGT (M N: Multiset) : Prop :=
| MSetGT: forall X Y Z,
X <>mul empty ->
M =mul= Z + X ->
N =mul= Z + Y ->
(forall y, y in Y -> (exists2 x, x in X & x >A y)) ->
MultisetGT M N.
Definition MultisetLT := transp MultisetGT.
Let AccA := Acc ltA.
Let AccM := Acc MultisetLt.
Let AccM_1 := Acc MultisetRedLt.
Let ACC_M := Acc MultisetLT.
Let clos_transM_RedGt := clos_trans MultisetRedGt.
Let clos_transM_RedLt := clos_trans MultisetRedLt.
(* ------------------------------------------------------------------
Notations
------------------------------------------------------------------ *)
Notation "X >mul Y" := (MultisetGt X Y) (at level 70) : mord_scope.
Notation "X >MUL Y" := (MultisetGT X Y) (at level 70) : mord_scope.
Notation "X <mul Y" := (MultisetLt X Y) (at level 70) : mord_scope.
Notation "X <MUL Y" := (MultisetLT X Y) (at level 70) : mord_scope.
Notation "X >mul_1 Y" := (MultisetRedGt X Y) (at level 70) : mord_scope.
Notation "X <mul_1 Y" := (MultisetRedLt X Y) (at level 70) : mord_scope.
Delimit Scope mord_scope with mord.
Open Scope mord_scope.
(* ------------------------------------------------------------------
Some morphisms
------------------------------------------------------------------ *)
Instance MultisetRedGt_morph : Proper (meq ==> meq ==> iff) MultisetRedGt.
Proof.
intros x1 x2 H x3 x4 H0. split; intros H1; inversion H1.
constructor 1 with X a Y; trivial. rewrite <- H; trivial.
rewrite <- H0; trivial.
constructor 1 with X a Y; trivial. rewrite H; trivial.
rewrite H0; trivial.
Qed.
Instance AccM_1_morph : Proper (meq ==> iff) AccM_1.
Proof.
intros; split; intro H0; inversion H0.
constructor; intros. apply H1; compute in *; rewrite H; trivial.
constructor; intros. apply H1; compute in *; rewrite <- H; trivial.
Qed.
Instance clos_transM_RedGt_morph :
Proper (meq ==> meq ==> iff) clos_transM_RedGt.
Proof.
intros a b ab c d cd. unfold clos_transM_RedGt.
refine (RelUtil.tc_prop_iff meq_Equivalence MultisetRedGt_morph a b ab c d cd).
Qed.
Instance clos_transM_RedLt_morph :
Proper (meq ==> meq ==> iff) clos_transM_RedLt.
Proof.
intros a b ab c d cd. unfold clos_transM_RedLt.
refine (RelUtil.tc_prop_iff meq_Equivalence _ a b ab c d cd).
reduce. unfold MultisetRedLt. unfold transp. rewrite H, H0. reflexivity.
Qed.
Instance MultisetGt_morph_equiv : Proper (meq ==> meq ==> iff) MultisetGt.
Proof.
intros x1 x2 H x0 x3 H0; split; intro; inversion H1.
constructor 1; rewrite <- H, <- H0; trivial.
constructor 2 with y; fold clos_transM_RedGt.
rewrite <- H; hyp. rewrite <- H0; hyp.
constructor 1; rewrite H, H0; trivial.
constructor 2 with y; fold clos_transM_RedGt.
rewrite H; hyp. rewrite H0; hyp.
Qed.
Instance MultisetGT_morph : Proper (meq ==> meq ==> iff) MultisetGT.
Proof.
intros xL xR H yL yR H0; split; intro; inversion H1.
constructor 1 with X Y Z. hyp.
rewrite <- H. hyp.
rewrite <- H0. hyp.
hyp.
constructor 1 with X Y Z. hyp.
rewrite H. hyp.
rewrite H0. hyp.
hyp.
Qed.
Lemma MultisetGt_morph : forall x1 x2 : Multiset, x1 =mul= x2 ->
forall x3 x4 : Multiset, x3 =mul= x4 -> x1 >mul x3 -> x2 >mul x4.
Proof.
intros. apply (proj1 (MultisetGt_morph_equiv H H0)). hyp.
Qed.
Instance AccM_morph : Proper (meq ==> iff) AccM.
Proof.
intros; split; intro; inversion H0.
unfold AccM; constructor; intros.
apply H1; compute; fold clos_transM_RedGt.
rewrite H; trivial.
unfold AccM; constructor; intros.
apply H1; compute; fold clos_transM_RedGt.
rewrite <- H; trivial.
Qed.
(* -----------------------------------------------------------------
Some additional properties needed for some lemmas
----------------------------------------------------------------- *)
Variable gtA_transitive : Transitive gtA.
Existing Instance gtA_transitive.
Variable gtA_irreflexive : RelUtil.irreflexive gtA.
Variable gtA_eqA_compat : Proper (eqA ==> eqA ==> impl) gtA.
Existing Instance gtA_eqA_compat.
Hint Resolve (gtA_transitive) : sets.
Hint Resolve (gtA_irreflexive) : sets.
Hint Resolve (so_not_symmetric
(Build_strict_order gtA_transitive gtA_irreflexive)) : sets.
Lemma gtA_eqA_compat' :
forall a b, eqA a b -> forall c d, eqA c d -> gtA a c -> gtA b d.
Proof. apply gtA_eqA_compat. Qed.
Hint Resolve gtA_eqA_compat' : sets.
Instance gtA_morph : Proper (eqA ==> eqA ==> iff) gtA.
Proof.
intros a b ab c d cd.
intuition. eapply gtA_eqA_compat. apply ab. apply cd. hyp.
eapply gtA_eqA_compat. apply Seq_sym. exact eqA_Equivalence. apply ab.
apply Seq_sym. exact eqA_Equivalence. apply cd. hyp.
Qed.
Instance ltA_morph : Proper (eqA ==> eqA ==> iff) ltA.
Proof. intros a b ab c d cd. unfold ltA, transp. apply gtA_morph; hyp. Qed.
Instance gtA_trans_morph : Proper (eqA ==> eqA ==> iff) gtA_trans.
Proof.
compute. intros a a' a_a' b b' b_b'.
refine (RelUtil.tc_prop_iff eqA_Equivalence gtA_morph a a' a_a' b b' b_b').
Qed.
Instance geA_morph : Proper (eqA ==> eqA ==> iff) geA.
Proof.
intros; split; intro; destruct H1.
left; rewrite <- H, <- H0; trivial.
right; rewrite <- H, <- H0; trivial.
left; rewrite H, H0; trivial.
right; rewrite H, H0; trivial.
Qed.
(* -----------------------------------------------------------------
Some conclusions following from the fact that ordering holds.
----------------------------------------------------------------- *)
Section OrderCharacterization.
Lemma lt_as_red: same_relation MultisetLt clos_transM_RedLt.
Proof. exact (RelUtil.tc_transp MultisetRedGt). Qed.
Lemma empty_min_red: forall M, ~(empty >mul_1 M).
Proof.
intros M empty_red_M; inversion empty_red_M.
apply not_empty with (X + {{a}}) a; auto with multisets.
Qed.
(* There is no multiset less than an empty one *)
Lemma empty_min: forall M, ~(empty >mul M).
Proof.
intros M empty_lt_M; case (RelUtil.tc_step_l empty_lt_M).
intro M_red_empty; apply empty_min_red with M; trivial.
intro step; destruct step; apply empty_min_red with x; trivial.
Qed.
Lemma mOrd_trans: forall M N P, M >MUL N -> N >MUL P -> M >MUL P.
Proof.
destruct 1 as [X1 Y1 Z1 X1_ne M1_def N1_def Ord1].
destruct 1 as [X2 Y2 Z2 X2_ne N2_def P2_def Ord2].
constructor 1 with (union X1 (diff X2 Y1))
(union Y2 (diff Y1 X2)) (intersection Z1 Z2).
(* 'X' not empty *)
auto with multisets.
(* left component ok *)
rewrite M1_def, (union_assoc (Z1#Z2) X1 (X2-Y1)),
(union_perm (Z1#Z2) X1 (X2-Y1)).
apply meq_meq_union.
apply double_split.
rewrite (union_comm Y1 Z1), (union_comm X2 Z2), <- N1_def, <- N2_def;
auto with multisets.
(* right component ok *)
rewrite P2_def, (union_assoc (Z1#Z2) Y2 (Y1-X2)),
(union_perm (Z1#Z2) Y2 (Y1-X2)).
apply meq_meq_union.
rewrite (intersection_comm Z1 Z2).
apply double_split.
rewrite (union_comm X2 Z2), (union_comm Y1 Z1), <- N1_def, <- N2_def;
auto with multisets.
(* order of elements ok *)
intros y y_in_union; case (member_union y_in_union); intro y_in.
(* *)
destruct (Ord2 y y_in) as [x x_in_X2 x_gt_y].
case (member_dec x Y1); intro x_in_Y1.
(* *)
destruct (Ord1 x x_in_Y1) as [x' x'_in_X1 x'_gt_x].
exists x'.
apply member_member_union; trivial.
eauto with sets.
(* *)
exists x.
rewrite (union_comm X1 (X2-Y1)); apply member_member_union.
unfold member in *; rewrite (diff_mult X2 Y1); lia.
trivial.
(* *)
destruct (Ord1 y).
eauto with multisets.
exists x.
auto with multisets.
trivial.
Qed.
Lemma gtA_comp: forall a, comp_eqA (gtA a).
Proof. intros a b c bc. apply gtA_morph. refl. hyp. Qed.
Lemma leA_comp: forall a, comp_eqA (leA a).
Proof.
intros a b c bc ab ca. apply ab. eapply gtA_morph. refl. apply bc. hyp.
Qed.
(* Begin addition by Solange Coupet-Grimal and William Delobel *)
Lemma acc_mord : forall M, AccM M -> (forall x, x in M -> AccA x).
Proof.
intros M acc_M.
induction acc_M as [M acc_M IHM].
intros x x_in_M.
constructor.
intros y y_less_x.
apply (IHM (M - {{x}} + {{y}})); auto with multisets.
constructor.
apply MSetRed with (X := M - {{x}}) (a := x) (Y := {{y}});
auto with multisets.
intros y0 Hy0.
gen (member_singleton Hy0); clear Hy0; intro Hy0.
eapply gtA_eqA_compat. refl. sym. apply Hy0. hyp.
Qed.
Lemma sub_transp_trans_2_mOrd_trans: forall P,
(forall p, p in P -> forall x y, x >A p -> y >A x -> y >A p) ->
forall M N, MultisetGT M N -> MultisetGT N P -> MultisetGT M P.
Proof.
intros P Hsub.
destruct 1 as [X1 Y1 Z1 X1_ne M1_def N1_def Ord1].
destruct 1 as [X2 Y2 Z2 X2_ne N2_def P2_def Ord2].
constructor 1 with (union X1 (diff X2 Y1))
(union Y2 (diff Y1 X2)) (intersection Z1 Z2).
(* 'X' not empty *)
auto with multisets.
(* left component ok *)
rewrite M1_def, (union_assoc (Z1#Z2) X1 (X2-Y1)),
(union_perm (Z1#Z2) X1 (X2-Y1)).
apply meq_meq_union.
apply double_split.
rewrite (union_comm Y1 Z1), (union_comm X2 Z2), <- N1_def, <- N2_def;
auto with multisets.
(* right component ok *)
rewrite P2_def, (union_assoc (Z1#Z2) Y2 (Y1-X2)),
(union_perm (Z1#Z2) Y2 (Y1-X2)).
apply meq_meq_union.
rewrite (intersection_comm Z1 Z2).
apply double_split.
rewrite (union_comm X2 Z2), (union_comm Y1 Z1), <- N1_def, <- N2_def;
auto with multisets.
(* order of elements ok *)
intros y y_in_union; case (member_union y_in_union); intro y_in.
(* *)
destruct (Ord2 y y_in) as [x x_in_X2 x_gt_y].
case (member_dec x Y1); intro x_in_Y1.
(* *)
destruct (Ord1 x x_in_Y1) as [x' x'_in_X1 x'_gt_x].
exists x'.
apply member_member_union; trivial.
cut (y in P); [intro y_in_P
| rewrite P2_def, (union_comm Z2 Y2); auto with multisets].
apply (Hsub y y_in_P x x'); trivial.
(* *)
exists x.
rewrite (union_comm X1 (X2-Y1)); apply member_member_union.
unfold member in *; rewrite (diff_mult X2 Y1); lia.
trivial.
(* *)
destruct (Ord1 y).
eauto with multisets.
exists x.
auto with multisets.
trivial.
Qed.
Lemma partition2 : forall Y X a,
(forall y, y in Y -> exists2 x : A, x in (X + {{a}}) & x >A y) ->
exists Ya, (exists2 Yx : Multiset,
Y =mul= Ya + Yx & (forall y, y in Ya -> a >A y)
/\ (forall y, y in Yx -> exists2 x, x in X & x >A y)).
Proof.
induction Y as [ | Y] using mset_ind.
intros; exists empty; exists empty.
solve_meq.
split; intros.
unfold member in H0; rewrite (empty_mult y) in H0; inversion H0.
unfold member in H0; rewrite (empty_mult y) in H0; inversion H0.
intros X a'; intros.
cut (forall y : A, y in Y -> exists2 x : A, x in (X + {{a'}}) & x >A y).
intro H'.
elim (IHY X a' H').
intros Ya HYa.
elim HYa; clear HYa; intros Yx HY HYx.
elim HYx; clear HYx; intros HYa HYx.
cut (a in (Y + {{a}})).
intro Ha; elim (H a Ha); intros x' Hx' Hx'2.
elim (member_union Hx'); intro case_x'.
(* x' in X : *)
exists Ya; exists (Yx + {{a}}).
rewrite HY.
auto with multisets.
split.
hyp.
intros y Hy.
elim (member_union Hy); intro case_y.
apply HYx; trivial.
exists x'; trivial.
generalize (member_singleton case_y) Hx'2; intro y_is_a.
apply gtA_eqA_compat; auto with multisets.
rewrite y_is_a; auto with multisets.
(* x' = a' : *)
exists (Ya + {{a}}); exists Yx.
rewrite HY.
solve_meq.
split.
intros y Hy.
elim (member_union Hy); intro case_y.
apply HYa; trivial.
gen Hx'2; apply gtA_eqA_compat.
apply (member_singleton case_x').
rewrite (member_singleton case_y); auto with multisets.
hyp.
rewrite (union_comm Y {{a}}).
apply member_member_union.
apply singleton_member.
intros y HY; apply H.
apply member_member_union; trivial.
Qed.
(* end of addition *)
Lemma direct_subset_red : forall M N, M >MUL N -> M >mul N.
Proof.
destruct 1.
generalize dependent Y.
generalize dependent Z.
generalize M N.
generalize dependent X.
induction X as [ | X] using mset_ind.
intros; absurd (empty <>mul empty); auto with multisets.
intros; case (empty_dec X).
(* X = empty *)
intro X_empty.
assert (X + {{a}} =mul= {{a}});
[ rewrite X_empty; eauto with multisets
| idtac].
constructor; constructor 1 with Z a Y.
solve_meq_ext.
trivial.
intros y yY; destruct (H2 y); trivial.
assert (x in {{a}}); [rewrite <- H3; trivial | idtac].
assert (x =A= a); [apply member_singleton; trivial | idtac].
rewrite <- H7; trivial.
(* X <> empty *)
intro X_nempty.
destruct (partition2 H2) as [Yg [Yl Ydec [Yg_ord Yl_ord]]].
constructor 2 with (Z + Yl + {{a}}).
(* Z + X + {{a}} >mul Z + Yl + {{a}} *)
apply IHX with (Z + {{a}}) Yl;
try solve [auto with multisets | solve_meq_ext].
(* Z + Yl + {{a}} >mul Z + Yl + Yg *)
constructor; constructor 1 with (Z + Yl) a Yg.
solve_meq_ext.
solve_meq_ext.
trivial.
Qed.
(* Be careful this equivalence holds only if >gtA is a strict order and
if >gtA is decidable *)
Lemma red_eq_direct : forall M N, M >mul N <-> M >MUL N.
Proof.
intros; split.
(* => *)
induction 1.
inversion H.
constructor 1 with {{a}} Y X; solve [ solve_meq_ext
| eauto with multisets ].
apply mOrd_trans with y; trivial.
(* <= *)
apply direct_subset_red.
Qed.
Lemma red_insert: forall M N a, N <mul_1 (M + {{a}}) -> exists M',
(N =mul= M' + {{a}} /\ M' <mul_1 M)
\/ (N =mul= M + M' /\ forall x, x in M' -> x <A a).
Proof.
intros; inversion H.
case (eqA_dec a a0); intro a_a0.
(* a = a0, order proved using inserted element *)
exists Y; right; split.
rewrite H1; setoid_replace X with M. auto with multisets.
apply meq_union_meq with {{a}}. rewrite <- a_a0 in H0.
auto with multisets.
intros; rewrite a_a0; apply (H2 x); trivial.
(* a <> a0, order proved with other element that inserted one *)
assert (a0_a: ~a0 =A= a); auto with sets.
exists (Y + (M - {{a0}})); left; split.
rewrite H1; setoid_replace X with (M - {{a0}} + {{a}}).
2: rewrite (meq_ins_ins (meq_sym H0)); auto with multisets.
2: try_solve_meq; case (eqA_dec x a); case (eqA_dec x a0);
intros; try_solve_meq_ext.
try_solve_meq.
constructor 1 with (M - {{a0}}) a0 Y; auto with multisets.
apply meq_ins_rem; eauto with multisets.
Qed.
Lemma noext_big: forall a M N, M >mul N ->
(forall m, m in M -> a >A m) -> (forall n, n in N -> a >A n).
Proof.
intros a m n MN; induction MN; intros.
(* induction base *)
inversion H.
assert (n in (X+Y)); [rewrite <- H3; trivial | idtac].
case (member_union H5); intro nIn.
apply H0.
rewrite H2; unfold insert; auto with multisets.
assert (a >A a0).
apply H0.
rewrite H2; auto with multisets.
assert (a0 >A n).
apply H4; auto with multisets.
eauto with sets.
(* induction step *)
apply IHMN2; trivial.
apply IHMN1; trivial.
Qed.
Lemma maxin_not_lt: forall M N, M >mul N ->
{x:A | x in N & (forall y, y in M -> x >A y)} -> False.
Proof.
intros M N MN cond; destruct cond.
absurd (x >A x); auto with sets.
apply (noext_big MN g m).
Qed.
Lemma mord_ext1_aux: forall a X Y, a in X -> a in Y ->
(forall y, y in Y -> (exists2 x, x in X & x >A y)) ->
(forall y, y in (Y - {{a}}) -> (exists2 x, x in (X - {{a}}) & x >A y)).
Proof.
intros; destruct (H1 y).
eauto with multisets.
case (eqA_dec a x); intro ax.
destruct (H1 a).
eauto with multisets.
exists x0; try apply mem_memrem; eauto with sets.
exists x; solve [apply mem_memrem; auto with sets | trivial].
Qed.
Lemma mord_ext1: forall M N a, M >mul N <-> M + {{a}} >mul N + {{a}}.
Proof.
intros; split; intros.
(* => *)
destruct (proj1 (red_eq_direct M N) H).
rewrite_rl (red_eq_direct (M + {{a}}) (N + {{a}})).
constructor 1 with X Y (insert a Z); solve [solve_meq_ext; auto].
(* <= *)
destruct (proj1 (red_eq_direct (M + {{a}}) (N + {{a}})) H).
rewrite_rl (red_eq_direct M N).
(* a in equal part of two multisets *)
case (member_dec a Z); intro a_Z.
constructor 1 with X Y (Z - {{a}}); solve
[ apply ins_meq_union; trivial
| auto].
(* a in parts that differ *)
assert (a_in_X: a in X).
apply member_meq_union with {{a}} M Z; auto with multisets.
rewrite (union_comm {{a}} M), (union_comm X Z); auto with multisets.
assert (a_in_Y: a in Y).
apply member_meq_union with {{a}} N Z; auto with multisets.
rewrite (union_comm {{a}} N), (union_comm Y Z); auto with multisets.
constructor 1 with (X - {{a}}) (Y - {{a}}) Z.
destruct (H3 a); [trivial | idtac].
apply member_notempty with x.
apply mem_memrem; eauto with sets.
rewrite (union_comm Z (X - {{a}})); eauto with multisets.
rewrite (union_comm Z (Y - {{a}})); eauto with multisets.
apply mord_ext1_aux; trivial.
Qed.
Lemma mord_ext_r: forall M N P, M >mul N <-> M + P >mul N + P.
Proof.
intros; induction P as [ | P] using mset_ind.
(* induction base *)
rewrite (union_empty M), (union_empty N); split; auto.
(* induction step *)
rewrite (union_assoc M P {{a}}), (union_assoc N P {{a}}).
split; intro ord.
rewrite_lr (mord_ext1 (M + P) (N + P) a).
rewrite_lr IHP; trivial.
rewrite_rl IHP.
rewrite_rl (mord_ext1 (M + P) (N + P) a); trivial.
Qed.
Lemma mord_ext_l M N P : M >mul N <-> union P M >mul union P N.
Proof. rewrite (union_comm P M), (union_comm P N). apply mord_ext_r. Qed.
End OrderCharacterization.
Hint Resolve empty_min empty_min_red : multisets.
(* -----------------------------------------------------------------
Multiset order being strict order
----------------------------------------------------------------- *)
Section MultisetOrder_StrictOrder.
(* Multiset order is irreflexible *)
Lemma mord_irreflex: forall M, ~ M >mul M.
Proof.
unfold not; intros M MgtM.
assert (M + empty >mul M + empty);
[ rewrite (union_empty M); trivial
| idtac].
absurd (empty >mul empty).
apply empty_min.
rewrite_rl (mord_ext_l empty empty M); trivial.
Qed.
(* ...it's also transitive *)
Lemma mord_trans: forall X Y Z, X >mul Y -> Y >mul Z -> X >mul Z.
Proof.
intros X Y Z oXY oYZ.
compute; constructor 2 with Y; trivial.
Qed.
(* Multiset reduction is irreflexible *)
Lemma mred_irreflex: forall M, ~M >mul_1 M.
Proof.
unfold not; intros.
absurd (M >mul M); [apply mord_irreflex | constructor; trivial].
Qed.
(* ...so it's a strict ordering *)
Lemma mord_sorder : strict_order MultisetGt.
Proof.
exact (Build_strict_order mord_trans mord_irreflex).
Qed.
End MultisetOrder_StrictOrder.
(* -----------------------------------------------------------------
Well foundedness of multiset order
----------------------------------------------------------------- *)
Section MultisetOrder_Wf.
Lemma mord_wf_1: forall a M0,
(forall b M, b <A a -> AccM_1 M -> AccM_1 (M + {{b}})) ->
AccM_1 M0 -> (forall M, M <mul_1 M0 -> AccM_1 (M + {{a}})) ->
AccM_1 (M0 + {{a}}).
Proof.
intros a M0 H1 H2 H3; constructor; intros N N_lt.
case (red_insert N_lt); intros; repeat destruct H; fold AccM_1; rewrite H.
apply H3; trivial.
clear H N_lt H3; induction x as [|M a0] using mset_ind.
setoid_replace (M0 + empty) with M0; auto with multisets.
setoid_replace (M0 + (M + {{a0}})) with ((M0 + M) + {{a0}}).
auto with multisets.
auto with multisets.
Qed.
Lemma mord_wf_2: forall a,
(forall b M, b <A a -> AccM_1 M -> AccM_1 (M + {{b}})) ->
forall M, AccM_1 M -> AccM_1 (M + {{a}}).
Proof.
unfold AccM_1; intros.
apply Acc_ind with (P := fun M => AccM_1 (M + {{a}}))
(R := MultisetRedLt).
intros x wfH wfH2; apply mord_wf_1; intros; unfold AccM_1.
apply H; trivial.
constructor; trivial.
apply wfH2; trivial.
trivial.
Qed.
Lemma mord_wf_3:
forall a, AccA a -> forall M, AccM_1 M -> AccM_1 (M + {{a}}).
Proof.
intros a a_wf.
apply Acc_ind with
(P := fun a => forall M, AccM_1 M -> AccM_1 (M + {{a}}))
(R := ltA); trivial.
intros; apply mord_wf_2; trivial.
intros; apply H0; trivial.
Qed.
Lemma mred_acc : forall M, (forall x, x in M -> AccA x) -> AccM_1 M.
Proof.
intros M wf_el.
induction M using mset_ind.
constructor; intros y y_lt; absurd (empty >mul_1 y);
auto with multisets.
apply mord_wf_3.
apply wf_el; auto with multisets.
apply IHM; intros; apply wf_el; auto with multisets.
Qed.
Lemma mred_wf : well_founded ltA -> well_founded MultisetRedLt.
Proof.
intro wf_lt; constructor; intros; apply mred_acc.
intros; exact (wf_lt x).
Qed.
Lemma mord_acc : forall M, (forall x, x in M -> AccA x) -> AccM M.
Proof.
intros; unfold AccM.
apply Acc_eq_rel with clos_transM_RedLt.
split.
apply (proj2 lt_as_red a b).
apply (proj1 lt_as_red a b).
unfold clos_transM_RedLt; apply Transitive_Closure.Acc_clos_trans.
apply mred_acc; trivial.
Qed.
Lemma mord_wf : well_founded ltA -> well_founded MultisetLt.
Proof.
intro wf_lt; constructor; intros; apply mord_acc.
intros; exact (wf_lt x).
Qed.
Lemma mord_acc_mOrd_acc : forall x, AccM x -> ACC_M x.
Proof.
intros.
unfold ACC_M.
apply Acc_homo with Multiset MultisetLt (fun x y : Multiset => x = y) x;
trivial.
intros.
exists y; trivial.
unfold MultisetLt, transp; simpl.
apply direct_subset_red.
rewrite H0; trivial.
Qed.
Lemma mOrd_acc : forall M, (forall x, x in M -> AccA x) -> ACC_M M.
Proof.
intros.
apply mord_acc_mOrd_acc.
apply mord_acc; trivial.
Qed.
Lemma mOrd_wf : well_founded ltA -> well_founded MultisetLT.
Proof.
intro wf_lt; constructor; intros; apply mOrd_acc.
intros; exact (wf_lt x).
Qed.
End MultisetOrder_Wf.
(* -----------------------------------------------------------------
Additional facts about multiset order
----------------------------------------------------------------- *)
Section OrderLemmas.
Variables M N : Multiset.
Lemma mord_meq_compat mA mA' mB mB' :
mA =mul= mA' -> mB =mul= mB' -> mA >mul mB -> mA' >mul mB'.
Proof. intros. rewrite <- H, <- H0; trivial. Qed.
Lemma mOrd_elts_ge : M >MUL N ->
(forall n, n in N -> exists2 m, m in M & m >=A n).
Proof.
intros.
destruct H as [X Y Z Xne MZX NZY Cond].
assert (nn: n =A= n); auto with sets.
set (nZY := proj1 (member_morph nn NZY) H0).
destruct (member_union nZY).
(* n in equal part *)
exists n.
rewrite MZX.
apply member_member_union; trivial.
right; trivial.
(* n in strict part *)
destruct (Cond n H) as [m mX mn].
exists m.
rewrite MZX, (union_comm Z X).
apply member_member_union; trivial.
left; trivial.
Qed.
Lemma mord_elts_ge: M >mul N -> forall n, n in N ->
exists2 m, m in M & m >*A n \/ m =A= n.
Proof.
(* induction on number of steps needed to show the ordering *)
induction 1 as [M N M_N | M N P M_N IH_MN N_P IH_NP];
intros n n_in_N.
(* order in one step *)
destruct M_N as [X a Y Mdef Ndef Ya_ord].
cut (n in N); [rewrite Ndef | trivial].
intros n_in_XY; destruct (member_union n_in_XY) as [n_in_X | n_in_Y].
exists n.
rewrite Mdef; auto with multisets.
right; auto with sets.
exists a.
rewrite Mdef; auto with multisets.
left; constructor; auto with sets.
(* order in many steps *)
destruct (IH_NP n n_in_N) as [np np_in_N np_ge_n].
destruct (IH_MN np np_in_N) as [mp mp_in_M mp_ge_n].
exists mp.
trivial.
destruct np_ge_n as [np_gt_n | np_n].
destruct mp_ge_n as [mp_gt_n | mp_n].
left; constructor 2 with np; trivial.
left; rewrite mp_n; trivial.
rewrite <- np_n; trivial.
Qed.
End OrderLemmas.
Section MOrdPair.
Variables aL aR bL bR : A.
Lemma pair_mord_left :
aL >A aR -> bL >=A bR -> {{ aL, bL }} >mul {{ aR, bR }}.
Proof.
intros; destruct H0.
constructor 2 with {{aR, bL}}.
constructor; constructor 1 with {{bL}} aL {{aR}}; intros;
eauto with multisets.
assert (xAr: y =A= aR); [apply member_singleton | rewrite xAr];
trivial.
constructor; constructor 1 with {{aR}} bL {{bR}}; intros;
eauto with multisets.
assert (xAr: y =A= bR); [apply member_singleton | rewrite xAr];
trivial.
rewrite H0.
constructor; constructor 1 with {{bR}} aL {{aR}}; intros;
eauto with multisets.
assert (xAr: y =A= aR); [apply member_singleton | rewrite xAr];
trivial.
Qed.
Lemma pair_mord_right :
aL >=A aR -> bL >A bR -> {{ aL, bL }} >mul {{ aR, bR }}.
Proof.
intros; destruct H.
constructor 2 with {{aR, bL}}.
constructor; constructor 1 with {{bL}} aL {{aR}}; intros;
eauto with multisets.
assert (xAr: y =A= aR); [apply member_singleton | rewrite xAr];
trivial.
constructor; constructor 1 with {{aR}} bL {{bR}}; intros;
eauto with multisets.
assert (xAr: y =A= bR); [apply member_singleton | rewrite xAr];
trivial.
rewrite H.
constructor; constructor 1 with {{aR}} bL {{bR}}; intros;
eauto with multisets.
assert (xAr: y =A= bR); [apply member_singleton | rewrite xAr];
trivial.
Qed.
Lemma pair_mOrd : {{ aL, bL }} >MUL {{ aR, bR }} ->
(aL >=A aR /\ aL >=A bR /\ (aL >A aR \/ aL >A bR)) \/
(bL >=A aR /\ bL >=A bR /\ (bL >A aR \/ bL >A bR)) \/
(aL >=A aR /\ bL >=A bR /\ (aL >A aR \/ bL >A bR)) \/
(bL >=A aR /\ aL >=A bR /\ (bL >A aR \/ aL >A bR)).
Proof.
intros.
inversion H.
destruct (pair_decomp H1)
as [[ZaLbL Xempty] | [[Zempty XaLbL] | [[ZaL XbL] | [ZbL XaL]]]].
(* {aL, bL}, {} *)
absurd (X =mul= empty); trivial.
(* {}, {aL, bL} *)
assert (Y =mul= {{aR, bR}}).
rewrite H2, Zempty; solve_meq.
destruct (H3 aR).
rewrite H4; mset_unfold.
apply member_union_l; auto with multisets.
assert (x in {{aL, bL}}).
rewrite <- XaLbL; trivial.
destruct (H3 bR).
rewrite H4; mset_unfold.
apply member_union_r; auto with multisets.
assert (x0 in {{aL, bL}}).
rewrite <- XaLbL; trivial.
destruct (member_pair H7); destruct (member_pair H10).
left; repeat split; rewrite <- H11; try solve [left; trivial].
left; rewrite H11, <- H12; trivial.
right; right; left; repeat split;
try rewrite <- H11; try rewrite <- H12; try solve [left; trivial].
right; right; right; repeat split;
try rewrite <- H11; try rewrite <- H12; try solve [left; trivial].
right; left; repeat split; rewrite <- H11; try solve [left; trivial].
left; rewrite H11, <- H12; trivial.
(* {aL}, {bL} *)
destruct (eqA_dec aL aR).
assert (Y =mul= {{bR}}).
setoid_replace Y with (Z + Y - Z).
rewrite <- (meq_diff_meq Z H2), ZaL, e.
solve_meq.
solve_meq.
destruct (H3 bR).
rewrite H4; auto with multisets.
assert (bL >A bR).
setoid_replace bL with x; trivial.
apply Seq_sym. exact eqA_Equivalence. apply member_singleton.
rewrite <- XbL; trivial.
right; right; left; repeat split.
right; trivial.
left; trivial.
right; trivial.
destruct (eqA_dec aL bR).
assert (Y =mul= {{aR}}).
setoid_replace Y with (Z + Y - Z).
rewrite <- (meq_diff_meq Z H2), ZaL, e.
solve_meq.
solve_meq.
destruct (H3 aR).
rewrite H4; auto with multisets.
assert (bL >A aR).
setoid_replace bL with x; trivial.
apply Seq_sym. exact eqA_Equivalence. apply member_singleton.
rewrite <- XbL; trivial.
right; right; right; repeat split.
left; trivial.
right; trivial.
left; trivial.
absurd (mult aL {{aR, bR}} = mult aL (Z + Y)).
mset_unfold; rewrite !union_mult, !singleton_mult_notin; trivial.
assert (aL in Z).
rewrite ZaL; auto with multisets.
unfold member in H4; lia.
apply meq_multeq; trivial.
(* {bL}, {aL} *)
destruct (eqA_dec bL aR).
assert (Y =mul= {{bR}}).
setoid_replace Y with (Z + Y - Z).
rewrite <- (meq_diff_meq Z H2), ZbL, e.
solve_meq.
solve_meq.
destruct (H3 bR).
rewrite H4; auto with multisets.
assert (aL >A bR).
setoid_replace aL with x; trivial.
apply Seq_sym. exact eqA_Equivalence. apply member_singleton.
rewrite <- XaL; trivial.
right; right; right; repeat split.
right; trivial.
left; trivial.
right; trivial.
destruct (eqA_dec bL bR).
assert (Y =mul= {{aR}}).
setoid_replace Y with (Z + Y - Z).
rewrite <- (meq_diff_meq Z H2), ZbL, e.
solve_meq.
solve_meq.