theory Axler
  imports Complex_Main
"HOL-Analysis.Inner_Product"
"HOL-Analysis.Abstract_Euclidean_Space"
"HOL.Vector_Spaces"
"Rank_Nullity_Theorem.Fundamental_Subspaces"
(*"HOL-Analysis.Weierstrass_Theorems"*)
"HOL-Computational_Algebra.Polynomial"

(* Note by Angeliki:
some types chosen are too general, some others too specific e.g. *real* vector etc.
Note to perhaps readjust with appropriate use of locales *)

begin

(*
problem_number:1_2
natural language statement:
Show that $\frac{-1 + \sqrt{3}i}{2}$ is a cube root of 1 (meaning that its cube equals 1).
lean statement:
theorem exercise_1_2 :
  (\<langle>-1/2, real.sqrt 3 / 2\<rangle> : \<complex>) ^ 3 = -1 :=

codex statement:
theorem cube_root_of_1:
  shows "(-1 + sqrt 3 * \<i>)^3 = 1"

Our comment on the codex statement: wrong function, missed the denominator.
 *)
theorem exercise_1_2: shows "((-1 + sqrt 3 * \<i>)/2)^3 = 1 " oops

(*
problem_number:1_3
natural language statement:
Prove that $-(-v) = v$ for every $v \in V$.
lean statement:
theorem exercise_1_3 {F V : Type*} [add_comm_group V] [field F]
  [module F V] {v : V} : -(-v) = v :=

codex statement:
theorem neg_neg_eq_self:
  fixes v::"'a::ab_group_add"
  shows "-(-v) = v"

Our comment on the codex statement: < the statement is in principle correct, though the type is not
specified in the natural language statement. By the choice of notation I assume it's a vector instead.   >
 *)
theorem exercise_1_3:

   fixes v::"'a::ab_group_add"and V::"'a::ab_group_add set"
  shows "\<forall> v \<in> V. -(-v) = v"
  oops

theorem exercise_1_3_alternative:  fixes v :: "'a :: real_vector"
  shows "-(-v) = v" oops

(*
problem_number:1_4
natural language statement:
Prove that if $a \in \mathbf{F}$, $v \in V$, and $av = 0$, then $a = 0$ or $v = 0$.
lean statement:
theorem exercise_1_4 {F V : Type*} [add_comm_group V] [field F]
  [module F V] (v : V) (a : F): a \<bullet> v = 0 \<longleftrightarrow> a = 0 \<or> v = 0 :=

codex statement:
theorem zero_of_scalar_times_vector_eq_zero:
  fixes a::"'a::field" and v::"'b::real_vector"
  assumes "a *\<^sub>R v = 0"
  shows "a = 0 ∨ v = 0"

Our comment on the codex statement: <wrong symbol for multiplication.
Can work if  the field is the reals here in particular. Can
we generalise? >
 *)
(*TODO *)
theorem exercise_1_4:
   fixes a::real and v::"'b::real_vector"
  assumes "scaleR a v = 0"
  shows "a = 0 ∨ v = 0"
  oops

(*
problem_number:1_6
natural language statement:
Give an example of a nonempty subset $U$ of $\mathbf{R}^2$ such that $U$ is closed under addition
and under taking additive inverses (meaning $-u \in U$ whenever $u \in U$),
but $U$ is not a subspace of $\mathbf{R}^2$.
lean statement:
theorem exercise_1_6 : \<exists> U : set (\<real> \<times> \<real>),
  (U \<noteq> \<emptyset>) \<and>
  (\<forall> (u v : \<real> \<times> \<real>), u \<in> U \<and> v \<in> U \<rightarrow> u + v \<in> U) \<and>
  (\<forall> (u : \<real> \<times> \<real>), u \<in> U \<rightarrow> -u \<in> U) \<and>
  (\<forall> U' : submodule \<real> (\<real> \<times> \<real>), U \<noteq> ↑U') :=

codex statement:
theorem exists_nonempty_subset_of_R2_closed_under_add_and_inv_not_subspace:
  shows "∃U. U ≠ {} ∧ (∀x∈U. -x∈U) ∧ (∀x y∈U. x+y∈U) ∧ ¬(subspace U (UNIV::(real, real) vec set))"

Our comment on the codex statement: <quite close but syntactic and type problems>
 *)
theorem exercise_1_6:
  fixes V::"'a::euclidean_space set" assumes" DIM('a::euclidean_space) = 2"
  obtains  U::"'a::euclidean_space set" where
"U \<subseteq> V \<and> U ≠ {} ∧ (\<forall> x \<in> U. -x \<in> U) ∧ (\<forall>x\<in>U
. \<forall> y \<in>U. x+y\<in> U) ∧ ¬(subspace U )"

  oops

(*
problem_number:1_7
natural language statement:
Give an example of a nonempty subset $U$ of $\mathbf{R}^2$ such that $U$ is closed under scalar multiplication,
 but $U$ is not a subspace of $\mathbf{R}^2$.
lean statement:
theorem exercise_1_7 : \<exists> U : set (\<real> \<times> \<real>),
  (U \<noteq> \<emptyset>) \<and>
  (\<forall> (c : \<real>) (u : \<real> \<times> \<real>), u \<in> U \<rightarrow> c \<bullet> u \<in> U) \<and>
  (\<forall> U' : submodule \<real> (\<real> \<times> \<real>), U \<noteq> ↑U') :=

codex statement:
theorem exists_nonempty_subset_closed_under_scalar_multiplication_not_subspace:
  fixes U::"('a::real_vector) set"
  assumes "∃U. U ≠ {} ∧ (∀x∈U. ∀c. c∈UNIV ⟶ c • x ∈ U)"
  shows "∃U. U ≠ {} ∧ (∀x∈U. ∀c. c∈UNIV ⟶ c • x ∈ U) ∧ ¬(subspace U)"

Our comment on the codex statement: <logically wrong: fixes U and then assumes \exists U, also
wrong notation for scalar multiplication>
 *)

theorem exercise_1_7:
   fixes V::"'a::euclidean_space set" assumes" DIM('a::euclidean_space) = 2"
  obtains  U::"'a::euclidean_space set" where
"U \<subseteq> V  \<and> U ≠ {} ∧ (\<forall> x \<in> U. \<forall> a::real. scaleR a x
\<in> U) ∧ ¬(subspace U )"

  oops

(*
problem_number:1_8
natural language statement:
Prove that the intersection of any collection of subspaces of $V$ is a subspace of $V$.
lean statement:
theorem exercise_1_8 {F V : Type*} [add_comm_group V] [field F]
  [module F V] {\<iota> : Type*} (u : \<iota> \<rightarrow> submodule F V) :
  \<exists> U : submodule F V, (\<Inter> (i : \<iota>), (u i).carrier) = ↑U :=

codex statement:
theorem subspace_of_intersection_of_subspaces:
  fixes V::"'a::real_vector set"
  assumes "∀S∈S. subspace S"
  shows "subspace (⋂S∈S. S)"

Our comment on the codex statement: <The natural language statement does not give the type of V,
but from the notation chosen we may infer that it is a vector space.
The codex formalisation is wrong:  introduces V and then only uses S.>
 *)
theorem exercise_1_8:
  fixes V::"'a::real_vector set"
  and C:: "'a::real_vector set set"
  assumes "C= {S. subspace S \<and> S\<subset> V}"
  shows "subspace (⋂S∈C. S)"
  oops

(*
problem_number:1_9
natural language statement:
Prove that the union of two subspaces of $V$ is a subspace of $V$ if and only
if one of the subspaces is contained in the other.
lean statement:
theorem exercise_1_9 {F V : Type*} [add_comm_group V] [field F]
  [module F V] (U W : submodule F V):
  \<exists> U' : submodule F V, U'.carrier = ↑U ∩ ↑W \<longleftrightarrow> U \<le> W \<or> W \<le> U :=

codex statement:
theorem union_of_subspaces_is_subspace_iff_one_subset_of_other:
  fixes V::"'a::real_vector set"
  assumes "subspace V" "subspace U" "subspace W"
  shows "subspace (U ∪ W) ⟷ U ⊆ W ∨ W ⊆ U"

Our comment on the codex statement: < introduces V without using it.>
 *)
theorem exercise_1_9:

  fixes U::"'a::real_vector set"
  fixes W::"'a::real_vector set"
  assumes "subspace U" "subspace W"
  shows "subspace (U ∪ W) ⟷ U ⊆ W ∨ W ⊆ U"
  oops

(*
problem_number:2_1
natural language statement:
Prove that if $\left(v_{1}, \ldots, v_{n}\right)$ spans $V$, then so does
the list $\left(v_{1}-v_{2}, v_{2}-v_{3}, \ldots, v_{n-1}-v_{n}, v_{n}\right)$
obtained by subtracting from each vector (except the last one) the following vector.
lean statement:

codex statement:
theorem span_of_subtract_succ_of_span:
  fixes v::"'a::euclidean_space set"
  assumes "span v = UNIV"
  shows "span (λn. v (Suc n) - v n) = UNIV"

Our comment on the codex statement: <wrong, mainly problem with types/indices>
 *)

theorem exercise_2_1:

undefined oops

(*
problem_number:2_2
natural language statement:
Prove that if $\left(v_{1}, \ldots, v_{n}\right)$ is linearly independent in $V$,
then so is the list $\left(v_{1}-v_{2}, v_{2}-v_{3}, \ldots, v_{n-1}-v_{n}, v_{n}\right)$
obtained by subtracting from each vector (except the last one) the following vector.
lean statement:

codex statement:
theorem linear_independent_of_linear_independent_sub:
  fixes v::"'a::euclidean_space set"
  assumes "independent v"

  shows "independent (λi. (v (Suc i)) - (v i))"
Our comment on the codex statement: <wrong, again mainly problem with types/indices >
 *)
theorem exercise_2_2:
undefined
  oops

(*
problem_number:2_6
natural language statement:
Prove that the real vector space consisting of all continuous real valued functions
on the interval $[0,1]$ is infinite dimensional.
lean statement:

codex statement:
theorem infinite_dim_of_continuous_real_valued_functions:
  fixes f::"real ⇒ real"
  assumes "continuous_on {0..1} f"
  shows "∃g. continuous_on {0..1} g ∧ g ≠ f"

Our comment on the codex statement: <completely wrong statement. syntax ok, but it talks about
a completely different statement>
 *)

theorem exercise_2_6:

  assumes " V= {f::real \<Rightarrow> real. continuous_on {0..1} f}"
  shows "infinite V"
  oops

(*
problem_number:3_1
natural language statement:
Show that every linear map from a one-dimensional vector space to itself is multiplication
by some scalar. More precisely, prove that if $\operatorname{dim} V=1$
and $T \in \mathcal{L}(V, V)$, then there
exists $a \in \mathbf{F}$ such that $T v=a v$ for all $v \in V$.
lean statement:
theorem exercise_3_1 {F V : Type*}
  [add_comm_group V] [field F] [module F V] [finite_dimensional F V]
  (T : V \<rightarrow>ₗ[F] V) (hT : finrank F V = 1) :
  \<exists> c : F, \<forall> v : V, T v = c \<bullet> v:=

codex statement:
theorem linear_map_of_dim_one_is_scalar_mult:
  fixes V::"'a::real_vector space" and T::"'a ⇒ 'a"
  assumes "linear T" "DIM('a) = 1"
  shows "∃a. ∀x. T x = a * x"

Our comment on the codex statement: <various type issues and multiplication symbol>
 *)

theorem exercise_3_1:

fixes  T::" 'a:: real_vector ⇒ 'a:: real_vector "
 (* assumes "linear T" *) (* TODO: how to incorporate assumptions without type issue?   *)
  shows "∃a \<in> \<real>. ∀x. T x = scaleR a x"

 oops (* TODO again I restrict it to real ..*)

(*
problem_number:3_8
natural language statement:
Suppose that $V$ is finite dimensional and that $T \in \mathcal{L}(V, W)$.
Prove that there exists a subspace $U$ of $V$ such that $U \cap \operatorname{null} T=\{0\}$
and range $T=\{T u: u \in U\}$.
lean statement:
theorem exercise_3_8 {F V W : Type*}  [add_comm_group V]
  [add_comm_group W] [field F] [module F V] [module F W]
  (L : V \<rightarrow>ₗ[F] W) :
  \<exists> U : submodule F V, U \<sqinter> L.ker = \<bot> \<and>
  linear_map.range L = range (dom_restrict L U):=

codex statement:
theorem exists_subspace_of_range_eq_image_of_subspace:
  fixes V::"'a::euclidean_space set" and W::"'b::euclidean_space set"
  assumes "finite_dimensional V" "finite_dimensional W" "linear T"
  shows "∃U. subspace U ∧ U ∩ null_space T = {0} ∧ range T = T ` U"

Our comment on the codex statement: < the codex formalisation is incorrect wrt assumptions,
conclusions, also it makes up nonexistent Isabelle definitions such as finite_dimensional   >
 *)
theorem exercise_3_8:
undefined

(* TODO*)

(* note that null_space refers to matrices *)

 (*
  obtains U where " subspace U \<and> U \<subseteq> V ∧ U ∩ null_space T = {0} ∧ range T = T ` U"
*)

  oops

(*
problem_number:3_9
natural language statement:
Prove that if $T$ is a linear map from $\mathbf{F}^{4}$ to $\mathbf{F}^{2}$
such that $\operatorname{null} T=\left\{\left(x_{1}, x_{2}, x_{3}, x_{4}\right) \in \mathbf{F}^{4}:
x_{1}=5 x_{2}\right.$ and $\left.x_{3}=7 x_{4}\right\}$, then $T$ is surjective.
lean statement:

codex statement:
theorem surjective_of_null_space:
  fixes T::"'a::{field}^4 ⇒ 'a^2"
  assumes "null_space T = {x. x$1 = 5 * x$2 ∧ x$3 = 7 * x$4}"
  shows "surj T"

Our comment on the codex statement: <various type issues >*)

theorem exercise_3_9:
undefined (* TODO *)
  oops

(*
problem_number:3_10
natural language statement:
Prove that there does not exist a linear map from $\mathbf{F}^{5}$ to $\mathbf{F}^{2}$
whose null space equals $\left\{\left(x_{1}, x_{2}, x_{3}, x_{4}, x_{5}\right)
\in \mathbf{F}^{5}: x_{1}=3 x_{2} \text { and } x_{3}=x_{4}=x_{5}\right\} .$
lean statement:

codex statement:
theorem not_exists_linear_map_of_null_space_eq_set:
  fixes f::"real^5 ⇒ real^2"
  assumes "linear f" "null_space f = {x | x. x$1 = 3 * x$2 ∧ x$3 = x$4 ∧ x$4 = x$5}"
  shows False

Our comment on the codex statement: <wrong, various type issues>
 *)
theorem exercise_3_10:
undefined (*TODO *)

  oops

(*
problem_number:3_11
natural language statement:
Prove that if there exists a linear map on $V$ whose null space and range are both finite dimensional,
then $V$ is finite dimensional.
lean statement:

codex statement:
theorem finite_dim_of_linear_map_finite_dim_null_space_range:
  fixes V::"'a::euclidean_space set" and f::"'a ⇒ 'b::euclidean_space"
  assumes "linear f" "finite_dimensional (null_space f)" "finite_dimensional (range f)"
  shows "finite_dimensional V"

Our comment on the codex statement: <various type problems but gets close>
 *)

