Skip to content

Commit c724781

Browse files
committed
feat: club sets (#37677)
In set theory, a club set is a subset of an ordinal of uncountable cofinality, which is closed in the order topology, and unbounded within the ordinal. We generalize this notion to that of a club set in a well-order `α`: this is a set which is cofinal and closed under suprema. We recover the more standard notion by setting `α = Iio o`, whenever `ℵ₀ < o.cof`. We prove that club sets are closed under intersections of size less than the cofinality of `α`, and that the fixed points of a normal function are a club set.
1 parent 9061ba1 commit c724781

8 files changed

Lines changed: 181 additions & 13 deletions

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6998,6 +6998,7 @@ public import Mathlib.SetTheory.Cardinal.Aleph
69986998
public import Mathlib.SetTheory.Cardinal.Arithmetic
69996999
public import Mathlib.SetTheory.Cardinal.Basic
70007000
public import Mathlib.SetTheory.Cardinal.Cofinality.Basic
7001+
public import Mathlib.SetTheory.Cardinal.Cofinality.Club
70017002
public import Mathlib.SetTheory.Cardinal.Cofinality.Ordinal
70027003
public import Mathlib.SetTheory.Cardinal.Continuum
70037004
public import Mathlib.SetTheory.Cardinal.CountableCover

Mathlib/Order/Cofinal.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ variable {α β : Type*}
3434
section LE
3535
variable [LE α]
3636

37-
theorem IsCofinal.of_isEmpty [IsEmpty α] (s : Set α) : IsCofinal s :=
37+
theorem IsCofinal.of_isEmpty [IsEmpty α] {s : Set α} : IsCofinal s :=
3838
fun a ↦ isEmptyElim a
3939

4040
theorem isCofinal_empty_iff : IsCofinal (∅ : Set α) ↔ IsEmpty α := by
41-
refine ⟨fun h ↦ ⟨fun a ↦ ?_⟩, fun h ↦ .of_isEmpty _
41+
refine ⟨fun h ↦ ⟨fun a ↦ ?_⟩, fun h ↦ .of_isEmpty⟩
4242
simpa using h a
4343

4444
@[simp]

Mathlib/Order/DirSupClosed.lean

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ def DirSupInacc (s : Set α) : Prop :=
6363
@[simp] lemma DirSupClosed.dirSupClosedOn : DirSupClosed s → DirSupClosedOn D s := @fun h _ _ ↦ @h _
6464
@[simp] lemma DirSupInacc.dirSupInaccOn : DirSupInacc s → DirSupInaccOn D s := @fun h _ _ ↦ @h _
6565

66-
@[simp] theorem DirSupClosed.of_isEmpty [IsEmpty α] (s : Set α) : DirSupClosed s :=
66+
@[simp] theorem DirSupClosed.of_isEmpty [IsEmpty α] {s : Set α} : DirSupClosed s :=
6767
fun _ _ ⟨a, _⟩ ↦ isEmptyElim a
6868

69-
@[simp] theorem DirSupInacc.of_isEmpty [IsEmpty α] (s : Set α) : DirSupInacc s :=
69+
@[simp] theorem DirSupInacc.of_isEmpty [IsEmpty α] {s : Set α} : DirSupInacc s :=
7070
fun _ ⟨a, _⟩ ↦ isEmptyElim a
7171

72-
theorem DirSupClosedOn.of_isEmpty [IsEmpty α] (s : Set α) : DirSupClosedOn D s := by simp
73-
theorem DirSupInaccOn.of_isEmpty [IsEmpty α] (s : Set α) : DirSupInaccOn D s := by simp
72+
theorem DirSupClosedOn.of_isEmpty [IsEmpty α] {s : Set α} : DirSupClosedOn D s := by simp
73+
theorem DirSupInaccOn.of_isEmpty [IsEmpty α] {s : Set α} : DirSupInaccOn D s := by simp
7474

7575
@[gcongr]
7676
lemma DirSupClosedOn.mono (hD : D₁ ⊆ D₂) (hf : DirSupClosedOn D₂ s) : DirSupClosedOn D₁ s :=

Mathlib/Order/IsNormal.lean

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Authors: Violeta Hernández Palacios
55
-/
66
module
77

8+
public import Mathlib.Dynamics.FixedPoints.Defs
89
public import Mathlib.Order.DirSupClosed
910
public import Mathlib.Order.SuccPred.CompleteLinearOrder
1011
public import Mathlib.Order.SuccPred.InitialSeg
@@ -131,6 +132,17 @@ theorem map_iSup {ι} [Nonempty ι] {g : ι → α} (hf : IsNormal f) (hg : BddA
131132
ext
132133
simp
133134

135+
theorem iSup_iterate_mem_fixedPoints [WellFoundedLT α] {f : α → α} (a : α) (hf : IsNormal f)
136+
(hf' : BddAbove (.range fun n ↦ f^[n] a)) : ⨆ n, f^[n] a ∈ f.fixedPoints := by
137+
rw [f.mem_fixedPoints_iff, hf.map_iSup hf']
138+
apply le_antisymm <;> refine ciSup_le fun n ↦ ?_
139+
· rw [← f.iterate_succ_apply']
140+
exact le_ciSup hf' _
141+
· apply hf.strictMono.le_apply.trans
142+
apply (le_ciSup (hf'.mono _) n)
143+
simp_rw [← f.iterate_succ_apply']
144+
grind
145+
134146
theorem preimage_Iic (hf : IsNormal f) {x : β}
135147
(h₁ : (f ⁻¹' Iic x).Nonempty) (h₂ : BddAbove (f ⁻¹' Iic x)) :
136148
f ⁻¹' Iic x = Iic (sSup (f ⁻¹' Iic x)) := by

Mathlib/SetTheory/Cardinal/Cofinality/Basic.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ theorem cof_lt_aleph0_iff : Order.cof α < ℵ₀ ↔ Order.cof α ≤ 1 := by
146146
theorem aleph0_le_cof_iff : ℵ₀ ≤ Order.cof α ↔ 1 < Order.cof α := by
147147
simp [← not_lt]
148148

149+
theorem aleph0_le_cof [Nonempty α] [NoMaxOrder α] : ℵ₀ ≤ cof α := by
150+
simp
151+
149152
@[simp]
150153
theorem cof_eq_aleph0 [NoMaxOrder α] [Nonempty α] [Countable α] : cof α = ℵ₀ :=
151154
((cof_le_cardinalMk _).trans mk_le_aleph0).antisymm (by simp)
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/-
2+
Copyright (c) 2026 Violeta Hernández Palacios. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Violeta Hernández Palacios
5+
-/
6+
module
7+
8+
public import Mathlib.Order.DirSupClosed
9+
public import Mathlib.Order.IsNormal
10+
public import Mathlib.SetTheory.Cardinal.Cofinality.Basic
11+
12+
/-!
13+
# Club sets
14+
15+
A subset of a well-ordered type `α` is called a club set when it is closed in the order topology and
16+
cofinal. If `α` has no maximum, then an equivalent condition is that `α` is closed and unbounded;
17+
hence the name.
18+
19+
## Implementation notes
20+
21+
To avoid importing topology in the ordinals, we spell out the closure property using `DirSupClosed`.
22+
For any type equipped with the Scott-Hausdorff topology (which includes well-orders with the order
23+
topology), `DirSupClosed s` and `IsClosed s` are equivalent predicates.
24+
-/
25+
26+
public section
27+
28+
universe u v
29+
30+
open Cardinal Order
31+
32+
/-- A club set is closed under suprema and cofinal. -/
33+
structure IsClub {α : Type*} [LinearOrder α] (s : Set α) where
34+
/-- Club sets are closed under suprema. If `α` is a well-order with the order topology, this
35+
condition is equivalent to `IsClosed s`. -/
36+
dirSupClosed : DirSupClosed s
37+
/-- Club sets are cofinal. If `α` has no maximum, this condition is equivalent to `¬ BddAbove s`.
38+
See `not_bddAbove_iff_isCofinal`. -/
39+
isCofinal : IsCofinal s
40+
41+
variable {α : Type v} {s t : Set α} {x : α} [LinearOrder α]
42+
43+
@[simp]
44+
theorem IsClub.of_isEmpty [IsEmpty α] {s : Set α} : IsClub s :=
45+
⟨.of_isEmpty, .of_isEmpty⟩
46+
47+
@[simp]
48+
theorem IsClub.univ : IsClub (α := α) .univ :=
49+
⟨.univ, .univ⟩
50+
51+
theorem IsClub.union (hs : IsClub s) (ht : IsClub t) : IsClub (s ∪ t) :=
52+
⟨hs.dirSupClosed.union ht.dirSupClosed, hs.isCofinal.mono Set.subset_union_left⟩
53+
54+
theorem IsClub.isLUB_mem (hs : IsClub s) (ht : t ⊆ s) (ht₀ : t.Nonempty) (hx : IsLUB t x) : x ∈ s :=
55+
hs.dirSupClosed ht ht₀ (.of_linearOrder _) hx
56+
57+
theorem IsClub.csSup_mem {α} [ConditionallyCompleteLinearOrder α] {s t : Set α}
58+
(hs : IsClub s) (ht : t ⊆ s) (ht₀ : t.Nonempty) (ht₁ : BddAbove t) : sSup t ∈ s :=
59+
hs.isLUB_mem ht ht₀ (isLUB_csSup ht₀ ht₁)
60+
61+
theorem IsClub.sInter_of_orderTop {s : Set (Set α)} [OrderTop α]
62+
(hs : ∀ x ∈ s, IsClub x) : IsClub (⋂₀ s) := by
63+
refine ⟨.sInter fun x hx ↦ (hs x hx).dirSupClosed, ?_⟩
64+
rw [isCofinal_iff_top_mem, Set.mem_sInter]
65+
exact fun x hx ↦ (hs x hx).isCofinal.top_mem
66+
67+
theorem IsClub.iInter_of_orderTop {ι : Type*} {f : ι → Set α} [OrderTop α]
68+
(hs : ∀ i, IsClub (f i)) : IsClub (⋂ i, f i) := by
69+
rw [← Set.sInter_range]
70+
exact .sInter_of_orderTop (by simpa)
71+
72+
theorem IsClub.sInter_of_cof_le_one {s : Set (Set α)} (hα : cof α ≤ 1)
73+
(hs : ∀ x ∈ s, IsClub x) : IsClub (⋂₀ s) := by
74+
cases isEmpty_or_nonempty α; · simp
75+
cases topOrderOrNoTopOrder α
76+
· exact .sInter_of_orderTop hs
77+
· cases one_lt_cof.not_ge hα
78+
79+
theorem IsClub.iInter_of_cof_le_one {ι : Type*} {f : ι → Set α} (hα : cof α ≤ 1)
80+
(hs : ∀ i, IsClub (f i)) : IsClub (⋂ i, f i) := by
81+
rw [← Set.sInter_range]
82+
exact .sInter_of_cof_le_one hα (by simpa)
83+
84+
section WellFoundedLT
85+
86+
variable [WellFoundedLT α]
87+
88+
attribute [local instance]
89+
WellFoundedLT.toOrderBot WellFoundedLT.conditionallyCompleteLinearOrderBot
90+
91+
theorem IsClub.sInter {s : Set (Set α)} (hα : cof α ≠ ℵ₀) (hsα : #s < cof α)
92+
(hs : ∀ x ∈ s, IsClub x) : IsClub (⋂₀ s) := by
93+
cases isEmpty_or_nonempty α; · simp
94+
obtain hα | hα := hα.lt_or_gt
95+
· exact .sInter_of_cof_le_one (cof_lt_aleph0_iff.1 hα) hs
96+
refine ⟨.sInter fun x hx ↦ (hs x hx).dirSupClosed, fun a ↦ ?_⟩
97+
choose f hf using fun x : s ↦ (hs _ x.2).isCofinal
98+
let g : ℕ → α := Nat.rec a fun _ IH ↦ sSup (.range (f · IH))
99+
have hg : BddAbove (.range g) := by
100+
refine .of_not_isCofinal fun hg ↦ (cof_le hg).not_gt (hα.trans_le' ?_)
101+
simpa using mk_range_le_lift (f := g)
102+
refine ⟨_, fun t ht ↦ ?_, le_csSup hg ⟨0, rfl⟩⟩
103+
apply (hs t ht).isLUB_mem (t := .range fun n ↦ f ⟨t, ht⟩ (g n)) _ (Set.range_nonempty _)
104+
· refine ⟨?_, fun b hb ↦ csSup_le' ?_⟩ <;> rintro _ ⟨n, rfl⟩
105+
· apply (le_csSup (.of_not_isCofinal _) _).trans (le_csSup hg ⟨n + 1, rfl⟩)
106+
· exact fun hg' ↦ (cof_le hg').not_gt (mk_range_le.trans_lt hsα)
107+
· use ⟨t, ht⟩
108+
· exact (hf ⟨t, ht⟩ _).2.trans <| hb ⟨_, rfl⟩
109+
· grind
110+
111+
theorem IsClub.iInter {ι : Type u} {f : ι → Set α} (hα : cof α ≠ ℵ₀)
112+
(hι : Cardinal.lift.{v} #ι < Cardinal.lift.{u} (cof α)) (hf : ∀ i, IsClub (f i)) :
113+
IsClub (⋂ i, f i) := by
114+
rw [← Set.sInter_range]
115+
refine IsClub.sInter hα ?_ (by simpa)
116+
rw [← Cardinal.lift_lt]
117+
exact mk_range_le_lift.trans_lt hι
118+
119+
theorem IsClub.inter {s t : Set α} (hα : cof α ≠ ℵ₀) (hs : IsClub s) (ht : IsClub t) :
120+
IsClub (s ∩ t) := by
121+
rw [← Set.sInter_pair]
122+
have H : ∀ x ∈ ({s, t} : Set _), IsClub x := by simpa [hs]
123+
obtain hα | hα' := hα.lt_or_gt
124+
· rw [cof_lt_aleph0_iff] at hα
125+
exact .sInter_of_cof_le_one hα H
126+
· exact .sInter hα (hα'.trans_le' <| by simp) H
127+
128+
theorem Order.IsNormal.isClub_range {f : α → α} (hf : IsNormal f) : IsClub (.range f) :=
129+
⟨hf.dirSupClosed_range, fun x ↦ ⟨_, ⟨x, rfl⟩, hf.strictMono.le_apply⟩⟩
130+
131+
theorem Order.IsNormal.isClub_fixedPoints {f : α → α} (hα : cof α ≠ ℵ₀) (hf : IsNormal f) :
132+
IsClub f.fixedPoints := by
133+
cases isEmpty_or_nonempty α; · simp
134+
refine ⟨fun s hs hs₀ _ a ha ↦ (hf.map_isLUB ha hs₀).unique ?_, fun a ↦ ?_⟩
135+
· rwa [Set.image_congr hs, Set.image_id']
136+
· cases topOrderOrNoTopOrder α with
137+
| inl => use ⊤; simpa using hf.strictMono.id_le ⊤
138+
| inr h =>
139+
rw [noTopOrder_iff_noMaxOrder] at h
140+
suffices BddAbove (.range fun n ↦ f^[n] a) from
141+
⟨_, hf.iSup_iterate_mem_fixedPoints a this, le_csSup this ⟨0, rfl⟩⟩
142+
refine .of_not_isCofinal fun h ↦ (cof_le h).not_gt
143+
((aleph0_le_cof.lt_of_ne' hα).trans_le' ?_)
144+
simpa using mk_range_le_lift (f := fun n : ℕ ↦ f^[n] a)
145+
146+
end WellFoundedLT

Mathlib/SetTheory/Ordinal/FixedPoint.lean

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ def deriv (f : Ordinal → Ordinal) : Ordinal → Ordinal :=
340340
theorem deriv_eq_derivFamily (f : Ordinal → Ordinal) : deriv f = derivFamily fun _ : Unit => f :=
341341
rfl
342342

343+
-- TODO: rename to `deriv_zero` once the name is available
343344
@[simp]
344345
theorem deriv_zero_right (f) : deriv f 0 = nfp f 0 :=
345346
derivFamily_zero _
@@ -361,6 +362,7 @@ theorem isNormal_deriv (f) : IsNormal (deriv f) :=
361362
theorem deriv_strictMono (f) : StrictMono (deriv f) :=
362363
derivFamily_strictMono _
363364

365+
@[deprecated "do not depend on the junk values of `nfp`" (since := "2026-05-13")]
364366
theorem deriv_eq_id_of_nfp_eq_id (h : nfp f = id) : deriv f = id :=
365367
((isNormal_deriv _).ext_iff .id).2 (by simp [h])
366368

@@ -380,6 +382,7 @@ theorem deriv_eq_enumOrd (H : IsNormal f) : deriv f = enumOrd (Function.fixedPoi
380382
convert derivFamily_eq_enumOrd fun _ : Unit => H
381383
exact (Set.iInter_const _).symm
382384

385+
@[deprecated "do not depend on the junk values of `nfp`" (since := "2026-05-13")]
383386
theorem nfp_zero_left (a) : nfp 0 a = a := by
384387
rw [← iSup_iterate_eq_nfp]
385388
apply (Ordinal.iSup_le ?_).antisymm (Ordinal.le_iSup _ 0)
@@ -389,15 +392,19 @@ theorem nfp_zero_left (a) : nfp 0 a = a := by
389392
· rw [Function.iterate_succ']
390393
simp
391394

392-
@[simp]
395+
set_option linter.deprecated false in
396+
@[deprecated "do not depend on the junk values of `nfp`" (since := "2026-05-13")]
393397
theorem nfp_zero : nfp 0 = id := by
394398
ext
395399
exact nfp_zero_left _
396400

397-
@[simp]
401+
set_option linter.deprecated false in
402+
@[deprecated "do not depend on the junk values of `deriv`" (since := "2026-05-13")]
398403
theorem deriv_zero : deriv 0 = id :=
399404
deriv_eq_id_of_nfp_eq_id nfp_zero
400405

406+
set_option linter.deprecated false in
407+
@[deprecated "do not depend on the junk values of `deriv`" (since := "2026-05-13")]
401408
theorem deriv_zero_left (a) : deriv 0 a = a := by
402409
rw [deriv_zero, id_eq]
403410

@@ -452,10 +459,9 @@ theorem nfp_mul_zero (a : Ordinal) : nfp (a * ·) 0 = 0 := by
452459

453460
theorem nfp_mul_eq_opow_omega0 {a b : Ordinal} (hb : 0 < b) (hba : b ≤ a ^ ω) :
454461
nfp (a * ·) b = a ^ ω := by
455-
rcases eq_zero_or_pos a with ha | ha
456-
· rw [ha, zero_opow omega0_ne_zero] at hba ⊢
457-
simp_rw [nonpos_iff_eq_zero.1 hba, zero_mul]
458-
exact nfp_zero_left 0
462+
rcases eq_zero_or_pos a with rfl | ha
463+
· rw [zero_opow omega0_ne_zero] at hba
464+
cases hba.not_gt hb
459465
apply le_antisymm
460466
· apply nfp_le_fp (isNormal_mul_right ha).monotone hba
461467
rw [← opow_one_add, one_add_omega0]

Mathlib/SetTheory/Ordinal/FundamentalSequence.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ protected theorem id (ho : o ≤ o.cof.ord) : IsFundamentalSeq (o := o) id where
7575
protected theorem zero (f : Iio 0 → Iio 0) : IsFundamentalSeq f where
7676
strictMono _ := by simp
7777
le_ord_cof := by simp
78-
isCofinal_range := .of_isEmpty _
78+
isCofinal_range := .of_isEmpty
7979

8080
/-- The length one sequence `(o)` is a fundamental sequence for `o + 1`. -/
8181
protected theorem add_one (o : Ordinal) :

0 commit comments

Comments
 (0)