--- title: Pruebas de equivalencia de definiciones de la función de Fibonacci date: 2024-08-29 06:00:00 UTC+02:00 category: Inducción has_math: true --- [mathjax] En Lean4, se puede definir la función de Fibonacci por
def fibonacci : Nat → Nat
| 0 => 0
| 1 => 1
| n + 2 => fibonacci n + fibonacci (n+1)
Otra definición más eficiente es
def fib (n : Nat) : Nat :=
(aux n).1
where
aux : Nat → Nat × Nat
| 0 => (0, 1)
| n + 1 =>
let p := aux n
(p.2, p.1 + p.2)
Demostrar que ambas definiciones son equivalentes; es decir,
fibonacci = fib
Para ello, completar la siguiente teoría de Lean4:
open Nat
-- Para que no use la notación con puntos
set_option pp.fieldNotation false
def fibonacci : Nat → Nat
| 0 => 0
| 1 => 1
| n + 2 => fibonacci n + fibonacci (n+1)
def fib (n : Nat) : Nat :=
(aux n).1
where
aux : Nat → Nat × Nat
| 0 => (0, 1)
| n + 1 =>
let p := aux n
(p.2, p.1 + p.2)
example : fibonacci = fib :=
by sorry
fib_suma (n : Nat) : fib (n + 2) = fib n + fib (n + 1)
Tenemos que demostrar que, para todo n ∈ ℕ,
fibonacci n = fib n
Lo probaremos por inducción en n.
**Caso 1**: Supongamos que n = 0. Entonces,
fibonacci n = fibonacci 0
= 1
y
fib n = fib 0
= (aux 0).1
= (0, 1).1
= 1
Por tanto,
fibonacci n = fib n
**Caso 2**: Supongamos que n = 1. Entonces,
fibonacci n = 1
y
fib 1 = (aux 1).1
= (p.2, p.1 + p.2).1
donde p = aux 0
= ((0, 1).2, (0, 1).1 + (0, 1).2).1
= (1, 0 + 1).1
= 1
**Caso 3**: Supongamos que n = m + 2 y que se verifica las hipótesis de inducción,
HI1 : fibonacci n = fib n
HI2 : fibonacci (n + 1) = fib (n + 1)
Entonces,
fibonacci n
= fibonacci (m + 2)
= fibonacci m + fibonacci (m + 1)
= fib m + fib (m + 1) [por HI1, HI2]
= fib (m + 2) [por fib_suma]
= fib n
open Nat
-- Para que no use la notación con puntos
set_option pp.fieldNotation false
def fibonacci : Nat → Nat
| 0 => 0
| 1 => 1
| n + 2 => fibonacci n + fibonacci (n+1)
def fib (n : Nat) : Nat :=
(aux n).1
where
aux : Nat → Nat × Nat
| 0 => (0, 1)
| n + 1 =>
let p := aux n
(p.2, p.1 + p.2)
-- Lema auxiliar
-- =============
theorem fib_suma (n : Nat) : fib (n + 2) = fib n + fib (n + 1) :=
by rfl
-- 1ª demostración
-- ===============
example : fibonacci = fib :=
by
ext n
-- n : Nat
-- ⊢ fibonacci n = fib n
induction n using fibonacci.induct with
| case1 =>
-- ⊢ fibonacci 0 = fib 0
rfl
| case2 =>
-- ⊢ fibonacci 1 = fib 1
rfl
| case3 n HI1 HI2 =>
-- n : Nat
-- HI1 : fibonacci n = fib n
-- HI2 : fibonacci (n + 1) = fib (n + 1)
-- ⊢ fibonacci (succ (succ n)) = fib (succ (succ n))
rw [fib_suma]
-- ⊢ fibonacci (succ (succ n)) = fib n + fib (n + 1)
rw [fibonacci]
-- ⊢ fibonacci n + fibonacci (n + 1) = fib n + fib (n + 1)
rw [HI1]
-- ⊢ fib n + fibonacci (n + 1) = fib n + fib (n + 1)
rw [HI2]
-- 2ª demostración
-- ===============
example : fibonacci = fib :=
by
ext n
-- n : Nat
-- ⊢ fibonacci n = fib n
induction n using fibonacci.induct with
| case1 =>
-- ⊢ fibonacci 0 = fib 0
rfl
| case2 =>
-- ⊢ fibonacci 1 = fib 1
rfl
| case3 n HI1 HI2 =>
-- n : Nat
-- HI1 : fibonacci n = fib n
-- HI2 : fibonacci (n + 1) = fib (n + 1)
-- ⊢ fibonacci (succ (succ n)) = fib (succ (succ n))
calc fibonacci (succ (succ n))
= fibonacci n + fibonacci (n + 1) := by rw [fibonacci]
_ = fib n + fib (n + 1) := by rw [HI1, HI2]
_ = fib (succ (succ n)) := by rw [fib_suma]
-- 3ª demostración
-- ===============
example : fibonacci = fib :=
by
ext n
-- n : Nat
-- ⊢ fibonacci n = fib n
induction n using fibonacci.induct with
| case1 =>
-- ⊢ fibonacci 0 = fib 0
rfl
| case2 =>
-- ⊢ fibonacci 1 = fib 1
rfl
| case3 n HI1 HI2 =>
-- n : Nat
-- HI1 : fibonacci n = fib n
-- HI2 : fibonacci (n + 1) = fib (n + 1)
-- ⊢ fibonacci (succ (succ n)) = fib (succ (succ n))
simp [HI1, HI2, fibonacci, fib_suma]
Se puede interactuar con las demostraciones anteriores en [Lean 4 Web](https://live.lean-lang.org/#url=https://raw.githubusercontent.com/jaalonso/Calculemus2_es/main/src/Fibonacci.lean).
theory Fibonacci
imports Main
begin
fun fibonacci :: "nat ⇒ nat"
where
"fibonacci 0 = 0"
| "fibonacci (Suc 0) = 1"
| "fibonacci (Suc (Suc n)) = fibonacci n + fibonacci (Suc n)"
fun fibAux :: "nat => nat × nat"
where
"fibAux 0 = (0, 1)"
| "fibAux (Suc n) = (let (a, b) = fibAux n in (b, a + b))"
definition fib :: "nat ⇒ nat" where
"fib n = fst (fibAux n)"
lemma fib_suma :
"fib (Suc (Suc n)) = fib n + fib (Suc n)"
proof (induct n)
show "fib (Suc (Suc 0)) = fib 0 + fib (Suc 0)"
by (simp add: fib_def)
next
fix n
assume HI : "fib (Suc (Suc n)) = fib n + fib (Suc n)"
have "fib (Suc (Suc (Suc n))) = fst (fibAux (Suc (Suc (Suc n))))"
by (simp add: fib_def)
also have "… = snd (fibAux (Suc (Suc n)))"
by (simp add: prod.case_eq_if)
also have "… = fst (fibAux (Suc n)) + snd (fibAux (Suc n))"
by (metis fibAux.simps(2) snd_conv split_def)
also have "… = fib (Suc n) + snd (fibAux (Suc n))"
using fib_def by auto
also have "… = fib (Suc n) + fib (Suc (Suc n))"
by (simp add: fib_def prod.case_eq_if)
finally show "fib (Suc (Suc (Suc n))) = fib (Suc n) + fib (Suc (Suc n))"
by this
qed
lemma "fibonacci n = fib n"
proof (induct n rule: fibonacci.induct)
show "fibonacci 0 = fib 0"
by (simp add: fib_def)
next
show "fibonacci (Suc 0) = fib (Suc 0)"
by (simp add: fib_def)
next
fix n
assume HI1 : "fibonacci n = fib n"
assume HI2 : "fibonacci (Suc n) = fib (Suc n)"
have "fibonacci (Suc (Suc n)) = fibonacci n + fibonacci (Suc n)"
by simp
also have "… = fib n + fib (Suc n)"
by (simp add: HI1 HI2)
also have "… = fib (Suc (Suc n))"
by (simp add: fib_suma)
finally show "fibonacci (Suc (Suc n)) = fib (Suc (Suc n))"
by this
qed
end