theorem exercise_3_11:
   fixes V::"'a::real_vector set" and f::"'a ⇒ 'a"
  assumes (*"linear f"*) (*"finite (null_space f)"*) "finite (range f)"
  shows "finite V"

  (* TODO *)
  oops

(*
problem_number:4_4
natural language statement:
Suppose $p \in \mathcal{P}(\mathbf{C})$ has degree $m$.
Prove that $p$ has $m$ distinct roots if and only if $p$ and its derivative $p^{\prime}$
have no roots in common.
lean statement:
theorem exercise_4_4 (p : polynomial \<complex>) :
  p.degree = @card (root_set p \<complex>) (polynomial.root_set_fintype p \<complex>) \<longleftrightarrow>
  disjoint
  (@card (root_set p.derivative \<complex>) (polynomial.root_set_fintype p.derivative \<complex>))
  (@card (root_set p \<complex>) (polynomial.root_set_fintype p \<complex>)) :=

codex statement:
theorem distinct_roots_of_poly_iff_no_common_roots_with_derivative:
  fixes p::"complex poly"
  assumes "degree p = m"
  shows "distinct_roots p ↔ (∀x. poly p x = 0 ⟶ poly (deriv p) x ≠ 0)"

Our comment on the codex statement: <makes up definitions that do not exist in Isabelle e.g. distinct_roots,
uses wrong defs that are inappropriate here like deriv, wrong double implication symbol >
 *)
theorem exercise_4_4:
  fixes p::"complex poly"
  assumes "degree p = m"
  shows "( {x. poly p x = 0}\<inter> {x. pderiv p = 0} = {}) \<longleftrightarrow> card {x. poly p x = 0}=m "
  oops

