theory Herstein
 imports "HOL-Algebra.Algebra"
begin

(*
problem_number:2_1_18
natural language statement:
If $G$ is a finite group of even order, show that there must be an element $a \neq e$ such that $a=a^{-1}$.
lean statement:
theorem exercise_2_1_18 {G : Type*} [group G]
  [fintype G] (hG2 : even (fintype.card G)) :
  \<exists> (a : G), a \<noteq> \<one> \<and> a = inv a :=

codex statement:
theorem exists_inv_eq_of_even_order:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "finite (carrier G)" "order G mod 2 = 0"
  shows "\<exists>a\<in>carrier G. a \<noteq> \<one> \<and> a = inv a"
Our comment on the codex statement: pretty good but needs a locale context, like most of the others
 *)
theorem (in group) exercise_2_1_18:
  assumes "finite (carrier G)" "even (order G)"
  shows "\<exists>a\<in>carrier G. a \<noteq> \<one> \<and> a = inv a"
  oops

(*
problem_number:2_1_21
natural language statement:
Show that a group of order 5 must be abelian.
lean statement:
theorem exercise_2_1_21 (G : Type* ) [group G] [fintype G]
  (hG : card G = 5) :
  comm_group G :=

codex statement:
theorem abelian_of_order_5:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "order G = 5"
  shows "abelian G"
Our comment on the codex statement: "abelian" is undefined (use comm_group)
 *)
theorem (in group) exercise_2_1_21:
  assumes "group G" "order G = 5"
  shows "comm_group G"
  oops

(*
problem_number:2_1_26
natural language statement:
If $G$ is a finite group, prove that, given $a \in G$, there is a positive integer $n$, depending on $a$, such that $a^n = e$.
lean statement:
theorem exercise_2_1_26 {G : Type*} [group G]
  [fintype G] (a : G) : \<exists> (n : \<nat>), a ^ n = \<one> :=

codex statement:
theorem exists_nat_pow_eq_one_of_finite_group:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "finite (carrier G)"
  shows "\<exists>n. a [^] n = \<one>"
Our comment on the codex statement: Needs locale group; also n needs to be positive
 *)
theorem (in group) exercise_2_1_26:
  assumes "finite (carrier G)"
  shows "\<exists>n>0. a [^] n = \<one>"
  oops

(*
problem_number:2_1_27
natural language statement:
If $G$ is a finite group, prove that there is an integer $m > 0$ such that $a^m = e$ for all $a \in G$.
lean statement:
theorem exercise_2_1_27 {G : Type*} [group G]
  [fintype G] : \<exists> (m : \<nat>), \<forall> (a : G), a ^ m = \<one> :=

codex statement:
theorem exists_nat_pow_eq_one_of_finite_group:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "finite (carrier G)"
  shows "\<exists>m::nat. \<forall>a\<in>carrier G. a [^] m = \<one>"
Our comment on the codex statement: Needs locale group; also m needs to be positive
 *)
theorem (in group) exercise_2_1_27:
  assumes "finite (carrier G)"
  shows "\<exists>m>0. \<forall>a\<in>carrier G. a [^] m = \<one>"
  oops

(*
problem_number:2_2_3
natural language statement:
If $G$ is a group in which $(a b)^{i}=a^{i} b^{i}$ for three consecutive integers $i$, prove that $G$ is abelian.
lean statement:
theorem exercise_2_2_3 {G : Type*} [group G]
  {P : \<nat> \<rightarrow> Prop} {hP : P = \<lambda> i, \<forall> a b : G, (a*b)^i = a^i * b^i}
  (hP1 : \<exists> n : \<nat>, P n \<and> P (n+1) \<and> P (n+2)) : comm_group G :=

codex statement:
theorem abelian_of_consecutive_powers_eq:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "\<forall>a b. (a * b) [^] (i::nat) = a [^] i * b [^] i" "i+1\<in>{i, i+1, i+2}"
  shows "comm_group G"
Our comment on the codex statement: the English version is ambiguous and the codex version is scrambled
 *)
theorem (in group) exercise_2_2_3:
  defines "P \<equiv> \<lambda>i::nat. \<forall>a b. (a \<otimes> b) [^] i = a [^] i \<otimes> b [^] i"
  assumes "P i" "P(Suc i)" "P(Suc(Suc i))"
  shows "comm_group G"
  oops

(*
problem_number:2_2_5
natural language statement:
Let $G$ be a group in which $(a b)^{3}=a^{3} b^{3}$ and $(a b)^{5}=a^{5} b^{5}$ for all $a, b \in G$. Show that $G$ is abelian.
lean statement:
theorem exercise_2_2_5 {G : Type*} [group G]
  (h : \<forall> (a b : G), (a * b) ^ 3 = a ^ 3 * b ^ 3 \<and> (a * b) ^ 5 = a ^ 5 * b ^ 5) :
  comm_group G :=

codex statement:
theorem abelian_of_power_eq_power:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "\<forall>a b. (a * b)^3 = a^3 * b^3" "\<forall>a b. (a * b)^5 = a^5 * b^5"
  shows "comm_group G"
Our comment on the codex statement: good but needs the group locale
 *)
theorem (in group) exercise_2_2_5:
  defines "P \<equiv> \<lambda>i::nat. \<forall>a b. (a \<otimes> b) [^] i = a [^] i \<otimes> b [^] i"
  assumes "P 3" "P 5"
  shows "comm_group G"
  oops

(*
problem_number:2_2_6c
natural language statement:
Let $G$ be a group in which $(a b)^{n}=a^{n} b^{n}$ for some fixed integer $n>1$ for all $a, b \in G$.
For all $a, b \in G$, prove that $\left(a b a^{-1} b^{-1}\right)^{n(n-1)}=e$.
lean statement:
theorem exercise_2_2_6c {G : Type*} [group G] {n : \<nat>} (hn : n > 1)
  (h : \<forall> (a b : G), (a * b) ^ n = a ^ n * b ^ n) :
  \<forall> (a b : G), (a * b * inv a * inv b) ^ (n * (n - 1)) = 1 :=

codex statement:
theorem power_of_commutator_eq_one:
  fixes G::"('a, 'b) monoid_scheme" (structure) and a b::'a
  assumes "group G" "\<forall>a b. (a * b) [^] n = a [^] n * b [^] n" "n > 1"
  shows "(a * b * a [^] -1 * b [^] -1) [^] (n * (n - 1)) = \<one>"
Our comment on the codex statement: Mainly it's * versus \<otimes>
 *)
theorem (in group) exercise_2_2_6c:
  assumes "\<forall>a b. (a \<otimes> b) [^] n = a [^] n \<otimes> b [^] n" and "n > 1"
  shows "(a \<otimes> b \<otimes> inv a \<otimes> inv b) [^] (n * (n - 1)) = \<one>"
  oops

(*
problem_number:2_3_17
natural language statement:
If $G$ is a group and $a, x \in G$, prove that $C\left(x^{-1} a x\right)=x^{-1} C(a) x$
lean statement:
theorem exercise_2_3_17 {G : Type*} [has_mul G] [group G] (a x : G) :
  set.centralizer {inv x*a*x} =
  (\<lambda> g : G, inv x*g*x) '' (set.centralizer {a}) :=

codex statement:
theorem conjugate_of_conjugate_eq_conjugate:
  fixes G::"('a, 'b) monoid_scheme" (structure) and a x::'a
  assumes "group G"
  shows "conjugate x (conjugate x a) = conjugate x a"
Our comment on the codex statement: CENTRALISER NOT AVAILABLE IN HOL-ALGEBRA
 *)
theorem (in group) exercise_2_3_17: undefined oops

(*
problem_number:2_3_19
natural language statement:
If $M$ is a subgroup of $G$ such that $x^{-1} M x \subset M$ for all $x \in G$, prove that actually $x^{-1} M x=M$.
lean statement:
theorem exercise_2_3_19 {G : Type*} [group G] {M : subgroup G}
  (hM : \<forall> (x : G), (\<lambda> g : G, inv x*g*x) '' M \<subset> M) :
  \<forall> x : G, (\<lambda> g : G, inv x*g*x) '' M = M :=

codex statement:
theorem subgroup_of_conjugate_subset_is_conjugate:
  fixes G::"('a, 'b) monoid_scheme" (structure) and M::"'a set"
  assumes "group G" "subgroup M G" "\<forall>x\<in>carrier G. inv x * M * x \<subseteq> M"
  shows "\<forall>x\<in>carrier G. inv x * M * x = M"
Our comment on the codex statement: locale group needed
 *)
theorem (in group) exercise_2_3_19:
  assumes "\<forall>x\<in>carrier G. inv x <# H #> x \<subseteq> H" "subgroup H G"
  shows "\<forall>x\<in>carrier G. inv x <# H #> x = H"
  oops

(*
problem_number:2_3_16
natural language statement:
If a group $G$ has no proper subgroups, prove that $G$ is cyclic of order $p$, where $p$ is a prime number.
lean statement:
theorem exercise_2_3_16 {G : Type*} [group G]
  (hG : \<forall> H : subgroup G, H = \<top> \<or> H = \<bot>) :
  is_cyclic G \<and> \<exists> (p : \<nat>) (fin : fintype G), nat.prime p \<and> @card G fin = p :=

codex statement:
theorem cyclic_of_prime_order_of_no_proper_subgroups:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "\<forall>H. subgroup H G \<rightarrow> H = G \<or> H = {\<one>}"
  shows "\<exists>p. prime p \<and> order G = p"
Our comment on the codex statement: "prime" has multiple meanings: Divisibility defines "prime" for groups!
          Doesn't G have to be finite?
 *)
theorem (in group) exercise_2_3_16:
  assumes "\<And>H. subgroup H G \<Longrightarrow> H = carrier G \<or> H = {\<one>}"
  shows "cyclic_group G" "\<exists>p. Factorial_Ring.prime p \<and> order G = p"
  oops

(*
problem_number:2_3_21
natural language statement:
If $A, B$ are subgroups of $G$ such that $b^{-1} Ab \subset A$ for all $b \in B$, show that $AB$ is a subgroup of $G$.
lean statement:

codex statement:
theorem subgroup_of_subgroup_conjugate_subset:
  fixes A B::"'a::group_add set"
  assumes "subgroup A G" "subgroup B G" "\<forall>b\<in>B. inv b * A * b \<subseteq> A"
  shows "subgroup (A + B) G"
Our comment on the codex statement: product of sets operator
 *)
theorem (in group) exercise_2_3_21:
  assumes "subgroup A G" "subgroup B G" "\<forall>b\<in> B. inv b <# A #> b \<subseteq> A"
  shows "subgroup (A<#>B) G"
  oops

(*
problem_number:2_3_22
natural language statement:
If $A$ and $B$ are finite subgroups, of orders $m$ and $n$, respectively, of the abelian group $G$, prove that $AB$ is a subgroup of order $mn$ if $m$ and $n$ are relatively prime.
lean statement:

codex statement:
theorem order_of_product_of_finite_subgroups_is_product_of_orders:
  fixes A B::"'a::group_add set"
  assumes "finite A" "finite B" "subgroup A G" "subgroup B G" "\<forall>x\<in>A. \<forall>y\<in>B. x+y\<in>A \<or> x+y\<in>B"
  shows "card (A+B) = card A * card B"
Our comment on the codex statement: need locale comm_group and set product operators
 *)
theorem (in comm_group) exercise_2_3_22:
  assumes "finite A" "finite B" "subgroup A G" "subgroup B G" "coprime (card A) (card B)"
  shows "subgroup (A<#>B) G" "card (A<#>B) = card A * card B"
  oops

(*
problem_number:2_3_28
natural language statement:
Let $M, N$ be subgroups of $G$ such that $x^{-1}Mx \subset M$ and $x^{-1} N x \subset N$ for all $x \in G$. Prove that $MN$ is a subgroup of $G$ and that $x^{-1} (MN)x \subset MN$ for all $x \in G$.
lean statement:

codex statement:
theorem subgroup_of_conjugate_subgroups:
  fixes G::"('a, 'b) monoid_scheme" (structure) and M N::"'a set"
  assumes "group G" "subgroup M G" "subgroup N G" "\<forall>x\<in>G. inv x * M * x \<subseteq> M" "\<forall>x\<in>G. inv x * N * x \<subseteq> N"
  shows "subgroup (M * N) G" "\<forall>x\<in>G. inv x * (M * N) * x \<subseteq> M * N"
Our comment on the codex statement: need locale group and set product operators
 *)
