Lean , 66 байт
def s:_->nat->nat|(m+1)(n+1):=(n+1)*(s m n+s m(n+1))|0 0:=1|_ _:=0
Спробуйте в Інтернеті!
Доказ правильності
Спробуйте в Інтернеті!
Пояснення
Дозвольмо виконувати функцію:
def s : nat->nat->nat
| (m+1) (n+1) := (n+1)*(s m n + s m (n+1))
| 0 0 := 1
| _ _ := 0
Функція визначається узгодженням шаблону та рекурсією, обидва з яких мають вбудовану підтримку.
Ми визначаємо s(m+1, n+1) = (n+1) * (s(m, n) + s(m, n+1)
і s(0, 0) = 1
, що залишає відкритим, s(m+1, 0)
і s(0, n+1)
обидва визначені 0
як останній випадок.
Lean використовує синтаксис обчислення lamdba, так і s m n
є s(m, n)
.
Тепер доказ коректності: я заявив це двома способами:
def correctness : ∀ m n, fin (s m n) ≃ { f : fin m → fin n // function.surjective f } :=
λ m, nat.rec_on m (λ n, nat.cases_on n s_zero_zero (λ n, s_zero_succ n)) $
λ m ih n, nat.cases_on n (s_succ_zero m) $ λ n,
calc fin (s (nat.succ m) (nat.succ n))
≃ (fin (n + 1) × (fin (s m n + s m (n + 1)))) :
(fin_prod _ _).symm
... ≃ (fin (n + 1) × (fin (s m n) ⊕ fin (s m (n + 1)))) :
equiv.prod_congr (equiv.refl _) (fin_sum _ _).symm
... ≃ (fin (n + 1) × ({f : fin m → fin n // function.surjective f} ⊕
{f : fin m → fin (n + 1) // function.surjective f})) :
equiv.prod_congr (equiv.refl _) (equiv.sum_congr (ih n) (ih (n + 1)))
... ≃ {f // function.surjective f} : s_aux m n
def correctness_2 (m n : nat) : s m n = fintype.card { f : fin m → fin n // function.surjective f } :=
by rw fintype.of_equiv_card (correctness m n); simp
Перший - це те, що відбувається насправді: біекція між [0 ... s(m, n)-1]
та вилучення з [0 ... m-1]
на [0 ... n-1]
.
Другий - як це констатується, тобто s(m, n)
кардинальність сюжетів з [0 ... m-1]
на [0 ... n-1]
.
Lean використовує теорію типів як свою основу (замість теорії множин). У теорії типів кожен об'єкт має властивий йому тип. nat
- це тип натуральних чисел, а твердження, що 0
є натуральним числом, виражається як 0 : nat
. Ми говоримо, що 0
це тип nat
, і це nat
є 0
як житель.
Пропозиції (твердження / твердження) також є типами: їх житель є доказом пропозиції.
def
: Ми збираємося ввести визначення (адже біекція - це дійсно функція, а не лише пропозиція).
correctness
: назва визначення
∀ m n
: для кожного m
і n
(Lean автоматично робить висновок про те, що їх тип nat
, через те, що випливає далі).
fin (s m n)
- тип натуральних чисел, менший за s m n
. Щоб зробити мешканця, треба надати натуральну кількість і доказ того, що він менший, ніж s m n
.
A ≃ B
: біекція між типом A
і типом B
. Скажімо, біекція вводить в оману, оскільки людина насправді повинна забезпечувати зворотну функцію.
{ f : fin m → fin n // function.surjective f }
тип сюжетів від fin m
до fin n
. Цей синтаксис будує підтип від типу fin m → fin n
, тобто тип функцій від fin m
до fin n
. Синтаксис є { var : base type // proposition about var }
.
λ m
: ∀ var, proposition / type involving var
дійсно є функцією, яка приймає var
як вхід, тому λ m
вводить вхід. ∀ m n,
є короткою рукою для∀ m, ∀ n,
nat.rec_on m
: зробити рекурсію на m
. Щоб визначити щось для m
, визначте річ для, 0
а потім дайте річ для k
, побудуйте річ для k+1
. Можна було б помітити, що це схоже на індукцію, і справді це є результатом листування Церкви-Говарда . Синтаксис є nat.rec_on var (thing when var is 0) (for all k, given "thing when k is k", build thing when var is "k+1")
.
Хе, це стає довго, і я лише на третьому рядку correctness
...