Acciones

Diferencia entre revisiones de «Desarrollo de teorías formalizadas con Isabelle/HOL»

De Lógica matemática y fundamentos (2018-19)

m
 
Línea 1: Línea 1:
 
<source lang="isabelle">
 
<source lang="isabelle">
chapter {* Desarrollo de teorías formalizadas *}
+
chapter ‹Desarrollo de teorías formalizadas›
  
 
theory T11_Desarrollo_de_teorias_formalizadas
 
theory T11_Desarrollo_de_teorias_formalizadas
Línea 6: Línea 6:
 
begin
 
begin
  
section {* Desarrollo de la teoría de grupos*}
+
section ‹Desarrollo de la teoría de grupos›
  
text {*
+
text ‹El objetivo de este tema es mostrar cómo se puede trabajar en
  El objetivo de este tema es mostrar cómo se puede trabajar en
+
   estructuras algebraicas por medio de locales.  
   estructuras algebraicas por medio de locales. Se usará como ejemplo la
 
  teoría de grupos. *}
 
  
text {*
+
  Se usará como ejemplo la teoría de grupos.›
  Ejemplo 1. Un grupo es una estructura (G,·,𝟭,^) tal que G es un
+
 
   conjunto, · es una operación binaria en G, 𝟭 es un elemento de G y ^
+
text ‹Ejemplo 1. Un grupo es una estructura (G,·,𝟭,^) tal que  
   es una función de G en G tales que se cumplen las siguientes
+
  * G es un conjunto,
  propiedades:
+
   * · es una operación binaria en G,  
 +
  * 𝟭 es un elemento de G y  
 +
   * ^ es una función de G en G  
 +
  tales que se cumplen las siguientes propiedades:
 
   * asociativa: ∀x y z. x ⋅ (y ⋅ z) = (x ⋅ y) ⋅ z
 
   * asociativa: ∀x y z. x ⋅ (y ⋅ z) = (x ⋅ y) ⋅ z
 
   * neutro por la izquierda: ∀x. 𝟭 ⋅ x = x
 
   * neutro por la izquierda: ∀x. 𝟭 ⋅ x = x
 
   * inverso por la izquierda: ∀x. x^ ⋅ x = 𝟭  
 
   * inverso por la izquierda: ∀x. x^ ⋅ x = 𝟭  
   Definir el entorno axiomático de los grupos. *}
+
 
 +
   Definir el entorno axiomático de los grupos.
  
 
locale grupo =  
 
locale grupo =  
Línea 31: Línea 33:
 
       and inverso_i:  "x^ ⋅ x = 𝟭"
 
       and inverso_i:  "x^ ⋅ x = 𝟭"
  
text {*
+
text ‹Notas sobre notación:
  Notas sobre notación:
 
 
   * El producto es ⋅ y se escribe con \ cdot (sin espacio entre ellos).  
 
   * El producto es ⋅ y se escribe con \ cdot (sin espacio entre ellos).  
   * El neutro es 𝟭 y se escribe con \ y <one> (sin espacio entre ellos).
+
   * El neutro es 𝟭 y se escribe con \ y one (sin espacio entre ellos).
   * El inverso de x es x^ y se escribe con pulsando 2 veces en ^. *}
+
   * El inverso de x es x^ y se escribe pulsando 2 veces en ^.
 +
 
 +
text ‹A continuación se crea un contexto en el que se supone la
 +
  notación y axiomas de grupos.
  
text {*
+
   En el contexto se demuestran propiedades de los grupos.
   A continuación se crea un contexto en el que se supone la notación y
 
  axiomas de grupos. En el contexto se demuestran propiedades de los
 
  grupos. *}
 
  
 
context grupo
 
context grupo
 
begin
 
begin
  
text {*
+
text ‹Ejemplo 2. En los grupos, x^ también es el inverso de x por la
  Ejemplo 2. En los grupos, x^ también es el inverso de x por la
 
 
   derecha; es decir  
 
   derecha; es decir  
     x ⋅ x^ = 𝟭  *}
+
     x ⋅ x^ = 𝟭›
  
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
 
lemma "x ⋅ x^ = 𝟭"
 
lemma "x ⋅ x^ = 𝟭"
 +
  (* sledgehammer *)
 
   by (metis asociativa inverso_i neutro_i)
 
   by (metis asociativa inverso_i neutro_i)
  
Línea 58: Línea 59:
 
   "x ⋅ x^ = 𝟭"
 
   "x ⋅ x^ = 𝟭"
 
proof -
 
proof -
   have "x ⋅ x^ = 𝟭 ⋅ (x ⋅ x^)" by (simp only: neutro_i)
+
   have "x ⋅ x^ = 𝟭 ⋅ (x ⋅ x^)"  
   also have "… = (𝟭 ⋅ x) ⋅ x^" by (simp only: asociativa)
+
    by (simp only: neutro_i)
   also have "… = (((x^)^ ⋅ x^) ⋅ x) ⋅ x^" by (simp only: inverso_i)
+
   also have "… = (𝟭 ⋅ x) ⋅ x^"  
   also have "… = ((x^)^ ⋅ (x^ ⋅ x)) ⋅ x^" by (simp only: asociativa)
+
    by (simp only: asociativa)
   also have "… = ((x^)^ ⋅ 𝟭) ⋅ x^" by (simp only: inverso_i)
+
   also have "… = (((x^)^ ⋅ x^) ⋅ x) ⋅ x^"  
   also have "… = (x^)^ ⋅ (𝟭 ⋅ x^)" by (simp only: asociativa)
+
    by (simp only: inverso_i)
   also have "… = (x^)^ ⋅ x^" by (simp only: neutro_i)
+
   also have "… = ((x^)^ ⋅ (x^ ⋅ x)) ⋅ x^"  
   also have "… = 𝟭" by (simp only: inverso_i)
+
    by (simp only: asociativa)
   finally show ?thesis .
+
   also have "… = ((x^)^ ⋅ 𝟭) ⋅ x^"  
 +
    by (simp only: inverso_i)
 +
   also have "… = (x^)^ ⋅ (𝟭 ⋅ x^)"  
 +
    by (simp only: asociativa)
 +
   also have "… = (x^)^ ⋅ x^"  
 +
    by (simp only: neutro_i)
 +
   also have "… = 𝟭"  
 +
    by (simp only: inverso_i)
 +
   finally show ?thesis  
 +
    by this
 
qed
 
qed
  
text {*
+
text ‹Ejemplo 2. En los grupos, 𝟭 también es el neutro por la derecha;  
  Ejemplo 2. En los grupos, 𝟭 también es el neutro por la derecha; es decir  
+
  es decir  
     x ⋅ 𝟭 = x  *}
+
     x ⋅ 𝟭 = x›
  
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
Línea 81: Línea 91:
 
   "x ⋅ 𝟭 = x"
 
   "x ⋅ 𝟭 = x"
 
proof -
 
proof -
   have "x ⋅ 𝟭 = x ⋅ (x^ ⋅ x)" by (simp only: inverso_i)
+
   have "x ⋅ 𝟭 = x ⋅ (x^ ⋅ x)"  
   also have "… = (x ⋅ x^) ⋅ x" by (simp only: asociativa)
+
    by (simp only: inverso_i)
   also have "… = 𝟭 ⋅ x" by (simp only: inverso_d)
+
   also have "… = (x ⋅ x^) ⋅ x"
   also have "… = x" by (simp only: neutro_i)
+
    by (simp only: asociativa)
   finally show "x ⋅ 𝟭 = x" .
+
   also have "… = 𝟭 ⋅ x"  
qed
+
    by (simp only: inverso_d)
 +
   also have "… = x"  
 +
    by (simp only: neutro_i)
 +
   finally show "x ⋅ 𝟭 = x"  
 +
    by this
 +
qed  
  
text {*
+
text ‹Ejemplo 3. En los grupos, se tiene la propiedad cancelativa por la
  Ejemplo 3. En los grupos, se tiene la propiedad cancelativa por la
 
 
   izquierda; es decir,
 
   izquierda; es decir,
     x ⋅ y = x ⋅ z syss y = z  *}
+
     x ⋅ y = x ⋅ z syss y = z›
  
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
Línea 102: Línea 116:
 
proof
 
proof
 
   assume "x ⋅ y = x ⋅ z"
 
   assume "x ⋅ y = x ⋅ z"
   hence "x^ ⋅ (x ⋅ y) = x^ ⋅ (x ⋅ z)" by simp
