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
|
From stdpp Require Import numbers option sorting ssreflect.
From stdpp Require Import options.
From routemon Require Import util.
Definition timestamp := Z.
Variant limit :=
| NegInftyLimit
| TsLimit (x : timestamp)
| PosInftyLimit.
Instance limit_eq_dec : EqDecision limit.
Proof. solve_decision. Qed.
Notation "-∞" := NegInftyLimit.
Notation "+∞" := PosInftyLimit.
Coercion TsLimit : timestamp >-> limit.
(* The interval [start, end). Considered empty when start >= end. *)
Record period :=
Period
{ period_start : limit
; period_end : limit
}.
Notation "'[' s ',' e ')'" := (Period s e).
(* Consider making an inductive variant of these? *)
Definition limit_le (l1 l2 : limit) :=
match l1, l2 with
| -∞, _ | _, +∞ => True
| TsLimit t1, TsLimit t2 => (t1 ≤ t2)%Z
| _, _ => False
end.
Arguments limit_le !_ !_ / : assert.
Definition limit_lt l1 l2 :=
match l1 with
| -∞ =>
match l2 with
| -∞ => False
| _ => True
end
| TsLimit t1 =>
match l2 with
| -∞ => False
| TsLimit t2 => (t1 < t2)%Z
| +∞ => True
end
| +∞ => False
end.
Arguments limit_lt !_ !_ / : assert.
Instance limit_le_dec : RelDecision limit_le.
Proof. intros [] []; simpl; solve_decision. Qed.
Instance limit_lt_dec : RelDecision limit_lt.
Proof. intros [] []; simpl; solve_decision. Qed.
Instance limit_lt_pi l1 l2 : ProofIrrel (limit_lt l1 l2).
Proof. destruct l1, l2; apply _. Qed.
Instance relation_equiv {A} : Equiv (relation A) :=
λ R1 R2, ∀ x y, R1 x y ↔ R2 x y.
Lemma strict_limit_le_limit_lt :
strict limit_le ≡ limit_lt.
Proof.
split.
- intros []. destruct x, y; simpl in *; try done. lia.
- intros H. destruct x, y; unfold strict; simpl in *; try done; auto with lia.
Qed.
Instance : Reflexive limit_le.
Proof. intros l. by destruct l; simpl. Qed.
Instance : Transitive limit_le.
Proof. intros [] [] []; simpl; try done. lia. Qed.
Instance : PreOrder limit_le.
Proof. constructor; apply _. Qed.
Instance : AntiSymm (=) limit_le.
Proof.
intros [] []; simpl; try done.
intros H1 H2. f_equal. by apply Z.le_antisymm.
Qed.
Instance : PartialOrder limit_le.
Proof. constructor; apply _. Qed.
Instance : Trichotomy (strict limit_le).
Proof with auto with lia.
intros [] []; unfold strict; simpl...
destruct (Z.lt_trichotomy x x0) as [H|[->|H]]...
Qed.
Instance : TotalOrder limit_le.
Proof. constructor; apply _. Qed.
Instance : StrictOrder (strict limit_le) := _.
(* TODO: apparently useless??
Instance rel_equiv_proper {A} (x y : A) : Proper ((≡) ==> (↔)) (λ R, R x y).
Proof. easy. Qed.
Search Proper iff eq.
*)
Instance complement_equiv {A} : Proper ((≡) ==> (≡)) (@complement A).
Proof. intros R1 R2 HR12. split; unfold complement; intros Hequiv []%HR12%Hequiv. Qed.
Instance Reflexive_equiv {A} : Proper ((≡) ==> (↔)) (@Reflexive A).
Proof.
intros R1 R2 Hequiv. unfold Reflexive.
split; intros H x; by apply Hequiv.
Qed.
Instance Irreflexive_equiv {A} : Proper ((≡) ==> (↔)) (@Irreflexive A).
Proof. unfold Irreflexive. by intros R1 R2 ->. Qed.
Instance Transitive_equiv {A} : Proper ((≡) ==> (↔)) (@Transitive A).
Proof.
intros R1 R2 Hequiv. unfold Transitive.
by split; intros H x y z Hxy%Hequiv Hyz%Hequiv; eapply Hequiv, H.
Qed.
Instance StrictOrder_equiv {A} : Proper ((≡) ==> (↔)) (@StrictOrder A).
Proof.
intros R1 R2 Hequiv. split; intros [Hirr Htrans].
- by rewrite ->Hequiv in Hirr, Htrans.
- by rewrite <-Hequiv in Hirr, Htrans.
Qed.
Instance Trichotomy_equiv {A} : Proper ((≡) ==> (↔)) (@Trichotomy A).
Proof.
intros R1 R2 Hequiv. split; intros.
- intros x y. by rewrite -(Hequiv x y) -(Hequiv y x).
- intros x y. by rewrite (Hequiv x y) (Hequiv y x).
Qed.
Instance : StrictOrder limit_lt.
Proof. rewrite -strict_limit_le_limit_lt. apply _. Qed.
Instance : Trichotomy limit_lt.
Proof. rewrite -strict_limit_le_limit_lt. apply _. Qed.
Definition limit_lt_ts' (l : limit) (t2 : timestamp) :=
match l with
| -∞ => True
| TsLimit t1 => (t1 < t2)%Z
| +∞ => False
end.
Definition ts_le_limit' (t1 : timestamp) (l : limit) :=
match l with
| -∞ => False
| TsLimit t2 => (t1 ≤ t2)%Z
| +∞ => True
end.
Lemma limit_lt_limit_lt_ts' l t2 : limit_lt_ts' l t2 ↔ limit_lt l t2.
Proof. by destruct l. Qed.
Lemma ts_le_limit'_limit_le t1 l : ts_le_limit' t1 l ↔ limit_le t1 l.
Proof. by destruct l. Qed.
Declare Scope limit_scope.
Delimit Scope limit_scope with lim.
Notation "l1 < l2" := (limit_lt l1 l2) : limit_scope.
Notation "l1 ≤ l2" := (limit_le l1 l2) : limit_scope.
Notation "l1 < l2 < l3" := (l1 < l2 ∧ l2 < l3)%lim : limit_scope.
Notation "l1 ≤ l2 < l3" := (l1 ≤ l2 ∧ l2 < l3)%lim : limit_scope.
Notation "l1 < l2 ≤ l3" := (l1 < l2 ∧ l2 ≤ l3)%lim : limit_scope.
Notation "l1 ≤ l2 ≤ l3" := (l1 ≤ l2 ∧ l2 ≤ l3)%lim : limit_scope.
Open Scope limit_scope.
Instance period_elem_of : ElemOf timestamp period :=
λ t '[s, e), (s ≤ t < e).
Instance period_elem_of_dec t (p : period) : Decision (t ∈ p).
Proof. destruct p as [s e]. apply _. Qed.
Lemma limit_le_lt l1 l2 : l1 < l2 ↔ l1 ≤ l2 ∧ l1 ≠ l2.
Proof. by rewrite -(strict_limit_le_limit_lt l1 l2) strict_spec_alt. Qed.
Lemma limit_le_cases {l1 l2} : l1 ≤ l2 ↔ l1 = l2 ∨ l1 < l2.
Proof.
rewrite -(strict_limit_le_limit_lt l1 l2) strict_spec_alt. split.
- intros Hl12. destruct (decide (l1 = l2)) as [<-|Hne]; tauto.
- by intros [<-|[Hl12 _]].
Qed.
Lemma limit_lt_le_lt {l1} l2 {l3} : l1 ≤ l2 < l3 → l1 < l3.
Proof. by intros [[<-|?]%limit_le_cases ?]; last etrans. Qed.
Definition period_empty '[s, e) := e ≤ s.
Definition period_empty_alt (p : period) := ∀ t, t ∉ p.
Lemma period_empty_alt_iff p : period_empty p ↔ period_empty_alt p.
Proof.
destruct p as [s e].
rewrite /period_empty /period_empty_alt /=.
split; intros H.
- intros t [contra []]%limit_lt_le_lt%limit_le_lt.
by eapply (anti_symm limit_le).
- destruct s as [|s|], e as [|e|]; try done.
+ exfalso. apply (H (Z.pred e)). rewrite /elem_of /period_elem_of /=. lia.
+ exfalso. by apply (H 0%Z).
+ rewrite /elem_of /period_elem_of /= in H.
specialize (H s). simpl. lia.
+ exfalso. apply (H s). rewrite /elem_of /period_elem_of /=. lia.
Qed.
Instance period_empty_dec p : Decision (period_empty p).
Proof. destruct p as [s e]. solve_decision. Qed.
Definition period_nonempty '[s, e) := s < e.
Instance period_nonempty_dec p : Decision (period_nonempty p).
Proof. destruct p. apply _. Qed.
Instance period_nonempty_pi p : ProofIrrel (period_nonempty p).
Proof. destruct p. apply _. Qed.
Instance period_equiv : Equiv period :=
λ p1 p2, ∀ t, t ∈ p1 ↔ t ∈ p2.
Instance period_equiv_reflexive : Reflexive period_equiv.
Proof. done. Qed.
Instance period_equiv_trans : Transitive period_equiv.
Proof. intros p1 p2 p3 H1 H2 t. by rewrite H1. Qed.
Instance period_equiv_symm : Symmetric period_equiv.
Proof. by intros p1 p2 H t. Qed.
Instance period_equiv_equiv : Equivalence period_equiv.
Proof. constructor; apply _. Qed.
(* All empty periods are equivalent *)
Lemma period_empty_equiv p1 p2 : period_empty p1 → period_empty p2 ↔ p1 ≡ p2.
Proof.
intros Hp1%period_empty_alt_iff. split.
- intros Hp2%period_empty_alt_iff. intros t.
split; [intros []%(Hp1 _) | intros []%(Hp2 _)].
- intros Hequiv. apply period_empty_alt_iff.
intros t []%Hequiv%(Hp1 _).
Qed.
Instance empty_period : Empty period := [TsLimit 0%Z, TsLimit 0%Z).
Definition empty_period_empty : period_empty empty_period.
Proof. done. Qed.
Definition limit_min (l1 l2 : limit) := if decide (l1 ≤ l2) then l1 else l2.
Definition limit_max (l1 l2 : limit) := if decide (l1 ≤ l2) then l2 else l1.
Notation "l1 '`min`' l2" := (limit_min l1 l2) : limit_scope.
Notation "l1 '`max`' l2" := (limit_max l1 l2) : limit_scope.
Definition limit_min_ts (t1 t2 : timestamp) :
t1 `min` t2 = TsLimit (t1 `min` t2)%Z.
Proof.
unfold limit_min.
destruct (decide (t1 ≤ t2));
simpl in *; f_equal; lia.
Qed.
Definition limit_max_ts (t1 t2 : timestamp) :
t1 `max` t2 = TsLimit (t1 `max` t2)%Z.
Proof.
unfold limit_max.
destruct (decide (t1 ≤ t2));
simpl in *; f_equal; lia.
Qed.
Instance period_intersection : Intersection period := λ '[s1, e1) '[s2, e2),
[ s1 `max` s2, e1 `min` e2 ).
Lemma intersect_and (p1 p2 : period) t :
t ∈ (p1 ∩ p2) ↔ t ∈ p1 ∧ t ∈ p2.
Proof.
(* It really should be possible to optimize this proof somehow. *)
destruct p1 as [[|s1|] [|e1|]], p2 as [[|s2|] [|e2|]];
rewrite /intersection /period_intersection /elem_of /period_elem_of /limit_min /limit_max /limit_le /limit_lt /=;
repeat case_decide; tauto || lia.
Qed.
(* The points in time given by p1 except those given by p2, given as a before/after pair. *)
Definition except '[s1, e1) '[s2, e2) : period * period :=
( [ s1, e1 `min` s2 ),
[ s1 `max` e2, e1 ) ).
Lemma limit_lt_ne l1 l2 : l1 < l2 → l1 ≠ l2.
Proof. rewrite -(strict_limit_le_limit_lt l1 l2) strict_spec_alt. easy. Qed.
Lemma not_limit_le l1 l2 : ¬ (l1 ≤ l2) ↔ l2 < l1.
Proof.
destruct (trichotomy limit_lt l1 l2) as [Hl12|[<-|Hl21]].
- split; intros H.
+ exfalso. apply H, limit_le_cases. by right.
+ exfalso. by eapply asymmetry.
- split; intros H.
+ exfalso. apply H, limit_le_cases. by left.
+ by apply (_ : Irreflexive limit_lt) in H.
- split; intros H; first done.
intros [<-|Hl12]%limit_le_cases.
+ by apply (_ : Irreflexive limit_lt) in H.
+ by eapply asymmetry.
Qed.
Lemma not_limit_le' : complement limit_le ≡ flip limit_lt.
Proof. apply: not_limit_le. Qed.
Instance relation_equiv_reflexive {A} : Reflexive (@relation_equiv A).
Proof. done. Qed.
Instance relation_equiv_trans {A} : Transitive (@relation_equiv A).
Proof. intros R1 R2 R3 H12 H23 x y. by rewrite H12 -H23. Qed.
Instance relation_equiv_symm {A} : Symmetric (@relation_equiv A).
Proof. by intros R1 R2 H12 x y. Qed.
Instance relation_equiv_equiv {A} : Equivalence (@relation_equiv A).
Proof. constructor; apply _. Qed.
Lemma relation_flip_equiv {A} : Proper ((≡@{relation A}) ==> (≡)) flip.
Proof. intros R1 R2 H12 x y. simpl. by rewrite (H12 y x). Qed.
(* Could also be more generic *)
Lemma relation_flip_involutive {A} (R : relation A) : flip (flip R) ≡ R.
Proof. done. Qed.
Lemma complement_involutive {A} `{!RelDecision (R : relation A)} : complement (complement R) ≡ R.
Proof.
intros x y. split; intros Hxy.
- by destruct (decide (R x y)).
- by apply.
Qed.
Lemma not_limit_lt' : complement limit_lt ≡ flip limit_le.
Proof.
rewrite -(relation_flip_involutive limit_lt) complement_inverse.
trans (flip (complement (complement limit_le))).
{ apply relation_flip_equiv, complement_equiv, symmetry, not_limit_le'. }
apply relation_flip_equiv, complement_involutive.
Qed.
Lemma not_limit_lt l1 l2 : ¬ (l1 < l2) ↔ l2 ≤ l1.
Proof. apply not_limit_lt'. Qed.
(* TODO: make conclusion positive? *)
Lemma period_nonempty_equiv_L_1 (s1 e1 s2 e2 : limit) :
period_nonempty [s1, e1) →
period_nonempty [s2, e2) →
[s1, e1) ≡ [s2, e2) →
¬ s1 < s2.
Proof.
unfold period_nonempty.
intros Hne1 Hne2 Hequiv Hs12.
destruct s2 as [|s2|]; [by destruct s1|..|by destruct s1].
destruct s1 as [|s1|]; last done.
* assert (Hs2a : s2 ∈ [s2, e2)).
{ unfold elem_of, period_elem_of. by destruct e2. }
pose proof (proj2 (Hequiv s2) Hs2a) as [_ Hs2b].
assert (Hs2c : Z.pred s2 ∈ [-∞, e1)).
{ unfold elem_of, period_elem_of.
by destruct e1 as [|e1|]; [|simpl in *; lia|]. }
pose proof (proj1 (Hequiv (Z.pred s2)) Hs2c) as [contra _].
simpl in contra. lia.
* assert (Hs1 : s1 ∈ [s1, e1)).
{ unfold elem_of, period_elem_of. by destruct e1. }
pose proof (proj1 (Hequiv s1) Hs1) as [[Heq|Heq]%limit_le_cases _].
{ rewrite Heq in Hs12. by eapply (_ : Irreflexive limit_lt). }
by eapply asymmetry.
Qed.
(* TODO: make conclusion positive? *)
Lemma period_nonempty_equiv_L_2 (s1 e1 s2 e2 : limit) :
period_nonempty [s1, e1) →
period_nonempty [s2, e2) →
[s1, e1) ≡ [s2, e2) →
¬ e1 < e2.
Proof.
intros Hne1 Hne2 Hequiv He12.
destruct e1 as [|e1|]; [by destruct s1|..|done].
destruct e2 as [|e2|]; first done.
* (* e2 - 1 ∈ [s2, e2) → e2 - 1 ∈ [s1, e1) → s1 ≤ e2 - 1 < e1 → e2 ≤ e1 → e2 = e1 ∨ e2 < e1 *)
assert (He2a : Z.pred e2 ∈ [s2, e2)).
{ unfold elem_of, period_elem_of.
by destruct s2 as [|s2|]; [simpl in *; lia..|]. }
pose proof (proj2 (Hequiv (Z.pred e2)) He2a) as [_ He2b].
simpl in *. lia.
* (* We want to plug e1 into the right side to get a
contradiction, so we need s2 ≤ e1. It suffices to show that
s2 ≤ e1 - 1 *)
assert (He1a : Z.pred e1 ∈ [s1, e1)).
{ unfold elem_of, period_elem_of.
by destruct s1 as [|s1|]; [simpl in *; lia..|]. }
pose proof (proj1 (Hequiv (Z.pred e1)) He1a) as [He1b _].
assert (He1c : e1 ∈ [s2, +∞)).
{ unfold elem_of, period_elem_of.
by destruct s2 as [|s2|]; [|simpl in *; lia|]. }
pose proof (proj2 (Hequiv e1) He1c) as [_ []%(_ : Irreflexive limit_lt)].
Qed.
Lemma period_nonempty_equiv_L p1 p2 :
period_nonempty p1 →
period_nonempty p2 →
p1 ≡ p2 → p1 = p2.
Proof.
destruct p1 as [s1 e1], p2 as [s2 e2].
unfold equiv, period_equiv.
intros Hne1 Hne2 Hequiv.
f_equal.
- destruct (decide (s1 < s2)) as [Hs12|[<-|Hs21]%not_limit_lt%limit_le_cases]; [|done|].
+ exfalso. by apply (period_nonempty_equiv_L_1 s1 e1 s2 e2).
+ exfalso. by apply (period_nonempty_equiv_L_1 s2 e2 s1 e1).
- destruct (decide (e1 < e2)) as [He12|[<-|He21]%not_limit_lt%limit_le_cases]; [|done|].
+ exfalso. by apply (period_nonempty_equiv_L_2 s1 e1 s2 e2).
+ exfalso. by apply (period_nonempty_equiv_L_2 s2 e2 s1 e1).
Qed.
Definition period_empty_not_nonempty p : ¬ period_empty p ↔ period_nonempty p.
Proof. destruct p. apply not_limit_le. Qed.
Lemma limit_lt_min l1 l2 l3 :
l1 < l2 ∧ l1 < l3 ↔ l1 < l2 `min` l3.
Proof.
split.
- intros [Hl12 Hl13]. unfold limit_min. by case_decide.
- unfold limit_min. intros H. case_decide.
+ split; first done.
apply limit_le_cases in H0 as [<-|H0]; first done.
by etrans.
+ apply not_limit_le in H0.
by split; first etrans.
Qed.
Lemma limit_max_le l1 l2 l3 :
l1 ≤ l3 ∧ l2 ≤ l3 ↔ l1 `max` l2 ≤ l3.
Proof.
split.
- intros [Hl12 Hl23]. unfold limit_max. by case_decide.
- unfold limit_max. intros H. case_decide.
+ by split; first etrans.
+ apply not_limit_le in H0. split; first done.
apply limit_le_lt in H0 as [H0 _]. by etrans.
Qed.
Lemma limit_le_max l1 l2 l3 :
l1 ≤ l2 `max` l3 ↔ l1 ≤ l2 ∨ l1 ≤ l3.
Proof.
unfold limit_max.
destruct (decide (l2 ≤ l3)) as [Hl23|Hl23%not_limit_le].
- split; first tauto. intros [H|H]; last done. by etrans.
- split; first tauto. intros [H|H]; first done.
by trans l3; last (apply limit_le_cases; right).
Qed.
Lemma except_lem p1 p2 t :
t ∈ p1 ∧ t ∉ p2 ↔
t ∈ (except p1 p2).1 ∨ t ∈ (except p1 p2).2.
Proof.
destruct p1 as [s1 e1], p2 as [s2 e2]. split.
- intros [Hp1 Hp2].
(* on the left if t < s2, on the right if e2 ≤ t *)
destruct (decide (t < s2)) as [Hts2|Hts2].
+ (* t < s2 *)
left. simpl. split.
* apply Hp1.
* apply limit_lt_min. split; last done.
rewrite /elem_of /period_elem_of in Hp1. easy.
+ (* ¬ (t < s2) (↔ s2 ≤ t) *)
apply not_limit_lt in Hts2.
right. simpl. split.
* apply limit_max_le. split.
-- apply Hp1.
-- apply not_limit_lt. intros contra. by apply Hp2.
* apply Hp1.
- intros [H|H]; simpl in *.
+ split.
* unfold elem_of, period_elem_of in *. split.
-- apply H.
-- by destruct H as [_ [H _]%limit_lt_min].
* unfold elem_of, period_elem_of in *.
destruct H as [H1 [H2 H3]%limit_lt_min].
intros [Hc1 Hc2].
apply limit_le_cases in Hc1 as [Hc1|Hc1].
-- inv Hc1. by apply (_ : Irreflexive limit_lt) in H3.
-- eapply asymmetry; [apply H3 | apply Hc1].
+ unfold elem_of, period_elem_of in H.
rewrite -limit_max_le in H. destruct H as [[H1 H2] H3].
split; first done.
intros [Hc1 Hc2].
apply limit_le_cases in H2 as [H2|H2].
-- inv H2. by apply (_ : Irreflexive limit_lt) in Hc2.
-- eapply asymmetry; [apply H2 | apply Hc2].
Qed.
Lemma limit_max_lt l1 l2 l3 :
l1 `max` l2 < l3 ↔ l1 < l3 ∧ l2 < l3.
Proof.
unfold limit_max.
destruct (decide (l1 ≤ l2)) as [Hl12|Hl12%not_limit_le].
- split; last easy. intros H. by split; first eapply limit_lt_le_lt.
- split; last easy. intros H. by split; last etrans.
Qed.
Lemma limit_min_lt l1 l2 l3 :
l1 `min` l2 < l3 ↔ l1 < l3 ∨ l2 < l3.
Proof.
unfold limit_min.
destruct (decide (l1 ≤ l2)%lim) as [Hl12|Hl12%not_limit_le].
- split; first tauto. by intros [H|H]; last eapply limit_lt_le_lt.
- split; first tauto. by intros [H|H]; first etrans.
Qed.
Lemma limit_lt_max l1 l2 l3 :
l1 < l2 `max` l3 ↔ l1 < l2 ∨ l1 < l3.
Proof.
unfold limit_max.
destruct (decide (l2 ≤ l3)) as [Hl23|Hl23%not_limit_le].
- split; first tauto. intros [H|H]; last done.
by apply limit_le_cases in Hl23 as [<-|Hl23]; last etrans.
- split; first tauto. by intros [H|H]; last etrans.
Qed.
Instance limit_min_comm : Comm (=) limit_min.
Proof.
unfold limit_min.
intros [] []; repeat case_decide;
try done; simpl in *; f_equal; lia.
Qed.
Instance limit_max_comm : Comm (=) limit_max.
Proof.
unfold limit_max.
intros [] []; repeat case_decide;
try done; simpl in *; f_equal; lia.
Qed.
Lemma limit_max_eq_l l1 l2 : l1 `max` l2 = l1 ↔ l2 ≤ l1.
Proof.
unfold limit_max. case_decide; split.
- by intros ->.
- intros H12. by eapply (_ : AntiSymm (=) limit_le).
- intros _. apply limit_le_cases. right.
by apply not_limit_le.
- by intros _.
Qed.
Lemma limit_max_eq_r l1 l2 : l1 `max` l2 = l2 ↔ l1 ≤ l2.
Proof. rewrite [l1 `max` l2]comm. apply limit_max_eq_l. Qed.
Lemma limit_max_l l1 l2 : l2 ≤ l1 → l1 `max` l2 = l1.
Proof. apply limit_max_eq_l. Qed.
Lemma limit_max_r l1 l2 : l1 ≤ l2 → l1 `max` l2 = l2.
Proof. apply limit_max_eq_r. Qed.
Definition ne_period := { p : period | period_nonempty p }.
Instance ne_period_elem_of : ElemOf timestamp ne_period :=
λ t p, t ∈ `p.
Instance ne_period_elem_of_dec t (p : ne_period) : Decision (t ∈ p).
Proof. apply _. Qed.
(* TODO: rename to ne_period_before *)
Definition period_before '([s1, e1) ↾ _ : ne_period) '([s2, e2) ↾ _ : ne_period) :=
e1 < s2.
Instance period_before_pi p1 p2 : ProofIrrel (period_before p1 p2).
Proof. destruct p1 as [[s1 e1] Hne1], p2 as [[s2 e2] Hne2]. apply _. Qed.
Instance period_before_trans : Transitive period_before.
Proof.
intros [[s1 e1] Hne1] [[s2 e2] Hne2] [[s3 e3] Hne3] H1 H2.
unfold period_before in *. simpl in *.
by trans s2; last trans e2.
Qed.
Instance period_before_irrefl : Irreflexive period_before.
Proof.
intros [[s e] Hne] Hp. simpl in *.
eapply (_ : Irreflexive limit_lt). by etrans.
Qed.
Instance period_before_strict_order : StrictOrder period_before.
Proof. split; apply _. Qed.
Definition ne_period_rel (R : relation ne_period) : relation period :=
λ p1 p2, ∃ H1 H2, R (p1 ↾ H1) (p2 ↾ H2).
Instance ne_period_rel_trans `{!Transitive R} : Transitive (ne_period_rel R).
Proof.
intros p1 p2 p3 (H1 & H2 & HR12) (H2' & H3 & HR23).
exists H1, H3. replace H2' with H2 in HR23; last apply proof_irrel.
by etrans.
Qed.
Instance ne_period_rel_irrefl `{!Irreflexive R} : Irreflexive (ne_period_rel R).
Proof.
intros p. intros (H1 & H2 & HR).
replace H2 with H1 in HR; last apply proof_irrel.
by apply (_ : Irreflexive R) in HR.
Qed.
Instance ne_period_rel_pi (R : relation ne_period) `{!∀ x y, ProofIrrel (R x y)} x y :
ProofIrrel (ne_period_rel R x y).
Proof. apply _. Qed.
Lemma except_parts_order p1 p2 :
period_nonempty p2 →
period_nonempty (except p1 p2).1 →
period_nonempty (except p1 p2).2 →
ne_period_rel period_before (except p1 p2).1 (except p1 p2).2.
Proof.
destruct p1 as [s1 e1], p2 as [s2 e2]. simpl. intros H0 Hne1 Hne2.
unfold period_before. split; [done|split; [done|]].
apply limit_min_lt. right. apply limit_lt_max. right. apply H0.
Qed.
Definition period_nonempty_alt (p : period) := ∃ t, t ∈ p.
Lemma period_nonempty_alt_iff p :
period_nonempty p ↔ period_nonempty_alt p.
Proof.
unfold period_nonempty, period_nonempty_alt.
destruct p as [s e]. split.
- intros Hlt. destruct s as [|s|]; last done.
+ destruct e as [|e|]; first done.
* exists (Z.pred e). by split; last (simpl; lia).
* exists 0%Z. done.
+ exists s. done.
- intros [t Ht]. by eapply limit_lt_le_lt.
Qed.
Instance period_eq_dec : EqDecision period.
Proof. solve_decision. Qed.
Instance period_disjoint : Disjoint period :=
λ p1 p2, period_empty (p1 ∩ p2).
Instance period_intersection_comm : Comm (=) period_intersection.
Proof.
intros [s1 e1] [s2 e2].
by rewrite /= [s2 `max` s1]comm [e2 `min` e1]comm.
Qed.
Instance period_disjoint_symm : Symmetric period_disjoint.
Proof. intros p1 p2. unfold period_disjoint. by rewrite comm. Qed.
Lemma limit_min_eq_l l1 l2 : l1 `min` l2 = l1 ↔ l1 ≤ l2.
Proof.
unfold limit_min. case_decide; first done. split.
- intros ->. exfalso. by apply H.
- intros []%H.
Qed.
Lemma limit_min_eq_r l1 l2 : l1 `min` l2 = l2 ↔ l2 ≤ l1.
Proof. rewrite [l1 `min` l2]comm. apply limit_min_eq_l. Qed.
Lemma limit_min_l l1 l2 : l1 ≤ l2 → l1 `min` l2 = l1.
Proof. apply limit_min_eq_l. Qed.
Lemma limit_min_r l1 l2 : l2 ≤ l1 → l1 `min` l2 = l2.
Proof. apply limit_min_eq_r. Qed.
Lemma limit_lt_le_trans {l1} l2 {l3} : l1 < l2 → l2 ≤ l3 → l1 < l3.
Proof. by intros Hlt12 [->|Hlt23]%limit_le_cases; last etrans. Qed.
Instance period_union : Union period :=
λ '[s1, e1) '[s2, e2), [s1 `min` s2, e1 `max` e2).
Lemma limit_min_le l1 l2 l3 :
l1 ≤ l3 ∨ l2 ≤ l3 ↔
l1 `min` l2 ≤ l3.
Proof.
unfold limit_min. case_decide; split.
- by intros [H13|H23]; last trans l2.
- intros H13. by left.
- apply not_limit_le in H. intros [H13|H23]; last done.
trans l1; last done.
apply limit_le_cases. by right.
- intros H23. by right.
Qed.
Lemma limit_le_min l1 l2 l3 :
l1 ≤ l2 ∧ l1 ≤ l3 ↔
l1 ≤ l2 `min` l3.
Proof.
unfold limit_min. case_decide; split.
- by intros [H12 _].
- intros ?. by split; last trans l2.
- by intros [_ H13].
- intros ?. split; last done.
apply not_limit_le in H.
trans l3; first done.
apply limit_le_cases. by right.
Qed.
Lemma period_union_lem_1 t (p1 p2 : period) :
t ∈ p1 ∨ t ∈ p2 → t ∈ p1 ∪ p2.
Proof.
destruct p1 as [s1 e1], p2 as [s2 e2].
unfold union, period_union.
intros [Ht|Ht]; split.
- apply limit_min_le. left. apply Ht.
- apply limit_lt_max. left. apply Ht.
- apply limit_min_le. right. apply Ht.
- apply limit_lt_max. right. apply Ht.
Qed.
Definition unifiable '[s1, e1) '[s2, e2) :=
s2 ≤ e1 ∧ s1 ≤ e2.
Instance unifiable_dec : RelDecision unifiable.
Proof. intros [] []. solve_decision. Qed.
Lemma not_limit_le_lt l1 l2 l3 :
¬ l1 ≤ l2 < l3 ↔ l2 < l1 ∨ l3 ≤ l2.
Proof.
split.
- intros H123.
destruct (decide (l2 < l1)) as [?|H21%not_limit_lt]; first by left.
destruct (decide (l3 ≤ l2)) as [?|H32%not_limit_le]; first by right.
exfalso. by apply H123.
- intros [H21|H32] contra.
+ eapply not_limit_le; [apply H21|apply contra].
+ eapply not_limit_lt; [apply H32|apply contra].
Qed.
Lemma limit_lt_le l1 l2 : l1 < l2 → l1 ≤ l2.
Proof. intros Hlt. apply limit_le_cases. by right. Qed.
Lemma period_union_lem_2 t (p1 p2 : period) :
unifiable p1 p2 →
t ∈ p1 ∪ p2 → t ∈ p1 ∨ t ∈ p2.
Proof.
intros Hunif Hunion.
destruct (decide (t ∈ p1)) as [?|Ht1]; first by left.
destruct (decide (t ∈ p2)) as [?|Ht2]; first by right.
exfalso.
destruct p1 as [s1 e1], p2 as [s2 e2].
unfold elem_of, period_elem_of in *.
simpl in *. destruct Hunif as [Hunif1 Hunif2].
(* If t is not in p1, then it must be in p2 *)
apply Ht2. clear Ht2.
apply not_limit_le_lt in Ht1.
destruct Ht1 as [Ht1|Ht1].
- (* t is not in p1 because it is before p1 (where p2 must hence be) *)
destruct Hunion as [Hunion1 Hunion2].
apply limit_min_le in Hunion1 as [[->|contra]%limit_le_cases | Hunion1].
{ exfalso. by eapply (_ : Irreflexive limit_lt). }
{ exfalso. by eapply (asymmetry (R:=limit_lt)). }
split; first done. by eapply limit_lt_le_trans.
- destruct Hunion as [Hunion1 Hunion2].
apply limit_lt_max in Hunion2 as [Hunion2 | Hunion2].
+ apply limit_le_cases in Ht1 as [->|contra].
{ exfalso. by eapply (_ : Irreflexive limit_lt). }
{ exfalso. by eapply (asymmetry (R:=limit_lt)). }
+ split; last done. by trans e1.
Qed.
Instance period_union_comm : Comm (=) period_union.
Proof.
unfold period_union. intros [s1 e1] [s2 e2].
by rewrite limit_min_comm limit_max_comm.
Qed.
Instance period_singleton : Singleton timestamp period :=
λ t, [t, TsLimit (Z.succ t)).
Lemma period_singleton_lem_1 t : t ∈ ({[t]} : period).
Proof. by split; simpl; last lia. Qed.
Lemma period_singleton_lem_2 t t' : t' ∈ ({[t]} : period) → t' = t.
Proof.
unfold singleton, period_singleton.
intros [H11 H12]. destruct t, t'; try done; simpl in *; lia.
Qed.
Lemma period_singleton_nonempty t : period_nonempty {[t]}.
Proof.
apply period_nonempty_alt_iff.
exists t. apply period_singleton_lem_1.
Qed.
Lemma unifiable_period_union p1 p2 p3 :
unifiable p1 p2 → unifiable p2 p3 →
unifiable (p1 ∪ p2) p3.
Proof.
destruct p1 as [s1 e1], p2 as [s2 e2], p3 as [s3 e3].
intros [Hunif11 Hunif12] [Hunif21 Hunif22]. simpl. split.
+ apply limit_le_max. by right.
+ apply limit_min_le. by right.
Qed.
Instance unifiable_symm : Symmetric unifiable.
Proof. by intros [] [] []. Qed.
Definition Σlift {A} {Φ : A → Prop} (R : relation A) : relation {x : A | Φ x} :=
λ '(x↾_) '(y↾_), R x y.
Instance Σlift_symm {A Φ} `{!Symmetric R} : Symmetric (@Σlift A Φ R).
Proof. intros [x Hx] [y Hy] HR. simpl in *. by apply symmetry. Qed.
(* TODO: probably unused? *)
Instance Σlift_dec {A Φ} `{!RelDecision R} : RelDecision (@Σlift A Φ R).
Proof. intros [x Hx] [y Hy]. by simpl. Qed.
Definition ne_period_unifiable : relation ne_period := Σlift unifiable.
Lemma period_unifiable_not_before p1 p2 : ne_period_unifiable p1 p2 → ¬ period_before p1 p2.
Proof.
destruct p1 as [[s1 e1] Hne1], p2 as [[s2 e2] Hne2]. simpl in *.
intros [Hunif1 Hunif2] Hbefore.
apply limit_le_cases in Hunif1 as [->|contra].
- by eapply (_ : Irreflexive limit_lt).
- by eapply (asymmetry (R:=limit_lt)).
Qed.
(* TODO: define total relation on Σperiod_nonempty, p1 p2 := unifiable p1 p2 ∨ p1 < p2.
(Then have [AntiSymm unifiable (≤@{Σperiod_nonempty})].)
Show decidability, perform mergesort.
Then make the rest of normalization consist in unification of the periods.
*)
Definition ne_period_le p1 p2 := ne_period_unifiable p1 p2 ∨ period_before p1 p2.
Instance ne_period_le_antisymm : AntiSymm ne_period_unifiable ne_period_le.
Proof.
intros p1 p2 [H12|H12] [H21|H21]; [done|done|..].
- exfalso. apply symmetry in H21.
by eapply period_unifiable_not_before.
- exfalso. by eapply asymmetry.
Qed.
Lemma ne_period_neither_before_unifiable p1 p2 :
¬ period_before p1 p2 → ¬ period_before p2 p1 →
ne_period_unifiable p1 p2.
Proof.
destruct p1 as [[s1 e1] Hne1], p2 as [[s2 e2] Hne2].
simpl in *. by intros ?%not_limit_lt ?%not_limit_lt.
Qed.
Instance period_before_dec : RelDecision period_before.
Proof.
intros [[s1 e1] ?] [[s2 e2] ?]. simpl in *.
solve_decision.
Qed.
Lemma ne_period_not_unifiable p1 p2 :
¬ ne_period_unifiable p1 p2 →
period_before p1 p2 ∨ period_before p2 p1.
Proof.
intros Hnunif.
destruct (decide (period_before p1 p2)) as [?|H12]; first by left.
destruct (decide (period_before p2 p1)) as [?|H21]; first by right.
exfalso. by apply Hnunif, ne_period_neither_before_unifiable.
Qed.
Instance ne_period_le_total : Total ne_period_le.
Proof.
intros p1 p2.
destruct (decide (ne_period_unifiable p1 p2)) as [Hunif|Hnunif].
- (* which one we pick does not matter *)
by do 2 left.
- apply ne_period_not_unifiable in Hnunif as [H12|H21].
+ left. by right.
+ right. by right.
Qed.
|