Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
adf4050
run mk_all
pfaffelh Jan 14, 2026
c5c0f32
Merge remote-tracking branch 'upstream/master'
pfaffelh Mar 2, 2026
3fffde0
like pfaffelh_compactSystem but in the module system
pfaffelh Mar 2, 2026
aea7a85
update one lemma
pfaffelh Mar 2, 2026
00181ac
update one lemma2
pfaffelh Mar 2, 2026
b95c809
Merge branch 'master' into pfaffelh_compactSystem10
RemyDegenne Mar 3, 2026
47ab101
golf; revert an import
RemyDegenne Mar 3, 2026
4ee793d
golf
RemyDegenne Mar 3, 2026
e778b5e
move and golf
RemyDegenne Mar 3, 2026
c4c2236
golf
RemyDegenne Mar 3, 2026
a2feb8f
follow in-person review: switch to sets of sets
RemyDegenne Mar 3, 2026
41caa5a
extract lemmas
RemyDegenne Mar 3, 2026
0493e62
init
pfaffelh Mar 3, 2026
1111522
Apply suggestions from code review
RemyDegenne Mar 4, 2026
c109d6c
fix
RemyDegenne Mar 4, 2026
37cd152
review
RemyDegenne Mar 4, 2026
9286ee2
names
RemyDegenne Mar 4, 2026
7eee760
review
RemyDegenne Mar 4, 2026
0161fd7
add accumulate versions
RemyDegenne Mar 4, 2026
8269323
flip iff
RemyDegenne Mar 4, 2026
a1c9178
Merge branch 'master' into pfaffelh_compactSystem10
RemyDegenne Mar 4, 2026
a17c917
add accumulate lemma
RemyDegenne Mar 4, 2026
29b83d4
definie FiniteUnion
RemyDegenne Mar 4, 2026
42ec551
docstrings
RemyDegenne Mar 4, 2026
74b7403
fix
RemyDegenne Mar 4, 2026
a73d948
Merge branch 'RD_finiteUnion' into pfaffelh_compactSystem11
RemyDegenne Mar 4, 2026
86f567d
Merge branch 'pfaffelh_compactSystem10' into pfaffelh_compactSystem11
RemyDegenne Mar 4, 2026
73980ce
some cleaning work
RemyDegenne Mar 4, 2026
091609e
minor changes
RemyDegenne Mar 4, 2026
d9d3fdd
Merge branch 'master' into pfaffelh_compactSystem11
RemyDegenne Mar 6, 2026
66c478f
undo
RemyDegenne Mar 6, 2026
ffab3ed
undo
RemyDegenne Mar 6, 2026
a7c3ddf
undo
RemyDegenne Mar 6, 2026
3e29fcb
undo
RemyDegenne Mar 6, 2026
740ef91
use supClosure instead of a new def
RemyDegenne Mar 6, 2026
d4508aa
Merge branch 'master' into pfaffelh_compactSystem11
RemyDegenne Mar 6, 2026
36d9e8d
Merge branch 'master' into pfaffelh_compactSystem11
RemyDegenne Apr 22, 2026
885ea1f
use Fin.rec0
RemyDegenne Apr 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Mathlib/Data/Set/Dissipate.lean
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ theorem dissipate_def [LE α] {x : α} : dissipate s x = ⋂ y ≤ x, s y := rfl
theorem dissipate_eq_biInter_lt {s : ℕ → Set β} {n : ℕ} : dissipate s n = ⋂ k < n + 1, s k := by
simp_rw [Nat.lt_add_one_iff, dissipate]

theorem dissipate_eq_ofFin {s : ℕ → Set β} {n : ℕ} : dissipate s n = ⋂ (k : Fin (n + 1)), s k := by
rw [dissipate]
ext x
simp only [mem_iInter]
refine ⟨fun h i ↦ h i.val (Fin.is_le i), fun h i hi ↦ h ⟨i, Nat.lt_succ_of_le hi⟩⟩

@[simp]
theorem mem_dissipate [LE α] {x : α} {z : β} : z ∈ dissipate s x ↔ ∀ y ≤ x, z ∈ s y := by
simp [dissipate_def]
Expand Down
266 changes: 266 additions & 0 deletions Mathlib/Topology/Compactness/CompactSystem.lean
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
-/
module

public import Mathlib.Data.Set.Constructions
public import Mathlib.MeasureTheory.PiSystem
public import Mathlib.Order.SupClosed
public import Mathlib.Topology.Separation.Hausdorff

