Skip to content

Commit 301c8f7

Browse files
committed
chore(SetTheory/Ordinal/FixedPointApproximants): simpler definition for lfpApprox (leanprover-community#37383)
We simplify the definition of `Ordinal.lfpApprox` - the old definition wasn't even simp-normal. We then golf the entire API using it.
1 parent ac4def2 commit 301c8f7

1 file changed

Lines changed: 67 additions & 117 deletions

File tree

Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean

Lines changed: 67 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -64,101 +64,66 @@ namespace OrdinalApprox
6464

6565
universe u
6666
variable {α : Type u}
67-
variable [CompleteLattice α] (f : α →o α) (x : α)
67+
variable [CompleteLattice α] (f : α →o α) {x : α} {a b c : Ordinal.{u}}
6868

6969
open Function fixedPoints Cardinal Order OrderHom
7070

71+
variable (x) in
7172
/-- The ordinal-indexed sequence approximating the least fixed point greater than
7273
an initial value `x`. It is defined in such a way that we have `lfpApprox 0 x = x` and
7374
`lfpApprox a x = ⨆ b < a, f (lfpApprox b x)`. -/
7475
def lfpApprox (a : Ordinal.{u}) : α :=
75-
sSup ({ f (lfpApprox b) | (b : Ordinal) (_ : b < a) } ∪ {x})
76+
x ⊔ ⨆ b < a, f (lfpApprox b)
7677
termination_by a
7778

78-
theorem lfpApprox_monotone : Monotone (lfpApprox f x) := by
79+
theorem lfpApprox_mono_right : Monotone (lfpApprox f x) := by
7980
intro a b h
8081
rw [lfpApprox, lfpApprox]
81-
gcongr sSup (?_ ∪ {x})
82-
simp only [exists_prop, Set.setOf_subset_setOf, forall_exists_index, and_imp,
83-
forall_apply_eq_imp_iff₂]
84-
intro a' h'
85-
use a'
86-
exact ⟨lt_of_lt_of_le h' h, rfl⟩
82+
apply sup_le_sup_left (iSup₂_mono' _)
83+
grind
84+
85+
@[deprecated (since := "2026-03-30")] alias lfpApprox_monotone := lfpApprox_mono_right
8786

8887
theorem le_lfpApprox {a : Ordinal} : x ≤ lfpApprox f x a := by
8988
rw [lfpApprox]
90-
apply le_sSup
91-
simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, true_or]
89+
exact le_sup_left
9290

93-
theorem lfpApprox_add_one (h : x ≤ f x) (a : Ordinal) :
91+
theorem lfpApprox_add_one (hx : x ≤ f x) (a : Ordinal) :
9492
lfpApprox f x (a + 1) = f (lfpApprox f x a) := by
95-
apply le_antisymm
96-
· conv => left; rw [lfpApprox]
97-
apply sSup_le
98-
simp only [lt_add_one_iff, exists_prop, Set.union_singleton,
99-
Set.mem_insert_iff, Set.mem_setOf_eq, forall_eq_or_imp, forall_exists_index, and_imp,
100-
forall_apply_eq_imp_iff₂]
101-
apply And.intro
102-
· apply le_trans h
103-
apply Monotone.imp f.monotone
104-
exact le_lfpApprox f x
105-
· intro a' h
106-
apply f.2; apply lfpApprox_monotone; exact h
107-
· conv => right; rw [lfpApprox]
108-
apply le_sSup
109-
simp only [lt_add_one_iff, exists_prop]
110-
rw [Set.mem_union]
111-
apply Or.inl
112-
simp only [Set.mem_setOf_eq]
113-
use a
114-
115-
theorem lfpApprox_mono_left : Monotone (lfpApprox : (α →o α) → _) := by
93+
rw [lfpApprox]
94+
apply (sup_le (hx.trans (f.mono (le_lfpApprox ..))) _).antisymm
95+
· exact le_sup_of_le_right <| le_iSup₂ (f := fun b _ ↦ f (lfpApprox f x b)) a (lt_add_one a)
96+
· simpa using fun i h ↦ f.monotone.comp (lfpApprox_mono_right f) h
97+
98+
theorem lfpApprox_mono_left : Monotone (lfpApprox (α := α)) := by
11699
intro f g h x a
117-
induction a using WellFoundedLT.induction with | ind i ih
100+
induction a using WellFoundedLT.induction with | ind i IH
118101
rw [lfpApprox, lfpApprox]
119-
apply sSup_le
120-
simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, sSup_insert,
121-
forall_eq_or_imp, le_sup_left, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂,
122-
true_and]
123-
intro i' h_lt
124-
grw [← le_sup_right]
125-
refine le_sSup_of_le ⟨i', h_lt, rfl⟩ ?_
126-
grw [h _, ih i' h_lt]
102+
exact sup_le_sup_left (iSup₂_mono fun j hj ↦ (f.mono (IH j hj)).trans (h _)) _
127103

128104
theorem lfpApprox_mono_mid : Monotone (lfpApprox f) := by
129105
intro x₁ x₂ h a
130-
induction a using WellFoundedLT.induction with | ind i ih
106+
induction a using WellFoundedLT.induction with | ind i IH
131107
rw [lfpApprox, lfpApprox]
132-
apply sSup_le
133-
simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, sSup_insert,
134-
forall_eq_or_imp, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂]
135-
constructor
136-
· exact le_sup_of_le_left h
137-
· intro i' h_i'
138-
apply le_sup_of_le_right
139-
apply le_sSup_of_le
140-
· use i'
141-
· exact f.monotone (ih i' h_i')
108+
exact sup_le_sup h <| iSup₂_mono fun j hj ↦ f.mono (IH j hj)
142109