theorem (in group) exercise_2_3_28:
  assumes "subgroup M G" "\<forall>x\<in>carrier G. inv x <# M #> x \<subseteq> M"
  assumes "subgroup N G" "\<forall>x\<in>carrier G. inv x <# N #> x \<subseteq> N"
  shows "subgroup (M<#>N) G" "\<forall>x\<in>carrier G. inv x <# (M<#>N) #> x \<subseteq> (M<#>N)"
  oops

(*
problem_number:2_3_29
natural language statement:
If $M$ is a subgroup of $G$ such that $x^{-1}Mx \subset M$ for all $x \in G$, prove that actually $x^{-1}Mx = M$.
lean statement:

codex statement:
theorem subgroup_of_conjugate_subset_is_conjugate:
  fixes G::"('a, 'b) monoid_scheme" (structure) and M::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "subgroup M G" "\<forall>x\<in>carrier G. inv x * M * x \<subseteq> M"
  shows "\<forall>x\<in>carrier G. inv x * M * x = M"
Our comment on the codex statement: locale group; set product operators
 *)
theorem (in group) exercise_2_3_29:
  assumes "\<forall>x\<in>carrier G. inv x <# H #> x \<subseteq> H" "subgroup H G"
  shows "\<forall>x\<in>carrier G. inv x <# H #> x = H"
  oops

(*
problem_number:2_4_8
natural language statement:
If every right coset of $H$ in $G$ is a left coset of $H$ in $G$, prove that $aHa^{-1} = H$ for all $a \in G$.
lean statement:

codex statement:
theorem right_coset_eq_left_coset_of_H_in_G_of_all_a_in_G:
  fixes G::"('a, 'b) monoid_scheme" (structure) and H::"('a, 'b) submonoid" (structure)
  assumes "group G" "subgroup H G" "\<forall>a\<in>carrier G. right_coset H a = left_coset H a"
  shows "\<forall>a\<in>carrier G. a * H * inv a = H"
Our comment on the codex statement: A different interpretation of the ambiguous text
 *)
theorem (in group) exercise_2_4_8:
  assumes "rcosets H \<subseteq> lcosets H" "subgroup H G"
  shows "\<forall>x\<in>carrier G. x <# H #> inv x = H"
  oops

