Acciones

R11

De Razonamiento automático (2014-15)

header {* R11: Plegados de listas y de árboles *}

theory R11
imports Main 
begin 

section {* Nuevas funciones sobre listas *}

text {* 
  Nota. En esta relación se usará la función suma tal que (suma xs) es
  la suma de los elementos de xs, definida por
*}

fun suma :: "nat list ⇒ nat" where
  "suma xs = undefined"

text {* 
  Las funciones de plegado, foldr y foldl, están definidas en la teoría
  List.thy por
       foldr :: "('a ⇒ 'b ⇒ 'b) ⇒ 'a list ⇒ 'b ⇒ 'b"
       foldr f []       = id
       foldr f (x # xs) = f x ∘ foldr f xs

       foldl :: "('b ⇒ 'a ⇒ 'b) ⇒ 'b ⇒ 'a list ⇒ 'b"
       foldl f a []       = a
       foldl f a (x # xs) = foldl f (f a x) xs"

  Por ejemplo,
     foldr (op +) [a,b,c] d        = a + (b + (c + d))
     foldl (op +) d [a,b,c]        = ((d + a) + b) + c
     foldr (op -) [9,4,2] (0::int) = 7
     foldl (op -) (0::int) [9,4,2] = -15
*}

value "foldr (op +) [a,b,c] d"        -- "= a + (b + (c + d))"
value "foldl (op +) d [a,b,c]"        -- "= ((d + a) + b) + c"
value "foldr (op -) [9,4,2] (0::int)" -- "= 7"
value "foldl (op -) (0::int) [9,4,2]" -- "= -15"

text {* 
  --------------------------------------------------------------------- 
  Ejercicio 1. Demostrar que
     suma xs = foldr (op +) xs 0
  --------------------------------------------------------------------- 
*}

lemma suma_foldr: "suma xs = foldr (op +) xs 0"
oops

text {* 
  --------------------------------------------------------------------- 
  Ejercicio 2. Demostrar que
     length xs = foldr (λ x res. 1 + res) xs 0
  --------------------------------------------------------------------- 
*}

lemma length_foldr: "length xs = foldr (λ x res. 1 + res) xs 0"
oops

text {* 
  --------------------------------------------------------------------- 
  Ejercicio 3. La aplicación repetida de foldr y map tiene el
  inconveniente de que la lista se recorre varias veces. Sin embargo, es
  suficiente recorrerla una vez como se muestra en el siguiente ejemplo,  
     suma (map (λx. x + 3) xs) = foldr h xs b
  Determinar los valores de h y b para que se verifique la igualdad
  anterior y demostrarla.
  --------------------------------------------------------------------- 
*}


text {* 
  --------------------------------------------------------------------- 
  Ejercicio 4. Generalizar el resultado anterior; es decir determinar
  los valores de h y b para que se verifique la igualdad 
     foldr g (map f xs) a = foldr h xs b
  y demostrarla.
  --------------------------------------------------------------------- 
*}

text {* 
  --------------------------------------------------------------------- 
  Ejercicio 5. La siguiente función invierte una lista en tiempo lineal
     fun inversa_ac :: "['a list, 'a list] ⇒ 'a list" where
       "inversa_ac [] ys = ys"
     | "inversa_ac (x#xs) ys = (inversa_ac xs (x#ys))"

     definition inversa_ac :: "'a list ⇒ 'a list" where
       "inversa_ac xs ≡ inversa_ac_aux xs []"
  Por ejemplo, 
     inversa_ac [a,d,b,c] = [c, b, d, a]
  Demostrar que inversa_ac se puede definir unsando foldl.
  --------------------------------------------------------------------- 
*}

fun inversa_ac_aux :: "['a list, 'a list] ⇒ 'a list" where
  "inversa_ac_aux [] ys = ys"
| "inversa_ac_aux (x#xs) ys = (inversa_ac_aux xs (x#ys))"

definition inversa_ac :: "'a list ⇒ 'a list" where
  "inversa_ac xs ≡ inversa_ac_aux xs []"

value "inversa_ac [a,d,b,c]" -- "= [c, b, d, a]"

lemma inversa_ac_aux_foldl: 
  "inversa_ac_aux xs a = foldl undefined a xs"
oops

text {* 
  --------------------------------------------------------------------- 
  Ejercicio 6. Demostrar la siguiente propiedad distributiva de la suma
  sobre la concatenación:
     suma (xs @ ys) = suma xs + suma ys
  --------------------------------------------------------------------- 
*}

lemma suma_append [simp]: 
  "suma (xs @ ys) = suma xs + suma ys"
oops

text {* 
  --------------------------------------------------------------------- 
  Ejercicio 7. Demostrar una propiedad similar para foldr
     foldr f (xs @ ys) a = f (foldr f xs a) (foldr f ys a)
  En este caso, hay que restringir el resultado teniendo en cuenta
  propiedades algebraicas de f y a.
  --------------------------------------------------------------------- 
*}

text {* 
  --------------------------------------------------------------------- 
  Ejercicio 8. Definir, usando foldr, la función
     prod :: "nat list ⇒ nat"
  tal que (prod xs) es el producto de los elementos de xs. Por ejemplo,
  --------------------------------------------------------------------- 
*}

definition prod :: "nat list ⇒ nat" where
  "prod xs ≡ undefined"

value "prod [2::nat,3,5]" -- "= 30"

text {* 
  --------------------------------------------------------------------- 
  Ejercicio 9. Demostrar directamente (es decir, sin inducción) que
     prod (xs @ ys) = prod xs * prod ys
  --------------------------------------------------------------------- 
*}

lemma "prod (xs @ ys) = prod xs * prod ys"
oops

section {* Functiones sobre árboles *}

text {*  
  --------------------------------------------------------------------- 
  Ejercicio 10. Definir el tipo de datos arbol para representar los
  árboles binarios que tiene información sólo en los nodos. Por ejemplo,
  el árbol 
          e
         / \
        /   \
       c     g
      / \   / \
     ·   · ·   · 
  se representa por "N (N H c H) e (N H g H)"
  --------------------------------------------------------------------- 
*}

datatype 'a arbol = H | N "'a arbol" "'a" "'a arbol"

value "N (N H c H) e (N H g H)"

text {*  
  --------------------------------------------------------------------- 
  Ejercicio 11. Definir la función 
     preOrden :: "'a arbol ⇒ 'a list"
  tal que (preOrden a) es el recorrido pre orden del árbol a. Por
  ejemplo, 
     preOrden (N (N H c H) e (N H g H))
     = [e,c,g]
  --------------------------------------------------------------------- 
*}

fun preOrden :: "'a arbol ⇒ 'a list" where
  "preOrden t = undefined"

value "preOrden (N (N H c H) e (N H g H))"
-- "= [e,c,g]"

text {*  
  --------------------------------------------------------------------- 
  Ejercicio 12. Definir la función 
     postOrden :: "'a arbol ⇒ 'a list"
  tal que (postOrden a) es el recorrido post orden del árbol a. Por
  ejemplo, 
     postOrden (N (N H c H) e (N H g H))
     = [c,g,e]
  --------------------------------------------------------------------- 
*}

fun postOrden :: "'a arbol ⇒ 'a list" where
  "postOrden t = undefined"

value "postOrden (N (N H c H) e (N H g H))"
-- "= [c,g,e]"

text {*  
  --------------------------------------------------------------------- 
  Ejercicio 13. Definir, usando un acumulador, la función 
     postOrdenA :: "'a arbol ⇒ 'a list"
  tal que (postOrdenA a) es el recorrido post orden del árbol a. Por
  ejemplo, 
     postOrdenA (N (N H c H) e (N H g H))
     = [c,g,e]
  --------------------------------------------------------------------- 
*}

fun postOrdenAaux :: "['a arbol, 'a list] ⇒ 'a list" where
  "postOrdenAaux t = undefined"

definition postOrdenA :: "'a arbol ⇒ 'a list" where
  "postOrdenA a ≡ undefined"

value "postOrdenA (N (N H c H) e (N H g H))"
-- "= [c,g,e]"

text {*  
  --------------------------------------------------------------------- 
  Ejercicio 14. Demostrar que
     postOrdenAaux a xs = (postOrden a) @ xs
  --------------------------------------------------------------------- 
*}

lemma "postOrdenAaux a xs = (postOrden a) @ xs"
oops

text {*  
  --------------------------------------------------------------------- 
  Ejercicio 15. Definir la función
     foldl_arbol :: "('b => 'a => 'b) ⇒ 'b ⇒ 'a arbol ⇒ 'b" where
  tal que (foldl_arbol f b a) es el plegado izquierdo del árbol a con la
  operación f y elemento inicial b.
  --------------------------------------------------------------------- 
*}

fun foldl_arbol :: "('b => 'a => 'b) ⇒ 'b ⇒ 'a arbol ⇒ 'b" where
  "foldl_arbol f b t = undefined"

text {*  
  --------------------------------------------------------------------- 
  Ejercicio 16. Demostrar que
     postOrdenAaux t a = foldl_arbol (λ xs x. Cons x xs) a t
  --------------------------------------------------------------------- 
*}

lemma "postOrdenAaux t a = foldl_arbol (λ xs x. Cons x xs) a t"
oops

text {*  
  --------------------------------------------------------------------- 
  Ejercicio 17. Definir la función
     suma_arbol :: "nat arbol ⇒ nat" 
  tal que (suma_arbol a) es la suma de los elementos del árbol de
  números naturales a.
  --------------------------------------------------------------------- 
*}

fun suma_arbol :: "nat arbol ⇒ nat" where
  "suma_arbol t = undefined"

text {*  
  --------------------------------------------------------------------- 
  Ejercicio 18. Demostrar que
     suma_arbol a = suma (preOrden a)"
  --------------------------------------------------------------------- 
*}

lemma "suma_arbol a = suma (preOrden a)"
oops

end