/-!
Expand All @@ -24,6 +26,8 @@
gives a compact system.
* `isCompactSystem_isCompact_isClosed`: The set of closed and compact sets is a compact system.
* `isCompactSystem_isCompact`: In a `T2Space`, the set of compact sets is a compact system.
* `IsCompactSystem.union_isCompactSystem`If `IsCompactSystem S`, the set of finite unions of sets
in `S` is also a compact system.
-/

@[expose] public section
Expand Down Expand Up @@ -62,6 +66,12 @@
∀ C : ℕ → Set α, (∀ i, C i ∈ S) → (∀ n, (dissipate C n).Nonempty) → (⋂ i, C i).Nonempty :=
⟨nonempty_iInter, of_nonempty_iInter⟩

lemma iff_nonempty_iInter_of_lt' (S : Set (Set α)) : IsCompactSystem S ↔
∀ C : ℕ → Set α, (∀ i, C i ∈ S) →
(∀ n, (⋂ k : Fin (n + 1), C k).Nonempty) → (⋂ i, C i).Nonempty := by
rw [iff_nonempty_iInter]
simp_rw [dissipate_eq_ofFin]

@[simp]
lemma of_IsEmpty [IsEmpty α] (S : Set (Set α)) : IsCompactSystem S :=
fun s _ _ ↦ ⟨0, Set.eq_empty_of_isEmpty (dissipate s 0)⟩
Expand Down Expand Up @@ -181,3 +191,259 @@
(isCompactSystem_isCompact_isClosed α).insert_univ

end IsCompactIsClosed

section PrefixInduction

-- Should this section be private, or moved to a different file?

/- In this section, we prove a general induction principle, which we need for the construction
`Nat.prefixInduction q step0 step : (k : ℕ) → (β k)` based on some
`q : (n : ℕ) → (k : (i : Fin n) → (β i)) → Prop`. For
the induction start, `step0 : q 0 _` always holds since `Fin 0` cannot be satisfied, and
`step : (n : ℕ) → (k : (i : Fin n) → β i) → q n k → { a : β n // q (n + 1) (Fin.snoc k a) })`
`(n : ℕ) : β n` constructs the next element satisfying `q (n + 1) _` from a proof of `q n k`
and finding the next element.

In comparison to other induction principles, the proofs of `q n k` are needed in order to find
the next element. -/


