-
Notifications
You must be signed in to change notification settings - Fork 258
/
BoundedOrder.lean
914 lines (664 loc) · 27.9 KB
/
BoundedOrder.lean
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
/-
Copyright (c) 2017 Johannes Hölzl. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Johannes Hölzl
-/
import Mathlib.Order.Lattice
import Mathlib.Order.ULift
import Mathlib.Tactic.PushNeg
#align_import order.bounded_order from "leanprover-community/mathlib"@"70d50ecfd4900dd6d328da39ab7ebd516abe4025"
/-!
# ⊤ and ⊥, bounded lattices and variants
This file defines top and bottom elements (greatest and least elements) of a type, the bounded
variants of different kinds of lattices, sets up the typeclass hierarchy between them and provides
instances for `Prop` and `fun`.
## Main declarations
* `<Top/Bot> α`: Typeclasses to declare the `⊤`/`⊥` notation.
* `Order<Top/Bot> α`: Order with a top/bottom element.
* `BoundedOrder α`: Order with a top and bottom element.
## Common lattices
* Distributive lattices with a bottom element. Notated by `[DistribLattice α] [OrderBot α]`
It captures the properties of `Disjoint` that are common to `GeneralizedBooleanAlgebra` and
`DistribLattice` when `OrderBot`.
* Bounded and distributive lattice. Notated by `[DistribLattice α] [BoundedOrder α]`.
Typical examples include `Prop` and `Det α`.
-/
open Function OrderDual
universe u v
variable {α : Type u} {β : Type v} {γ δ : Type*}
/-! ### Top, bottom element -/
/-- An order is an `OrderTop` if it has a greatest element.
We state this using a data mixin, holding the value of `⊤` and the greatest element constraint. -/
class OrderTop (α : Type u) [LE α] extends Top α where
/-- `⊤` is the greatest element -/
le_top : ∀ a : α, a ≤ ⊤
#align order_top OrderTop
section OrderTop
/-- An order is (noncomputably) either an `OrderTop` or a `NoTopOrder`. Use as
`casesI topOrderOrNoTopOrder α`. -/
noncomputable def topOrderOrNoTopOrder (α : Type*) [LE α] : PSum (OrderTop α) (NoTopOrder α) := by
by_cases H : ∀ a : α, ∃ b, ¬b ≤ a
· exact PSum.inr ⟨H⟩
· push_neg at H
letI : Top α := ⟨Classical.choose H⟩
exact PSum.inl ⟨Classical.choose_spec H⟩
#align top_order_or_no_top_order topOrderOrNoTopOrder
section LE
variable [LE α] [OrderTop α] {a : α}
@[simp]
theorem le_top : a ≤ ⊤ :=
OrderTop.le_top a
#align le_top le_top
@[simp]
theorem isTop_top : IsTop (⊤ : α) := fun _ => le_top
#align is_top_top isTop_top
end LE
section Preorder
variable [Preorder α] [OrderTop α] {a b : α}
@[simp]
theorem isMax_top : IsMax (⊤ : α) :=
isTop_top.isMax
#align is_max_top isMax_top
@[simp]
theorem not_top_lt : ¬⊤ < a :=
isMax_top.not_lt
#align not_top_lt not_top_lt
theorem ne_top_of_lt (h : a < b) : a ≠ ⊤ :=
(h.trans_le le_top).ne
#align ne_top_of_lt ne_top_of_lt
alias LT.lt.ne_top := ne_top_of_lt
end Preorder
variable [PartialOrder α] [OrderTop α] [Preorder β] {f : α → β} {a b : α}
@[simp]
theorem isMax_iff_eq_top : IsMax a ↔ a = ⊤ :=
⟨fun h => h.eq_of_le le_top, fun h _ _ => h.symm ▸ le_top⟩
#align is_max_iff_eq_top isMax_iff_eq_top
@[simp]
theorem isTop_iff_eq_top : IsTop a ↔ a = ⊤ :=
⟨fun h => h.isMax.eq_of_le le_top, fun h _ => h.symm ▸ le_top⟩
#align is_top_iff_eq_top isTop_iff_eq_top
theorem not_isMax_iff_ne_top : ¬IsMax a ↔ a ≠ ⊤ :=
isMax_iff_eq_top.not
#align not_is_max_iff_ne_top not_isMax_iff_ne_top
theorem not_isTop_iff_ne_top : ¬IsTop a ↔ a ≠ ⊤ :=
isTop_iff_eq_top.not
#align not_is_top_iff_ne_top not_isTop_iff_ne_top
alias ⟨IsMax.eq_top, _⟩ := isMax_iff_eq_top
#align is_max.eq_top IsMax.eq_top
alias ⟨IsTop.eq_top, _⟩ := isTop_iff_eq_top
#align is_top.eq_top IsTop.eq_top
@[simp]
theorem top_le_iff : ⊤ ≤ a ↔ a = ⊤ :=
le_top.le_iff_eq.trans eq_comm
#align top_le_iff top_le_iff
theorem top_unique (h : ⊤ ≤ a) : a = ⊤ :=
le_top.antisymm h
#align top_unique top_unique
theorem eq_top_iff : a = ⊤ ↔ ⊤ ≤ a :=
top_le_iff.symm
#align eq_top_iff eq_top_iff
theorem eq_top_mono (h : a ≤ b) (h₂ : a = ⊤) : b = ⊤ :=
top_unique <| h₂ ▸ h
#align eq_top_mono eq_top_mono
theorem lt_top_iff_ne_top : a < ⊤ ↔ a ≠ ⊤ :=
le_top.lt_iff_ne
#align lt_top_iff_ne_top lt_top_iff_ne_top
@[simp]
theorem not_lt_top_iff : ¬a < ⊤ ↔ a = ⊤ :=
lt_top_iff_ne_top.not_left
#align not_lt_top_iff not_lt_top_iff
theorem eq_top_or_lt_top (a : α) : a = ⊤ ∨ a < ⊤ :=
le_top.eq_or_lt
#align eq_top_or_lt_top eq_top_or_lt_top
theorem Ne.lt_top (h : a ≠ ⊤) : a < ⊤ :=
lt_top_iff_ne_top.mpr h
#align ne.lt_top Ne.lt_top
theorem Ne.lt_top' (h : ⊤ ≠ a) : a < ⊤ :=
h.symm.lt_top
#align ne.lt_top' Ne.lt_top'
theorem ne_top_of_le_ne_top (hb : b ≠ ⊤) (hab : a ≤ b) : a ≠ ⊤ :=
(hab.trans_lt hb.lt_top).ne
#align ne_top_of_le_ne_top ne_top_of_le_ne_top
theorem StrictMono.apply_eq_top_iff (hf : StrictMono f) : f a = f ⊤ ↔ a = ⊤ :=
⟨fun h => not_lt_top_iff.1 fun ha => (hf ha).ne h, congr_arg _⟩
#align strict_mono.apply_eq_top_iff StrictMono.apply_eq_top_iff
theorem StrictAnti.apply_eq_top_iff (hf : StrictAnti f) : f a = f ⊤ ↔ a = ⊤ :=
⟨fun h => not_lt_top_iff.1 fun ha => (hf ha).ne' h, congr_arg _⟩
#align strict_anti.apply_eq_top_iff StrictAnti.apply_eq_top_iff
variable [Nontrivial α]
theorem not_isMin_top : ¬IsMin (⊤ : α) := fun h =>
let ⟨_, ha⟩ := exists_ne (⊤ : α)
ha <| top_le_iff.1 <| h le_top
#align not_is_min_top not_isMin_top
end OrderTop
theorem StrictMono.maximal_preimage_top [LinearOrder α] [Preorder β] [OrderTop β] {f : α → β}
(H : StrictMono f) {a} (h_top : f a = ⊤) (x : α) : x ≤ a :=
H.maximal_of_maximal_image
(fun p => by
rw [h_top]
exact le_top)
x
#align strict_mono.maximal_preimage_top StrictMono.maximal_preimage_top
theorem OrderTop.ext_top {α} {hA : PartialOrder α} (A : OrderTop α) {hB : PartialOrder α}
(B : OrderTop α) (H : ∀ x y : α, (haveI := hA; x ≤ y) ↔ x ≤ y) :
(@Top.top α (@OrderTop.toTop α hA.toLE A)) = (@Top.top α (@OrderTop.toTop α hB.toLE B)) := by
cases PartialOrder.ext H
apply top_unique
exact @le_top _ _ A _
#align order_top.ext_top OrderTop.ext_top
/-- An order is an `OrderBot` if it has a least element.
We state this using a data mixin, holding the value of `⊥` and the least element constraint. -/
class OrderBot (α : Type u) [LE α] extends Bot α where
/-- `⊥` is the least element -/
bot_le : ∀ a : α, ⊥ ≤ a
#align order_bot OrderBot
section OrderBot
/-- An order is (noncomputably) either an `OrderBot` or a `NoBotOrder`. Use as
`casesI botOrderOrNoBotOrder α`. -/
noncomputable def botOrderOrNoBotOrder (α : Type*) [LE α] : PSum (OrderBot α) (NoBotOrder α) := by
by_cases H : ∀ a : α, ∃ b, ¬a ≤ b
· exact PSum.inr ⟨H⟩
· push_neg at H
letI : Bot α := ⟨Classical.choose H⟩
exact PSum.inl ⟨Classical.choose_spec H⟩
#align bot_order_or_no_bot_order botOrderOrNoBotOrder
section LE
variable [LE α] [OrderBot α] {a : α}
@[simp]
theorem bot_le : ⊥ ≤ a :=
OrderBot.bot_le a
#align bot_le bot_le
@[simp]
theorem isBot_bot : IsBot (⊥ : α) := fun _ => bot_le
#align is_bot_bot isBot_bot
end LE
namespace OrderDual
variable (α)
instance instTop [Bot α] : Top αᵒᵈ :=
⟨(⊥ : α)⟩
instance instBot [Top α] : Bot αᵒᵈ :=
⟨(⊤ : α)⟩
instance instOrderTop [LE α] [OrderBot α] : OrderTop αᵒᵈ where
__ := inferInstanceAs (Top αᵒᵈ)
le_top := @bot_le α _ _
instance instOrderBot [LE α] [OrderTop α] : OrderBot αᵒᵈ where
__ := inferInstanceAs (Bot αᵒᵈ)
bot_le := @le_top α _ _
@[simp]
theorem ofDual_bot [Top α] : ofDual ⊥ = (⊤ : α) :=
rfl
#align order_dual.of_dual_bot OrderDual.ofDual_bot
@[simp]
theorem ofDual_top [Bot α] : ofDual ⊤ = (⊥ : α) :=
rfl
#align order_dual.of_dual_top OrderDual.ofDual_top
@[simp]
theorem toDual_bot [Bot α] : toDual (⊥ : α) = ⊤ :=
rfl
#align order_dual.to_dual_bot OrderDual.toDual_bot
@[simp]
theorem toDual_top [Top α] : toDual (⊤ : α) = ⊥ :=
rfl
#align order_dual.to_dual_top OrderDual.toDual_top
end OrderDual
section Preorder
variable [Preorder α] [OrderBot α] {a b : α}
@[simp]
theorem isMin_bot : IsMin (⊥ : α) :=
isBot_bot.isMin
#align is_min_bot isMin_bot
@[simp]
theorem not_lt_bot : ¬a < ⊥ :=
isMin_bot.not_lt
#align not_lt_bot not_lt_bot
theorem ne_bot_of_gt (h : a < b) : b ≠ ⊥ :=
(bot_le.trans_lt h).ne'
#align ne_bot_of_gt ne_bot_of_gt
alias LT.lt.ne_bot := ne_bot_of_gt
end Preorder
variable [PartialOrder α] [OrderBot α] [Preorder β] {f : α → β} {a b : α}
@[simp]
theorem isMin_iff_eq_bot : IsMin a ↔ a = ⊥ :=
⟨fun h => h.eq_of_ge bot_le, fun h _ _ => h.symm ▸ bot_le⟩
#align is_min_iff_eq_bot isMin_iff_eq_bot
@[simp]
theorem isBot_iff_eq_bot : IsBot a ↔ a = ⊥ :=
⟨fun h => h.isMin.eq_of_ge bot_le, fun h _ => h.symm ▸ bot_le⟩
#align is_bot_iff_eq_bot isBot_iff_eq_bot
theorem not_isMin_iff_ne_bot : ¬IsMin a ↔ a ≠ ⊥ :=
isMin_iff_eq_bot.not
#align not_is_min_iff_ne_bot not_isMin_iff_ne_bot
theorem not_isBot_iff_ne_bot : ¬IsBot a ↔ a ≠ ⊥ :=
isBot_iff_eq_bot.not
#align not_is_bot_iff_ne_bot not_isBot_iff_ne_bot
alias ⟨IsMin.eq_bot, _⟩ := isMin_iff_eq_bot
#align is_min.eq_bot IsMin.eq_bot
alias ⟨IsBot.eq_bot, _⟩ := isBot_iff_eq_bot
#align is_bot.eq_bot IsBot.eq_bot
@[simp]
theorem le_bot_iff : a ≤ ⊥ ↔ a = ⊥ :=
bot_le.le_iff_eq
#align le_bot_iff le_bot_iff
theorem bot_unique (h : a ≤ ⊥) : a = ⊥ :=
h.antisymm bot_le
#align bot_unique bot_unique
theorem eq_bot_iff : a = ⊥ ↔ a ≤ ⊥ :=
le_bot_iff.symm
#align eq_bot_iff eq_bot_iff
theorem eq_bot_mono (h : a ≤ b) (h₂ : b = ⊥) : a = ⊥ :=
bot_unique <| h₂ ▸ h
#align eq_bot_mono eq_bot_mono
theorem bot_lt_iff_ne_bot : ⊥ < a ↔ a ≠ ⊥ :=
bot_le.lt_iff_ne.trans ne_comm
#align bot_lt_iff_ne_bot bot_lt_iff_ne_bot
@[simp]
theorem not_bot_lt_iff : ¬⊥ < a ↔ a = ⊥ :=
bot_lt_iff_ne_bot.not_left
#align not_bot_lt_iff not_bot_lt_iff
theorem eq_bot_or_bot_lt (a : α) : a = ⊥ ∨ ⊥ < a :=
bot_le.eq_or_gt
#align eq_bot_or_bot_lt eq_bot_or_bot_lt
theorem eq_bot_of_minimal (h : ∀ b, ¬b < a) : a = ⊥ :=
(eq_bot_or_bot_lt a).resolve_right (h ⊥)
#align eq_bot_of_minimal eq_bot_of_minimal
theorem Ne.bot_lt (h : a ≠ ⊥) : ⊥ < a :=
bot_lt_iff_ne_bot.mpr h
#align ne.bot_lt Ne.bot_lt
theorem Ne.bot_lt' (h : ⊥ ≠ a) : ⊥ < a :=
h.symm.bot_lt
#align ne.bot_lt' Ne.bot_lt'
theorem ne_bot_of_le_ne_bot (hb : b ≠ ⊥) (hab : b ≤ a) : a ≠ ⊥ :=
(hb.bot_lt.trans_le hab).ne'
#align ne_bot_of_le_ne_bot ne_bot_of_le_ne_bot
theorem StrictMono.apply_eq_bot_iff (hf : StrictMono f) : f a = f ⊥ ↔ a = ⊥ :=
hf.dual.apply_eq_top_iff
#align strict_mono.apply_eq_bot_iff StrictMono.apply_eq_bot_iff
theorem StrictAnti.apply_eq_bot_iff (hf : StrictAnti f) : f a = f ⊥ ↔ a = ⊥ :=
hf.dual.apply_eq_top_iff
#align strict_anti.apply_eq_bot_iff StrictAnti.apply_eq_bot_iff
variable [Nontrivial α]
theorem not_isMax_bot : ¬IsMax (⊥ : α) :=
@not_isMin_top αᵒᵈ _ _ _
#align not_is_max_bot not_isMax_bot
end OrderBot
theorem StrictMono.minimal_preimage_bot [LinearOrder α] [PartialOrder β] [OrderBot β] {f : α → β}
(H : StrictMono f) {a} (h_bot : f a = ⊥) (x : α) : a ≤ x :=
H.minimal_of_minimal_image
(fun p => by
rw [h_bot]
exact bot_le)
x
#align strict_mono.minimal_preimage_bot StrictMono.minimal_preimage_bot
theorem OrderBot.ext_bot {α} {hA : PartialOrder α} (A : OrderBot α) {hB : PartialOrder α}
(B : OrderBot α) (H : ∀ x y : α, (haveI := hA; x ≤ y) ↔ x ≤ y) :
(@Bot.bot α (@OrderBot.toBot α hA.toLE A)) = (@Bot.bot α (@OrderBot.toBot α hB.toLE B)) := by
cases PartialOrder.ext H
apply bot_unique
exact @bot_le _ _ A _
#align order_bot.ext_bot OrderBot.ext_bot
section SemilatticeSupTop
variable [SemilatticeSup α] [OrderTop α] {a : α}
-- Porting note: Not simp because simp can prove it
theorem top_sup_eq (a : α) : ⊤ ⊔ a = ⊤ :=
sup_of_le_left le_top
#align top_sup_eq top_sup_eq
-- Porting note: Not simp because simp can prove it
theorem sup_top_eq (a : α) : a ⊔ ⊤ = ⊤ :=
sup_of_le_right le_top
#align sup_top_eq sup_top_eq
end SemilatticeSupTop
section SemilatticeSupBot
variable [SemilatticeSup α] [OrderBot α] {a b : α}
-- Porting note: Not simp because simp can prove it
theorem bot_sup_eq (a : α) : ⊥ ⊔ a = a :=
sup_of_le_right bot_le
#align bot_sup_eq bot_sup_eq
-- Porting note: Not simp because simp can prove it
theorem sup_bot_eq (a : α) : a ⊔ ⊥ = a :=
sup_of_le_left bot_le
#align sup_bot_eq sup_bot_eq
@[simp]
theorem sup_eq_bot_iff : a ⊔ b = ⊥ ↔ a = ⊥ ∧ b = ⊥ := by rw [eq_bot_iff, sup_le_iff]; simp
#align sup_eq_bot_iff sup_eq_bot_iff
end SemilatticeSupBot
section SemilatticeInfTop
variable [SemilatticeInf α] [OrderTop α] {a b : α}
-- Porting note: Not simp because simp can prove it
lemma top_inf_eq (a : α) : ⊤ ⊓ a = a := inf_of_le_right le_top
#align top_inf_eq top_inf_eq
-- Porting note: Not simp because simp can prove it
lemma inf_top_eq (a : α) : a ⊓ ⊤ = a := inf_of_le_left le_top
#align inf_top_eq inf_top_eq
@[simp]
theorem inf_eq_top_iff : a ⊓ b = ⊤ ↔ a = ⊤ ∧ b = ⊤ :=
@sup_eq_bot_iff αᵒᵈ _ _ _ _
#align inf_eq_top_iff inf_eq_top_iff
end SemilatticeInfTop
section SemilatticeInfBot
variable [SemilatticeInf α] [OrderBot α] {a : α}
-- Porting note: Not simp because simp can prove it
lemma bot_inf_eq (a : α) : ⊥ ⊓ a = ⊥ := inf_of_le_left bot_le
#align bot_inf_eq bot_inf_eq
-- Porting note: Not simp because simp can prove it
lemma inf_bot_eq (a : α) : a ⊓ ⊥ = ⊥ := inf_of_le_right bot_le
#align inf_bot_eq inf_bot_eq
end SemilatticeInfBot
/-! ### Bounded order -/
/-- A bounded order describes an order `(≤)` with a top and bottom element,
denoted `⊤` and `⊥` respectively. -/
class BoundedOrder (α : Type u) [LE α] extends OrderTop α, OrderBot α
#align bounded_order BoundedOrder
instance OrderDual.instBoundedOrder (α : Type u) [LE α] [BoundedOrder α] : BoundedOrder αᵒᵈ where
__ := inferInstanceAs (OrderTop αᵒᵈ)
__ := inferInstanceAs (OrderBot αᵒᵈ)
section PartialOrder
variable [PartialOrder α]
instance OrderBot.instSubsingleton : Subsingleton (OrderBot α) where
allEq := by rintro @⟨⟨a⟩, ha⟩ @⟨⟨b⟩, hb⟩; congr; exact le_antisymm (ha _) (hb _)
instance OrderTop.instSubsingleton : Subsingleton (OrderTop α) where
allEq := by rintro @⟨⟨a⟩, ha⟩ @⟨⟨b⟩, hb⟩; congr; exact le_antisymm (hb _) (ha _)
instance BoundedOrder.instSubsingleton : Subsingleton (BoundedOrder α) where
allEq := by rintro ⟨⟩ ⟨⟩; congr <;> exact Subsingleton.elim _ _
end PartialOrder
section Logic
/-!
#### In this section we prove some properties about monotone and antitone operations on `Prop`
-/
section Preorder
variable [Preorder α]
theorem monotone_and {p q : α → Prop} (m_p : Monotone p) (m_q : Monotone q) :
Monotone fun x => p x ∧ q x :=
fun _ _ h => And.imp (m_p h) (m_q h)
#align monotone_and monotone_and
-- Note: by finish [monotone] doesn't work
theorem monotone_or {p q : α → Prop} (m_p : Monotone p) (m_q : Monotone q) :
Monotone fun x => p x ∨ q x :=
fun _ _ h => Or.imp (m_p h) (m_q h)
#align monotone_or monotone_or
theorem monotone_le {x : α} : Monotone (x ≤ ·) := fun _ _ h' h => h.trans h'
#align monotone_le monotone_le
theorem monotone_lt {x : α} : Monotone (x < ·) := fun _ _ h' h => h.trans_le h'
#align monotone_lt monotone_lt
theorem antitone_le {x : α} : Antitone (· ≤ x) := fun _ _ h' h => h'.trans h
#align antitone_le antitone_le
theorem antitone_lt {x : α} : Antitone (· < x) := fun _ _ h' h => h'.trans_lt h
#align antitone_lt antitone_lt
theorem Monotone.forall {P : β → α → Prop} (hP : ∀ x, Monotone (P x)) :
Monotone fun y => ∀ x, P x y :=
fun _ _ hy h x => hP x hy <| h x
#align monotone.forall Monotone.forall
theorem Antitone.forall {P : β → α → Prop} (hP : ∀ x, Antitone (P x)) :
Antitone fun y => ∀ x, P x y :=
fun _ _ hy h x => hP x hy (h x)
#align antitone.forall Antitone.forall
theorem Monotone.ball {P : β → α → Prop} {s : Set β} (hP : ∀ x ∈ s, Monotone (P x)) :
Monotone fun y => ∀ x ∈ s, P x y := fun _ _ hy h x hx => hP x hx hy (h x hx)
#align monotone.ball Monotone.ball
theorem Antitone.ball {P : β → α → Prop} {s : Set β} (hP : ∀ x ∈ s, Antitone (P x)) :
Antitone fun y => ∀ x ∈ s, P x y := fun _ _ hy h x hx => hP x hx hy (h x hx)
#align antitone.ball Antitone.ball
theorem Monotone.exists {P : β → α → Prop} (hP : ∀ x, Monotone (P x)) :
Monotone fun y => ∃ x, P x y :=
fun _ _ hy ⟨x, hx⟩ ↦ ⟨x, hP x hy hx⟩
theorem Antitone.exists {P : β → α → Prop} (hP : ∀ x, Antitone (P x)) :
Antitone fun y => ∃ x, P x y :=
fun _ _ hy ⟨x, hx⟩ ↦ ⟨x, hP x hy hx⟩
theorem forall_ge_iff {P : α → Prop} {x₀ : α} (hP : Monotone P) :
(∀ x ≥ x₀, P x) ↔ P x₀ :=
⟨fun H ↦ H x₀ le_rfl, fun H _ hx ↦ hP hx H⟩
theorem forall_le_iff {P : α → Prop} {x₀ : α} (hP : Antitone P) :
(∀ x ≤ x₀, P x) ↔ P x₀ :=
⟨fun H ↦ H x₀ le_rfl, fun H _ hx ↦ hP hx H⟩
end Preorder
section SemilatticeSup
variable [SemilatticeSup α]
theorem exists_ge_and_iff_exists {P : α → Prop} {x₀ : α} (hP : Monotone P) :
(∃ x, x₀ ≤ x ∧ P x) ↔ ∃ x, P x :=
⟨fun h => h.imp fun _ h => h.2, fun ⟨x, hx⟩ => ⟨x ⊔ x₀, le_sup_right, hP le_sup_left hx⟩⟩
#align exists_ge_and_iff_exists exists_ge_and_iff_exists
end SemilatticeSup
section SemilatticeInf
variable [SemilatticeInf α]
theorem exists_le_and_iff_exists {P : α → Prop} {x₀ : α} (hP : Antitone P) :
(∃ x, x ≤ x₀ ∧ P x) ↔ ∃ x, P x :=
exists_ge_and_iff_exists <| hP.dual_left
#align exists_le_and_iff_exists exists_le_and_iff_exists
end SemilatticeInf
end Logic
/-! ### Function lattices -/
namespace Pi
variable {ι : Type*} {α' : ι → Type*}
instance [∀ i, Bot (α' i)] : Bot (∀ i, α' i) :=
⟨fun _ => ⊥⟩
@[simp]
theorem bot_apply [∀ i, Bot (α' i)] (i : ι) : (⊥ : ∀ i, α' i) i = ⊥ :=
rfl
#align pi.bot_apply Pi.bot_apply
theorem bot_def [∀ i, Bot (α' i)] : (⊥ : ∀ i, α' i) = fun _ => ⊥ :=
rfl
#align pi.bot_def Pi.bot_def
instance [∀ i, Top (α' i)] : Top (∀ i, α' i) :=
⟨fun _ => ⊤⟩
@[simp]
theorem top_apply [∀ i, Top (α' i)] (i : ι) : (⊤ : ∀ i, α' i) i = ⊤ :=
rfl
#align pi.top_apply Pi.top_apply
theorem top_def [∀ i, Top (α' i)] : (⊤ : ∀ i, α' i) = fun _ => ⊤ :=
rfl
#align pi.top_def Pi.top_def
instance instOrderTop [∀ i, LE (α' i)] [∀ i, OrderTop (α' i)] : OrderTop (∀ i, α' i) where
le_top _ := fun _ => le_top
instance instOrderBot [∀ i, LE (α' i)] [∀ i, OrderBot (α' i)] : OrderBot (∀ i, α' i) where
bot_le _ := fun _ => bot_le
instance instBoundedOrder [∀ i, LE (α' i)] [∀ i, BoundedOrder (α' i)] :
BoundedOrder (∀ i, α' i) where
__ := inferInstanceAs (OrderTop (∀ i, α' i))
__ := inferInstanceAs (OrderBot (∀ i, α' i))
end Pi
section Subsingleton
variable [PartialOrder α] [BoundedOrder α]
theorem eq_bot_of_bot_eq_top (hα : (⊥ : α) = ⊤) (x : α) : x = (⊥ : α) :=
eq_bot_mono le_top (Eq.symm hα)
#align eq_bot_of_bot_eq_top eq_bot_of_bot_eq_top
theorem eq_top_of_bot_eq_top (hα : (⊥ : α) = ⊤) (x : α) : x = (⊤ : α) :=
eq_top_mono bot_le hα
#align eq_top_of_bot_eq_top eq_top_of_bot_eq_top
theorem subsingleton_of_top_le_bot (h : (⊤ : α) ≤ (⊥ : α)) : Subsingleton α :=
⟨fun _ _ => le_antisymm
(le_trans le_top <| le_trans h bot_le) (le_trans le_top <| le_trans h bot_le)⟩
#align subsingleton_of_top_le_bot subsingleton_of_top_le_bot
theorem subsingleton_of_bot_eq_top (hα : (⊥ : α) = (⊤ : α)) : Subsingleton α :=
subsingleton_of_top_le_bot (ge_of_eq hα)
#align subsingleton_of_bot_eq_top subsingleton_of_bot_eq_top
theorem subsingleton_iff_bot_eq_top : (⊥ : α) = (⊤ : α) ↔ Subsingleton α :=
⟨subsingleton_of_bot_eq_top, fun _ => Subsingleton.elim ⊥ ⊤⟩
#align subsingleton_iff_bot_eq_top subsingleton_iff_bot_eq_top
end Subsingleton
section lift
-- See note [reducible non-instances]
/-- Pullback an `OrderTop`. -/
abbrev OrderTop.lift [LE α] [Top α] [LE β] [OrderTop β] (f : α → β)
(map_le : ∀ a b, f a ≤ f b → a ≤ b) (map_top : f ⊤ = ⊤) : OrderTop α :=
⟨fun a =>
map_le _ _ <| by
rw [map_top]
-- Porting note: lean3 didn't need the type annotation
exact @le_top β _ _ _⟩
#align order_top.lift OrderTop.lift
-- See note [reducible non-instances]
/-- Pullback an `OrderBot`. -/
abbrev OrderBot.lift [LE α] [Bot α] [LE β] [OrderBot β] (f : α → β)
(map_le : ∀ a b, f a ≤ f b → a ≤ b) (map_bot : f ⊥ = ⊥) : OrderBot α :=
⟨fun a =>
map_le _ _ <| by
rw [map_bot]
-- Porting note: lean3 didn't need the type annotation
exact @bot_le β _ _ _⟩
#align order_bot.lift OrderBot.lift
-- See note [reducible non-instances]
/-- Pullback a `BoundedOrder`. -/
abbrev BoundedOrder.lift [LE α] [Top α] [Bot α] [LE β] [BoundedOrder β] (f : α → β)
(map_le : ∀ a b, f a ≤ f b → a ≤ b) (map_top : f ⊤ = ⊤) (map_bot : f ⊥ = ⊥) :
BoundedOrder α where
__ := OrderTop.lift f map_le map_top
__ := OrderBot.lift f map_le map_bot
#align bounded_order.lift BoundedOrder.lift
end lift
/-! ### Subtype, order dual, product lattices -/
namespace Subtype
variable {p : α → Prop}
-- See note [reducible non-instances]
/-- A subtype remains a `⊥`-order if the property holds at `⊥`. -/
protected abbrev orderBot [LE α] [OrderBot α] (hbot : p ⊥) : OrderBot { x : α // p x } where
bot := ⟨⊥, hbot⟩
bot_le _ := bot_le
#align subtype.order_bot Subtype.orderBot
-- See note [reducible non-instances]
/-- A subtype remains a `⊤`-order if the property holds at `⊤`. -/
protected abbrev orderTop [LE α] [OrderTop α] (htop : p ⊤) : OrderTop { x : α // p x } where
top := ⟨⊤, htop⟩
le_top _ := le_top
#align subtype.order_top Subtype.orderTop
-- See note [reducible non-instances]
/-- A subtype remains a bounded order if the property holds at `⊥` and `⊤`. -/
protected abbrev boundedOrder [LE α] [BoundedOrder α] (hbot : p ⊥) (htop : p ⊤) :
BoundedOrder (Subtype p) where
__ := Subtype.orderTop htop
__ := Subtype.orderBot hbot
#align subtype.bounded_order Subtype.boundedOrder
variable [PartialOrder α]
@[simp]
theorem mk_bot [OrderBot α] [OrderBot (Subtype p)] (hbot : p ⊥) : mk ⊥ hbot = ⊥ :=
le_bot_iff.1 <| coe_le_coe.1 bot_le
#align subtype.mk_bot Subtype.mk_bot
@[simp]
theorem mk_top [OrderTop α] [OrderTop (Subtype p)] (htop : p ⊤) : mk ⊤ htop = ⊤ :=
top_le_iff.1 <| coe_le_coe.1 le_top
#align subtype.mk_top Subtype.mk_top
theorem coe_bot [OrderBot α] [OrderBot (Subtype p)] (hbot : p ⊥) : ((⊥ : Subtype p) : α) = ⊥ :=
congr_arg Subtype.val (mk_bot hbot).symm
#align subtype.coe_bot Subtype.coe_bot
theorem coe_top [OrderTop α] [OrderTop (Subtype p)] (htop : p ⊤) : ((⊤ : Subtype p) : α) = ⊤ :=
congr_arg Subtype.val (mk_top htop).symm
#align subtype.coe_top Subtype.coe_top
@[simp]
theorem coe_eq_bot_iff [OrderBot α] [OrderBot (Subtype p)] (hbot : p ⊥) {x : { x // p x }} :
(x : α) = ⊥ ↔ x = ⊥ := by
rw [← coe_bot hbot, ext_iff]
#align subtype.coe_eq_bot_iff Subtype.coe_eq_bot_iff
@[simp]
theorem coe_eq_top_iff [OrderTop α] [OrderTop (Subtype p)] (htop : p ⊤) {x : { x // p x }} :
(x : α) = ⊤ ↔ x = ⊤ := by
rw [← coe_top htop, ext_iff]
#align subtype.coe_eq_top_iff Subtype.coe_eq_top_iff
@[simp]
theorem mk_eq_bot_iff [OrderBot α] [OrderBot (Subtype p)] (hbot : p ⊥) {x : α} (hx : p x) :
(⟨x, hx⟩ : Subtype p) = ⊥ ↔ x = ⊥ :=
(coe_eq_bot_iff hbot).symm
#align subtype.mk_eq_bot_iff Subtype.mk_eq_bot_iff
@[simp]
theorem mk_eq_top_iff [OrderTop α] [OrderTop (Subtype p)] (htop : p ⊤) {x : α} (hx : p x) :
(⟨x, hx⟩ : Subtype p) = ⊤ ↔ x = ⊤ :=
(coe_eq_top_iff htop).symm
#align subtype.mk_eq_top_iff Subtype.mk_eq_top_iff
end Subtype
namespace Prod
variable (α β)
instance instTop [Top α] [Top β] : Top (α × β) :=
⟨⟨⊤, ⊤⟩⟩
instance instBot [Bot α] [Bot β] : Bot (α × β) :=
⟨⟨⊥, ⊥⟩⟩
theorem fst_top [Top α] [Top β] : (⊤ : α × β).fst = ⊤ := rfl
theorem snd_top [Top α] [Top β] : (⊤ : α × β).snd = ⊤ := rfl
theorem fst_bot [Bot α] [Bot β] : (⊥ : α × β).fst = ⊥ := rfl
theorem snd_bot [Bot α] [Bot β] : (⊥ : α × β).snd = ⊥ := rfl
instance instOrderTop [LE α] [LE β] [OrderTop α] [OrderTop β] : OrderTop (α × β) where
__ := inferInstanceAs (Top (α × β))
le_top _ := ⟨le_top, le_top⟩
instance instOrderBot [LE α] [LE β] [OrderBot α] [OrderBot β] : OrderBot (α × β) where
__ := inferInstanceAs (Bot (α × β))
bot_le _ := ⟨bot_le, bot_le⟩
instance instBoundedOrder [LE α] [LE β] [BoundedOrder α] [BoundedOrder β] :
BoundedOrder (α × β) where
__ := inferInstanceAs (OrderTop (α × β))
__ := inferInstanceAs (OrderBot (α × β))
end Prod
namespace ULift
instance [Top α] : Top (ULift.{v} α) where top := up ⊤
@[simp] theorem up_top [Top α] : up (⊤ : α) = ⊤ := rfl
@[simp] theorem down_top [Top α] : down (⊤ : ULift α) = ⊤ := rfl
instance [Bot α] : Bot (ULift.{v} α) where bot := up ⊥
@[simp] theorem up_bot [Bot α] : up (⊥ : α) = ⊥ := rfl
@[simp] theorem down_bot [Bot α] : down (⊥ : ULift α) = ⊥ := rfl
instance [LE α] [OrderBot α] : OrderBot (ULift.{v} α) :=
OrderBot.lift ULift.down (fun _ _ => down_le.mp) down_bot
instance [LE α] [OrderTop α] : OrderTop (ULift.{v} α) :=
OrderTop.lift ULift.down (fun _ _ => down_le.mp) down_top
instance [LE α] [BoundedOrder α] : BoundedOrder (ULift.{v} α) where
end ULift
section LinearOrder
variable [LinearOrder α]
-- `simp` can prove these, so they shouldn't be simp-lemmas.
theorem min_bot_left [OrderBot α] (a : α) : min ⊥ a = ⊥ := bot_inf_eq _
#align min_bot_left min_bot_left
theorem max_top_left [OrderTop α] (a : α) : max ⊤ a = ⊤ := top_sup_eq _
#align max_top_left max_top_left
theorem min_top_left [OrderTop α] (a : α) : min ⊤ a = a := top_inf_eq _
#align min_top_left min_top_left
theorem max_bot_left [OrderBot α] (a : α) : max ⊥ a = a := bot_sup_eq _
#align max_bot_left max_bot_left
theorem min_top_right [OrderTop α] (a : α) : min a ⊤ = a := inf_top_eq _
#align min_top_right min_top_right
theorem max_bot_right [OrderBot α] (a : α) : max a ⊥ = a := sup_bot_eq _
#align max_bot_right max_bot_right
theorem min_bot_right [OrderBot α] (a : α) : min a ⊥ = ⊥ := inf_bot_eq _
#align min_bot_right min_bot_right
theorem max_top_right [OrderTop α] (a : α) : max a ⊤ = ⊤ := sup_top_eq _
#align max_top_right max_top_right
@[simp]
theorem min_eq_bot [OrderBot α] {a b : α} : min a b = ⊥ ↔ a = ⊥ ∨ b = ⊥ := by
simp only [← inf_eq_min, ← le_bot_iff, inf_le_iff]
#align min_eq_bot min_eq_bot
@[simp]
theorem max_eq_top [OrderTop α] {a b : α} : max a b = ⊤ ↔ a = ⊤ ∨ b = ⊤ :=
@min_eq_bot αᵒᵈ _ _ a b
#align max_eq_top max_eq_top
@[simp]
theorem max_eq_bot [OrderBot α] {a b : α} : max a b = ⊥ ↔ a = ⊥ ∧ b = ⊥ :=
sup_eq_bot_iff
#align max_eq_bot max_eq_bot
@[simp]
theorem min_eq_top [OrderTop α] {a b : α} : min a b = ⊤ ↔ a = ⊤ ∧ b = ⊤ :=
inf_eq_top_iff
#align min_eq_top min_eq_top
end LinearOrder
section Nontrivial
variable [PartialOrder α] [BoundedOrder α] [Nontrivial α]
@[simp]
theorem bot_ne_top : (⊥ : α) ≠ ⊤ := fun h => not_subsingleton _ <| subsingleton_of_bot_eq_top h
#align bot_ne_top bot_ne_top
@[simp]
theorem top_ne_bot : (⊤ : α) ≠ ⊥ :=
bot_ne_top.symm
#align top_ne_bot top_ne_bot
@[simp]
theorem bot_lt_top : (⊥ : α) < ⊤ :=
lt_top_iff_ne_top.2 bot_ne_top
#align bot_lt_top bot_lt_top
end Nontrivial
section Bool
open Bool
instance Bool.instBoundedOrder : BoundedOrder Bool where
top := true
le_top := Bool.le_true
bot := false
bot_le := Bool.false_le
@[simp]
theorem top_eq_true : ⊤ = true :=
rfl
#align top_eq_tt top_eq_true
@[simp]
theorem bot_eq_false : ⊥ = false :=
rfl
#align bot_eq_ff bot_eq_false
end Bool