-
Notifications
You must be signed in to change notification settings - Fork 273
/
Cofinite.lean
235 lines (183 loc) · 11.3 KB
/
Cofinite.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
/-
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, Jeremy Avigad, Yury Kudryashov
-/
import Mathlib.Order.Filter.AtTopBot
import Mathlib.Order.Filter.Pi
#align_import order.filter.cofinite from "leanprover-community/mathlib"@"8631e2d5ea77f6c13054d9151d82b83069680cb1"
/-!
# The cofinite filter
In this file we define
`Filter.cofinite`: the filter of sets with finite complement
and prove its basic properties. In particular, we prove that for `ℕ` it is equal to `Filter.atTop`.
## TODO
Define filters for other cardinalities of the complement.
-/
open Set Function
variable {ι α β : Type*} {l : Filter α}
namespace Filter
/-- The cofinite filter is the filter of subsets whose complements are finite. -/
def cofinite : Filter α :=
comk Set.Finite finite_empty (fun _t ht _s hsub ↦ ht.subset hsub) fun _ h _ ↦ h.union
#align filter.cofinite Filter.cofinite
@[simp]
theorem mem_cofinite {s : Set α} : s ∈ @cofinite α ↔ sᶜ.Finite :=
Iff.rfl
#align filter.mem_cofinite Filter.mem_cofinite
@[simp]
theorem eventually_cofinite {p : α → Prop} : (∀ᶠ x in cofinite, p x) ↔ { x | ¬p x }.Finite :=
Iff.rfl
#align filter.eventually_cofinite Filter.eventually_cofinite
theorem hasBasis_cofinite : HasBasis cofinite (fun s : Set α => s.Finite) compl :=
⟨fun s =>
⟨fun h => ⟨sᶜ, h, (compl_compl s).subset⟩, fun ⟨_t, htf, hts⟩ =>
htf.subset <| compl_subset_comm.2 hts⟩⟩
#align filter.has_basis_cofinite Filter.hasBasis_cofinite
instance cofinite_neBot [Infinite α] : NeBot (@cofinite α) :=
hasBasis_cofinite.neBot_iff.2 fun hs => hs.infinite_compl.nonempty
#align filter.cofinite_ne_bot Filter.cofinite_neBot
@[simp]
theorem cofinite_eq_bot_iff : @cofinite α = ⊥ ↔ Finite α := by
simp [← empty_mem_iff_bot, finite_univ_iff]
@[simp]
theorem cofinite_eq_bot [Finite α] : @cofinite α = ⊥ := cofinite_eq_bot_iff.2 ‹_›
theorem frequently_cofinite_iff_infinite {p : α → Prop} :
(∃ᶠ x in cofinite, p x) ↔ Set.Infinite { x | p x } := by
simp only [Filter.Frequently, eventually_cofinite, not_not, Set.Infinite]
#align filter.frequently_cofinite_iff_infinite Filter.frequently_cofinite_iff_infinite
lemma frequently_cofinite_mem_iff_infinite {s : Set α} : (∃ᶠ x in cofinite, x ∈ s) ↔ s.Infinite :=
frequently_cofinite_iff_infinite
alias ⟨_, _root_.Set.Infinite.frequently_cofinite⟩ := frequently_cofinite_mem_iff_infinite
@[simp]
lemma cofinite_inf_principal_neBot_iff {s : Set α} : (cofinite ⊓ 𝓟 s).NeBot ↔ s.Infinite :=
frequently_mem_iff_neBot.symm.trans frequently_cofinite_mem_iff_infinite
alias ⟨_, _root_.Set.Infinite.cofinite_inf_principal_neBot⟩ := cofinite_inf_principal_neBot_iff
theorem _root_.Set.Finite.compl_mem_cofinite {s : Set α} (hs : s.Finite) : sᶜ ∈ @cofinite α :=
mem_cofinite.2 <| (compl_compl s).symm ▸ hs
#align set.finite.compl_mem_cofinite Set.Finite.compl_mem_cofinite
theorem _root_.Set.Finite.eventually_cofinite_nmem {s : Set α} (hs : s.Finite) :
∀ᶠ x in cofinite, x ∉ s :=
hs.compl_mem_cofinite
#align set.finite.eventually_cofinite_nmem Set.Finite.eventually_cofinite_nmem
theorem _root_.Finset.eventually_cofinite_nmem (s : Finset α) : ∀ᶠ x in cofinite, x ∉ s :=
s.finite_toSet.eventually_cofinite_nmem
#align finset.eventually_cofinite_nmem Finset.eventually_cofinite_nmem
theorem _root_.Set.infinite_iff_frequently_cofinite {s : Set α} :
Set.Infinite s ↔ ∃ᶠ x in cofinite, x ∈ s :=
frequently_cofinite_iff_infinite.symm
#align set.infinite_iff_frequently_cofinite Set.infinite_iff_frequently_cofinite
theorem eventually_cofinite_ne (x : α) : ∀ᶠ a in cofinite, a ≠ x :=
(Set.finite_singleton x).eventually_cofinite_nmem
#align filter.eventually_cofinite_ne Filter.eventually_cofinite_ne
theorem le_cofinite_iff_compl_singleton_mem : l ≤ cofinite ↔ ∀ x, {x}ᶜ ∈ l := by
refine' ⟨fun h x => h (finite_singleton x).compl_mem_cofinite, fun h s (hs : sᶜ.Finite) => _⟩
rw [← compl_compl s, ← biUnion_of_singleton sᶜ, compl_iUnion₂, Filter.biInter_mem hs]
exact fun x _ => h x
#align filter.le_cofinite_iff_compl_singleton_mem Filter.le_cofinite_iff_compl_singleton_mem
theorem le_cofinite_iff_eventually_ne : l ≤ cofinite ↔ ∀ x, ∀ᶠ y in l, y ≠ x :=
le_cofinite_iff_compl_singleton_mem
#align filter.le_cofinite_iff_eventually_ne Filter.le_cofinite_iff_eventually_ne
/-- If `α` is a preorder with no maximal element, then `atTop ≤ cofinite`. -/
theorem atTop_le_cofinite [Preorder α] [NoMaxOrder α] : (atTop : Filter α) ≤ cofinite :=
le_cofinite_iff_eventually_ne.mpr eventually_ne_atTop
#align filter.at_top_le_cofinite Filter.atTop_le_cofinite
theorem comap_cofinite_le (f : α → β) : comap f cofinite ≤ cofinite :=
le_cofinite_iff_eventually_ne.mpr fun x =>
mem_comap.2 ⟨{f x}ᶜ, (finite_singleton _).compl_mem_cofinite, fun _ => ne_of_apply_ne f⟩
#align filter.comap_cofinite_le Filter.comap_cofinite_le
/-- The coproduct of the cofinite filters on two types is the cofinite filter on their product. -/
theorem coprod_cofinite : (cofinite : Filter α).coprod (cofinite : Filter β) = cofinite :=
Filter.coext fun s => by
simp only [compl_mem_coprod, mem_cofinite, compl_compl, finite_image_fst_and_snd_iff]
#align filter.coprod_cofinite Filter.coprod_cofinite
theorem coprodᵢ_cofinite {α : ι → Type*} [Finite ι] :
(Filter.coprodᵢ fun i => (cofinite : Filter (α i))) = cofinite :=
Filter.coext fun s => by
simp only [compl_mem_coprodᵢ, mem_cofinite, compl_compl, forall_finite_image_eval_iff]
set_option linter.uppercaseLean3 false in
#align filter.Coprod_cofinite Filter.coprodᵢ_cofinite
theorem disjoint_cofinite_left : Disjoint cofinite l ↔ ∃ s ∈ l, Set.Finite s := by
simp [l.basis_sets.disjoint_iff_right]
#align filter.disjoint_cofinite_left Filter.disjoint_cofinite_left
theorem disjoint_cofinite_right : Disjoint l cofinite ↔ ∃ s ∈ l, Set.Finite s :=
disjoint_comm.trans disjoint_cofinite_left
#align filter.disjoint_cofinite_right Filter.disjoint_cofinite_right
/-- If `l ≥ Filter.cofinite` is a countably generated filter, then `l.ker` is cocountable. -/
theorem countable_compl_ker [l.IsCountablyGenerated] (h : cofinite ≤ l) : Set.Countable l.kerᶜ := by
rcases exists_antitone_basis l with ⟨s, hs⟩
simp only [hs.ker, iInter_true, compl_iInter]
exact countable_iUnion fun n ↦ Set.Finite.countable <| h <| hs.mem _
/-- If `f` tends to a countably generated filter `l` along `Filter.cofinite`,
then for all but countably many elements, `f x ∈ l.ker`. -/
theorem Tendsto.countable_compl_preimage_ker {f : α → β}
{l : Filter β} [l.IsCountablyGenerated] (h : Tendsto f cofinite l) :
Set.Countable (f ⁻¹' l.ker)ᶜ := by rw [← ker_comap]; exact countable_compl_ker h.le_comap
end Filter
open Filter
lemma Set.Finite.cofinite_inf_principal_compl {s : Set α} (hs : s.Finite) :
cofinite ⊓ 𝓟 sᶜ = cofinite := by
simpa using hs.compl_mem_cofinite
lemma Set.Finite.cofinite_inf_principal_diff {s t : Set α} (ht : t.Finite) :
cofinite ⊓ 𝓟 (s \ t) = cofinite ⊓ 𝓟 s := by
rw [diff_eq, ← inf_principal, ← inf_assoc, inf_right_comm, ht.cofinite_inf_principal_compl]
/-- For natural numbers the filters `Filter.cofinite` and `Filter.atTop` coincide. -/
theorem Nat.cofinite_eq_atTop : @cofinite ℕ = atTop := by
refine' le_antisymm _ atTop_le_cofinite
refine' atTop_basis.ge_iff.2 fun N _ => _
simpa only [mem_cofinite, compl_Ici] using finite_lt_nat N
#align nat.cofinite_eq_at_top Nat.cofinite_eq_atTop
theorem Nat.frequently_atTop_iff_infinite {p : ℕ → Prop} :
(∃ᶠ n in atTop, p n) ↔ Set.Infinite { n | p n } := by
rw [← Nat.cofinite_eq_atTop, frequently_cofinite_iff_infinite]
#align nat.frequently_at_top_iff_infinite Nat.frequently_atTop_iff_infinite
lemma Nat.eventually_pos : ∀ᶠ (k : ℕ) in Filter.atTop, 0 < k :=
Filter.eventually_of_mem (Filter.mem_atTop_sets.mpr ⟨1, fun _ hx ↦ hx⟩) (fun _ hx ↦ hx)
theorem Filter.Tendsto.exists_within_forall_le {α β : Type*} [LinearOrder β] {s : Set α}
(hs : s.Nonempty) {f : α → β} (hf : Filter.Tendsto f Filter.cofinite Filter.atTop) :
∃ a₀ ∈ s, ∀ a ∈ s, f a₀ ≤ f a := by
rcases em (∃ y ∈ s, ∃ x, f y < x) with (⟨y, hys, x, hx⟩ | not_all_top)
· -- the set of points `{y | f y < x}` is nonempty and finite, so we take `min` over this set
have : { y | ¬x ≤ f y }.Finite := Filter.eventually_cofinite.mp (tendsto_atTop.1 hf x)
simp only [not_le] at this
obtain ⟨a₀, ⟨ha₀ : f a₀ < x, ha₀s⟩, others_bigger⟩ :=
exists_min_image _ f (this.inter_of_left s) ⟨y, hx, hys⟩
refine' ⟨a₀, ha₀s, fun a has => (lt_or_le (f a) x).elim _ (le_trans ha₀.le)⟩
exact fun h => others_bigger a ⟨h, has⟩
· -- in this case, f is constant because all values are at top
push_neg at not_all_top
obtain ⟨a₀, ha₀s⟩ := hs
exact ⟨a₀, ha₀s, fun a ha => not_all_top a ha (f a₀)⟩
#align filter.tendsto.exists_within_forall_le Filter.Tendsto.exists_within_forall_le
theorem Filter.Tendsto.exists_forall_le [Nonempty α] [LinearOrder β] {f : α → β}
(hf : Tendsto f cofinite atTop) : ∃ a₀, ∀ a, f a₀ ≤ f a :=
let ⟨a₀, _, ha₀⟩ := hf.exists_within_forall_le univ_nonempty
⟨a₀, fun a => ha₀ a (mem_univ _)⟩
#align filter.tendsto.exists_forall_le Filter.Tendsto.exists_forall_le
theorem Filter.Tendsto.exists_within_forall_ge [LinearOrder β] {s : Set α} (hs : s.Nonempty)
{f : α → β} (hf : Filter.Tendsto f Filter.cofinite Filter.atBot) :
∃ a₀ ∈ s, ∀ a ∈ s, f a ≤ f a₀ :=
@Filter.Tendsto.exists_within_forall_le _ βᵒᵈ _ _ hs _ hf
#align filter.tendsto.exists_within_forall_ge Filter.Tendsto.exists_within_forall_ge
theorem Filter.Tendsto.exists_forall_ge [Nonempty α] [LinearOrder β] {f : α → β}
(hf : Tendsto f cofinite atBot) : ∃ a₀, ∀ a, f a ≤ f a₀ :=
@Filter.Tendsto.exists_forall_le _ βᵒᵈ _ _ _ hf
#align filter.tendsto.exists_forall_ge Filter.Tendsto.exists_forall_ge
theorem Function.Surjective.le_map_cofinite {f : α → β} (hf : Surjective f) :
cofinite ≤ map f cofinite := fun _ h => .of_preimage h hf
/-- For an injective function `f`, inverse images of finite sets are finite. See also
`Filter.comap_cofinite_le` and `Function.Injective.comap_cofinite_eq`. -/
theorem Function.Injective.tendsto_cofinite {f : α → β} (hf : Injective f) :
Tendsto f cofinite cofinite := fun _ h => h.preimage (hf.injOn _)
#align function.injective.tendsto_cofinite Function.Injective.tendsto_cofinite
/-- The pullback of the `Filter.cofinite` under an injective function is equal to `Filter.cofinite`.
See also `Filter.comap_cofinite_le` and `Function.Injective.tendsto_cofinite`. -/
theorem Function.Injective.comap_cofinite_eq {f : α → β} (hf : Injective f) :
comap f cofinite = cofinite :=
(comap_cofinite_le f).antisymm hf.tendsto_cofinite.le_comap
#align function.injective.comap_cofinite_eq Function.Injective.comap_cofinite_eq
/-- An injective sequence `f : ℕ → ℕ` tends to infinity at infinity. -/
theorem Function.Injective.nat_tendsto_atTop {f : ℕ → ℕ} (hf : Injective f) :
Tendsto f atTop atTop :=
Nat.cofinite_eq_atTop ▸ hf.tendsto_cofinite
#align function.injective.nat_tendsto_at_top Function.Injective.nat_tendsto_atTop