(*
problem_number:5_1
natural language statement:
Suppose $T \in \mathcal{L}(V)$. Prove that if $U_{1}, \ldots, U_{m}$ are subspaces
 of $V$ invariant under $T$, then $U_{1}+\cdots+U_{m}$ is invariant under $T$.
lean statement:
theorem exercise_5_1 {F V : Type*} [add_comm_group V] [field F]
  [module F V] {L : V \<rightarrow>ₗ[F] V} {n : \<nat>} (U : fin n \<rightarrow> submodule F V)
  (hU : \<forall> i : fin n, map L (U i) = U i) :
  map L (\<Sum> i : fin n, U i : submodule F V) =
  (\<Sum> i : fin n, U i : submodule F V) :=

codex statement:
theorem sum_of_invariant_subspace_is_invariant:
  fixes T::"'a::real_vector ⇒ 'a"
  assumes "∀i. i ≤ m ⟶ subspace (U i)" "∀i. i ≤ m ⟶ T (U i) ⊆ U i"
  shows "T (⨁i≤m. U i) ⊆ (⨁i≤m. U i)"

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

(*
problem_number:5_4
natural language statement:
Suppose that $S, T \in \mathcal{L}(V)$ are such that $S T=T S$.
Prove that $\operatorname{null} (T-\lambda I)$ is invariant under $S$ for every $\lambda \in \mathbf{F}$.
lean statement:
theorem exercise_5_4 {F V : Type*} [add_comm_group V] [field F]
  [module F V] (S T : V \<rightarrow>ₗ[F] V) (hST : S ∘ T = T ∘ S) (c : F):
  map S (T - c \<bullet> id).ker = (T - c \<bullet> id).ker :=

codex statement:
theorem null_of_commutative_is_invariant:
  fixes S T::"'a::{real_normed_algebra_1, finite_dimensional} ⇒ 'a"
  assumes "commutative S T"
  shows "∀λ. subspace (null_space (T - λ *\<^sub>R 𝟭)) (range S)"

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

(*
problem_number:5_11
natural language statement:
Suppose $S, T \in \mathcal{L}(V)$. Prove that $S T$ and $T S$ have the same eigenvalues.
lean statement:
theorem exercise_5_11 {F V : Type*} [add_comm_group V] [field F]
  [module F V] (S T : End F V) :
  (S * T).eigenvalues = (T * S).eigenvalues  :=

codex statement:
theorem eigenvalues_of_commutative_linear_operators:
  fixes S T::"'a::{comm_ring_1,euclidean_space} ⇒ 'a"
  assumes "linear S" "linear T"
  shows "eigenvalues (S ∘ T) = eigenvalues (T ∘ S)"

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

(*
problem_number:5_12
natural language statement:
Suppose $T \in \mathcal{L}(V)$ is such that every vector in $V$ is an eigenvector of $T$. Prove that $T$ is a scalar multiple of the identity operator.
lean statement:
theorem exercise_5_12 {F V : Type*} [add_comm_group V] [field F]
  [module F V] {S : End F V}
  (hS : \<forall> v : V, \<exists> c : F, v \<in> eigenspace S c) :
  \<exists> c : F, S = c \<bullet> id :=

codex statement:
theorem scalar_multiple_of_identity_of_eigenvector_of_all_vectors:
  fixes T::"'a::{real_normed_algebra_1, real_inner} ⇒ 'a"
  assumes "linear T" "∀x. ∃c. T x = c * x"
  shows "∃c. T = (λx. c * x)"

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

(*
problem_number:5_13
natural language statement:
Suppose $T \in \mathcal{L}(V)$ is such that every subspace of $V$ with dimension $\operatorname{dim} V-1$ is invariant under $T$. Prove that $T$ is a scalar multiple of the identity operator.
lean statement:
theorem exercise_5_13 {F V : Type*} [add_comm_group V] [field F]
  [module F V] [finite_dimensional F V] {T : End F V}
  (hS : \<forall> U : submodule F V, finrank F U = finrank F V - 1 \<rightarrow>
  map T U = U) : \<exists> c : F, T = c \<bullet> id :=

codex statement:
theorem scalar_multiple_of_identity_of_invariant_subspace_of_dim_pred:
  fixes T::"'a::euclidean_space ⇒ 'a"
  assumes "linear T" "∀S. subspace S ⟶ dim S = dim V - 1 ⟶ subspace (T ` S)"
  shows "T = (λx. c * x) ∘ T ∘ (λx. c * x)"

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

(*
problem_number:5_20
natural language statement:
Suppose that $T \in \mathcal{L}(V)$ has $\operatorname{dim} V$ distinct eigenvalues and that $S \in \mathcal{L}(V)$ has the same eigenvectors as $T$ (not necessarily with the same eigenvalues). Prove that $S T=T S$.
lean statement:
theorem exercise_5_20 {F V : Type*} [add_comm_group V] [field F]
  [module F V] [finite_dimensional F V] {S T : End F V}
  (h1 : @card T.eigenvalues (eigenvalues.fintype T) = finrank F V)
  (h2 : \<forall> v : V, \<exists> c : F, v \<in> eigenspace S c \<longleftrightarrow> \<exists> c : F, v \<in> eigenspace T c) :
  S * T = T * S :=

codex statement:
theorem commutative_of_same_eigenvectors:
  fixes T::"'a::{finite_dimensional, real_inner} ⇒ 'a" and S::"'a::{finite_dimensional, real_inner} ⇒ 'a"
  assumes "linear T" "linear S" "∀x. x∈carrier_vec n ⟶ (∃λ. T x = λ *\<^sub>R x)" "∀x. x∈carrier_vec n ⟶ (∃λ. S x = λ *\<^sub>R x)" "∀x. x∈carrier_vec n ⟶ (∃λ. T x = λ *\<^sub>R x) ⟶ (∃λ. S x = λ *\<^sub>R x)"
  shows "T ∘ S = S ∘ T"

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

(*
problem_number:5_24
natural language statement:
Suppose $V$ is a real vector space and $T \in \mathcal{L}(V)$ has no eigenvalues. Prove that every subspace of $V$ invariant under $T$ has even dimension.
lean statement:
theorem exercise_5_24 {V : Type*} [add_comm_group V]
  [module \<real> V] [finite_dimensional \<real> V] {T : End \<real> V}
  (hT : \<forall> c : \<real>, eigenspace T c = \<bot>) {U : submodule \<real> V}
  (hU : map T U = U) : even (finrank U) :=

codex statement:
theorem even_dim_of_invariant_subspace_of_no_eigenvalue:
  fixes V::"'a::euclidean_space set" and T::"'a ⇒ 'a"
  assumes "linear T" "∀x. T x ≠ x"
  shows "∀S. subspace S ⟶ subspace.invariant S T ⟶ even (dim S)"

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

(*
problem_number:6_2
natural language statement:
Suppose $u, v \in V$. Prove that $\langle u, v\rangle=0$ if and only if $\|u\| \leq\|u+a v\|$ for all $a \in \mathbf{F}$.
lean statement:
theorem exercise_6_2 {V : Type*} [add_comm_group V] [module \<complex> V]
  [inner_product_space \<complex> V] (u v : V) :
  ⟪u, v⟫_\<complex> = 0 \<longleftrightarrow> \<forall> (a : \<complex>), ∥u∥ \<le> ∥u + a \<bullet> v∥ :=

codex statement:
theorem norm_leq_norm_add_scalar_mul_iff_inner_eq_zero:
  fixes u v::"'a::euclidean_space"
  shows "inner u v = 0 ⟷ ∀a. norm u ≤ norm (u + a *\<^sub>R v)"

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

(*
problem_number:6_3
natural language statement:
Prove that $\left(\sum_{j=1}^{n} a_{j} b_{j}\right)^{2} \leq\left(\sum_{j=1}^{n}
j a_{j}{ }^{2}\right)\left(\sum_{j=1}^{n} \frac{b_{j}{ }^{2}}{j}\right)$
for all real numbers $a_{1}, \ldots, a_{n}$ and $b_{1}, \ldots, b_{n}$.
lean statement:
theorem exercise_6_3 {n : \<nat>} (a b : fin n \<rightarrow> \<real>) :
  (\<Sum> i, a i * b i) ^ 2 \<le> (\<Sum> i : fin n, i * a i ^ 2) * (\<Sum> i, b i ^ 2 / i) :=

codex statement:
theorem sum_square_leq_sum_square_of_sum_square:
  fixes a b::"nat ⇒ real"
  assumes "∀i. i ≤ n ⟶ a i ≥ 0" "∀i. i ≤ n ⟶ b i ≥ 0"
  shows "(∑i=1..n. a i * b i)^2 ≤ (∑i=1..n. i * (a i)^2) * (∑i=1..n. (b i)^2 / i)"

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

(*
problem_number:6_7
natural language statement:
Prove that if $V$ is a complex inner-product space,
then $\langle u, v\rangle=\frac{\|u+v\|^{2}-\|u-v\|^{2}+\|u+i v\|^{2} i-\|u-i v\|^{2} i}{4}$
for all $u, v \in V$.
lean statement:
theorem exercise_6_7 {V : Type*} [inner_product_space \<complex> V] (u v : V) :
  ⟪u, v⟫_\<complex> = (∥u + v∥^2 - ∥u - v∥^2 + I*∥u + I\<bullet>v∥^2 - I*∥u-I\<bullet>v∥^2) / 4 :=

codex statement:
theorem inner_product_eq_sum_square_sub_square_sum_square_sub_square:
  fixes u v::"'a::euclidean_space"
  shows "inner_product u v = (norm (u+v)^2 - norm (u-v)^2 + norm (u+ii*v)^2 - norm (u-ii*v)^2)/4"

Our comment on the codex statement: <wrong: missed
factors  𝗂 in the expression, uses wrong type, nonexistent definition inner_product>
 *)
theorem exercise_6_7:
 fixes u v::"complex"
  shows "inner u v = (norm (u+v)^2 - norm (u-v)^2 + (norm (u+ 𝗂 * v)^2) * 𝗂 - (norm (u- 𝗂  * v)^2)* 𝗂)/4"

 oops

(*
problem_number:6_13
natural language statement:
Suppose $\left(e_{1}, \ldots, e_{m}\right)$ is an orthonormal list of vectors in $V$.
Let $v \in V$.
Prove that
$\|v\|^{2}=\left|\left\langle v, e_{1}\right\rangle\right|^{2}+\cdots+\left|\left\langle v,
e_{m}\right\rangle\right|^{2}$
if and only if $v \in \operatorname{span}\left(e_{1}, \ldots, e_{m}\right)$.
lean statement:
theorem exercise_6_13 {V : Type*} [inner_product_space \<complex> V] {n : \<nat>}
  {e : fin n \<rightarrow> V} (he : orthonormal \<complex> e) (v : V) :
  ∥v∥^2 = \<Sum> i : fin n, ∥⟪v, e i⟫_\<complex>∥^2 \<longleftrightarrow> v \<in> span \<complex> (e '' univ) :=

codex statement:
theorem norm_square_eq_sum_abs_square_of_orthonormal_list_iff_in_span:
  fixes v::"'a::euclidean_space" and e::"'a set"
  assumes "finite e" "e ⊆ orthonormal_basis" "v ∈ span e"
  shows "norm v ^ 2 = (∑x∈e. (cinner v x)^2)"

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

(*
problem_number:6_16
natural language statement:
Suppose $U$ is a subspace of $V$. Prove that $U^{\perp}=\{0\}$ if and only if $U=V$
lean statement:
theorem exercise_6_16 {K V : Type*} [is_R_or_C K] [inner_product_space K V]
  {U : submodule K V} :
  U.orthogonal = \<bot>  \<longleftrightarrow> U = \<top> :=

codex statement:
theorem orthogonal_of_subspace_eq_zero_iff_eq_space:
  fixes U::"'a::euclidean_space set"
  assumes "subspace U"
  shows "orthogonal_complement U = {0} ⟷ U = UNIV"

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

(*
problem_number:6_17
natural language statement:
Prove that if $P \in \mathcal{L}(V)$ is such that $P^{2}=P$ and every vector
 in $\operatorname{null} P$ is orthogonal to every vector in $\operatorname{range} P$,
then $P$ is an orthogonal projection.
lean statement:

codex statement:
theorem orthogonal_projection_of_null_orthogonal_range:
  fixes P::"'a::euclidean_space ⇒ 'a"
  assumes "linear P" "P^2 = P" "∀x∈null_space P. ∀y∈range P. x⋅y = 0"
  shows "orthogonal_projection P"

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

(*
problem_number:6_18
natural language statement:
Prove that if $P \in \mathcal{L}(V)$ is
such that $P^{2}=P$ and $\|P v\| \leq\|v\|$ for every $v \in V$, then $P$ is an orthogonal projection.
lean statement:

codex statement:
theorem orthogonal_projection_of_square_eq_self_and_norm_leq_norm:
  fixes P::"'a::euclidean_space ⇒ 'a"
  assumes "linear P" "P^2 = P" "∀x. norm (P x) ≤ norm x"
  shows "∀x y. P x = P y ⟶ x = y"

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

(*
problem_number:6_19
natural language statement:
Suppose $T \in \mathcal{L}(V)$ and $U$ is a subspace of $V$. Prove that $U$ is invariant under $T$
if and only if $P_{U} T P_{U}=T P_{U}$.
lean statement:

codex statement:
theorem invariant_of_projection_eq_projection_comp:
  fixes T::"'a::euclidean_space ⇒ 'a" and U::"'a set"
  assumes "subspace U"
  shows "invariant_under T U ⟷ (T ∘ (projection U) = projection U ∘ T)"

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

(*
problem_number:6_20
natural language statement:
Suppose $T \in \mathcal{L}(V)$ and $U$ is a subspace of $V$.
Prove that $U$ and $U^{\perp}$ are both invariant under $T$ if and only if $P_{U} T=T P_{U}$.
lean statement:

codex statement:
theorem orthogonal_projection_eq_projection_orthogonal_iff_invariant:
  fixes T::"'a::euclidean_space ⇒ 'a" and U::"'a set"
  assumes "subspace U"
  shows "T ` U ⊆ U ∧ T ` U⊥ ⊆ U⊥ ⟷ (T ∘ (projection U) = (projection U) ∘ T)"

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

(*
problem_number:6_29
natural language statement:
Suppose $T \in \mathcal{L}(V)$ and $U$ is a subspace of $V$. Prove that $U$
is invariant under $T$ if and only if $U^{\perp}$ is invariant under $T^{*}$.
lean statement:

codex statement:
theorem invariant_of_adjoint_invariant:
  fixes T::"'a::euclidean_space ⇒ 'a" and U::"'a set"
  assumes "linear T" "subspace U"
  shows "U ⊆ carrier T ⟺ (orthogonal_complement U) ⊆ carrier (adjoint T)"

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

(*
problem_number:7_4
natural language statement:
Suppose $P \in \mathcal{L}(V)$ is such that $P^{2}=P$.
Prove that $P$ is an orthogonal projection if and only if $P$ is self-adjoint.
lean statement:

codex statement:
theorem orthogonal_projection_iff_self_adjoint:
  fixes P::"'a::euclidean_space ⇒ 'a"
  assumes "linear P" "P^2 = P"
  shows "orthogonal_projection P ⟷ selfadjoint P"

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

(*
problem_number:7_5
natural language statement:
Show that if $\operatorname{dim} V \geq 2$, then the set of normal
operators on $V$ is not a subspace of $\mathcal{L}(V)$.
lean statement:
theorem exercise_7_5 {V : Type*} [inner_product_space \<complex> V]
  [finite_dimensional \<complex> V] (hV : finrank V \<ge> 2) :
  \<forall> U : submodule \<complex> (End \<complex> V), U.carrier \<noteq>
  {T | T * T.adjoint = T.adjoint * T} :=

codex statement:
theorem normal_operators_not_subspace_of_linear_operators:
  fixes V::"'a::euclidean_space set"
  assumes "DIM('a) ≥ 2"
  shows "∀N. linear N ⟶ normal N ⟶ False"

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

(*
problem_number:7_6
natural language statement:
Prove that if $T \in \mathcal{L}(V)$ is normal, then $\operatorname{range} T=\operatorname{range} T^{*}.$
lean statement:
theorem exercise_7_6 {V : Type*} [inner_product_space \<complex> V]
  [finite_dimensional \<complex> V] (T : End \<complex> V)
  (hT : T * T.adjoint = T.adjoint * T) :
  T.range = T.adjoint.range :=

codex statement:
theorem range_of_normal_eq_range_of_adjoint:
  fixes T::"'a::euclidean_space \<Rightarrow> 'a"
  assumes "linear T" "T adjoint = T"
  shows "range T = range (T adjoint)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_7_6: undefined oops

(*
problem_number:7_8
natural language statement:
Prove that there does not exist a self-adjoint operator
$T \in \mathcal{L}\left(\mathbf{R}^{3}\right)$ such that $T(1,2,3)=(0,0,0)$ and $T(2,5,7)=(2,5,7)$.
lean statement:

codex statement:
theorem not_exists_self_adjoint_operator_of_two_eigenvectors:
  fixes T::"real^3 \<Rightarrow> real^3"
  assumes "linear T" "self_adjoint T" "T (vector [1,2,3]) = 0" "T (vector [2,5,7]) = vector [2,5,7]"
  shows False
Our comment on the codex statement: <linear assumption issue. makes use of nonexistent def. self_adjoint>
 *)

theorem exercise_7_8:
  fixes T::"real^3 \<Rightarrow> real^3" assumes  (* "linear T"*)
(* TODO T linear *)
  "T (vector [1,2,3]) = 0" "T (vector [2,5,7]) = vector [2,5,7]"
"adjoint T = T"
  shows False
  oops

(*
problem_number:7_9
natural language statement:
Prove that a normal operator on a complex inner-product space is self-adjoint if and
only if all its eigenvalues are real.
lean statement:
theorem exercise_7_9 {V : Type*} [inner_product_space \<complex> V]
  [finite_dimensional \<complex> V] (T : End \<complex> V)
  (hT : T * T.adjoint = T.adjoint * T) :
  is_self_adjoint T \<longleftrightarrow> \<forall> e : T.eigenvalues, (e : \<complex>).im = 0 :=

codex statement:
theorem normal_operator_is_self_adjoint_iff_eigenvalues_are_real:
  fixes A::"'a::euclidean_space \<Rightarrow> 'a"
  assumes "normal_operator A"
  shows "self_adjoint A \<longleftrightarrow> (\<forall>x. eigenvalue A x \<longrightarrow> x\<in>\<real>)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_7_9: undefined oops

(*
problem_number:7_10
natural language statement:
Suppose $V$ is a complex inner-product space and $T \in \mathcal{L}(V)$ is a normal
operator such that $T^{9}=T^{8}$. Prove that $T$ is self-adjoint and $T^{2}=T$.
lean statement:
theorem exercise_7_10 {V : Type*} [inner_product_space \<complex> V]
  [finite_dimensional \<complex> V] (T : End \<complex> V)
  (hT : T * T.adjoint = T.adjoint * T) (hT1 : T^9 = T^8) :
  is_self_adjoint T \<and> T^2 = T :=

codex statement:
theorem normal_operator_of_power_eq_power_succ:
  fixes T::"'a::complex_inner_product_space \<Rightarrow> 'a"
  assumes "normal T" "T^9 = T^8"
  shows "T = adjoint T \<and> T^2 = T"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_7_10: undefined oops

(*
problem_number:7_11
natural language statement:
Suppose $V$ is a complex inner-product space. Prove that every normal
operator on $V$ has a square root. (
An operator $S \in \mathcal{L}(V)$ is called a square root of $T \in \mathcal{L}(V)$ if $S^{2}=T$.)
lean statement:
theorem exercise_7_11 {V : Type*} [inner_product_space \<complex> V]
  [finite_dimensional \<complex> V] {T : End \<complex> V} (hT : T*T.adjoint = T.adjoint*T) :
  \<exists> (S : End \<complex> V), S ^ 2 = T :=

codex statement:
theorem exists_sqrt_of_normal_operator:
  fixes V::"'a::complex_inner_product_space"
  assumes "normal_operator V"
  shows "\<exists>S. bounded_linear S \<and> S^2 = T"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_7_11: undefined oops
(*
problem_number:7_14
natural language statement:
Suppose $T \in \mathcal{L}(V)$ is self-adjoint, $\lambda \in \mathbf{F}$, and $\epsilon>0$. Prove that if there exists $v \in V$ such that $\|v\|=1$ and $\|T v-\lambda v\|<\epsilon,$ then $T$ has an eigenvalue $\lambda^{\prime}$ such that $\left|\lambda-\lambda^{\prime}\right|<\epsilon$.
lean statement:
theorem exercise_7_14 {𝕜 V : Type*} [is_R_or_C 𝕜]
  [inner_product_space 𝕜 V] [finite_dimensional 𝕜 V]
  {T : End 𝕜 V} (hT : is_self_adjoint T)
  {l : 𝕜} {\<epsilon> : \<real>} (he : \<epsilon> > 0) : \<exists> v : V, ∥v∥ = 1 \<and> ∥T v - l \<bullet> v∥ < \<epsilon> \<rightarrow>
  \<exists> l' : T.eigenvalues, ∥l - l'∥ < \<epsilon> :=

codex statement:
theorem exists_eigenvalue_of_self_adjoint_operator:
  fixes T::"'a::euclidean_space \<Rightarrow> 'a"
  assumes "self_adjoint T" "\<exists>v. norm v = 1 \<and> norm (T v - \<lambda> v) < \<epsilon>"
  shows "\<exists>\<lambda>'. eigenvalue T \<lambda>' \<and> abs (\<lambda> - \<lambda>') < \<epsilon>"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_7_14: undefined oops

(*
problem_number:7_15
natural language statement:
Suppose $U$ is a finite-dimensional real vector space and $T \in$ $\mathcal{L}(U)$.
Prove that $U$ has a basis consisting of eigenvectors of $T$ if and only if there is an
inner product on $U$ that makes $T$ into a self-adjoint operator.
lean statement:

codex statement:
theorem exists_inner_product_of_eigenvectors_basis:
  fixes T::"'a::euclidean_space \<Rightarrow> 'a"
  assumes "linear T" "\<exists>b. independent b \<and> b \<subseteq> carrier_vec n \<and> span b = carrier_vec n"
  shows "\<exists>B. inner_product_space B \<and> (\<forall>x\<in>b. eigenvector B T x)"
Our comment on the codex statement: <various type errors, wrong statement, and makes up defs that
don't exist in Isabelle.>
 *)
theorem exercise_7_15:
  undefined
  oops

(*
problem_number:7_17
natural language statement:
Prove that the sum of any two positive operators on $V$ is positive.
lean statement:

codex statement:
theorem sum_of_positive_operators_is_positive:
  fixes V::"'a::euclidean_space set" and f g::"'a \<Rightarrow> 'a"
  assumes "linear f" "linear g" "\<forall>x\<in>V. 0 \<le> f x ⋅ x" "\<forall>x\<in>V. 0 \<le> g x ⋅ x"
  shows "\<forall>x\<in>V. 0 \<le> (f + g) x ⋅ x"
Our comment on the codex statement: <wrong assumptions and type issues>
 *)
theorem exercise_7_17:
undefined

  oops

(*
problem_number:7_18
natural language statement:
Prove that if $T \in \mathcal{L}(V)$ is positive, then so is $T^{k}$ for every positive integer $k$.
lean statement:

codex statement:
theorem positive_of_positive_power:
  fixes T::"'a::euclidean_space \<Rightarrow> 'a"
  assumes "linear T" "positive T"
  shows "positive (T^k)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_7_18:
undefined
  oops

end


theory Seminarski
  imports Complex_Main Main HOL.NthRoot

begin

primrec proizvod :: "nat \<Rightarrow> real" where
"proizvod 0 = 1" |
"proizvod (Suc n) = ((3*(Suc n) - 2)/(3*(Suc n) - 1)) * proizvod n"

value "proizvod 2"

lemma kubiranje_1[simp]:
  fixes n::nat
  assumes "n>0"
  shows "(3*(n+1)-2)^3 = 27*n^3+27*n^2+9*n+1"
proof-
  have "(3*(n+1)-2)^3 = (3*n+3-2)^3"
    by simp
  also have "... = (3*n+1)^3"
    by simp
  also have "... = (3*n+1)^2*(3*n+1)"
    by (simp add: power2_eq_square power3_eq_cube)
  also have "... = (9*n^2+6*n+1)*(3*n+1)"
    by (smt Suc_eq_plus1 eval_nat_numeral(3) mult_2 numeral_Bit0 one_add_one one_power2 plus_1_eq_Suc power2_sum power_mult_distrib semiring_normalization_rules(18) semiring_normalization_rules(25))
  also have "... = (3*n)*(9*n^2+6*n+1)+(9*n^2+6*n+1)"
    by simp
  also have "... = (3*n)*(9*n^2)+(3*n)*(6*n)+(3*n)+(9*n^2+6*n+1)"
    by (simp add: linordered_field_class.sign_simps(18))
  also have "... = (3*9)*(n*n^2)+(3*6)*(n*n)+(3*n)+(9*n^2+6*n+1)"
  by simp
  also have "... = (27)*(n*n^2)+(18)*(n*n)+(3*n)+(9*n^2+6*n+1)"
    by simp
  also have "... = 27*n^3+18*n^2+3*n+9*n^2+6*n+1"
    by (metis (no_types, lifting) One_nat_def numeral_3_eq_3 one_add_one plus_1_eq_Suc power2_eq_square semiring_normalization_rules(25) semiring_normalization_rules(27))
  also have "... = 27*n^3+27*n^2+9*n+1"
  by linarith
  finally show ?thesis .
qed

lemma kubiranje_2[simp]:
  fixes n::nat
  assumes "n>0"
  shows "(3*(n+1)-1)^3 = 27*n^3+54*n^2+36*n+8"
proof-
  have "(3*(n+1)-1)^3 = (3*n+3-1)^3"
    by simp
  also have "... = (3*n+2)^3"
    by simp
  also have "... = (3*n+2)^2*(3*n+2)"
    by (simp add: power2_eq_square power3_eq_cube)
  also have "... = (9*n^2+12*n+4)*(3*n+2)"
  by (smt mult_2 mult_2_right numeral_Bit0 numeral_Bit1 one_add_one one_power2 power2_sum power_mult_distrib semiring_normalization_rules(23) semiring_normalization_rules(8))
  also have "... = (3*n)*(9*n^2+12*n+4)+2*(9*n^2+12*n+4)"
    by simp
  also have "... = (3*n)*(9*n^2)+(3*n)*(12*n)+(3*n)*4+2*(9*n^2+12*n+4)"
    by (simp add: linordered_field_class.sign_simps(18))
  also have "... = (3*9)*(n*n^2)+(3*12)*(n*n)+(12*n)+2*(9*n^2+12*n+4)"
  by simp
  also have "... = (27)*(n*n^2)+(36)*(n*n)+(12*n)+2*(9*n^2+12*n+4)"
  by simp
  also have "... = 27*n^3+36*n^2+12*n+(18*n^2)+(24*n)+8"
  by (simp add: power2_eq_square power3_eq_cube)
  also have "... = 27*n^3+54*n^2+36*n+8"
  by linarith
  finally show ?thesis .
qed

lemma kubiranje_korena1[simp]:
  fixes n::nat
  assumes "n>0"
  shows "(root 3 (8*(n+1)))^3=8*(n+1)"
  by simp

lemma kubiranje_korena2[simp]:
  fixes n::nat
  assumes "n>0"
  shows "(root 3 (8*n))^3=8*(n)"
  by simp

lemma zakljucak1[simp]:
  fixes n::nat
  assumes "n>0"
  shows "16*n+8\<ge>0"
  by blast

lemma razlika_3korena1[simp]:
  fixes n::nat
  assumes "n>0"
  shows "((3*(n+1)-2)*(root 3 (8*(n+1))))^3-((3*(n+1)-1)*(root 3 (8 * n)))^3\<ge>0"
proof-
  have  1:"((3*(n+1)-2)*(root 3 (8*(n+1))))^3-((3*(n+1)-1)*(root 3 (8 * n)))^3 = (3*(n+1)-2)^3*(root 3 (8*(n+1)))^3-(3*(n+1)-1)^3*(root 3 (8 * n))^3"
  by (simp add: power_mult_distrib)
  then have 2:"... = (27*n^3+27*n^2+9*n+1)*(root 3 (8*(n+1)))^3-(27*n^3+54*n^2+36*n+8)*(root 3 (8 * n))^3"
    using assms kubiranje_1 kubiranje_2 by auto
  then have 3:"... = (27*n^3+27*n^2+9*n+1)*(8*(n+1))-(27*n^3+54*n^2+36*n+8)*(root 3 (8*n))^3"
    by (metis (no_types, lifting) assms of_nat_mult kubiranje_korena1 kubiranje_korena2)
  then have 4:"... = (27*n^3+27*n^2+9*n+1)*(8*n+8)-(27*n^3+54*n^2+36*n+8)*(root 3 (8*n))^3"
    by (metis (mono_tags, hide_lams) add.commute mult.assoc mult.commute semiring_normalization_rules(19) semiring_normalization_rules(29) semiring_normalization_rules(3) semiring_normalization_rules(34))
  then have 5:"... = (27*n^3+27*n^2+9*n+1)*(8*n)+(27*n^3+27*n^2+9*n+1)*8-(27*n^3+54*n^2+36*n+8)*(root 3 (8*n))^3"
    by (simp add: add_mult_distrib2)
  then have 6:"... = (27*n^3)*(8*n)+(27*n^2)*(8*n)+(9*n)*(8*n)+(8*n)+(27*n^3+27*n^2+9*n+1)*8-(27*n^3+54*n^2+36*n+8)*(root 3 (8*n))^3"
    by (simp add: add_mult_distrib)
  then have 7:"... = (27*n^3)*(8*n)+(27*n^2)*(8*n)+(9*n)*(8*n)+(8*n)+27*n^3*8+27*n^2*8+9*n*8+8-(27*n^3+54*n^2+36*n+8)*(root 3 (8*n))^3"
    by (simp add: add_mult_distrib)
  then have 8:"... = (27*n^3)*(8*n)+(27*n^2)*(8*n)+(9*n)*(8*n)+(8*n)+27*n^3*8+27*n^2*8+9*n*8+8-((27*n^3)*(root 3 (8*n))^3+(54*n^2)*(root 3 (8*n))^3+(36*n)*(root 3 (8*n))^3+8*(root 3 (8*n))^3)"
    using add_mult_distrib
  by (simp add: semiring_normalization_rules(8))
  then have 9:"... = (27*n^3)*(8*n)+(27*n^2)*(8*n)+(9*n)*(8*n)+(8*n)+27*n^3*8+27*n^2*8+9*n*8+8-(27*n^3)*(root 3 (8*n))^3-(54*n^2)*(root 3 (8*n))^3-(36*n)*(root 3 (8*n))^3-8*(root 3 (8*n))^3"
    by simp
  then have 10:"... = (27*n^2)*(8*n)+(9*n)*(8*n)+(8*n)+27*n^3*8+27*n^2*8+9*n*8+8-(54*n^2)*(root 3 (8*n))^3-(36*n)*(root 3 (8*n))^3-8*(root 3 (8*n))^3"
    by simp
  then have 11:"... = (27*n^2)*(root 3 (8*n))^3+(9*n)*(root 3 (8*n))^3+(root 3 (8*n))^3+27*n^3*8+27*n^2*8+9*n*8+8-(54*n^2)*(root 3 (8*n))^3-(36*n)*(root 3 (8*n))^3-8*(root 3 (8*n))^3"
    by auto
  then have 12:"... = (27*n^2)*(8*n)+(9*n)*(8*n)+(root 3 (8*n))^3+27*n^3*8+27*n^2*8+9*n*8+8-(54*n^2)*(8*n)-(36*n)*(root 3 (8*n))^3-8*(root 3 (8*n))^3"
    by auto
  then have 13:"... = (27*8)*(n^2*n)+(9*8)*(n*n)+(root 3 (8*n))^3+27*8*n^3+27*8*n^2+9*n*8+8-(54*8)*(n^2*n)-(36*n)*(root 3 (8*n))^3-8*(root 3 (8*n))^3"
  by linarith
  then have 14:"... = (216)*(n^3)+(72)*(n^2)+(root 3 (8*n))^3+216*n^3+216*n^2+72*n+8-(432)*(n^3)-(36*n)*(root 3 (8*n))^3-8*(root 3 (8*n))^3"
  by (simp add: power2_eq_square power3_eq_cube)
  then have 15:"... = 432*n^3+288*n^2+(root 3 (8*n))^3+72*n+8-432*n^3-(36*n)*(root 3 (8*n))^3-8*(root 3 (8*n))^3"
    by simp
  then have 16:"... = 288*n^2+(root 3 (8*n))^3+72*n+8-(36*n)*(root 3 (8*n))^3-8*(root 3 (8*n))^3"
    by linarith
  then have 17:"... = 288*n^2+(root 3 ( 8*n))^3+72*n+8-(36*n)*(8*n)-8*(root 3 (8*n))^3"
    by simp
  then have 18:"... = 288*n^2+(root 3 ( 8*n))^3+72*n+8-(36*8)*(n*n)-8*(root 3 (8*n))^3"
    by simp
  then have 19:"... = 288*n^2+(root 3 ( 8*n))^3+72*n+8-288*n^2-8*(root 3 (8*n))^3"
  using power2_eq_square by force
  then have 20:"... =  8*n+72*n+8-8*(8*n)"
    using power2_eq_square by force
    then have 22:"... = 16*n+8"
    by simp
  then have 23:"...\<ge>0"
    using assms zakljucak1
  using of_nat_0_le_iff by blast
  then show ?thesis
  by (smt "1" "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "2" "20" "22" "3" "4" "5" "6" "7" "8")
qed

lemma pomocna2[simp]:
  fixes n::nat
  assumes "n>0"
  assumes "((3*(n+1)-2)*(root 3 (8*(n+1))))^3-((3*(n+1)-1)*(root 3 (8 * n)))^3\<ge>0"
  shows "((3*(n+1)-2)*(root 3 (8*(n+1))))^3\<ge>((3*(n+1)-1)*(root 3 (8 * n)))^3"
  using assms
proof-
  have  "((3*(n+1)-2)*(root 3 (8*(n+1))))^3-((3*(n+1)-1)*(root 3 (8 * n)))^3\<ge>0"
    using assms by blast
  then show ?thesis
    by simp
qed

lemma pomocna3[simp]:
  fixes n::nat
  assumes "n>0"
  assumes "((3*(n+1)-2)*(root 3 (8*(n+1))))^3\<ge>((3*(n+1)-1)*(root 3 (8 * n)))^3"
  shows "(3*(n+1)-2)*(root 3 (8*(n+1)))\<ge>(3*(n+1)-1)*(root 3 (8 * n))"
  using assms
proof-
  have  "((3*(n+1)-2)*(root 3 (8*(n+1))))^3\<ge>((3*(n+1)-1)*(root 3 (8 * n)))^3"
    using assms by blast
  then have "root 3 (((3*(n+1)-2)*(root 3 (8*(n+1))))^3) \<ge>root 3 (((3*(n+1)-1)*(root 3 (8 * n)))^3)"
  using real_root_le_mono zero_less_numeral by blast
  then show ?thesis
  by (simp add: real_root_power_cancel)
qed

lemma kub_je_veci_od_nule1[simp]:
  fixes n::nat
  assumes "n>0"
  shows "root 3 (8*(n+1))> 0"
  by simp

lemma kub_je_veci_od_nule2[simp]:
  fixes n::nat
  assumes "n>0"
  shows "root 3 (8*n)> 0"
  using assms by auto

lemma veci_od_nule1[simp]:
  fixes n::nat
  assumes "n>0"
  shows "(3*(n+1)-1)> 0"
  using assms by auto

lemma medjukorak[simp]:
  fixes n::nat
  assumes "n>0"
  shows "(3*(n+1)-2)\<ge>((3*(n+1)-1)*(root 3 (8 * n)))/(root 3 (8*(n+1)))"
  using assms kub_je_veci_od_nule1
proof-
  have "(3*(n+1)-2)*(root 3 (8*(n+1)))\<ge>(3*(n+1)-1)*(root 3 (8 * n))"
    using assms razlika_3korena1 pomocna3 by auto
  then have "((3*(n+1)-2)*(root 3 (8*(n+1))))/(root 3 (8*(n+1)))\<ge>((3*(n+1)-1)*(root 3 (8 * n)))/(root 3 (8*(n+1)))"
    by (smt assms divide_right_mono kub_je_veci_od_nule1)
  then have "(3*(n+1)-2)\<ge>((3*(n+1)-1)*(root 3 (8 * n)))/(root 3 (8*(n+1)))"
    using assms(1) by auto
  then show ?thesis
    by (simp add: mult.commute)
qed

lemma kljucan_dokaz_za_levu_stranu[simp]:
  fixes n::nat
  assumes "n>0"
  shows "(3*(n+1)-2)/((3*(n+1)-1)*(root 3 (8 * n)))\<ge>1/(root 3 (8*(n+1)))"
  using assms
proof-
  have "(3*(n+1)-2)\<ge>((3*(n+1)-1)*(root 3 (8 * n)))/(root 3 (8*(n+1)))"
    using assms razlika_3korena1 pomocna3 medjukorak by auto
  then have "(3*(n+1)-2)/(root 3 (8 * n))\<ge>((3*(n+1)-1)*(root 3 (8 * n)))/(root 3 (8*(n+1)))*(1/(root 3 (8 * n)))"
    using kub_je_veci_od_nule2 assms
    by (metis (no_types, hide_lams) divide_right_mono mult.right_neutral of_nat_0_le_iff real_root_pos_pos_le times_divide_eq_right)
  then have "(3*(n+1)-2)/(root 3 (8 * n))\<ge>((3*(n+1)-1))/(root 3 (8*(n+1)))"
    using assms(1) by auto
  then have "((3*(n+1)-2)/(root 3 (8 * n)))*(1/(3*(n+1)-1))\<ge>((3*(n+1)-1))/(root 3 (8*(n+1)))*(1/(3*(n+1)-1))"
    using assms veci_od_nule1
  by (smt divide_le_0_1_iff division_ring_divide_zero of_nat_0_le_iff real_mult_le_cancel_iff1 times_divide_eq_right)
  then have "((3*(n+1)-2)/(root 3 (8 * n)))*(1/(3*(n+1)-1))\<ge>1/(root 3 (8*(n+1)))"
    by simp
  then show ?thesis
    by (simp add: mult.commute)
qed

lemma pomocna4[simp]:
  fixes n::nat
  assumes "n>0"
  shows "8*(root 3 (7*n+1))^3=8*(7*n+1)"
  by simp

lemma kubiranje_3[simp]:
  fixes n::nat
  assumes "n>0"
  shows "(27*n^3+54*n^2+36*n+8)*(root 3 (7*n+1))^3=(27*n^3+54*n^2+36*n+8)*(7*n+1)"
  by (metis (no_types, lifting) of_nat_0_le_iff of_nat_mult real_root_pow_pos2 zero_less_numeral)

lemma kubiranje_4[simp]:
  fixes n::nat
  assumes "n>0"
  shows "(27*n^3+27*n^2+9*n+1)*(root 3 (7*(n+1)+1))^3=(27*n^3+27*n^2+9*n+1)*(7*(n+1)+1)"
  by (metis (no_types, lifting) of_nat_0_le_iff of_nat_mult real_root_pow_pos2 zero_less_numeral)

lemma p1[simp]:
  fixes n::nat
  assumes "n>0"
  shows "8*(root 3 (7*n+1))^3 =8*( 7*n+1)"
  by simp

lemma p2[simp]:
  fixes n::nat
  assumes "n>0"
  shows "-56*n-8=-8*(7*n+1)"
  by simp

lemma razlika_3korena2[simp]:
  fixes n::nat
  assumes "n>0"
  shows "((3*(n+1)-1)*(root 3 (7*n+1)))^3-((3*(n+1)-2)*(root 3 (7*(n+1)+1)))^3\<ge>0"
proof-
  have  1:"((3*(n+1)-1)*(root 3 (7*n+1)))^3-((3*(n+1)-2)*(root 3 (7*(n+1)+1)))^3 = (3*(n+1)-1)^3*(root 3 (7*n+1))^3-(3*(n+1)-2)^3*(root 3 (7*(n+1)+1))^3"
  by (simp add: power_mult_distrib)
  then have 2:"... = (27*n^3+54*n^2+36*n+8)*(root 3 (7*n+1))^3-(27*n^3+27*n^2+9*n+1)*(root 3 (7*(n+1)+1))^3"
  using assms kubiranje_1 kubiranje_2 by auto
  then have 3:"... = (27*n^3+54*n^2+36*n+8)*(root 3 (7*n+1))^3-(27*n^3+27*n^2+9*n+1)*(7*(n+1)+1)"
    by (metis (no_types, lifting) of_nat_0_le_iff of_nat_mult real_root_pow_pos2 zero_less_numeral)
  then have 4:"... = (27*n^3+54*n^2+36*n+8)*(root 3 (7*n+1))^3-(27*n^3+27*n^2+9*n+1)*(7*n+7+1)"
  by simp
  then have 5:"... = (27*n^3+54*n^2+36*n+8)*(root 3 (7*n+1))^3-((27*n^3+27*n^2+9*n+1)*(7*n+1) + 7*(27*n^3+27*n^2+9*n+1))"
    by (simp add: add_mult_distrib2)
  then have "5a":"... = (27*n^3+54*n^2+36*n+8)*(root 3 (7*n+1))^3-(27*n^3+27*n^2+9*n+1)*(7*n+1) - 7*(27*n^3+27*n^2+9*n+1)"
    by (simp add: add_mult_distrib2)
  then have 6:"... = (27*n^3+54*n^2+36*n+8)*(root 3 (7*n+1))^3-(27*n^3*(7*n+1)+27*n^2*(7*n+1)+9*n*(7*n+1)+(7*n+1)) - (7*27*n^3+7*27*n^2+7*9*n+7)"
    by (simp add: add_mult_distrib)
  then have 7:"... = (27*n^3+54*n^2+36*n+8)*(root 3 (7*n+1))^3-27*n^3*(7*n+1)-27*n^2*(7*n+1)-9*n*(7*n+1)-(7*n+1) - 189*n^3-189*n^2-63*n-7"
    by (simp add: add_mult_distrib)
  then have 8:"... =  27*n^3*(root 3 (7*n+1))^3+54*n^2*(root 3 (7*n+1))^3+36*n*(root 3 (7*n+1))^3+8*(root 3 (7*n+1))^3-27*n^3*(7*n+1)-27*n^2*(7*n+1)-9*n*(7*n+1)-(7*n+1) - 189*n^3-189*n^2-63*n-7"
    using add_mult_distrib
  by (simp add: semiring_normalization_rules(8))
  then have "8a":"... =  27*n^3*(7*n+1)+54*n^2*((root 3 (7*n+1))^3)+36*n*(root 3 (7*n+1))^3+8*(root 3 (7*n+1))^3-27*n^3*(7*n+1)-27*n^2*(7*n+1)-9*n*(7*n+1)-(7*n+1) - 189*n^3-189*n^2-63*n-7"
  by (smt of_nat_0_le_iff of_nat_mult real_root_pow_pos2 zero_less_numeral)
  then have 9:"... = 54*n^2*((root 3 (7*n+1))^3)+36*n*(root 3 (7*n+1))^3+8*(root 3 (7*n+1))^3-27*n^2*(7*n+1)-9*n*(7*n+1)-(7*n+1) - 189*n^3-189*n^2-63*n-7"
    by simp
  then have "... = 54*n^2*(7*n+1)+36*n*(root 3 (7*n+1))^3+8*(root 3 (7*n+1))^3-27*n^2*(7*n+1)-9*n*(7*n+1)-(7*n+1) - 189*n^3-189*n^2-63*n-7"
  by (metis (no_types, lifting) of_nat_0_le_iff of_nat_mult real_root_pow_pos2 zero_less_numeral)
  then have "... = 54*n^2*(7*n+1)+36*n*(7*n+1)+8*(root 3 (7*n+1))^3-27*n^2*(7*n+1)-9*n*(7*n+1)-(7*n+1) - 189*n^3-189*n^2-63*n-7"
  by (metis (no_types, lifting) of_nat_0_le_iff of_nat_add of_nat_mult real_root_pow_pos2 zero_less_numeral)
  then have 10:"... = 54*n^2*7*n+54*n^2+36*n*7*n+36*n+8*(root 3 (7*n+1))^3-(27*n^2*7*n+27*n^2)-(9*n*7*n+9*n)-(7*n+1) - 189*n^3-189*n^2-63*n-7"
    by simp
  then have 11:"... =378*n^2*n+54*n^2+252*n*n+36*n+8*(root 3 (7*n+1))^3-189*n^2*n-27*n^2-63*n*n-9*n-7*n-1 - 189*n^3-189*n^2-63*n-7"
    by auto
  then have 12:"...  = 378*n^3+54*n^2+252*n^2+36*n+8*(root 3 (7*n+1))^3-189*n^3-27*n^2-63*n^2-9*n-7*n-1 - 189*n^3-189*n^2-63*n-7"
  by (simp add: power2_eq_square power3_eq_cube)
  then have 13:"... = 54*n^2+252*n^2+36*n+8*(root 3 (7*n+1))^3-27*n^2-63*n^2-9*n-7*n-1 -189*n^2-63*n-7"
    by linarith
  then have 14:"... = 306*n^2+36*n+8*(root 3 (7*n+1))^3-1 -279*n^2-79*n-7"
  by (simp add: power2_eq_square power3_eq_cube)
  then have 15:"... = 306*n^2+36*n+8*(root 3 (7*n+1))^3 -279*n^2-23*n-56*n-8"
  by linarith
  then have 16:"... =306*n^2+36*n+8*(root 3 (7*n+1))^3 -279*n^2-23*n-8*(7*n+1)"
    using p2 by simp
  then have 17:"... =306*n^2+36*n+8*(root 3 (7*n+1))^3 -279*n^2-23*n-8*(root 3 (7*n+1))^3"
  by simp
  then have 18:"... = 306*n^2+36*n-279*n^2-23*n"
    by simp
  then have 19:"... = 27*n^2+13*n"
    by simp
  then have 23:"...\<ge>0"
    using assms zakljucak1
  using of_nat_0_le_iff by blast
  then show ?thesis
  by (smt "1" "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "2" "3" "4" "5" "5a" "6" "7" "8" "8a" \<open>real (54 * n\<^sup>2 * (7 * n + 1)) + real (36 * n) * root 3 (real (7 * n + 1)) ^ 3 + 8 * root 3 (real (7 * n + 1)) ^ 3 - real (27 * n\<^sup>2 * (7 * n + 1)) - real (9 * n * (7 * n + 1)) - real (7 * n + 1) - real (189 * n ^ 3) - real (189 * n\<^sup>2) - real (63 * n) - 7 = real (54 * n\<^sup>2 * (7 * n + 1) + 36 * n * (7 * n + 1)) + 8 * root 3 (real (7 * n + 1)) ^ 3 - real (27 * n\<^sup>2 * (7 * n + 1)) - real (9 * n * (7 * n + 1)) - real (7 * n + 1) - real (189 * n ^ 3) - real (189 * n\<^sup>2) - real (63 * n) - 7\<close> \<open>real (54 * n\<^sup>2) * root 3 (real (7 * n + 1)) ^ 3 + real (36 * n) * root 3 (real (7 * n + 1)) ^ 3 + 8 * root 3 (real (7 * n + 1)) ^ 3 - real (27 * n\<^sup>2 * (7 * n + 1)) - real (9 * n * (7 * n + 1)) - real (7 * n + 1) - real (189 * n ^ 3) - real (189 * n\<^sup>2) - real (63 * n) - 7 = real (54 * n\<^sup>2 * (7 * n + 1)) + real (36 * n) * root 3 (real (7 * n + 1)) ^ 3 + 8 * root 3 (real (7 * n + 1)) ^ 3 - real (27 * n\<^sup>2 * (7 * n + 1)) - real (9 * n * (7 * n + 1)) - real (7 * n + 1) - real (189 * n ^ 3) - real (189 * n\<^sup>2) - real (63 * n) - 7\<close>)
qed

lemma pomocna5[simp]:
  fixes n::nat
  assumes "n>0"
  shows "((3*(n+1)-1)*(root 3 (7*n+1)))^3\<ge>((3*(n+1)-2)*(root 3 (7*(n+1)+1)))^3"
  using assms
  using razlika_3korena2 by auto

lemma pomocna6[simp]:
  fixes n::nat
  assumes "n>0"
  shows "(3*(n+1)-1)*(root 3 (7*n+1))\<ge>(3*(n+1)-2)*(root 3 (7*(n+1)+1))"
  using assms
proof-
  have "((3*(n+1)-1)*(root 3 (7*n+1)))^3\<ge>((3*(n+1)-2)*(root 3 (7*(n+1)+1)))^3"
    using assms razlika_3korena2 by auto
  then have "root 3 (((3*(n+1)-1)*(root 3 (7*n+1)))^3)\<ge>root 3 (((3*(n+1)-2)*(root 3 (7*(n+1)+1)))^3)"
    using assms razlika_3korena2 by auto
  then show ?thesis
    by (simp add: real_root_power_cancel)
qed

lemma medjukorak1[simp]:
  fixes n::nat
  assumes "n>0"
  shows "((3*(n+1)-1)*(root 3 (7*n+1)))/(root 3 (7*(n+1)+1))\<ge>(3*(n+1)-2)"
  using assms
proof-
  have "(3*(n+1)-1)*(root 3 (7*n+1))\<ge>(3*(n+1)-2)*(root 3 (7*(n+1)+1))"
    using assms pomocna6 by blast
  then have "((3*(n+1)-1)*(root 3 (7*n+1)))/(root 3 (7*(n+1)+1))\<ge>((3*(n+1)-2)*(root 3 (7*(n+1)+1)))/(root 3 (7*(n+1)+1))"
  by (meson divide_right_mono of_nat_0_le_iff real_root_pos_pos_le)
  thus ?thesis
  by simp
qed

lemma kubiranje_12[simp]:
  fixes n::nat
  assumes "n>0"
  shows "root 3 (7*n+1)>0"
  by simp

lemma kljucni_korak_za_desnu_stranu[simp]:
  fixes n::nat
  assumes "n>0"
  shows "1/(root 3 (7*(n+1)+1))\<ge>(3*(n+1)-2)/((3*(n+1)-1)*(root 3 (7*n+1)))"
  using assms
proof-
  have "((3*(n+1)-1)*(root 3 (7*n+1)))/(root 3 (7*(n+1)+1))\<ge>(3*(n+1)-2)"
    using assms medjukorak1 by blast
 then have "((3*(n+1)-1)*(root 3 (7*n+1)))/(root 3 (7*(n+1)+1))*(1/(root 3 (7*n+1)))\<ge>(3*(n+1)-2)*(1/(root 3 (7*n+1)))"
   using kubiranje_12
  by (smt \<open>real (3 * (n + 1) - 2) \<le> real (3 * (n + 1) - 1) * root 3 (real (7 * n + 1)) / root 3 (real (7 * (n + 1) + 1))\<close> divide_right_mono mult_cancel_left2 of_nat_0_le_iff real_root_pos_pos_le times_divide_eq_right)
 then have "((3*(n+1)-1))/(root 3 (7*(n+1)+1))\<ge>(3*(n+1)-2)*(1/(root 3 (7*n+1)))"
  by simp
 then have "((3*(n+1)-1))/(root 3 (7*(n+1)+1))*(1/(3*(n+1)-1))\<ge>(3*(n+1)-2)*(1/(root 3 (7*n+1)))*(1/(3*(n+1)-1))"
  by (smt assms divide_le_0_1_iff of_nat_0_less_iff veci_od_nule1 real_mult_le_cancel_iff1)
 then have "1/(root 3 (7*(n+1)+1))\<ge>(3*(n+1)-2)*(1/(root 3 (7*n+1)))*(1/(3*(n+1)-1))"
   by simp
  then show ?thesis
  by (metis (no_types, hide_lams) divide_divide_eq_left' divide_inverse mult.left_neutral)
qed

theorem desna_strana:
  fixes n::nat
  assumes "n\<ge>1"
  shows "proizvod n \<le> 1/(root 3 (7*n+1))"
  using assms
proof(induction n)
case 0
then show ?case
  by simp
next
  case (Suc n)
  then have "proizvod (Suc n) = ((3*(Suc n) - 2)/(3*(Suc n) - 1)) *(proizvod n)"
    using proizvod.simps(2) by blast
  then have "... \<le> ((3*(Suc n) - 2)/(3*(Suc n) - 1))*(1/(root 3 (7*n+1)))"
  by (smt Suc.IH division_ring_divide_zero mult_left_mono mult_not_zero neq0_conv of_nat_0 of_nat_0_le_iff proizvod.simps(1) real_of_nat_div4 real_root_zero)
  then show ?case
  proof-
    have 1:"((3*(Suc n) - 2)/(3*(Suc n) - 1))*(1/(root 3 (7*n+1))) = (3*(Suc n) - 2)/((3*(Suc n) - 1)*(root 3 (7*n+1)))"
      by simp
    then have 2:"... = (3*(n+1) - 2)/((3*(n+1) - 1)*(root 3 (7*n+1)))"
      using Suc_eq_plus1 by presburger
    then have 3:"... \<le> 1/(root 3 (7*(n+1)+1))"
      using kljucni_korak_za_desnu_stranu assms  by fastforce
    then show ?thesis
    by (smt "1" Suc_eq_plus1 \<open>proizvod (Suc n) = real (3 * Suc n - 2) / real (3 * Suc n - 1) * proizvod n\<close> \<open>real (3 * Suc n - 2) / real (3 * Suc n - 1) * proizvod n \<le> real (3 * Suc n - 2) / real (3 * Suc n - 1) * (1 / root 3 (real (7 * n + 1)))\<close>)
    qed
  qed

theorem leva_strana:
  fixes n::nat
  assumes "n\<ge>1"
  shows "1/(root 3 (8*n)) \<le> proizvod n"
  using assms
proof(induction n)
  case 0
  then show ?case
  by auto
next
  case (Suc n)
   have "proizvod (Suc n) = ((3*(Suc n) - 2)/(3*(Suc n) - 1)) * (proizvod n)"
        using proizvod.simps(2) by blast
   then have "... \<ge> ((3*(Suc n) - 2)/(3*(Suc n) - 1)) * (1/(root 3 (8*n)))"
     by (smt Suc.IH division_ring_divide_zero mult_left_mono mult_not_zero neq0_conv of_nat_0 of_nat_0_le_iff proizvod.simps(1) real_of_nat_div4 real_root_zero)
   then show ?case
   proof-
     have 1:"((3*(Suc n) - 2)/(3*(Suc n) - 1)) * (1/(root 3 (8*n))) = (3*(Suc n) - 2)/((3*(Suc n) - 1)*(root 3 (8*n)))"
       by auto
     then have 2:"... = (3*(n+1) - 2)/((3*(n+1) - 1)*(root 3 (8*n)))"
       by auto
     then have 3:"(3*(n+1) - 2)/((3*(n+1) - 1)*(root 3 (8*n)))\<ge> 1/(root 3 (8*(n+1)))"
       using assms kljucan_dokaz_za_levu_stranu
       by fastforce
     then have 4:"(3*(Suc n) - 2)/((3*(Suc n) - 1)*(root 3 (8*n)))\<ge> 1/(root 3 (8*(Suc n)))"
     using Suc_eq_plus1 by presburger
     then show ?thesis
     using "1" \<open>proizvod (Suc n) = real (3 * Suc n - 2) / real (3 * Suc n - 1) * proizvod n\<close> \<open>real (3 * Suc n - 2) / real (3 * Suc n - 1) * (1 / root 3 (real (8 * n))) \<le> real (3 * Suc n - 2) / real (3 * Suc n - 1) * proizvod n\<close> by linarith
   qed
 qed

end


theory tree_sort_AddSame
imports Main
        "$HIPSTER_HOME/IsaHipster"
begin

datatype 'a list = Nil2 | Cons2 "'a" "'a list"

datatype 'a Tree = Node "'a Tree" "'a" "'a Tree" | Nil2

datatype Nat = Z | S "Nat"

fun le :: "Nat => Nat => bool" where
"le (Z) y = True"
| "le (S z) (Z) = False"
| "le (S z) (S x2) = le z x2"

fun flatten :: "'a Tree => 'a list => 'a list" where
"flatten (Node q z q2) y = flatten q (Cons2 z (flatten q2 y))"
| "flatten (Nil2) y = y"

fun equal2 :: "Nat => Nat => bool" where
"equal2 (Z) (Z) = True"
| "equal2 (Z) (S z) = False"
| "equal2 (S x2) (Z) = False"
| "equal2 (S x2) (S y2) = equal2 x2 y2"

fun count :: "Nat => Nat list => Nat" where
"count x (Nil2) = Z"
| "count x (Cons2 z xs) =
     (if equal2 x z then S (count x xs) else count x xs)"

fun add :: "Nat => Nat Tree => Nat Tree" where
"add x (Node q z q2) =
   (if le x z then Node (add x q) z q2 else Node q z (add x q2))"
| "add x (Nil2) = Node (Nil2) x (Nil2)"

(*hipster le flatten equal2 count add *)

theorem x0 :
  "!! (x :: Nat) (t :: Nat Tree) .
     (count x (flatten (add x t) (Nil2))) =
       (S (count x (flatten t (Nil2))))"
  by (tactic \<open>Subgoal.FOCUS_PARAMS (K (Tactic_Data.hard_tac @{context})) @{context} 1\<close>)

end


(*  Title:       Verification Examples
    Author:      Jonathan Julián Huerta y Munive, 2020
    Maintainer:  Jonathan Julián Huerta y Munive <jonjulian23@gmail.com>
*)

section \<open> Verification examples \<close>

theory MTX_Examples
  imports
    MTX_Flows
    "../HS_VC_Spartan"

begin

subsection \<open> Examples \<close>

abbreviation hoareT :: "('a \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'a set) \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> bool"
  ("PRE_ HP _ POST _" [85,85]85) where "PRE P HP X POST Q \<equiv> (P \<le> |X]Q)"

subsubsection \<open> Verification by uniqueness. \<close>

abbreviation mtx_circ :: "2 sq_mtx" ("A")
  where "A \<equiv> mtx
   ([0,  1] #
    [-1, 0] # [])"

abbreviation mtx_circ_flow :: "real \<Rightarrow> real^2 \<Rightarrow> real^2" ("\<phi>")
  where "\<phi> t s \<equiv> (\<chi> i. if i = 1 then s$1 * cos t + s$2 * sin t else - s$1 * sin t + s$2 * cos t)"

lemma mtx_circ_flow_eq: "exp (t *\<^sub>R A) *\<^sub>V s = \<phi> t s"
  apply(rule local_flow.eq_solution[OF local_flow_sq_mtx_linear, symmetric, of _ "\<lambda>s. UNIV"], simp_all)
    apply(rule ivp_solsI, simp_all add: sq_mtx_vec_mult_eq vec_eq_iff)
  unfolding UNIV_2 using exhaust_2
  by (force intro!: poly_derivatives simp: matrix_vector_mult_def)+

lemma mtx_circ:
  "PRE(\<lambda>s. r\<^sup>2 = (s $ 1)\<^sup>2 + (s $ 2)\<^sup>2)
  HP x\<acute>=(*\<^sub>V) A & G
  POST (\<lambda>s. r\<^sup>2 = (s $ 1)\<^sup>2 + (s $ 2)\<^sup>2)"
  apply(subst local_flow.fbox_g_ode_subset[OF local_flow_sq_mtx_linear])
  unfolding mtx_circ_flow_eq by auto

no_notation mtx_circ ("A")
        and mtx_circ_flow ("\<phi>")

subsubsection \<open> Flow of diagonalisable matrix. \<close>

abbreviation mtx_hOsc :: "real \<Rightarrow> real \<Rightarrow> 2 sq_mtx" ("A")
  where "A a b \<equiv> mtx
   ([0, 1] #
    [a, b] # [])"

abbreviation mtx_chB_hOsc :: "real \<Rightarrow> real \<Rightarrow> 2 sq_mtx" ("P")
  where "P a b \<equiv> mtx
   ([a, b] #
    [1, 1] # [])"

lemma inv_mtx_chB_hOsc:
  "a \<noteq> b \<Longrightarrow> (P a b)\<^sup>-\<^sup>1 = (1/(a - b)) *\<^sub>R mtx
   ([ 1, -b] #
    [-1,  a] # [])"
  apply(rule sq_mtx_inv_unique, unfold scaleR_mtx2 times_mtx2)
  by (simp add: diff_divide_distrib[symmetric] one_mtx2)+

lemma invertible_mtx_chB_hOsc: "a \<noteq> b \<Longrightarrow> mtx_invertible (P a b)"
  apply(rule mtx_invertibleI[of _ "(P a b)\<^sup>-\<^sup>1"])
   apply(unfold inv_mtx_chB_hOsc scaleR_mtx2 times_mtx2 one_mtx2)
  by (subst sq_mtx_eq_iff, simp add: vector_def frac_diff_eq1)+

lemma mtx_hOsc_diagonalizable:
  fixes a b :: real
  defines "\<iota>\<^sub>1 \<equiv> (b - sqrt (b^2+4*a))/2" and "\<iota>\<^sub>2 \<equiv> (b + sqrt (b^2+4*a))/2"
  assumes "b\<^sup>2 + a * 4 > 0" and "a \<noteq> 0"
  shows "A a b = P (-\<iota>\<^sub>2/a) (-\<iota>\<^sub>1/a) * (\<d>\<i>\<a>\<g> i. if i = 1 then \<iota>\<^sub>1 else \<iota>\<^sub>2) * (P (-\<iota>\<^sub>2/a) (-\<iota>\<^sub>1/a))\<^sup>-\<^sup>1"
  unfolding assms apply(subst inv_mtx_chB_hOsc)
  using assms(3,4) apply(simp_all add: diag2_eq[symmetric])
  unfolding sq_mtx_times_eq sq_mtx_scaleR_eq UNIV_2 apply(subst sq_mtx_eq_iff)
  using exhaust_2 assms by (auto simp: field_simps, auto simp: field_power_simps)

lemma mtx_hOsc_solution_eq:
  fixes a b :: real
  defines "\<iota>\<^sub>1 \<equiv> (b - sqrt (b\<^sup>2+4*a))/2" and "\<iota>\<^sub>2 \<equiv> (b + sqrt (b\<^sup>2+4*a))/2"
  defines "\<Phi> t \<equiv> mtx (
   [\<iota>\<^sub>2*exp(t*\<iota>\<^sub>1) - \<iota>\<^sub>1*exp(t*\<iota>\<^sub>2),     exp(t*\<iota>\<^sub>2)-exp(t*\<iota>\<^sub>1)]#
   [a*exp(t*\<iota>\<^sub>2) - a*exp(t*\<iota>\<^sub>1), \<iota>\<^sub>2*exp(t*\<iota>\<^sub>2)-\<iota>\<^sub>1*exp(t*\<iota>\<^sub>1)]#[])"
  assumes "b\<^sup>2 + a * 4 > 0" and "a \<noteq> 0"
  shows "P (-\<iota>\<^sub>2/a) (-\<iota>\<^sub>1/a) * (\<d>\<i>\<a>\<g> i. exp (t * (if i=1 then \<iota>\<^sub>1 else \<iota>\<^sub>2))) * (P (-\<iota>\<^sub>2/a) (-\<iota>\<^sub>1/a))\<^sup>-\<^sup>1
  = (1/sqrt (b\<^sup>2 + a * 4)) *\<^sub>R (\<Phi> t)"
  unfolding assms apply(subst inv_mtx_chB_hOsc)
  using assms apply(simp_all add: mtx_times_scaleR_commute, subst sq_mtx_eq_iff)
  unfolding UNIV_2 sq_mtx_times_eq sq_mtx_scaleR_eq sq_mtx_uminus_eq apply(simp_all add: axis_def)
  by (auto simp: field_simps, auto simp: field_power_simps)+

lemma local_flow_mtx_hOsc:
  fixes a b
  defines "\<iota>\<^sub>1 \<equiv> (b - sqrt (b^2+4*a))/2" and "\<iota>\<^sub>2 \<equiv> (b + sqrt (b^2+4*a))/2"
  defines "\<Phi> t \<equiv> mtx (
   [\<iota>\<^sub>2*exp(t*\<iota>\<^sub>1) - \<iota>\<^sub>1*exp(t*\<iota>\<^sub>2),     exp(t*\<iota>\<^sub>2)-exp(t*\<iota>\<^sub>1)]#
   [a*exp(t*\<iota>\<^sub>2) - a*exp(t*\<iota>\<^sub>1), \<iota>\<^sub>2*exp(t*\<iota>\<^sub>2)-\<iota>\<^sub>1*exp(t*\<iota>\<^sub>1)]#[])"
  assumes "b\<^sup>2 + a * 4 > 0" and "a \<noteq> 0"
  shows "local_flow ((*\<^sub>V) (A a b)) UNIV UNIV (\<lambda>t. (*\<^sub>V) ((1/sqrt (b\<^sup>2 + a * 4)) *\<^sub>R \<Phi> t))"
  unfolding assms using local_flow_sq_mtx_linear[of "A a b"] assms
  apply(subst (asm) exp_scaleR_diagonal2[OF invertible_mtx_chB_hOsc mtx_hOsc_diagonalizable])
     apply(simp, simp, simp)
  by (subst (asm) mtx_hOsc_solution_eq) simp_all

lemma overdamped_door_arith:
  assumes "b\<^sup>2 + a * 4 > 0" and "a < 0" and "b \<le> 0" and "t \<ge> 0" and "s1 > 0"
  shows "0 \<le> ((b + sqrt (b\<^sup>2 + 4 * a)) * exp (t * (b - sqrt (b\<^sup>2 + 4 * a)) / 2) / 2 -
(b - sqrt (b\<^sup>2 + 4 * a)) * exp (t * (b + sqrt (b\<^sup>2 + 4 * a)) / 2) / 2) * s1 / sqrt (b\<^sup>2 + a * 4)"
proof(subst diff_divide_distrib[symmetric], simp)
  have f0: "s1 / (2 * sqrt (b\<^sup>2 + a * 4)) > 0"  (is "s1/?c3 > 0")
    using assms(1,5) by simp
  have f1: "(b - sqrt (b\<^sup>2 + 4 * a)) < (b + sqrt (b\<^sup>2 + 4 * a))" (is "?c2 < ?c1")
    and f2: "(b + sqrt (b\<^sup>2 + 4 * a)) < 0"
    using sqrt_ge_absD[of b "b\<^sup>2 + 4 * a"] assms by (force, linarith)
  hence f3: "exp (t * ?c2 / 2) \<le> exp (t * ?c1 / 2)" (is "exp ?t1 \<le> exp ?t2")
    unfolding exp_le_cancel_iff
    using assms(4) by (case_tac "t=0", simp_all)
  hence "?c2 * exp ?t2 \<le> ?c2 * exp ?t1"
    using f1 f2 real_mult_le_cancel_iff2[of "-?c2" "exp ?t1" "exp ?t2"] by linarith
  also have "... < ?c1 * exp ?t1"
    using f1 by auto
  also have"... \<le> ?c1 * exp ?t1"
    using f1 f2 by auto
  ultimately show "0 \<le> (?c1 * exp ?t1 - ?c2 * exp ?t2) * s1 / ?c3"
    using f0 f1 assms(5) by auto
qed

abbreviation "open_door s \<equiv> {s. s$1 > 0 \<and> s$2 = 0}"

lemma overdamped_door:
  assumes "b\<^sup>2 + a * 4 > 0" and "a < 0" and "b \<le> 0"
  shows "PRE (\<lambda>s. s$1 = 0)
  HP (LOOP open_door; (x\<acute>=((*\<^sub>V) (A a b)) & G) INV (\<lambda>s. 0 \<le> s$1))
  POST (\<lambda>s. 0 \<le> s $ 1)"
  apply(rule fbox_loopI, simp_all add: le_fun_def)
  apply(subst local_flow.fbox_g_ode_subset[OF local_flow_mtx_hOsc[OF assms(1)]])
  using assms apply(simp_all add: le_fun_def fbox_def)
  unfolding sq_mtx_scaleR_eq UNIV_2 sq_mtx_vec_mult_eq
  by (clarsimp simp: overdamped_door_arith)

no_notation mtx_hOsc ("A")
        and mtx_chB_hOsc ("P")

subsubsection \<open> Flow of non-diagonalisable matrix. \<close>

abbreviation mtx_cnst_acc :: "3 sq_mtx" ("K")
  where "K \<equiv> mtx (
  [0,1,0] #
  [0,0,1] #
  [0,0,0] # [])"

lemma pow2_scaleR_mtx_cnst_acc: "(t *\<^sub>R K)\<^sup>2 = mtx (
  [0,0,t\<^sup>2] #
  [0,0,0] #
  [0,0,0] # [])"
  unfolding power2_eq_square apply(subst sq_mtx_eq_iff)
  unfolding sq_mtx_times_eq UNIV_3 by auto

lemma powN_scaleR_mtx_cnst_acc: "n > 2 \<Longrightarrow> (t *\<^sub>R K)^n = 0"
  apply(induct n, simp, case_tac "n \<le> 2")
   apply(subgoal_tac "n = 2", erule ssubst)
  unfolding power_Suc2 pow2_scaleR_mtx_cnst_acc sq_mtx_times_eq UNIV_3
  by (auto simp: sq_mtx_eq_iff)

lemma exp_mtx_cnst_acc_vec_mult_eq: "exp (t *\<^sub>R K) *\<^sub>V s =
  vector [s$3 * t^2/2 + s$2 * t + s$1, s$3 * t + s$2, s$3]"
  apply(subst exp_mtx_cnst_acc, subst pow2_scaleR_mtx_cnst_acc)
  apply(simp add: sq_mtx_vec_mult_eq vector_def)
  unfolding UNIV_3 by (simp add: fun_eq_iff)

lemma local_flow_mtx_cnst_acc:
  "local_flow ((*\<^sub>V) K) UNIV UNIV (\<lambda>t s. ((t *\<^sub>R K)\<^sup>2/\<^sub>R 2 + (t *\<^sub>R K) + 1) *\<^sub>V s)"
  using local_flow_sq_mtx_linear[of K] unfolding exp_mtx_cnst_acc .

lemma docking_station_arith:
  assumes "(d::real) > x" and "v > 0"
  shows "(v = v\<^sup>2 * t / (2 * d - 2 * x)) \<longleftrightarrow> (v * t - v\<^sup>2 * t\<^sup>2 / (4 * d - 4 * x) + x = d)"
proof
  assume "v = v\<^sup>2 * t / (2 * d - 2 * x)"
  hence "v * t = 2 * (d - x)"
    using assms by (simp add: eq_divide_eq power2_eq_square)
  hence "v * t - v\<^sup>2 * t\<^sup>2 / (4 * d - 4 * x) + x = 2 * (d - x) - 4 * (d - x)\<^sup>2 / (4 * (d - x)) + x"
    apply(subst power_mult_distrib[symmetric])
    by (erule ssubst, subst power_mult_distrib, simp)
  also have "... = d"
    apply(simp only: mult_divide_mult_cancel_left_if)
    using assms by (auto simp: power2_eq_square)
  finally show "v * t - v\<^sup>2 * t\<^sup>2 / (4 * d - 4 * x) + x = d" .
next
  assume "v * t - v\<^sup>2 * t\<^sup>2 / (4 * d - 4 * x) + x = d"
  hence "0 = v\<^sup>2 * t\<^sup>2 / (4 * (d - x)) + (d - x) - v * t"
    by auto
  hence "0 = (4 * (d - x)) * (v\<^sup>2 * t\<^sup>2 / (4 * (d - x)) + (d - x) - v * t)"
    by auto
  also have "... = v\<^sup>2 * t\<^sup>2 + 4 * (d - x)\<^sup>2  - (4 * (d - x)) * (v * t)"
    using assms apply(simp add: distrib_left right_diff_distrib)
    apply(subst right_diff_distrib[symmetric])+
    by (simp add: power2_eq_square)
  also have "... = (v * t - 2 * (d - x))\<^sup>2"
    by (simp only: power2_diff, auto simp: field_simps power2_diff)
  finally have "0 = (v * t - 2 * (d - x))\<^sup>2" .
  hence "v * t = 2 * (d - x)"
    by auto
  thus "v = v\<^sup>2 * t / (2 * d - 2 * x)"
    apply(subst power2_eq_square, subst mult.assoc)
    apply(erule ssubst, subst right_diff_distrib[symmetric])
    using assms by auto
qed

lemma docking_station:
  assumes "d > x\<^sub>0" and "v\<^sub>0 > 0"
  shows "PRE (\<lambda>s. s$1 = x\<^sub>0 \<and> s$2 = v\<^sub>0)
  HP ((3 ::= (\<lambda>s. -(v\<^sub>0^2/(2*(d-x\<^sub>0))))); x\<acute>=(*\<^sub>V) K & G)
  POST (\<lambda>s. s$2 = 0 \<longleftrightarrow> s$1 = d)"
  apply(clarsimp simp: le_fun_def local_flow.fbox_g_ode_subset[OF local_flow_sq_mtx_linear[of K]])
  unfolding exp_mtx_cnst_acc_vec_mult_eq using assms by (simp add: docking_station_arith)

no_notation mtx_cnst_acc ("K")

end


theory NgFHOL_pol imports Main
begin

(* A polymorphic Embedding of Negative Free Higher-Order Logic (NgFHOL) in HOL *)

text \<open> Negative Free Higher-Order Logic \<close>

  typedecl i (* — Type for individuals *)

  consts fExistence :: "'a \<Rightarrow> bool" ("E") (* — Existence/definedness predicate *)

  consts fUndef :: "'a" ("\<^bold>e") (* Distinguished symbol for undefinedness *)
  axiomatization where fUndefIAxiom: "\<not>E (\<^bold>e::i)"
  axiomatization where fFalsehoodBAxiom: "(\<^bold>e::bool) = False"
  axiomatization where fTrueAxiom: "E True"
  axiomatization where fFalseAxiom: "E False"

  (* axiomatization where fNonemptyDomains: "\<exists>x. E x" *)

  definition fIdentity :: "'a \<Rightarrow> 'a \<Rightarrow> bool" (infixr "\<^bold>=" 56) (* — Free identity *)
    where "\<phi> \<^bold>= \<psi> \<equiv> E \<phi> \<and> E \<psi> \<and> (\<phi> = \<psi>)"

  definition fNot :: "bool \<Rightarrow> bool" ("\<^bold>\<not>_" [52]53) (* — Free negation *)
    where "\<^bold>\<not>\<phi> \<equiv> \<not>\<phi>"
  definition fOr :: "bool \<Rightarrow> bool \<Rightarrow> bool" (infixr "\<^bold>\<or>" 51) (* — Free disjunction *)
    where "\<phi> \<^bold>\<or> \<psi> \<equiv> \<phi> \<or> \<psi>"

  definition fForall :: "('a \<Rightarrow> bool) \<Rightarrow> bool" ("\<^bold>\<forall>") (* — Free universal quantification guarded by predicate E *)
    where "\<^bold>\<forall>\<Phi> \<equiv> \<forall>x. E x \<longrightarrow> \<Phi> x"
  definition fForallBinder:: "('a \<Rightarrow> bool) \<Rightarrow> bool" (binder "\<^bold>\<forall>" [8]9) (* — Binder notation *)
    where "\<^bold>\<forall>x. \<phi> x \<equiv> \<^bold>\<forall>\<phi>"

  definition fThat :: "('a \<Rightarrow> bool) \<Rightarrow> 'a" ("\<^bold>I") (* — Free definite description guarded by predicate E *)
    where "\<^bold>I\<Phi> \<equiv> if \<exists>x. E x \<and> \<Phi> x \<and> (\<forall>y. (E y \<and> \<Phi> y) \<longrightarrow> (y = x))
                 then THE x. E x \<and> \<Phi> x
                 else \<^bold>e"
  definition fThatBinder:: "('a \<Rightarrow> bool) \<Rightarrow> 'a" (binder "\<^bold>I" [8]9) (* — Binder notation *)
    where "\<^bold>Ix. \<phi> x \<equiv> \<^bold>I\<phi>"

  definition fPredicate1 :: "('a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> bool" ("\<^sup>n") (* — Free predicate guarded by predicate E *)
    where "\<^sup>nP x \<equiv> E x \<and> P x"
  definition fPredicate2 :: "('a \<Rightarrow> 'b \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'b \<Rightarrow> bool" ("\<^sup>n\<^sup>n") (* — Free predicate guarded by predicate E *)
    where "\<^sup>n\<^sup>nP x y \<equiv> E x \<and> E y \<and> P x y"

  text \<open> Further logical constants can be defined as usual \<close>

  definition fAnd :: "bool \<Rightarrow> bool \<Rightarrow> bool" (infixr "\<^bold>\<and>" 52) (* — Free conjunction *)
    where "\<phi> \<^bold>\<and> \<psi> \<equiv> \<^bold>\<not>(\<^bold>\<not>\<phi> \<^bold>\<or> \<^bold>\<not>\<psi>)"
  definition fImp :: "bool \<Rightarrow> bool \<Rightarrow> bool" (infixr "\<^bold>\<rightarrow>" 49) (* — Free implication *)
    where "\<phi> \<^bold>\<rightarrow> \<psi> \<equiv> \<^bold>\<not>\<phi> \<^bold>\<or> \<psi>"
  definition fEquiv :: "bool \<Rightarrow> bool \<Rightarrow> bool" (infixr "\<^bold>\<leftrightarrow>" 50) (* — Free equivalence *)
    where "\<phi> \<^bold>\<leftrightarrow> \<psi> \<equiv> \<phi> \<^bold>\<rightarrow> \<psi> \<^bold>\<and> \<psi> \<^bold>\<rightarrow> \<phi>"

  definition fExists :: "('a \<Rightarrow> bool) \<Rightarrow> bool" ("\<^bold>\<exists>") (* — Free existential quantification *)
    where "\<^bold>\<exists>\<Phi> \<equiv> \<^bold>\<not>(\<^bold>\<forall>(\<lambda>y. \<^bold>\<not>(\<Phi> y)))"
  definition fExistsBinder :: "('a \<Rightarrow> bool) \<Rightarrow> bool" (binder "\<^bold>\<exists>" [8]9) (* — Binder notation *)
    where "\<^bold>\<exists>x. \<phi> x \<equiv> \<^bold>\<exists>\<phi>"

  (* Introducing "Defs" as the set of the above definitions; useful for convenient unfolding *)
  named_theorems Defs declare fIdentity_def[Defs] fNot_def[Defs] fOr_def[Defs] fForall_def[Defs]
    fForallBinder_def[Defs] fThat_def[Defs] fPredicate1_def[Defs] fPredicate2_def[Defs]
    fThatBinder_def[Defs] fAnd_def[Defs] fImp_def[Defs] fEquiv_def[Defs] fExists_def[Defs]
    fExistsBinder_def[Defs]

text \<open> Some Tests \<close>

  lemma "(\<^bold>\<forall>x. \<^sup>nP x) \<^bold>\<rightarrow> \<^sup>nP x" nitpick [user_axioms=true, show_all, format=2] oops (* properly invalid *)
  lemma "((\<^bold>\<forall>x. (\<^sup>nP x)) \<^bold>\<and> (E x)) \<^bold>\<rightarrow> (\<^sup>nP x)"
    by (metis fAnd_def fForallBinder_def fForall_def fImp_def fNot_def fOr_def) (* properly valid *)

  lemma "\<^sup>nP x \<^bold>\<rightarrow> (\<^bold>\<exists>x. \<^sup>nP x)" unfolding Defs by auto (* properly valid *)
  lemma "(x \<^bold>= y) \<^bold>\<rightarrow> (\<^bold>\<exists>x. (x \<^bold>= y))" unfolding Defs by blast (* properly valid *)
  lemma "(x \<^bold>\<or> y) \<^bold>\<rightarrow> (\<^bold>\<exists>x. (x \<^bold>\<or> y))" unfolding Defs using fTrueAxiom by auto (* properly valid *)
  lemma "(\<^sup>nP x) \<^bold>\<and> (\<^bold>\<exists>x. \<^sup>nP x)" nitpick [user_axioms=true, show_all, format=2] oops (* properly invalid *)
  lemma "(\<^sup>nP x) \<^bold>\<rightarrow> (E x)" unfolding Defs by simp (* properly valid *)

  lemma "(\<^sup>nP x) \<^bold>\<or> (\<^bold>\<not>(\<^sup>nP x))" unfolding Defs by auto (* properly valid *)
  lemma "(\<^sup>nP x) \<^bold>\<and> (\<^bold>\<not>(\<^sup>nP x))" nitpick [user_axioms=true, show_all, format=2] oops (* properly invalid *)
  lemma "\<^bold>\<not>((\<^sup>nP x) \<^bold>\<and> (\<^bold>\<not>(\<^sup>nP x)))" unfolding Defs by auto (* properly valid *)

  consts fIndividual1 :: "i" ("i\<^sub>1")
  axiomatization where fUndefIndividual1Axiom: "\<^bold>\<not>(E i\<^sub>1)"

  consts fIndividual2 :: "i" ("i\<^sub>2")
  axiomatization where fUndefIndividual2Axiom: "\<^bold>\<not>(E i\<^sub>2)"

  lemma "x \<^bold>= x" nitpick [user_axioms=true, show_all, format=2] oops (* properly invalid *)
  lemma "i\<^sub>1 \<^bold>= i\<^sub>1" nitpick [user_axioms=true, show_all, format=2] oops (* properly invalid *)
  lemma "\<^bold>\<not>(i\<^sub>1 \<^bold>= i\<^sub>1)" unfolding Defs using fNot_def fUndefIndividual1Axiom by auto (* properly valid *)

  lemma test_True: "True" by simp
  lemma test_False: "False" nitpick [satisfy, user_axioms=true] oops

text \<open> Prior's Theorem \<close>

  lemma "(Q (\<forall>p. (Q p \<longrightarrow> (\<not>p)))) \<longrightarrow> ((\<exists>p. Q p \<and> p) \<and> (\<exists>p. Q p \<and> (\<not>p)))" by blast

  lemma "(\<^sup>nQ (\<^bold>\<forall>p. (\<^sup>nQ p \<^bold>\<rightarrow> (\<^bold>\<not>p)))) \<^bold>\<rightarrow> ((\<^bold>\<exists>p. \<^sup>nQ p \<^bold>\<and> p) \<^bold>\<and> (\<^bold>\<exists>p. \<^sup>nQ p \<^bold>\<and> (\<^bold>\<not>p)))" unfolding Defs by smt


theory hw03
  imports  "~~/src/HOL/Library/Tree" Main
begin

(* Part 1 - complete*)

declare Let_def [simp]

datatype direction = L|R
type_synonym path = "direction list"

fun valid:: "'a tree \<Rightarrow> path \<Rightarrow> bool" where
  "valid _ [] = True"
| "valid Leaf _ = False"
| "valid (Node ltr a rtr) (x#xs) = (if x = L then (valid ltr xs) else (valid rtr xs))"

fun get:: "'a tree \<Rightarrow> path \<Rightarrow> 'a tree" where
  "get x [] = x"
| "get (Node ltr a rtr) (x# xs) = (if x = L then get ltr xs else get rtr xs)"
| "get _ _ = undefined "

fun put:: "'a tree \<Rightarrow> path \<Rightarrow> 'a tree \<Rightarrow> 'a tree" where
  "put x [] y = y"
| "put Leaf _ _ = Leaf"
| "put (Node l a r) (x# xs) y = (if x = L then (Node (put l xs y) a r) else (Node l a (put r xs y)))"

value "put (Node (Node (Leaf) b (Leaf)) d Leaf) [R,R] (Node Leaf q Leaf)"
value "valid (Node Leaf a Leaf) [R]"

lemma put_invalid[simp]: "\<not>valid t p \<Longrightarrow> put t p s = t"
  apply(induction p rule:valid.induct)
     apply(auto)
  done

lemma get_put[simp]: "put t p (get t p) = t"
  apply(induction p rule:get.induct)
     apply(auto)
  done

lemma put_put[simp]: "valid t p \<Longrightarrow> put (put t p s) p s' = put t p s'"
  apply(induction p arbitrary:s' rule: valid.induct)
  apply(auto)
  done

lemma put_get[simp]: "valid t p \<Longrightarrow> get (put t p s) p = s"
  apply(induction t p rule:get.induct)
    apply(auto)
  done

lemma valid_put[simp]: "valid t p \<longleftrightarrow> valid (put t p s) p"
  apply(induction t p rule:valid.induct)
    apply(auto)
  done

lemma valid_append[simp]: "valid t (p@q)\<longleftrightarrow> valid t p \<and> valid (get t p) q"
  apply(induction t p rule:valid.induct)
    apply auto
  done

lemma get_append[simp]: "valid t p \<Longrightarrow> get t (p@q) = get (get t p) q"
  apply(induction t p rule:get.induct)
    apply auto
  done

lemma put_append[simp]: "put t (p@q) s = put t p (put (get t p) q s)"
  apply(induction t p rule:get.induct)
  apply auto
  done

(*Part 2 - Incomplete, bst_remdups done, sublist done, first proof done with a generalization which I couldn't prove*)

fun ins :: "'a::linorder \<Rightarrow> 'a tree \<Rightarrow> 'a tree" where
"ins x Leaf = Node Leaf x Leaf" |
"ins x (Node l a r) =
  (if x < a then Node (ins x l) a r else
   if x > a then Node l a (ins x r)
   else Node l a r)"

fun bst_remdups_aux:: "'a::linorder tree \<Rightarrow> 'a list \<Rightarrow> 'a list" where
  "bst_remdups_aux t [] = inorder t"
| "bst_remdups_aux t (x # xs) = bst_remdups_aux (ins x t) xs"

definition "bst_remdups xs \<equiv> bst_remdups_aux Leaf xs"

value "bst_remdups [1::int,2,3,4,1,5,5,6,6,10,7]"

value "bst_remdups_aux (Node Leaf (7::nat) (Node Leaf (1::nat) Leaf)) [2::nat]"

lemma bst_gen[simp]:"set (bst_remdups_aux t s) = set(bst_remdups_aux t []) \<union> set s"
  sorry

value "filter (\<lambda>x. x \<le> (2::nat)) [2::nat,3,4]"

lemma "set (bst_remdups xs) = set xs"
  unfolding bst_remdups_def
  apply(induction xs)
  apply(auto)
  done

fun remove:: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
  "remove a [] = []"
| "remove a (x #xs) = (if (a = x) then xs else x #(remove a xs))"

fun sublist:: "'a list \<Rightarrow> 'a list \<Rightarrow> bool" where
  "sublist [] ys = True"
| "sublist xs [] = False"
| "sublist (x#xs) ys = (if x\<in> set ys then sublist xs (remove x ys) else False)"

end


(* Title:  Weighted_Graph.thy
   Author: Lars Noschinski, TU München
*)

theory Weighted_Graph
imports
  Digraph
  Arc_Walk
  Complex_Main
begin

section \<open>Weighted Graphs\<close>

type_synonym 'b weight_fun = "'b \<Rightarrow> real"

context wf_digraph begin

definition awalk_cost :: "'b weight_fun \<Rightarrow> 'b awalk \<Rightarrow> real" where
  "awalk_cost f es = sum_list (map f es)"

lemma awalk_cost_Nil[simp]: "awalk_cost f [] = 0"
  unfolding awalk_cost_def by simp

lemma awalk_cost_Cons[simp]: "awalk_cost f (x # xs) = f x + awalk_cost  f xs"
  unfolding awalk_cost_def by simp

lemma awalk_cost_append[simp]:
  "awalk_cost f (xs @ ys) = awalk_cost f xs + awalk_cost f ys"
  unfolding awalk_cost_def by simp

end

end


theory DemoComp = Main:

datatype binop = Plus | Minus | Mult

datatype 'v expr = Const nat
                 | Var 'v
                 | Binop binop "'v expr"  "'v expr"

consts semop :: "binop \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat" ("\<lbrakk>_\<rbrakk>")
primrec
  "\<lbrakk>Plus\<rbrakk> = (\<lambda>x y. x + y)"
  "\<lbrakk>Minus\<rbrakk> = (\<lambda>x y. x - y)"
  "\<lbrakk>Mult\<rbrakk> = (\<lambda>x y. x * y)"

consts value :: "'v expr \<Rightarrow> ('v \<Rightarrow> nat) \<Rightarrow> nat"
primrec
  "value (Const v) E = v"
  "value (Var a) E = E a"
  "value (Binop f e\<^isub>1 e\<^isub>2) E = \<lbrakk>f\<rbrakk> (value e\<^isub>1 E) (value e\<^isub>2 E)";

datatype 'v instr = Push nat
                  | Load 'v
                  | Apply binop

consts exec :: "'v instr list \<Rightarrow> ('v \<Rightarrow> nat) \<Rightarrow> nat list \<Rightarrow> nat list"
primrec
  "exec [] s vs = vs"
  "exec (i#is) s vs = (case i of
    Push v  \<Rightarrow> exec is s (v # vs)
  | Load a  \<Rightarrow> exec is s (s a # vs)
  | Apply f \<Rightarrow> let v\<^isub>1 = hd vs; v\<^isub>2 = hd (tl vs); ts = tl (tl vs) in
               exec is s (\<lbrakk>f\<rbrakk> v\<^isub>1 v\<^isub>2 # ts))"

consts cmp :: "'v expr \<Rightarrow> 'v instr list"
primrec
  "cmp (Const v) = [Push v]"
  "cmp (Var a) = [Load a]"
  "cmp (Binop f e\<^isub>1 e\<^isub>2) = (cmp e\<^isub>2) @ (cmp e\<^isub>1) @ [Apply f]"

theorem "exec (cmp e) s [] = [value e s]"

oops
-- solution

lemma exec_append [simp]:
  "\<And>st. exec (is\<^isub>1@is\<^isub>2) s st = exec is\<^isub>2 s (exec is\<^isub>1 s st)"
proof (induct is\<^isub>1)
  fix st show "exec ([] @ is\<^isub>2) s st = exec is\<^isub>2 s (exec [] s st)" by simp
next
  fix st i "is"
  assume IH: "\<And>st. exec (is@is\<^isub>2) s st = exec is\<^isub>2 s (exec is s st)"
  show "exec ((i#is) @ is\<^isub>2) s st = exec is\<^isub>2 s (exec (i#is) s st)"
  proof (cases i)
    fix n assume "i = Push n" then show ?thesis by (simp add: IH)
  next
    fix v assume "i = Load v" then show ?thesis by (simp add: IH)
  next
    fix f assume "i = Apply f" then show ?thesis by (simp add: IH Let_def)
  qed
qed

lemma correct:
  "\<And>st. exec (cmp e) s st = value e s # st"
proof (induct e)
  fix st n
  show "exec (cmp (Const n)) s st = value (Const n) s # st" by simp
next
  fix st v
  show "exec (cmp (Var v)) s st = value (Var v) s # st" by simp
next
  fix st f e\<^isub>1 e\<^isub>2
  assume
    "\<And>st. exec (cmp e\<^isub>1) s st = value e\<^isub>1 s # st" and
    "\<And>st. exec (cmp e\<^isub>2) s st = value e\<^isub>2 s # st"
  then
  show "exec (cmp (Binop f e\<^isub>1 e\<^isub>2)) s st = value (Binop f e\<^isub>1 e\<^isub>2) s # st"
    by (simp add: Let_def)
qed

corollary "exec (cmp e) s [] = [value e s]" by (rule correct)

end


header{* Lattice Orderd Groups *}

(*
    Author: Viorel Preoteasa
*)

theory Lattice_Ordered_Group
imports Modular_Distrib_Lattice
begin

text{*
This theory introduces lattice ordered groups \cite{birkhoff:1942}
and proves some results about them. The most important result is
that a lattice ordered group is also a distributive lattice.
*}

class lgroup = group_add + lattice +
assumes add_order_preserving: "a \<le> b \<Longrightarrow> u + a + v \<le> u + b + v"
begin

lemma add_order_preserving_left: "a \<le> b \<Longrightarrow> u + a \<le> u + b"
  apply (cut_tac a = a and b = b and u = u and v = 0 in add_order_preserving)
  by simp_all

lemma add_order_preserving_right: "a \<le> b \<Longrightarrow> a + v \<le> b + v"
  apply (cut_tac a = a and b = b and u = 0 and v = v in add_order_preserving)
  by simp_all

lemma minus_order: "-a \<le> -b \<Longrightarrow> b \<le> a"
  apply (cut_tac a = "-a" and b = "-b" and u = a and v = b in add_order_preserving)
  by simp_all

lemma right_move_to_left: "a + - c \<le> b \<Longrightarrow> a \<le> b + c"
  apply (drule_tac v = "c" in add_order_preserving_right)
  by (simp add: add.assoc)

lemma right_move_to_right: "a \<le> b + -c \<Longrightarrow> a + c \<le> b"
  apply (drule_tac v = "c" in add_order_preserving_right)
  by (simp add: add.assoc)

lemma [simp]: "(a \<sqinter> b) - c = (a - c) \<sqinter> (b - c)"
  by (simp add: diff_conv_add_uminus del: add_uminus_conv_diff)

lemma left_move_to_left: "-c + a \<le> b \<Longrightarrow> a \<le> c + b"
  apply (drule_tac u = "c" in add_order_preserving_left)
  by (simp add: add.assoc [THEN sym])

lemma left_move_to_right: "a \<le> - c + b \<Longrightarrow> c + a \<le> b"
  apply (drule_tac u = "c" in add_order_preserving_left)
  by (simp add: add.assoc [THEN sym])

lemma [simp]: "c + (a \<sqinter> b) = (c + a) \<sqinter> (c + b)"
  apply (rule antisym)
  apply simp
  apply safe
  apply (rule add_order_preserving_left)
  apply simp
  apply (rule add_order_preserving_left)
  apply simp
  apply (rule left_move_to_left)
  apply simp
  apply safe
  apply (rule left_move_to_right)
  apply simp
  apply (rule left_move_to_right)
  by simp

lemma [simp]: "- (a \<sqinter> b) = (- a) \<squnion> (- b)"
  apply (rule antisym)
  apply (rule minus_order)
  apply simp
  apply safe
  apply (rule minus_order)
  apply simp
  apply (rule minus_order)
  apply simp
  apply simp
  apply safe
  apply (rule minus_order)
  apply simp
  apply (rule minus_order)
  by simp

lemma [simp]: "(a \<squnion> b) + c = (a + c) \<squnion> (b + c)"
  apply (rule antisym)
  apply (rule right_move_to_right)
  apply simp
  apply safe
  apply (simp_all only: diff_conv_add_uminus)
  apply (rule right_move_to_left)
  apply simp
  apply (rule right_move_to_left)
  apply simp
  apply simp
  apply safe
  apply (rule add_order_preserving_right)
  apply simp
  apply (rule add_order_preserving_right)
  by simp

lemma [simp]: "c + (a \<squnion> b) = (c + a) \<squnion> (c + b)"
  apply (rule antisym)
  apply (rule left_move_to_right)
  apply simp
  apply safe
  apply (rule left_move_to_left)
  apply simp
  apply (rule left_move_to_left)
  apply simp
  apply simp
  apply safe
  apply (rule add_order_preserving_left)
  apply simp
  apply (rule add_order_preserving_left)
  by simp

lemma [simp]: "c - (a \<sqinter> b) = (c - a) \<squnion> (c - b)"
  by (simp add: diff_conv_add_uminus del: add_uminus_conv_diff)

lemma [simp]: "(a \<squnion> b) - c = (a - c) \<squnion>  (b - c)"
  by (simp add: diff_conv_add_uminus del: add_uminus_conv_diff)

lemma [simp]: "- (a \<squnion> b) = (- a) \<sqinter> (- b)"
  apply (rule antisym)
  apply simp
  apply safe
  apply (rule minus_order)
  apply simp
  apply (rule minus_order)
  apply simp
  apply (rule minus_order)
  by simp

lemma [simp]: "c - (a \<squnion> b) = (c - a) \<sqinter> (c - b)"
  by (simp add: diff_conv_add_uminus del: add_uminus_conv_diff)

lemma add_pos: "0 \<le> a \<Longrightarrow> b \<le> b + a"
  apply (cut_tac a = 0 and b = a and u = b and v = 0 in add_order_preserving)
  by simp_all

lemma add_pos_left: "0 \<le> a \<Longrightarrow> b \<le> a + b"
  apply (rule right_move_to_left)
  by simp

lemma inf_sup: "a - (a \<sqinter> b) + b = a \<squnion> b"
  by (simp add: add.assoc sup_commute)

lemma inf_sup_2: "b = (a \<sqinter> b) - a + (a \<squnion> b)"
  apply (unfold inf_sup [THEN sym])
  proof -
    fix a b:: 'a
    have "b = (a \<sqinter> b) + (- a + a) + - (a \<sqinter> b) + b" by (simp only: right_minus left_minus add_0_right add_0_left)
    also have "\<dots> = (a \<sqinter> b) + - a + (a + - (a \<sqinter> b) + b)" by (unfold add.assoc, simp)
    also have "\<dots> = (a \<sqinter> b) - a + (a - (a \<sqinter> b) + b)" by simp
    finally show "b = (a \<sqinter> b) - a + (a - (a \<sqinter> b) + b)" .
  qed

subclass inf_sup_eq_lattice
  proof
    fix x y z:: 'a
    assume A: "x \<sqinter> z = y \<sqinter> z"
    assume B: "x \<squnion> z = y \<squnion> z"
    have "x = (z \<sqinter> x) - z + (z \<squnion> x)" by (rule inf_sup_2)
    also have "\<dots> = (z \<sqinter> y) - z + (z \<squnion> y)" by (simp add: sup_commute inf_commute A B)
    also have "\<dots> = y" by (simp only: inf_sup_2 [THEN sym])
    finally show "x = y" .
  qed
end

end


(*  Title:      HOL/ex/Transfer_Debug.thy
    Author:     Ondřej Kunčar, TU München
*)
theory Transfer_Debug
imports Main "~~/src/HOL/Library/FSet"
begin

(*
  This file demonstrates some of the typical scenarios
  when transfer or transfer_prover does not produce expected results
  and how the user might handle such cases.
*)

(* As an example, we use finite sets. The following command recreates the environment in which
   the type of finite sets was created and allows us to do transferring on this type. *)
context
includes fset.lifting
begin

subsection \<open>1. A missing transfer rule\<close>

(* We will simulate the situation in which there is not any transfer rules for fmember. *)
declare fmember.transfer[transfer_rule del] fmember_transfer[transfer_rule del]

(* We want to prove the following theorem about |\<subseteq>| by transfer *)
lemma "(A |\<subseteq>| B) = fBall A (\<lambda>x. x |\<in>| B)"
apply transfer
(*
   Transfer complains that it could not find a transfer rule for |\<subseteq>| with a matching transfer
   relation. An experienced user could notice that |\<in>| was transferred to |\<in>| by a
   a default reflexivity transfer rule (because there was not any genuine transfer rule for |\<in>|)
   and fBall was transferred to Ball using the transfer relation pcr_fset. Therefore transfer
   is looking for a transfer rule for |\<subseteq>| with a transfer relation that mixes op= and pcr_fset.
   This situation might be confusing because the real problem (a missing transfer rule) propagates
   during the transferring algorithm and manifests later in an obfuscated way. Fortunately,
   we could inspect the behavior of transfer in a more interactive way to pin down the real problem.
*)
oops

lemma "(A |\<subseteq>| B) = fBall A (\<lambda>x. x |\<in>| B)"
apply transfer_start
(* Setups 6 goals for 6 transfer rules that have to be found and the result as the 7. goal, which
   gets synthesized to the final result of transferring when we find the 6 transfer rules. *)
apply transfer_step
(* We can see that the default reflexivity transfer rule was applied and |\<in>|
  was transferred to |\<in>| \<Longrightarrow> there is no genuine transfer rule for |\<in>|. *)
oops

(* We provide a transfer rule for |\<in>|. *)

lemma "(A |\<subseteq>| B) = fBall A (\<lambda>x. x |\<in>| B)"
apply transfer_start
apply transfer_step (* The new transfer rule was selected and |\<in>| was transferred to \<in>. *)
apply transfer_step+
apply transfer_end
by blast

(* Of course in the real life, we would use transfer instead of transfer_start, transfer_step+ and
   transfer_end. *)
lemma "(A |\<subseteq>| B) = fBall A (\<lambda>x. x |\<in>| B)"
by transfer blast

subsection \<open>2. Unwanted instantiation of a transfer relation variable\<close>

(* We want to prove the following fact. *)
lemma "finite (UNIV :: 'a::finite fset set)"
apply transfer
(* Transfer does not do anything here. *)
oops

(* Let us inspect interactively what happened. *)
lemma "finite (UNIV :: 'a::finite fset set)"
apply transfer_start
apply transfer_step
(*
   Here we can realize that not an expected transfer rule was chosen.
   We stumbled upon a limitation of Transfer: the tool used the rule Lifting_Set.UNIV_transfer,
   which transfers UNIV to UNIV and assumes that the transfer relation has to be bi-total.
   The problem is that at this point the transfer relation is not known (it is represented by
   a schematic variable ?R) and therefore in order to discharge the assumption "bi_total ?R", ?R is
   instantiated to op=. If the relation had been known (we wish pcr_fset op=, which is not bi-total),
   the assumption bi_total pcr_fset op= could not have been discharged and the tool would have
   backtracked and chosen Lifting.right_total_UNIV_transfer, which assumes only right-totalness
   (and pcr_fset is right-total).
*)
back back (* We can force the tool to backtrack and choose the desired transfer rule. *)
apply transfer_step
apply transfer_end
by auto

(* Of course, to use "back" in proofs is not a desired style. But we can prioritize
   the rule Lifting.right_total_UNIV_transfer by redeclaring it LOCALLY as a transfer rule.
 *)
lemma "finite (UNIV :: 'a::finite fset set)"
proof -
  note right_total_UNIV_transfer[transfer_rule]
  show ?thesis by transfer auto
qed

end

(* Let us close the environment of fset transferring and add the rule that we deleted. *)
lifting_forget fset.lifting (* deletes the extra added transfer rule for |\<in>| *)
declare fmember_transfer[transfer_rule] (* we want to keep parametricity of |\<in>| *)

end


(* This Isabelle theory is produced using the TIP tool offered at the following website:
     https://github.com/tip-org/tools
   This file was originally provided as part of TIP benchmark at the following website:
     https://github.com/tip-org/benchmarks
   Yutaka Nagashima at CIIRC, CTU changed the TIP output theory file slightly
   to make it compatible with Isabelle2017.*)
  theory TIP_list_nat_perm_elem
imports "../../Test_Base"
begin

datatype 'a list = nil2 | cons2 "'a" "'a list"

fun elem :: "'a => 'a list => bool" where
"elem x (nil2) = False"
| "elem x (cons2 z xs) = ((z = x) | (elem x xs))"

fun deleteBy :: "('a => ('a => bool)) => 'a => 'a list =>
                 'a list" where
"deleteBy x y (nil2) = nil2"
| "deleteBy x y (cons2 y2 ys) =
     (if (x y) y2 then ys else cons2 y2 (deleteBy x y ys))"

fun isPermutation :: "'a list => 'a list => bool" where
"isPermutation (nil2) (nil2) = True"
| "isPermutation (nil2) (cons2 z x2) = False"
| "isPermutation (cons2 x3 xs) y =
     ((elem x3 y) &
        (isPermutation
           xs (deleteBy (% (x4 :: 'a) => % (x5 :: 'a) => (x4 = x5)) x3 y)))"

theorem property0 :
  "((elem x xs) ==> ((isPermutation xs ys) ==> (elem x ys)))"
  oops

end