Desarrollo de teorías formalizadas con Isabelle/HOL
De Lógica matemática y fundamentos (2018-19)
Revisión del 17:20 20 may 2020 de Jalonso (discusión | contribuciones)
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') = (x⊗x',y⊗y'),
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