+
   then have "x^ ⋅ (x ⋅ y) = x^ ⋅ (x ⋅ z)"
   hence "(x^ ⋅ x) ⋅ y = (x^ ⋅ x) ⋅ z" by (simp only: asociativa)
+
    by (simp only: arg_cong [of "x ⋅ y" "x ⋅ z"])
   hence "𝟭 ⋅ y = 𝟭 ⋅ z" by (simp only: inverso_i)
+
   then have "(x^ ⋅ x) ⋅ y = (x^ ⋅ x) ⋅ z"  
   thus "y = z" by (simp only: neutro_i)
+
    by (simp only: asociativa)
 +
   then have "𝟭 ⋅ y = 𝟭 ⋅ z"  
 +
    by (simp only: inverso_i)
 +
   thus "y = z"  
 +
    by (simp only: neutro_i)
 
next
 
next
 
   assume "y = z"
 
   assume "y = z"
   then show "x ⋅ y = x ⋅ z" by simp
+
   then show "x ⋅ y = x ⋅ z"  
 +
    by (simp only: arg_cong [of "y" "z"])
 
qed
 
qed
  
text {*
+
text ‹Ejemplo 4. En los grupos, el elemento neutro por la izquierda es
  Ejemplo 4. En los grupos, el elemento neutro por la izquierda es
 
 
   único; es decir, si e es un elemento tal que para todo x se tiene que  
 
   único; es decir, si e es un elemento tal que para todo x se tiene que  
   e ⋅ x = x, entonces e = 𝟭. *}
+
   e ⋅ x = x, entonces e = 𝟭.
  
 
― ‹La demostración automática es (obtenida con Sledgehammer) es›
 
― ‹La demostración automática es (obtenida con Sledgehammer) es›
Línea 128: Línea 146:
 
   shows "𝟭 = e"
 
   shows "𝟭 = e"
 
proof -
 
proof -
   have "𝟭 = x ⋅ x^" by (simp only: inverso_d)
+
   have "𝟭 = x ⋅ x^"  
   also have "... = (e ⋅ x) ⋅ x^" using assms by simp
+
    by (simp only: inverso_d)
   also have "... = e ⋅ (x ⋅ x^)" by (simp only: asociativa)
+
   also have "... = (e ⋅ x) ⋅ x^"  
   also have "... = e ⋅ 𝟭" by (simp only: inverso_d)
+
    using assms [THEN sym]
   also have "... = e" by (simp only: neutro_d)
+
    by (rule arg_cong [of "x" "e ⋅ x" "λy. y ⋅ x^"])
   finally show ?thesis .
+
   also have "... = e ⋅ (x ⋅ x^)"  
qed
+
    by (simp only: asociativa)
 +
   also have "... = e ⋅ 𝟭"  
 +
    by (simp only: inverso_d)
 +
   also have "... = e"  
 +
    by (simp only: neutro_d)
 +
   finally show ?thesis  
 +
    by this
 +
qed  
  
