Еквівалентність натуральних чисел
Аналіз I, Розділ 2, Епілог: Ізоморфізм із натуральними числами Mathlib
У цьому (технічному) епілозі ми показуємо, що натуральні числа Chapter2.Nat з "Розділу 2"
ізоморфні стандартним натуральним числам ℕ у різних типових сенсах.
З цього моменту Chapter2.Nat буде застарілим типом, і замість нього ми використовуватимемо
стандартні натуральні числа ℕ. Зокрема, для всіх наступних розділів слід використовувати
повний API Mathlib для ℕ замість API Chapter2.Nat.
Для заповнення цих вибачень потрібні як Chapter2.Nat API, так і Mathlib API для стандартних
натуральних чисел ℕ. Таким чином, вони є чудовими вправами для підготовки до вищезгаданого
переходу.
У другій половині цього розділу ми також наводимо повністю аксіоматичне трактування
натуральних чисел за допомогою аксіом Пеано. Розгляд у попередніх трьох розділах
був лише частково аксіоматичним, оскільки ми використовували специфічну конструкцію
Chapter2.Nat натуральних чисел, яка була індуктивного типу, і використовували цей
індуктивний тип для побудови рекурсора. Тут ми наводимо кілька вправ, щоб показати,
як можна виконати ті ж завдання безпосередньо з аксіом Пеано, не знаючи конкретної
реалізації натуральних чисел.
Підказки від попередніх користувачів
Користувачі супровідного матеріалу, які виконали вправи в цьому розділі, можуть надсилати свої поради майбутнім користувачам цього розділу як PRи.
-
(Додайте підказку тут)
Перетворення натурального числа з Розділу 2 на натуральне число Mathlib.
abbrev Chapter2.Nat.toNat (n : Chapter2.Nat) : ℕ := match n with
| zero => 0
| succ n' => n'.toNat + 1lemma Chapter2.Nat.zero_toNat : (0 : Chapter2.Nat).toNat = 0 := rfllemma Chapter2.Nat.succ_toNat (n : Chapter2.Nat) : (n++).toNat = n.toNat + 1 := rflПеретворення є бієкцією. Тут ми використовуємо наявну можливість (з Розділу 2.1) для відображення натуральних чисел Mathlib на натуральні числа Розділу 2.
abbrev Chapter2.Nat.equivNat : Chapter2.Nat ≃ ℕ where
toFun := toNat
invFun n := (n:Chapter2.Nat)
left_inv n := n:Nat⊢ (fun n => ↑n) n.toNat = n
⊢ (fun n => ↑n) zero.toNat = zeron:Nathn:(fun n => ↑n) n.toNat = n⊢ (fun n => ↑n) n++.toNat = n++; n:Nathn:(fun n => ↑n) n.toNat = n⊢ (fun n => ↑n) n++.toNat = n++
n:Nathn:(fun n => ↑n) n.toNat = n⊢ n + 1 = n++
All goals completed! 🐙
right_inv n := n:ℕ⊢ ((fun n => ↑n) n).toNat = n
⊢ ((fun n => ↑n) 0).toNat = 0n:ℕhn:((fun n => ↑n) n).toNat = n⊢ ((fun n => ↑n) (n + 1)).toNat = n + 1; n:ℕhn:((fun n => ↑n) n).toNat = n⊢ ((fun n => ↑n) (n + 1)).toNat = n + 1
All goals completed! 🐙Перетворення зберігає операцію додавання.
abbrev Chapter2.Nat.map_add : ∀ (n m : Nat), (n + m).toNat = n.toNat + m.toNat := ⊢ ∀ (n m : Nat), (n + m).toNat = n.toNat + m.toNat
n:Natm:Nat⊢ (n + m).toNat = n.toNat + m.toNat
m:Nat⊢ (zero + m).toNat = zero.toNat + m.toNatm:Natn:Nathn:(n + m).toNat = n.toNat + m.toNat⊢ (n++ + m).toNat = n++.toNat + m.toNat
m:Nat⊢ (zero + m).toNat = zero.toNat + m.toNat All goals completed! 🐙
All goals completed! 🐙Перетворення зберігає операцію множення.
abbrev Chapter2.Nat.map_mul : ∀ (n m : Nat), (n * m).toNat = n.toNat * m.toNat := ⊢ ∀ (n m : Nat), (n * m).toNat = n.toNat * m.toNat
n:Natm:Nat⊢ (n * m).toNat = n.toNat * m.toNat
All goals completed! 🐙Перетворення зберігає порядок.
abbrev Chapter2.Nat.map_le_map_iff : ∀ {n m : Nat}, n.toNat ≤ m.toNat ↔ n ≤ m := ⊢ ∀ {n m : Nat}, n.toNat ≤ m.toNat ↔ n ≤ m
n:Natm:Nat⊢ n.toNat ≤ m.toNat ↔ n ≤ m
All goals completed! 🐙abbrev Chapter2.Nat.equivNat_ordered_ring : Chapter2.Nat ≃+*o ℕ where
toEquiv := equivNat
map_add' := map_add
map_mul' := map_mul
map_le_map_iff' := map_le_map_iffПеретворення зберігає піднесення до степеня.
lemma Chapter2.Nat.pow_eq_pow (n m : Chapter2.Nat) :
n.toNat ^ m.toNat = (n^m).toNat := n:Natm:Nat⊢ n.toNat ^ m.toNat = (n ^ m).toNat
All goals completed! 🐙
Аксіоми Пеано для абстрактного типу Nat
@[ext]
structure PeanoAxioms where
Nat : Type
zero : Nat -- Аксіома 2.1
succ : Nat → Nat -- Аксіома 2.2
succ_ne : ∀ n : Nat, succ n ≠ zero -- Аксіома 2.3
succ_cancel : ∀ {n m : Nat}, succ n = succ m → n = m -- Аксіома 2.4
induction : ∀ (P : Nat → Prop),
P zero → (∀ n : Nat, P n → P (succ n)) → ∀ n : Nat, P n -- Аксіома 2.5namespace PeanoAxiomsНатуральні числа розділу 2 дотримуються аксіом Пеано.
def Chapter2_Nat : PeanoAxioms where
Nat := Chapter2.Nat
zero := Chapter2.Nat.zero
succ := Chapter2.Nat.succ
succ_ne := Chapter2.Nat.succ_ne
succ_cancel := Chapter2.Nat.succ_cancel
induction := Chapter2.Nat.inductionНатуральні числа Mathlib дотримуються аксіом Пеано.
def Mathlib_Nat : PeanoAxioms where
Nat := ℕ
zero := 0
succ := Nat.succ
succ_ne := Nat.succ_ne_zero
succ_cancel := Nat.succ_inj.mp
induction _ := Nat.recВи можете співставити натуральні числа Mathlib у іншу струкруту яка дотримується аксіом Пеано.
abbrev natCast (P : PeanoAxioms) : ℕ → P.Nat := fun n ↦ match n with
| Nat.zero => P.zero
| Nat.succ n => P.succ (natCast P n)
Доведення можна почати тут з unfold Function.Injective, хоча це не є строго обов’язковим.
theorem natCast_injective (P : PeanoAxioms) : Function.Injective P.natCast := P:PeanoAxioms⊢ Function.Injective P.natCast
All goals completed! 🐙
Доведення можна почати тут з unfold Function.Surjective, хоча це не є строго обов’язковим.
theorem natCast_surjective (P : PeanoAxioms) : Function.Surjective P.natCast := P:PeanoAxioms⊢ Function.Surjective P.natCast
All goals completed! 🐙
Поняття еквівалентності між двома структурами, що задовольняють аксіоми Пеано.
Символ є псевдонімом для класу Equiv у Mathlib; наприклад, P.Nat ≃ Q.Nat
є псевдонімом для _root_.Equiv P.Nat Q.Nat.
class Equiv (P Q : PeanoAxioms) where
equiv : P.Nat ≃ Q.Nat
equiv_zero : equiv P.zero = Q.zero
equiv_succ : ∀ n : P.Nat, equiv (P.succ n) = Q.succ (equiv n)
Ця вправа вимагатиме застосування API Mathlib для класу Equiv.
Деякі частини цього API можна викликати автоматично за допомогою тактики simp.
abbrev Equiv.symm {P Q: PeanoAxioms} (equiv : Equiv P Q) : Equiv Q P where
equiv := equiv.equiv.symm
equiv_zero := P:PeanoAxiomsQ:PeanoAxiomsequiv:P.Equiv Q⊢ Equiv.equiv.symm Q.zero = P.zero All goals completed! 🐙
equiv_succ n := P:PeanoAxiomsQ:PeanoAxiomsequiv:P.Equiv Qn:Q.Nat⊢ Equiv.equiv.symm (Q.succ n) = P.succ (Equiv.equiv.symm n) All goals completed! 🐙
Ця вправа вимагатиме застосування API Mathlib для класу Equiv.
Деякі частини цього API можна викликати автоматично за допомогою тактики simp.
abbrev Equiv.trans {P Q R: PeanoAxioms} (equiv1 : Equiv P Q) (equiv2 : Equiv Q R) : Equiv P R where
equiv := equiv1.equiv.trans equiv2.equiv
equiv_zero := P:PeanoAxiomsQ:PeanoAxiomsR:PeanoAxiomsequiv1:P.Equiv Qequiv2:Q.Equiv R⊢ (equiv.trans equiv) P.zero = R.zero All goals completed! 🐙
equiv_succ n := P:PeanoAxiomsQ:PeanoAxiomsR:PeanoAxiomsequiv1:P.Equiv Qequiv2:Q.Equiv Rn:P.Nat⊢ (equiv.trans equiv) (P.succ n) = R.succ ((equiv.trans equiv) n) All goals completed! 🐙
Корисні інструменти Mathlib для інверсії бієкцій включають Function.surjInv та Function.invFun.
noncomputable abbrev Equiv.fromNat (P : PeanoAxioms) : Equiv Mathlib_Nat P where
equiv := {
toFun := P.natCast
invFun := P:PeanoAxioms⊢ P.Nat → Mathlib_Nat.Nat All goals completed! 🐙
left_inv := P:PeanoAxioms⊢ Function.LeftInverse sorry P.natCast All goals completed! 🐙
right_inv := P:PeanoAxioms⊢ Function.RightInverse sorry P.natCast All goals completed! 🐙
}
equiv_zero := P:PeanoAxioms⊢ { toFun := P.natCast, invFun := sorry, left_inv := ⋯, right_inv := ⋯ } Mathlib_Nat.zero = P.zero All goals completed! 🐙
equiv_succ n := P:PeanoAxiomsn:Mathlib_Nat.Nat⊢ { toFun := P.natCast, invFun := sorry, left_inv := ⋯, right_inv := ⋯ } (Mathlib_Nat.succ n) =
P.succ ({ toFun := P.natCast, invFun := sorry, left_inv := ⋯, right_inv := ⋯ } n) All goals completed! 🐙Завдання тут полягає в тому, щоб довести, що будь-які дві структури, які задовольняють аксіоми Пеано, є еквівалентними.
noncomputable abbrev Equiv.mk' (P Q : PeanoAxioms) : Equiv P Q := P:PeanoAxiomsQ:PeanoAxioms⊢ P.Equiv Q All goals completed! 🐙Існує лише одна еквівалентність між будь-якими двома структурами, що задовольняють аксіоми Пеано.
theorem Equiv.uniq {P Q : PeanoAxioms} (equiv1 equiv2 : PeanoAxioms.Equiv P Q) :
equiv1 = equiv2 := P:PeanoAxiomsQ:PeanoAxiomsequiv1:P.Equiv Qequiv2:P.Equiv Q⊢ equiv1 = equiv2
P:PeanoAxiomsQ:PeanoAxiomsequiv2:P.Equiv Qequiv1:P.Nat ≃ Q.Natequiv_zero1:equiv1 P.zero = Q.zeroequiv_succ1:∀ (n : P.Nat), equiv1 (P.succ n) = Q.succ (equiv1 n)⊢ { equiv := equiv1, equiv_zero := equiv_zero1, equiv_succ := equiv_succ1 } = equiv2
P:PeanoAxiomsQ:PeanoAxiomsequiv1:P.Nat ≃ Q.Natequiv_zero1:equiv1 P.zero = Q.zeroequiv_succ1:∀ (n : P.Nat), equiv1 (P.succ n) = Q.succ (equiv1 n)equiv2:P.Nat ≃ Q.Natequiv_zero2:equiv2 P.zero = Q.zeroequiv_succ2:∀ (n : P.Nat), equiv2 (P.succ n) = Q.succ (equiv2 n)⊢ { equiv := equiv1, equiv_zero := equiv_zero1, equiv_succ := equiv_succ1 } =
{ equiv := equiv2, equiv_zero := equiv_zero2, equiv_succ := equiv_succ2 }
P:PeanoAxiomsQ:PeanoAxiomsequiv1:P.Nat ≃ Q.Natequiv_zero1:equiv1 P.zero = Q.zeroequiv_succ1:∀ (n : P.Nat), equiv1 (P.succ n) = Q.succ (equiv1 n)equiv2:P.Nat ≃ Q.Natequiv_zero2:equiv2 P.zero = Q.zeroequiv_succ2:∀ (n : P.Nat), equiv2 (P.succ n) = Q.succ (equiv2 n)⊢ equiv1 = equiv2
P:PeanoAxiomsQ:PeanoAxiomsequiv1:P.Nat ≃ Q.Natequiv_zero1:equiv1 P.zero = Q.zeroequiv_succ1:∀ (n : P.Nat), equiv1 (P.succ n) = Q.succ (equiv1 n)equiv2:P.Nat ≃ Q.Natequiv_zero2:equiv2 P.zero = Q.zeroequiv_succ2:∀ (n : P.Nat), equiv2 (P.succ n) = Q.succ (equiv2 n)n:P.Nat⊢ equiv1 n = equiv2 n
All goals completed! 🐙Приклад результату: рекурсія коректно визначена на будь-якій структурі, що підпорядковується аксіомам Пеано.
theorem Nat.recurse_uniq {P : PeanoAxioms} (f: P.Nat → P.Nat → P.Nat) (c: P.Nat) :
∃! (a: P.Nat → P.Nat), a P.zero = c ∧ ∀ n, a (P.succ n) = f n (a n) := P:PeanoAxiomsf:P.Nat → P.Nat → P.Natc:P.Nat⊢ ∃! a, a P.zero = c ∧ ∀ (n : P.Nat), a (P.succ n) = f n (a n)
All goals completed! 🐙end PeanoAxioms