chapter ‹R12: Razonamiento sobre programas en Isabelle/HOL (III)›
theory R12_sol
imports Main
begin
text ‹------------------------------------------------------------------
En toda la relación de ejercicios las demostraciones han de realizarse
de las formas siguientes:
+ en lenguaje natural
+ aplicativa o declarativa usando "simp"
+ aplicativa o declarativa usando "simp only: ..."
+ automática
Además, se recomienda el uso de lemas auxiliares (nuevos o de los
ejercicios anteriores) para que las demostraciones sean más cortas y
claras.
---------------------------------------------------------------------›
text ‹------------------------------------------------------------------
Ejercicio 1. Definir la función
estaEn :: 'a ⇒ 'a list ⇒ bool
tal que (estaEn x xs) se verifica si el elemento x está en la lista
xs. Por ejemplo,
estaEn (2::nat) [3,2,4] = True
estaEn (1::nat) [3,2,4] = False
---------------------------------------------------------------------›
fun estaEn :: "'a ⇒ 'a list ⇒ bool" where
"estaEn x [] = False"
| "estaEn x (a # xs) = (a = x ∨ estaEn x xs)"
text ‹------------------------------------------------------------------
Ejercicio 2. Definir la función
sublista :: "'a list ⇒ 'a list ⇒ bool
tal que (sublista xs ys) se verifica si todos los elementos de la
lista xs están en la lista ys. Por ejemplo,
sublista [(1::nat),2,3] [3,2,1,2] = True
sublista [(1::nat),2,3] [2,1,2] = False
----------------------------------------------------------------------›
fun sublista :: "'a list ⇒ 'a list ⇒ bool" where
"sublista [] ys = True"
| "sublista (x # xs) ys = (estaEn x ys ∧ sublista xs ys )"
text ‹------------------------------------------------------------------
Ejercicio 3. Demostrar la siguiente propiedad: si xs es sublista de
ys, entonces xs también es sublista de la lista (y # ys). Es decir,
sublista xs ys ⟹ sublista xs (y # ys)
----------------------------------------------------------------------›
― ‹Demostración en lenguaje natural:
Por inducción en xs.
+ Caso base: Sea xs = [].
Supongamos que "sublista [] ys", entonces se tiene
"sublista [] (y # ys)" por la definición de sublista.
+ Paso inductivo: Sea x un elemento y xs una lista de elementos que
verifica la hipótesis de inducción (HI):
sublista xs ys ⟶ sublista xs (y # ys)
Hay que probar que
sublista (x # xs) ys ⟶ sublista (x # xs) (y # ys)
Para ello, se supone que
1. sublista (x # xs) ys
y basta probar que
sublista (x # xs) (y # ys).
La demostración es
2. estaEn x ys /\ sublista xs ys (de 1, por def. sublista)
3. sublista xs ys (de 2, por conjunct2)
4. sublista xs (y # ys) (de 4 e HI, por mp)
5. estaEn x ys (de 2, por conjunct1)
6. estaEn x (y # ys) (de 5, por def. estaEn)
7. estaEn x (y # ys) /\ sublista xs (y # ys) (de 6 y 4, por conjI)
8. sublista (x # xs) (y # ys) (de 7, por def. sublista)
›
― ‹Demostración declarativa con simp:›
lemma
"sublista xs ys ⟶ sublista xs (y # ys)"
proof (induct xs)
show "sublista [] ys ⟶ sublista [] (y # ys)" by simp
next
fix a xs
assume HI: "sublista xs ys ⟶ sublista xs (y # ys)"
show "sublista (a # xs) ys ⟶ sublista (a # xs) (y # ys)"
by (simp add: HI)
qed
― ‹Demostración declarativa detallada:›
lemma sublistaMono_d:
"sublista xs ys ⟶ sublista xs (y # ys)"
proof (induct xs)
show "sublista [] ys ⟶ sublista [] (y # ys)"
proof (rule impI)
assume "sublista [] ys"
show "sublista [] (y # ys)"
by (simp only: sublista.simps(1))
qed
next
fix a xs
assume HI: "sublista xs ys ⟶ sublista xs (y # ys)"
show "sublista (a # xs) ys ⟶ sublista (a # xs) (y # ys)"
proof (rule impI)
assume "sublista (a # xs) ys"
then have 1: "(estaEn a ys ∧ sublista xs ys )"
by (simp only: sublista.simps(2))
then have "estaEn a ys"
by (rule conjunct1)
then have "y = a ∨ estaEn a ys"
by (rule disjI2)
then have "estaEn a (y # ys)"
by (simp only: estaEn.simps(2))
have "sublista xs ys"
using 1 by (rule conjunct2)
with HI have "sublista xs (y # ys)"
by (rule mp)
with ‹estaEn a (y # ys)›
have "estaEn a (y # ys) ∧ sublista xs (y # ys)"
by (rule conjI)
then show "sublista (a # xs) (y # ys)"
by (simp only: sublista.simps(2))
qed
qed
lemma sublistaMono_de:
assumes "sublista xs ys"
shows "sublista xs (y#ys)"
proof -
have "sublista xs ys ⟶ sublista xs (y#ys)"
by (rule sublistaMono_d)
then show "sublista xs (y#ys)"
using assms by (rule mp)
qed
― ‹Demostración aplicativa detallada:›
lemma sublistaMono: "sublista xs ys ⟹ sublista xs (y # ys)"
apply (induct xs)
apply (simp only: sublista.simps(1))
apply (simp only: sublista.simps(2))
apply (rule conjI)
apply (erule conjE)
apply (simp only: estaEn.simps(2))
apply (rule disjI2)
apply (simp only: implies_True_equals)+
done
text ‹------------------------------------------------------------------
Ejercicio 4. Demostrar que la relación sublista es reflexiva. Es
decir,
sublista xs xs
---------------------------------------------------------------------›
― ‹Demostración en lenguaje natural:
Por inducción en xs.
+ Caso base: xs = []
Se verifica "sublista [] []" (por def. de sublista)
+ Paso inductivo: Sean x un elemento y xs una lista de elementos que
verifican la hipótesis de inducción (HI):
sublista xs xs
Hay que probarque
sublista (x # xs) (x # xs)
En efecto:
1. sublista xs xs (por HI)
2. sublista xs (x # xs) (por 1 y sublistaMono)
3. estaEn x (x # xs) (por lema auxiliar)
4. estaEn x (x # xs) ∧ sublista xs (x # xs) (de 3 y 2, por conjI)
5. sublista (x # xs) (x # xs) (de 4 por def. sublista)
›
― ‹Demostración declarativa:›
lemma sublistaReflexiva_d: "sublista xs xs"
proof (induct xs)
show "sublista [] []"
by (simp only: sublista.simps(1))
next
fix x :: "'a" and xs :: "'a list"
assume "sublista xs xs"
then show "sublista (x # xs) (x # xs)"
by (simp add: sublistaMono)
qed
(* Lema auxiliar *)
lemma estaEn1: "estaEn x (x # xs)"
apply (simp only: estaEn.simps(2))
apply (rule disjI1)
apply (rule refl)
done
― ‹Demostración declarativa detallada›
lemma "sublista xs xs"
proof (induct xs)
show "sublista [] []"
by (simp only: sublista.simps(1))
next
fix x :: "'a" and xs :: "'a list"
assume "sublista xs xs"
then have "sublista xs (x # xs)"
by (rule sublistaMono)
then have "estaEn x (x # xs) ∧ sublista xs (x # xs)"
by (simp only: estaEn1)
then show "sublista (x # xs) (x # xs)"
by (simp only: sublista.simps(2))
qed
― ‹Demostración aplicativa detallada›
lemma sublistaReflexiva: "sublista xs xs"
apply (induct xs)
apply (simp only: sublista.simps(1))
apply (simp only: sublista.simps(2))
apply (rule conjI)
apply (rule estaEn1)
apply (rule sublistaMono, assumption)
done
text ‹------------------------------------------------------------------
Ejercicio 5. Probar, como corolario, que
sublista xs (x # xs)
---------------------------------------------------------------------›
― ‹Demostración en lenguaje natural:
Se verifica "sublista xs xs" por el lema sublistaReflexiva. Por tanto,
aplicando el lema sublistaMono, se tiene "sublista xs (x # xs)".›
― ‹Demostración declarativa detallada›
corollary sublistaInc_d: "sublista xs (x # xs)"
proof-
have "sublista xs xs"
by (rule sublistaReflexiva)
then show "sublista xs (x # xs)"
by (rule sublistaMono)
qed
― ‹Demostración aplicativa detallada›
corollary sublistaInc: "sublista xs (x # xs)"
apply (rule sublistaMono)
apply (rule sublistaReflexiva)
done
text ‹------------------------------------------------------------------
Ejercicio 6. Probar que la relación sublista es transitiva. Es decir,
sublista xs ys ∧ sublista ys zs ⟶ sublista xs zs
---------------------------------------------------------------------›
― ‹Demostración en lenguaje natural:
Por inducción en xs.
+ Caso base: Supongamos que xs = [].
Hay que probar que
"sublista [] ys ∧ sublista ys zs ⟶ sublista [] zs"
Para ello, supongamos que
"sublista [] ys ∧ sublista ys zs"
Entonces "sublista [] zs" se tiene por la definición de sublista.
+ Paso inductivo: Sean a un elemento y xs una lista de elementos para
los que se cumple la hipótesis de inducción (HI):
"sublista xs ys ∧ sublista ys zs ⟶ sublista xs zs"
Hay que probar que
"sublista (a # xs) ys ∧ sublista ys zs ⟶ sublista (a # xs) zs"
Para ello, supongamos que
1. "sublista (a # xs) ys ∧ sublista ys zs"
y hay que probar que
"sublista (a # xs) zs".
Su prueba es
2. (estaEn a ys ∧ sublista xs ys) ∧ sublista ys zs
(de 1, por def. sublista)
3. sublista xs ys ∧ sublista ys zs
(de 2, por la asociativa de la conjunción y la eliminación de
la conjunción)
4. sublista xs zs
(de 3, por HI)
5. estaEn a ys
(de 2, por eliminación de la conjunción)
6. sublista ys zs
(de 3)
7. estaEn a zs
(de 5 y 6 por lema auxiliar)
8. sublista (a # xs) zs
(de 7 y 4, por def. sublista)
›
(* Auxiliar *)
lemma sublistaEstaEn:
"estaEn x xs ∧ sublista xs ys ⟶ estaEn x ys"
apply (induct xs)
apply (rule impI)
apply (simp only: estaEn.simps(1))
apply (drule conjunct1)
apply (simp only: False_implies_equals)
apply (rule impI)
apply (simp only: estaEn.simps(2))
apply (erule conjE)
apply (erule disjE)
apply (simp only: sublista.simps(2))
apply (simp only: sublista.simps(2))
done
― ‹Demostración declarativa:›
lemma sublistaTransitiva_e:
"sublista xs ys ∧ sublista ys zs ⟶ sublista xs zs"
proof (induct xs)
show "sublista [] ys ∧ sublista ys zs ⟶ sublista [] zs"
by simp
next
fix a xs
assume HI:"sublista xs ys ∧ sublista ys zs ⟶ sublista xs zs"
show " sublista (a # xs) ys ∧ sublista ys zs ⟶ sublista (a # xs) zs"
proof (rule impI)
assume "sublista (a # xs) ys ∧ sublista ys zs"
then have 1: "(estaEn a ys ∧ sublista xs ys) ∧ sublista ys zs" by simp
then have "estaEn a ys" by simp
have "sublista ys zs" using 1 by simp
then have "estaEn a zs" using ‹estaEn a ys›
by (simp add: sublistaEstaEn)
have "sublista xs ys ∧ sublista ys zs" using 1 by simp
then have "sublista xs zs" using HI by simp
then show "sublista (a # xs) zs" using ‹estaEn a zs› by simp
qed
qed
― ‹Demostración declarativa detallada›
lemma sublistaTransitiva_d:
"sublista xs ys ∧ sublista ys zs ⟶ sublista xs zs"
proof (induct xs)
show "sublista [] ys ∧ sublista ys zs ⟶ sublista [] zs"
proof (rule impI)
assume "sublista [] ys ∧ sublista ys zs"
show "sublista [] zs"
by (simp only: sublista.simps(1))
qed
next
fix a xs
assume HI: "sublista xs ys ∧ sublista ys zs ⟶ sublista xs zs"
show " sublista (a # xs) ys ∧ sublista ys zs ⟶ sublista (a # xs) zs"
proof (rule impI)
assume "sublista (a # xs) ys ∧ sublista ys zs"
then have "(estaEn a ys ∧ sublista xs ys) ∧ sublista ys zs"
by (simp only: sublista.simps(2))
then have 1: "estaEn a ys ∧ (sublista xs ys ∧ sublista ys zs)"
by (simp only: conj_assoc)
then have "sublista xs ys ∧ sublista ys zs"
by (rule conjunct2)
with HI have "sublista xs zs"
by (rule mp)
have "estaEn a ys"
using 1 by (rule conjunct1)
have "sublista ys zs"
using ‹sublista xs ys ∧ sublista ys zs› by (rule conjunct2)
with ‹estaEn a ys› have "estaEn a zs"
by (simp only: sublistaEstaEn)
then show "sublista (a # xs) zs"
using ‹sublista xs zs› by (simp only: sublista.simps(2))
qed
qed
― ‹Demostración aplicativa detallada›
lemma sublistaTransitiva:
"sublista xs ys ∧ sublista ys zs ⟶ sublista xs zs"
apply (induct xs)
apply (rule impI)
apply (simp only: sublista.simps(1))
apply (simp only: sublista.simps(2))
apply (rule impI)
apply (rule conjI)
apply (simp only: conj_comms)
apply (frule conjunct1)
apply (drule conjunct2)+
apply (simp only: sublistaEstaEn)
apply (erule mp)
apply (rule conjI)
apply (drule conjunct1)
apply (drule conjunct2, assumption)+
done
text ‹------------------------------------------------------------------
Ejercicio 7. Definir la función
coge :: nat ⇒ 'a list ⇒ 'a list
tal que (coge n xs) es la lista de los n primeros elementos de xs. Por
ejemplo,
coge 2 [a,c,d,b,e] = [a,c]
------------------------------------------------------------------ ›
fun coge :: "nat ⇒ 'a list ⇒ 'a list" where
"coge n [] = []"
| "coge 0 xs = []"
| "coge (Suc n) (x # xs) = x # (coge n xs)"
text ‹------------------------------------------------------------------
Ejercicio 8. Probar que
coge 0 xs = []
---------------------------------------------------------------------›
― ‹Demostración en lenguaje natural:
Por casos sobre los posibles valores de xs.
+ Caso 1: Supongamos que xs = []. En este caso, "coge 0 [] = []" por la
primera ecuación de la definición de coge.
+ Caso 2: Supongamos quexs es de la forma y#ys. En este caso,
"coge 0 (y#ys) = []" por la segunda ecuación de la definición de coge.
›
― ‹Demostración declarativa detallada›
lemma coge0_d: "coge 0 xs = []"
proof (cases xs)
case Nil
then show ?thesis by (simp only: coge.simps(1))
next
case Cons
then show ?thesis by (simp only: coge.simps(2))
qed
― ‹Demostración aplicativa detallada›
lemma coge0: "coge 0 xs = []"
apply (case_tac xs)
apply (simp only: coge.simps(1))
apply (simp only: coge.simps(2))
done
text ‹------------------------------------------------------------------
Ejercicio 9. Probar que
length xs ≤ n ⟹ coge n xs = xs
---------------------------------------------------------------------›
― ‹Demostración en lenguaje natural:
Por inducción según el esquema coge.induct. Se generan los tres casos
siguientes:
+ Caso 1: "⋀n. length [] ≤ n ⟶ coge n [] = []"
Sea n cualquiera. Por la regla impI, hay que suponer "length [] ≤ n"
y probar "coge n [] = []", lo que es cierto por la definición de coge.
+ Caso 2: "⋀x xs. length (x # xs) ≤ 0 ⟶ coge 0 (x # xs) = x # xs"
Sean x un elemento y xs una lista.
2.1. length (x # xs) ≤ 0 (por supuesto)
2.2. False (de 2.1 por def. de length)
2.3. coge 0 (x # xs) = x # xs (de 2.2 por eliminación de False)
+ Caso 3. "⋀n x xs.
length xs ≤ n ⟶ coge n xs = xs ⟹
length (x # xs) ≤ Suc n ⟶ coge (Suc n) (x # xs) = x # xs"
Sean n un número natural, x un elememto y xs una lista.
HI: "length xs ≤ n ⟶ coge n xs = xs"
Hay que probar:
length (x # xs) ≤ Suc n ⟶ coge (Suc n) (x # xs) = x # xs"
Aplicando la regla impI, suponemos 3.1.
3.1. length (x # xs) ≤ Suc n
3.2. 1 + length xs ≤ Suc n (de 3.1 por def. de length)
3.3. length xs ≤ n (de 3.2 por monotonía)
3.4. coge n xs = xs (de 3.4 por HI)
3.5. coge (Suc n) (x # xs) = x # coge n xs (por def. de coge)
3.6. coge (Suc n) (x # xs) = x # xs (de 3.5 y 3.4)
›
― ‹Demostración declarativa›
lemma
"length xs ≤ n ⟶ coge n xs = xs"
proof (induct rule: coge.induct)
fix n
show "length [] ≤ n ⟶ coge n [] = []" by simp
next
fix x :: "'a" and xs :: "'a list"
show "length (x # xs) ≤ 0 ⟶ coge 0 (x # xs) = x # xs" by simp
next
fix n
fix x :: "'a" and xs :: "'a list"
assume HI: "length xs ≤ n ⟶ coge n xs = xs"
show "length (x # xs) ≤ Suc n ⟶ coge (Suc n) (x # xs) = x # xs"
by (simp add: HI)
qed
― ‹Demostración declarativa detallada ›
lemma cogeTodos_d:
"length xs ≤ n ⟶ coge n xs = xs"
proof (induct rule: coge.induct)
fix n
show "length [] ≤ n ⟶ coge n [] = []"
proof (rule impI)
assume "length [] ≤ n"
show "coge n [] = []"
by (simp only:coge.simps(1))
qed
next
fix x :: "'a" and xs :: "'a list"
show "length (x # xs) ≤ 0 ⟶ coge 0 (x # xs) = x # xs"
proof (rule impI)
assume "length (x # xs) ≤ 0"
then have False
by (simp only: list.size)
then show "coge 0 (x # xs) = x # xs"
by (rule FalseE)
qed
next
fix n and x :: "'a" and xs :: "'a list"
assume HI: "length xs ≤ n ⟶ coge n xs = xs"
show "length (x # xs) ≤ Suc n ⟶ coge (Suc n) (x # xs) = x # xs"
proof (rule impI)
assume "length (x # xs) ≤ Suc n"
then have "1 + length xs ≤ Suc n"
by (simp only: list.size(4))
then have "length xs ≤ n"
by (simp only: Suc_le_mono)
with HI have "coge n xs = xs"
by (rule mp)
have "coge (Suc n) (x # xs) = x # coge n xs"
by (simp only: coge.simps(3))
also have "… = x#xs"
using ‹coge n xs = xs› by (rule arg_cong)
finally show "coge (Suc n) (x # xs) = x # xs"
by this
qed
qed
lemma cogeTodos_de:
assumes "length xs ≤ n"
shows "coge n xs = xs"
proof-
have "length xs ≤ n ⟶ coge n xs = xs"
by (rule cogeTodos_d)
then show "coge n xs = xs"
using assms by (rule mp)
qed
― ‹Demostración aplicativa detallada:›
lemma cogeTodos: "length xs ≤ n ⟹ coge n xs = xs"
apply (induct rule: coge.induct)
apply (simp only: coge.simps(1))
apply (simp only: list.size)
apply (simp only: coge.simps(3))
apply (simp only: list.size)
done
text ‹------------------------------------------------------------------
Ejercicio 10. Probar que
length (coge n xs) ≤ n
---------------------------------------------------------------------›
― ‹Demostración en lenguaje natural:
Por inducción en n con xs arbitrario.
+ Caso base: Supongamos que n = 0.
Hay que probar: ∀xs. length (coge 0 xs) ≤ 0
En efecto, sea xs una lista cualquiera.
length (coge 0 xs)
= length [] (def. de coge)
= 0 (def. de length)
≤ 0
+ Paso inductivo:
HI: ∀xs. length (coge n xs) ≤ n
Hay que probar: ∀xs. length (coge (n+1) xs) ≤ n+1
Sea xs una lista cualquiera. Consideramos dos casos para xs:
+ Caso 1: xs = []
length (coge (n+1) [])
= length [] (def. de coge)
= 0 (def. de lenght)
≤ n+1 (aritmética)
+ Caso 2: xs = y#ys
length (coge (n+1) (y#ys))
= length (y#(coge n ys)) (def. de coge)
= 1 + length (coge n ys) (def. de length)
≤ 1 + n (HI aplicada a ys)
= n + 1
›
― ‹Demostración declarativa›
lemma "length (coge n xs) ≤ n"
proof (induct n arbitrary: xs)
fix xs :: "'a list"
show "length (coge 0 xs) ≤ 0"
by (simp add: coge0)
next
fix n and xs :: "'a list"
assume HI: "(⋀xs :: 'a list. length (coge n xs) ≤ n)"
show "length (coge (Suc n) xs) ≤ Suc n"
proof (cases xs)
assume "xs = []"
then show "length (coge (Suc n) xs) ≤ Suc n"
by simp
next
fix y ys
assume 1: "xs = y # ys"
show "length (coge (Suc n) xs) ≤ Suc n"
proof -
have 2: "length (coge n ys) ≤ n"
using HI by simp
have "length (coge (Suc n) xs) =
length (coge (Suc n) (y#ys))"
using 1 by (rule arg_cong)
also have "… = length (y#(coge n ys))"
by (simp only: coge.simps(3))
also have "… = 1 + length (coge n ys)"
by (simp only: list.size(4))
also have "… ≤ 1 + n" using 2
by (rule add_left_mono)
also have "… = Suc n"
by (simp only: Suc_eq_plus1_left)
finally show ?thesis
by this
qed
qed
qed
― ‹Demostración declarativa detallada›
lemma "length (coge n xs) ≤ n"
proof (induct n arbitrary: xs)
fix xs :: "'a list"
show "length (coge 0 xs) ≤ 0"
proof-
have "coge 0 xs = []"
by (rule coge0)
then have "length (coge 0 xs) = 0"
by (simp only: list.size(3))
then show "length (coge 0 xs) ≤ 0"
by (simp only: order_refl)
qed
next
fix n and xs :: "'a list"
assume HI: "(⋀xs :: 'a list. length (coge n xs) ≤ n)"
show "length (coge (Suc n) xs) ≤ Suc n"
proof (cases xs)
assume "xs = []"
then have "coge (Suc n) xs = coge (Suc n) []"
by (rule arg_cong)
also have "… = []"
by (simp only:coge.simps(1))
finally have "coge (Suc n) xs = []"
by this
then have "length (coge (Suc n) xs) = 0"
by (simp only: list.size)
then show "length (coge (Suc n) xs) ≤ Suc n"
by (simp only: zero_le)
next
fix y ys
assume 1: "xs = y # ys"
show "length (coge (Suc n) xs) ≤ Suc n"
proof -
have 2: "length (coge n ys) ≤ n"
using HI by this
have "length (coge (Suc n) xs) =
length (coge (Suc n) (y#ys))"
using 1 by (rule arg_cong)
also have "… = length (y#(coge n ys))"
by (simp only: coge.simps(3))
also have "… = 1 + length (coge n ys)"
by (simp only: list.size(4))
also have "… ≤ 1 + n" using 2
by (rule add_left_mono)
also have "… = Suc n"
by (simp only: Suc_eq_plus1_left)
finally show ?thesis
by this
qed
qed
qed
― ‹Demostración aplicativa detallada:›
lemma cogeLongN: "length (coge n xs) ≤ n"
apply(induct n arbitrary:xs)
apply (simp only: coge0)
apply (simp only: list.size)
apply (case_tac xs)
apply (simp only: coge.simps(1))
apply (simp only: list.size)
apply (simp only: coge.simps(3))
apply (simp only: list.size)
apply (simp only: add_Suc_right)
apply (simp only: Suc_le_mono)
apply (simp only: add.right_neutral)
done
text ‹------------------------------------------------------------------
Ejercicio 11. Probar que
length (coge n xs) ≤ length xs
---------------------------------------------------------------------›
― ‹Demostración en lenguaje natural:
Por inducción en n con xs arbitrario. Hay que probar los siguientes casos:
+ Caso base: ⋀xs. length (coge 0 xs) ≤ length xs
En efecto, sea xs una lista cualquiera,
length (coge 0 xs)
= 0 (por coge0 y prop. de length)
≤ 0
+ Paso inductivo: sea n un número natural y xs una lista.
Por HI se tiene ⋀xs. length (coge n xs) ≤ length xs
Y hay que probar: length (coge (Suc n) xs) ≤ length xs
La demostración se realiza por casos, según los posibles
casos de xs.
+ Caso 1: xs = []
En este caso,
1. coge (Suc n) [] = [] (por def. de coge)
2. length (coge (Suc n) xs) = 0 (de 1, por def. de length)
3. length (coge (Suc n) xs) ≤ length xs (de 2, por def. de length)
+ Caso 2: xs = y # ys
En este caso se tiene
1. length (coge n ys) ≤ length ys (por HI)
Luego:
length (coge (Suc n) xs)
= length (coge (Suc n) (y#ys)) (por xs = y # ys)
= length (y#(coge n ys)) (por def. de coge)
= 1 + length (coge n ys) (por def. de length)
≤ 1 + length ys" (por 1 y monotonía)
= length (y#ys) (por def. de length)
= length xs
›
― ‹Demostración declarativa detallada:›
lemma cogeLongL_d: "length (coge n xs) ≤ length xs"
proof (induct n arbitrary: xs)
fix xs :: "'a list"
show "length (coge 0 xs) ≤ length xs"
by (simp only: coge0 list.size(3))
next
fix n and xs :: "'a list"
assume HI: "⋀xs:: 'a list. length (coge n xs) ≤ length xs"
show "length (coge (Suc n) xs) ≤ length xs"
proof (cases xs)
assume "xs = []"
then have "coge (Suc n) xs = coge (Suc n) []"
by (rule arg_cong)
also have "… = []"
by (simp only: coge.simps(1))
finally have "coge (Suc n) xs = []"
by this
then have "length (coge (Suc n) xs) = 0"
by (simp only: list.size)
then show "length (coge (Suc n) xs) ≤ length xs"
by (simp only: list.size(3))
next
fix y ys
assume 1:"xs = y # ys"
have 2: "length (coge n ys) ≤ length ys"
using HI by this
have "length (coge (Suc n) xs) = length (coge (Suc n) (y#ys))"
using 1 by (rule arg_cong)
also have "… = length (y#(coge n ys))"
by (simp only: coge.simps(3))
also have "… = 1 + length (coge n ys)"
by (simp only: list.size(4))
also have "… ≤ 1 + length ys"
using 2 by (simp only: Suc_le_mono)
also have "… = length (y#ys)"
by (simp only: list.size(4))
also have "… = length xs"
using 1 by (simp only:list.size(4))
finally show "length (coge (Suc n) xs) ≤ length xs"
by this
qed
qed
― ‹Demostración aplicativa detallada:›
lemma cogeLongL: "length (coge n xs) ≤ length xs"
apply (induct n arbitrary: xs)
apply (simp only: coge0 list.size(3))
apply (case_tac xs)
apply (simp only: coge.simps(1))
apply (simp only: coge.simps(3))
apply (simp only: list.size(4))
apply (simp only: add_Suc_right)
apply (simp only: add.right_neutral)
apply (simp only: Suc_le_mono)
done
text ‹------------------------------------------------------------------
Ejercicio 12. Probar que
length (coge n xs) = min n (length xs)
---------------------------------------------------------------------›
― ‹Demostración en lenguaje natural:
Se pueden realizar distintas demostraciones.
(A) Primera demostración:
Por inducción en xs con n arbitrario, se generan los dos
casos siguientes:
+ Caso base: ⋀n. length (coge n []) = min n (length [])
En este caso, sea n un número natural,
length (coge n [])
= length [] (por def. de coge)
= 0 (por def. de length)
= min n 0 (por prop. de min)
= min n (length [])
+ Paso inductivo: ⋀x xs n.
(⋀n. length (coge n xs) = min n (length xs)) ==>
length (coge n (x # xs)) = min n (length (x # xs))
Sean x un elemento, xs una lista y n un natural, se tiene
HI: length (coge n xs) = min n (length xs)), y
hay que probar: length (coge n (x # xs)) = min n (length (x # xs))
Para ello, consideramos dos casos según n:
+ Caso 1: n = 0
En este caso,
length (coge 0 (x # xs))
= length [] (por coge0)
= 0 (por def. de length)
= min 0 (length (x # xs)) (por prop. de min y length)
+ Caso 2: n = m + 1
En este caso,
length (coge (m+1) (x # xs))
= length (x # (coge m xs)) (por def. de coge)
= 1 + length m xs (por def. de coge)
= 1 + min m (length xs) (por HI)
= min (1 + m) (1 + length xs) (por prop. de min)
= min n (length (x # xs)) (por def. de length)
(B) Segunda demostración:
Por inducción en n con xs arbitrario, hay que demostrar los siguintes
casos:
+ Caso base: ⋀xs. length (coge 0 xs) = min 0 (length xs)
En efecto, sea xs una lista cualquiera.
length (coge 0 xs)
= length [] (por def. de coge)
= 0 (por def. de length)
= min 0 (length xs) (por prop. de length)
+ Paso inductivo:
⋀n xs. (⋀xs. length (coge n xs) = min n (length xs)) ⟹
length (coge (Suc n) xs) = min (Suc n) (length xs)
Sea n un número natural y xs una lista cualquiera.
Por HI: (⋀xs. length (coge n xs) = min n (length xs))
Hay que probar: length (coge (Suc n) xs) = min (Suc n) (length xs)
Para ello, distinguimos dos casos, según los valores que puede tomar
xs.
+ Caso 1: xs = []
En este caso,
length (coge (Suc n) [])
= length [] (por def. de coge)
= 0 (por def. de length)
= min (Suc n) 0 (por prop. de min)
= min (Suc n) (length []) (por def. de length)
+ Caso 2: xs = y # ys
En este caso,
length (coge (Suc n) (y # ys))
= length (y # (coge n ys)) (por def. de coge)
= 1 + length (coge n ys) (por def. de length)
= 1 + min n (length ys) (por HI aplicada a ys)
= min (1 + n) (1 + length ys) (por prop. de min)
= min (Suc n) (length (y # ys)) (por def. de length)
= min (Suc n) (length xs)
(C) Tercera demostración:
Por doble desigualdad, probando como lemas auxiliares:
C1: "length (coge n xs) ≤ min n (length xs)"
C2: "min n (length xs) ≤ length (coge n xs)"
›
― ‹Demostración declarativa detallada de la primera demostración›
lemma lengthCogeMin_d:"length (coge n xs) = min n (length xs)"
proof (induct xs arbitrary:n)
fix n::"nat"
have "length (coge n []) = 0"
by (simp only:coge.simps(1) list.size)
then show "length (coge n []) = min n (length [])"
by (simp only:list.size min_0R)
next
fix x::"'a" and xs::"'a list" and n::"nat"
assume HI:"⋀n. length (coge n xs) = min n (length xs)"
show "length (coge n (x#xs)) = min n (length (x#xs))"
proof (cases n)
assume "n = 0"
then have "0 = n" by (rule sym)
have "length (coge 0 (x#xs)) = 0" by (simp only:coge0 list.size)
then have "length (coge 0 (x#xs)) = min 0 (length (x#xs))"
by (simp only:min_0L)
with`0=n` show "length (coge n (x#xs)) = min n (length (x#xs))"
by (rule subst)
next
fix m::"nat"
assume 1:"n = Suc(m)"
then have 2:"Suc(m) = n" by (rule sym)
have "length (coge n (x#xs)) = length (x # coge m xs)"
using 1 by (simp only:coge.simps(3))
then have "length (coge n (x#xs)) = 1 + length (coge m xs)"
by (simp only:list.size)
then have "length (coge n (x#xs)) = 1 + min m (length xs)"
using HI by simp
then have "length (coge n (x#xs)) = min (Suc m) (1+length xs)"
by simp
then show "length (coge n (x # xs)) = min n (length (x#xs))"
using 2 by (simp only:list.size)
qed
qed
― ‹Demostración aplicativa detallada de la segunda demostración:›
lemma lengthCogeMin: "length (coge n xs) = min n (length xs)"
apply (induct n arbitrary: xs)
apply (simp only: coge0)
apply (simp only: list.size(3))
apply (case_tac xs)
apply (simp only: coge.simps(1))
apply (simp only: list.size(3))
apply (simp only: coge.simps(3))
apply (simp only: list.size(4))
done
― ‹Demostración declarativa detallada de la tercera demostración:›
lemma lengthCogeMenorMin:
"length (coge n xs) ≤ min n (length xs)"
proof -
have 1: "length (coge n xs) ≤ n"
by (rule cogeLongN)
have 2: "length (coge n xs) ≤ length xs"
by (rule cogeLongL)
show "length (coge n xs) ≤ min n (length xs)"
using 1 2 by (rule min.boundedI)
qed
lemma lengthCogeMayorMin:
"min n (length xs) ≤ length (coge n xs)"
proof (induct n arbitrary: xs)
fix xs:: "'a list"
show "min 0 (length xs) ≤ length (coge 0 xs)"
by simp
next
fix n and xs:: "'a list"
assume HI: "⋀xs::'a list. min n (length xs) ≤ length (coge n xs)"
show "min (Suc n) (length xs) ≤ length (coge (Suc n) xs)"
proof (cases xs)
assume "xs = []"
then show "min (Suc n) (length xs) ≤ length (coge (Suc n) xs)"
by simp
next
fix y :: "'a" and ys :: "'a list"
assume 1: "xs = y # ys"
have 2: "min n (length ys) ≤ length (coge n ys)"
using HI by this
show "min (Suc n) (length xs) ≤ length (coge (Suc n) xs)"
proof -
have "min (Suc n) (length xs) = min (Suc n) (length (y # ys))"
using 1 by (rule arg_cong)
also have "… = min (Suc n) (1 + length ys)"
by (simp only: list.size(4))
also have "… = 1 + min n (length ys)"
by (simp only: min_add_distrib_right)
also have "… ≤ 1 + length (coge n ys)"
using HI by simp
also have "… = length (y # coge n ys)"
by (simp only: list.size(4))
also have "… = length (coge (Suc n) (y # ys))"
by (simp only: coge.simps(3))
also have "… = length (coge (Suc n) xs)"
using 1 by (simp only: list.size(4))
finally show ?thesis
by this
qed
qed
qed
lemma lengthCogeMin_d2:
"length (coge n xs) = min n (length xs)"
proof -
have 1: "length (coge n xs) ≤ min n (length xs)"
by (rule lengthCogeMenorMin)
have "min n (length xs) ≤ length (coge n xs)"
by (rule lengthCogeMayorMin)
with 1 show ?thesis by (rule le_antisym)
qed
text ‹------------------------------------------------------------------
Ejercicio 13. Probar que
estaEn x (coge n xs) ⟹ estaEn x xs
---------------------------------------------------------------------›
― ‹Demostración en lenguaje natural:
Por inducción según el esquema coge.induct, se generan los tres
casos siguientes:
+ Caso base 1. ⋀n. estaEn x (coge n []) ⟶ estaEn x []
Sea n un número natural. Hay que probar,
estaEn x (coge n []) ⟶ estaEn x []. Para ello, se supone
1.1. estaEn x (coge n [])
y hay que probar estaEn x []
En efecto,
1.2. coge n [] = [] (por def. de coge)
==> 1.3 estaEn x [] (de 1.1 y 1.2)
==> 1.4. False (por def. de estaEn)
==> 1.5 estaEn x [] (de 1.4 y eliminación de False)
+ Caso base 2. ⋀y ys. estaEn x (coge 0 (y # ys)) ⟶ estaEn x (y # ys)
Sean y un elemento e ys una lista. Hay que probar
estaEn x (coge 0 (y # ys)) ⟶ estaEn x (y # ys). Para ello, se supone
2.1. estaEn x (coge 0 (y # ys)) y basta probar estaEn x (y # ys)
En efecto,
2.2. coge 0 (y # ys) = [] (por el lema coge0)
==> 2.3. estaEn x [] (de 2.1 y 2.3)
==> 2.4. False (por def. de estaEn)
==> 2.5 estaEn x (y # ys) (de 2.4. y eliminación de False)
+ Paso inductivo: ⋀n y ys. estaEn x (coge n ys) ⟶ estaEn x ys
⟹ estaEn x (coge (Suc n) (y # ys)) ⟶ estaEn x (y # ys)
Sean n un número natural, y un elemento e ys una lista. Se tiene por
HI: estaEn x (coge n ys) ⟶ estaEn x ys
Hay que probar: estaEn x (coge (Suc n) (y # ys)) ⟶ estaEn x (y # ys)
Para ello, se supone
3.1 estaEn x (coge (Suc n) (y # ys))
y basta probar "estaEn x (y # ys)"
En efecto,
3.2 estaEn x (y # coge n ys) (de 3.1, por def. de coge)
3.3. y = x ∨ estaEn x (coge n ys) (de 3.2, por def de estaEn)
De 3.3, la prueba se sivide en dos casos
+ Caso 1: y = x
En este caso, se verifica "estaEn y (y # ys)", por def. de estaEn
+ Caso 2: estaEn x (coge n ys)
En este caso, por HI se tiene "estaEn x ys". Y, por def. de estaEn
se verifica "estaEn x (y # ys)".
›
― ‹Demostración declarativa›
lemma
"estaEn x (coge n xs) ⟶ estaEn x xs"
proof (induct rule: coge.induct)
fix n
show "estaEn x (coge n []) ⟶ estaEn x []"
by simp
next
fix y ys
show "estaEn x (coge 0 (y # ys)) ⟶ estaEn x (y # ys)"
proof (rule impI)
assume "estaEn x (coge 0 (y # ys))"
then have "estaEn x []"
by simp
then show "estaEn x (y # ys)"
by simp
qed
next
fix n and y :: "'a" and ys :: "'a list"
assume HI: "estaEn x (coge n ys) ⟶ estaEn x ys"
show "estaEn x (coge (Suc n) (y # ys)) ⟶ estaEn x (y # ys)"
proof (rule impI)
assume "estaEn x (coge (Suc n) (y # ys))"
then have "estaEn x (y# coge n ys)"
by simp
then have "((y = x) ∨ (estaEn x (coge n ys)))"
by (simp only: estaEn.simps(2))
then show "estaEn x (y # ys)"
proof (rule disjE)
assume "y = x"
then have "((y = x) ∨ (estaEn x ys))"
by (rule disjI1)
then show "estaEn x (y # ys)"
by (simp only:estaEn.simps(2))
next
assume "estaEn x (coge n ys)"
with HI have "estaEn x ys"
by (rule mp)
then have "((y = x) ∨ (estaEn x ys))"
by (rule disjI2)
then show "estaEn x (y # ys)"
by (simp only: estaEn.simps(2))
qed
qed
qed
― ‹Demostración declarativa detallada:›
lemma estaEnCoge_d:
"estaEn x (coge n xs) ⟶ estaEn x xs"
proof (induct rule: coge.induct)
fix n
show "estaEn x (coge n []) ⟶ estaEn x []"
proof (rule impI)
assume "estaEn x (coge n [])"
then have "estaEn x []"
by (simp only: coge.simps(1))
then have False
by (simp only: estaEn.simps(1))
then show "estaEn x []"
by (rule FalseE)
qed
next
fix y ys
show "estaEn x (coge 0 (y # ys)) ⟶ estaEn x (y # ys)"
proof (rule impI)
assume "estaEn x (coge 0 (y # ys))"
then have "estaEn x []"
by (simp only: coge.simps(2))
then have False
by (simp only: estaEn.simps(1))
then show "estaEn x (y # ys)"
by (rule FalseE)
qed
next
fix n and y :: "'a" and ys :: "'a list"
assume HI: "estaEn x (coge n ys) ⟶ estaEn x ys"
show "estaEn x (coge (Suc n) (y # ys)) ⟶ estaEn x (y # ys)"
proof (rule impI)
assume "estaEn x (coge (Suc n) (y # ys))"
then have "estaEn x (y # coge n ys)"
by (simp only: coge.simps(3))
then have "y = x ∨ estaEn x (coge n ys)"
by (simp only: estaEn.simps(2))
then show "estaEn x (y # ys)"
proof (rule disjE)
assume "y = x"
then have "y = x ∨ estaEn x ys"
by (rule disjI1)
then show "estaEn x (y # ys)"
by (simp only: estaEn.simps(2))
next
assume "estaEn x (coge n ys)"
with HI have "estaEn x ys"
by (rule mp)
then have "y = x ∨ estaEn x ys"
by (rule disjI2)
then show "estaEn x (y # ys)"
by (simp only: estaEn.simps(2))
qed
qed
qed
lemma estaEnCoge_de:
assumes "estaEn x (coge n xs)"
shows "estaEn x xs"
proof-
have "estaEn x (coge n xs) ⟶ estaEn x xs"
by (rule estaEnCoge_d)
then show "estaEn x xs" using assms by (rule mp)
qed
― ‹Demostración aplicativa detallada›
lemma estaEnCoge:
"estaEn x (coge n xs) ⟹ estaEn x xs"
apply (induct rule: coge.induct)
apply (simp only: coge.simps(1))
apply (simp only: coge.simps(2) estaEn.simps(1))
apply (simp only: coge.simps(3))
apply (simp only: estaEn.simps(2))
apply (erule disjE)
apply (rule disjI1, assumption)
apply (rule disjI2, assumption)
done
text ‹------------------------------------------------------------------
Ejercicio 14. Probar que
sublista (coge n xs) xs
---------------------------------------------------------------------›
― ‹Demostración en lenguaje natural:
Por inducción según el esquema coge.induct, se generan los tres casos
siguientes:
+ Caso base 1. ⋀n. sublista (coge n []) []
Sea n un número natural.
1.1. coge n [] = [] (por def. de coge)
1.2. sublista [] [] (por def. de sublista)
1.3. sublista (coge n []) [] (de 1.1 y 1.2)
+ Caso base 2. ⋀x xs. sublista (coge 0 (x # xs)) (x # xs)
Sean x un elemento y xs una lista cualquiera
2.1. coge 0 (x # xs) = []
(por coge0)
2.2. sublista (coge 0 (x # xs)) (x # xs)
(de 2.1,por def. de sublista)
+ Paso inductivo. ⋀n x xs. sublista (coge n xs) xs
⟹ sublista (coge (Suc n) (x # xs)) (x # xs)
Sean n un número natural, x un elemento y xs una lista. Se verifica por
HI: sublista (coge n xs) xs.
Y hay que probar: sublista (coge (Suc n) (x # xs)) (x # xs)
En efecto,
3.1. coge (Suc n) (x # xs) = x # coge n xs
(por def. de coge)
3.2. estaEn x (x # xs)
(por estaEn1)
3.3. sublista (coge n xs) (x # xs)
(por HI y el lema sublistaMono)
3.4. sublista (x # coge n xs) (x # xs)
(de 3.2, 3.3, por def. sublista)
3.5. sublista (coge (Suc n) (x # xs)) (x # xs)
(de 3.1 y 3.4)
›
― ‹Demostración declarativa›
lemma "sublista (coge n xs) xs"
proof (induct rule: coge.induct)
fix n
show "sublista (coge n []) []"
by (simp only: coge.simps(1) sublista.simps(1))
next
fix y :: "'a" and ys :: "'a list"
show "sublista (coge 0 (y # ys)) (y # ys)"
by simp
next
fix n and x::"'a" and xs::"'a list"
assume HI: "sublista (coge n xs) xs"
then have "sublista (x # coge n xs) (x # xs)"
by (simp add: sublistaMono)
then show "sublista (coge (Suc n) (x # xs)) (x # xs)"
by simp
qed
― ‹Demostración declarativa detallada:›
lemma sublistaCoge_d: "sublista (coge n xs) xs"
proof (induct rule: coge.induct)
fix n
show "sublista (coge n []) []"
by (simp only: coge.simps(1) sublista.simps(1))
next
fix y :: "'a" and ys :: "'a list"
have "coge 0 (y#ys) = []"
by (rule coge0)
then show "sublista (coge 0 (y # ys)) (y # ys)"
by (simp only: sublista.simps(1))
next
fix n and x :: "'a" and xs :: "'a list"
assume HI: "sublista (coge n xs) xs"
then have "sublista (coge n xs) (x # xs)"
by (simp only: sublistaMono)
then have "(estaEn x (x # xs) ∧ sublista (coge n xs) (x # xs))"
by (simp only: estaEn1)
then have "sublista (x # coge n xs) (x # xs)"
by (simp only: sublista.simps(2))
then show "sublista (coge (Suc n) (x # xs)) (x # xs)"
by (simp only: coge.simps(3))
qed
― ‹Demostración aplicativa detallada›
lemma sublistaCoge: "sublista (coge n xs) xs"
apply (induct rule: coge.induct)
apply (simp only: coge.simps(1) sublista.simps(1))
apply (simp only: coge.simps(2) sublista.simps(1))
apply (simp only: coge.simps(3))
apply (simp only: sublista.simps(2))
apply (rule conjI)
apply (rule estaEn1)
apply (simp only: sublistaMono)
done
end