-
Notifications
You must be signed in to change notification settings - Fork 259
/
CompleteLattice.lean
2023 lines (1595 loc) · 78.1 KB
/
CompleteLattice.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
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
/-
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.Data.Bool.Set
import Mathlib.Data.Nat.Set
import Mathlib.Data.ULift
import Mathlib.Order.Bounds.Basic
import Mathlib.Order.Hom.Basic
import Mathlib.Mathport.Notation
#align_import order.complete_lattice from "leanprover-community/mathlib"@"5709b0d8725255e76f47debca6400c07b5c2d8e6"
/-!
# Theory of complete lattices
## Main definitions
* `sSup` and `sInf` are the supremum and the infimum of a set;
* `iSup (f : ι → α)` and `iInf (f : ι → α)` are indexed supremum and infimum of a function,
defined as `sSup` and `sInf` of the range of this function;
* class `CompleteLattice`: a bounded lattice such that `sSup s` is always the least upper boundary
of `s` and `sInf s` is always the greatest lower boundary of `s`;
* class `CompleteLinearOrder`: a linear ordered complete lattice.
## Naming conventions
In lemma names,
* `sSup` is called `sSup`
* `sInf` is called `sInf`
* `⨆ i, s i` is called `iSup`
* `⨅ i, s i` is called `iInf`
* `⨆ i j, s i j` is called `iSup₂`. This is an `iSup` inside an `iSup`.
* `⨅ i j, s i j` is called `iInf₂`. This is an `iInf` inside an `iInf`.
* `⨆ i ∈ s, t i` is called `biSup` for "bounded `iSup`". This is the special case of `iSup₂`
where `j : i ∈ s`.
* `⨅ i ∈ s, t i` is called `biInf` for "bounded `iInf`". This is the special case of `iInf₂`
where `j : i ∈ s`.
## Notation
* `⨆ i, f i` : `iSup f`, the supremum of the range of `f`;
* `⨅ i, f i` : `iInf f`, the infimum of the range of `f`.
-/
set_option autoImplicit true
open Function OrderDual Set
variable {α β β₂ γ : Type*} {ι ι' : Sort*} {κ : ι → Sort*} {κ' : ι' → Sort*}
/-- Class for the `sSup` operator -/
class SupSet (α : Type*) where
sSup : Set α → α
#align has_Sup SupSet
#align has_Sup.Sup SupSet.sSup
/-- Class for the `sInf` operator -/
class InfSet (α : Type*) where
sInf : Set α → α
#align has_Inf InfSet
#align has_Inf.Inf InfSet.sInf
export SupSet (sSup)
export InfSet (sInf)
/-- Supremum of a set -/
add_decl_doc SupSet.sSup
/-- Infimum of a set -/
add_decl_doc InfSet.sInf
/-- Indexed supremum -/
def iSup [SupSet α] {ι} (s : ι → α) : α :=
sSup (range s)
#align supr iSup
/-- Indexed infimum -/
def iInf [InfSet α] {ι} (s : ι → α) : α :=
sInf (range s)
#align infi iInf
instance (priority := 50) infSet_to_nonempty (α) [InfSet α] : Nonempty α :=
⟨sInf ∅⟩
#align has_Inf_to_nonempty infSet_to_nonempty
instance (priority := 50) supSet_to_nonempty (α) [SupSet α] : Nonempty α :=
⟨sSup ∅⟩
#align has_Sup_to_nonempty supSet_to_nonempty
/-
Porting note: the code below could replace the `notation3` command
open Std.ExtendedBinder in
syntax "⨆ " extBinder ", " term:51 : term
macro_rules
| `(⨆ $x:ident, $p) => `(iSup fun $x:ident ↦ $p)
| `(⨆ $x:ident : $t, $p) => `(iSup fun $x:ident : $t ↦ $p)
| `(⨆ $x:ident $b:binderPred, $p) =>
`(iSup fun $x:ident ↦ satisfies_binder_pred% $x $b ∧ $p) -/
/-- Indexed supremum. -/
notation3 "⨆ "(...)", "r:60:(scoped f => iSup f) => r
/-- Indexed infimum. -/
notation3 "⨅ "(...)", "r:60:(scoped f => iInf f) => r
instance OrderDual.supSet (α) [InfSet α] : SupSet αᵒᵈ :=
⟨(sInf : Set α → α)⟩
instance OrderDual.infSet (α) [SupSet α] : InfSet αᵒᵈ :=
⟨(sSup : Set α → α)⟩
/-- Note that we rarely use `CompleteSemilatticeSup`
(in fact, any such object is always a `CompleteLattice`, so it's usually best to start there).
Nevertheless it is sometimes a useful intermediate step in constructions.
-/
class CompleteSemilatticeSup (α : Type*) extends PartialOrder α, SupSet α where
/-- Any element of a set is less than the set supremum. -/
le_sSup : ∀ s, ∀ a ∈ s, a ≤ sSup s
/-- Any upper bound is more than the set supremum. -/
sSup_le : ∀ s a, (∀ b ∈ s, b ≤ a) → sSup s ≤ a
#align complete_semilattice_Sup CompleteSemilatticeSup
section
variable [CompleteSemilatticeSup α] {s t : Set α} {a b : α}
-- --@[ematch] Porting note: attribute removed
theorem le_sSup : a ∈ s → a ≤ sSup s :=
CompleteSemilatticeSup.le_sSup s a
#align le_Sup le_sSup
theorem sSup_le : (∀ b ∈ s, b ≤ a) → sSup s ≤ a :=
CompleteSemilatticeSup.sSup_le s a
#align Sup_le sSup_le
theorem isLUB_sSup (s : Set α) : IsLUB s (sSup s) :=
⟨fun _ ↦ le_sSup, fun _ ↦ sSup_le⟩
#align is_lub_Sup isLUB_sSup
theorem IsLUB.sSup_eq (h : IsLUB s a) : sSup s = a :=
(isLUB_sSup s).unique h
#align is_lub.Sup_eq IsLUB.sSup_eq
theorem le_sSup_of_le (hb : b ∈ s) (h : a ≤ b) : a ≤ sSup s :=
le_trans h (le_sSup hb)
#align le_Sup_of_le le_sSup_of_le
@[gcongr]
theorem sSup_le_sSup (h : s ⊆ t) : sSup s ≤ sSup t :=
(isLUB_sSup s).mono (isLUB_sSup t) h
#align Sup_le_Sup sSup_le_sSup
@[simp]
theorem sSup_le_iff : sSup s ≤ a ↔ ∀ b ∈ s, b ≤ a :=
isLUB_le_iff (isLUB_sSup s)
#align Sup_le_iff sSup_le_iff
theorem le_sSup_iff : a ≤ sSup s ↔ ∀ b ∈ upperBounds s, a ≤ b :=
⟨fun h _ hb => le_trans h (sSup_le hb), fun hb => hb _ fun _ => le_sSup⟩
#align le_Sup_iff le_sSup_iff
theorem le_iSup_iff {s : ι → α} : a ≤ iSup s ↔ ∀ b, (∀ i, s i ≤ b) → a ≤ b := by
simp [iSup, le_sSup_iff, upperBounds]
#align le_supr_iff le_iSup_iff
theorem sSup_le_sSup_of_forall_exists_le (h : ∀ x ∈ s, ∃ y ∈ t, x ≤ y) : sSup s ≤ sSup t :=
le_sSup_iff.2 fun _ hb =>
sSup_le fun a ha =>
let ⟨_, hct, hac⟩ := h a ha
hac.trans (hb hct)
#align Sup_le_Sup_of_forall_exists_le sSup_le_sSup_of_forall_exists_le
-- We will generalize this to conditionally complete lattices in `csSup_singleton`.
theorem sSup_singleton {a : α} : sSup {a} = a :=
isLUB_singleton.sSup_eq
#align Sup_singleton sSup_singleton
end
/-- Note that we rarely use `CompleteSemilatticeInf`
(in fact, any such object is always a `CompleteLattice`, so it's usually best to start there).
Nevertheless it is sometimes a useful intermediate step in constructions.
-/
class CompleteSemilatticeInf (α : Type*) extends PartialOrder α, InfSet α where
/-- Any element of a set is more than the set infimum. -/
sInf_le : ∀ s, ∀ a ∈ s, sInf s ≤ a
/-- Any lower bound is less than the set infimum. -/
le_sInf : ∀ s a, (∀ b ∈ s, a ≤ b) → a ≤ sInf s
#align complete_semilattice_Inf CompleteSemilatticeInf
section
variable [CompleteSemilatticeInf α] {s t : Set α} {a b : α}
-- --@[ematch] Porting note: attribute removed
theorem sInf_le : a ∈ s → sInf s ≤ a :=
CompleteSemilatticeInf.sInf_le s a
#align Inf_le sInf_le
theorem le_sInf : (∀ b ∈ s, a ≤ b) → a ≤ sInf s :=
CompleteSemilatticeInf.le_sInf s a
#align le_Inf le_sInf
theorem isGLB_sInf (s : Set α) : IsGLB s (sInf s) :=
⟨fun _ => sInf_le, fun _ => le_sInf⟩
#align is_glb_Inf isGLB_sInf
theorem IsGLB.sInf_eq (h : IsGLB s a) : sInf s = a :=
(isGLB_sInf s).unique h
#align is_glb.Inf_eq IsGLB.sInf_eq
theorem sInf_le_of_le (hb : b ∈ s) (h : b ≤ a) : sInf s ≤ a :=
le_trans (sInf_le hb) h
#align Inf_le_of_le sInf_le_of_le
@[gcongr]
theorem sInf_le_sInf (h : s ⊆ t) : sInf t ≤ sInf s :=
(isGLB_sInf s).mono (isGLB_sInf t) h
#align Inf_le_Inf sInf_le_sInf
@[simp]
theorem le_sInf_iff : a ≤ sInf s ↔ ∀ b ∈ s, a ≤ b :=
le_isGLB_iff (isGLB_sInf s)
#align le_Inf_iff le_sInf_iff
theorem sInf_le_iff : sInf s ≤ a ↔ ∀ b ∈ lowerBounds s, b ≤ a :=
⟨fun h _ hb => le_trans (le_sInf hb) h, fun hb => hb _ fun _ => sInf_le⟩
#align Inf_le_iff sInf_le_iff
theorem iInf_le_iff {s : ι → α} : iInf s ≤ a ↔ ∀ b, (∀ i, b ≤ s i) → b ≤ a := by
simp [iInf, sInf_le_iff, lowerBounds]
#align infi_le_iff iInf_le_iff
theorem sInf_le_sInf_of_forall_exists_le (h : ∀ x ∈ s, ∃ y ∈ t, y ≤ x) : sInf t ≤ sInf s :=
le_of_forall_le
(by
simp only [le_sInf_iff]
introv h₀ h₁
rcases h _ h₁ with ⟨y, hy, hy'⟩
solve_by_elim [le_trans _ hy'])
#align Inf_le_Inf_of_forall_exists_le sInf_le_sInf_of_forall_exists_le
-- We will generalize this to conditionally complete lattices in `csInf_singleton`.
theorem sInf_singleton {a : α} : sInf {a} = a :=
isGLB_singleton.sInf_eq
#align Inf_singleton sInf_singleton
end
/-- A complete lattice is a bounded lattice which has suprema and infima for every subset. -/
class CompleteLattice (α : Type*) extends Lattice α, CompleteSemilatticeSup α,
CompleteSemilatticeInf α, Top α, Bot α where
/-- Any element is less than the top one. -/
protected le_top : ∀ x : α, x ≤ ⊤
/-- Any element is more than the bottom one. -/
protected bot_le : ∀ x : α, ⊥ ≤ x
#align complete_lattice CompleteLattice
-- see Note [lower instance priority]
instance (priority := 100) CompleteLattice.toBoundedOrder [h : CompleteLattice α] :
BoundedOrder α :=
{ h with }
#align complete_lattice.to_bounded_order CompleteLattice.toBoundedOrder
/-- Create a `CompleteLattice` from a `PartialOrder` and `InfSet`
that returns the greatest lower bound of a set. Usually this constructor provides
poor definitional equalities. If other fields are known explicitly, they should be
provided; for example, if `inf` is known explicitly, construct the `CompleteLattice`
instance as
```
instance : CompleteLattice my_T :=
{ inf := better_inf,
le_inf := ...,
inf_le_right := ...,
inf_le_left := ...
-- don't care to fix sup, sSup, bot, top
..completeLatticeOfInf my_T _ }
```
-/
def completeLatticeOfInf (α : Type*) [H1 : PartialOrder α] [H2 : InfSet α]
(isGLB_sInf : ∀ s : Set α, IsGLB s (sInf s)) : CompleteLattice α :=
{ H1, H2 with
bot := sInf univ
bot_le := fun x => (isGLB_sInf univ).1 trivial
top := sInf ∅
le_top := fun a => (isGLB_sInf ∅).2 <| by simp
sup := fun a b => sInf { x : α | a ≤ x ∧ b ≤ x }
inf := fun a b => sInf {a, b}
le_inf := fun a b c hab hac => by
apply (isGLB_sInf _).2
simp [*]
inf_le_right := fun a b => (isGLB_sInf _).1 <| mem_insert_of_mem _ <| mem_singleton _
inf_le_left := fun a b => (isGLB_sInf _).1 <| mem_insert _ _
sup_le := fun a b c hac hbc => (isGLB_sInf _).1 <| by simp [*]
le_sup_left := fun a b => (isGLB_sInf _).2 fun x => And.left
le_sup_right := fun a b => (isGLB_sInf _).2 fun x => And.right
le_sInf := fun s a ha => (isGLB_sInf s).2 ha
sInf_le := fun s a ha => (isGLB_sInf s).1 ha
sSup := fun s => sInf (upperBounds s)
le_sSup := fun s a ha => (isGLB_sInf (upperBounds s)).2 fun b hb => hb ha
sSup_le := fun s a ha => (isGLB_sInf (upperBounds s)).1 ha }
#align complete_lattice_of_Inf completeLatticeOfInf
/-- Any `CompleteSemilatticeInf` is in fact a `CompleteLattice`.
Note that this construction has bad definitional properties:
see the doc-string on `completeLatticeOfInf`.
-/
def completeLatticeOfCompleteSemilatticeInf (α : Type*) [CompleteSemilatticeInf α] :
CompleteLattice α :=
completeLatticeOfInf α fun s => isGLB_sInf s
#align complete_lattice_of_complete_semilattice_Inf completeLatticeOfCompleteSemilatticeInf
/-- Create a `CompleteLattice` from a `PartialOrder` and `SupSet`
that returns the least upper bound of a set. Usually this constructor provides
poor definitional equalities. If other fields are known explicitly, they should be
provided; for example, if `inf` is known explicitly, construct the `CompleteLattice`
instance as
```
instance : CompleteLattice my_T :=
{ inf := better_inf,
le_inf := ...,
inf_le_right := ...,
inf_le_left := ...
-- don't care to fix sup, sInf, bot, top
..completeLatticeOfSup my_T _ }
```
-/
def completeLatticeOfSup (α : Type*) [H1 : PartialOrder α] [H2 : SupSet α]
(isLUB_sSup : ∀ s : Set α, IsLUB s (sSup s)) : CompleteLattice α :=
{ H1, H2 with
top := sSup univ
le_top := fun x => (isLUB_sSup univ).1 trivial
bot := sSup ∅
bot_le := fun x => (isLUB_sSup ∅).2 <| by simp
sup := fun a b => sSup {a, b}
sup_le := fun a b c hac hbc => (isLUB_sSup _).2 (by simp [*])
le_sup_left := fun a b => (isLUB_sSup _).1 <| mem_insert _ _
le_sup_right := fun a b => (isLUB_sSup _).1 <| mem_insert_of_mem _ <| mem_singleton _
inf := fun a b => sSup { x | x ≤ a ∧ x ≤ b }
le_inf := fun a b c hab hac => (isLUB_sSup _).1 <| by simp [*]
inf_le_left := fun a b => (isLUB_sSup _).2 fun x => And.left
inf_le_right := fun a b => (isLUB_sSup _).2 fun x => And.right
sInf := fun s => sSup (lowerBounds s)
sSup_le := fun s a ha => (isLUB_sSup s).2 ha
le_sSup := fun s a ha => (isLUB_sSup s).1 ha
sInf_le := fun s a ha => (isLUB_sSup (lowerBounds s)).2 fun b hb => hb ha
le_sInf := fun s a ha => (isLUB_sSup (lowerBounds s)).1 ha }
#align complete_lattice_of_Sup completeLatticeOfSup
/-- Any `CompleteSemilatticeSup` is in fact a `CompleteLattice`.
Note that this construction has bad definitional properties:
see the doc-string on `completeLatticeOfSup`.
-/
def completeLatticeOfCompleteSemilatticeSup (α : Type*) [CompleteSemilatticeSup α] :
CompleteLattice α :=
completeLatticeOfSup α fun s => isLUB_sSup s
#align complete_lattice_of_complete_semilattice_Sup completeLatticeOfCompleteSemilatticeSup
-- Porting note: as we cannot rename fields while extending,
-- `CompleteLinearOrder` does not directly extend `LinearOrder`.
-- Instead we add the fields by hand, and write a manual instance.
/-- A complete linear order is a linear order whose lattice structure is complete. -/
class CompleteLinearOrder (α : Type*) extends CompleteLattice α where
/-- A linear order is total. -/
le_total (a b : α) : a ≤ b ∨ b ≤ a
/-- In a linearly ordered type, we assume the order relations are all decidable. -/
decidableLE : DecidableRel (· ≤ · : α → α → Prop)
/-- In a linearly ordered type, we assume the order relations are all decidable. -/
decidableEq : DecidableEq α := @decidableEqOfDecidableLE _ _ decidableLE
/-- In a linearly ordered type, we assume the order relations are all decidable. -/
decidableLT : DecidableRel (· < · : α → α → Prop) :=
@decidableLTOfDecidableLE _ _ decidableLE
#align complete_linear_order CompleteLinearOrder
instance CompleteLinearOrder.toLinearOrder [i : CompleteLinearOrder α] : LinearOrder α :=
{ i with
min := Inf.inf
max := Sup.sup
min_def := fun a b => by
split_ifs with h
· simp [h]
· simp [(CompleteLinearOrder.le_total a b).resolve_left h]
max_def := fun a b => by
split_ifs with h
· simp [h]
· simp [(CompleteLinearOrder.le_total a b).resolve_left h] }
namespace OrderDual
variable (α)
instance completeLattice [CompleteLattice α] : CompleteLattice αᵒᵈ :=
{ OrderDual.lattice α, OrderDual.supSet α, OrderDual.infSet α, OrderDual.boundedOrder α with
le_sSup := @CompleteLattice.sInf_le α _
sSup_le := @CompleteLattice.le_sInf α _
sInf_le := @CompleteLattice.le_sSup α _
le_sInf := @CompleteLattice.sSup_le α _ }
instance [CompleteLinearOrder α] : CompleteLinearOrder αᵒᵈ :=
{ OrderDual.completeLattice α, OrderDual.instLinearOrder α with }
end OrderDual
open OrderDual
section
variable [CompleteLattice α] {s t : Set α} {a b : α}
@[simp]
theorem toDual_sSup (s : Set α) : toDual (sSup s) = sInf (ofDual ⁻¹' s) :=
rfl
#align to_dual_Sup toDual_sSup
@[simp]
theorem toDual_sInf (s : Set α) : toDual (sInf s) = sSup (ofDual ⁻¹' s) :=
rfl
#align to_dual_Inf toDual_sInf
@[simp]
theorem ofDual_sSup (s : Set αᵒᵈ) : ofDual (sSup s) = sInf (toDual ⁻¹' s) :=
rfl
#align of_dual_Sup ofDual_sSup
@[simp]
theorem ofDual_sInf (s : Set αᵒᵈ) : ofDual (sInf s) = sSup (toDual ⁻¹' s) :=
rfl
#align of_dual_Inf ofDual_sInf
@[simp]
theorem toDual_iSup (f : ι → α) : toDual (⨆ i, f i) = ⨅ i, toDual (f i) :=
rfl
#align to_dual_supr toDual_iSup
@[simp]
theorem toDual_iInf (f : ι → α) : toDual (⨅ i, f i) = ⨆ i, toDual (f i) :=
rfl
#align to_dual_infi toDual_iInf
@[simp]
theorem ofDual_iSup (f : ι → αᵒᵈ) : ofDual (⨆ i, f i) = ⨅ i, ofDual (f i) :=
rfl
#align of_dual_supr ofDual_iSup
@[simp]
theorem ofDual_iInf (f : ι → αᵒᵈ) : ofDual (⨅ i, f i) = ⨆ i, ofDual (f i) :=
rfl
#align of_dual_infi ofDual_iInf
theorem sInf_le_sSup (hs : s.Nonempty) : sInf s ≤ sSup s :=
isGLB_le_isLUB (isGLB_sInf s) (isLUB_sSup s) hs
#align Inf_le_Sup sInf_le_sSup
theorem sSup_union {s t : Set α} : sSup (s ∪ t) = sSup s ⊔ sSup t :=
((isLUB_sSup s).union (isLUB_sSup t)).sSup_eq
#align Sup_union sSup_union
theorem sInf_union {s t : Set α} : sInf (s ∪ t) = sInf s ⊓ sInf t :=
((isGLB_sInf s).union (isGLB_sInf t)).sInf_eq
#align Inf_union sInf_union
theorem sSup_inter_le {s t : Set α} : sSup (s ∩ t) ≤ sSup s ⊓ sSup t :=
sSup_le fun _ hb => le_inf (le_sSup hb.1) (le_sSup hb.2)
#align Sup_inter_le sSup_inter_le
theorem le_sInf_inter {s t : Set α} : sInf s ⊔ sInf t ≤ sInf (s ∩ t) :=
@sSup_inter_le αᵒᵈ _ _ _
#align le_Inf_inter le_sInf_inter
@[simp]
theorem sSup_empty : sSup ∅ = (⊥ : α) :=
(@isLUB_empty α _ _).sSup_eq
#align Sup_empty sSup_empty
@[simp]
theorem sInf_empty : sInf ∅ = (⊤ : α) :=
(@isGLB_empty α _ _).sInf_eq
#align Inf_empty sInf_empty
@[simp]
theorem sSup_univ : sSup univ = (⊤ : α) :=
(@isLUB_univ α _ _).sSup_eq
#align Sup_univ sSup_univ
@[simp]
theorem sInf_univ : sInf univ = (⊥ : α) :=
(@isGLB_univ α _ _).sInf_eq
#align Inf_univ sInf_univ
-- TODO(Jeremy): get this automatically
@[simp]
theorem sSup_insert {a : α} {s : Set α} : sSup (insert a s) = a ⊔ sSup s :=
((isLUB_sSup s).insert a).sSup_eq
#align Sup_insert sSup_insert
@[simp]
theorem sInf_insert {a : α} {s : Set α} : sInf (insert a s) = a ⊓ sInf s :=
((isGLB_sInf s).insert a).sInf_eq
#align Inf_insert sInf_insert
theorem sSup_le_sSup_of_subset_insert_bot (h : s ⊆ insert ⊥ t) : sSup s ≤ sSup t :=
le_trans (sSup_le_sSup h) (le_of_eq (_root_.trans sSup_insert bot_sup_eq))
#align Sup_le_Sup_of_subset_insert_bot sSup_le_sSup_of_subset_insert_bot
theorem sInf_le_sInf_of_subset_insert_top (h : s ⊆ insert ⊤ t) : sInf t ≤ sInf s :=
le_trans (le_of_eq (_root_.trans top_inf_eq.symm sInf_insert.symm)) (sInf_le_sInf h)
#align Inf_le_Inf_of_subset_insert_top sInf_le_sInf_of_subset_insert_top
@[simp]
theorem sSup_diff_singleton_bot (s : Set α) : sSup (s \ {⊥}) = sSup s :=
(sSup_le_sSup (diff_subset _ _)).antisymm <|
sSup_le_sSup_of_subset_insert_bot <| subset_insert_diff_singleton _ _
#align Sup_diff_singleton_bot sSup_diff_singleton_bot
@[simp]
theorem sInf_diff_singleton_top (s : Set α) : sInf (s \ {⊤}) = sInf s :=
@sSup_diff_singleton_bot αᵒᵈ _ s
#align Inf_diff_singleton_top sInf_diff_singleton_top
theorem sSup_pair {a b : α} : sSup {a, b} = a ⊔ b :=
(@isLUB_pair α _ a b).sSup_eq
#align Sup_pair sSup_pair
theorem sInf_pair {a b : α} : sInf {a, b} = a ⊓ b :=
(@isGLB_pair α _ a b).sInf_eq
#align Inf_pair sInf_pair
@[simp]
theorem sSup_eq_bot : sSup s = ⊥ ↔ ∀ a ∈ s, a = ⊥ :=
⟨fun h _ ha => bot_unique <| h ▸ le_sSup ha, fun h =>
bot_unique <| sSup_le fun a ha => le_bot_iff.2 <| h a ha⟩
#align Sup_eq_bot sSup_eq_bot
@[simp]
theorem sInf_eq_top : sInf s = ⊤ ↔ ∀ a ∈ s, a = ⊤ :=
@sSup_eq_bot αᵒᵈ _ _
#align Inf_eq_top sInf_eq_top
theorem eq_singleton_bot_of_sSup_eq_bot_of_nonempty {s : Set α} (h_sup : sSup s = ⊥)
(hne : s.Nonempty) : s = {⊥} := by
rw [Set.eq_singleton_iff_nonempty_unique_mem]
rw [sSup_eq_bot] at h_sup
exact ⟨hne, h_sup⟩
#align eq_singleton_bot_of_Sup_eq_bot_of_nonempty eq_singleton_bot_of_sSup_eq_bot_of_nonempty
theorem eq_singleton_top_of_sInf_eq_top_of_nonempty : sInf s = ⊤ → s.Nonempty → s = {⊤} :=
@eq_singleton_bot_of_sSup_eq_bot_of_nonempty αᵒᵈ _ _
#align eq_singleton_top_of_Inf_eq_top_of_nonempty eq_singleton_top_of_sInf_eq_top_of_nonempty
/-- Introduction rule to prove that `b` is the supremum of `s`: it suffices to check that `b`
is larger than all elements of `s`, and that this is not the case of any `w < b`.
See `csSup_eq_of_forall_le_of_forall_lt_exists_gt` for a version in conditionally complete
lattices. -/
theorem sSup_eq_of_forall_le_of_forall_lt_exists_gt (h₁ : ∀ a ∈ s, a ≤ b)
(h₂ : ∀ w, w < b → ∃ a ∈ s, w < a) : sSup s = b :=
(sSup_le h₁).eq_of_not_lt fun h =>
let ⟨_, ha, ha'⟩ := h₂ _ h
((le_sSup ha).trans_lt ha').false
#align Sup_eq_of_forall_le_of_forall_lt_exists_gt sSup_eq_of_forall_le_of_forall_lt_exists_gt
/-- Introduction rule to prove that `b` is the infimum of `s`: it suffices to check that `b`
is smaller than all elements of `s`, and that this is not the case of any `w > b`.
See `csInf_eq_of_forall_ge_of_forall_gt_exists_lt` for a version in conditionally complete
lattices. -/
theorem sInf_eq_of_forall_ge_of_forall_gt_exists_lt :
(∀ a ∈ s, b ≤ a) → (∀ w, b < w → ∃ a ∈ s, a < w) → sInf s = b :=
@sSup_eq_of_forall_le_of_forall_lt_exists_gt αᵒᵈ _ _ _
#align Inf_eq_of_forall_ge_of_forall_gt_exists_lt sInf_eq_of_forall_ge_of_forall_gt_exists_lt
end
section CompleteLinearOrder
variable [CompleteLinearOrder α] {s t : Set α} {a b : α}
theorem lt_sSup_iff : b < sSup s ↔ ∃ a ∈ s, b < a :=
lt_isLUB_iff <| isLUB_sSup s
#align lt_Sup_iff lt_sSup_iff
theorem sInf_lt_iff : sInf s < b ↔ ∃ a ∈ s, a < b :=
isGLB_lt_iff <| isGLB_sInf s
#align Inf_lt_iff sInf_lt_iff
theorem sSup_eq_top : sSup s = ⊤ ↔ ∀ b < ⊤, ∃ a ∈ s, b < a :=
⟨fun h _ hb => lt_sSup_iff.1 <| hb.trans_eq h.symm, fun h =>
top_unique <|
le_of_not_gt fun h' =>
let ⟨_, ha, h⟩ := h _ h'
(h.trans_le <| le_sSup ha).false⟩
#align Sup_eq_top sSup_eq_top
theorem sInf_eq_bot : sInf s = ⊥ ↔ ∀ b > ⊥, ∃ a ∈ s, a < b :=
@sSup_eq_top αᵒᵈ _ _
#align Inf_eq_bot sInf_eq_bot
theorem lt_iSup_iff {f : ι → α} : a < iSup f ↔ ∃ i, a < f i :=
lt_sSup_iff.trans exists_range_iff
#align lt_supr_iff lt_iSup_iff
theorem iInf_lt_iff {f : ι → α} : iInf f < a ↔ ∃ i, f i < a :=
sInf_lt_iff.trans exists_range_iff
#align infi_lt_iff iInf_lt_iff
end CompleteLinearOrder
/-
### iSup & iInf
-/
section SupSet
variable [SupSet α] {f g : ι → α}
theorem sSup_range : sSup (range f) = iSup f :=
rfl
#align Sup_range sSup_range
theorem sSup_eq_iSup' (s : Set α) : sSup s = ⨆ a : s, (a : α) := by rw [iSup, Subtype.range_coe]
#align Sup_eq_supr' sSup_eq_iSup'
theorem iSup_congr (h : ∀ i, f i = g i) : ⨆ i, f i = ⨆ i, g i :=
congr_arg _ <| funext h
#align supr_congr iSup_congr
theorem Function.Surjective.iSup_comp {f : ι → ι'} (hf : Surjective f) (g : ι' → α) :
⨆ x, g (f x) = ⨆ y, g y := by
simp [iSup]
congr
exact hf.range_comp g
#align function.surjective.supr_comp Function.Surjective.iSup_comp
theorem Equiv.iSup_comp {g : ι' → α} (e : ι ≃ ι') : ⨆ x, g (e x) = ⨆ y, g y :=
e.surjective.iSup_comp _
#align equiv.supr_comp Equiv.iSup_comp
protected theorem Function.Surjective.iSup_congr {g : ι' → α} (h : ι → ι') (h1 : Surjective h)
(h2 : ∀ x, g (h x) = f x) : ⨆ x, f x = ⨆ y, g y := by
convert h1.iSup_comp g
exact (h2 _).symm
#align function.surjective.supr_congr Function.Surjective.iSup_congr
protected theorem Equiv.iSup_congr {g : ι' → α} (e : ι ≃ ι') (h : ∀ x, g (e x) = f x) :
⨆ x, f x = ⨆ y, g y :=
e.surjective.iSup_congr _ h
#align equiv.supr_congr Equiv.iSup_congr
@[congr]
theorem iSup_congr_Prop {p q : Prop} {f₁ : p → α} {f₂ : q → α} (pq : p ↔ q)
(f : ∀ x, f₁ (pq.mpr x) = f₂ x) : iSup f₁ = iSup f₂ := by
obtain rfl := propext pq
congr with x
apply f
#align supr_congr_Prop iSup_congr_Prop
theorem iSup_plift_up (f : PLift ι → α) : ⨆ i, f (PLift.up i) = ⨆ i, f i :=
(PLift.up_surjective.iSup_congr _) fun _ => rfl
#align supr_plift_up iSup_plift_up
theorem iSup_plift_down (f : ι → α) : ⨆ i, f (PLift.down i) = ⨆ i, f i :=
(PLift.down_surjective.iSup_congr _) fun _ => rfl
#align supr_plift_down iSup_plift_down
theorem iSup_range' (g : β → α) (f : ι → β) : ⨆ b : range f, g b = ⨆ i, g (f i) := by
rw [iSup, iSup, ← image_eq_range, ← range_comp]
rfl
#align supr_range' iSup_range'
theorem sSup_image' {s : Set β} {f : β → α} : sSup (f '' s) = ⨆ a : s, f a := by
rw [iSup, image_eq_range]
#align Sup_image' sSup_image'
end SupSet
section InfSet
variable [InfSet α] {f g : ι → α}
theorem sInf_range : sInf (range f) = iInf f :=
rfl
#align Inf_range sInf_range
theorem sInf_eq_iInf' (s : Set α) : sInf s = ⨅ a : s, (a : α) :=
@sSup_eq_iSup' αᵒᵈ _ _
#align Inf_eq_infi' sInf_eq_iInf'
theorem iInf_congr (h : ∀ i, f i = g i) : ⨅ i, f i = ⨅ i, g i :=
congr_arg _ <| funext h
#align infi_congr iInf_congr
theorem Function.Surjective.iInf_comp {f : ι → ι'} (hf : Surjective f) (g : ι' → α) :
⨅ x, g (f x) = ⨅ y, g y :=
@Function.Surjective.iSup_comp αᵒᵈ _ _ _ f hf g
#align function.surjective.infi_comp Function.Surjective.iInf_comp
theorem Equiv.iInf_comp {g : ι' → α} (e : ι ≃ ι') : ⨅ x, g (e x) = ⨅ y, g y :=
@Equiv.iSup_comp αᵒᵈ _ _ _ _ e
#align equiv.infi_comp Equiv.iInf_comp
protected theorem Function.Surjective.iInf_congr {g : ι' → α} (h : ι → ι') (h1 : Surjective h)
(h2 : ∀ x, g (h x) = f x) : ⨅ x, f x = ⨅ y, g y :=
@Function.Surjective.iSup_congr αᵒᵈ _ _ _ _ _ h h1 h2
#align function.surjective.infi_congr Function.Surjective.iInf_congr
protected theorem Equiv.iInf_congr {g : ι' → α} (e : ι ≃ ι') (h : ∀ x, g (e x) = f x) :
⨅ x, f x = ⨅ y, g y :=
@Equiv.iSup_congr αᵒᵈ _ _ _ _ _ e h
#align equiv.infi_congr Equiv.iInf_congr
@[congr]
theorem iInf_congr_Prop {p q : Prop} {f₁ : p → α} {f₂ : q → α} (pq : p ↔ q)
(f : ∀ x, f₁ (pq.mpr x) = f₂ x) : iInf f₁ = iInf f₂ :=
@iSup_congr_Prop αᵒᵈ _ p q f₁ f₂ pq f
#align infi_congr_Prop iInf_congr_Prop
theorem iInf_plift_up (f : PLift ι → α) : ⨅ i, f (PLift.up i) = ⨅ i, f i :=
(PLift.up_surjective.iInf_congr _) fun _ => rfl
#align infi_plift_up iInf_plift_up
theorem iInf_plift_down (f : ι → α) : ⨅ i, f (PLift.down i) = ⨅ i, f i :=
(PLift.down_surjective.iInf_congr _) fun _ => rfl
#align infi_plift_down iInf_plift_down
theorem iInf_range' (g : β → α) (f : ι → β) : ⨅ b : range f, g b = ⨅ i, g (f i) :=
@iSup_range' αᵒᵈ _ _ _ _ _
#align infi_range' iInf_range'
theorem sInf_image' {s : Set β} {f : β → α} : sInf (f '' s) = ⨅ a : s, f a :=
@sSup_image' αᵒᵈ _ _ _ _
#align Inf_image' sInf_image'
end InfSet
section
variable [CompleteLattice α] {f g s t : ι → α} {a b : α}
-- TODO: this declaration gives error when starting smt state
----@[ematch] Porting note: attribute removed
theorem le_iSup (f : ι → α) (i : ι) : f i ≤ iSup f :=
le_sSup ⟨i, rfl⟩
#align le_supr le_iSup
theorem iInf_le (f : ι → α) (i : ι) : iInf f ≤ f i :=
sInf_le ⟨i, rfl⟩
#align infi_le iInf_le
-- --@[ematch] Porting note: attribute removed
theorem le_iSup' (f : ι → α) (i : ι) : f i ≤ iSup f :=
le_sSup ⟨i, rfl⟩
#align le_supr' le_iSup'
----@[ematch] Porting note: attribute removed
theorem iInf_le' (f : ι → α) (i : ι) : iInf f ≤ f i :=
sInf_le ⟨i, rfl⟩
#align infi_le' iInf_le'
/- TODO: this version would be more powerful, but, alas, the pattern matcher
doesn't accept it.
--@[ematch] lemma le_iSup' (f : ι → α) (i : ι) : (: f i :) ≤ (: iSup f :) :=
le_sSup ⟨i, rfl⟩
-/
theorem isLUB_iSup : IsLUB (range f) (⨆ j, f j) :=
isLUB_sSup _
#align is_lub_supr isLUB_iSup
theorem isGLB_iInf : IsGLB (range f) (⨅ j, f j) :=
isGLB_sInf _
#align is_glb_infi isGLB_iInf
theorem IsLUB.iSup_eq (h : IsLUB (range f) a) : ⨆ j, f j = a :=
h.sSup_eq
#align is_lub.supr_eq IsLUB.iSup_eq
theorem IsGLB.iInf_eq (h : IsGLB (range f) a) : ⨅ j, f j = a :=
h.sInf_eq
#align is_glb.infi_eq IsGLB.iInf_eq
theorem le_iSup_of_le (i : ι) (h : a ≤ f i) : a ≤ iSup f :=
h.trans <| le_iSup _ i
#align le_supr_of_le le_iSup_of_le
theorem iInf_le_of_le (i : ι) (h : f i ≤ a) : iInf f ≤ a :=
(iInf_le _ i).trans h
#align infi_le_of_le iInf_le_of_le
theorem le_iSup₂ {f : ∀ i, κ i → α} (i : ι) (j : κ i) : f i j ≤ ⨆ (i) (j), f i j :=
le_iSup_of_le i <| le_iSup (f i) j
#align le_supr₂ le_iSup₂
theorem iInf₂_le {f : ∀ i, κ i → α} (i : ι) (j : κ i) : ⨅ (i) (j), f i j ≤ f i j :=
iInf_le_of_le i <| iInf_le (f i) j
#align infi₂_le iInf₂_le
theorem le_iSup₂_of_le {f : ∀ i, κ i → α} (i : ι) (j : κ i) (h : a ≤ f i j) :
a ≤ ⨆ (i) (j), f i j :=
h.trans <| le_iSup₂ i j
#align le_supr₂_of_le le_iSup₂_of_le
theorem iInf₂_le_of_le {f : ∀ i, κ i → α} (i : ι) (j : κ i) (h : f i j ≤ a) :
⨅ (i) (j), f i j ≤ a :=
(iInf₂_le i j).trans h
#align infi₂_le_of_le iInf₂_le_of_le
theorem iSup_le (h : ∀ i, f i ≤ a) : iSup f ≤ a :=
sSup_le fun _ ⟨i, Eq⟩ => Eq ▸ h i
#align supr_le iSup_le
theorem le_iInf (h : ∀ i, a ≤ f i) : a ≤ iInf f :=
le_sInf fun _ ⟨i, Eq⟩ => Eq ▸ h i
#align le_infi le_iInf
theorem iSup₂_le {f : ∀ i, κ i → α} (h : ∀ i j, f i j ≤ a) : ⨆ (i) (j), f i j ≤ a :=
iSup_le fun i => iSup_le <| h i
#align supr₂_le iSup₂_le
theorem le_iInf₂ {f : ∀ i, κ i → α} (h : ∀ i j, a ≤ f i j) : a ≤ ⨅ (i) (j), f i j :=
le_iInf fun i => le_iInf <| h i
#align le_infi₂ le_iInf₂
theorem iSup₂_le_iSup (κ : ι → Sort*) (f : ι → α) : ⨆ (i) (_ : κ i), f i ≤ ⨆ i, f i :=
iSup₂_le fun i _ => le_iSup f i
#align supr₂_le_supr iSup₂_le_iSup
theorem iInf_le_iInf₂ (κ : ι → Sort*) (f : ι → α) : ⨅ i, f i ≤ ⨅ (i) (_ : κ i), f i :=
le_iInf₂ fun i _ => iInf_le f i
#align infi_le_infi₂ iInf_le_iInf₂
@[gcongr]
theorem iSup_mono (h : ∀ i, f i ≤ g i) : iSup f ≤ iSup g :=
iSup_le fun i => le_iSup_of_le i <| h i
#align supr_mono iSup_mono
@[gcongr]
theorem iInf_mono (h : ∀ i, f i ≤ g i) : iInf f ≤ iInf g :=
le_iInf fun i => iInf_le_of_le i <| h i
#align infi_mono iInf_mono
theorem iSup₂_mono {f g : ∀ i, κ i → α} (h : ∀ i j, f i j ≤ g i j) :
⨆ (i) (j), f i j ≤ ⨆ (i) (j), g i j :=
iSup_mono fun i => iSup_mono <| h i
#align supr₂_mono iSup₂_mono
theorem iInf₂_mono {f g : ∀ i, κ i → α} (h : ∀ i j, f i j ≤ g i j) :
⨅ (i) (j), f i j ≤ ⨅ (i) (j), g i j :=
iInf_mono fun i => iInf_mono <| h i
#align infi₂_mono iInf₂_mono
theorem iSup_mono' {g : ι' → α} (h : ∀ i, ∃ i', f i ≤ g i') : iSup f ≤ iSup g :=
iSup_le fun i => Exists.elim (h i) le_iSup_of_le
#align supr_mono' iSup_mono'
theorem iInf_mono' {g : ι' → α} (h : ∀ i', ∃ i, f i ≤ g i') : iInf f ≤ iInf g :=
le_iInf fun i' => Exists.elim (h i') iInf_le_of_le
#align infi_mono' iInf_mono'
theorem iSup₂_mono' {f : ∀ i, κ i → α} {g : ∀ i', κ' i' → α} (h : ∀ i j, ∃ i' j', f i j ≤ g i' j') :
⨆ (i) (j), f i j ≤ ⨆ (i) (j), g i j :=
iSup₂_le fun i j =>
let ⟨i', j', h⟩ := h i j
le_iSup₂_of_le i' j' h
#align supr₂_mono' iSup₂_mono'
theorem iInf₂_mono' {f : ∀ i, κ i → α} {g : ∀ i', κ' i' → α} (h : ∀ i j, ∃ i' j', f i' j' ≤ g i j) :
⨅ (i) (j), f i j ≤ ⨅ (i) (j), g i j :=
le_iInf₂ fun i j =>
let ⟨i', j', h⟩ := h i j
iInf₂_le_of_le i' j' h
#align infi₂_mono' iInf₂_mono'
theorem iSup_const_mono (h : ι → ι') : ⨆ _ : ι, a ≤ ⨆ _ : ι', a :=
iSup_le <| le_iSup _ ∘ h
#align supr_const_mono iSup_const_mono
theorem iInf_const_mono (h : ι' → ι) : ⨅ _ : ι, a ≤ ⨅ _ : ι', a :=
le_iInf <| iInf_le _ ∘ h
#align infi_const_mono iInf_const_mono
theorem iSup_iInf_le_iInf_iSup (f : ι → ι' → α) : ⨆ i, ⨅ j, f i j ≤ ⨅ j, ⨆ i, f i j :=
iSup_le fun i => iInf_mono fun j => le_iSup (fun i => f i j) i
#align supr_infi_le_infi_supr iSup_iInf_le_iInf_iSup
theorem biSup_mono {p q : ι → Prop} (hpq : ∀ i, p i → q i) :
⨆ (i) (_ : p i), f i ≤ ⨆ (i) (_ : q i), f i :=
iSup_mono fun i => iSup_const_mono (hpq i)
#align bsupr_mono biSup_mono
theorem biInf_mono {p q : ι → Prop} (hpq : ∀ i, p i → q i) :
⨅ (i) (_ : q i), f i ≤ ⨅ (i) (_ : p i), f i :=
iInf_mono fun i => iInf_const_mono (hpq i)
#align binfi_mono biInf_mono
@[simp]
theorem iSup_le_iff : iSup f ≤ a ↔ ∀ i, f i ≤ a :=
(isLUB_le_iff isLUB_iSup).trans forall_range_iff
#align supr_le_iff iSup_le_iff
@[simp]
theorem le_iInf_iff : a ≤ iInf f ↔ ∀ i, a ≤ f i :=
(le_isGLB_iff isGLB_iInf).trans forall_range_iff
#align le_infi_iff le_iInf_iff
theorem iSup₂_le_iff {f : ∀ i, κ i → α} : ⨆ (i) (j), f i j ≤ a ↔ ∀ i j, f i j ≤ a := by
simp_rw [iSup_le_iff]
#align supr₂_le_iff iSup₂_le_iff
theorem le_iInf₂_iff {f : ∀ i, κ i → α} : (a ≤ ⨅ (i) (j), f i j) ↔ ∀ i j, a ≤ f i j := by
simp_rw [le_iInf_iff]
#align le_infi₂_iff le_iInf₂_iff
theorem iSup_lt_iff : iSup f < a ↔ ∃ b, b < a ∧ ∀ i, f i ≤ b :=
⟨fun h => ⟨iSup f, h, le_iSup f⟩, fun ⟨_, h, hb⟩ => (iSup_le hb).trans_lt h⟩
#align supr_lt_iff iSup_lt_iff
theorem lt_iInf_iff : a < iInf f ↔ ∃ b, a < b ∧ ∀ i, b ≤ f i :=
⟨fun h => ⟨iInf f, h, iInf_le f⟩, fun ⟨_, h, hb⟩ => h.trans_le <| le_iInf hb⟩
#align lt_infi_iff lt_iInf_iff
theorem sSup_eq_iSup {s : Set α} : sSup s = ⨆ a ∈ s, a :=
le_antisymm (sSup_le le_iSup₂) (iSup₂_le fun _ => le_sSup)
#align Sup_eq_supr sSup_eq_iSup
theorem sInf_eq_iInf {s : Set α} : sInf s = ⨅ a ∈ s, a :=
@sSup_eq_iSup αᵒᵈ _ _
#align Inf_eq_infi sInf_eq_iInf
theorem Monotone.le_map_iSup [CompleteLattice β] {f : α → β} (hf : Monotone f) :
⨆ i, f (s i) ≤ f (iSup s) :=
iSup_le fun _ => hf <| le_iSup _ _
#align monotone.le_map_supr Monotone.le_map_iSup
theorem Antitone.le_map_iInf [CompleteLattice β] {f : α → β} (hf : Antitone f) :
⨆ i, f (s i) ≤ f (iInf s) :=
hf.dual_left.le_map_iSup
#align antitone.le_map_infi Antitone.le_map_iInf
theorem Monotone.le_map_iSup₂ [CompleteLattice β] {f : α → β} (hf : Monotone f) (s : ∀ i, κ i → α) :
⨆ (i) (j), f (s i j) ≤ f (⨆ (i) (j), s i j) :=
iSup₂_le fun _ _ => hf <| le_iSup₂ _ _
#align monotone.le_map_supr₂ Monotone.le_map_iSup₂
theorem Antitone.le_map_iInf₂ [CompleteLattice β] {f : α → β} (hf : Antitone f) (s : ∀ i, κ i → α) :
⨆ (i) (j), f (s i j) ≤ f (⨅ (i) (j), s i j) :=
hf.dual_left.le_map_iSup₂ _
#align antitone.le_map_infi₂ Antitone.le_map_iInf₂
theorem Monotone.le_map_sSup [CompleteLattice β] {s : Set α} {f : α → β} (hf : Monotone f) :
⨆ a ∈ s, f a ≤ f (sSup s) := by rw [sSup_eq_iSup]; exact hf.le_map_iSup₂ _
#align monotone.le_map_Sup Monotone.le_map_sSup
theorem Antitone.le_map_sInf [CompleteLattice β] {s : Set α} {f : α → β} (hf : Antitone f) :
⨆ a ∈ s, f a ≤ f (sInf s) :=
hf.dual_left.le_map_sSup
#align antitone.le_map_Inf Antitone.le_map_sInf
theorem OrderIso.map_iSup [CompleteLattice β] (f : α ≃o β) (x : ι → α) :
f (⨆ i, x i) = ⨆ i, f (x i) :=
eq_of_forall_ge_iff <| f.surjective.forall.2
fun x => by simp only [f.le_iff_le, iSup_le_iff]
#align order_iso.map_supr OrderIso.map_iSup
theorem OrderIso.map_iInf [CompleteLattice β] (f : α ≃o β) (x : ι → α) :
f (⨅ i, x i) = ⨅ i, f (x i) :=
OrderIso.map_iSup f.dual _
#align order_iso.map_infi OrderIso.map_iInf
theorem OrderIso.map_sSup [CompleteLattice β] (f : α ≃o β) (s : Set α) :
f (sSup s) = ⨆ a ∈ s, f a :=
by simp only [sSup_eq_iSup, OrderIso.map_iSup]
#align order_iso.map_Sup OrderIso.map_sSup
theorem OrderIso.map_sInf [CompleteLattice β] (f : α ≃o β) (s : Set α) :
f (sInf s) = ⨅ a ∈ s, f a :=
OrderIso.map_sSup f.dual _
#align order_iso.map_Inf OrderIso.map_sInf
theorem iSup_comp_le {ι' : Sort*} (f : ι' → α) (g : ι → ι') : ⨆ x, f (g x) ≤ ⨆ y, f y :=
iSup_mono' fun _ => ⟨_, le_rfl⟩
#align supr_comp_le iSup_comp_le
theorem le_iInf_comp {ι' : Sort*} (f : ι' → α) (g : ι → ι') : ⨅ y, f y ≤ ⨅ x, f (g x) :=
iInf_mono' fun _ => ⟨_, le_rfl⟩
#align le_infi_comp le_iInf_comp
theorem Monotone.iSup_comp_eq [Preorder β] {f : β → α} (hf : Monotone f) {s : ι → β}
(hs : ∀ x, ∃ i, x ≤ s i) : ⨆ x, f (s x) = ⨆ y, f y :=
le_antisymm (iSup_comp_le _ _) (iSup_mono' fun x => (hs x).imp fun _ hi => hf hi)
#align monotone.supr_comp_eq Monotone.iSup_comp_eq
theorem Monotone.iInf_comp_eq [Preorder β] {f : β → α} (hf : Monotone f) {s : ι → β}
(hs : ∀ x, ∃ i, s i ≤ x) : ⨅ x, f (s x) = ⨅ y, f y :=