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
в последнем случае.
Постные использует синтаксис 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
...