143110
/-- The approximations of the least fixed point stabilize at a fixed point of `f` -/
144-
theorem lfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (h_init : x ≤ f x) (h_ab : a ≤ b)
145-
(h : lfpApprox f x a ∈ fixedPoints f) : lfpApprox f x b = lfpApprox f x a := by
146-
rw [mem_fixedPoints_iff] at h
111+
theorem lfpApprox_eq_of_mem_fixedPoints (hx : x ≤ f x) (hab : a ≤ b)
112+
(hf : lfpApprox f x a ∈ fixedPoints f) : lfpApprox f x b = lfpApprox f x a := by
113+
rw [mem_fixedPoints_iff] at hf
147114
induction b using WellFoundedLT.induction with | ind b IH
148-
apply le_antisymm
149-
· conv => left; rw [lfpApprox]
150-
apply sSup_le
151-
simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq,
152-
forall_eq_or_imp, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂]
153-
apply And.intro (le_lfpApprox f x)
154-
intro a' ha'b
155-
by_cases! haa : a' < a
156-
· rw [← lfpApprox_add_one f x h_init]
157-
apply lfpApprox_monotone
158-
simpa
159-
· rw [IH a' ha'b haa, h]
160-
· exact lfpApprox_monotone f x h_ab
161-
115+
apply (lfpApprox_mono_right f hab).antisymm'
116+
rw [lfpApprox]
117+
apply sup_le (le_lfpApprox ..)
118+
rw [iSup₂_le_iff]
119+
intro i hi
120+
by_cases! hi' : i < a
121+
· rw [← lfpApprox_add_one f hx]
122+
apply lfpApprox_mono_right
123+
rwa [add_one_le_iff]
124+
· rw [IH _ hi hi', hf]
125+
126+
variable (x) in
162127
/-- There are distinct indices smaller than the successor of the domain's cardinality
163128
yielding the same value -/
164129
theorem exists_lfpApprox_eq_lfpApprox : ∃ a < ord <| succ #α, ∃ b < ord <| succ #α,
@@ -174,60 +139,42 @@ theorem exists_lfpApprox_eq_lfpApprox : ∃ a < ord <| succ #α, ∃ b < ord <|
174139

175140
/-- If the sequence of ordinal-indexed approximations takes a value twice,
176141
then it actually stabilised at that value. -/
177-
lemma lfpApprox_mem_fixedPoints_of_eq {a b c : Ordinal}
178-
(h_init : x ≤ f x) (h_ab : a < b) (h_ac : a ≤ c) (h_fab : lfpApprox f x a = lfpApprox f x b) :
179-
lfpApprox f x c ∈ fixedPoints f := by
180-
have lfpApprox_mem_fixedPoint :
181-
lfpApprox f x a ∈ fixedPoints f := by
182-
rw [mem_fixedPoints_iff, ← lfpApprox_add_one f x h_init]
183-
exact Monotone.eq_of_ge_of_le (lfpApprox_monotone f x)
184-
h_fab (SuccOrder.le_succ a) (SuccOrder.succ_le_of_lt h_ab)
185-
rw [lfpApprox_eq_of_mem_fixedPoints f x h_init]
186-
· exact lfpApprox_mem_fixedPoint
187-
· exact h_ac
188-
· exact lfpApprox_mem_fixedPoint
142+
lemma lfpApprox_mem_fixedPoints_of_eq (hx : x ≤ f x) (hab : a < b) (hac : a ≤ c)
143+
(hf : lfpApprox f x a = lfpApprox f x b) : lfpApprox f x c ∈ fixedPoints f := by
144+
have H : lfpApprox f x a ∈ fixedPoints f := by
145+
rw [mem_fixedPoints_iff, ← lfpApprox_add_one f hx]
146+
exact (lfpApprox_mono_right f).eq_of_ge_of_le
147+
hf (lt_add_one a).le (add_one_le_of_lt hab)
148+
rwa [lfpApprox_eq_of_mem_fixedPoints f hx hac H]
189149

190150
/-- The approximation at the index of the successor of the domain's cardinality is a fixed point -/
191-
theorem lfpApprox_ord_mem_fixedPoint (h_init : x ≤ f x) :
151+
theorem lfpApprox_ord_mem_fixedPoint (hx : x ≤ f x) :
192152
lfpApprox f x (ord <| succ #α) ∈ fixedPoints f := by
193-
let ⟨a, h_a, b, h_b, h_nab, h_fab⟩ := exists_lfpApprox_eq_lfpApprox f x
153+
let ⟨a, ha, b, hb, hne, hf⟩ := exists_lfpApprox_eq_lfpApprox f x
194154
cases le_total a b with
195-
| inl h_ab =>
196-
exact lfpApprox_mem_fixedPoints_of_eq f x h_init
197-
(h_nab.lt_of_le h_ab) (le_of_lt h_a) h_fab
198-
| inr h_ba =>
199-
exact lfpApprox_mem_fixedPoints_of_eq f x h_init
200-
(h_nab.symm.lt_of_le h_ba) (le_of_lt h_b) (h_fab.symm)
155+
| inl hab => exact lfpApprox_mem_fixedPoints_of_eq f hx (hne.lt_of_le hab) ha.le hf
156+
| inr hba => exact lfpApprox_mem_fixedPoints_of_eq f hx (hne.symm.lt_of_le hba) hb.le hf.symm
201157

202158
/-- Every value of the approximation is less or equal than every fixed point of `f`
203159
greater or equal than the initial value -/
204160
theorem lfpApprox_le_of_mem_fixedPoints {a : α}
205-
(h_a : a ∈ fixedPoints f) (h_le_init : x ≤ a) (i : Ordinal) : lfpApprox f x i ≤ a := by
161+
(ha : a ∈ fixedPoints f) (hxa : x ≤ a) (i : Ordinal) : lfpApprox f x i ≤ a := by
206162
induction i using WellFoundedLT.induction with | ind i IH
207163
rw [lfpApprox]
208-
apply sSup_le
209-
simp only [exists_prop]
210-
intro y h_y
211-
simp only [Set.mem_union, Set.mem_setOf_eq, Set.mem_singleton_iff] at h_y
212-
cases h_y with
213-
| inl h_y =>
214-
let ⟨j, h_j_lt, h_j⟩ := h_y
215-
rw [← h_j, ← h_a]
216-
exact f.monotone' (IH j h_j_lt)
217-
| inr h_y =>
218-
rw [h_y]
219-
exact h_le_init
164+
apply sup_le hxa
165+
rw [iSup₂_le_iff, ← ha.eq]
166+
exact fun y hy ↦ f.mono (IH y hy)
220167

221168
/-- The approximation sequence converges at the successor of the domain's cardinality
222169
to the least fixed point if starting from `⊥` -/
223170
theorem lfpApprox_ord_eq_lfp : lfpApprox f ⊥ (ord <| succ #α) = f.lfp := by
224171
apply le_antisymm
225172
· have h_lfp : ∃ y : fixedPoints f, f.lfp = y := by use ⊥; exact rfl
226173
let ⟨y, h_y⟩ := h_lfp; rw [h_y]
227-
exact lfpApprox_le_of_mem_fixedPoints f y.2 bot_le (ord <| succ #α)
174+
exact lfpApprox_le_of_mem_fixedPoints f y.2 bot_le (ord <| succ #α)
228175
· have h_fix : ∃ y : fixedPoints f, lfpApprox f ⊥ (ord <| succ #α) = y := by
229176
simpa only [Subtype.exists, mem_fixedPoints, exists_prop, exists_eq_right'] using
230-
lfpApprox_ord_mem_fixedPoint f bot_le
177+
lfpApprox_ord_mem_fixedPoint f bot_le
231178
let ⟨x, h_x⟩ := h_fix; rw [h_x]
232179
exact lfp_le_fixed f x.prop
233180

@@ -236,26 +183,29 @@ theorem lfp_mem_range_lfpApprox : f.lfp ∈ Set.range (lfpApprox f ⊥) := by
236183
use ord <| succ #α
237184
exact lfpApprox_ord_eq_lfp f
238185

186+
variable (x) in
239187
/-- The ordinal-indexed sequence approximating the greatest fixed point greater than
240188
an initial value `x`. It is defined in such a way that we have `gfpApprox 0 x = x` and
241189
`gfpApprox a x = ⨅ b < a, f (lfpApprox b x)`. -/
242190
def gfpApprox (a : Ordinal.{u}) : α :=
243-
sInf ({ f (gfpApprox b) | (b : Ordinal) (_ : b < a) } ∪ {x})
191+
x ⊓ ⨅ b < a, f (gfpApprox b)
244192
termination_by a
245193

246194
-- By unsealing these recursive definitions we can relate them
247195
-- by definitional equality
248196
unseal gfpApprox lfpApprox
249197

250-
theorem gfpApprox_antitone : Antitone (gfpApprox f x) :=
251-
lfpApprox_monotone f.dual x
198+
theorem gfpApprox_anti_right : Antitone (gfpApprox f x) :=
199+
lfpApprox_mono_right f.dual
200+
201+
@[deprecated (since := "2026-03-30")] alias gfpApprox_antitone := gfpApprox_anti_right
252202

253203
theorem gfpApprox_le {a : Ordinal} : gfpApprox f x a ≤ x :=
254-
le_lfpApprox f.dual x
204+
le_lfpApprox f.dual
255205

256-
theorem gfpApprox_add_one (h : f x ≤ x) (a : Ordinal) :
206+
theorem gfpApprox_add_one (hx : f x ≤ x) (a : Ordinal) :
257207
gfpApprox f x (a + 1) = f (gfpApprox f x a) :=
258-
lfpApprox_add_one f.dual x h a
208+
lfpApprox_add_one f.dual hx a
259209

260210
theorem gfpApprox_mono_left : Monotone (gfpApprox : (α →o α) → _) := by
261211
intro f g h
@@ -266,9 +216,9 @@ theorem gfpApprox_mono_mid : Monotone (gfpApprox f) :=
266216
fun _ _ h => lfpApprox_mono_mid f.dual h
267217

268218
/-- The approximations of the greatest fixed point stabilize at a fixed point of `f` -/
269-
theorem gfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (h_init : f x ≤ x) (h_ab : a ≤ b)
219+
theorem gfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (hx : f x ≤ x) (hab : a ≤ b)
270220
(h : gfpApprox f x a ∈ fixedPoints f) : gfpApprox f x b = gfpApprox f x a :=
271-
lfpApprox_eq_of_mem_fixedPoints f.dual x h_init h_ab h
221+
lfpApprox_eq_of_mem_fixedPoints f.dual hx hab h
272222

273223
/-- There are distinct indices smaller than the successor of the domain's cardinality
274224
yielding the same value -/
@@ -277,15 +227,15 @@ theorem exists_gfpApprox_eq_gfpApprox : ∃ a < ord <| succ #α, ∃ b < ord <|
277227
exists_lfpApprox_eq_lfpApprox f.dual x
278228

279229
/-- The approximation at the index of the successor of the domain's cardinality is a fixed point -/
280-
lemma gfpApprox_ord_mem_fixedPoint (h_init : f x ≤ x) :
230+
lemma gfpApprox_ord_mem_fixedPoint (hx : f x ≤ x) :
281231
gfpApprox f x (ord <| succ #α) ∈ fixedPoints f :=
282-
lfpApprox_ord_mem_fixedPoint f.dual x h_init
232+
lfpApprox_ord_mem_fixedPoint f.dual hx
283233

284234
/-- Every value of the approximation is greater or equal than every fixed point of `f`
285235
less or equal than the initial value -/
286236
lemma le_gfpApprox_of_mem_fixedPoints {a : α}
287-
(h_a : a ∈ fixedPoints f) (h_le_init : a ≤ x) (i : Ordinal) : a ≤ gfpApprox f x i :=
288-
lfpApprox_le_of_mem_fixedPoints f.dual x h_a h_le_init i
237+
(ha : a ∈ fixedPoints f) (hax : a ≤ x) (i : Ordinal) : a ≤ gfpApprox f x i :=
238+
lfpApprox_le_of_mem_fixedPoints f.dual ha hax i
289239

290240
/-- The approximation sequence converges at the successor of the domain's cardinality
291241
to the greatest fixed point if starting from `⊥` -/

0 commit comments

Comments
 (0)