(*
problem_number:2_4_26
natural language statement:
Let $G$ be a group, $H$ a subgroup of $G$, and let $S$ be the set of all distinct right cosets of $H$ in $G$, $T$ the set of all left cosets of $H$ in $G$. Prove that there is a 1-1 mapping of $S$ onto $T$.
lean statement:

codex statement:
theorem exists_bijective_of_right_left_cosets:
  fixes G::"('a, 'b) monoid_scheme" (structure) and H::"('a, 'b) submonoid" (structure)
  assumes "group G" "subgroup H G"
  shows "\<exists>f. bij_betw f (right_cosets H G) (left_cosets H G)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem (in group) exercise_2_4_26:
  assumes "subgroup H G"
  shows "\<exists>f. bij_betw f (rcosets H) (lcosets H)"
  oops

(*
problem_number:2_4_32
natural language statement:
Let $G$ be a finite group, $H$ a subgroup of $G$. Let $f(a)$ be the least positive $m$ such that $a^m \in H$. Prove that $f(a) \mid o(a)$, where $o(a)$ is an order of $a$.
lean statement:

codex statement:
theorem order_of_element_divides_order_of_subgroup:
  fixes G::"('a, 'b) monoid_scheme" (structure) and H::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "subgroup H G" "finite_group G" "a \<in> carrier G"
  shows "order G a | order H a"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem (in group) exercise_2_4_32:
  assumes "finite (carrier G)" "subgroup H G"
  defines "f \<equiv> \<lambda>a. LEAST m. a [^] m \<in> H"
  shows "\<forall>x\<in>carrier G. f x dvd ord x"
  oops

(*
problem_number:2_4_36
natural language statement:
If $a > 1$ is an integer, show that $n \mid \varphi(a^n - 1)$, where $\phi$ is the Euler $\varphi$-function.
lean statement:
theorem exercise_2_4_36 {a n : \<nat>} (h : a > 1) :
  n | (a ^ n - 1).totient :=

codex statement:
theorem divides_phi_of_int_succ_one_power_int_sub_one:
  fixes a::int
  assumes "a > 1"
  shows "\<forall>n::nat. n | phi (a^n - 1)"
Our comment on the codex statement: Needs the theory HOL-Number_Theory.Totient
 *)
theorem exercise_2_4_36: undefined oops

(*
problem_number:2_5_6
natural language statement:
Prove that if $\varphi \colon G \rightarrow G'$ is a homomorphism, then $\varphi(G)$, the image of $G$, is a subgroup of $G'$.
lean statement:

codex statement:
theorem image_of_homomorphism_is_subgroup:
  fixes G G'::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "group G'" "\<forall>x y. \<exists>z. z \<in> carrier G \<and> \<exists>z'. z' \<in> carrier G' \<and> f z = z' \<and> f (x * y) = f x * f y"
  shows "subgroup (f ` carrier G) G'"
Our comment on the codex statement: use locale group_hom
 *)
theorem (in group_hom) exercise_2_5_6:
  shows "subgroup (h ` carrier G) H"
  using img_is_subgroup by blast

(*
problem_number:2_5_23
natural language statement:
Let $G$ be a group such that all subgroups of $G$ are normal in $G$. If $a, b \in G$, prove that $ba = a^jb$ for some $j$.
lean statement:
theorem exercise_2_5_23 {G : Type*} [group G]
  (hG : \<forall> (H : subgroup G), H.normal) (a b : G) :
  \<exists> (j : \<int>) , b*a = a^j * b:=

codex statement:
theorem exists_j_of_subgroup_normal:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "\<forall>H. subgroup H G \<rightarrow> normal_subgroup H G" "a \<in> carrier G" "b \<in> carrier G"
  shows "\<exists>j. b * a = a [^] j * b"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem (in group) exercise_2_5_23:
  assumes "\<And>H. subgroup H G \<Longrightarrow> normal H G"
  shows "\<forall>a\<in>carrier G. \<forall>b\<in>carrier G. \<exists>j. b \<otimes> a = a [^] j \<otimes> b"
  oops

(*
problem_number:2_5_30
natural language statement:
Suppose that $|G| = pm$, where $p \nmid m$ and $p$ is a prime. If $H$ is a normal subgroup of order $p$ in $G$, prove that $H$ is characteristic.
lean statement:
theorem exercise_2_5_30 {G : Type*} [group G] [fintype G]
  {p m : \<nat>} (hp : nat.prime p) (hp1 : \<not> p | m) (hG : card G = p*m)
  {H : subgroup G} [fintype H] [H.normal] (hH : card H = p):
  characteristic H :=

codex statement:
theorem characteristic_of_order_prime_power_div_order_prime:
  fixes G::"('a, 'b) monoid_scheme" (structure) and H::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "group H" "order G = p * m" "prime p" "p | m" "order H = p" "H \<subseteq> G" "normal G H"
  shows "char G H"
Our comment on the codex statement: Locale. And no need for m (also in the problem statement)
 *)
theorem (in group) exercise_2_5_30:
  fixes p::nat
  assumes "normal N G" "card N = p" "Factorial_Ring.prime p" "finite (carrier G)" "p dvd order G"
  shows "char N G"
  oops

(*
problem_number:2_5_31
natural language statement:
Suppose that $G$ is an abelian group of order $p^nm$ where $p \nmid m$ is a prime.  If $H$ is a subgroup of $G$ of order $p^n$, prove that $H$ is a characteristic subgroup of $G$.
lean statement:
theorem exercise_2_5_31 {G : Type*} [comm_group G] [fintype G]
  {p m n : \<nat>} (hp : nat.prime p) (hp1 : \<not> p | m) (hG : card G = p^n*m)
  {H : subgroup G} [fintype H] (hH : card H = p^n) :
  characteristic H :=

codex statement:
theorem characteristic_of_abelian_group_of_order_p_power_n_times_m:
  fixes G::"('a, 'b) monoid_scheme" (structure) and H::"('a, 'b) monoid_scheme" (structure)
  assumes "abelian_group G" "order G = p^n * m" "prime p" "coprime m p" "order H = p^n" "subgroup H G"
  shows "char_subgroup H G"
Our comment on the codex statement: problem statement can be simplified
 *)
theorem (in comm_group) exercise_2_5_31:
  fixes p::nat
  assumes "subgroup H G" "card H = p^n" "Factorial_Ring.prime p" "finite (carrier G)" "p^n dvd order G"
  shows "char H G"
  oops

(*
problem_number:2_5_37
natural language statement:
If $G$ is a nonabelian group of order 6, prove that $G \simeq S_3$.
lean statement:
theorem exercise_2_5_37 (G : Type* ) [group G] [fintype G]
  (hG : card G = 6) (hG' : is_empty (comm_group G)) :
  G \<cong> equiv.perm (fin 3) :=

codex statement:
theorem nonabelian_group_of_order_6_is_isomorphic_to_S3:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "order G = 6" "\<not> abelian G"
  shows "G \<cong> (permutations (UNIV::'a set))"
Our comment on the codex statement: comm_group not abelian
 *)
theorem exercise_2_5_37: undefined oops
theorem (in group) exercise_2_5_37:
  assumes "order G = 6" "\<not> comm_group G"
  shows "G \<cong> sym_group 3"
  oops

(*
problem_number:2_5_43
natural language statement:
Prove that a group of order 9 must be abelian.
lean statement:
theorem exercise_2_5_43 (G : Type* ) [group G] [fintype G]
  (hG : card G = 9) :
  comm_group G :=

codex statement:
theorem abelian_of_order_9:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "order G = 9"
  shows "abelian G"
Our comment on the codex statement: comm_group not abelian
 *)
theorem exercise_2_5_43: undefined oops
theorem (in group) exercise_2_5_43:
  assumes "order G = 9"
  shows "comm_group G"
  oops

(*
problem_number:2_5_44
natural language statement:
Prove that a group of order $p^2$, $p$ a prime, has a normal subgroup of order $p$.
lean statement:
theorem exercise_2_5_44 {G : Type*} [group G] [fintype G] {p : \<nat>}
  (hp : nat.prime p) (hG : card G = p^2) :
  \<exists> (N : subgroup G) (fin : fintype N), @card N fin = p \<and> N.normal :=

codex statement:
theorem exists_normal_subgroup_of_order_prime_power:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "order G = p^2" "normalization_semidom_class.prime p"
  shows "\<exists>H. subgroup H G \<and> order H = p"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem (in group) exercise_2_5_44:
  fixes p::nat
  assumes "order G = p^2" "Factorial_Ring.prime p"
  shows "\<exists>N. normal N G \<and> card N = p"
  oops

(*
problem_number:2_5_52
natural language statement:
Let $G$ be a finite group and $\varphi$ an automorphism of $G$ such that $\varphi(x) = x^{-1}$ for more than three-fourths of the elements of $G$. Prove that $\varphi(y) = y^{-1}$ for all $y \in G$, and so $G$ is abelian.
lean statement:
theorem exercise_2_5_52 {G : Type*} [group G] [fintype G]
  (\<phi> : G \<cong>* G) {I : finset G} (hI : \<forall> x \<in> I, \<phi> x = inv x)
  (hI1 : 0.75 * card G \<le> card I) :
  \<forall> x : G, \<phi> x = inv x \<and> \<forall> x y : G, x*y = y*x :=

codex statement:
theorem abelian_of_inverse_of_automorphism_of_finite_group:
  fixes G::"'a::group_add monoid"
  assumes "finite (carrier G)" "\<exists>\<phi>. automorphism G \<phi> \<and> (\<forall>x\<in>carrier G. \<phi> x = inv x)"
  shows "abelian G"
Our comment on the codex statement: It's wrong, e.g. no 3/4 and wrong conclusion
 *)
theorem (in group) exercise_2_5_52:
  assumes "finite (carrier G)" "\<phi> \<in> iso G G"
  defines "INV \<equiv> {x \<in> carrier G. \<phi> x = inv x}"
  assumes "card INV > (3/4) * real (order G)"
  shows "\<forall>x\<in> carrier G. \<phi> x = inv x"
  oops

(*
problem_number:2_6_15
natural language statement:
If $G$ is an abelian group and if $G$ has an element of order $m$ and one of order $n$, where $m$ and $n$ are relatively prime, prove that $G$ has an element of order $mn$.
lean statement:
theorem exercise_2_6_15 {G : Type*} [comm_group G] {m n : \<nat>}
  (hm : \<exists> (g : G), order_of g = m)
  (hn : \<exists> (g : G), order_of g = n)
  (hmn : m.coprime n) :
  \<exists> (g : G), order_of g = m * n :=

codex statement:
theorem exists_element_of_order_mul_of_relatively_prime:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "\<forall>n ::nat. x [^] n \<noteq> \<one>" "\<forall>n ::nat. y [^] n \<noteq> \<one>" "coprime m n"
  shows "\<exists>z. z [^] (m*n) = \<one>"
Our comment on the codex statement: Needs to use ord
 *)
theorem (in comm_group) exercise_2_6_15:
  assumes "a \<in> carrier G" "b \<in> carrier G" "coprime (ord a) (ord b)"
  shows "\<exists>x \<in> carrier G. ord x = ord a * ord b"
  oops

(*
problem_number:2_7_3
natural language statement:
Let $G$ be the group of nonzero real numbers under multiplication and let $N = \{1, -1\}$. Prove that $G / N \simeq$ positive real numbers under multiplication.
lean statement:

codex statement:
theorem quotient_group_of_nonzero_real_numbers_isomorphic_positive_real_numbers:
  shows "group_isomorphism (quotient_group (nonzero_real_numbers::real monoid) {1, -1}) (positive_real_numbers::real monoid)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_2_7_3:
  defines "R_group \<equiv>  \<lparr>carrier = UNIV-{0}, monoid.mult = (*), one = (1::real)\<rparr>"
  defines "RP_group \<equiv> \<lparr>carrier = {0<..}, monoid.mult = (*), one = (1::real)\<rparr>"
  shows "R_group Mod {1,-1} \<cong> RP_group"
  oops

(*
problem_number:2_7_7
natural language statement:
If $\varphi$ is a homomorphism of $G$ onto $G'$ and $N \triangleleft G$, show that $\varphi(N) \triangleleft G'$.
lean statement:
theorem exercise_2_7_7 {G : Type*} [group G] {G' : Type*} [group G']
  (\<phi> : G \<rightarrow>* G') (N : subgroup G) [N.normal] :
  (map \<phi> N).normal  :=

codex statement:
theorem normal_of_homomorphism_image:
  fixes G G'::"('a, 'b) monoid_scheme" (structure) and \<phi>::"'a \<Rightarrow> 'a"
  assumes "group G" "group G'" "homomorphism G G' \<phi>" "normal_subgroup N G"
  shows "normal_subgroup (\<phi> '' N) G'"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem (in group_hom) exercise_2_7_7:
  assumes "normal N G"
  shows "normal (h ` N) H"
  oops

(*
problem_number:2_8_7
natural language statement:
If $G$ is a group with subgroups $A, B$ of orders $m, n$, respectively, where $m$ and $n$ are relatively prime, prove that the subset of $G$, $AB = \{ab \mid a \in A, b \in B\}$, has $mn$ distinct elements.
lean statement:

codex statement:
theorem card_prod_of_subgroups_eq_mul_card_of_subgroups:
  fixes G::"('a, 'b) monoid_scheme" (structure) and A B::"'a set"
  assumes "group G" "subgroup A G" "subgroup B G" "coprime (card A) (card B)"
  shows "card (A * B) = card A * card B"
Our comment on the codex statement: Note that the conclusion overlaps with exercise_2_3_22, though not assuming G is abelian
 *)
theorem exercise_2_8_7: undefined oops
theorem (in group) exercise_2_8_7:
  assumes "finite A" "finite B" "subgroup A G" "subgroup B G" "coprime (card A) (card B)"
  shows "card (A<#>B) = card A * card B"
  oops

(*
problem_number:2_8_12
natural language statement:
Prove that any two nonabelian groups of order 21 are isomorphic.
lean statement:
theorem exercise_2_8_12 {G H : Type*} [fintype G] [fintype H]
  [group G] [group H] (hG : card G = 21) (hH : card H = 21)
  (hG1 : is_empty(comm_group G)) (hH1 : is_empty (comm_group H)) :
  G \<cong>* H :=

codex statement:
theorem isomorphic_of_nonabelian_order_21:
  fixes G H::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "group H" "order G = 21" "order H = 21" "\<not> abelian_group G" "\<not> abelian_group H"
  shows "G \<cong> H"
Our comment on the codex statement: Great but for comm_group
 *)
theorem exercise_2_8_12:
  assumes "group G" "group H" "order G = 21" "order H = 21" "\<not> comm_group G" "\<not> comm_group H"
  shows "G \<cong> H"
  oops

(*
problem_number:2_8_15
natural language statement:
Prove that if $p > q$ are two primes such that $q \mid p - 1$, then any two nonabelian groups of order $pq$ are isomorphic.
lean statement:
theorem exercise_2_8_15 {G H: Type*} [fintype G] [group G] [fintype H]
  [group H] {p q : \<nat>} (hp : nat.prime p) (hq : nat.prime q)
  (h : p > q) (h1 : q | p - 1) (hG : card G = p*q) (hH : card G = p*q) :
  G \<cong>* H :=

codex statement:
theorem isomorphic_of_prime_divides_prime_minus_one:
  fixes p q::nat
  assumes "prime p" "prime q" "q > p" "q dvd p - 1"
  shows "\<forall>G H. group G \<and> group H \<and> order G = p * q \<and> order H = p * q \<rightarrow> G \<cong> H"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_2_8_15:
  fixes p q::nat
  assumes "group G" "group H" "order G = p*q" "order H = p*q" "\<not> comm_group G" "\<not> comm_group H"
  assumes "Factorial_Ring.prime p" "Factorial_Ring.prime q" "q dvd (p - 1)"
  shows "G \<cong> H"
  oops

(*
problem_number:2_9_2
natural language statement:
If $G_1$ and $G_2$ are cyclic groups of orders $m$ and $n$, respectively, prove that $G_1 \times G_2$ is cyclic if and only if $m$ and $n$ are relatively prime.
lean statement:
theorem exercise_2_9_2 {G H : Type*} [fintype G] [fintype H] [group G]
  [group H] (hG : is_cyclic G) (hH : is_cyclic H) :
  is_cyclic (G \<times> H) \<Longrightarrow> (card G).coprime (card H) :=

codex statement:
theorem cyclic_of_relatively_prime:
  fixes G1 G2::"('a, 'b) monoid_scheme" (structure)
  assumes "group G1" "group G2" "cyclic G1" "cyclic G2" "\<forall>x\<in>carrier G1. \<forall>y\<in>carrier G2. order x = order y \<rightarrow> x = \<one> \<and> y = \<one>"
  shows "cyclic (G1 \<times> G2)"
Our comment on the codex statement: just wrong
 *)
theorem exercise_2_9_2:
  assumes "group G" "group H" "cyclic_group G" "cyclic_group H" "finite (carrier G)" "finite (carrier H)"
  shows "cyclic_group (G1 \<times>\<times> G2) \<longleftrightarrow> coprime (order G) (order H)"
  oops

(*
problem_number:2_10_1
natural language statement:
Let $A$ be a normal subgroup of a group $G$, and suppose that $b \in G$ is an element of prime order $p$, and that $b \not\in A$. Show that $A \cap (b) = (e)$.
lean statement:
theorem exercise_2_10_1 {G : Type*} [group G] (A : subgroup G)
  [A.normal] {b : G} (hp : nat.prime (order_of b)) :
  A \<sqcap> (closure {b}) = \<bot> :=

codex statement:
theorem trivial_intersection_of_prime_order_element_and_normal_subgroup:
  fixes G::"('a, 'b) monoid_scheme" (structure) and A::"'a set"
  assumes "group G" "normal_subgroup G A" "prime (order b)" "b \<notin> A"
  shows "A \<cap> (carrier (b)) = {\<one>}"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem (in group) exercise_2_10_1:
  assumes "normal N G" "b \<in> carrier G" "b \<notin> N" "Factorial_Ring.prime (ord b)"
  shows "N \<inter> generate G {b} = {\<one>}"
  oops

(*
problem_number:2_11_6
natural language statement:
If $P$ is a $p$-Sylow subgroup of $G$ and $P \triangleleft G$, prove that $P$ is the only $p$-Sylow subgroup of $G$.
lean statement:
theorem exercise_2_11_6 {G : Type*} [group G] {p : \<nat>} (hp : nat.prime p)
  {P : sylow p G} (hP : P.normal) :
  \<forall> (Q : sylow p G), P = Q :=

codex statement:
theorem sylow_subgroup_of_normal_subgroup_is_unique:
  fixes p::nat and G::"('a, 'b) monoid_scheme" (structure)
  assumes "normalization_semidom_class.prime p" "group G" "order G = (p^a) * m" "finite (carrier G)" "subgroup P G" "card P = p^a" "P \<subseteq> carrier G" "P \<subseteq> normalizer G P"
  shows "\<forall>Q. subgroup Q G \<and> card Q = p^a \<rightarrow> Q = P"
Our comment on the codex statement: not bad
 *)
theorem (in group) exercise_2_11_6:
  fixes p::nat
  assumes "Factorial_Ring.prime p" "p^k dvd order G" "\<not> (p * p^k dvd order G)" "normal P G" "card P = p^k"
  shows "\<forall>Q. subgroup Q G \<and> card Q = p^k \<longrightarrow> Q = P"
  oops

(*
problem_number:2_11_7
natural language statement:
If $P \triangleleft G$, $P$ a $p$-Sylow subgroup of $G$, prove that $\varphi(P) = P$ for every automorphism $\varphi$ of $G$.
lean statement:
theorem exercise_2_11_7 {G : Type*} [group G] {p : \<nat>} (hp : nat.prime p)
  {P : sylow p G} (hP : P.normal) :
  characteristic (P : subgroup G) :=

codex statement:
theorem phi_of_sylow_is_sylow:
  fixes G::"('a, 'b) monoid_scheme" (structure) and P::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "normalization_semidom_class.prime p" "p_group P" "p_group G" "p_group.is_Sylow p P G" "group_hom G G \<phi>"
  shows "group_hom P P \<phi>"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem (in group) exercise_2_11_7:
  fixes p::nat
  assumes "Factorial_Ring.prime p" "p^k dvd order G" "\<not> (p ^ Suc k dvd order G)" "normal P G" "card P = p^k" "\<phi> \<in> iso G G"
  shows "\<phi> ` P = P"
  oops

(*
problem_number:2_11_22
natural language statement:
Show that any subgroup of order $p^{n-1}$ in a group $G$ of order $p^n$ is normal in $G$.
lean statement:
theorem exercise_2_11_22 {p : \<nat>} {n : \<nat>} {G : Type*} [fintype G]
  [group G] (hp : nat.prime p) (hG : card G = p ^ n) {K : subgroup G}
  [fintype K] (hK : card K = p ^ (n-1)) :
  K.normal :=

codex statement:
theorem normal_of_order_p_pow_n_minus_1_of_order_p_pow_n:
  fixes G::"('a, 'b) monoid_scheme" (structure)
  assumes "group G" "order G = p^n" "subgroup H G" "order H = p^(n-1)"
  shows "normal H G"
Our comment on the codex statement: every variable called p ranges over primes\<And>
 *)
theorem (in group) exercise_2_11_22:
  fixes p::nat
  assumes "Factorial_Ring.prime p" "subgroup H G" "card H = p^k" "order G = p ^ Suc k"
  shows "normal H G"
  oops

(*
problem_number:3_2_21
natural language statement:
If $\sigma, \tau$ are two permutations that disturb no common element and $\sigma \tau = e$, prove that $\sigma = \tau = e$.
lean statement:
theorem exercise_3_2_21 {\<alpha> : Type*} [fintype \<alpha>] {\<sigma> \<tau>: equiv.perm \<alpha>}
  (h1 : \<forall> a : \<alpha>, \<sigma> a = a \<Longrightarrow> \<tau> a \<noteq> a) (h2 : \<tau> \<circ> \<sigma> = id) :
  \<sigma> = 1 \<and> \<tau> = 1 :=

codex statement:
theorem permutation_of_disturb_no_common_eq_id_eq_id:
  fixes \<sigma>::"'a \<Rightarrow> 'a" and \<tau>::"'a \<Rightarrow> 'a"
  assumes "permutation \<sigma>" "permutation \<tau>" "\<forall>x. \<sigma> x \<noteq> x \<rightarrow> \<tau> x \<noteq> x" "\<sigma> \<circ> \<tau> = id"
  shows "\<sigma> = id \<and> \<tau> = id"
Our comment on the codex statement: wrong
 *)
theorem exercise_3_2_21:
  fixes \<sigma>::"'a \<Rightarrow> 'a" and \<tau>::"'a \<Rightarrow> 'a"
  assumes "permutation \<sigma>" "permutation \<tau>" "{x. \<sigma> x \<noteq> x} \<inter> {x. \<tau> x \<noteq> x} = {}" "\<sigma> \<circ> \<tau> = id"
  shows "\<sigma> = id \<and> \<tau> = id"
  oops

(*
problem_number:3_2_23
natural language statement:
Let $\sigma, \tau$ be two permutations such that they both have decompositions into disjoint cycles of cycles of lengths $m_1, m_2, \ldots, m_k$. Prove that for some permutation $\beta, \tau = \beta \sigma \beta^{-1}$.
lean statement:

codex statement:
theorem exists_permutation_eq_permutation_comp_permutation_inv:
  fixes \<sigma>::"'a perm" and \<tau>::"'a perm"
  assumes "\<sigma> permutes {1..n}" "\<tau> permutes {1..n}" "\<sigma> = (\<prod>i\<in>{1..n}. (\<sigma> i))" "\<tau> = (\<prod>i\<in>{1..n}. (\<tau> i))"
  shows "\<exists>\<beta>. \<tau> = \<beta> \<circ> \<sigma> \<circ> inv \<beta>"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_3_2_23: undefined oops

(*
problem_number:3_3_2
natural language statement:
If $\sigma$ is a $k$-cycle, show that $\sigma$ is an odd permutation if $k$ is even, and is an even permutation if $k$ is odd.
lean statement:

codex statement:
theorem even_permutation_of_even_cycle:
  fixes \<sigma>::"'a::finite perm"
  assumes "\<sigma> = (a_R b_R c_R d_R e_R f_R g_R h_R i_R j_R k_R l_R m_R n_R o_R p_R q_R r_R s_R t_R u_R v_R w_R x_R y_R z_R)"
  shows "evenperm \<sigma>"
Our comment on the codex statement: assumption is crazy, link to evenperm is nice
 *)
theorem exercise_3_3_2:
  shows "evenperm (cycle_of_list l) \<longleftrightarrow> even (length l)"
  oops

(*
problem_number:3_3_9
natural language statement:
If $n \geq 5$ and $(e) \neq N \subset A_n$ is a normal subgroup of $A_n$, show that $N$ must contain a 3-cycle.
lean statement:

codex statement:
theorem exists_three_cycle_of_normal_subgroup_of_An:
  fixes n::nat and N::"'a set"
  assumes "n \<ge> 5" "group_set A_n" "N \<subseteq> carrier A_n" "normal_subgroup A_n N" "N \<noteq> {\<one>}"
  shows "\<exists>a b c. a \<noteq> b \<and> b \<noteq> c \<and> c \<noteq> a \<and> (a, b, c) \<in> N"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem (in group) exercise_3_3_9:
  fixes n::nat
  assumes "normal N (alt_group n)" "card N \<ge> 2" "n \<ge> 5"
  shows "\<exists>x \<in> N. \<exists>l. length l = 3 \<and> x = cycle_of_list l"
  oops

(*
problem_number:4_1_19
natural language statement:
Show that there is an infinite number of solutions to $x^2 = -1$ in the quaternions.
lean statement:
theorem exercise_4_1_19 : infinite {x : quaternion \<real> | x^2 = -1} :=

codex statement:
theorem infinite_solutions_of_quaternion_square_eq_neg_one:
  fixes x::"'a::real_normed_algebra_1"
  assumes "x^2 = -1"
  shows "\<exists>y. y^2 = -1 \<and> y \<noteq> x"
Our comment on the codex statement: We do have quaternions but should we bother to load it just one exercise?
 *)
theorem exercise_4_1_19: undefined oops

(*
problem_number:4_1_28
natural language statement:
Show that $\{x \in R \mid \det x \neq O\}$ forms a group, $G$, under matrix multiplication and that $N = \{x \in R \mid \det x = 1\}$ is a normal subgroup of $G$.
lean statement:

codex statement:
theorem det_neq_zero_is_group:
  fixes R::"('a::{comm_ring_1,ring_no_zero_divisors}^'n) set"
  assumes "\<forall>x\<in>R. det x \<noteq> 0"
  shows "group R"
Our comment on the codex statement:
 *)
theorem exercise_4_1_28: undefined oops

(*
problem_number:4_1_29
natural language statement:
If $x \in R$ is a zero-divisor, show that $\det x = 0$, and, conversely, if $x \neq 0$ is such that $\det x = 0$, then $x$ is a zero-divisor in $R$.
lean statement:

codex statement:
theorem det_eq_zero_of_zero_divisor:
  fixes x::"'a::{comm_ring_1, ring_no_zero_divisors}"
  assumes "x \<noteq> 0" "\<exists>y. y \<noteq> 0 \<and> x * y = 0"
  shows "det x = 0"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_4_1_29: undefined oops

(*
problem_number:4_1_34
natural language statement:
Let $T$ be the group of matrices $A$ with entries in the field $\mathbb{Z}_2$ such that $\det A$ is not equal to 0.
Prove that $T$ is isomorphic to $S_3$, the symmetric group of degree 3.
lean statement:
theorem exercise_4_1_34 : equiv.perm (fin 3) \<cong>* general_linear_group (fin 2) (zmod 2) :=

codex statement:
theorem isomorphic_to_symmetric_group_of_degree_3:
  fixes T::"int matrix set"
  assumes "T = {A. det A \<noteq> 0}"
  shows "T \<cong> (permutations_of_set (UNIV::'a::finite set))"
Our comment on the codex statement: We do have matrices and determinants but again it's a bit much to load them for this one exercise
 *)
theorem exercise_4_1_34: undefined oops

(*
problem_number:4_2_5
natural language statement:
Let $R$ be a ring in which $x^3 = x$ for every $x \in R$. Prove that $R$ is commutative.
lean statement:
theorem exercise_4_2_5 {R : Type*} [ring R]
  (h : \<forall> x : R, x ^ 3 = x) : comm_ring R :=

codex statement:
theorem commutative_of_cube_eq_id:
  fixes R::"'a::ring_1"
  assumes "\<forall>x. x^3 = x"
  shows "comm_ring R"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem (in ring) exercise_4_2_5:
  assumes "\<forall>x \<in> carrier R. x[^]3 = x"
  shows "cring R"
  oops

(*
problem_number:4_2_6
natural language statement:
If $a^2 = 0$ in $R$, show that $ax + xa$ commutes with $a$.
lean statement:
theorem exercise_4_2_6 {R : Type*} [ring R] (a x : R)
  (h : a ^ 2 = 0) : a * (a * x + x * a) = (x + x * a) * a :=

codex statement:
theorem commutes_of_square_zero:
  fixes a x::"'a::ring"
  assumes "a^2 = 0"
  shows "a * x + x * a = a * (x + x)"
Our comment on the codex statement: the operators
 *)
theorem (in ring) exercise_4_2_6:
  assumes "a \<in> carrier R" "a[^]2 = x"
  shows "\<forall>x \<in> carrier R. a \<otimes> (a \<otimes> x \<oplus> x \<otimes> a) = (x \<oplus> x \<otimes> a) \<otimes> a"
  oops

(*
problem_number:4_2_9
natural language statement:
Let $p$ be an odd prime and let $1 + \frac{1}{2} + ... + \frac{1}{p - 1} = \frac{a}{b}$, where $a, b$ are integers. Show that $p \mid a$.
lean statement:
theorem exercise_4_2_9 {p : \<nat>} (hp : nat.prime p) (hp1 : odd p) :
  \<exists> (a b : \<int>), a / b = \<Sum> i in finset.range p, 1 / (i + 1) \<rightarrow>  UP p | a :=

codex statement:
theorem prime_divides_a_of_sum_frac_eq_frac_a_b:
  fixes p::nat and a b::int
  assumes "prime p" "p > 2" "\<Sum>i=1..p-1. 1/(of_nat i) = of_int a / of_int b"
  shows "p dvd a"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_4_2_9:
  fixes p::nat and a b::nat
  assumes "Factorial_Ring.prime p" "p > 2" "(\<Sum>i=1..p-1. 1/(real i)) = real a / real b"
  shows "p dvd a"
oops

(*
problem_number:4_3_1
natural language statement:
If $R$ is a commutative ring and $a \in R$, let $L(a) = \{x \in R \mid xa = 0\}$. Prove that $L(a)$ is an ideal of $R$.
lean statement:
theorem exercise_4_3_1 {R : Type*} [comm_ring R] (a : R) :
  \<exists> I : ideal R, {x : R | x*a=0} = I :=

codex statement:
theorem ideal_of_left_zero_of_commutative_ring:
  fixes R::"'a::comm_ring_1"
  assumes "a\<in>R"
  shows "ideal R (left_zero_of R a)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem (in cring) exercise_4_3_1:
  defines "L \<equiv> \<lambda>a. {x \<in> carrier R. x \<otimes> a = \<zero>}"
  shows "\<forall>a \<in> carrier R. ideal (L a) R"
  oops

(*
problem_number:4_3_4
natural language statement:
If $I, J$ are ideals of $R$, define $I + J$ by $I + J = {i + j \mid i \in I, j \in J}$. Prove that $I + J$ is an ideal of $R$.
lean statement:

codex statement:
theorem sum_ideals_is_ideal:
  fixes R::"'a::comm_ring_1 ring" and I J::"'a set"
  assumes "ideal R I" "ideal R J"
  shows "ideal R (I + J)"
Our comment on the codex statement: not bad
 *)

theorem (in ring) exercise_4_3_4:
  assumes "ideal I R" "ideal J R"
  defines "IJ \<equiv> \<Union>i \<in> I. \<Union>j \<in> J. {i\<oplus>j}"
  shows "ideal IJ R"
  oops

(*
problem_number:4_3_25
natural language statement:
Let $R$ be the ring of $2 \times 2$ matrices over the real numbers; suppose that $I$ is an ideal of $R$. Show that $I = (0)$ or $I = R$.
lean statement:
theorem exercise_4_3_25 (I : ideal (matrix (fin 2) (fin 2) \<real>)) :
  I = \<bot> \<or> I = \<top> :=

codex statement:
theorem ideal_of_2x2_matrix_ring_is_zero_or_ring:
  fixes R::"real mat"
  assumes "ideal R I"
  shows "I = {0} \<or> I = carrier R"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_4_3_25: undefined oops

(*
problem_number:4_4_9
natural language statement:
Show that $(p - 1)/2$ of the numbers $1, 2, \ldots, p - 1$ are quadratic residues and $(p - 1)/2$ are quadratic nonresidues $\mod p$.
lean statement:
theorem exercise_4_4_9 (p : \<nat>) (hp : nat.prime p) :
  \<exists> S : finset (zmod p), S.card = (p-1)/2 \<and> \<exists> x : zmod p, x^2 = p \<and>
  \<exists> S : finset (zmod p), S.card = (p-1)/2 \<and> \<not> \<exists> x : zmod p, x^2 = p :=

codex statement:
theorem quadratic_residues_and_nonresidues_mod_p:
  fixes p::nat
  assumes "prime p"
  shows "card {x. x < p \<and> x^2 == 1 [MOD p]} = (p - 1) div 2"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_4_4_9: undefined oops

(*
problem_number:4_5_12
natural language statement:
If $F \subset K$ are two fields and $f(x), g(x) \in F[x]$ are relatively prime in $F[x]$, show that they are relatively prime in $K[x]$.
lean statement:

codex statement:
theorem relatively_prime_of_relatively_prime_in_subfield:
  fixes F::"'a::field_char_0" and K::"'a::field_char_0"
  assumes "F \<subseteq> K" "poly_relprime F f g"
  shows "poly_relprime K f g"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_4_5_12: undefined oops

(*
problem_number:4_5_16
natural language statement:
Let $F = \mathbb{Z}_p$ be the field of integers $\mod p$, where $p$ is a prime, and let $q(x) \in F[x]$ be irreducible of degree $n$. Show that $F[x]/(q(x))$ is a field having at exactly $p^n$ elements.
lean statement:
theorem exercise_4_5_16 {p n: \<nat>} (hp : nat.prime p)
  {q : polynomial (zmod p)} (hq : irreducible q) (hn : q.degree = n) :
  \<exists> is_fin : fintype $ polynomial (zmod p) / ideal.span ({q} : set (polynomial $ zmod p)),
  @card (polynomial (zmod p) / ideal.span {q}) is_fin = p ^ n \<and>
  is_field (polynomial $ zmod p):=

codex statement:
theorem card_of_quotient_ring_eq_pow_prime:
  fixes p::nat and q::"nat \<Rightarrow> nat"
  assumes "prime p" "irreducible q" "degree q = n"
  shows "card (quotient_ring (poly_ring p) q) = p^n"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_4_5_16: undefined oops

(*
problem_number:4_5_23
natural language statement:
Let $F = \mathbb{Z}_7$ and let $p(x) = x^3 - 2$ and $q(x) = x^3 + 2$ be in $F[x]$. Show that $p(x)$ and $q(x)$ are irreducible in $F[x]$ and that the fields $F[x]/(p(x))$ and $F[x]/(q(x))$ are isomorphic.
lean statement:
theorem exercise_4_5_23 {p q: polynomial (zmod 7)}
  (hp : p = X^3 - 2) (hq : q = X^3 + 2) :
  irreducible p \<and> irreducible q \<and>
  (nonempty $ polynomial (zmod 7) / ideal.span ({p} : set $ polynomial $ zmod 7) \<cong>+*
  polynomial (zmod 7) / ideal.span ({q} : set $ polynomial $ zmod 7)) :=

codex statement:
theorem isomorphic_of_irreducible_polynomial:
  fixes p q::"int poly"
  assumes "irreducible p" "irreducible q" "degree p = degree q"
  shows "ring_hom_ring.quotient_ring_isomorphic (poly_ring \<int>) p q"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_4_5_23: undefined oops

(*
problem_number:4_5_25
natural language statement:
If $p$ is a prime, show that $q(x) = 1 + x + x^2 + \cdots x^{p - 1}$ is irreducible in $Q[x]$.
lean statement:
theorem exercise_4_5_25 {p : \<nat>} (hp : nat.prime p) :
  irreducible (\<Sum> i : finset.range p, X ^ p : polynomial \<rat>) :=

codex statement:

Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_4_5_25: undefined oops

(*
problem_number:4_6_2
natural language statement:
Prove that $f(x) = x^3 + 3x + 2$ is irreducible in $Q[x]$.
lean statement:
theorem exercise_4_6_2 : irreducible (X^3 + 3*X + 2 : polynomial \<rat>) :=

codex statement:
theorem irreducible_of_polynomial:
  fixes f::"real \<Rightarrow> real"
  assumes "f = (\<lambda>x. x^3 + 3*x + 2)"
  shows "irreducible (polynomial f)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_4_6_2: undefined oops

(*
problem_number:4_6_3
natural language statement:
Show that there is an infinite number of integers a such that $f(x) = x^7 + 15x^2 - 30x + a$ is irreducible in $Q[x]$.
lean statement:
theorem exercise_4_6_3 :
  infinite {a : \<int> | irreducible (X^7 + 15*X^2 - 30*X + a : polynomial \<rat>)} :=

codex statement:
theorem infinite_irreducible_polynomial_of_degree_7:
  fixes a::int
  assumes "\<forall>x. x^7 + 15*x^2 - 30*x + a \<noteq> 0"
  shows "\<exists>a. irreducible (poly_of_int a)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_4_6_3: undefined oops

(*
problem_number:5_1_8
natural language statement:
If $F$ is a field of characteristic $p \neq 0$, show that $(a + b)^m = a^m + b^m$, where $m = p^n$, for all $a, b \in F$ and any positive integer $n$.
lean statement:
theorem exercise_5_1_8 {p m n: \<nat>} {F : Type*} [field F]
  (hp : nat.prime p) (hF : char_p F p) (a b : F) (hm : m = p ^ n) :
  (a + b) ^ m = a^m + b^m :=

codex statement:
theorem sum_power_eq_sum_power_of_char_neq_zero:
  fixes F::"'a::field" and a b::'a and m::nat
  assumes "characteristic F \<noteq> 0" "m = characteristic F ^ n" "n > 0"
  shows "(a + b)^m = a^m + b^m"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_5_1_8: undefined oops

(*
problem_number:5_2_20
natural language statement:
Let $V$ be a vector space over an infinite field $F$. Show that $V$ cannot be the set-theoretic union of a finite number of proper subspaces of $V$.
lean statement:
theorem exercise_5_2_20 {F V I: Type*} [infinite F] [field F]
  [add_comm_group V] [module F V] {u : I \<rightarrow> submodule F V}
  (hu : \<forall> i : I, u i \<noteq> \<top>) :
  (\<Union> i : I, (u i : set V)) \<noteq> \<top> :=

codex statement:
theorem not_union_of_finite_proper_subspaces:
  fixes V::"'a::{field, infinite} set"
  assumes "finite S" "S \<subseteq> Pow V" "\<forall>X\<in>S. X \<subset> V" "\<forall>X\<in>S. X \<noteq> V" "\<Union>S = V"
  shows False
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_5_2_20: undefined oops

(*
problem_number:5_3_7
natural language statement:
If $a \in K$ is such that $a^2$ is algebraic over the subfield $F$ of $K$, show that a is algebraic over $F$.
lean statement:
theorem exercise_5_3_7 {K : Type*} [field K] {F : subfield K}
  {a : K} (ha : is_algebraic F (a ^ 2)) : is_algebraic F a :=

codex statement:
theorem algebraic_of_algebraic_square:
  fixes a::"'a::{field_char_0,algebra_1}"
  assumes "algebraic K a^2"
  shows "algebraic K a"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_5_3_7: undefined oops

(*
problem_number:5_3_10
natural language statement:
Prove that $\cos 1^{\circ}$  is algebraic over $\mathbb{Q}$.
lean statement:
theorem exercise_5_3_10 : is_algebraic \<rat> (cos (real.pi / 180)) :=

codex statement:
theorem cos_one_degree_is_algebraic:
  shows "algebraic (cos (1::real))"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_5_3_10: undefined oops

(*
problem_number:5_4_3
natural language statement:
If $a \in C$ is such that $p(a) = 0$, where $p(x) = x^5 + \sqrt{2}x^3 + \sqrt{5}x^2 + \sqrt{7}x + \sqrt{11}$, show that $a$ is algebraic over $\mathbb{Q}$ of degree at most 80.
lean statement:
theorem exercise_5_4_3 {a : \<complex>} {p : \<complex> \<rightarrow> \<complex>}
  (hp : p = \<lambda> x, x^5 + real.sqrt 2 * x^3 + real.sqrt 5 * x^2 +
  real.sqrt 7 * x + 11)
  (ha : p a = 0) :
  \<exists> p : polynomial \<complex> , p.degree < 80 \<and> a \<in> p.roots \<and>
  \<forall> n : p.support, \<exists> a b : \<int>, p.coeff n = a / b :=

codex statement:
theorem exists_poly_of_degree_leq_80:
  fixes a::complex
  assumes "poly p a = 0" "degree p = 5" "\<forall>x. poly p x \<noteq> 0"
  shows "\<exists>q. degree q \<le> 80 \<and> poly q a = 0"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_5_4_3: undefined oops

(*
problem_number:5_5_2
natural language statement:
Prove that $x^3 - 3x - 1$ is irreducible over $\mathbb{Q}$.
lean statement:
theorem exercise_5_5_2 : irreducible (X^3 - 3*X - 1 : polynomial \<rat>) :=

codex statement:
theorem irreducible_of_polynomial_over_Q:
  fixes x::"real poly"
  assumes "degree x = 3" "\<forall>x. x^3 - 3*x - 1 = 0 \<rightarrow> x = 1 \<or> x = -1"
  shows "irreducible x"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_5_5_2: undefined oops

(*
problem_number:5_6_3
natural language statement:
Let $\mathbb{Q}$ be the rational field and let $p(x) = x^4 + x^3 + x^2 + x + 1$.  Show that there is an extension $K$ of $Q$ with $[K:Q] = 4$ over which $p(x)$ splits into linear factors.
lean statement:

codex statement:
theorem exists_splitting_field_of_polynomial_over_rational_field:
  fixes p::"complex poly"
  assumes "p = [:1, 1, 1, 1, 1:]"
  shows "\<exists>K. algebraic_closure K = K \<and> K \<subseteq> \<complex> \<and> (\<exists>f. degree f = 4 \<and> f dvd p \<and> irreducible f \<and> (\<exists>g. degree g = 1 \<and> g dvd f))"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_5_6_3: undefined oops

(*
problem_number:5_6_14
natural language statement:
If $F$ is of characteristic $p \neq 0$, show that all the roots of $x^m - x$, where $m = p^n$, are distinct.
lean statement:
theorem exercise_5_6_14 {p m n: \<nat>} (hp : nat.prime p) {F : Type*}
  [field F] [char_p F p] (hm : m = p ^ n) :
  card (root_set (X ^ m - X : polynomial F) F) = m :=

codex statement:
theorem distinct_roots_of_x_pow_m_minus_x:
  fixes F::"'a::field" and m::nat
  assumes "characteristic F \<noteq> 0" "m = characteristic F ^ n"
  shows "\<forall>x y. x \<noteq> y \<rightarrow> x^m \<noteq> y^m"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_5_6_14: undefined oops

end


(*  Title:      HOL/Quotient_Examples/Quotient_Int.thy
    Author:     Cezary Kaliszyk
    Author:     Christian Urban

Integers based on Quotients, based on an older version by Larry
Paulson.
*)

theory Quotient_Int
imports "HOL-Library.Quotient_Product"
begin

fun
  intrel :: "(nat \<times> nat) \<Rightarrow> (nat \<times> nat) \<Rightarrow> bool" (infix "\<approx>" 50)
where
  "intrel (x, y) (u, v) = (x + v = u + y)"

quotient_type int = "nat \<times> nat" / intrel
  by (auto simp add: equivp_def fun_eq_iff)

instantiation int :: "{zero, one, plus, uminus, minus, times, ord, abs, sgn}"
begin

quotient_definition
  "0 :: int" is "(0::nat, 0::nat)" done

quotient_definition
  "1 :: int" is "(1::nat, 0::nat)" done

fun
  plus_int_raw :: "(nat \<times> nat) \<Rightarrow> (nat \<times> nat) \<Rightarrow> (nat \<times> nat)"
where
  "plus_int_raw (x, y) (u, v) = (x + u, y + v)"

quotient_definition
  "(+) :: (int \<Rightarrow> int \<Rightarrow> int)" is "plus_int_raw" by auto

fun
  uminus_int_raw :: "(nat \<times> nat) \<Rightarrow> (nat \<times> nat)"
where
  "uminus_int_raw (x, y) = (y, x)"

quotient_definition
  "(uminus :: (int \<Rightarrow> int))" is "uminus_int_raw" by auto

definition
  minus_int_def:  "z - w = z + (-w::int)"

fun
  times_int_raw :: "(nat \<times> nat) \<Rightarrow> (nat \<times> nat) \<Rightarrow> (nat \<times> nat)"
where
  "times_int_raw (x, y) (u, v) = (x*u + y*v, x*v + y*u)"

lemma times_int_raw_fst:
  assumes a: "x \<approx> z"
  shows "times_int_raw x y \<approx> times_int_raw z y"
  using a
  apply(cases x, cases y, cases z)
  apply(auto simp add: times_int_raw.simps intrel.simps)
  apply(hypsubst_thin)
  apply(rename_tac u v w x y z)
  apply(subgoal_tac "u*w + z*w = y*w + v*w  &  u*x + z*x = y*x + v*x")
  apply(simp add: ac_simps)
  apply(simp add: add_mult_distrib [symmetric])
done

lemma times_int_raw_snd:
  assumes a: "x \<approx> z"
  shows "times_int_raw y x \<approx> times_int_raw y z"
  using a
  apply(cases x, cases y, cases z)
  apply(auto simp add: times_int_raw.simps intrel.simps)
  apply(hypsubst_thin)
  apply(rename_tac u v w x y z)
  apply(subgoal_tac "u*w + z*w = y*w + v*w  &  u*x + z*x = y*x + v*x")
  apply(simp add: ac_simps)
  apply(simp add: add_mult_distrib [symmetric])
done

quotient_definition
  "((*)) :: (int \<Rightarrow> int \<Rightarrow> int)" is "times_int_raw"
  apply(rule equivp_transp[OF int_equivp])
  apply(rule times_int_raw_fst)
  apply(assumption)
  apply(rule times_int_raw_snd)
  apply(assumption)
done

fun
  le_int_raw :: "(nat \<times> nat) \<Rightarrow> (nat \<times> nat) \<Rightarrow> bool"
where
  "le_int_raw (x, y) (u, v) = (x+v \<le> u+y)"

quotient_definition
  le_int_def: "(\<le>) :: int \<Rightarrow> int \<Rightarrow> bool" is "le_int_raw" by auto

definition
  less_int_def: "(z::int) < w = (z \<le> w \<and> z \<noteq> w)"

definition
  zabs_def: "\<bar>i::int\<bar> = (if i < 0 then - i else i)"

definition
  zsgn_def: "sgn (i::int) = (if i = 0 then 0 else if 0 < i then 1 else - 1)"

instance ..

end

text\<open>The integers form a \<open>comm_ring_1\<close>\<close>

instance int :: comm_ring_1
proof
  fix i j k :: int
  show "(i + j) + k = i + (j + k)"
    by (descending) (auto)
  show "i + j = j + i"
    by (descending) (auto)
  show "0 + i = (i::int)"
    by (descending) (auto)
  show "- i + i = 0"
    by (descending) (auto)
  show "i - j = i + - j"
    by (simp add: minus_int_def)
  show "(i * j) * k = i * (j * k)"
    by (descending) (auto simp add: algebra_simps)
  show "i * j = j * i"
    by (descending) (auto)
  show "1 * i = i"
    by (descending) (auto)
  show "(i + j) * k = i * k + j * k"
    by (descending) (auto simp add: algebra_simps)
  show "0 \<noteq> (1::int)"
    by (descending) (auto)
qed

lemma plus_int_raw_rsp_aux:
  assumes a: "a \<approx> b" "c \<approx> d"
  shows "plus_int_raw a c \<approx> plus_int_raw b d"
  using a
  by (cases a, cases b, cases c, cases d)
     (simp)

lemma add_abs_int:
  "(abs_int (x,y)) + (abs_int (u,v)) =
   (abs_int (x + u, y + v))"
  apply(simp add: plus_int_def id_simps)
  apply(fold plus_int_raw.simps)
  apply(rule Quotient3_rel_abs[OF Quotient3_int])
  apply(rule plus_int_raw_rsp_aux)
  apply(simp_all add: rep_abs_rsp_left[OF Quotient3_int])
  done

definition int_of_nat_raw:
  "int_of_nat_raw m = (m :: nat, 0 :: nat)"

quotient_definition
  "int_of_nat :: nat \<Rightarrow> int" is "int_of_nat_raw" done

lemma int_of_nat:
  shows "of_nat m = int_of_nat m"
  by (induct m)
     (simp_all add: zero_int_def one_int_def int_of_nat_def int_of_nat_raw add_abs_int)

instance int :: linorder
proof
  fix i j k :: int
  show antisym: "i \<le> j \<Longrightarrow> j \<le> i \<Longrightarrow> i = j"
    by (descending) (auto)
  show "(i < j) = (i \<le> j \<and> \<not> j \<le> i)"
    by (auto simp add: less_int_def dest: antisym)
  show "i \<le> i"
    by (descending) (auto)
  show "i \<le> j \<Longrightarrow> j \<le> k \<Longrightarrow> i \<le> k"
    by (descending) (auto)
  show "i \<le> j \<or> j \<le> i"
    by (descending) (auto)
qed

instantiation int :: distrib_lattice
begin

definition
  "(inf :: int \<Rightarrow> int \<Rightarrow> int) = min"

definition
  "(sup :: int \<Rightarrow> int \<Rightarrow> int) = max"

instance
  by standard (auto simp add: inf_int_def sup_int_def max_min_distrib2)

end

instance int :: ordered_cancel_ab_semigroup_add
proof
  fix i j k :: int
  show "i \<le> j \<Longrightarrow> k + i \<le> k + j"
    by (descending) (auto)
qed

abbreviation
  "less_int_raw i j \<equiv> le_int_raw i j \<and> \<not>(i \<approx> j)"

lemma zmult_zless_mono2_lemma:
  fixes i j::int
  and   k::nat
  shows "i < j \<Longrightarrow> 0 < k \<Longrightarrow> of_nat k * i < of_nat k * j"
  apply(induct "k")
  apply(simp)
  apply(case_tac "k = 0")
  apply(simp_all add: distrib_right add_strict_mono)
  done

lemma zero_le_imp_eq_int_raw:
  fixes k::"(nat \<times> nat)"
  shows "less_int_raw (0, 0) k \<Longrightarrow> (\<exists>n > 0. k \<approx> int_of_nat_raw n)"
  apply(cases k)
  apply(simp add:int_of_nat_raw)
  apply(auto)
  apply(rule_tac i="b" and j="a" in less_Suc_induct)
  apply(auto)
  done

lemma zero_le_imp_eq_int:
  fixes k::int
  shows "0 < k \<Longrightarrow> \<exists>n > 0. k = of_nat n"
  unfolding less_int_def int_of_nat
  by (descending) (rule zero_le_imp_eq_int_raw)

lemma zmult_zless_mono2:
  fixes i j k::int
  assumes a: "i < j" "0 < k"
  shows "k * i < k * j"
  using a
  by (drule_tac zero_le_imp_eq_int) (auto simp add: zmult_zless_mono2_lemma)

text\<open>The integers form an ordered integral domain\<close>

instance int :: linordered_idom
proof
  fix i j k :: int
  show "i < j \<Longrightarrow> 0 < k \<Longrightarrow> k * i < k * j"
    by (rule zmult_zless_mono2)
  show "\<bar>i\<bar> = (if i < 0 then -i else i)"
    by (simp only: zabs_def)
  show "sgn (i::int) = (if i=0 then 0 else if 0<i then 1 else - 1)"
    by (simp only: zsgn_def)
qed

lemmas int_distrib =
  distrib_right [of z1 z2 w]
  distrib_left [of w z1 z2]
  left_diff_distrib [of z1 z2 w]
  right_diff_distrib [of w z1 z2]
  minus_add_distrib[of z1 z2]
  for z1 z2 w :: int

lemma int_induct2:
  assumes "P 0 0"
  and     "\<And>n m. P n m \<Longrightarrow> P (Suc n) m"
  and     "\<And>n m. P n m \<Longrightarrow> P n (Suc m)"
  shows   "P n m"
using assms
by (induction_schema) (pat_completeness, lexicographic_order)

lemma int_induct:
  fixes j :: int
  assumes a: "P 0"
  and     b: "\<And>i::int. P i \<Longrightarrow> P (i + 1)"
  and     c: "\<And>i::int. P i \<Longrightarrow> P (i - 1)"
  shows      "P j"
using a b c
unfolding minus_int_def
by (descending) (auto intro: int_induct2)

text \<open>Magnitide of an Integer, as a Natural Number: \<^term>\<open>nat\<close>\<close>

definition
  "int_to_nat_raw \<equiv> \<lambda>(x, y).x - (y::nat)"

quotient_definition
  "int_to_nat::int \<Rightarrow> nat"
is
  "int_to_nat_raw"
unfolding int_to_nat_raw_def by auto

lemma nat_le_eq_zle:
  fixes w z::"int"
  shows "0 < w \<or> 0 \<le> z \<Longrightarrow> (int_to_nat w \<le> int_to_nat z) = (w \<le> z)"
  unfolding less_int_def
  by (descending) (auto simp add: int_to_nat_raw_def)

end


theory Liminf_Limsup_Lemma_Bucket
imports
  Main
  "~~/src/HOL/Library/Extended_Real"
  "~~/src/HOL/Library/Liminf_Limsup"
  Extended_Real_Lemma_Bucket
begin

lemma ge_Limsup_iff:
  fixes X :: "_ \<Rightarrow> _ :: complete_linorder"
  shows "C \<ge> Limsup F X \<longleftrightarrow> (\<forall>y>C. eventually (\<lambda>x. y > X x) F)"
proof -
  { fix y P assume "eventually P F" "y > SUPREMUM (Collect P) X"
    then have "eventually (\<lambda>x. y > X x) F"
      by (auto elim!: eventually_mono dest: SUP_lessD) }
  moreover
  { fix y P assume "y > C" and y: "\<forall>y>C. eventually (\<lambda>x. y > X x) F"
    have "\<exists>P. eventually P F \<and> y > SUPREMUM (Collect P) X"
    proof (cases "\<exists>z. C < z \<and> z < y")
      case True
      then obtain z where z: "C < z \<and> z < y" ..
      moreover from z have "z \<ge> SUPREMUM {x. z > X x} X"
        by (auto intro!: SUP_least)
      ultimately show ?thesis
        using y by (intro exI[of _ "\<lambda>x. z > X x"]) auto
    next
      case False
      then have "C \<ge> SUPREMUM {x. y > X x} X"
        by (intro SUP_least) (auto simp: not_less)
      with \<open>y > C\<close> show ?thesis
        using y by (intro exI[of _ "\<lambda>x. y > X x"]) auto
    qed }
  ultimately show ?thesis
    unfolding Limsup_def INF_le_iff by auto
qed

lemma Limsup_ereal_mult_right:
  assumes "F \<noteq> bot" "(c::real) \<ge> 0"
  shows   "Limsup F (\<lambda>n. f n * ereal c) = Limsup F f * ereal c"
proof (cases "c = 0")
  assume "c \<noteq> 0"
  with assms have c: "c > 0" by simp
  show ?thesis
  proof (rule Limsup_eqI)
    fix P assume P: "eventually P F"
    hence "eventually (\<lambda>n. f n \<le> (SUP x:Collect P. f x)) F"
      by (rule eventually_mono) (auto intro: SUP_upper)
    with assms and P show " Limsup F f * ereal c \<le> (SUP n:Collect P. f n * ereal c)"
      by (subst Sup_ereal_mult_right'[symmetric])
         (auto dest: eventually_happens' intro!: ereal_mult_right_mono Limsup_bounded SUP_upper)
  next
    fix C assume C: "\<And>P. eventually P F \<Longrightarrow> C \<le> (SUP n:Collect P. f n * ereal c)"
    {
      fix P assume P: "eventually P F"
      note C[OF P]
      also from P assms have "(SUP n:Collect P. f n * ereal c) = SUPREMUM (Collect P) f * ereal c"
        by (subst Sup_ereal_mult_right'[symmetric])
           (auto dest: eventually_happens' intro!: ereal_mult_right_mono Limsup_bounded SUP_upper)
      finally have "C / ereal c \<le> SUPREMUM (Collect P) f" using c
        by (subst ereal_divide_le_pos) (simp_all add: mult.commute)
    }
    hence "C / ereal c \<le> (INF P:{P. eventually P F}. SUPREMUM (Collect P) f)"
      by (intro INF_greatest) simp
    with c show "C \<le> Limsup F f * ereal c"
      unfolding Limsup_def by (simp add: ereal_divide_le_pos mult.commute)
  qed
qed (simp add: assms Limsup_const zero_ereal_def[symmetric])

lemma Inf_ereal_mult_right':
  assumes nonempty: "Y \<noteq> {}"
  and x: "x \<ge> 0"
  shows "(INF i:Y. f i) * ereal x = (INF i:Y. f i * ereal x)" (is "?lhs = ?rhs")
proof(cases "x = 0")
  case True thus ?thesis by(auto simp add: nonempty zero_ereal_def[symmetric])
next
  case False
  show ?thesis
  proof(rule antisym)
    show "?rhs \<ge> ?lhs"
      by(rule INF_greatest) (simp add: ereal_mult_right_mono INF_lower x)
  next
    have "?rhs = ?rhs / ereal x * ereal x" using False
      by (simp only: ereal_times_divide_eq_left ereal_times_divide_eq[symmetric] ereal_divide)
         (simp add: one_ereal_def[symmetric])
    also have "?rhs / ereal x \<le> (INF i:Y. f i)"
    proof(rule INF_greatest)
      fix i
      assume "i \<in> Y"
      have "f i = f i * (ereal x / ereal x)" using False by simp
      also have "\<dots> = f i * x / x" by(simp only: ereal_times_divide_eq)
      also from \<open>i \<in> Y\<close> have "f i * x \<ge> ?rhs" by (rule INF_lower)
      hence "f i * x / x \<ge> ?rhs / x" using x False by simp
      finally show "f i \<ge> ?rhs / x" .
    qed
    hence "?rhs / ereal x * ereal x \<le> (INF i:Y. f i) * ereal x" using x
      by (intro ereal_mult_right_mono) simp_all
    finally show "?lhs \<ge> ?rhs" .
  qed
qed

lemma Liminf_ereal_mult_right:
  assumes "F \<noteq> bot" "(c::real) \<ge> 0"
  shows   "Liminf F (\<lambda>n. f n * ereal c) = Liminf F f * ereal c"
proof (cases "c = 0")
  assume "c \<noteq> 0"
  with assms have c: "c > 0" by simp
  show ?thesis
  proof (rule Liminf_eqI)
    fix P assume P: "eventually P F"
    hence "eventually (\<lambda>n. f n \<ge> (INF x:Collect P. f x)) F"
      by (rule eventually_mono) (auto intro: INF_lower)
    with assms and P show " Liminf F f * ereal c \<ge> (INF n:Collect P. f n * ereal c)"
      by (subst Inf_ereal_mult_right'[symmetric])
         (auto dest: eventually_happens' intro!: ereal_mult_right_mono Liminf_bounded INF_lower)
  next
    fix C assume C: "\<And>P. eventually P F \<Longrightarrow> C \<ge> (INF n:Collect P. f n * ereal c)"
    {
      fix P assume P: "eventually P F"
      note C[OF P]
      also from P assms have "(INF n:Collect P. f n * ereal c) = INFIMUM (Collect P) f * ereal c"
        by (subst Inf_ereal_mult_right'[symmetric])
           (auto dest: eventually_happens' intro!: ereal_mult_right_mono Limsup_bounded SUP_upper)
      finally have "C / ereal c \<ge> INFIMUM (Collect P) f" using c
        by (subst ereal_le_divide_pos) (simp_all add: mult.commute)
    }
    hence "C / ereal c \<ge> (SUP P:{P. eventually P F}. INFIMUM (Collect P) f)"
      by (intro SUP_least) simp
    with c show "C \<ge> Liminf F f * ereal c"
      unfolding Liminf_def by (simp add: ereal_le_divide_pos mult.commute)
  qed
qed (simp add: assms Liminf_const zero_ereal_def[symmetric])

lemma Limsup_ereal_mult_left:
  assumes "F \<noteq> bot" "(c::real) \<ge> 0"
  shows   "Limsup F (\<lambda>n. ereal c * f n) = ereal c * Limsup F f"
  using Limsup_ereal_mult_right[OF assms] by (subst (1 2) mult.commute)

lemma limsup_ereal_mult_right:
  "(c::real) \<ge> 0 \<Longrightarrow> limsup (\<lambda>n. f n * ereal c) = limsup f * ereal c"
  by (rule Limsup_ereal_mult_right) simp_all

lemma limsup_ereal_mult_left:
  "(c::real) \<ge> 0 \<Longrightarrow> limsup (\<lambda>n. ereal c * f n) = ereal c * limsup f"
  by (subst (1 2) mult.commute, rule limsup_ereal_mult_right) simp_all

lemma Limsup_compose_continuous_antimono:
  fixes f :: "'a::{complete_linorder, linorder_topology} \<Rightarrow> 'b::{complete_linorder, linorder_topology}"
  assumes c: "continuous_on UNIV f" and am: "antimono f" and F: "F \<noteq> bot"
  shows "Limsup F (\<lambda>n. f (g n)) = f (Liminf F g)"
proof -
  { fix P assume "eventually P F"
    have "\<exists>x. P x"
    proof (rule ccontr)
      assume "\<not> (\<exists>x. P x)" then have "P = (\<lambda>x. False)"
        by auto
      with \<open>eventually P F\<close> F show False
        by auto
    qed }
  note * = this

  have "f (Liminf F g) = (INF P : {P. eventually P F}. f (Inf (g ` Collect P)))"
    unfolding Liminf_def SUP_def
    by (subst continuous_at_Sup_antimono[OF am continuous_on_imp_continuous_within[OF c]])
       (auto intro: eventually_True)
  also have "\<dots> = (INF P : {P. eventually P F}. SUPREMUM (g ` Collect P) f)"
    by (intro INF_cong refl continuous_at_Inf_antimono[OF am continuous_on_imp_continuous_within[OF c]])
       (auto dest!: eventually_happens simp: F)
  finally show ?thesis
    by (auto simp: Limsup_def)
qed

lemma Liminf_compose_continuous_mono:
  fixes f :: "'a::{complete_linorder, linorder_topology} \<Rightarrow> 'b::{complete_linorder, linorder_topology}"
  assumes c: "continuous_on UNIV f" and am: "mono f" and F: "F \<noteq> bot"
  shows "Liminf F (\<lambda>n. f (g n)) = f (Liminf F g)"
proof -
  { fix P assume "eventually P F"
    have "\<exists>x. P x"
    proof (rule ccontr)
      assume "\<not> (\<exists>x. P x)" then have "P = (\<lambda>x. False)"
        by auto
      with \<open>eventually P F\<close> F show False
        by auto
    qed }
  note * = this

  have "f (Liminf F g) = (SUP P : {P. eventually P F}. f (Inf (g ` Collect P)))"
    unfolding Liminf_def SUP_def
    by (subst continuous_at_Sup_mono[OF am continuous_on_imp_continuous_within[OF c]])
       (auto intro: eventually_True)
  also have "\<dots> = (SUP P : {P. eventually P F}. INFIMUM (g ` Collect P) f)"
    by (intro SUP_cong refl continuous_at_Inf_mono[OF am continuous_on_imp_continuous_within[OF c]])
       (auto dest!: eventually_happens simp: F)
  finally show ?thesis by (auto simp: Liminf_def)
qed

lemma Limsup_compose_continuous_mono:
  fixes f :: "'a::{complete_linorder, linorder_topology} \<Rightarrow> 'b::{complete_linorder, linorder_topology}"
  assumes c: "continuous_on UNIV f" and am: "mono f" and F: "F \<noteq> bot"
  shows "Limsup F (\<lambda>n. f (g n)) = f (Limsup F g)"
proof -
  { fix P assume "eventually P F"
    have "\<exists>x. P x"
    proof (rule ccontr)
      assume "\<not> (\<exists>x. P x)" then have "P = (\<lambda>x. False)"
        by auto
      with \<open>eventually P F\<close> F show False
        by auto
    qed }
  note * = this

  have "f (Limsup F g) = (INF P : {P. eventually P F}. f (Sup (g ` Collect P)))"
    unfolding Limsup_def INF_def
    by (subst continuous_at_Inf_mono[OF am continuous_on_imp_continuous_within[OF c]])
       (auto intro: eventually_True)
  also have "\<dots> = (INF P : {P. eventually P F}. SUPREMUM (g ` Collect P) f)"
    by (intro INF_cong refl continuous_at_Sup_mono[OF am continuous_on_imp_continuous_within[OF c]])
       (auto dest!: eventually_happens simp: F)
  finally show ?thesis by (auto simp: Limsup_def)
qed

lemma Limsup_add_ereal_right:
  "F \<noteq> bot \<Longrightarrow> abs c \<noteq> \<infinity> \<Longrightarrow> Limsup F (\<lambda>n. g n + (c :: ereal)) = Limsup F g + c"
  by (rule Limsup_compose_continuous_mono) (auto simp: mono_def ereal_add_mono continuous_on_def)

lemma Limsup_add_ereal_left:
  "F \<noteq> bot \<Longrightarrow> abs c \<noteq> \<infinity> \<Longrightarrow> Limsup F (\<lambda>n. (c :: ereal) + g n) = c + Limsup F g"
  by (subst (1 2) add.commute) (rule Limsup_add_ereal_right)

lemma Liminf_add_ereal_right:
  "F \<noteq> bot \<Longrightarrow> abs c \<noteq> \<infinity> \<Longrightarrow> Liminf F (\<lambda>n. g n + (c :: ereal)) = Liminf F g + c"
  by (rule Liminf_compose_continuous_mono) (auto simp: mono_def ereal_add_mono continuous_on_def)

lemma Liminf_add_ereal_left:
  "F \<noteq> bot \<Longrightarrow> abs c \<noteq> \<infinity> \<Longrightarrow> Liminf F (\<lambda>n. (c :: ereal) + g n) = c + Liminf F g"
  by (subst (1 2) add.commute) (rule Liminf_add_ereal_right)

lemma
  assumes "F \<noteq> bot"
  assumes nonneg: "eventually (\<lambda>x. f x \<ge> (0::ereal)) F"
  shows   Liminf_inverse_ereal: "Liminf F (\<lambda>x. inverse (f x)) = inverse (Limsup F f)"
  and     Limsup_inverse_ereal: "Limsup F (\<lambda>x. inverse (f x)) = inverse (Liminf F f)"
proof -
  def inv \<equiv> "\<lambda>x. if x \<le> 0 then \<infinity> else inverse x :: ereal"
  have "continuous_on ({..0} \<union> {0..}) inv" unfolding inv_def
    by (intro continuous_on_If) (auto intro!: continuous_intros)
  also have "{..0} \<union> {0..} = (UNIV :: ereal set)" by auto
  finally have cont: "continuous_on UNIV inv" .
  have antimono: "antimono inv" unfolding inv_def antimono_def
    by (auto intro!: ereal_inverse_antimono)

  have "Liminf F (\<lambda>x. inverse (f x)) = Liminf F (\<lambda>x. inv (f x))" using nonneg
    by (auto intro!: Liminf_eq elim!: eventually_mono simp: inv_def)
  also have "... = inv (Limsup F f)"
    by (simp add: assms(1) Liminf_compose_continuous_antimono[OF cont antimono])
  also from assms have "Limsup F f \<ge> 0" by (intro le_Limsup) simp_all
  hence "inv (Limsup F f) = inverse (Limsup F f)" by (simp add: inv_def)
  finally show "Liminf F (\<lambda>x. inverse (f x)) = inverse (Limsup F f)" .

  have "Limsup F (\<lambda>x. inverse (f x)) = Limsup F (\<lambda>x. inv (f x))" using nonneg
    by (auto intro!: Limsup_eq elim!: eventually_mono simp: inv_def)
  also have "... = inv (Liminf F f)"
    by (simp add: assms(1) Limsup_compose_continuous_antimono[OF cont antimono])
  also from assms have "Liminf F f \<ge> 0" by (intro Liminf_bounded) simp_all
  hence "inv (Liminf F f) = inverse (Liminf F f)" by (simp add: inv_def)
  finally show "Limsup F (\<lambda>x. inverse (f x)) = inverse (Liminf F f)" .
qed

lemma less_LiminfD:
  "y < Liminf F (f :: _ \<Rightarrow> 'a :: complete_linorder) \<Longrightarrow> eventually (\<lambda>x. f x > y) F"
  using le_Liminf_iff[of "Liminf F f" F f] by simp

lemma gt_LimsupD:
  "y > Limsup F (f :: _ \<Rightarrow> 'a :: complete_linorder) \<Longrightarrow> eventually (\<lambda>x. f x < y) F"
  using ge_Limsup_iff[of F f "Limsup F f"] by simp

end


(* Title: Verification Component Based on KAD: Trace Semantics
   Author: Victor Gomes, Georg Struth
   Maintainer: Victor Gomes <victor.gomes@cl.cam.ac.uk>
               Georg Struth <g.struth@sheffield.ac.uk>
*)

subsection \<open>Two Extensions\<close>

subsubsection \<open>KAD Component with Trace Semantics\<close>

theory Path_Model_Example
  imports VC_KAD "HOL-Eisbach.Eisbach"
begin

text \<open>This component supports the verification of simple while programs
in a partial correctness setting based on a program trace semantics.\<close>

text \<open>Program traces are modelled as non-empty paths or state sequences. The non-empty path model
of Kleene algebra is taken from the AFP entry for Kleene algebra. Here we show that sets of paths form
antidomain Kleene Algebras.\<close>

definition pp_a ::  "'a ppath set \<Rightarrow> 'a ppath set" where
  "pp_a X = {(Node u) |u. \<not> (\<exists>v \<in> X. u = pp_first v)}"

interpretation ppath_aka: antidomain_kleene_algebra pp_a "(\<union>)" pp_prod pp_one "{}" "(\<subseteq>)" "(\<subset>)" pp_star
  apply standard
  apply (clarsimp simp add: pp_prod_def pp_a_def)
  apply (simp add: pp_prod_def pp_a_def, safe, metis pp_first.simps(1) pp_first_pp_fusion)
  by (auto simp: pp_a_def pp_one_def)

text \<open>A verification component can then be built with little effort, by and large reusing
parts of the relational components that are generic with respect to the store.\<close>

definition pp_gets :: "string \<Rightarrow> ('a store \<Rightarrow> 'a) \<Rightarrow> 'a store ppath set" ("_ ::= _" [70, 65] 61) where
  "v ::= e = {Cons s (Node (s (v := e s))) | s. True}"

definition p2pp :: "'a pred \<Rightarrow> 'a ppath set" where
  "p2pp P = {Node s |s. P s}"

lemma pp_a_neg [simp]: "pp_a (p2pp Q) = p2pp (-Q)"
  by (force simp add: pp_a_def p2pp_def)

lemma ppath_assign [simp]: "ppath_aka.fbox (v ::= e) (p2pp Q) = p2pp (\<lambda>s. Q (s(v := e s)))"
  by (force simp: ppath_aka.fbox_def pp_a_def p2pp_def pp_prod_def pp_gets_def)

no_notation spec_sugar ("PRE _ _ POST _" [64,64,64] 63)
   and relcomp (infixl ";" 70)
   and cond_sugar ("IF _ THEN _ ELSE _ FI" [64,64,64] 63)
   and whilei_sugar ("WHILE _ INV _ DO _ OD" [64,64,64] 63)
   and gets ("_ ::= _" [70, 65] 61)
   and rel_antidomain_kleene_algebra.fbox ("wp")
   and rel_antidomain_kleene_algebra.ads_d ("rdom")
   and p2r ("\<lceil>_\<rceil>")

notation ppath_aka.fbox ("wp")
  and ppath_aka.ads_d ("rdom")
  and p2pp ("\<lceil>_\<rceil>")
  and pp_prod (infixl ";" 70)

abbreviation spec_sugar :: "'a pred \<Rightarrow> 'a ppath set \<Rightarrow> 'a pred \<Rightarrow> bool" ("PRE _ _ POST _" [64,64,64] 63) where
  "PRE P X POST Q \<equiv> rdom \<lceil>P\<rceil> \<subseteq> wp X \<lceil>Q\<rceil>"

abbreviation cond_sugar :: "'a pred \<Rightarrow> 'a ppath set \<Rightarrow> 'a ppath set \<Rightarrow> 'a ppath set" ("IF _ THEN _ ELSE _ FI" [64,64,64] 63) where
  "IF P THEN X ELSE Y FI \<equiv> ppath_aka.cond \<lceil>P\<rceil> X Y"

abbreviation whilei_sugar :: "'a pred \<Rightarrow> 'a pred \<Rightarrow> 'a ppath set \<Rightarrow> 'a ppath set" ("WHILE _ INV _ DO _ OD" [64,64,64] 63) where
  "WHILE P INV I DO X OD \<equiv> ppath_aka.whilei \<lceil>P\<rceil> \<lceil>I\<rceil> X"

lemma [simp]: "p2pp P; p2pp Q = p2pp (P \<sqinter> Q)"
  by (force simp: p2pp_def pp_prod_def)

lemma [intro!]:  "P \<le> Q \<Longrightarrow> \<lceil>P\<rceil> \<subseteq> \<lceil>Q\<rceil>"
  by (force simp: p2pp_def)

lemma [simp]: "rdom \<lceil>P\<rceil> = \<lceil>P\<rceil>"
  by (simp add: ppath_aka.addual.ars_r_def)

lemma euclid:
  "PRE (\<lambda>s::nat store. s ''x'' = x \<and> s ''y'' = y)
   (WHILE (\<lambda>s. s ''y'' \<noteq> 0) INV (\<lambda>s. gcd (s ''x'') (s ''y'') = gcd x y)
    DO
     (''z'' ::= (\<lambda>s. s ''y''));
     (''y'' ::= (\<lambda>s. s ''x'' mod s ''y''));
     (''x'' ::= (\<lambda>s. s ''z''))
    OD)
   POST (\<lambda>s. s ''x'' = gcd x y)"
  by (rule ppath_aka.fbox_whilei, simp_all, auto simp: p2pp_def rel_ad_def gcd_non_0_nat)

lemma euclid_diff:
   "PRE (\<lambda>s::nat store. s ''x'' = x \<and> s ''y'' = y \<and> x > 0 \<and> y > 0)
    (WHILE (\<lambda>s. s ''x''\<noteq> s ''y'') INV (\<lambda>s. gcd (s ''x'') (s ''y'') = gcd x y)
     DO
        (IF (\<lambda>s. s ''x'' >  s ''y'')
         THEN (''x'' ::= (\<lambda>s. s ''x'' - s ''y''))
         ELSE (''y'' ::= (\<lambda>s. s ''y'' - s ''x''))
         FI)
    OD)
    POST (\<lambda>s. s ''x'' = gcd x y)"
  apply (rule ppath_aka.fbox_whilei, simp_all)
  apply (simp_all add: p2pp_def)
  apply auto[2]
  by (safe, metis gcd.commute gcd_diff1_nat le_cases nat_less_le)

lemma varible_swap:
  "PRE (\<lambda>s. s ''x'' = a \<and> s ''y'' = b)
    (''z'' ::= (\<lambda>s. s ''x''));
    (''x'' ::= (\<lambda>s. s ''y''));
    (''y'' ::= (\<lambda>s. s ''z''))
   POST (\<lambda>s. s ''x'' = b \<and> s ''y'' = a)"
  by auto

lemma maximum:
  "PRE (\<lambda>s:: nat store. True)
   (IF (\<lambda>s. s ''x'' \<ge> s ''y'')
    THEN (''z'' ::= (\<lambda>s. s ''x''))
    ELSE (''z'' ::= (\<lambda>s. s ''y''))
    FI)
   POST (\<lambda>s. s ''z'' = max (s ''x'') (s ''y''))"
  by auto

lemma integer_division:
  "PRE (\<lambda>s::nat store. x \<ge> 0)
    (''q'' ::= (\<lambda>s. 0));
    (''r'' ::= (\<lambda>s. x));
    (WHILE (\<lambda>s. y \<le> s ''r'') INV (\<lambda>s. x = s ''q'' * y + s ''r'' \<and> s ''r'' \<ge> 0)
     DO
      (''q'' ::= (\<lambda>s. s ''q'' + 1));
      (''r'' ::= (\<lambda>s. s ''r'' - y))
      OD)
   POST (\<lambda>s. x = s ''q'' * y + s ''r'' \<and> s ''r'' \<ge> 0 \<and> s ''r'' < y)"
  by (rule ppath_aka.fbox_whilei_break, auto)

text \<open>We now reconsider these examples with an Eisbach tactic.\<close>

named_theorems ht

declare ppath_aka.fbox_whilei [ht]
  ppath_aka.fbox_seq_var [ht]
  subset_refl[ht]

method hoare = (rule ht; hoare?)

lemma euclid2:
  "PRE (\<lambda>s::nat store. s ''x'' = x \<and> s ''y'' = y)
   (WHILE (\<lambda>s. s ''y'' \<noteq> 0) INV (\<lambda>s. gcd (s ''x'') (s ''y'') = gcd x y)
    DO
     (''z'' ::= (\<lambda>s. s ''y''));
     (''y'' ::= (\<lambda>s. s ''x'' mod s ''y''));
     (''x'' ::= (\<lambda>s. s ''z''))
    OD)
   POST (\<lambda>s. s ''x'' = gcd x y)"
apply hoare
using gcd_red_nat by auto

lemma euclid_diff2:
   "PRE (\<lambda>s::nat store. s ''x'' = x \<and> s ''y'' = y \<and> x > 0 \<and> y > 0)
    (WHILE (\<lambda>s. s ''x''\<noteq> s ''y'') INV (\<lambda>s. gcd (s ''x'') (s ''y'') = gcd x y)
     DO
        (IF (\<lambda>s. s ''x'' >  s ''y'')
         THEN (''x'' ::= (\<lambda>s. s ''x'' - s ''y''))
         ELSE (''y'' ::= (\<lambda>s. s ''y'' - s ''x''))
         FI)
    OD)
    POST (\<lambda>s. s ''x'' = gcd x y)"
  by (hoare; clarsimp; metis gcd.commute gcd_diff1_nat le_cases nat_less_le)

lemma varible_swap2:
  "PRE (\<lambda>s. s ''x'' = a \<and> s ''y'' = b)
    (''z'' ::= (\<lambda>s. s ''x''));
    (''x'' ::= (\<lambda>s. s ''y''));
    (''y'' ::= (\<lambda>s. s ''z''))
   POST (\<lambda>s. s ''x'' = b \<and> s ''y'' = a)"
  by clarsimp

lemma maximum2:
  "PRE (\<lambda>s:: nat store. True)
   (IF (\<lambda>s. s ''x'' \<ge> s ''y'')
    THEN (''z'' ::= (\<lambda>s. s ''x''))
    ELSE (''z'' ::= (\<lambda>s. s ''y''))
    FI)
   POST (\<lambda>s. s ''z'' = max (s ''x'') (s ''y''))"
   by auto

lemma my_power2:
  "PRE (\<lambda>s::nat store. True)
   (''i'' ::= (\<lambda>s. 0));
   (''y'' ::= (\<lambda>s. 1));
   (WHILE (\<lambda>s. s ''i'' < n) INV (\<lambda>s. s ''y'' = x ^ (s ''i'') \<and> s ''i'' \<le> n)
     DO
       (''y'' ::= (\<lambda>s. (s ''y'') * x));
       (''i'' ::= (\<lambda>s. s ''i'' + 1))
     OD)
   POST (\<lambda>s. s ''y'' = x ^ n)"
  by hoare auto

lemma imp_reverse2:
  "PRE (\<lambda>s:: 'a list store. s ''x'' = X)
   (''y'' ::= (\<lambda>s. []));
   (WHILE (\<lambda>s. s ''x'' \<noteq> []) INV (\<lambda>s. rev (s ''x'') @ s ''y'' = rev X)
    DO
     (''y'' ::= (\<lambda>s. hd (s ''x'') # s ''y''));
     (''x'' ::= (\<lambda>s. tl (s ''x'')))
    OD)
   POST (\<lambda>s. s ''y''= rev X )"
  apply hoare
  apply auto
  apply (metis append.simps append_assoc hd_Cons_tl rev.simps(2))
done

end