variable {β : ℕ → Type*} (q : ∀ n, (k : (i : Fin n) → β i) → Prop) (step0 : q 0 Fin.rec0)
(step : ∀ n (k : (i : Fin n) → β i) (_ : q n k), { a : β n // q (n + 1) (Fin.snoc k a)})

def Nat.prefixInduction.aux : ∀ (n : Nat), { k : (i : Fin n) → β i // q n k }

Check failure on line 214 in Mathlib/Topology/Compactness/CompactSystem.lean

View workflow job for this annotation

GitHub Actions / ci (fork) / Build

@Nat.prefixInduction.aux definition missing documentation string
| 0 => ⟨Fin.rec0, step0⟩
| n + 1 =>
let ⟨k, hk⟩ := aux n
let ⟨a, ha⟩ := step n k hk
⟨Fin.snoc k a, ha⟩

theorem Nat.prefixInduction.auxConsistent (n : ℕ) (i : Fin n) :
(Nat.prefixInduction.aux q step0 step (i + 1)).1 (Fin.last i) =
(Nat.prefixInduction.aux q step0 step n).1 i := by
revert i
induction n with
| zero => simp
| succ n ih =>
apply Fin.lastCases
case last => simp
case cast =>
intro i
simp_rw [Fin.val_castSucc, ih, aux]
simp

/-- An induction principle showing that `q : (n : ℕ) → (k : (i : Fin n) → (β i)) → Prop` holds
for all `n`. `step0` is satisfied by construction since `Fin 0` is empty.
In the induction `step`, we use that `q n k` holds for showing that `q (n + 1) (Fin.snoc k a)`
holds for some `a : β n`. -/
def Nat.prefixInduction (n : Nat) : β n :=
(Nat.prefixInduction.aux q step0 step (n + 1)).1 (Fin.last n)

theorem Nat.prefixInduction_spec (n : Nat) : q n (Nat.prefixInduction q step0 step ·) := by
cases n with
| zero => convert step0
| succ n =>
have hk := (Nat.prefixInduction.aux q step0 step (n + 1)).2
convert hk with i
apply Nat.prefixInduction.auxConsistent

/- Often, `step` can only be proved by showing an `∃` statement. For this case, we use `step'`. -/
variable (step' : ∀ n (k : (i : Fin n) → β i) (_ : q n k), ∃ a, q (n + 1) (Fin.snoc k a))

/-- This version is noncomputable since it relies on an `∃`-statement -/
noncomputable def Nat.prefixInduction' (n : Nat) : β n :=
(Nat.prefixInduction.aux q step0
(fun n k hn ↦ ⟨(step' n k hn).choose, (step' n k hn).choose_spec⟩) (n + 1)).1 (Fin.last n)

theorem Nat.prefixInduction'_spec (n : Nat) : q n (Nat.prefixInduction' q step0 step' ·) := by
apply prefixInduction_spec

end PrefixInduction

section Union

/- For a reference of `union.isCompactSystem`, see Pfanzagl, Pierlo.
Compact Systems of Sets. Springer, 1966, Lemma 1.4. -/

namespace IsCompactSystem

variable {L : ℕ → Finset (Set α)} {n : ℕ} {K : (k : Fin n) → Set α}

/-- `q n K` is the joint property that `∀ (k : Fin n), K k ∈ L k` and
`∀ N, (⋂ (j : Fin n), K j) ∩ (⋂ (k < N), ⋃₀ ↑(L (n + k))) ≠ ∅`.` holds. -/
def q (L : ℕ → Finset (Set α)) (n : ℕ) (K : (k : Fin n) → Set α) : Prop :=
(∀ k : Fin n, K k ∈ L k) ∧ ∀ N, ((⋂ j, K j) ∩ ⋂ k < N, ⋃₀ L (n + k)).Nonempty

lemma q_iff_iInter (hK : ∀ k : Fin n, K k ∈ L k) :
q L n K ↔
∀ N, ((⋂ (j : ℕ) (hj : j < n), K ⟨j, hj⟩) ∩
(⋂ k < N, ⋃₀ L (n + k))).Nonempty := by
simp only [q, hK, implies_true, true_and]
congr! 2 with N
ext
simp
grind

lemma q_snoc_iff_iInter (hK : ∀ k : Fin n, K k ∈ L k) (y : Set α) :
q L (n + 1) (Fin.snoc K y) ↔
y ∈ L n ∧
(∀ N, ((⋂ (j : ℕ) (hj : j < n), K ⟨j, hj⟩) ∩ y ∩ (⋂ k < N, ⋃₀ L (n + k))).Nonempty) := by
simp only [q]
have h_imp : q L (n + 1) (Fin.snoc K y) → y ∈ L n := by
intro ⟨h_mem, h⟩
specialize h_mem ⟨n, by grind⟩
simpa [Fin.snoc] using h_mem
refine ⟨fun h' ↦ ⟨h_imp h', fun N ↦ ?_⟩, fun ⟨hy, h⟩ ↦ ⟨fun k ↦ ?_, fun N ↦ ?_⟩⟩
· have ⟨h_mem, h⟩ := h'
obtain ⟨x, ⟨hx1, hx2⟩⟩ := h N
use x
simp only [mem_iInter, mem_sUnion, SetLike.mem_coe, mem_inter_iff] at hx1 hx2 ⊢
refine ⟨⟨fun i hi ↦ ?_, ?_⟩, fun i hi ↦ ?_⟩
· simpa [Fin.snoc, hi] using hx1 ⟨i, hi.trans_le (le_succ n)⟩
· simpa [Fin.snoc] using hx1 ⟨n, Nat.lt_add_one n⟩
· have hy := h_imp h'
cases i with
| zero =>
specialize hx1 ⟨n, Nat.lt_add_one n⟩
simp only [Fin.snoc, lt_self_iff_false, ↓reduceDIte, cast_eq] at hx1
exact ⟨y, hy, hx1⟩
| succ n =>
have hj' : n < N := by grind
grind
· unfold Fin.snoc
by_cases hkn : k = n
· simpa [hkn]
· have hkn' : k < n := by grind
grind
· specialize h (N + 1)
rw [Set.inter_nonempty_iff_exists_left] at h ⊢
obtain ⟨x, ⟨hx1, hx2⟩⟩ := h
use x
simp only [mem_inter_iff, mem_iInter, mem_sUnion, SetLike.mem_coe] at hx1 hx2 ⊢
exact ⟨by simp [Fin.snoc]; grind, by grind⟩

lemma step0 {L : ℕ → Finset (Set α)} (hL : ∀ N, (⋂ k < N, ⋃₀ (L k : Set (Set α))).Nonempty) :
q L 0 Fin.rec0 :=
⟨by simp, by simpa using hL⟩

lemma inter_sUnion_eq_empty (s : Set α) (L : Set (Set α)) :
(∀ a ∈ L, s ∩ a = ∅) ↔ s ∩ ⋃₀ L = ∅ := by
simp_rw [← disjoint_iff_inter_eq_empty]
exact Iff.symm disjoint_sUnion_right

lemma step' {L : ℕ → Finset (Set α)} (n : ℕ) (K : (k : Fin n) → Set α) (hK : q L n K) :
∃ a, q L (n + 1) (Fin.snoc K a) := by
have hK' := hK.1
simp_rw [q_iff_iInter hK'] at hK
simp_rw [q_snoc_iff_iInter hK'] at ⊢
by_contra! h
choose b hb using h
classical
let b' := fun x ↦ dite (x ∈ (L n)) (fun c ↦ b x c) (fun _ ↦ 0)
have hs : (L n : Set (Set α)).Nonempty := by
specialize hK 1
rw [Set.nonempty_def] at hK ⊢
simp only [lt_one_iff, iInter_iInter_eq_left, add_zero, mem_inter_iff, mem_iInter, mem_sUnion,
Finset.mem_coe] at hK ⊢
obtain ⟨x, ⟨hx1, ⟨t, ⟨ht1, ht2⟩⟩⟩⟩ := hK
use t
obtain ⟨K0Max, ⟨hK0₁, hK0₂⟩⟩ := Finset.exists_max_image (L (Fin.last n)) b' hs
simp_rw [Set.nonempty_iff_ne_empty] at hK
apply hK (b' K0Max + 1)
have h₂ (a : Set α) (ha : a ∈ L n) :
⋂ k < b' K0Max, ⋃₀ L (n + k) ⊆ ⋂ k < b a ha, ⋃₀ (L (n + k) : Set (Set α)) := by
intro x hx
simp only [mem_iInter, mem_sUnion, SetLike.mem_coe] at hx ⊢
have f : b' a = b a ha := by simp [b', ha]
exact fun i hi ↦ hx i (hi.trans_le (f ▸ hK0₂ a ha))
have h₃ (a : Set α) (ha : a ∈ L (Fin.last n)) : (⋂ (j) (hj : j < n), K ⟨j, hj⟩) ∩ a ∩
⋂ k < b' K0Max, ⋃₀ L (n + k) = ∅ := by
rw [← subset_empty_iff, ← hb a ha]
exact inter_subset_inter (fun ⦃a⦄ a ↦ a) (h₂ a ha)
simp_rw [inter_comm, inter_assoc] at h₃
simp_rw [← disjoint_iff_inter_eq_empty] at h₃ ⊢
simp only [Fin.val_last] at h₃
have h₃'' := disjoint_iff_inter_eq_empty.mp (disjoint_sUnion_left.mpr h₃)
rw [inter_comm, inter_assoc, ← disjoint_iff_inter_eq_empty] at h₃''
apply disjoint_of_subset (fun ⦃a⦄ a ↦ a) _ h₃''
simp only [subset_inter_iff, subset_iInter_iff]
refine ⟨fun i hi x hx ↦ ?_, fun x hx ↦ ?_⟩
· simp only [mem_iInter, mem_sUnion, SetLike.mem_coe] at hx ⊢
obtain ⟨t, ht⟩ := hx i (lt_trans hi (Nat.lt_add_one _))
use t
· simp only [mem_iInter, mem_sUnion, SetLike.mem_coe] at hx ⊢
obtain ⟨t, ht⟩ := hx 0 (zero_lt_succ _)
use t
simpa

/-- For `L : ℕ → Finset (Set α)` such that `L n ⊆ K` and
`h : ∀ N, ⋂ k < N, ⋃₀ L k ≠ ∅`, `memOfUnion h n` is some `K : ℕ → Set α` such that `K n ∈ L n`
for all `n` (this is `prop₀`) and `∀ N, ⋂ (j < n, K j) ∩ ⋂ (k < N), (⋃₀ L (n + k)) ≠ ∅`
(this is `prop₁`.) -/
noncomputable def memOfUnion (L : ℕ → Finset (Set α))
(hL : ∀ N, (⋂ k < N, ⋃₀ (L k : Set (Set α))).Nonempty) :
ℕ → Set α :=
Nat.prefixInduction' (q L) (step0 hL) step'

theorem memOfUnion.spec (L : ℕ → Finset (Set α))
(hL : ∀ N, (⋂ k < N, ⋃₀ (L k : Set (Set α))).Nonempty) (n : ℕ) :
q L n (fun k : Fin n ↦ memOfUnion L hL k) :=
Nat.prefixInduction'_spec (β := fun _ ↦ Set α) (q L) (step0 hL) step' n

lemma sInter_memOfUnion_nonempty (L : ℕ → Finset (Set α))
(hL : ∀ N, (⋂ k, ⋂ (_ : k < N), ⋃₀ (L k : Set (Set α))).Nonempty) (n : ℕ) :
(⋂ (j : Fin n), memOfUnion L hL j).Nonempty := by
simpa using (memOfUnion.spec L hL n).2 0

lemma sInter_memOfUnion_isSubset (L : ℕ → Finset (Set α))
(hL : ∀ N, (⋂ k < N, ⋃₀ (L k : Set (Set α))).Nonempty) :
(⋂ j, memOfUnion L hL j) ⊆ ⋂ k, ⋃₀ L k := by
exact iInter_mono <| fun n ↦
subset_sUnion_of_subset (L n) (memOfUnion L hL n) (fun ⦃a⦄ a ↦ a)
((memOfUnion.spec L hL (n + 1)).1 ⟨n, by grind⟩)

lemma mem_subClosure_set_iff (s : Set α) :
s ∈ supClosure S ↔ ∃ L : Finset (Set α), L.Nonempty ∧ s = ⋃₀ L ∧ ↑L ⊆ S := by
refine ⟨fun ⟨L, hL⟩ ↦ ?_, fun h ↦ ?_⟩
· choose hL_nonempty hL_subset hL_sup using hL
refine ⟨L, hL_nonempty, ?_, hL_subset⟩
rw [← hL_sup, ← Finset.sup_id_set_eq_sUnion, Finset.sup'_eq_sup]
· obtain ⟨L, hL_nonempty, hL_eq, hL_subset⟩ := h
refine ⟨L, hL_nonempty, hL_subset, ?_⟩
rw [hL_eq, ← Finset.sup_id_set_eq_sUnion, Finset.sup'_eq_sup]

lemma mem_subClosure_insert_empty_iff (s : Set α) :
s ∈ supClosure (insert ∅ S) ↔
∃ L : Finset (Set α), s = ⋃₀ L ∧ ↑L ⊆ insert ∅ S := by
rw [mem_subClosure_set_iff]
refine ⟨fun ⟨L, hL_nonempty, hL_eq, hL_subset⟩ ↦ ⟨L, hL_eq, hL_subset⟩,
fun ⟨L, hL_eq, hL_subset⟩ ↦ ?_⟩
classical
refine ⟨if L.Nonempty then L else {∅}, ?_, ?_, ?_⟩
· split_ifs
· simpa
· simp
· rcases Finset.eq_empty_or_nonempty L with (rfl | hL_nonempty)
· simpa using hL_eq
· simpa [hL_nonempty]
· intro
simp
grind

/- If `IsCompactSystem S`, the set of finite unions of sets in `S` is also a compact system. -/
theorem isCompactSystem_supClosure_insert_empty (S : Set (Set α)) (hS : IsCompactSystem S) :
IsCompactSystem (supClosure (insert ∅ S)) := by
simp_rw [isCompactSystem_iff_nonempty_iInter_of_lt, mem_subClosure_insert_empty_iff]
intro C hi
choose L' hL'_eq hL'_mem using hi
simp_rw [hL'_eq]
intro hL'_nonempty
refine Nonempty.mono (sInter_memOfUnion_isSubset L' hL'_nonempty) ?_
exact (IsCompactSystem.iff_nonempty_iInter_of_lt' (insert ∅ S)).mp hS.insert_empty
(fun k ↦ memOfUnion L' hL'_nonempty k)
(fun i ↦ hL'_mem i <| (memOfUnion.spec L' hL'_nonempty (i + 1)).1 ⟨i, by grind⟩)
(fun n ↦ sInter_memOfUnion_nonempty L' hL'_nonempty (n + 1))

end IsCompactSystem

end Union
Loading