Tema 6a: Verificación de la ordenación por inserción
De Razonamiento automático (2018-19)
<source lang="isabelle"> chapter {* T6a: Verificación de la ordenación por inserción *}
theory T6a_Verificacion_de_la_ordenacion_por_insercion imports Main begin
text {*
En este de tema se define el algoritmo de ordenación de listas por inserción y se demuestra que es correcto. *}
text {*
--------------------------------------------------------------------- Ejercicio 1. Definir la función inserta :: int ⇒ int list ⇒ int list tal que (inserta a xs) es la lista obtenida insertando a delante del primer elemento de xs que es mayor o igual que a. Por ejemplo, inserta 3 [2,5,1,7] = [2,3,5,1,7] ------------------------------------------------------------------ *}
fun inserta :: "int ⇒ int list ⇒ int list" where
"inserta a [] = [a]"
| "inserta a (x#xs) = (if a ≤ x
then a # x # xs else x # inserta a xs)"
value "inserta 3 [2,5,1,7] = [2,3,5,1,7]"
text {*
--------------------------------------------------------------------- Ejercicio 2. Definir la función ordena :: int list ⇒ int list tal que (ordena xs) es la lista obtenida ordenando xs por inserción. Por ejemplo, ordena [3,2,5,3] = [2,3,3,5] ------------------------------------------------------------------ *}
fun ordena :: "int list ⇒ int list" where
"ordena [] = []"
| "ordena (x#xs) = inserta x (ordena xs)"
value "ordena [3,2,5,3] = [2,3,3,5]"
text {*
--------------------------------------------------------------------- Ejercicio 3. Definir la función menor :: int ⇒ int list ⇒ bool tal que (menor a xs) se verifica si a es menor o igual que todos los elementos de xs.Por ejemplo, menor 2 [3,2,5] = True menor 2 [3,0,5] = False ------------------------------------------------------------------ *}
fun menor :: "int ⇒ int list ⇒ bool" where
"menor a [] = True"
| "menor a (x#xs) = (a ≤ x ∧ menor a xs)"
value "menor 2 [3,2,5] = True" value "menor 2 [3,0,5] = False"
text {*
--------------------------------------------------------------------- Ejercicio 4. Definir la función ordenada :: int list ⇒ bool tal que (ordenada xs) se verifica si xs es una lista ordenada de manera creciente. Por ejemplo, ordenada [2,3,3,5] = True ordenada [2,4,3,5] = False ------------------------------------------------------------------ *}
fun ordenada :: "int list ⇒ bool" where
"ordenada [] = True"
| "ordenada (x#xs) = (menor x xs & ordenada xs)"
value "ordenada [2,3,3,5] = True" value "ordenada [2,4,3,5] = False"
text {*
--------------------------------------------------------------------- Ejercicio 5. Demostrar que si y es una cota inferior de zs y x ≤ y, entonces x es una cota inferior de zs. ------------------------------------------------------------------ *}
― ‹La demostración automática es› lemma menor_menor:
assumes "x ≤ y" shows "menor y zs ⟶ menor x zs"
using assms by (induct zs) auto
― ‹La demostración estructurada es› lemma menor_menor_2:
assumes "x ≤ y" shows "menor y zs ⟶ menor x zs"
proof (induct zs)
show "menor y [] ⟶ menor x []" by simp
next
fix z zs assume HI: "menor y zs ⟶ menor x zs" show "menor y (z # zs) ⟶ menor x (z # zs)" proof assume sup: "menor y (z # zs)" show "menor x (z # zs)" proof (simp only: menor.simps(2)) show "x ≤ z ∧ menor x zs" proof have "x ≤ y" using assms . also have "y ≤ z" using sup by simp finally show "x ≤ z" . next have "menor y zs" using sup by simp with HI show "menor x zs" by simp qed qed qed
qed
text {*
--------------------------------------------------------------------- Ejercicio 6. Demostrar el siguiente teorema de corrección: x es una cota inferior de la lista obtenida insertando y en zs syss x ≤ y y x es una cota inferior de zs. ------------------------------------------------------------------ *}
― ‹La demostración automática es› lemma menor_inserta:
"menor x (inserta y zs) = (x ≤ y ∧ menor x zs)"
by (induct zs) auto
― ‹La demostración estructurada es› lemma menor_inserta_2:
"menor x (inserta y zs) = (x ≤ y ∧ menor x zs)"
proof (induct zs)
show "menor x (inserta y []) = (x ≤ y ∧ menor x [])" by simp
next
fix z zs assume HI: "menor x (inserta y zs) = (x ≤ y ∧ menor x zs)" show "menor x (inserta y (z#zs)) = (x ≤ y ∧ menor x (z#zs))" proof (cases "y ≤ z") assume "y ≤ z" hence "menor x (inserta y (z#zs)) = menor x (y#z#zs)" by simp also have "… = (x ≤ y ∧ menor x (z#zs))" by simp finally show ?thesis by simp next assume "¬(y ≤ z)" hence "menor x (inserta y (z#zs)) = menor x (z # inserta y zs)" by simp also have "… = (x ≤ z ∧ menor x (inserta y zs))" by simp also have "… = (x ≤ z ∧ x ≤ y ∧ menor x zs)" using HI by simp also have "… = (x ≤ y ∧ menor x (z#zs))" by auto finally show ?thesis by simp qed
qed
text {*
--------------------------------------------------------------------- Ejercicio 6. Demostrar que al insertar un elemento la lista obtenida está ordenada syss lo estaba la original. ------------------------------------------------------------------ *}
― ‹La demostración automática es› lemma ordenada_inserta:
"ordenada (inserta a xs) = ordenada xs"
by (induct xs) (auto simp add: menor_menor menor_inserta)
― ‹La demostración estructurada es› lemma ordenada_inserta_2:
"ordenada (inserta a xs) = ordenada xs"
proof (induct xs)
show "ordenada (inserta a []) = ordenada []" by simp
next
fix x xs assume HI: "ordenada (inserta a xs) = ordenada xs" show "ordenada (inserta a (x # xs)) = ordenada (x # xs)" proof (cases "a ≤ x") assume "a ≤ x" hence "ordenada (inserta a (x # xs)) = ordenada (a # x # xs)" by simp also have "… = (menor a (x#xs) ∧ ordenada (x # xs))" by simp also have "… = ordenada (x # xs)" using `a ≤ x` by (auto simp add: menor_menor) finally show "ordenada (inserta a (x # xs)) = ordenada (x # xs)" by simp next assume "¬(a ≤ x)" hence "ordenada (inserta a (x # xs)) = ordenada (x # inserta a xs)" by simp also have "… = (menor x (inserta a xs) ∧ ordenada (inserta a xs))" by simp also have "… = (menor x (inserta a xs) ∧ ordenada xs)" using HI by simp also have "… = (menor x xs ∧ ordenada xs)" using `¬(a ≤ x)` by (simp add: menor_inserta) also have "… = ordenada (x # xs)" by simp finally show "ordenada (inserta a (x # xs)) = ordenada (x # xs)" by simp qed
qed
text {*
--------------------------------------------------------------------- Ejercicio 7. Demostrar que, para toda lista xs, (ordena xs) está ordenada. ------------------------------------------------------------------ *}
― ‹La demostración automática es› theorem ordenada_ordena:
"ordenada (ordena xs)"
by (induct xs) (auto simp add: ordenada_inserta)
― ‹La demostración estructurada es› theorem ordenada_ordena_2:
"ordenada (ordena xs)"
proof (induct xs)
show "ordenada (ordena [])" by simp
next
fix x xs assume "ordenada (ordena xs)" then have "ordenada (inserta x (ordena xs))" by (simp add: ordenada_inserta) then show "ordenada (ordena (x # xs))" by simp
qed
text {*
--------------------------------------------------------------------- Nota. El teorema anterior no garantiza que ordena sea correcta, ya que puede que (ordena xs) no tenga los mismos elementos que xs. Por ejemplo, si se define (ordena xs) como [] se tiene que (ordena xs) está ordenada pero no es una ordenación de xs.
Para garantizarlo, definimos la función cuenta. ------------------------------------------------------------------ *}
text {*
--------------------------------------------------------------------- Ejercicio 8. Definir la función cuenta :: int list ⇒ int ⇒ nat tal que (cuenta xs y) es el número de veces que aparece el elemento y en la lista xs. Por ejemplo, cuenta [1,3,4,3,5] 3 = 2 ------------------------------------------------------------------ *}
fun cuenta :: "int list ⇒ int ⇒ nat" where
"cuenta [] y = 0"
| "cuenta (x#xs) y = (if x=y
then Suc (cuenta xs y) else cuenta xs y)"
value "cuenta [1,3,4,3,5] 3 = 2"
text {*
--------------------------------------------------------------------- Ejercicio 9. Demostrar que el número de veces que aparece y en (inserta x xs) es * uno más el número de veces que aparece en xs, si y = x; * el número de veces que aparece en xs, si y ≠ x; ------------------------------------------------------------------ *}
― ‹La demostración automática es› lemma cuenta_inserta:
"cuenta (inserta x xs) y = (if x=y then Suc (cuenta xs y) else cuenta xs y)"
by (induct xs) auto
text {*
--------------------------------------------------------------------- Ejercicio 10. Demostrar que el número de veces que aparece y en (ordena xs) es el número de veces que aparece en xs. ------------------------------------------------------------------ *}
― ‹La demostración automática es› theorem cuenta_ordena:
"cuenta (ordena xs) y = cuenta xs y"
by (induct xs) (auto simp add: cuenta_inserta)
― ‹La demostración estructurada es› theorem cuenta_ordena_2:
"cuenta (ordena xs) y = cuenta xs y"
proof (induct xs)
show "cuenta (ordena []) y = cuenta [] y" by simp
next
fix x xs assume HI: "cuenta (ordena xs) y = cuenta xs y" show "cuenta (ordena (x # xs)) y = cuenta (x # xs) y" proof (cases "x = y") assume "x = y" have "cuenta (ordena (x # xs)) y = cuenta (inserta x (ordena xs)) y" by simp also have "… = Suc (cuenta (ordena xs) y)" using `x = y` by (simp add: cuenta_inserta) also have "… = Suc (cuenta xs y)" using HI by simp also have "… = cuenta (x # xs) y" using `x = y` by simp finally show "cuenta (ordena (x # xs)) y = cuenta (x # xs) y" by simp next assume "x ≠ y" have "cuenta (ordena (x # xs)) y = cuenta (inserta x (ordena xs)) y" by simp also have "… = cuenta (ordena xs) y" using `x ≠ y` by (simp add: cuenta_inserta) also have "… = cuenta xs y" using HI by simp also have "… = cuenta (x # xs) y" using `x ≠ y` by simp finally show "cuenta (ordena (x # xs)) y = cuenta (x # xs) y" by simp qed
qed
end </end>