-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[Merged by Bors] - feat: club sets #37677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5920dc0
d95fb2d
dadb299
a45d246
fc7d23c
d3c8814
658640c
a7d7800
8c14427
e86f8bf
cbd1de3
45d11af
07729e2
0bc5c75
6c6ea02
aa246e3
ead304b
f0d220a
d472d5c
b27674b
5400b16
5a446de
f1b46ac
0fb35f8
08b5953
34a6cf9
44e2cb5
d65b49e
f594449
9381344
8fe031f
09d5a39
5229c35
9b0ec71
740c16a
cb72a58
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| /- | ||
| Copyright (c) 2026 Violeta Hernández Palacios. All rights reserved. | ||
| Released under Apache 2.0 license as described in the file LICENSE. | ||
| Authors: Violeta Hernández Palacios | ||
| -/ | ||
| module | ||
|
|
||
| public import Mathlib.Order.DirSupClosed | ||
| public import Mathlib.Order.IsNormal | ||
| public import Mathlib.SetTheory.Cardinal.Cofinality.Basic | ||
|
|
||
| /-! | ||
| # Club sets | ||
|
|
||
| A subset of a well-ordered type `α` is called a club set when it is closed in the order topology and | ||
| cofinal. If `α` has no maximum, then an equivalent condition is that `α` is closed and unbounded; | ||
| hence the name. | ||
|
|
||
| ## Implementation notes | ||
|
|
||
| To avoid importing topology in the ordinals, we spell out the closure property using `DirSupClosed`. | ||
| For any type equipped with the Scott-Hausdorff topology (which includes well-orders with the order | ||
| topology), `DirSupClosed s` and `IsClosed s` are equivalent predicates. | ||
| -/ | ||
|
|
||
| public section | ||
|
|
||
| universe u v | ||
|
|
||
| open Cardinal Order | ||
|
|
||
| /-- A club set is closed under suprema and cofinal. -/ | ||
| structure IsClub {α : Type*} [LinearOrder α] (s : Set α) where | ||
| /-- Club sets are closed under suprema. If `α` is a well-order with the order topology, this | ||
| condition is equivalent to `IsClosed s`. -/ | ||
| dirSupClosed : DirSupClosed s | ||
| /-- Club sets are cofinal. If `α` has no maximum, this condition is equivalent to `¬ BddAbove s`. | ||
| See `not_bddAbove_iff_isCofinal`. -/ | ||
| isCofinal : IsCofinal s | ||
|
|
||
| variable {α : Type v} {s t : Set α} {x : α} [LinearOrder α] | ||
|
|
||
| @[simp] | ||
| theorem IsClub.of_isEmpty [IsEmpty α] {s : Set α} : IsClub s := | ||
| ⟨.of_isEmpty, .of_isEmpty⟩ | ||
|
|
||
| @[simp] | ||
| theorem IsClub.univ : IsClub (α := α) .univ := | ||
| ⟨.univ, .univ⟩ | ||
|
|
||
| theorem IsClub.union (hs : IsClub s) (ht : IsClub t) : IsClub (s ∪ t) := | ||
| ⟨hs.dirSupClosed.union ht.dirSupClosed, hs.isCofinal.mono Set.subset_union_left⟩ | ||
|
|
||
| theorem IsClub.isLUB_mem (hs : IsClub s) (ht : t ⊆ s) (ht₀ : t.Nonempty) (hx : IsLUB t x) : x ∈ s := | ||
| hs.dirSupClosed ht ht₀ (.of_linearOrder _) hx | ||
|
|
||
| theorem IsClub.csSup_mem {α} [ConditionallyCompleteLinearOrder α] {s t : Set α} | ||
| (hs : IsClub s) (ht : t ⊆ s) (ht₀ : t.Nonempty) (ht₁ : BddAbove t) : sSup t ∈ s := | ||
| hs.isLUB_mem ht ht₀ (isLUB_csSup ht₀ ht₁) | ||
|
|
||
| theorem IsClub.sInter_of_orderTop {s : Set (Set α)} [OrderTop α] | ||
| (hs : ∀ x ∈ s, IsClub x) : IsClub (⋂₀ s) := by | ||
| refine ⟨.sInter fun x hx ↦ (hs x hx).dirSupClosed, ?_⟩ | ||
| rw [isCofinal_iff_top_mem, Set.mem_sInter] | ||
| exact fun x hx ↦ (hs x hx).isCofinal.top_mem | ||
|
|
||
| theorem IsClub.iInter_of_orderTop {ι : Type*} {f : ι → Set α} [OrderTop α] | ||
| (hs : ∀ i, IsClub (f i)) : IsClub (⋂ i, f i) := by | ||
| rw [← Set.sInter_range] | ||
| exact .sInter_of_orderTop (by simpa) | ||
|
|
||
| theorem IsClub.sInter_of_cof_le_one {s : Set (Set α)} (hα : cof α ≤ 1) | ||
| (hs : ∀ x ∈ s, IsClub x) : IsClub (⋂₀ s) := by | ||
| cases isEmpty_or_nonempty α; · simp | ||
| cases topOrderOrNoTopOrder α | ||
| · exact .sInter_of_orderTop hs | ||
| · cases one_lt_cof.not_ge hα | ||
|
Comment on lines
+75
to
+77
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you abstract this out into a lemma saying that
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have this (the correct version of it, at least): Agree with the other theorem being misnamed, I'll open a PR for that later tonight.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use it here then? Is it impractical?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you have golfing ideas, let me know! This is as short as I could get it. |
||
|
|
||
| theorem IsClub.iInter_of_cof_le_one {ι : Type*} {f : ι → Set α} (hα : cof α ≤ 1) | ||
| (hs : ∀ i, IsClub (f i)) : IsClub (⋂ i, f i) := by | ||
| rw [← Set.sInter_range] | ||
| exact .sInter_of_cof_le_one hα (by simpa) | ||
|
|
||
| section WellFoundedLT | ||
|
|
||
| variable [WellFoundedLT α] | ||
|
|
||
| attribute [local instance] | ||
| WellFoundedLT.toOrderBot WellFoundedLT.conditionallyCompleteLinearOrderBot | ||
|
|
||
| theorem IsClub.sInter {s : Set (Set α)} (hα : cof α ≠ ℵ₀) (hsα : #s < cof α) | ||
| (hs : ∀ x ∈ s, IsClub x) : IsClub (⋂₀ s) := by | ||
| cases isEmpty_or_nonempty α; · simp | ||
| obtain hα | hα := hα.lt_or_gt | ||
| · exact .sInter_of_cof_le_one (cof_lt_aleph0_iff.1 hα) hs | ||
| refine ⟨.sInter fun x hx ↦ (hs x hx).dirSupClosed, fun a ↦ ?_⟩ | ||
| choose f hf using fun x : s ↦ (hs _ x.2).isCofinal | ||
| let g : ℕ → α := Nat.rec a fun _ IH ↦ sSup (.range (f · IH)) | ||
| have hg : BddAbove (.range g) := by | ||
| refine .of_not_isCofinal fun hg ↦ (cof_le hg).not_gt (hα.trans_le' ?_) | ||
| simpa using mk_range_le_lift (f := g) | ||
| refine ⟨_, fun t ht ↦ ?_, le_csSup hg ⟨0, rfl⟩⟩ | ||
| apply (hs t ht).isLUB_mem (t := .range fun n ↦ f ⟨t, ht⟩ (g n)) _ (Set.range_nonempty _) | ||
| · refine ⟨?_, fun b hb ↦ csSup_le' ?_⟩ <;> rintro _ ⟨n, rfl⟩ | ||
| · apply (le_csSup (.of_not_isCofinal _) _).trans (le_csSup hg ⟨n + 1, rfl⟩) | ||
| · exact fun hg' ↦ (cof_le hg').not_gt (mk_range_le.trans_lt hsα) | ||
| · use ⟨t, ht⟩ | ||
| · exact (hf ⟨t, ht⟩ _).2.trans <| hb ⟨_, rfl⟩ | ||
| · grind | ||
|
|
||
| theorem IsClub.iInter {ι : Type u} {f : ι → Set α} (hα : cof α ≠ ℵ₀) | ||
| (hι : Cardinal.lift.{v} #ι < Cardinal.lift.{u} (cof α)) (hf : ∀ i, IsClub (f i)) : | ||
| IsClub (⋂ i, f i) := by | ||
| rw [← Set.sInter_range] | ||
| refine IsClub.sInter hα ?_ (by simpa) | ||
| rw [← Cardinal.lift_lt] | ||
| exact mk_range_le_lift.trans_lt hι | ||
|
|
||
| theorem IsClub.inter {s t : Set α} (hα : cof α ≠ ℵ₀) (hs : IsClub s) (ht : IsClub t) : | ||
| IsClub (s ∩ t) := by | ||
| rw [← Set.sInter_pair] | ||
| have H : ∀ x ∈ ({s, t} : Set _), IsClub x := by simpa [hs] | ||
| obtain hα | hα' := hα.lt_or_gt | ||
| · rw [cof_lt_aleph0_iff] at hα | ||
| exact .sInter_of_cof_le_one hα H | ||
| · exact .sInter hα (hα'.trans_le' <| by simp) H | ||
|
|
||
| theorem Order.IsNormal.isClub_range {f : α → α} (hf : IsNormal f) : IsClub (.range f) := | ||
| ⟨hf.dirSupClosed_range, fun x ↦ ⟨_, ⟨x, rfl⟩, hf.strictMono.le_apply⟩⟩ | ||
|
|
||
| theorem Order.IsNormal.isClub_fixedPoints {f : α → α} (hα : cof α ≠ ℵ₀) (hf : IsNormal f) : | ||
| IsClub f.fixedPoints := by | ||
| cases isEmpty_or_nonempty α; · simp | ||
| refine ⟨fun s hs hs₀ _ a ha ↦ (hf.map_isLUB ha hs₀).unique ?_, fun a ↦ ?_⟩ | ||
| · rwa [Set.image_congr hs, Set.image_id'] | ||
| · cases topOrderOrNoTopOrder α with | ||
| | inl => use ⊤; simpa using hf.strictMono.id_le ⊤ | ||
| | inr h => | ||
| rw [noTopOrder_iff_noMaxOrder] at h | ||
| suffices BddAbove (.range fun n ↦ f^[n] a) from | ||
| ⟨_, hf.iSup_iterate_mem_fixedPoints a this, le_csSup this ⟨0, rfl⟩⟩ | ||
| refine .of_not_isCofinal fun h ↦ (cof_le h).not_gt | ||
| ((aleph0_le_cof.lt_of_ne' hα).trans_le' ?_) | ||
| simpa using mk_range_le_lift (f := fun n : ℕ ↦ f^[n] a) | ||
|
|
||
| end WellFoundedLT | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you just
namespace IsClubinstead for this file (the last two declarations will need_root_.)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really sorry, I did this locally but forgot to push. I opened #39641 to implement this change.