text {*
+
text ‹Ejemplo 5. En los grupos, los inversos por la izquierda son  
  Ejemplo 5. En los grupos, los inversos por la izquierda son únicos; es
+
  únicos; es decir, si x' es un elemento tal que x' ⋅ x = 𝟭, entonces  
  decir, si x' es un elemento tal que x' ⋅ x = 𝟭, entonces x^ x'. *}
+
  x^ = x'.
  
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
Línea 152: Línea 177:
 
   shows "x^ = x'"
 
   shows "x^ = x'"
 
proof -
 
proof -
   have "x^ = 𝟭 ⋅ x^" by (simp only: neutro_i)
+
   have "x^ = 𝟭 ⋅ x^"  
   also have "... = (x' ⋅ x) ⋅ x^" using assms by simp
+
    by (simp only: neutro_i)
   also have "... = x' ⋅ (x ⋅ x^)" by (simp only: asociativa)
+
   also have "... = (x' ⋅ x) ⋅ x^"  
   also have "... = x' ⋅ 𝟭" by (simp only: inverso_d)
+
    using assms [THEN sym]
   also have "... = x'" by (simp only: neutro_d)
+
    by (simp only: arg_cong [of "𝟭" "x' ⋅ x"])
   finally show ?thesis .
+
   also have "... = x' ⋅ (x ⋅ x^)"  
 +
    by (simp only: asociativa)
 +
   also have "... = x' ⋅ 𝟭"  
 +
    by (simp only: inverso_d)
 +
   also have "... = x'"  
 +
    by (simp only: neutro_d)
 +
   finally show ?thesis  
 +
    by this
 
qed
 
qed
  
text {*
+
text ‹Ejemplo 6. En los grupos, es inverso de un producto es el  
  Ejemplo 6. En los grupos, es inverso de un producto es el producto de
+
  producto de los inversos cambiados de orden; es decir,
  los inversos cambiados de orden; es decir,
+
     (x ⋅ y)^ = y^ ⋅ x^
     (x ⋅ y)^ = y^ ⋅ x^   *}
 
  
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
Línea 175: Línea 206:
 
   show "(y^ ⋅ x^) ⋅ (x ⋅ y) = 𝟭"
 
   show "(y^ ⋅ x^) ⋅ (x ⋅ y) = 𝟭"
 
   proof -
 
   proof -
     have "(y^ ⋅ x^) ⋅ (x ⋅ y) = (y^ ⋅ (x^ ⋅ x)) ⋅ y" by (simp only: asociativa)
+
     have "(y^ ⋅ x^) ⋅ (x ⋅ y) = (y^ ⋅ (x^ ⋅ x)) ⋅ y"  
     also have "... = (y^ ⋅ 𝟭) ⋅ y" by (simp only: inverso_i)
+
      by (simp only: asociativa)
     also have "... = y^ ⋅ y" by (simp only: neutro_d)
+
     also have "... = (y^ ⋅ 𝟭) ⋅ y"  
     also have "... = 𝟭" by (simp only: inverso_i)
+
      by (simp only: inverso_i)
     finally show ?thesis .
+
     also have "... = y^ ⋅ y"  
 +
      by (simp only: neutro_d)
 +
     also have "... = 𝟭"  
 +
      by (simp only: inverso_i)
 +
     finally show ?thesis  
 +
      by this
 
   qed
 
   qed
 
qed
 
qed
  
text {*
+
text ‹Ejemplo 7. En los grupos, el inverso del inverso es el propio
  Ejemplo 7. En los grupos, el inverso del inverso es el propio
 
 
   elemento; es decir,  
 
   elemento; es decir,  
     (x^)^ = x    *}
+
     (x^)^ = x›
  
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
 
― ‹La demostración automática (obtenida con Sledgehammer) es›
Línea 196: Línea 231:
 
   "(x^)^ = x"
 
   "(x^)^ = x"
 
proof (rule unicidad_inverso_i)
 
proof (rule unicidad_inverso_i)
   show "x ⋅ x^ = 𝟭" by (simp only: inverso_d)
+
   show "x ⋅ x^ = 𝟭"  
 +
    by (simp only: inverso_d)
 
qed
 
qed
  
text {*
+
text ‹Ejemplo 8. En los grupos, la función inversa es inyectiva; es  
  Ejemplo 8. En los grupos, la función inversa es inyectiva; es decir,
+
  decir, si x e y tienen los mismos inversos, entonces son iguales.
  si x e y tienen los mismos inversos, entonces son iguales. *}
 
  
 
― ‹La demostración automática es (obtenida con Sledgehammer) es›
 
― ‹La demostración automática es (obtenida con Sledgehammer) es›
Línea 215: Línea 250:
 
   shows "x = y"
 
   shows "x = y"
 
proof -
 
proof -
   have "(x^)^ = (y^)^" using assms by simp
+
   have "(x^)^ = (y^)^"  
   thus "x = y" by (simp only: inverso_inverso)
+
    using assms by (simp only: arg_cong [of "x^" "y^"])
 +
   thus "x = y"  
 +
    by (simp only: inverso_inverso)
 
qed
 
qed
  
 
end
 
end
  
section {* Teorías de órdenes mediante clases *}
+
section ‹Teorías de órdenes mediante clases›
  
text {*
+
text ‹El tutorial sobre clases está en la teoría Clases.thy.
  El tutorial sobre clases está en la teoría Clases.thy.
 
 
    
 
    
 
   La clase de los órdenes es la colección de los tipos que poseen una
 
   La clase de los órdenes es la colección de los tipos que poseen una
Línea 231: Línea 267:
 
   · transitiva: ⟦x ≼ y; y ≼ z⟧ ⟹ x ≼ z
 
   · transitiva: ⟦x ≼ y; y ≼ z⟧ ⟹ x ≼ z
 
   · antisimétrica: ⟦x ≼ y; y ≼ x⟧ ⟹ x = y
 
   · antisimétrica: ⟦x ≼ y; y ≼ x⟧ ⟹ x = y
*}
+
  
 
class orden =  
 
class orden =  
Línea 239: Línea 275:
 
       and antisim: "⟦x ≼ y; y ≼ x⟧ ⟹ x = y"
 
       and antisim: "⟦x ≼ y; y ≼ x⟧ ⟹ x = y"
  
text {*
+
text ‹Ha generado los teoremas correspondientes a los axiomas. Pueden  
  Ha generado los teoremas correspondientes a los axiomas. Pueden consultarse
+
   consultarse mediante thm como se muestra a continuación.
   mediante thm como se muestra a continuación.
 
*}
 
  
 
thm trans
 
thm trans
  
text {*
+
text ‹Se inicia el contexto orden en el que se van a realizar  
  Se inicia el contexto orden en el que se van a realizar definiciones y
+
  definiciones y demostraciones.
  demostraciones.  
 
*}
 
  
 
context orden
 
context orden
 
begin
 
begin
  
text {*
+
text ‹x es menor que y si x es menor o igual que y y no es menos o igual
  x es menor que y si x es menor o igual que y y no son iguales.
+
  que x.
*}
 
  
 
definition menor :: "'a ⇒ 'a ⇒ bool"  (infix "≺" 50)
 
definition menor :: "'a ⇒ 'a ⇒ bool"  (infix "≺" 50)
 
   where "x ≺ y ⟷ x ≼ y ∧ ¬ y ≼ x"
 
   where "x ≺ y ⟷ x ≼ y ∧ ¬ y ≼ x"
  
text {*
+
text ‹La relación menor es irreflexiva.
    La relación menor es irreflexiva.
 
*}
 
  
 
lemma irrefl: "¬ x ≺ x"
 
lemma irrefl: "¬ x ≺ x"
 
   by (auto simp: menor_def)
 
   by (auto simp: menor_def)
  
text {*
+
text ‹La relación menor es transitiva.
  La relación menor es transitiva.
 
*}
 
  
 
(* Demostración aplicativa *)
 
(* Demostración aplicativa *)
Línea 284: Línea 311:
 
   by (auto simp: menor_def intro: trans)
 
   by (auto simp: menor_def intro: trans)
  
text {*
+
text ‹La relación menor es asimétrica; es decir, si x ≺ y e y ≺ x,  
  La relación menor es asimétrica; es decir, si x ≺ y e y ≺ x, entonces
+
   entonces se verifica cualquier propiedad P.
   se verifica cualquier propiedad P.  
 
*}
 
  
 
lemma asimetrica: "x ≺ y ⟹ y ≺ x ⟹ P"
 
lemma asimetrica: "x ≺ y ⟹ y ≺ x ⟹ P"
   by (auto simp: menor_def)
+
   by (simp add: menor_def)
  
 
end
 
end
  
subsection {* Subclase *}
+
subsection ‹Subclase›
  
text {*
+
text ‹Un orden lineal es un orden en que cada par de elementos son  
  Un orden lineal es un orden en que cada par de elementos son comparables.
+
  comparables.
*}
 
  
 
class ordenLineal = orden +
 
class ordenLineal = orden +
Línea 304: Línea 328:
 
begin
 
begin
  
text {*
+
text ‹En los órdenes lineales se tiene que x ≺ y ∨ x = y ∨ y ≺ x.
  En los órdenes lineales se tiene que x ≺ y ∨ x = y ∨ y ≺ x.
 
*}
 
  
 
(* Demostración aplicativa *)
 
(* Demostración aplicativa *)
Línea 344: Línea 366:
 
(* Demostración automática *)
 
(* Demostración automática *)
 
lemma "x ≺ y ∨ x = y ∨ y ≺ x"
 
lemma "x ≺ y ∨ x = y ∨ y ≺ x"
   using menor_def lineal antisim 
+
   using antisim lineal menor_def by auto
  by blast
 
  
 
end
 
end
  
section {* Teoría de órdenes mediante ámbitos ("Locales") *}
+
section ‹Teoría de órdenes mediante ámbitos ("Locales")
  
text {*
+
text ‹Un orden es una estructura con una relación reflexiva,  
  Un orden es una estructura con una relación reflexiva, transitiva y
+
  transitiva y antisimétrica.
  antisimétrica.  
 
*}
 
  
 
locale Orden =
 
locale Orden =
Línea 362: Línea 381:
 
       and antisim: "⟦x ⊑ y; y ⊑ x⟧ ⟹ x = y"
 
       and antisim: "⟦x ⊑ y; y ⊑ x⟧ ⟹ x = y"
  
text {*
+
text ‹Los teoremas se diferencian por el nombre y el ámbito.  
    Los teoremas se diferencian por el nombre y el ámbito. Por ejemplo,
+
  Por ejemplo,
 
     refl: ?x ≼ ?x
 
     refl: ?x ≼ ?x
 
     Orden.refl: Orden ?menor_ig ⟹ ?menor_ig ?x ?x
 
     Orden.refl: Orden ?menor_ig ⟹ ?menor_ig ?x ?x
Línea 370: Línea 389:
 
               (∀x y z. ?menor_ig x y ⟶ ?menor_ig y z ⟶ ?menor_ig x z) ∧
 
               (∀x y z. ?menor_ig x y ⟶ ?menor_ig y z ⟶ ?menor_ig x z) ∧
 
               (∀x y. ?menor_ig x y ⟶ ?menor_ig y x ⟶ x = y)
 
               (∀x y. ?menor_ig x y ⟶ ?menor_ig y x ⟶ x = y)
*}
+
  
 
thm refl
 
thm refl
Línea 376: Línea 395:
 
thm Orden_def
 
thm Orden_def
  
text {*
+
text ‹Un orden lineal es un orden en el que todos los pares de elementos son  
  Un orden lineal es un orden en el que todos los pares de elementos son  
+
   comparables.
   comparables.  
 
*}
 
  
 
locale OrdenLineal = Orden +
 
locale OrdenLineal = Orden +
 
   assumes lineal: "x ⊑ y ∨ y ⊑ x"
 
   assumes lineal: "x ⊑ y ∨ y ⊑ x"
  
text {*
+
text ‹Los boooleanos está ordenados con el condicional.
  Los boooleanos está ordenados con el condicional.
 
*}
 
  
 
interpretation Orden_imp: Orden "λx y. x ⟶ y"
 
interpretation Orden_imp: Orden "λx y. x ⟶ y"
 
proof
 
proof
   fix P show "P ⟶ P" by blast
+
   fix P show "P ⟶ P" by simp
 
next
 
next
   fix P Q R show "P ⟶ Q ⟹ Q ⟶ R ⟹ P ⟶ R" by blast
+
   fix P Q R show "P ⟶ Q ⟹ Q ⟶ R ⟹ P ⟶ R" by simp
 
next
 
next
 
   fix P Q show "P ⟶ Q ⟹ Q ⟶ P ⟹ P = Q" by blast
 
   fix P Q show "P ⟶ Q ⟹ Q ⟶ P ⟹ P = Q" by blast
 
qed
 
qed
  
text {*
+
text ‹Los naturales con la relación de divisibilidad es un conjunto  
  Los naturales con la relación de divisibilidad es un conjunto ordenado.
+
  ordenado.
*}
 
  
 
interpretation Orden_dvd: Orden "(dvd) :: nat ⇒ nat ⇒ bool"
 
interpretation Orden_dvd: Orden "(dvd) :: nat ⇒ nat ⇒ bool"
 
proof  
 
proof  
 
   fix x :: nat
 
   fix x :: nat
   show "x dvd x" using dvd_refl by simp
+
   show "x dvd x" by simp
 
next
 
next
 
   fix x y z :: nat
 
   fix x y z :: nat
   show "⟦x dvd y; y dvd z⟧ ⟹ x dvd z" using dvd_trans by auto
+
   show "⟦x dvd y; y dvd z⟧ ⟹ x dvd z" by auto  
 
next
 
next
 
   fix x y :: nat
 
   fix x y :: nat
   show "⟦x dvd y; y dvd x⟧ ⟹ x = y" using dvd_antisym by simp
+
   show "⟦x dvd y; y dvd x⟧ ⟹ x = y" by auto
 
qed
 
qed
  
text {*
+
section ‹Semigrupos, monoides y grupos›
  Ámbito de las funciones monótonas (ver la página 12 del tutorial de
 
  locales).
 
*}
 
 
 
locale Mono =
 
  le1: Orden le1 +
 
  le2: Orden le2
 
    for le1 (infix "⊑⇩1" 50) and le2 (infix "⊑⇩2" 50) +
 
  fixes f :: "'a ⇒ 'b"
 
  assumes mono: "x ⊑⇩1 y ⟹ f(x) ⊑⇩2 f(y)"
 
 
 
text {*
 
  Si f es monótona, x ⊑_1 y e y ⊑_1 z, entonces f(x) ⊑_2 f(z).
 
*}
 
  
lemma (in Mono) mono_trans:
+
subsection ‹Definición de clases›
  assumes "x ⊑⇩1 y" and "y ⊑⇩1 z"
 
  shows "f(x) ⊑⇩2 f(z)"
 
proof -
 
  have "x ⊑⇩1 z" using assms and le1.trans by blast
 
  then show "f(x) ⊑⇩2 f(z)" using mono by simp
 
qed
 
  
text {*
+
text ‹Un semigrupo es una estructura compuesta por un conjunto A y una
  El teorema generado se llama Mono.mono_trans.
+
   operación binaria en A.
*}
 
 
 
thm Mono.mono_trans
 
 
 
text {*
 
  En el contexto Mono el nombre es mono_trans.
 
*}
 
 
 
context Mono
 
begin
 
thm mono_trans
 
end
 
 
 
text {*
 
  El predicado `ser par' es un operador monótono entre los naturales con la
 
  relación de divisibilidad y los booleanos con el condicional; es decir,
 
    x dvd y ⟹ even x ⟶ even y
 
*}
 
 
 
interpretation Mono "(dvd)" "(⟶)" "λn::nat. 2 dvd n"
 
proof
 
  fix x y :: nat
 
  show "x dvd y ⟹ even x ⟶ even y"
 
    proof
 
      assume "x dvd y" and "even x"
 
      then show "even y"
 
        using  Rings.comm_monoid_mult_class.dvd_trans by auto
 
    qed
 
qed
 
 
 
section {* Semigrupos, monoides y grupos *}
 
 
 
subsection {* Definición de clases *}
 
 
 
text {*
 
  Un semigrupo es una estructura compuesta por un conjunto A y una
 
   operación binaria en A.
 
*}
 
  
 
class semigrupo =
 
class semigrupo =
Línea 482: Línea 438:
 
   assumes asoc: "(x ⊗ y) ⊗ z = x ⊗ (y ⊗ z )"
 
   assumes asoc: "(x ⊗ y) ⊗ z = x ⊗ (y ⊗ z )"
  
subsection {* Instanciación de clases *}
+
subsection ‹Instanciación de clases›
  
text {*
+
text ‹Los enteros con la suma forman un semigrupo.
  Los enteros con la suma forman un semigrupo.
 
*}
 
  
 
instantiation int :: semigrupo  
 
instantiation int :: semigrupo  
Línea 500: Línea 454:
 
end  
 
end  
  
text {*
+
text ‹Los naturales con la suma forman un semigrupo.
  Los naturales con la suma forman un semigrupo.
 
*}
 
  
 
instantiation nat :: semigrupo  
 
instantiation nat :: semigrupo  
 
begin  
 
begin  
primrec mult_nat where  
+
fun mult_nat where  
 
   "(0::nat) ⊗ n = n"  
 
   "(0::nat) ⊗ n = n"  
 
| "Suc m ⊗ n = Suc (m ⊗ n)"  
 
| "Suc m ⊗ n = Suc (m ⊗ n)"  
Línea 517: Línea 469:
 
end
 
end
  
subsection {* Instancias recursivas *}
+
subsection ‹Instancias recursivas›
  
text {*
+
text ‹Si (A,⊗) y (B,⊗) son semigrupos, entonces ((A×B,⊗), donde el  
  Si (A,⊗) y (B,⊗) son semigrupos, entonces ((A×B,⊗), donde el producto
+
   producto se define por  
   se define por  
 
 
     (x,y)⊗(x',y') = (x⊗x',y⊗y'),
 
     (x,y)⊗(x',y') = (x⊗x',y⊗y'),
   es un semigrupo.
+
   es un semigrupo.
*}
 
 
   
 
   
 
instantiation prod :: (semigrupo, semigrupo) semigrupo  
 
instantiation prod :: (semigrupo, semigrupo) semigrupo  
Línea 539: Línea 489:
 
end
 
end
  
subsection {* Subclases *}
+
subsection ‹Subclases›
  
text {*
+
text Un monoide izquierdo es un semigrupo con elemento neutro por la  
  Un monoide izquierdo es un semigrupo con elemento neutro por la izquierda.  
+
  izquierda.
*}
 
  
 
class monoideI = semigrupo +  
 
class monoideI = semigrupo +  
Línea 549: Línea 498:
 
   assumes neutroI: "𝟭 ⊗ x = x"
 
   assumes neutroI: "𝟭 ⊗ x = x"
  
text {*
+
text ‹Los naturales y los enteros con la suma forman monoides por la  
  Los naturales y los enteros con la suma forman monoides por la izquierda.
+
  izquierda.
*}
 
  
 
instantiation nat and int :: monoideI  
 
instantiation nat and int :: monoideI  
Línea 571: Línea 519:
 
end
 
end
  
text {*
+
text ‹El producto de dos monoides por la izquierda es un monoide por la
  El producto de dos monoides por la izquierda es un monoide por la
+
   izquierda, donde el neutro es el par formado por los elementos  
   izquierda, donde el neutro es el par formado por los elementos neutros.
+
  neutros.
*}
 
  
 
instantiation prod :: (monoideI , monoideI) monoideI  
 
instantiation prod :: (monoideI , monoideI) monoideI  
Línea 589: Línea 536:
 
end
 
end
  
text {*
+
text ‹Un monoide es un monoide por la izquierda cuyo elemento neutro  
  Un monoide es un monoide por la izquierda cuyo elemento neutro por la
+
  por la izquierda lo es también por la derecha.
  izquierda lo es también por la derecha.
 
*}
 
  
 
class monoide = monoideI +  
 
class monoide = monoideI +  
 
   assumes neutro: "x ⊗ 𝟭 = x"  
 
   assumes neutro: "x ⊗ 𝟭 = x"  
  
text {*
+
text ‹Los naturales y los enteros con la suma son monoides.
  Los naturales y los enteros con la suma son monoides.
 
*}
 
  
 
instantiation nat and int :: monoide  
 
instantiation nat and int :: monoide  
Línea 615: Línea 558:
 
end
 
end
  
text {*
+
text ‹El producto de dos monoides es un monoide.
  El producto de dos monoides es un monoide.
 
*}
 
  
 
instantiation prod :: (monoide, monoide) monoide  
 
instantiation prod :: (monoide, monoide) monoide  
Línea 629: Línea 570:
 
end
 
end
  
text {*
+
text ‹Un grupo es un monoide por la izquierda tal que todo elemento  
  Un grupo es un monoide por la izquierda tal que todo elemento posee un
+
  posee un inverso por la izquierda.
  inverso por la izquierda.
 
*}
 
  
 
class grupo2 = monoideI +  
 
class grupo2 = monoideI +  
Línea 638: Línea 577:
 
   assumes inversoI: "x⇧-⇧1 ⊗ x = 𝟭"  
 
   assumes inversoI: "x⇧-⇧1 ⊗ x = 𝟭"  
  
text {*
+
text ‹Los enteros con la suma forman un grupo.
  Los enteros con la suma forman un grupo.
 
*}
 
  
 
instantiation int :: grupo2  
 
instantiation int :: grupo2  
Línea 656: Línea 593:
 
end
 
end
  
subsection {* Razonamiento abstracto *}
+
subsection ‹Razonamiento abstracto›
  
text {*
+
text ‹En los grupos se verifica la propiedad cancelativa por la  
  En los grupos se verifica la propiedad cancelativa por la izquierda, i.e.
+
  izquierda, i.e.
 
     x ⊗ y = x ⊗ z ⟷ y = z
 
     x ⊗ y = x ⊗ z ⟷ y = z
*}
+
  
 
lemma (in grupo2) cancelativa_izq: "x ⊗ y = x ⊗ z ⟷ y = z"  
 
lemma (in grupo2) cancelativa_izq: "x ⊗ y = x ⊗ z ⟷ y = z"  
 
proof  
 
proof  
 
   assume "x ⊗ y = x ⊗ z"
 
   assume "x ⊗ y = x ⊗ z"
   hence "x⇧-⇧1 ⊗ (x ⊗ y) = x⇧-⇧1 ⊗ (x ⊗ z)" by simp  
+
   then have "x⇧-⇧1 ⊗ (x ⊗ y) = x⇧-⇧1 ⊗ (x ⊗ z)"  
   hence "(x⇧-⇧1 ⊗ x) ⊗ y = (x⇧-⇧1 ⊗ x) ⊗ z" using asoc by simp  
+
    by simp  
   then show "y = z" using neutroI and inversoI by simp
+
   then have "(x⇧-⇧1 ⊗ x) ⊗ y = (x⇧-⇧1 ⊗ x) ⊗ z"  
 +
    using asoc by simp  
 +
   then show "y = z"  
 +
    using neutroI and inversoI by simp
 
next  
 
next  
 
   assume "y = z"  
 
   assume "y = z"  
   then show "x ⊗ y = x ⊗ z" by simp
+
   then show "x ⊗ y = x ⊗ z"  
 +
    by simp
 
qed
 
qed
  
 
thm grupo2.cancelativa_izq
 
thm grupo2.cancelativa_izq
  
text {*
+
text ‹Se genera el teorema grupo.cancelativa_izq
  Se genera el teorema grupo.cancelativa_izq
 
 
     class.grupo2 ?mult ?neutro ?inverso ⟹  
 
     class.grupo2 ?mult ?neutro ?inverso ⟹  
 
     (?mult ?x ?y = ?mult ?x ?z) = (?y = ?z)
 
     (?mult ?x ?y = ?mult ?x ?z) = (?y = ?z)
  
   El teorema se aplica automáticamente a todas las instancias de la clase
+
   El teorema se aplica automáticamente a todas las instancias de la  
   grupo. Por ejemplo, a los enteros.
+
   clase grupo. Por ejemplo, a los enteros.
*}
 
  
subsection {* Definiciones derivadas *}
+
subsection ‹Definiciones derivadas›
  
text {*
+
text ‹En los monoides se define la potencia natural por
  En los monoides se define la potencia natural por
 
 
   · x^0    = 1
 
   · x^0    = 1
 
   · x^{n+1} = x*x^n
 
   · x^{n+1} = x*x^n
*}
+
  
 
fun (in monoide) potencia_nat :: "nat ⇒ 'a ⇒ 'a" where  
 
fun (in monoide) potencia_nat :: "nat ⇒ 'a ⇒ 'a" where  
Línea 697: Línea 635:
 
| "potencia_nat (Suc n) x = x ⊗ potencia_nat n x"
 
| "potencia_nat (Suc n) x = x ⊗ potencia_nat n x"
  
subsection {* Analogía entre clases y functores *}
+
subsection ‹Analogía entre clases y functores›
  
text {*
+
text ‹Las listas con la operación de concatenación y la lista vacía  
  Las listas con la operación de concatenación y la lista vacía como elemento
+
  como elemento neutro forman un monoide.
  neutro forman un monoide.
 
*}
 
  
 
interpretation list_monoide: monoide "append" "[]"
 
interpretation list_monoide: monoide "append" "[]"
Línea 713: Línea 649:
 
qed
 
qed
  
text {*
+
text ‹Se pueden aplicar propiedades de los monides a las listas. Por  
  Se pueden aplicar propiedades de los monides a las listas. Por ejemplo,
+
  ejemplo,
*}
 
  
 
lemma "append [] xs = xs"
 
lemma "append [] xs = xs"
 
   by simp
 
   by simp
  
text {*
+
text (repite n xs) es la lista obtenida concatenando n veces la lista  
  (repite n xs) es la lista obtenida concatenando n veces la lista xs.  
+
  xs.
*}
 
  
 
fun repite :: "nat ⇒ 'a list ⇒ 'a list" where  
 
fun repite :: "nat ⇒ 'a list ⇒ 'a list" where  
Línea 728: Línea 662:
 
| "repite (Suc n) xs = xs @ repite n xs"
 
| "repite (Suc n) xs = xs @ repite n xs"
  
text {*
+
text ‹Las listas con la operación de concatenación y la lista vacía como elemento
  Las listas con la operación de concatenación y la lista vacía como elemento
+
   neutro forman un monoide. Además, la potencia natural se intepreta  
   neutro forman un monoide. Además, la potencia natural se intepreta como
+
   como repite.
   repite.  
 
*}
 
  
 
interpretation list_monoide: monoide "append" "[]" rewrites
 
interpretation list_monoide: monoide "append" "[]" rewrites
Línea 746: Línea 678:
 
qed intro_locales
 
qed intro_locales
  
subsection {* Relaciones de subclase adicionales *}
+
subsection ‹Relaciones de subclase adicionales›
  
text {*
+
text ‹Los grupos son monoides.
  Los grupos son monoides.
 
*}
 
  
 
subclass (in grupo2) monoide  
 
subclass (in grupo2) monoide  
 
proof  
 
proof  
 
   fix x  
 
   fix x  
   have "x⇧-⇧1 ⊗ (x ⊗ 𝟭) = x⇧-⇧1 ⊗ (x ⊗ (x⇧-⇧1 ⊗ x))" using inversoI by simp
+
   have "x⇧-⇧1 ⊗ (x ⊗ 𝟭) = x⇧-⇧1 ⊗ (x ⊗ (x⇧-⇧1 ⊗ x))"  
   also have "… = (x⇧-⇧1 ⊗ x) ⊗ (x⇧-⇧1 ⊗ x)" using asoc [symmetric] by simp
+
    using inversoI by simp
   also have "… = 𝟭 ⊗ (x⇧-⇧1 ⊗ x)" using inversoI by simp
+
   also have "… = (x⇧-⇧1 ⊗ x) ⊗ (x⇧-⇧1 ⊗ x)"  
   also have "… = x⇧-⇧1 ⊗ x" using neutroI by simp
+
    using asoc [symmetric] by simp
   finally have "x⇧-⇧1 ⊗ (x ⊗ 𝟭) = x⇧-⇧1 ⊗ x" .
+
   also have "… = 𝟭 ⊗ (x⇧-⇧1 ⊗ x)"  
   then show "x ⊗ 𝟭 = x" using cancelativa_izq by simp
+
    using inversoI by simp
 +
   also have "… = x⇧-⇧1 ⊗ x"  
 +
    using neutroI by simp
 +
   finally have "x⇧-⇧1 ⊗ (x ⊗ 𝟭) = x⇧-⇧1 ⊗ x"  
 +
    by this
 +
   then show "x ⊗ 𝟭 = x"  
 +
    using cancelativa_izq by simp
 
qed
 
qed
  
text {*
+
text ‹La potencia entera en los grupos se define a partir de la potencia  
  La potencia entera en los grupos se define a partir de la potencia natural
+
   natural como sigue:
   como sigue:
 
 
   · x^k = x^k si k ≥ 0
 
   · x^k = x^k si k ≥ 0
 
   · x^k = (x^{-k})^{-1}, en caso contrario.
 
   · x^k = (x^{-k})^{-1}, en caso contrario.
*}
+
  
 
definition (in grupo2) potencia_entera :: "int ⇒ 'a ⇒ 'a" where  
 
definition (in grupo2) potencia_entera :: "int ⇒ 'a ⇒ 'a" where  
Línea 776: Línea 711:
 
     else (potencia_nat (nat (- k)) x)⇧-⇧1)"
 
     else (potencia_nat (nat (- k)) x)⇧-⇧1)"
  
section {* Bibliografía *}
+
section ‹Bibliografía›
text {*
+
 
 +
text
 
   + "Haskell-style type classes with Isabelle/Isar" ~ F. Haftmann.
 
   + "Haskell-style type classes with Isabelle/Isar" ~ F. Haftmann.
 
     http://bit.ly/2E55pAJ
 
     http://bit.ly/2E55pAJ
 
   + "Tutorial to locales and locale interpretation" ~ C. Ballarin.
 
   + "Tutorial to locales and locale interpretation" ~ C. Ballarin.
 
     http://bit.ly/2E3ozXB   
 
     http://bit.ly/2E3ozXB   
*}
+
  
 
end
 
end
 
</source>
 
</source>

Revisión actual del 17:20 20 may 2020

chapter Desarrollo de teorías formalizadas

theory T11_Desarrollo_de_teorias_formalizadas
imports Main
begin

section Desarrollo de la teoría de grupos

text El objetivo de este tema es mostrar cómo se puede trabajar en
  estructuras algebraicas por medio de locales. 

  Se usará como ejemplo la teoría de grupos.

text Ejemplo 1. Un grupo es una estructura (G,·,𝟭,^) tal que 
  * G es un conjunto, 
  * · es una operación binaria en G, 
  * 𝟭 es un elemento de G y 
  * ^ es una función de G en G 
  tales que se cumplen las siguientes propiedades:
  * asociativa: x y z. x  (y  z) = (x  y)  z
  * neutro por la izquierda: x. 𝟭  x = x
  * inverso por la izquierda: x. x^  x = 𝟭 

  Definir el entorno axiomático de los grupos.

locale grupo = 
  fixes prod :: "['a, 'a] ⇒ 'a" (infixl "⋅" 70)
    and neutro ("𝟭") 
    and inverso ("_^" [100] 100)
  assumes asociativa: "(x ⋅ y) ⋅ z = x ⋅ (y ⋅ z)"
      and neutro_i:   "𝟭 ⋅ x = x"
      and inverso_i:  "x^ ⋅ x = 𝟭"

text Notas sobre notación:
  * El producto es  y se escribe con \ cdot (sin espacio entre ellos). 
  * El neutro es 𝟭 y se escribe con \ y one (sin espacio entre ellos).
  * El inverso de x es x^ y se escribe pulsando 2 veces en ^.

text A continuación se crea un contexto en el que se supone la 
  notación y axiomas de grupos. 

  En el contexto se demuestran propiedades de los grupos.

context grupo
begin

text Ejemplo 2. En los grupos, x^ también es el inverso de x por la
  derecha; es decir 
     x  x^ = 𝟭

 La demostración automática (obtenida con Sledgehammer) es
lemma "x ⋅ x^ = 𝟭"
  (* sledgehammer *)
  by (metis asociativa inverso_i neutro_i)

 La demostración detallada es
lemma inverso_d: 
  "x ⋅ x^ = 𝟭"
proof -
  have "x ⋅ x^ = 𝟭 ⋅ (x ⋅ x^)" 
    by (simp only: neutro_i)
  also have "… = (𝟭 ⋅ x) ⋅ x^" 
    by (simp only: asociativa)
  also have "… = (((x^)^ ⋅ x^) ⋅ x) ⋅ x^" 
    by (simp only: inverso_i)
  also have "… = ((x^)^ ⋅ (x^ ⋅ x)) ⋅ x^" 
    by (simp only: asociativa)
  also have "… = ((x^)^ ⋅ 𝟭) ⋅ x^" 
    by (simp only: inverso_i)
  also have "… = (x^)^ ⋅ (𝟭 ⋅ x^)" 
    by (simp only: asociativa)
  also have "… = (x^)^ ⋅ x^" 
    by (simp only: neutro_i)
  also have "… = 𝟭" 
    by (simp only: inverso_i)
  finally show ?thesis 
    by this
qed

text Ejemplo 2. En los grupos, 𝟭 también es el neutro por la derecha; 
  es decir 
     x  𝟭 = x

 La demostración automática (obtenida con Sledgehammer) es
lemma "x ⋅ 𝟭 = x"
  by (metis asociativa inverso_i neutro_i)

 La demostración detallada es
lemma neutro_d: 
  "x ⋅ 𝟭 = x"
proof -
  have "x ⋅ 𝟭 = x ⋅ (x^ ⋅ x)" 
    by (simp only: inverso_i)
  also have "… = (x ⋅ x^) ⋅ x"
    by (simp only: asociativa)
  also have "… = 𝟭 ⋅ x" 
    by (simp only: inverso_d)
  also have "… = x" 
    by (simp only: neutro_i)
  finally show "x ⋅ 𝟭 = x" 
    by this
qed 

text Ejemplo 3. En los grupos, se tiene la propiedad cancelativa por la
  izquierda; es decir,
     x  y = x  z syss y = z

 La demostración automática (obtenida con Sledgehammer) es
lemma "(x ⋅ y = x ⋅ z) = (y = z)"
  by (metis asociativa inverso_i neutro_i)

 La demostración detallada es
lemma cancelativa_i: 
  "(x ⋅ y = x ⋅ z) = (y = z)"
proof
  assume "x ⋅ y = x ⋅ z"
  then have "x^ ⋅ (x ⋅ y) = x^ ⋅ (x ⋅ z)"
    by (simp only: arg_cong [of "x ⋅ y" "x ⋅ z"])
  then have "(x^ ⋅ x) ⋅ y = (x^ ⋅ x) ⋅ z" 
    by (simp only: asociativa)
  then have "𝟭 ⋅ y = 𝟭 ⋅ z" 
    by (simp only: inverso_i)
  thus "y = z" 
    by (simp only: neutro_i)
next
  assume "y = z"
  then show "x ⋅ y = x ⋅ z" 
    by (simp only: arg_cong [of "y" "z"])
qed

text Ejemplo 4. En los grupos, el elemento neutro por la izquierda es
  único; es decir, si e es un elemento tal que para todo x se tiene que 
  e  x = x, entonces e = 𝟭.

 La demostración automática es (obtenida con Sledgehammer) es
lemma 
  assumes "e ⋅ x = x"
  shows "𝟭 = e"
  using assms
  by (metis asociativa inverso_d neutro_d)

 La demostración estructurada es
lemma unicidad_neutro_i:
  assumes "e ⋅ x = x"
  shows "𝟭 = e"
proof -
  have "𝟭 = x ⋅ x^" 
    by (simp only: inverso_d)
  also have "... = (e ⋅ x) ⋅ x^" 
    using assms [THEN sym] 
    by (rule arg_cong [of "x" "e ⋅ x" "λy. y ⋅ x^"])
  also have "... = e ⋅ (x ⋅ x^)" 
    by (simp only: asociativa)
  also have "... = e ⋅ 𝟭" 
    by (simp only: inverso_d)
  also have "... = e" 
    by (simp only: neutro_d)
  finally show ?thesis 
    by this
qed 

text Ejemplo 5. En los grupos, los inversos por la izquierda son 
  únicos; es decir, si x' es un elemento tal que x'  x = 𝟭, entonces 
  x^ = x'.

 La demostración automática (obtenida con Sledgehammer) es
lemma 
  assumes "x' ⋅ x = 𝟭"
  shows "x^ = x'"
  using assms
  by (metis asociativa inverso_i neutro_i)

 La demostración estructurada es
lemma unicidad_inverso_i:
  assumes "x' ⋅ x = 𝟭"
  shows "x^ = x'"
proof -
  have "x^ = 𝟭 ⋅ x^" 
    by (simp only: neutro_i)
  also have "... = (x' ⋅ x) ⋅ x^" 
    using assms [THEN sym] 
    by (simp only: arg_cong [of "𝟭" "x' ⋅ x"])
  also have "... = x' ⋅ (x ⋅ x^)" 
    by (simp only: asociativa)
  also have "... = x' ⋅ 𝟭" 
    by (simp only: inverso_d)
  also have "... = x'" 
    by (simp only: neutro_d)
  finally show ?thesis 
    by this
qed

text Ejemplo 6. En los grupos, es inverso de un producto es el 
  producto de los inversos cambiados de orden; es decir,
     (x  y)^ = y^  x^›

 La demostración automática (obtenida con Sledgehammer) es
lemma "(x ⋅ y)^ = y^ ⋅ x^"
  by (metis asociativa inverso_d neutro_d)

 La demostración detallada es
lemma inversa_producto:
  "(x ⋅ y)^ = y^ ⋅ x^"
proof (rule unicidad_inverso_i)
  show "(y^ ⋅ x^) ⋅ (x ⋅ y) = 𝟭"
  proof -
    have "(y^ ⋅ x^) ⋅ (x ⋅ y) = (y^ ⋅ (x^ ⋅ x)) ⋅ y" 
      by (simp only: asociativa)
    also have "... = (y^ ⋅ 𝟭) ⋅ y" 
      by (simp only: inverso_i)
    also have "... = y^ ⋅ y" 
      by (simp only: neutro_d)
    also have "... = 𝟭" 
      by (simp only: inverso_i)
    finally show ?thesis 
      by this
  qed
qed

text Ejemplo 7. En los grupos, el inverso del inverso es el propio
  elemento; es decir, 
     (x^)^ = x

 La demostración automática (obtenida con Sledgehammer) es
lemma "(x^)^ = x"
  using inverso_d unicidad_inverso_i by blast

 La demostración estructurada es
lemma inverso_inverso: 
  "(x^)^ = x"
proof (rule unicidad_inverso_i)
  show "x ⋅ x^ = 𝟭" 
    by (simp only: inverso_d)
qed

text Ejemplo 8. En los grupos, la función inversa es inyectiva; es 
  decir, si x e y tienen los mismos inversos, entonces son iguales.

 La demostración automática es (obtenida con Sledgehammer) es
lemma 
  assumes "x^ = y^"
  shows "x = y"
  using assms
  by (metis inverso_inverso)

 La demostración automática estructurada es
lemma inversa_inyectiva:
  assumes "x^ = y^"
  shows "x = y"
proof -
  have "(x^)^ = (y^)^" 
    using assms by (simp only: arg_cong [of "x^" "y^"])
  thus "x = y" 
    by (simp only: inverso_inverso)
qed

end

section Teorías de órdenes mediante clases

text El tutorial sobre clases está en la teoría Clases.thy.
  
  La clase de los órdenes es la colección de los tipos que poseen una
  relación  verificando las siguientes propiedades
  · reflexiva: x  x
  · transitiva: x  y; y  z  x  z
  · antisimétrica: x  y; y  x  x = y


class orden = 
  fixes menor_ig :: "'a ⇒ 'a ⇒ bool"  (infix "≼" 50)
  assumes refl: "x ≼ x"
      and trans: "⟦x ≼ y; y ≼ z⟧ ⟹ x ≼ z"
      and antisim: "⟦x ≼ y; y ≼ x⟧ ⟹ x = y"

text Ha generado los teoremas correspondientes a los axiomas. Pueden 
  consultarse mediante thm como se muestra a continuación.

thm trans

text Se inicia el contexto orden en el que se van a realizar 
  definiciones y demostraciones.

context orden
begin

text x es menor que y si x es menor o igual que y y no es menos o igual 
  que x.

definition menor :: "'a ⇒ 'a ⇒ bool"  (infix "≺" 50)
  where "x ≺ y ⟷ x ≼ y ∧ ¬ y ≼ x"

text La relación menor es irreflexiva.

lemma irrefl: "¬ x ≺ x"
  by (auto simp: menor_def)

text La relación menor es transitiva.

(* Demostración aplicativa *)
lemma "⟦x ≺ y; y ≺ z⟧ ⟹ x ≺ z"
  apply (unfold menor_def)
    (* ⟦x ≼ y ∧ ¬ y ≼ x; y ≼ z ∧ ¬ z ≼ y⟧ ⟹ x ≼ z ∧ ¬ z ≼ x *)
  apply (auto intro: trans)
    (* *)
  done

(* Demostración automática *)
lemma menor_trans: "⟦x ≺ y; y ≺ z⟧ ⟹ x ≺ z"
  by (auto simp: menor_def intro: trans)

text La relación menor es asimétrica; es decir, si x  y e y  x, 
  entonces se verifica cualquier propiedad P. 

lemma asimetrica: "x ≺ y ⟹ y ≺ x ⟹ P"
  by (simp add: menor_def)

end

subsection Subclase

text Un orden lineal es un orden en que cada par de elementos son 
  comparables.

class ordenLineal = orden +
  assumes lineal: "x ≼ y ∨ y ≼ x"
begin

text En los órdenes lineales se tiene que x  y  x = y  y  x.

(* Demostración aplicativa *)
lemma "x ≺ y ∨ x = y ∨ y ≺ x"
  apply (unfold menor_def)
      (* (x ≼ y ∧ ¬ y ≼ x) ∨ x = y ∨ (y ≼ x ∧ ¬ x ≼ y) *)
  apply auto
      (*  1. ⟦x ≠ y; ¬ x ≼ y⟧ ⟹ y ≼ x
          2. ⟦x ≠ y; y ≼ x; x ≼ y⟧ ⟹ False *)
   apply (cut_tac x=x and y=y in lineal)
      (* 1. ⟦x ≠ y; ¬ x ≼ y; x ≼ y ∨ y ≼ x⟧ ⟹ y ≼ x
         2. ⟦x ≠ y; y ≼ x; x ≼ y⟧ ⟹ False *)
   apply (erule disjE)
      (* 1. ⟦x ≠ y; ¬ x ≼ y; x ≼ y⟧ ⟹ y ≼ x
         2. ⟦x ≠ y; ¬ x ≼ y; y ≼ x⟧ ⟹ y ≼ x
         3. ⟦x ≠ y; y ≼ x; x ≼ y⟧ ⟹ False *)
    apply (erule_tac P="x ≼ y" in notE)
      (* 1. ⟦x ≠ y; x ≼ y⟧ ⟹ x ≼ y
         2. ⟦x ≠ y; ¬ x ≼ y; y ≼ x⟧ ⟹ y ≼ x
         3. ⟦x ≠ y; y ≼ x; x ≼ y⟧ ⟹ False *)
    apply assumption
      (* 1. ⟦x ≠ y; ¬ x ≼ y; y ≼ x⟧ ⟹ y ≼ x
         2. ⟦x ≠ y; y ≼ x; x ≼ y⟧ ⟹ False *)
   apply assumption
      (* 1. ⟦x ≠ y; y ≼ x; x ≼ y⟧ ⟹ False *)
  apply (drule antisim)
      (* 1. ⟦x ≠ y; x ≼ y⟧ ⟹ x ≼ y
         2. ⟦x ≠ y; x ≼ y; y = x⟧ ⟹ False *)
   apply assumption
      (* 1. ⟦x ≠ y; x ≼ y; y = x⟧ ⟹ False *)
  apply (erule notE)
      (* 1. ⟦x ≼ y; y = x⟧ ⟹ x = y *)
  apply (erule sym)
      (* *)
  done

(* Demostración automática *)
lemma "x ≺ y ∨ x = y ∨ y ≺ x"
  using antisim lineal menor_def by auto

end

section Teoría de órdenes mediante ámbitos ("Locales")

text Un orden es una estructura con una relación reflexiva, 
  transitiva y antisimétrica.

locale Orden =
  fixes menor_ig :: "'a ⇒ 'a ⇒ bool"  (infix "⊑" 50)
  assumes refl:    "x ⊑ x"
      and trans:   "⟦x ⊑ y; y ⊑ z⟧ ⟹ x ⊑ z"
      and antisim: "⟦x ⊑ y; y ⊑ x⟧ ⟹ x = y"

text Los teoremas se diferencian por el nombre y el ámbito. 
  Por ejemplo,
    refl: ?x  ?x
    Orden.refl: Orden ?menor_ig  ?menor_ig ?x ?x
    Orden_def: Orden ?menor_ig 
               (x. ?menor_ig x x) 
               (x y z. ?menor_ig x y  ?menor_ig y z  ?menor_ig x z) 
               (x y. ?menor_ig x y  ?menor_ig y x  x = y)


thm refl
thm Orden.refl
thm Orden_def

text Un orden lineal es un orden en el que todos los pares de elementos son 
  comparables.

locale OrdenLineal = Orden +
  assumes lineal: "x ⊑ y ∨ y ⊑ x"

text Los boooleanos está ordenados con el condicional.

interpretation Orden_imp: Orden "λx y. x ⟶ y"
proof
  fix P show "P ⟶ P" by simp
next
  fix P Q R show "P ⟶ Q ⟹ Q ⟶ R ⟹ P ⟶ R" by simp
next
  fix P Q show "P ⟶ Q ⟹ Q ⟶ P ⟹ P = Q" by blast
qed

text Los naturales con la relación de divisibilidad es un conjunto 
  ordenado.

interpretation Orden_dvd: Orden "(dvd) :: nat ⇒ nat ⇒ bool"
proof 
  fix x :: nat
  show "x dvd x" by simp
next
  fix x y z :: nat
  show "⟦x dvd y; y dvd z⟧ ⟹ x dvd z" by auto 
next
  fix x y :: nat
  show "⟦x dvd y; y dvd x⟧ ⟹ x = y" by auto
qed

section Semigrupos, monoides y grupos

subsection Definición de clases

text Un semigrupo es una estructura compuesta por un conjunto A y una
  operación binaria en A.

class semigrupo =
  fixes mult :: "'a ⇒ 'a ⇒ 'a" (infixl "⊗" 70) 
  assumes asoc: "(x ⊗ y) ⊗ z = x ⊗ (y ⊗ z )"

subsection Instanciación de clases

text Los enteros con la suma forman un semigrupo.

instantiation int :: semigrupo 
begin 
definition 
  mult_int_def: "i ⊗ j = i + (j ::int)" 

instance proof 
  fix i j k :: "int" 
  have "(i + j ) + k = i + (j + k)" by simp 
  then show "(i ⊗ j ) ⊗ k = i ⊗ (j ⊗ k)" unfolding mult_int_def . 
qed 
end 

text Los naturales con la suma forman un semigrupo.

instantiation nat :: semigrupo 
begin 
fun mult_nat where 
  "(0::nat) ⊗ n = n" 
| "Suc m ⊗ n = Suc (m ⊗ n)" 

instance proof 
  fix m n q :: "nat" 
  show "m ⊗ n ⊗ q = m ⊗ (n ⊗ q)" 
    by (induct m) auto
qed 
end

subsection Instancias recursivas

text Si (A,) y (B,) son semigrupos, entonces ((A×B,), donde el 
  producto se define por 
     (x,y)(x',y') = (xx',yy'),
  es un semigrupo.
 
instantiation prod :: (semigrupo, semigrupo) semigrupo 
begin 

definition 
  mult_prod_def : "p1 ⊗ p2 = (fst p1 ⊗ fst p2, snd p1 ⊗ snd p2)" 

instance proof 
  fix p1 p2 p3 :: "'a::semigrupo × 'b::semigrupo" 
  show "(p1 ⊗ p2) ⊗ p3 = p1 ⊗ (p2 ⊗ p3)" 
    unfolding mult_prod_def by (simp add: asoc) 
qed 
end

subsection Subclases

text  Un monoide izquierdo es un semigrupo con elemento neutro por la 
  izquierda.

class monoideI = semigrupo + 
  fixes neutro :: "'a" ("𝟭") 
  assumes neutroI: "𝟭 ⊗ x = x"

text Los naturales y los enteros con la suma forman monoides por la 
  izquierda.

instantiation nat and int :: monoideI 
begin 

definition 
  neutro_nat_def : "𝟭 = (0::nat)" 

definition 
  neutro_int_def : "𝟭 = (0::int)" 

instance proof 
  fix n :: nat 
  show "𝟭 ⊗ n = n" unfolding neutro_nat_def by simp
next 
  fix k :: int 
  show "𝟭 ⊗ k = k" unfolding neutro_int_def mult_int_def by simp 
qed 
end

text El producto de dos monoides por la izquierda es un monoide por la
  izquierda, donde el neutro es el par formado por los elementos 
  neutros.

instantiation prod :: (monoideI , monoideI) monoideI 
begin 

definition 
  neutro_prod_def : "𝟭 = (𝟭, 𝟭)" 

instance proof 
  fix p :: "'a::monoideI × 'b::monoideI" 
  show "𝟭 ⊗ p = p" 
    unfolding neutro_prod_def mult_prod_def by (simp add: neutroI) 
qed 
end

text Un monoide es un monoide por la izquierda cuyo elemento neutro 
  por la izquierda lo es también por la derecha.

class monoide = monoideI + 
  assumes neutro: "x ⊗ 𝟭 = x" 

text Los naturales y los enteros con la suma son monoides.

instantiation nat and int :: monoide 
begin 

instance proof 
  fix n :: nat 
  show "n ⊗ 𝟭 = n" 
    unfolding neutro_nat_def by (induct n) simp_all 
next 
  fix k :: int 
  show "k ⊗ 𝟭 = k" 
    unfolding neutro_int_def mult_int_def by simp 
qed
end

text El producto de dos monoides es un monoide.

instantiation prod :: (monoide, monoide) monoide 
begin 

instance proof 
  fix p :: "'a::monoide × 'b::monoide" 
  show "p ⊗ 𝟭 = p" 
    unfolding neutro_prod_def mult_prod_def by (simp add: neutro) 
qed 
end

text Un grupo es un monoide por la izquierda tal que todo elemento 
  posee un inverso por la izquierda.

class grupo2 = monoideI + 
  fixes inverso :: "'a ⇒ 'a" ("(_⇧-⇧1)" [1000] 999)
  assumes inversoI: "x⇧-⇧1 ⊗ x = 𝟭" 

text Los enteros con la suma forman un grupo.

instantiation int :: grupo2 
begin 

definition
  inverso_int_def: "i⇧-⇧1 = -(i::int)"

instance proof 
  fix i :: "int" 
  have "-i + i = 0" by simp 
  then show "i⇧-⇧1 ⊗ i = 𝟭" 
    unfolding mult_int_def neutro_int_def inverso_int_def . 
qed 
end

subsection Razonamiento abstracto

text En los grupos se verifica la propiedad cancelativa por la 
  izquierda, i.e.
     x  y = x  z  y = z


lemma (in grupo2) cancelativa_izq: "x ⊗ y = x ⊗ z ⟷ y = z" 
proof 
  assume "x ⊗ y = x ⊗ z"
  then have "x⇧-⇧1 ⊗ (x ⊗ y) = x⇧-⇧1 ⊗ (x ⊗ z)" 
    by simp 
  then have "(x⇧-⇧1 ⊗ x) ⊗ y = (x⇧-⇧1 ⊗ x) ⊗ z" 
    using asoc by simp 
  then show "y = z" 
    using neutroI and inversoI by simp
next 
  assume "y = z" 
  then show "x ⊗ y = x ⊗ z" 
    by simp
qed

thm grupo2.cancelativa_izq

text Se genera el teorema grupo.cancelativa_izq
     class.grupo2 ?mult ?neutro ?inverso  
     (?mult ?x ?y = ?mult ?x ?z) = (?y = ?z)

  El teorema se aplica automáticamente a todas las instancias de la 
  clase grupo. Por ejemplo, a los enteros.

subsection Definiciones derivadas

text En los monoides se define la potencia natural por
  · x^0     = 1
  · x^{n+1} = x*x^n


fun (in monoide) potencia_nat :: "nat ⇒ 'a ⇒ 'a" where 
  "potencia_nat 0 x       = 𝟭"  
| "potencia_nat (Suc n) x = x ⊗ potencia_nat n x"

subsection Analogía entre clases y functores

text Las listas con la operación de concatenación y la lista vacía 
  como elemento neutro forman un monoide.

interpretation list_monoide: monoide "append" "[]"
proof 
  show "⋀x y z. (x @ y) @ z = x @ (y @ z)" by simp
next
  show "⋀x. [] @ x = x" by simp
next
  show "⋀x. x @ [] = x" by simp
qed

text Se pueden aplicar propiedades de los monides a las listas. Por 
  ejemplo,

lemma "append [] xs = xs"
  by simp

text (repite n xs) es la lista obtenida concatenando n veces la lista 
  xs.

fun repite :: "nat ⇒ 'a list ⇒ 'a list" where 
  "repite 0 _        = []"
| "repite (Suc n) xs = xs @ repite n xs"

text Las listas con la operación de concatenación y la lista vacía como elemento
  neutro forman un monoide. Además, la potencia natural se intepreta 
  como repite.

interpretation list_monoide: monoide "append" "[]" rewrites
  "monoide.potencia_nat append [] = repite" 
proof -
  interpret monoide "append" "[]" .. 
  show "monoide.potencia_nat append [] = repite" 
  proof 
    fix n 
    show "monoide.potencia_nat append [] n = repite n"
      by (induct n) auto 
  qed 
qed intro_locales

subsection Relaciones de subclase adicionales

text Los grupos son monoides.

subclass (in grupo2) monoide 
proof 
  fix x 
  have "x⇧-⇧1 ⊗ (x ⊗ 𝟭) = x⇧-⇧1 ⊗ (x ⊗ (x⇧-⇧1 ⊗ x))" 
    using inversoI by simp
  also have "… = (x⇧-⇧1 ⊗ x) ⊗ (x⇧-⇧1 ⊗ x)" 
    using asoc [symmetric] by simp
  also have "… = 𝟭 ⊗ (x⇧-⇧1 ⊗ x)" 
    using inversoI by simp
  also have "… = x⇧-⇧1 ⊗ x" 
    using neutroI by simp
  finally have "x⇧-⇧1 ⊗ (x ⊗ 𝟭) = x⇧-⇧1 ⊗ x" 
    by this
  then show "x ⊗ 𝟭 = x" 
    using cancelativa_izq by simp
qed

text La potencia entera en los grupos se define a partir de la potencia 
  natural como sigue:
  · x^k = x^k si k  0
  · x^k = (x^{-k})^{-1}, en caso contrario.


definition (in grupo2) potencia_entera :: "int ⇒ 'a ⇒ 'a" where 
  "potencia_entera k x = 
   (if k >= 0 
    then potencia_nat (nat k) x 
    else (potencia_nat (nat (- k)) x)⇧-⇧1)"

section Bibliografía

text 
  + "Haskell-style type classes with Isabelle/Isar" ~ F. Haftmann.
    http://bit.ly/2E55pAJ
  + "Tutorial to locales and locale interpretation" ~ C. Ballarin.
    http://bit.ly/2E3ozXB  


end