diff --git a/Mathlib.lean b/Mathlib.lean index 59418a4f3addc..6ed213fd85763 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1033,6 +1033,7 @@ import Mathlib.SetTheory.Cardinal.SchroederBernstein import Mathlib.SetTheory.Lists import Mathlib.SetTheory.Ordinal.Arithmetic import Mathlib.SetTheory.Ordinal.Basic +import Mathlib.SetTheory.Ordinal.CantorNormalForm import Mathlib.SetTheory.Ordinal.Exponential import Mathlib.SetTheory.Ordinal.FixedPoint import Mathlib.SetTheory.Ordinal.NaturalOps diff --git a/Mathlib/SetTheory/Ordinal/CantorNormalForm.lean b/Mathlib/SetTheory/Ordinal/CantorNormalForm.lean new file mode 100644 index 0000000000000..f0528e812806d --- /dev/null +++ b/Mathlib/SetTheory/Ordinal/CantorNormalForm.lean @@ -0,0 +1,190 @@ +/- +Copyright (c) 2018 Mario Carneiro. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro + +! This file was ported from Lean 3 source module set_theory.ordinal.cantor_normal_form +! leanprover-community/mathlib commit f1e061e3caef3022f0daa99d670ecf2c30e0b5c6 +! Please do not edit these lines, except to modify the commit id +! if you have ported upstream changes. +-/ +import Mathlib.SetTheory.Ordinal.Arithmetic +import Mathlib.SetTheory.Ordinal.Exponential + +/-! +# Cantor Normal Form + +The Cantor normal form of an ordinal is generally defined as its base `ω` expansion, with its +non-zero exponents in decreasing order. Here, we more generally define a base `b` expansion +`Ordinal.CNF` in this manner, which is well-behaved for any `b ≥ 2`. + +# Implementation notes + +We implement `Ordinal.CNF` as an association list, where keys are exponents and values are +coefficients. This is because this structure intrinsically reflects two key properties of the Cantor +normal form: + +- It is ordered. +- It has finitely many entries. + +# Todo + +- Add API for the coefficients of the Cantor normal form. +- Prove the basic results relating the CNF to the arithmetic operations on ordinals. +-/ + + +noncomputable section + +universe u + +open Order + +namespace Ordinal + +/-- Inducts on the base `b` expansion of an ordinal. -/ +@[elab_as_elim] +noncomputable def CNFRec (b : Ordinal) {C : Ordinal → Sort _} (H0 : C 0) + (H : ∀ o, o ≠ 0 → C (o % b ^ log b o) → C o) : ∀ o, C o := fun o ↦ by + by_cases (o = 0) + · rw [h]; exact H0 + · exact H o h (CNFRec _ H0 H (o % b ^ log b o)) + termination_by CNFRec b H0 H o => o + decreasing_by exact mod_opow_log_lt_self b h +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_rec Ordinal.CNFRec + +@[simp] +theorem CNFRec_zero {C : Ordinal → Sort _} (b : Ordinal) (H0 : C 0) + (H : ∀ o, o ≠ 0 → C (o % b ^ log b o) → C o) : @CNFRec b C H0 H 0 = H0 := by + rw [CNFRec, dif_pos rfl] + rfl +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_rec_zero Ordinal.CNFRec_zero + +theorem CNFRec_pos (b : Ordinal) {o : Ordinal} {C : Ordinal → Sort _} (ho : o ≠ 0) (H0 : C 0) + (H : ∀ o, o ≠ 0 → C (o % b ^ log b o) → C o) : + @CNFRec b C H0 H o = H o ho (@CNFRec b C H0 H _) := by rw [CNFRec, dif_neg ho] +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_rec_pos Ordinal.CNFRec_pos + +-- Porting note: unknown attribute @[pp_nodot] +/-- The Cantor normal form of an ordinal `o` is the list of coefficients and exponents in the +base-`b` expansion of `o`. + +We special-case `CNF 0 o = CNF 1 o = [(0, o)]` for `o ≠ 0`. + +`CNF b (b ^ u₁ * v₁ + b ^ u₂ * v₂) = [(u₁, v₁), (u₂, v₂)]` -/ +def CNF (b o : Ordinal) : List (Ordinal × Ordinal) := + CNFRec b [] (fun o _ho IH ↦ (log b o, o / b ^ log b o)::IH) o +set_option linter.uppercaseLean3 false in +#align ordinal.CNF Ordinal.CNF + +@[simp] +theorem CNF_zero (b : Ordinal) : CNF b 0 = [] := + CNFRec_zero b _ _ +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_zero Ordinal.CNF_zero + +/-- Recursive definition for the Cantor normal form. -/ +theorem CNF_ne_zero {b o : Ordinal} (ho : o ≠ 0) : + CNF b o = (log b o, o / b ^ log b o)::CNF b (o % b ^ log b o) := + CNFRec_pos b ho _ _ +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_ne_zero Ordinal.CNF_ne_zero + +theorem zero_CNF {o : Ordinal} (ho : o ≠ 0) : CNF 0 o = [⟨0, o⟩] := by simp [CNF_ne_zero ho] +set_option linter.uppercaseLean3 false in +#align ordinal.zero_CNF Ordinal.zero_CNF + +theorem one_CNF {o : Ordinal} (ho : o ≠ 0) : CNF 1 o = [⟨0, o⟩] := by simp [CNF_ne_zero ho] +set_option linter.uppercaseLean3 false in +#align ordinal.one_CNF Ordinal.one_CNF + +theorem CNF_of_le_one {b o : Ordinal} (hb : b ≤ 1) (ho : o ≠ 0) : CNF b o = [⟨0, o⟩] := by + rcases le_one_iff.1 hb with (rfl | rfl) + · exact zero_CNF ho + · exact one_CNF ho +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_of_le_one Ordinal.CNF_of_le_one + +theorem CNF_of_lt {b o : Ordinal} (ho : o ≠ 0) (hb : o < b) : CNF b o = [⟨0, o⟩] := by + simp only [CNF_ne_zero ho, log_eq_zero hb, opow_zero, div_one, mod_one, CNF_zero] +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_of_lt Ordinal.CNF_of_lt + +/-- Evaluating the Cantor normal form of an ordinal returns the ordinal. -/ +theorem CNF_foldr (b o : Ordinal) : (CNF b o).foldr (fun p r ↦ b ^ p.1 * p.2 + r) 0 = o := + CNFRec b (by rw [CNF_zero]; rfl) + (fun o ho IH ↦ by rw [CNF_ne_zero ho, List.foldr_cons, IH, div_add_mod]) o +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_foldr Ordinal.CNF_foldr + +/-- Every exponent in the Cantor normal form `CNF b o` is less or equal to `log b o`. -/ +theorem CNF_fst_le_log {b o : Ordinal.{u}} {x : Ordinal × Ordinal} : x ∈ CNF b o → x.1 ≤ log b o := + by + refine' CNFRec b _ (fun o ho H ↦ _) o + · rw [CNF_zero] + intro contra; contradiction + · rw [CNF_ne_zero ho, List.mem_cons] + rintro (rfl | h) + · exact le_rfl + · exact (H h).trans (log_mono_right _ (mod_opow_log_lt_self b ho).le) +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_fst_le_log Ordinal.CNF_fst_le_log + +/-- Every exponent in the Cantor normal form `CNF b o` is less or equal to `o`. -/ +theorem CNF_fst_le {b o : Ordinal.{u}} {x : Ordinal × Ordinal} (h : x ∈ CNF b o) : x.1 ≤ o := + (CNF_fst_le_log h).trans <| log_le_self _ _ +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_fst_le Ordinal.CNF_fst_le + +/-- Every coefficient in a Cantor normal form is positive. -/ +theorem CNF_lt_snd {b o : Ordinal.{u}} {x : Ordinal × Ordinal} : x ∈ CNF b o → 0 < x.2 := by + refine' CNFRec b _ (fun o ho IH ↦ _) o + · simp only [CNF_zero, List.not_mem_nil, IsEmpty.forall_iff] + · rcases eq_zero_or_pos b with (rfl | hb) + · rw [zero_CNF ho, List.mem_singleton] + rintro rfl + exact Ordinal.pos_iff_ne_zero.2 ho + · rw [CNF_ne_zero ho] + intro h + cases' (List.mem_cons.mp h) with h h + · rw [h]; rw [div_pos] + · exact opow_log_le_self _ ho + · exact (opow_pos _ hb).ne' + · exact IH h +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_lt_snd Ordinal.CNF_lt_snd + +/-- Every coefficient in the Cantor normal form `CNF b o` is less than `b`. -/ +theorem CNF_snd_lt {b o : Ordinal.{u}} (hb : 1 < b) {x : Ordinal × Ordinal} : + x ∈ CNF b o → x.2 < b := by + refine' CNFRec b _ (fun o ho IH ↦ _) o + · simp only [CNF_zero, List.not_mem_nil, IsEmpty.forall_iff] + · rw [CNF_ne_zero ho] + intro h + cases' (List.mem_cons.mp h) with h h + · rw [h]; simpa only using div_opow_log_lt o hb + · exact IH h +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_snd_lt Ordinal.CNF_snd_lt + +/-- The exponents of the Cantor normal form are decreasing. -/ +theorem CNF_sorted (b o : Ordinal) : ((CNF b o).map Prod.fst).Sorted (· > ·) := by + refine' CNFRec b _ (fun o ho IH ↦ _) o + · simp only [CNF_zero] + · cases' le_or_lt b 1 with hb hb + · simp only [CNF_of_le_one hb ho, List.map] + · cases' lt_or_le o b with hob hbo + · simp only [CNF_of_lt ho hob, List.map] + · rw [CNF_ne_zero ho, List.map_cons, List.sorted_cons] + refine' ⟨fun a H ↦ _, IH⟩ + rw [List.mem_map'] at H + rcases H with ⟨⟨a, a'⟩, H, rfl⟩ + exact (CNF_fst_le_log H).trans_lt (log_mod_opow_log_lt_log_self hb ho hbo) +set_option linter.uppercaseLean3 false in +#align ordinal.CNF_sorted Ordinal.CNF_sorted + +end Ordinal +