/- Copyright (c) 2018 Violeta Hernández Palacios, Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Violeta Hernández Palacios, Mario Carneiro -/ module public import Mathlib.Logic.Small.List public import Mathlib.SetTheory.Ordinal.Enum public import Mathlib.SetTheory.Ordinal.Exponential /-! # Fixed points of normal functions We prove various statements about the fixed points of normal ordinal functions. We state them in two forms: as statements about indexed families of normal functions, and as statements about a single normal function. Moreover, we prove some lemmas about the fixed points of specific normal functions. ## Main definitions and results * `nfpFamily`, `nfp`: the next fixed point of a (family of) normal function(s). * `not_bddAbove_fp_family`, `not_bddAbove_fp`: the (common) fixed points of a (family of) normal function(s) are unbounded in the ordinals. * `deriv_add_eq_mul_omega0_add`: a characterization of the derivative of addition. * `deriv_mul_eq_opow_omega0_mul`: a characterization of the derivative of multiplication. -/ @[expose] public section noncomputable section universe u v open Function Order namespace Ordinal /-! ### Fixed points of type-indexed families of ordinals -/ section variable {ι : Type*} {f : ι → Ordinal.{u} → Ordinal.{u}} /-- The next common fixed point, at least `a`, for a family of normal functions. This is defined for any family of functions, as the supremum of all values reachable by applying finitely many functions in the family to `a`. `Ordinal.nfpFamily_fp` shows this is a fixed point, `Ordinal.le_nfpFamily` shows it's at least `a`, and `Ordinal.nfpFamily_le_fp` shows this is the least ordinal with these properties. -/ def nfpFamily (f : ι → Ordinal.{u} → Ordinal.{u}) (a : Ordinal.{u}) : Ordinal := ⨆ i, List.foldr f a i theorem foldr_le_nfpFamily [Small.{u} ι] (f : ι → Ordinal.{u} → Ordinal.{u}) (a l) : List.foldr f a l ≤ nfpFamily f a := Ordinal.le_iSup _ _ theorem le_nfpFamily [Small.{u} ι] (f : ι → Ordinal.{u} → Ordinal.{u}) (a) : a ≤ nfpFamily f a := foldr_le_nfpFamily f a [] theorem lt_nfpFamily_iff [Small.{u} ι] {a b} : a < nfpFamily f b ↔ ∃ l, a < List.foldr f b l := Ordinal.lt_iSup_iff theorem nfpFamily_le_iff [Small.{u} ι] {a b} : nfpFamily f a ≤ b ↔ ∀ l, List.foldr f a l ≤ b := Ordinal.iSup_le_iff theorem nfpFamily_le {a b} : (∀ l, List.foldr f a l ≤ b) → nfpFamily f a ≤ b := Ordinal.iSup_le theorem nfpFamily_monotone [Small.{u} ι] (hf : ∀ i, Monotone (f i)) : Monotone (nfpFamily f) := fun _ _ h ↦ nfpFamily_le <| fun l ↦ (List.foldr_monotone hf l h).trans (foldr_le_nfpFamily _ _ l) theorem apply_lt_nfpFamily [Small.{u} ι] (H : ∀ i, IsNormal (f i)) {a b} (hb : b < nfpFamily f a) (i) : f i b < nfpFamily f a := let ⟨l, hl⟩ := lt_nfpFamily_iff.1 hb lt_nfpFamily_iff.2 ⟨i::l, (H i).strictMono hl⟩ theorem apply_lt_nfpFamily_iff [Nonempty ι] [Small.{u} ι] (H : ∀ i, IsNormal (f i)) {a b} : (∀ i, f i b < nfpFamily f a) ↔ b < nfpFamily f a := by refine ⟨fun h ↦ ?_, apply_lt_nfpFamily H⟩ let ⟨l, hl⟩ := lt_nfpFamily_iff.1 (h (Classical.arbitrary ι)) exact lt_nfpFamily_iff.2 <| ⟨l, (H _).strictMono.le_apply.trans_lt hl⟩ theorem nfpFamily_le_apply [Nonempty ι] [Small.{u} ι] (H : ∀ i, IsNormal (f i)) {a b} : (∃ i, nfpFamily f a ≤ f i b) ↔ nfpFamily f a ≤ b := by contrapose!; exact apply_lt_nfpFamily_iff H theorem nfpFamily_le_fp (H : ∀ i, Monotone (f i)) {a b} (ab : a ≤ b) (h : ∀ i, f i b ≤ b) : nfpFamily f a ≤ b := by apply Ordinal.iSup_le fun l ↦ ?_ induction l generalizing a with | nil => exact ab | cons i l IH => exact (H i (IH ab)).trans (h i) theorem nfpFamily_fp [Small.{u} ι] {i} (H : IsNormal (f i)) (a) : f i (nfpFamily f a) = nfpFamily f a := by rw [nfpFamily, H.map_iSup (bddAbove_of_small _)] apply le_antisymm <;> refine Ordinal.iSup_le fun l => ?_ · exact Ordinal.le_iSup _ (i::l) · exact H.strictMono.le_apply.trans (Ordinal.le_iSup _ _) theorem apply_le_nfpFamily [Small.{u} ι] [hι : Nonempty ι] (H : ∀ i, IsNormal (f i)) {a b} : (∀ i, f i b ≤ nfpFamily f a) ↔ b ≤ nfpFamily f a := by refine ⟨fun h => ?_, fun h i => ?_⟩ · obtain ⟨i⟩ := hι exact (H i).strictMono.le_apply.trans (h i) · rw [← nfpFamily_fp (H i)] exact (H i).monotone h theorem nfpFamily_eq_self [Small.{u} ι] {a} (h : ∀ i, f i a = a) : nfpFamily f a = a := by apply (Ordinal.iSup_le ?_).antisymm (le_nfpFamily f a) intro l rw [List.foldr_fixed' h l] -- Todo: This is actually a special case of the fact the intersection of club sets is a club set. /-- A generalization of the fixed point lemma for normal functions: any family of normal functions has an unbounded set of common fixed points. -/ theorem not_bddAbove_fp_family [Small.{u} ι] (H : ∀ i, IsNormal (f i)) : ¬ BddAbove (⋂ i, Function.fixedPoints (f i)) := by rw [not_bddAbove_iff] refine fun a ↦ ⟨nfpFamily f (succ a), ?_, (lt_succ a).trans_le (le_nfpFamily f _)⟩ rintro _ ⟨i, rfl⟩ exact nfpFamily_fp (H i) _ /-- The derivative of a family of normal functions is the sequence of their common fixed points. This is defined for all functions such that `Ordinal.derivFamily_zero`, `Ordinal.derivFamily_succ`, and `Ordinal.derivFamily_limit` are satisfied. -/ def derivFamily (f : ι → Ordinal.{u} → Ordinal.{u}) (o : Ordinal.{u}) : Ordinal.{u} := limitRecOn o (nfpFamily f 0) (fun _ IH => nfpFamily f (succ IH)) fun a _ g => ⨆ b : Set.Iio a, g _ b.2 @[simp] theorem derivFamily_zero (f : ι → Ordinal → Ordinal) : derivFamily f 0 = nfpFamily f 0 := limitRecOn_zero .. @[simp] theorem derivFamily_add_one (f : ι → Ordinal → Ordinal) (o) : derivFamily f (o + 1) = nfpFamily f (derivFamily f o + 1) := limitRecOn_succ .. -- TODO: deprecate theorem derivFamily_succ (f : ι → Ordinal → Ordinal) (o) : derivFamily f (succ o) = nfpFamily f (succ (derivFamily f o)) := derivFamily_add_one f o theorem derivFamily_limit (f : ι → Ordinal → Ordinal) {o} : IsSuccLimit o → derivFamily f o = ⨆ b : Set.Iio o, derivFamily f b := limitRecOn_limit _ _ _ _ theorem isNormal_derivFamily [Small.{u} ι] (f : ι → Ordinal.{u} → Ordinal.{u}) : IsNormal (derivFamily f) := by refine IsNormal.of_succ_lt (fun o ↦ ?_) @fun o h ↦ ?_ · rw [derivFamily_succ, ← succ_le_iff] exact le_nfpFamily _ _ · rw [derivFamily_limit _ h, Set.image_eq_range] have := h.nonempty_Iio.to_subtype exact isLUB_ciSup (bddAbove_of_small _) theorem derivFamily_strictMono [Small.{u} ι] (f : ι → Ordinal.{u} → Ordinal.{u}) : StrictMono (derivFamily f) := (isNormal_derivFamily f).strictMono theorem derivFamily_fp [Small.{u} ι] {i} (H : IsNormal (f i)) (o : Ordinal) : f i (derivFamily f o) = derivFamily f o := by induction o using limitRecOn with | zero => rw [derivFamily_zero] exact nfpFamily_fp H 0 | succ => rw [derivFamily_succ] exact nfpFamily_fp H _ | limit o l IH => have := l.nonempty_Iio.to_subtype rw [derivFamily_limit _ l, H.map_iSup (bddAbove_of_small _)] refine eq_of_forall_ge_iff fun c => ?_ rw [Ordinal.iSup_le_iff, Ordinal.iSup_le_iff] refine forall_congr' fun a ↦ ?_ rw [IH _ a.2] theorem le_iff_derivFamily [Small.{u} ι] (H : ∀ i, IsNormal (f i)) {a} : (∀ i, f i a ≤ a) ↔ ∃ o, derivFamily f o = a := ⟨fun ha => by suffices ∀ (o), a ≤ derivFamily f o → ∃ o, derivFamily f o = a from this a (isNormal_derivFamily _).strictMono.le_apply intro o induction o using limitRecOn with | zero => intro h₁ refine ⟨0, le_antisymm ?_ h₁⟩ rw [derivFamily_zero] exact nfpFamily_le_fp (fun i => (H i).monotone) (zero_le _) ha | succ o IH => intro h₁ rcases le_or_gt a (derivFamily f o) with h | h · exact IH h refine ⟨succ o, le_antisymm ?_ h₁⟩ rw [derivFamily_succ] exact nfpFamily_le_fp (fun i => (H i).monotone) (succ_le_of_lt h) ha | limit o l IH => intro h₁ rcases eq_or_lt_of_le h₁ with h | h · exact ⟨_, h.symm⟩ rw [derivFamily_limit _ l, ← not_le, Ordinal.iSup_le_iff, not_forall] at h obtain ⟨o', h⟩ := h exact IH o' o'.2 (le_of_not_ge h), fun ⟨_, e⟩ i => e ▸ (derivFamily_fp (H i) _).le⟩ theorem fp_iff_derivFamily [Small.{u} ι] (H : ∀ i, IsNormal (f i)) {a} : (∀ i, f i a = a) ↔ ∃ o, derivFamily f o = a := Iff.trans ⟨fun h i => le_of_eq (h i), fun h i => (H i).strictMono.le_apply.ge_iff_eq'.1 (h i)⟩ (le_iff_derivFamily H) theorem mem_range_derivFamily [Small.{u} ι] (H : ∀ i, IsNormal (f i)) {a} : a ∈ Set.range (derivFamily f) ↔ ∀ i, f i a = a := (fp_iff_derivFamily H).symm /-- For a family of normal functions, `Ordinal.derivFamily` enumerates the common fixed points. -/ theorem derivFamily_eq_enumOrd [Small.{u} ι] (H : ∀ i, IsNormal (f i)) : derivFamily f = enumOrd (⋂ i, Function.fixedPoints (f i)) := by rw [eq_comm, eq_enumOrd _ (not_bddAbove_fp_family H)] use (isNormal_derivFamily f).strictMono rw [Set.range_eq_iff] refine ⟨?_, fun a ha => ?_⟩ · rintro a S ⟨i, hi⟩ rw [← hi] exact derivFamily_fp (H i) a rw [Set.mem_iInter] at ha rwa [← fp_iff_derivFamily H] end /-! ### Fixed points of a single function -/ section variable {f : Ordinal.{u} → Ordinal.{u}} /-- The next fixed point function, the least fixed point of the normal function `f`, at least `a`. This is defined as `nfpFamily` applied to a family consisting only of `f`. -/ def nfp (f : Ordinal → Ordinal) : Ordinal → Ordinal := nfpFamily fun _ : Unit => f theorem nfp_eq_nfpFamily (f : Ordinal → Ordinal) : nfp f = nfpFamily fun _ : Unit => f := rfl theorem iSup_iterate_eq_nfp (f : Ordinal.{u} → Ordinal.{u}) (a : Ordinal.{u}) : ⨆ n : ℕ, f^[n] a = nfp f a := by apply le_antisymm · rw [Ordinal.iSup_le_iff] intro n rw [← List.length_replicate (n := n) (a := Unit.unit), ← List.foldr_const f a] exact Ordinal.le_iSup _ _ · apply Ordinal.iSup_le intro l rw [List.foldr_const f a l] exact Ordinal.le_iSup _ _ theorem iterate_le_nfp (f a n) : f^[n] a ≤ nfp f a := by rw [← iSup_iterate_eq_nfp] exact Ordinal.le_iSup (fun n ↦ f^[n] a) n theorem le_nfp (f a) : a ≤ nfp f a := iterate_le_nfp f a 0 theorem lt_nfp_iff {a b} : a < nfp f b ↔ ∃ n, a < f^[n] b := by rw [← iSup_iterate_eq_nfp] exact Ordinal.lt_iSup_iff theorem nfp_le_iff {a b} : nfp f a ≤ b ↔ ∀ n, f^[n] a ≤ b := by rw [← iSup_iterate_eq_nfp] exact Ordinal.iSup_le_iff theorem nfp_le {a b} : (∀ n, f^[n] a ≤ b) → nfp f a ≤ b := nfp_le_iff.2 @[simp] theorem nfp_id : nfp id = id := by ext simp_rw [← iSup_iterate_eq_nfp, iterate_id] exact ciSup_const theorem nfp_monotone (hf : Monotone f) : Monotone (nfp f) := nfpFamily_monotone fun _ => hf theorem iterate_lt_nfp (hf : StrictMono f) {a} (h : a < f a) (n : ℕ) : f^[n] a < nfp f a := by apply (hf.iterate n h).trans_le rw [← iterate_succ_apply] exact iterate_le_nfp .. theorem apply_lt_nfp (H : IsNormal f) {a b} : f b < nfp f a ↔ b < nfp f a := by unfold nfp rw [← @apply_lt_nfpFamily_iff Unit (fun _ => f) _ _ (fun _ => H) a b] exact ⟨fun h _ => h, fun h => h Unit.unit⟩ @[deprecated (since := "2025-12-25")] alias IsNormal.apply_lt_nfp := apply_lt_nfp theorem nfp_le_apply (H : IsNormal f) {a b} : nfp f a ≤ f b ↔ nfp f a ≤ b := le_iff_le_iff_lt_iff_lt.2 (apply_lt_nfp H) @[deprecated (since := "2025-12-25")] alias IsNormal.nfp_le_apply := nfp_le_apply theorem nfp_le_fp (H : Monotone f) {a b} (ab : a ≤ b) (h : f b ≤ b) : nfp f a ≤ b := nfpFamily_le_fp (fun _ => H) ab fun _ => h theorem nfp_fp (H : IsNormal f) : ∀ a, f (nfp f a) = nfp f a := @nfpFamily_fp Unit (fun _ => f) _ () H @[deprecated (since := "2025-12-25")] alias IsNormal.nfp_fp := nfp_fp theorem apply_le_nfp (H : IsNormal f) {a b} : f b ≤ nfp f a ↔ b ≤ nfp f a := ⟨H.strictMono.le_apply.trans, fun h => by simpa only [nfp_fp H] using H.monotone h⟩ @[deprecated (since := "2025-12-25")] alias IsNormal.apply_le_nfp := apply_le_nfp theorem nfp_eq_self {a} (h : f a = a) : nfp f a = a := nfpFamily_eq_self fun _ => h /-- The fixed point lemma for normal functions: any normal function has an unbounded set of fixed points. -/ theorem not_bddAbove_fp (H : IsNormal f) : ¬ BddAbove (Function.fixedPoints f) := by convert not_bddAbove_fp_family fun _ : Unit => H exact (Set.iInter_const _).symm /-- The derivative of a normal function `f` is the sequence of fixed points of `f`. This is defined as `Ordinal.derivFamily` applied to a trivial family consisting only of `f`. -/ def deriv (f : Ordinal → Ordinal) : Ordinal → Ordinal := derivFamily fun _ : Unit => f theorem deriv_eq_derivFamily (f : Ordinal → Ordinal) : deriv f = derivFamily fun _ : Unit => f := rfl @[simp] theorem deriv_zero_right (f) : deriv f 0 = nfp f 0 := derivFamily_zero _ @[simp] theorem deriv_add_one (f o) : deriv f (o + 1) = nfp f (deriv f o + 1) := derivFamily_succ _ _ -- TODO: deprecate theorem deriv_succ (f o) : deriv f (succ o) = nfp f (succ (deriv f o)) := deriv_add_one .. theorem deriv_limit (f) {o} : IsSuccLimit o → deriv f o = ⨆ a : {a // a < o}, deriv f a := derivFamily_limit _ theorem isNormal_deriv (f) : IsNormal (deriv f) := isNormal_derivFamily _ theorem deriv_strictMono (f) : StrictMono (deriv f) := derivFamily_strictMono _ theorem deriv_eq_id_of_nfp_eq_id (h : nfp f = id) : deriv f = id := ((isNormal_deriv _).ext .id).2 (by simp [h]) @[deprecated (since := "2025-10-25")] alias deriv_id_of_nfp_id := deriv_eq_id_of_nfp_eq_id theorem deriv_fp (H : IsNormal f) : ∀ o, f (deriv f o) = deriv f o := derivFamily_fp (i := ⟨⟩) H @[deprecated (since := "2025-10-25")] alias IsNormal.deriv_fp := deriv_fp theorem le_iff_deriv (H : IsNormal f) {a} : f a ≤ a ↔ ∃ o, deriv f o = a := by unfold deriv rw [← le_iff_derivFamily fun _ : Unit => H] exact ⟨fun h _ => h, fun h => h Unit.unit⟩ @[deprecated (since := "2025-10-25")] alias IsNormal.le_iff_deriv := le_iff_deriv theorem mem_range_deriv (H : IsNormal f) {a} : a ∈ Set.range (deriv f) ↔ f a = a := by rw [Set.mem_range, ← H.strictMono.le_apply.ge_iff_eq', le_iff_deriv H] @[deprecated mem_range_deriv (since := "2025-10-25")] theorem fp_iff_deriv (H : IsNormal f) {a} : f a = a ↔ ∃ o, deriv f o = a := (mem_range_deriv H).symm @[deprecated mem_range_deriv (since := "2025-10-25")] alias IsNormal.fp_iff_deriv := fp_iff_deriv /-- `Ordinal.deriv` enumerates the fixed points of a normal function. -/ theorem deriv_eq_enumOrd (H : IsNormal f) : deriv f = enumOrd (Function.fixedPoints f) := by convert derivFamily_eq_enumOrd fun _ : Unit => H exact (Set.iInter_const _).symm theorem nfp_zero_left (a) : nfp 0 a = a := by rw [← iSup_iterate_eq_nfp] apply (Ordinal.iSup_le ?_).antisymm (Ordinal.le_iSup _ 0) intro n cases n · rfl · rw [Function.iterate_succ'] simp @[simp] theorem nfp_zero : nfp 0 = id := by ext exact nfp_zero_left _ @[simp] theorem deriv_zero : deriv 0 = id := deriv_eq_id_of_nfp_eq_id nfp_zero theorem deriv_zero_left (a) : deriv 0 a = a := by rw [deriv_zero, id_eq] end /-! ### Fixed points of addition -/ @[simp] theorem nfp_add_zero (a) : nfp (a + ·) 0 = a * ω := by simp_rw [← iSup_iterate_eq_nfp, ← iSup_mul_natCast] congr; funext n induction n with | zero => rw [Nat.cast_zero, mul_zero, iterate_zero_apply] | succ n hn => rw [iterate_succ_apply', Nat.add_comm, Nat.cast_add, Nat.cast_one, mul_one_add, hn] theorem nfp_add_eq_mul_omega0 {a b} (hba : b ≤ a * ω) : nfp (a + ·) b = a * ω := by apply le_antisymm (nfp_le_fp (isNormal_add_right a).monotone hba _) · rw [← nfp_add_zero] exact nfp_monotone (isNormal_add_right a).monotone (zero_le b) · dsimp; rw [← mul_one_add, one_add_omega0] theorem add_eq_right_iff_mul_omega0_le {a b : Ordinal} : a + b = b ↔ a * ω ≤ b := by refine ⟨fun h => ?_, fun h => ?_⟩ · rw [← nfp_add_zero a, ← deriv_zero_right] obtain ⟨c, hc⟩ := (mem_range_deriv (isNormal_add_right a)).2 h rw [← hc] exact (isNormal_deriv _).monotone (zero_le _) · have := Ordinal.add_sub_cancel_of_le h nth_rw 1 [← this] rwa [← add_assoc, ← mul_one_add, one_add_omega0] theorem add_le_right_iff_mul_omega0_le {a b : Ordinal} : a + b ≤ b ↔ a * ω ≤ b := by rw [← add_eq_right_iff_mul_omega0_le] exact (isNormal_add_right a).strictMono.le_apply.ge_iff_eq' theorem deriv_add_eq_mul_omega0_add (a b : Ordinal.{u}) : deriv (a + ·) b = a * ω + b := by revert b rw [← funext_iff, IsNormal.ext (isNormal_deriv _) (isNormal_add_right _)] refine ⟨?_, fun a h => ?_⟩ · rw [bot_eq_zero, deriv_zero_right, add_zero] exact nfp_add_zero a · rw [deriv_succ, h, add_succ] exact nfp_eq_self (add_eq_right_iff_mul_omega0_le.2 (le_self_add.trans (le_succ _))) /-! ### Fixed points of multiplication -/ @[simp] theorem nfp_mul_one {a : Ordinal} (ha : 0 < a) : nfp (a * ·) 1 = a ^ ω := by rw [← iSup_iterate_eq_nfp, ← iSup_pow_natCast ha] simp @[simp] theorem nfp_mul_zero (a : Ordinal) : nfp (a * ·) 0 = 0 := by rw [← nonpos_iff_eq_zero, nfp_le_iff] simp theorem nfp_mul_eq_opow_omega0 {a b : Ordinal} (hb : 0 < b) (hba : b ≤ a ^ ω) : nfp (a * ·) b = a ^ ω := by rcases eq_zero_or_pos a with ha | ha · rw [ha, zero_opow omega0_ne_zero] at hba ⊢ simp_rw [nonpos_iff_eq_zero.1 hba, zero_mul] exact nfp_zero_left 0 apply le_antisymm · apply nfp_le_fp (isNormal_mul_right ha).monotone hba rw [← opow_one_add, one_add_omega0] rw [← nfp_mul_one ha] exact nfp_monotone (isNormal_mul_right ha).monotone (one_le_iff_pos.2 hb) theorem eq_zero_or_opow_omega0_le_of_mul_eq_right {a b : Ordinal} (hab : a * b = b) : b = 0 ∨ a ^ ω ≤ b := by rcases eq_zero_or_pos a with ha | ha · rw [ha, zero_opow omega0_ne_zero] exact Or.inr (zero_le b) rw [or_iff_not_imp_left] intro hb rw [← nfp_mul_one ha] rw [← Ne, ← one_le_iff_ne_zero] at hb exact nfp_le_fp (isNormal_mul_right ha).monotone hb (le_of_eq hab) theorem mul_eq_right_iff_opow_omega0_dvd {a b : Ordinal} : a * b = b ↔ a ^ ω ∣ b := by rcases eq_zero_or_pos a with ha | ha · rw [ha, zero_mul, zero_opow omega0_ne_zero, zero_dvd_iff] exact eq_comm refine ⟨fun hab => ?_, fun h => ?_⟩ · rw [dvd_iff_mod_eq_zero] rw [← div_add_mod b (a ^ ω), mul_add, ← mul_assoc, ← opow_one_add, one_add_omega0, add_left_cancel_iff] at hab rcases eq_zero_or_opow_omega0_le_of_mul_eq_right hab with hab | hab · exact hab refine (not_lt_of_ge hab (mod_lt b (opow_ne_zero ω ?_))).elim rwa [← pos_iff_ne_zero] obtain ⟨c, hc⟩ := h rw [hc, ← mul_assoc, ← opow_one_add, one_add_omega0] theorem mul_le_right_iff_opow_omega0_dvd {a b : Ordinal} (ha : 0 < a) : a * b ≤ b ↔ (a ^ ω) ∣ b := by rw [← mul_eq_right_iff_opow_omega0_dvd] exact (isNormal_mul_right ha).strictMono.le_apply.ge_iff_eq' theorem nfp_mul_opow_omega0_add {a c : Ordinal} (b) (ha : 0 < a) (hc : 0 < c) (hca : c ≤ a ^ ω) : nfp (a * ·) (a ^ ω * b + c) = a ^ ω * succ b := by apply le_antisymm · apply nfp_le_fp (isNormal_mul_right ha).monotone · rw [mul_succ] gcongr · dsimp only; rw [← mul_assoc, ← opow_one_add, one_add_omega0] · obtain ⟨d, hd⟩ := mul_eq_right_iff_opow_omega0_dvd.1 (nfp_fp (isNormal_mul_right ha) (a ^ ω * b + c)) rw [hd] apply mul_le_mul_right have := le_nfp (a * ·) (a ^ ω * b + c) rw [hd] at this have := (add_lt_add_right hc (a ^ ω * b)).trans_le this rw [add_zero, mul_lt_mul_iff_right₀ (opow_pos ω ha)] at this rwa [succ_le_iff] theorem deriv_mul_eq_opow_omega0_mul {a : Ordinal.{u}} (ha : 0 < a) (b) : deriv (a * ·) b = a ^ ω * b := by revert b rw [← funext_iff, IsNormal.ext (isNormal_deriv _) (isNormal_mul_right (opow_pos ω ha))] refine ⟨?_, fun c h => ?_⟩ · rw [bot_eq_zero, deriv_zero_right, nfp_mul_zero, mul_zero] · rw [deriv_succ, h] exact nfp_mul_opow_omega0_add c ha zero_lt_one (one_le_iff_pos.2 (opow_pos _ ha)) end Ordinal