Zulip Chat Archive
Stream: new members
Topic: Formalisation of the Bourbaki-Witt Theorem
Finn Mortimore (Aug 29 2025 at 20:20):
Hi all,
Long time lurker. I have finally tried my hand at a LEAN project by formalising the Boubaki-Witt Theorem using the proof in Lang's Algebra. Would appreciate any and all feedback on my code (especially on whether/how I could have used CompleteSemilatticeInf to use a minimal admissible set instead of reproving specific instances of more general lemmas). Based on the 1000+ theorems list on the community website, I believe this is the first formalisation of the theorem and would love to contribute it to the library if possible (after of course making any necessary changes!).
import Mathlib.Order.PreOrder.Chain
import Mathlib.Data.Set.Lattice
section
variable {α : Type} [LE α]
@[ext]
structure neChain (α : Type) [LE α] where
carrier : Set α
ne : ∃ x, x ∈ carrier
Chain' : IsChain (· ≤ ·) carrier
instance : SetLike (neChain α) α where
coe := neChain.carrier
coe_injective' _ _ := neChain.ext
end
class CCPO (α : Type) [Nonempty α] extends PartialOrder α where
cSup : neChain α → α
le_cSup (c : neChain α) (a : α) : a ∈ c.carrier → a ≤ cSup c
cSup_le (c : neChain α) (a : α) : (∀ b ∈ c.carrier, b ≤ a) → cSup c ≤ a
structure Inflationary (α : Type) [PartialOrder α] where
toFun : α → α
inflationary (x : α) : x ≤ toFun x
instance {α : Type} [PartialOrder α] : CoeFun (Inflationary α) (fun _ ↦ α → α) where
coe := Inflationary.toFun
open CCPO Set
section
variable {α : Type} [Nonempty α] [CCPO α] {a : α} {f : Inflationary α}
-- We change the definition of admissible set to include '∀ x ∈ B, a ≤ x'
structure IsAdmissible (a : α) (f : Inflationary α) (B : Set α) : Prop where
a_mem : a ∈ B
image_self_sub : f '' B ⊆ B
cSup_mem : ∀ (T : neChain α), ↑T ⊆ B → cSup T ∈ B
a_min : ∀ x ∈ B, a ≤ x
abbrev A (a : α) : Set α := {x | a ≤ x}
lemma AIsAdmissible (a : α) (f : Inflationary α) : IsAdmissible a f (A a) := by
apply IsAdmissible.mk
· exact le_refl a
· rintro _ ⟨_, a_le, rfl⟩
exact le_trans a_le (f.inflationary _)
· rintro T T_sub_A
have ⟨_, mem_T⟩ := T.ne
apply le_trans (T_sub_A mem_T) (le_cSup _ _ mem_T)
· exact fun _ h => h
def M (a : α) (f : Inflationary α) : Set α :=
⋂₀ {B | IsAdmissible a f B}
lemma mem_M_iff {x : α} (a : α) (f : Inflationary α) :
x ∈ M a f ↔ ∀ B ∈ {B | IsAdmissible a f B}, x ∈ B := by
unfold M
exact mem_sInter
lemma MIsAdmissible (a : α) (f : Inflationary α) : IsAdmissible a f (M a f) where
a_mem := by
rw [mem_M_iff]
exact fun _ h => h.a_mem
image_self_sub := by
rintro x ⟨y, y_mem_M, rfl⟩
rw [mem_M_iff]
rintro _ IsAdmissible
exact IsAdmissible.image_self_sub ⟨y, ⟨mem_sInter.1 y_mem_M _ IsAdmissible, rfl⟩⟩
cSup_mem := by
intro T T_sub_M
rw [mem_M_iff]
intro _ IsAdmissible
exact IsAdmissible.cSup_mem T (subset_trans T_sub_M (sInter_subset_of_mem IsAdmissible))
a_min := by
intro _ x_mem_M
rw [mem_M_iff a f] at x_mem_M
exact (x_mem_M (A a) (AIsAdmissible a f))
lemma sub_M_eq_M {B : Set α} (h : IsAdmissible a f B) (h' : B ⊆ M a f) :
B = M a f :=
subset_antisymm h' (sInter_subset_of_mem h)
def IsExtremePt (a : α) (f : Inflationary α) (c : α) : Prop :=
c ∈ M a f ∧ (∀ x ∈ M a f, x < c → f x ≤ c)
def Mc {c : α} (_ : IsExtremePt a f c) : Set α := {x ∈ M a f | x ≤ c ∨ f c ≤ x}
lemma image_mem_M {x : α} (x_mem_M : x ∈ M a f) : f x ∈ M a f := by
apply (MIsAdmissible a f).image_self_sub
use x
lemma Mc_eq_M {c : α} (cIsExtremePt : IsExtremePt a f c) : Mc cIsExtremePt = M a f := by
apply sub_M_eq_M ?_ (sep_subset _ _)
apply IsAdmissible.mk
· exact ⟨(MIsAdmissible a f).a_mem, Or.inl ((MIsAdmissible a f).a_min c cIsExtremePt.1)⟩
· rintro _ ⟨x, ⟨x_mem_M, (x_le_c | fc_le_x)⟩, rfl⟩ <;>
refine ⟨image_mem_M x_mem_M, ?_⟩
· rcases le_iff_lt_or_eq.1 x_le_c with (x_lt_c | rfl)
· left; exact cIsExtremePt.2 x x_mem_M x_lt_c
· right; exact le_refl _
· right
exact le_trans fc_le_x (f.inflationary x)
· intro T T_sub_Mc
refine ⟨(MIsAdmissible a f).cSup_mem _ (subset_trans T_sub_Mc (sep_subset _ _)), ?_⟩
· by_cases c_IsUB_T : ∀ x ∈ T, x ≤ c
· left; apply cSup_le T c c_IsUB_T
· push_neg at c_IsUB_T
rcases c_IsUB_T with ⟨x, x_mem_T, not_x_le_c⟩
obtain fc_le_x := Or.resolve_left (T_sub_Mc x_mem_T).2 not_x_le_c
right
apply le_trans fc_le_x (le_cSup _ _ x_mem_T)
· exact fun x ⟨x_mem_M, _⟩ => (MIsAdmissible a f).a_min x x_mem_M
lemma E_eq_M : {c | IsExtremePt a f c} = M a f := by
apply sub_M_eq_M _ (sep_subset _ _)
apply IsAdmissible.mk
· refine ⟨(MIsAdmissible a f).a_mem, ?_⟩
intro x x_mem_M hx
exfalso
exact lt_irrefl a (lt_of_le_of_lt ((MIsAdmissible a f).a_min x x_mem_M) hx)
· rintro _ ⟨c, c_mem_E, rfl⟩
refine ⟨image_mem_M c_mem_E.1, ?_⟩
intro x x_mem_M x_lt_fc
have x_mem_Mc := x_mem_M
rw [← Mc_eq_M c_mem_E] at x_mem_Mc
rcases x_mem_Mc with ⟨_, (x_le_c | fc_le_x)⟩
· rcases le_iff_lt_or_eq.1 x_le_c with (x_lt_c | rfl)
· exact le_trans (c_mem_E.2 _ x_mem_M x_lt_c) (f.inflationary c)
· exact le_refl (f x)
· exfalso
exact lt_irrefl x (lt_of_lt_of_le x_lt_fc fc_le_x)
· intro T T_sub_E
refine ⟨(MIsAdmissible a f).cSup_mem _ (subset_trans T_sub_E (sep_subset _ _)), ?_⟩
intro x x_mem_M x_lt_cSup
by_cases h : ∀ c ∈ T, f c ≤ x
· exfalso
apply lt_irrefl x (lt_of_lt_of_le x_lt_cSup ?_)
apply cSup_le
intro c c_mem_T
apply le_trans (f.inflationary c) (h c c_mem_T)
· push_neg at h
obtain ⟨c, c_mem_T, not_fc_le_x⟩ := h
have x_mem_Mc := x_mem_M
rw [← Mc_eq_M (T_sub_E c_mem_T)] at x_mem_Mc
obtain (x_lt_c | rfl) := le_iff_lt_or_eq.1 (Or.resolve_right x_mem_Mc.2 not_fc_le_x)
· exact le_trans ((T_sub_E c_mem_T).2 x x_mem_M x_lt_c) (le_cSup _ _ c_mem_T)
· have b_mem_Mc := (MIsAdmissible a f).cSup_mem _ (subset_trans T_sub_E (sep_subset _ _))
rw [← Mc_eq_M (T_sub_E c_mem_T)] at b_mem_Mc
obtain ⟨_, (cSup_le_x | fx_le_cSup)⟩ := b_mem_Mc
· exfalso
apply lt_irrefl x (lt_of_lt_of_le x_lt_cSup cSup_le_x)
· exact fx_le_cSup
· exact fun x ⟨x_mem_M, _⟩ => (MIsAdmissible a f).a_min x x_mem_M
lemma mem_M_iff_IsExtremePt {c : α} : c ∈ M a f ↔ IsExtremePt a f c := by
rw [← E_eq_M]
rfl
lemma MIsChain : IsChain (· ≤ ·) (M a f) := by
intro x xIsExtremePt y y_mem_Mx _
rw [mem_M_iff_IsExtremePt] at xIsExtremePt
rw [← Mc_eq_M xIsExtremePt] at y_mem_Mx
obtain ⟨_, (y_le_x | fx_le_y)⟩ := y_mem_Mx
· right; exact y_le_x
· left; exact le_trans (f.inflationary x) fx_le_y
end
theorem BourbakiWitt {α : Type} [Nonempty α] [CCPO α] (f : Inflationary α) : ∃ x, f x = x := by
let a : α := Classical.ofNonempty
let b : α := cSup (neChain.mk (M a f) ⟨a, (MIsAdmissible a f).a_mem⟩ (MIsChain))
use b
apply le_antisymm _ (f.inflationary _)
apply le_cSup _ _
apply (MIsAdmissible a f).image_self_sub
use b
exact ⟨(MIsAdmissible a f).cSup_mem _ (subset_refl _), rfl⟩
Matt Diamond (Aug 30 2025 at 03:53):
FYI the first import has a capitalization issue... should be import Mathlib.Order.Preorder.Chain
Matt Diamond (Aug 30 2025 at 04:11):
for neChain.ne you could have also written carrier.Nonempty... using that gives you access to some useful lemmas via dot notation
Niels Voss (Aug 30 2025 at 04:32):
I think whether the capitalization issue affects you might be OS-dependent, which is why you might not have noticed it. It does need to be fixed before getting it into mathlib though
Finn Mortimore (Sep 01 2025 at 11:19):
Thank you both — I have implemented those suggestions. What are the next steps I would need to take to get this into mathlib (if there is a place for it)?
Last updated: Dec 20 2025 at 21:32 UTC