theory Munkres
 imports "HOL-Analysis.Analysis"
begin

(*
problem_number:13_1
natural language statement:
Let $X$ be a topological space; let $A$ be a subset of $X$. Suppose that for each $x \in A$ there is an open set $U$ containing $x$ such that $U \subset A$. Show that $A$ is open in $X$.
lean statement:
theorem exercise_13_1 (X : Type* ) [topological_space X] (A : set X)
  (h1 : \<forall> x \<in> A, \<exists> U : set X, x \<in> U \<and> is_open U \<and> U \<subseteq> A) :
  is_open A :=
begin
  have : A = \<Union> x, \<Union> h : x \<in> A, (classical.some (h1 x h)),
  { ext x, simp, split,
  { intro xA,
  use [x, xA],
  exact (classical.some_spec (h1 x xA)).1},
  { rintros \<langle>y, yA, yspec\<rangle>,
  have h := classical.some_spec (h1 y yA),
  exact h.2.2 yspec }, },
  rw this,
  apply is_open_Union,
  intro x,
  apply is_open_Union,
  intro xA,
  have h := classical.some_spec (h1 x xA),
  exact h.2.1
end

codex statement:
theorem subset_of_open_subset_is_open:
  fixes T::"'a topology" and A::"'a set"
  assumes "A \<subseteq> topspace T" "\<forall>x\<in>A. \<exists> U \<subseteq> topspace T. openin T U \<and> x\<in>U \<and> U \<subseteq> A"
  shows "openin T A"
Our comment on the codex statement: very good!
 *)
theorem exercise_13_1:  (*FIRST ASSUMPTION NOT NECESSARY*)
  fixes T::"'a topology" and A::"'a set"
  assumes "A \<subseteq> topspace T" "\<forall>x\<in>A. \<exists>U. openin T U \<and> x\<in>U \<and> U \<subseteq> A"
  shows "openin T A"
  using assms(2) openin_subopen by fastforce

(*
problem_number:13_5a
natural language statement:
Show that if $\mathcal{A}$ is a basis for a topology on $X$, then the topology generated by $\mathcal{A}$ equals the intersection of all topologies on $X$ that contain $\mathcal{A}$.
lean statement:
theorem exercise_13_5a {X : Type*}
  [topological_space X] (A : set (set X)) (hA : is_topological_basis A) :
  generate_from A = generate_from (sInter {T | is_topology X T \<and> A \<subseteq> T}) :=

codex statement:
theorem topology_generated_by_basis_eq_intersection_of_topologies_containing_basis:
  fixes X::"'a set" and A::"'a set set"
  assumes "topological_basis A"
  shows "topology_generated_by A = \<Inter>T. topological_space T \<and> A \<subseteq> sets T"
Our comment on the codex statement: "basis of a topology" is not directly available
 *)

theorem exercise_13_5a: undefined oops

(*
problem_number:13_5b
natural language statement:
Show that if $\mathcal{A}$ is a subbasis for a topology on $X$, then the topology generated by $\mathcal{A}$ equals the intersection of all topologies on $X$ that contain $\mathcal{A}$.
lean statement:
theorem exercise_13_5b {X : Type*}
  [t : topological_space X] (A : set (set X)) (hA : t = generate_from A) :
  generate_from A = generate_from (sInter {T | is_topology X T \<and> A \<subseteq> T}) :=

codex statement:
theorem topology_generated_by_subbasis_eq_intersection_of_topologies_containing_subbasis:
  fixes X::"'a set" and A::"'a set set"
  assumes "subbasis A X"
  shows "topology_generated_by A = \<Inter>T. topology T \<and> A \<subseteq> T"
Our comment on the codex statement:  mostly wrong. This was very tricky to get right, and I proved it to check
 *)
theorem exercise_13_5b: (*"subbasis of a topology" is not directly available*)
  shows "topology_generated_by \<A> = topology(\<lambda>S. \<forall>T \<in> {T::'a topology. \<A> \<subseteq> {S. openin T S}}. openin T S)"
proof -
  have istop: "istopology (\<lambda>S. \<forall>T. \<A> \<subseteq> Collect (openin T) \<longrightarrow> openin T S)"
    by (simp add: istopology_def openin_Int openin_Union)
  show ?thesis
  apply (simp add: topology_eq openin_topology_generated_by_iff topology_inverse' [OF istop])
    by (metis Ball_Collect Basis generate_topology_on_coarsest istopology_generate_topology_on istopology_openin topology_inverse')
qed

(*
problem_number:16_1
natural language statement:
Show that if $Y$ is a subspace of $X$, and $A$ is a subset of $Y$, then the topology $A$ inherits as a subspace of $Y$ is the same as the topology it inherits as a subspace of $X$.
lean statement:
theorem exercise_16_1 {X : Type*} [topological_space X]
  (Y : set X)
  (A : set Y)
  :
  \<forall> U : set A, is_open U \<longleftrightarrow> is_open (subtype.val '' U) :=

codex statement:
theorem subspace_topology_of_subspace_eq_subspace_topology_of_superspace:
  fixes X::"'a::topological_space set" and Y::"'a::topological_space set" and A::"'a::topological_space set"
  assumes "subspace Y" "A \<subseteq> Y"
  shows "subtopology (subspace_topology Y A) (subspace_topology X A)"
Our comment on the codex statement: Wrong and in particular it keeps wanting to use the typeclass-based versions
 *)
theorem exercise_16_1:
  assumes "Y = subtopology X S" "A \<subseteq> topspace Y"
  shows "subtopology X A = subtopology Y A"
  by (metis assms inf.absorb2 le_inf_iff subtopology_subtopology topspace_subtopology)

(*
problem_number:16_4
natural language statement:
A map $f: X \rightarrow Y$ is said to be an open map if for every open set $U$ of $X$, the set $f(U)$ is open in $Y$. Show that $\pi_{1}: X \times Y \rightarrow X$ and $\pi_{2}: X \times Y \rightarrow Y$ are open maps.
lean statement:
theorem exercise_16_4 {X Y : Type*} [topological_space X] [topological_space Y]
  (\<pi>_1 : X \<times> Y \<rightarrow> X)
  (\<pi>_2 : X \<times> Y \<rightarrow> Y)
  (h_1 : \<pi>_1 = prod.fst)
  (h_2 : \<pi>_2 = prod.snd) :
  is_open_map \<pi>_1 \<and> is_open_map \<pi>_2 :=

codex statement:
theorem open_map_of_prod_space:
  fixes X Y::"'a::topological_space"
  shows "open_map (prod_topology X Y) (X \<times> Y) (\<lambda>x. fst x)" "open_map (prod_topology X Y) (X \<times> Y) (\<lambda>x. snd x)"
Our comment on the codex statement:  partly right. Again used the typeclass version
 *)
theorem exercise_16_4:
    fixes X Y::"'a topology"
  shows "open_map (prod_topology X Y) X fst" "open_map (prod_topology X Y) Y snd"
  by (auto simp: open_map_fst open_map_snd)

(*
problem_number:16_6
natural language statement:
Show that the countable collection \[\{(a, b) \times (c, d) | a < b \text{ and } c < d, \text{ and } a, b, c, d \text{ are rational}\}\] is a basis for $\mathbb{R}^2$.
lean statement:
theorem exercise_16_6
  (S : set (set (\<real> \<times> \<real>)))
  (hS : \<forall> s, s \<in> S \<rightarrow> \<exists> a b c d, (rational a \<and> rational b \<and> rational c \<and> rational d
  \<and> s = {x | \<exists> x_1 x_2, x = (x_1, x_2) \<and> a < x_1 \<and> x_1 < b \<and> c < x_2 \<and> x_2 < d})) :
  is_topological_basis S :=

codex statement:
theorem basis_of_rational_interval:
  fixes a b c d::rat
  assumes "a < b" "c < d"
  shows "openin (subtopology euclidean_space (UNIV::real^2 set)) ((a, b) \<times> (c, d))"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_16_6:
  defines "\<B> \<equiv> { {a<..<b::real} \<times> {c<..<d::real} | a b c d. a \<in> \<rat> \<and> b \<in> \<rat> \<and> c \<in> \<rat> \<and> d \<in> \<rat> \<and> a<b \<and> c<d }"
  shows "topology_generated_by \<B> = euclidean"
  oops

(*
problem_number:16_9
natural language statement:
Show that the dictionary order topology on the set $\mathbb{R} \times \mathbb{R}$ is the same as the product topology $\mathbb{R}_d \times \mathbb{R}$, where $\mathbb{R}_d$ denotes $\mathbb{R}$ in the discrete topology.
lean statement:

codex statement:
theorem dictionary_order_topology_eq_product_topology:
  shows "dictionary_order_topology = product_topology (discrete_topology::'a::linorder_topology topology) (discrete_topology::'b::linorder_topology topology)"
Our comment on the codex statement:  wrong, but this was difficult
 *)

definition
  "dictless x y \<equiv> fst x < fst y \<or> fst x \<le> fst y \<and> snd x < snd y"

definition
  "dict_basis \<equiv> range (\<lambda>a. {x. dictless x a}) \<union> range (\<lambda>a. {x. dictless a x})"

theorem exercise_16_9:
  shows "topology_generated_by dict_basis = prod_topology (discrete_topology (UNIV::real set)) euclidean"
  oops

(*
problem_number:17_2
natural language statement:
Show that if $A$ is closed in $Y$ and $Y$ is closed in $X$, then $A$ is closed in $X$.
lean statement:

codex statement:
theorem closed_of_closed_subset:
  fixes A::"'a::topological_space set" and X::"'b::topological_space set"
  assumes "closed_in (subtopology (top_of_set X) Y) A" "closed_in (top_of_set X) Y"
  shows "closed_in (top_of_set X) A"
Our comment on the codex statement:  not bad but again the typeclass issue
 *)
theorem exercise_17_2:
  assumes "closedin (subtopology X Y) A" "closedin X Y"
  shows "closedin X A"
  using assms closedin_closed_subtopology by blast

(*
problem_number:17_3
natural language statement:
Show that if $A$ is closed in $X$ and $B$ is closed in $Y$, then $A \times B$ is closed in $X \times Y$.
lean statement:

codex statement:
theorem closed_of_closed_times_closed:
  fixes A::"'a::topological_space set" and B::"'b::topological_space set"
  assumes "closedin (top_of_set (UNIV::'a set)) A" "closedin (top_of_set (UNIV::'b set)) B"
  shows "closedin (top_of_set (UNIV::('a\<times>'b) set)) (A\<times>B)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_17_3:
  assumes "closedin X A" "closedin Y B"
  shows "closedin (prod_topology X Y) (A\<times>B)"
  by (simp add: assms closedin_prod_Times_iff)

(*
problem_number:17_4
natural language statement:
Show that if $U$ is open in $X$ and $A$ is closed in $X$, then $U-A$ is open in $X$, and $A-U$ is closed in $X$.
lean statement:
theorem exercise_17_4 {X : Type*} [topological_space X]
  (U A : set X) (hU : is_open U) (hA : is_closed A) :
  is_open (U \ A) \<and> is_closed (A \ U) :=

codex statement:
theorem open_of_open_diff_closed:
  fixes U A::"'a::topological_space set"
  assumes "open U" "closed A"
  shows "open (U - A)"
Our comment on the codex statement: Not bad but it is the type class version
 *)
theorem exercise_17_4:
  assumes "openin X U" "closedin X A"
  shows "openin X (U - A) \<and> closedin X (A - U)"
  by (simp add: assms closedin_diff openin_diff)

(*
problem_number:18_8a
natural language statement:
Let $Y$ be an ordered set in the order topology. Let $f, g: X \rightarrow Y$ be continuous. Show that the set $\{x \mid f(x) \leq g(x)\}$ is closed in $X$.
lean statement:
theorem exercise_18_8a {X Y : Type*} [topological_space X] [topological_space Y]
  [linear_order Y] [order_topology Y] {f g : X \<rightarrow> Y}
  (hf : continuous f) (hg : continuous g) :
  is_closed {x | f x \<le> g x} :=

codex statement:
theorem closed_of_continuous_leq:
  fixes f g::"'a::topological_space \<Rightarrow> 'b::order_topology"
  assumes "continuous_on UNIV f" "continuous_on UNIV g"
  shows "closed {x. f x \<le> g x}"
Our comment on the codex statement:  perfect except it is for type classes
 *)

definition "order_topology \<equiv> topology_generated_by (range (\<lambda>a. {..<a}) \<union> range (\<lambda>a::'a::linorder. {a<..}))"

theorem exercise_18_8a:
  fixes A :: "'a::linorder set"
  defines "X \<equiv> order_topology"
  defines "Y \<equiv> subtopology X A"
  assumes "continuous_map X Y f" "continuous_map X Y g"
  shows "closedin Y {x. f x \<le> g x}"
  oops

theorem closed_of_continuous_leq:
  fixes f g::"'a::topological_space \<Rightarrow> 'b::order_topology"
  assumes "continuous_on UNIV f" "continuous_on UNIV g"
  shows "closed {x. f x \<le> g x}"
  oops

(*
problem_number:18_8b
natural language statement:
Let $Y$ be an ordered set in the order topology. Let $f, g: X \rightarrow Y$ be continuous. Let $h: X \rightarrow Y$ be the function $h(x)=\min \{f(x), g(x)\}.$ Show that $h$ is continuous.
lean statement:
theorem exercise_18_8b {X Y : Type*} [topological_space X] [topological_space Y]
  [linear_order Y] [order_topology Y] {f g : X \<rightarrow> Y}
  (hf : continuous f) (hg : continuous g) :
  continuous (\<lambda> x, min (f x) (g x)) :=

codex statement:
theorem continuous_of_continuous_min:
  fixes f g::"'a::topological_space \<Rightarrow> 'b::order_topology"
  assumes "continuous_on UNIV f" "continuous_on UNIV g"
  shows "continuous_on UNIV (\<lambda>x. min (f x) (g x))"
Our comment on the codex statement: type classes
 *)
theorem exercise_18_8b:
  fixes A :: "'a::linorder set"
  defines "X \<equiv> order_topology"
  defines "Y \<equiv> subtopology X A"
  assumes "continuous_map X Y f" "continuous_map X Y g"
  defines "h \<equiv> \<lambda>x. min (f x) (g x)"
  shows "continuous_map X Y h"
  oops

(*
problem_number:18_13
natural language statement:
Let $A \subset X$; let $f: A \rightarrow Y$ be continuous; let $Y$ be Hausdorff. Show that if $f$ may be extended to a continuous function $g: \bar{A} \rightarrow Y$, then $g$ is uniquely determined by $f$.
lean statement:
theorem exercise_18_13
  {X : Type*} [topological_space X] {Y : Type*} [topological_space Y]
  [t2_space Y] {A : set X} {f : A \<rightarrow> Y} (hf : continuous f)
  (g : closure A \<rightarrow> Y)
  (g_con : continuous g) :
  \<forall> (g' : closure A \<rightarrow> Y), continuous g' \<rightarrow>  (\<forall> (x : closure A), g x = g' x) :=

codex statement:
theorem unique_continuous_extension_of_continuous_on_closure:
  fixes f::"'a::t1_space \<Rightarrow> 'b::t2_space" and g::"'a::t1_space \<Rightarrow> 'b::t2_space"
  assumes "continuous_on A f" "continuous_on (closure A) g" "g|`A = f"
  shows "g = f"
Our comment on the codex statement:  it went wrong and it is the type class version
 *)
theorem exercise_18_13:
  fixes A :: "'a set" and X :: "'a topology"
  defines "A' \<equiv> subtopology X (X closure_of A)"
  assumes "A \<subseteq> topspace X" "Hausdorff_space Y" "continuous_map (subtopology X A) Y f"
    and "continuous_map A' Y g1" "restrict g1 A = f"
    and "continuous_map A' Y g2" "restrict g2 A = f"
  shows "g1 = g2"
  oops

(*
problem_number:19_4
natural language statement:
Show that $(X_1 \times  \cdots \times X_{n-1}) \times X_n$ is homeomorphic with $X_1 \times  \cdots \times X_n$.
lean statement:

codex statement:
theorem homeomorphic_of_prod_prod_prod:
  fixes X::"'a::topological_space set" and Y::"'b::topological_space set" and Z::"'c::topological_space set"
  assumes "topological_space X" "topological_space Y" "topological_space Z"
  shows "X \<times> Y \<times> Z \<cong> (X \<times> Y) \<times> Z"
Our comment on the codex statement:  kind of model with kind of muddled with the type class setup
 *)
theorem exercise_19_4:  (*only for n=3: trickery is needed to express the general case,
                          cf DirProd_list in Algebra/Weak_Morphisms*)
  shows "prod_topology (prod_topology X1 X2) X3 homeomorphic_space prod_topology X1 (prod_topology X2 X3)"
  oops

(*
problem_number:19_6a
natural language statement:
Let $\mathbf{x}_1, \mathbf{x}_2, \ldots$ be a sequence of the points of the product space $\prod X_\alpha$.  Show that this sequence converges to the point $\mathbf{x}$ if and only if the sequence $\pi_\alpha(\mathbf{x}_i)$ converges to $\pi_\alpha(\mathbf{x})$ for each $\alpha$.
lean statement:
theorem exercise_19_6a
  {n : \<nat>}
  {f : fin n \<rightarrow> Type*} {x : \<nat> \<rightarrow> \<pi>a, f a}
  (y : \<pi>i, f i)
  [\<pi>a, topological_space (f a)] :
  tendsto x at_top (\<N> y) \<longleftrightarrow> \<forall> i, tendsto (\<lambda> j, (x j) i) at_top (\<N> (y i)) :=

codex statement:
theorem convergent_of_prod_convergent:
  fixes X::"('a::metric_space) set" and f::"nat \<Rightarrow> 'a"
  assumes "\<forall>n. f n \<in> X" "\<forall>n. (\<forall>x\<in>X. (f n x) = (f (n+1) x)) \<longrightarrow> (f n = f (n+1))"
  shows "convergent f"
Our comment on the codex statement: just no.
 *)
theorem exercise_19_6a:
  "limitin (product_topology X I) x a sequentially  \<longleftrightarrow> (\<forall>i\<in>I. limitin (X i) (x i) (a i) sequentially)"
  oops

(*
problem_number:19_9
natural language statement:
Show that the choice axiom is equivalent to the statement that for any indexed family of nonempty sets, $\{A_\alpha\}_{\alpha \in J}$ with $J \neq 0$, the cartesian product \[\prod_{\alpha \in J} A_\alpha\] is not empty.
lean statement:

codex statement:
theorem choice_iff_cartesian_product_not_empty:
  fixes J::"'a set" and A::"'a \<Rightarrow> 'b set"
  assumes "J \<noteq> \<emptyset>"
  shows "\<exists>f. \<forall>x\<in>J. f x \<in> A x \<Longleftrightarrow> (\<exists>f. \<forall>x\<in>J. f x \<in> A x)"
Our comment on the codex statement: not really
 *)
theorem exercise_19_9: (* not expressible in full because AC is included in Isabelle/HOL*)
  assumes "J \<noteq> {}" "\<And>j. j \<in> J \<Longrightarrow> A j \<noteq> {}"
  shows "Pi J A \<noteq> {}"
  by (simp add: assms(2))

(*
problem_number:20_2
natural language statement:
Show that $\mathbb{R} \times \mathbb{R}$ in the dictionary order topology is metrizable.
lean statement:
theorem exercise_20_2
  [topological_space (\<real> \<times>ₗ \<real>)] [order_topology (\<real> \<times>ₗ \<real>)]
  : metrizable_space (\<real> \<times>ₗ \<real>) :=

codex statement:
theorem metrizable_of_dictionary_order_topology:
  fixes X::"real set"
  assumes "X = UNIV"
  shows "metrizable_space (order_topology (dictionary_order X))"
Our comment on the codex statement:  it kind of assumes we have everything
 *)
theorem exercise_20_2: undefined oops
  (*
  shows "topology_generated_by dict_basis = XXX"
 NOT POSSIBLE until we get an abstract formalisation of metric spaces*)

(*
problem_number:20_5
natural language statement:
Let $\mathbb{R}^\infty$ be the subset of $\mathbb{R}^\omega$ consisting of all sequences that are eventually zero.  What is the closure of $\mathbb{R}^\infty$ in $\mathbb{R}^\omega$ in the uniform topology? Justify your answer.
lean statement:

codex statement:
theorem closure_of_eventually_zero_seq_is_all_seq:
  fixes f::"nat \<Rightarrow> 'a::real_normed_vector"
  assumes "\<forall>n. \<exists>m. \<forall>k. m \<le> k \<longrightarrow> f k = 0"
  shows "closure {f. \<forall>n. \<exists>m. \<forall>k. m \<le> k \<longrightarrow> f k = 0} = UNIV"
Our comment on the codex statement:  nonsense
 *)
theorem exercise_20_5: undefined oops (* this is a "WHAT-IS" exercise with no actual theorem statement*)

(*
problem_number:21_6a
natural language statement:
Define $f_{n}:[0,1] \rightarrow \mathbb{R}$ by the equation $f_{n}(x)=x^{n}$. Show that the sequence $\left(f_{n}(x)\right)$ converges for each $x \in[0,1]$.
lean statement:
theorem exercise_21_6a
  (f : \<nat> \<rightarrow> I \<rightarrow> \<real> )
  (h : \<forall> x n, f n x = x ^ n) :
  \<forall> x, \<exists> y, tendsto (\<lambda> n, f n x) at_top (\<N> y) :=

codex statement:
theorem converges_of_power_seq:
  fixes x::real
  assumes "0 \<le> x \<and> x \<le> 1"
  shows "convergent (\<lambda>n. x^n)"
Our comment on the codex statement:  perfect!
 *)
theorem exercise_21_6a:
  fixes x::real
  assumes "0 \<le> x \<and> x \<le> 1"
  shows "convergent (\<lambda>n. x^n)"
  using assms convergent_realpow by presburger

(*
problem_number:21_6b
natural language statement:
Define $f_{n}:[0,1] \rightarrow \mathbb{R}$ by the equation $f_{n}(x)=x^{n}$. Show that the sequence $\left(f_{n}\right)$ does not converge uniformly.
lean statement:
theorem exercise_21_6b
  (f : \<nat> \<rightarrow> I \<rightarrow> \<real> )
  (h : \<forall> x n, f n x = x ^ n) :
  \<not> \<exists> f₀, tendsto_uniformly f f₀ at_top :=

codex statement:
theorem not_uniformly_convergent_of_power_function:
  fixes n::nat
  shows "\<forall>\<epsilon>>0. \<exists>x. \<forall>n. dist (x^n) (x^(n+1)) > \<epsilon>"
Our comment on the codex statement:  Interesting
 *)
theorem exercise_21_6b:
  shows "\<not> uniformly_convergent_on {0..1} (\<lambda>x n. x^n)"
  oops

(*
problem_number:21_8
natural language statement:
Let $X$ be a topological space and let $Y$ be a metric space. Let $f_{n}: X \rightarrow Y$ be a sequence of continuous functions. Let $x_{n}$ be a sequence of points of $X$ converging to $x$. Show that if the sequence $\left(f_{n}\right)$ converges uniformly to $f$, then $\left(f_{n}\left(x_{n}\right)\right)$ converges to $f(x)$.
lean statement:
theorem exercise_21_8
  {X : Type*} [topological_space X] {Y : Type*} [metric_space Y]
  {f : \<nat> \<rightarrow> X \<rightarrow> Y} {x : \<nat> \<rightarrow> X}
  (hf : \<forall> n, continuous (f n))
  (x₀ : X)
  (hx : tendsto x at_top (\<N> x₀))
  (f₀ : X \<rightarrow> Y)
  (hh : tendsto_uniformly f f₀ at_top) :
  tendsto (\<lambda> n, f n (x n)) at_top (\<N> (f₀ x₀)) :=

codex statement:
theorem converges_of_uniformly_converges_and_converges:
  fixes f::"'a::metric_space \<Rightarrow> 'b::metric_space" and X::"'a set" and Y::"'b set"
  assumes "compact X" "continuous_on X f" "uniformly_convergent_on X (f \<circ> g)" "convergent g"
  shows "convergent (f \<circ> g)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_21_8: undefined oops
(*NOT POSSIBLE until we get an abstract formalisation of metric spaces*)

(*
problem_number:22_2a
natural language statement:
Let $p: X \rightarrow Y$ be a continuous map. Show that if there is a continuous map $f: Y \rightarrow X$ such that $p \circ f$ equals the identity map of $Y$, then $p$ is a quotient map.
lean statement:
theorem exercise_22_2a {X Y : Type*} [topological_space X]
  [topological_space Y] (p : X \<rightarrow> Y) (h : continuous p) :
  quotient_map p \<longleftrightarrow> \<exists> (f : Y \<rightarrow> X), continuous f \<and> p \<circ> f = id :=

codex statement:
theorem quotient_map_of_continuous_map_and_continuous_map_comp_id:
  fixes p::"'a::topological_space \<Rightarrow> 'b::topological_space" and f::"'b::topological_space \<Rightarrow> 'a::topological_space"
  assumes "continuous_on UNIV p" "continuous_on UNIV f" "\<forall>x. p (f x) = x"
  shows "quotient_map p"
Our comment on the codex statement:  it is the type class version and it is scrambled
 *)
theorem exercise_22_2a:
  assumes "continuous_map X Y p"  "continuous_map Y X f"
    and "\<And>y. y \<in> topspace Y \<Longrightarrow> p (f y) = y"
  shows "quotient_map X Y p"
  by (smt (verit) assms comp_apply continuous_map_compose continuous_open_imp_quotient_map
      homeomorphic_eq_everything_map homeomorphic_map_involution quotient_map_from_composition)

(*
problem_number:22_2b
natural language statement:
If $A \subset X$, a retraction of $X$ onto $A$ is a continuous map $r: X \rightarrow A$ such that $r(a)=a$ for each $a \in A$. Show that a retraction is a quotient map.
lean statement:
theorem exercise_22_2b {X : Type*} [topological_space X]
  {A : set X} (r : X \<rightarrow> A) (hr : continuous r) (h : \<forall> x : A, r x = x) :
  quotient_map r :=

codex statement:
theorem retraction_is_quotient_map:
  fixes X::"'a::topological_space topology" and A::"'a set" and r::"'a \<Rightarrow> 'a"
  assumes "continuous_on (carrier X) r" "r ` (carrier X) \<subseteq> A" "\<forall>x\<in>A. r x = x"
  shows "quotient_map X (subtopology X A) r"
Our comment on the codex statement:  partly right
 *)
theorem exercise_22_2b:
  assumes "A \<subseteq> topspace X" "continuous_map X (subtopology X A) r"
    and "\<And>x. x \<in> A \<Longrightarrow> r x = x"
  shows "quotient_map X (subtopology X A) r"
  by (metis assms continuous_map_from_subtopology continuous_map_into_fulltopology exercise_22_2a topspace_subtopology_subset)

(*
problem_number:22_5
natural language statement:
Let $p \colon X \rightarrow Y$ be an open map. Show that if $A$ is open in $X$, then the map $q \colon A \rightarrow p(A)$ obtained by restricting $p$ is an open map.
lean statement:
theorem exercise_22_5 {X Y : Type*} [topological_space X]
  [topological_space Y] (p : X \<rightarrow> Y) (hp : is_open_map p)
  (A : set X) (hA : is_open A) : is_open_map (p \<circ> subtype.val : A \<rightarrow> Y) :=

codex statement:
theorem open_map_of_open_subset:
  fixes p::"'a::topological_space \<Rightarrow> 'b::topological_space"
  assumes "open_map p" "openin (top_of_set (UNIV::'a set)) A"
  shows "open_map (p|A)"
Our comment on the codex statement:  type class primitives, and scrambled
 *)
theorem exercise_22_5:
  assumes "open_map X Y p" "openin X A"
  shows "open_map (subtopology X A) (subtopology Y (p ` A)) (restrict p A)"
  oops

(*
problem_number:23_2
natural language statement:
Let $\left\{A_{n}\right\}$ be a sequence of connected subspaces of $X$, such that $A_{n} \cap A_{n+1} \neq \varnothing$ for all $n$. Show that $\bigcup A_{n}$ is connected.
lean statement:
theorem exercise_23_2 {X : Type*}
  [topological_space X] {A : \<nat> \<rightarrow> set X} (hA : \<forall> n, is_connected (A n))
  (hAn : \<forall> n, A n \<inter> A (n + 1) \<noteq> \<emptyset>) :
  is_connected (\<Union> n, A n) :=

codex statement:
theorem connected_of_connected_inter_nonempty:
  fixes X::"'a::topological_space set" and A::"nat \<Rightarrow> 'a set"
  assumes "\<forall>n. connected (A n)" "\<forall>n. A n \<inter> A (n+1) \<noteq> {}"
  shows "connected (\<Union>i. A i)"
Our comment on the codex statement:  very good but uses type classes
 *)
theorem exercise_23_2:
  assumes "\<And>n. connectedin X (A n)" "\<And>n. A n \<inter> A (Suc n) \<noteq> {}"
  shows "connectedin X (\<Union>i. A i)"
  oops

(*
problem_number:23_3
natural language statement:
Let $\left\{A_{\alpha}\right\}$ be a collection of connected subspaces of $X$; let $A$ be a connectea eubsen of $X$ Show that if $A \cap A_{\alpha} \neq \varnothing$ for all $\alpha$, then $A \cup\left(\bigcup A_{\alpha}\right)$ is connected.
lean statement:
theorem exercise_23_3 {X : Type*} [topological_space X]
  [topological_space X] {A : \<nat> \<rightarrow> set X}
  (hAn : \<forall> n, is_connected (A n))
  (A₀ : set X)
  (hA : is_connected A₀)
  (h : \<forall> n, A₀ \<inter> A n \<noteq> \<emptyset>) :
  is_connected (A₀ \<union> (\<Union> n, A n)) :=

codex statement:
theorem connected_of_connected_inter_nonempty:
  fixes X::"'a::topological_space set" and A::"'a set" and A\<alpha>::"'a set"
  assumes "\<forall>\<alpha>. connected (A\<alpha> \<alpha>)" "connected A" "\<forall>\<alpha>. A \<inter> A\<alpha> \<alpha> \<noteq> {}"
  shows "connected (A \<union> (\<Union>\<alpha>. A\<alpha> \<alpha>))"
Our comment on the codex statement: very good but uses type classes
 *)
theorem exercise_23_3:
  assumes "\<And>\<alpha>. connectedin X (\<A> \<alpha>)" "\<And>n. \<A> n \<inter> \<A> (Suc n) \<noteq> {}"
          "A \<subseteq> topspace X" "connectedin X A"
  shows "connectedin X (A \<union> (\<Union>i. \<A> i))"
  oops

(*
problem_number:23_4
natural language statement:
Show that if $X$ is an infinite set, it is connected in the finite complement topology.
lean statement:
theorem exercise_23_4 {X : Type*} [topological_space X] [cofinite_topology X]
  (s : set X) : set.infinite s \<rightarrow> is_connected s :=

codex statement:
theorem connected_of_infinite_set:
  fixes X::"'a set"
  assumes "infinite X"
  shows "connected_space (subtopology (discrete_topology X) X)"
Our comment on the codex statement: not about discrete topology; uses type classes
 *)
theorem exercise_23_4:
  assumes "infinite A"
  shows "connectedin (topology (\<lambda>U. finite (-U))) A"
  oops

(*
problem_number:23_6
natural language statement:
Let $A \subset X$. Show that if $C$ is a connected subspace of $X$ that intersects both $A$ and $X-A$, then $C$ intersects $\operatorname{Bd} A$.
lean statement:
theorem exercise_23_6 {X : Type*}
  [topological_space X] {A C : set X} (hc : is_connected C)
  (hCA : C \<inter> A \<noteq> \<emptyset>) (hCXA : C \<inter> Aᶜ \<noteq> \<emptyset>) :
  C \<inter> (frontier A) \<noteq> \<emptyset> :=

codex statement:
theorem connected_intersect_of_subset_intersect_diff_subset_intersect_boundary:
  fixes A::"'a::topological_space set" and C::"'a set"
  assumes "connected C" "C \<inter> A \<noteq> {}" "C \<inter> (UNIV - A) \<noteq> {}"
  shows "C \<inter> (boundary A) \<noteq> {}"
Our comment on the codex statement: very good but uses type classes; it's frontier not boundary
 *)
theorem exercise_23_6:
  assumes "connectedin X C" "C \<inter> A \<noteq> {}" "C \<inter> (-A) \<noteq> {}"
  shows "C \<inter> (frontier A) \<noteq> {}"
  oops

(*
problem_number:23_9
natural language statement:
Let $A$ be a proper subset of $X$, and let $B$ be a proper subset of $Y$. If $X$ and $Y$ are connected, show that $(X \times Y)-(A \times B)$ is connected.
lean statement:
theorem exercise_23_9 {X Y : Type*}
  [topological_space X] [topological_space Y]
  (A_1 A_2 : set X)
  (B_1 B_2 : set Y)
  (hA : A_1 \<subset> A_2)
  (hB : B_1 \<subset> B_2)
  (hA : is_connected A_2)
  (hB : is_connected B_2) :
  is_connected ({x | \<exists> a b, x = (a, b) \<and> a \<in> A_2 \<and> b \<in> B_2} \
      {x | \<exists> a b, x = (a, b) \<and> a \<in> A_1 \<and> b \<in> B_1}) :=

codex statement:
theorem connected_of_connected_times_connected_minus_proper_subset:
  fixes X Y::"'a::topological_space set"
  assumes "connected X" "connected Y" "A \<subset> X" "B \<subset> Y"
  shows "connected ((X \<inter> Y) - (A \<inter> B))"
Our comment on the codex statement:  where did those intersections come from?
 *)
theorem exercise_23_9:
  assumes "connected_space X" "connected_space Y" "A \<subset> topspace X" "B \<subset> topspace Y"
  shows "connectedin (prod_topology X Y) ((topspace X \<times> topspace Y) - (A \<times> B))"
oops

(*
problem_number:23_11
natural language statement:
Let $p: X \rightarrow Y$ be a quotient map. Show that if each set $p^{-1}(\{y\})$ is connected, and if $Y$ is connected, then $X$ is connected.
lean statement:
theorem exercise_23_11 {X Y : Type*} [topological_space X] [topological_space Y]
  (p : X \<rightarrow> Y) (hq : quotient_map p)
  (hY : connected_space Y) (hX : \<forall> y : Y, is_connected (p ⁻¹' {y})) :
  connected_space X :=

codex statement:
theorem connected_of_connected_quotient_map:
  fixes X::"'a topology" and Y::"'b topology"
  assumes "continuous_map X Y p" "\<forall>y\<in>Y. connected (p -` {y})" "connected Y"
  shows "connected X"
Our comment on the codex statement: very good but uses type classes
 *)
theorem exercise_23_11:
  assumes "quotient_map X Y p" "\<forall>y \<in> topspace Y. connectedin X (p -` {y})" "connected_space Y"
  shows "connected_space X"
oops

(*
problem_number:23_12
natural language statement:
Let $Y \subset X$; let $X$ and $Y$ be connected. Show that if $A$ and $B$ form a separation of $X-Y$, then $Y \cup A$ and $Y \cup B$ are connected.
lean statement:

codex statement:
theorem connected_of_connected_of_separation:
  fixes X Y::"'a::topological_space set"
  assumes "connected X" "connected Y" "Y \<subseteq> X" "separation_set (X - Y) A B"
  shows "connected (Y \<union> A)" "connected (Y \<union> B)"
Our comment on the codex statement: very good but uses type classes
 *)
theorem exercise_23_12:
  assumes "connected_space X" "connectedin X Y"
  assumes "openin X A" "A \<noteq> {}" "openin X B" "B \<noteq> {}" "A \<inter> B = {}" "A \<union> B = topspace X - Y"
  shows "connectedin X (Y \<union> A)" "connectedin X (Y \<union> B)"
oops

(*
problem_number:24_2
natural language statement:
Let $f: S^{1} \rightarrow \mathbb{R}$ be a continuous map. Show there exists a point $x$ of $S^{1}$ such that $f(x)=f(-x)$.
lean statement:
theorem exercise_24_2 {f : (metric.sphere 0 1 : set \<real>) \<rightarrow> \<real>}
  (hf : continuous f) : \<exists> x, f x = f (-x) :=

codex statement:
theorem exists_eq_of_continuous_map:
  fixes f::"complex \<Rightarrow> real"
  assumes "continuous_on (sphere 1) f"
  shows "\<exists>x. f x = f (-x)"
Our comment on the codex statement: Uses type classes and overlooks that x must lie on the sphere
 *)
theorem exercise_24_2:
  fixes f::"complex \<Rightarrow> real"
  assumes "continuous_map (top_of_set (sphere 0 1)) euclidean f"
  shows "\<exists>x \<in> sphere 0 1. f x = f (-x)"
proof -
  have "continuous_on (sphere 0 1) f"
    using assms continuous_map_iff_continuous by blast
  then show ?thesis
  oops

(*
problem_number:24_3a
natural language statement:
Let $f \colon X \rightarrow X$ be continuous. Show that if $X = [0, 1]$, there is a point $x$ such that $f(x) = x$. (The point $x$ is called a fixed point of $f$.)
lean statement:
theorem exercise_24_3a [topological_space I]
  (f : I \<rightarrow> I) (hf : continuous f) :
  \<exists> (x : I), f x = x :=

codex statement:
theorem exists_fixed_point_of_continuous_on_closed_interval:
  fixes f::"'a::metric_space \<Rightarrow> 'a"
  assumes "continuous_on {0..1} f"
  shows "\<exists>x. f x = x"
Our comment on the codex statement: very good but uses type classes
 *)
theorem exercise_24_3a:
  fixes f::"real \<Rightarrow> real"
  defines "X \<equiv> top_of_set {0..1}"
  assumes "continuous_map X X f"
  shows "\<exists>x \<in> {0..1}. f x = x"
oops

(*
problem_number:24_4
natural language statement:
Let $X$ be an ordered set in the order topology. Show that if $X$ is connected, then $X$ is a linear continuum.
lean statement:

codex statement:
theorem connected_of_linear_continuum:
  fixes X::"'a::linorder_topology"
  assumes "connected X"
  shows "linear_continuum X"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_24_4: undefined oops (* NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:24_6
natural language statement:
Show that if $X$ is a well-ordered set, then $X \times [0, 1)$ in the dictionary order is a linear continuum.
lean statement:

codex statement:
theorem linear_continuum_of_well_order:
  fixes X::"'a::wellorder set"
  assumes "well_order X"
  shows "linear_continuum (X \<times> {0..<1})"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_24_6: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:25_4
natural language statement:
Let $X$ be locally path connected. Show that every connected open set in $X$ is path connected.
lean statement:
theorem exercise_25_4 {X : Type*} [topological_space X]
  [loc_path_connected_space X] (U : set X) (hU : is_open U)
  (hcU : is_connected U) : is_path_connected U :=

codex statement:
theorem connected_open_is_path_connected:
  fixes X::"'a::topological_space topology"
  assumes "locally path_connected X" "openin X U" "connected U"
  shows "path_connected U"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_25_4: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:25_9
natural language statement:
Let $G$ be a topological group; let $C$ be the component of $G$ containing the identity element $e$. Show that $C$ is a normal subgroup of $G$.
lean statement:
theorem exercise_25_9 {G : Type*} [topological_space G] [group G]
  [topological_group G] (C : set G) (h : C = connected_component 1) :
  is_normal_subgroup C :=

codex statement:
theorem component_of_topological_group_is_normal:
  fixes G::"('a, 'b) topological_group_scheme"
  assumes "topological_group G"
  shows "normal_subgroup (component_of G (\<one> G)) G"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_25_9: undefined oops (* no idea what this is about*)

(*
problem_number:26_9
natural language statement:
Let $A$ and $B$ be subspaces of $X$ and $Y$, respectively; let $N$ be an open set in $X \times Y$ containing $A \times B$. If $A$ and $B$ are compact, then there exist open sets $U$ and $V$ in $X$ and $Y$, respectively, such that $A \times B \subset U \times V \subset N .$
lean statement:

codex statement:
theorem exists_open_subset_of_compact_subset_in_open_set:
  fixes A B::"'a::euclidean_space set" and N::"'a set \<times> 'a set"
  assumes "compact A" "compact B" "open N" "A \<times> B \<subseteq> N"
  shows "\<exists>U V. open U \<and> open V \<and> A \<times> B \<subseteq> U \<times> V \<and> U \<times> V \<subseteq> N"
Our comment on the codex statement: very good but uses type classes
 *)
theorem exercise_26_9:
  assumes "A \<subseteq> topspace X" "B \<subseteq> topspace Y" "openin (prod_topology X Y) N" "A \<times> B \<subseteq> N"
  assumes "compact A" "compact B"
  shows "\<exists>U V. openin X U \<and> openin Y V \<and> A \<times> B \<subseteq> U \<times> V \<and> U \<times> V \<subseteq> N"
  oops

(*
problem_number:26_11
natural language statement:
Let $X$ be a compact Hausdorff space. Let $\mathcal{A}$ be a collection of closed connected subsets of $X$ that is simply ordered by proper inclusion. Then $Y=\bigcap_{A \in \mathcal{A}} A$ is connected.
lean statement:
theorem exercise_26_11
  {X : Type*} [topological_space X] [compact_space X] [t2_space X]
  (A : set (set X)) (hA : \<forall> (a b : set X), a \<in> A \<rightarrow> b \<in> A \<rightarrow> a \<subseteq> b \<or> b \<subseteq> a)
  (hA' : \<forall> a \<in> A, is_closed a) (hA'' : \<forall> a \<in> A, is_connected a) :
  is_connected (\<Inter>₀ A) :=

codex statement:
theorem connected_of_compact_hausdorff_simply_ordered_closed_connected_subsets:
  fixes X::"'a::t2_space set" and A::"'a set set"
  assumes "compact X" "hausdorff X" "\<forall>A B. A \<in> A \<and> B \<in> A \<longrightarrow> A \<subseteq> B \<or> B \<subseteq> A" "\<forall>A\<in>A. closedin (subtopology X UNIV) A \<and> connected A"
  shows "connected (\<Inter>A\<in>A. A)"
Our comment on the codex statement: very good but uses type classes
 *)
theorem exercise_26_11:
  assumes "compact_space X" "Hausdorff_space X" "\<Union>\<A> \<subseteq> topspace X"
    "\<forall>A\<in>\<A>. closedin X A \<and> connectedin X A"
    "\<forall>A\<in>\<A>. \<forall>B\<in>\<A>. A \<subseteq> B \<or> B \<subseteq> A"
  shows "connectedin X (\<Inter>A\<in>A. A)"
oops

(*
problem_number:26_12
natural language statement:
Let $p: X \rightarrow Y$ be a closed continuous surjective map such that $p^{-1}(\{y\})$ is compact, for each $y \in Y$. (Such a map is called a perfect map.) Show that if $Y$ is compact, then $X$ is compact.
lean statement:
theorem exercise_26_12 {X Y : Type*} [topological_space X] [topological_space Y]
  (p : X \<rightarrow> Y) (h : function.surjective p) (hc : continuous p) (hp : \<forall> y, is_compact (p ⁻¹' {y}))
  (hY : compact_space Y) : compact_space X :=

codex statement:
theorem compact_of_perfect_map_compact:
  fixes f::"'a::metric_space \<Rightarrow> 'b::metric_space"
  assumes "compact (UNIV::'b set)" "continuous_on UNIV f" "surj f" "\<forall>y\<in>UNIV. compact (f -` {y})"
  shows "compact (UNIV::'a set)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_26_12:
  assumes "closed_map X Y p" "continuous_map X Y p" "p ` topspace X = topspace Y"
  assumes "\<forall>y \<in> topspace Y. compactin X (f -` {y})" "compact_space Y"
  shows "compact_space X"
oops

(*
problem_number:27_1
natural language statement:
Prove that if $X$ is an ordered set in which every closed interval is compact, then $X$ has the least upper bound property.
lean statement:

codex statement:
theorem least_upper_bound_of_compact_closed_interval:
  fixes X::"'a::{order_topology, linorder_topology} set"
  assumes "compact {a..b}"
  shows "\<exists>c. is_lub {a..b} c"
Our comment on the codex statement:  many quantification issues
 *)
theorem exercise_27_1:  (*this version assumes type classes*)
  fixes A::"'a::linorder_topology set"
  assumes "\<And>a b. a \<in> A \<Longrightarrow> b \<in> A \<Longrightarrow> compact {a..b}"
  assumes "A' \<subseteq> A" "bdd_above A'"
  shows "\<exists>x \<in> A. A' \<subseteq> {..x}"
  oops

(*
problem_number:27_4
natural language statement:
Show that a connected metric space having more than one point is uncountable.
lean statement:
theorem exercise_27_4
  {X : Type*} [metric_space X] [connected_space X] (hX : \<exists> x y : X, x \<noteq> y) :
  \<not> countable (univ : set X) :=

codex statement:
theorem connected_metric_space_of_more_than_one_point_is_uncountable:
  fixes X::"'a::metric_space set"
  assumes "connected X" "card X > 1"
  shows "uncountable X"
Our comment on the codex statement:  perfect, because for this one we have to use type classes ATM
 *)
theorem exercise_27_4: (*this version assumes type classes*)
  fixes X::"'a::metric_space set"
  assumes "connected X" "card X > 1"
  shows "uncountable X"
  using assms connected_finite_iff_sing by fastforce

(*
problem_number:28_4
natural language statement:
A space $X$ is said to be countably compact if every countable open covering of $X$ contains a finite subcollection that covers $X$. Show that for a $T_1$ space $X$, countable compactness is equivalent to limit point compactness.
lean statement:
theorem exercise_28_4 {X : Type*}
  [topological_space X] (hT1 : t1_space X) :
  countably_compact X \<longleftrightarrow> limit_point_compact X :=

codex statement:
theorem countably_compact_of_limit_point_compact:
  fixes X::"'a::t1_space topological_space"
  assumes "limit_point_compact X"
  shows "countably_compact X"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_28_4: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:28_5
natural language statement:
Show that X is countably compact if and only if every nested sequence $C_1 \supset C_2 \supset \cdots$ of closed nonempty sets of X has a nonempty intersection.
lean statement:
theorem exercise_28_5
  (X : Type* ) [topological_space X] :
  countably_compact X \<longleftrightarrow> \<forall> (C : \<nat> \<rightarrow> set X), (\<forall> n, is_closed (C n)) \<and>
  (\<forall> n, C n \<noteq> \<emptyset>) \<and> (\<forall> n, C n \<subseteq> C (n + 1)) \<rightarrow> \<exists> x, \<forall> n, x \<in> C n :=

codex statement:
theorem countably_compact_of_nested_closed_nonempty_has_nonempty_intersection:
  fixes X::"'a::t2_space set"
  assumes "\<forall>n. closed (C n)" "\<forall>n. C n \<noteq> {}" "\<forall>n. C n \<subseteq> C (n+1)"
  shows "\<exists>x. x\<in>\<Inter>n. C n"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_28_5: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:28_6
natural language statement:
Let $(X, d)$ be a metric space. If $f: X \rightarrow X$ satisfies the condition $d(f(x), f(y))=d(x, y)$ for all $x, y \in X$, then $f$ is called an isometry of $X$. Show that if $f$ is an isometry and $X$ is compact, then $f$ is bijective and hence a homeomorphism.
lean statement:
theorem exercise_28_6 {X : Type*} [metric_space X]
  [compact_space X] {f : X \<rightarrow> X} (hf : isometry f) :
  function.bijective f :=

codex statement:
theorem isometry_of_compact_is_homeomorphism:
  fixes f::"'a::metric_space \<Rightarrow> 'a"
  assumes "compact (UNIV::'a set)" "\<forall>x y. dist (f x) (f y) = dist x y"
  shows "homeomorphism (UNIV::'a set) (UNIV::'a set) f"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_28_6: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:29_1
natural language statement:
Show that the rationals $\mathbb{Q}$ are not locally compact.
lean statement:
theorem exercise_29_1 : \<not> locally_compact_space \<rat> :=

codex statement:
theorem not_locally_compact_of_Q:
  shows "\<forall>x\<in>UNIV. \<exists>U. open U \<and> x\<in>U \<and> (\<forall>V. open V \<and> x\<in>V \<longrightarrow> \<exists>y\<in>V. y\<notin>U)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_29_1: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:29_4
natural language statement:
Show that $[0, 1]^\omega$ is not locally compact in the uniform topology.
lean statement:
theorem exercise_29_4 [topological_space (\<nat> \<rightarrow> I)] :
  \<not> locally_compact_space (\<nat> \<rightarrow> I) :=

codex statement:
theorem not_locally_compact_of_uniform_topology:
  fixes X::"nat \<Rightarrow> real"
  assumes "\<forall>n. 0 \<le> X n \<and> X n \<le> 1"
  shows "\<forall>U. openin (uniform_topology (product_topology real UNIV)) U \<longrightarrow> \<exists>V. openin (uniform_topology (product_topology real UNIV)) V \<and> compact V \<and> X \<in> V \<and> V \<subseteq> U"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_29_4: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:29_5
natural language statement:
If $f \colon X_1 \rightarrow X_2$ is a homeomorphism of locally compact Hausdorff spaces, show that $f$ extends to a homeomorphism of their one-point compactifications.
lean statement:

codex statement:
theorem homeomorphism_of_one_point_compactification:
  fixes f::"'a::t2_space \<Rightarrow> 'b::t2_space"
  assumes "homeomorphism X1 X2 f" "locally compact X1" "locally compact X2" "compact_space X1" "compact_space X2"
  shows "homeomorphism (one_point_compactification X1) (one_point_compactification X2) (extend_map f)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_29_5: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:29_6
natural language statement:
Show that the one-point compactification of $\mathbb{R}$ is homeomorphic with the circle $S^1$.
lean statement:

codex statement:
theorem homeomorphic_of_one_point_compactification_of_real_is_circle:
  shows "one_point_compactification \<real> homeomorphic (sphere (1::real) 0)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_29_6: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:29_10
natural language statement:
Show that if $X$ is a Hausdorff space that is locally compact at the point $x$, then for each neighborhood $U$ of $x$, there is a neighborhood $V$ of $x$ such that $\bar{V}$ is compact and $\bar{V} \subset U$.
lean statement:
theorem exercise_29_10 {X : Type*}
  [topological_space X] [t2_space X] (x : X)
  (hx : \<exists> U : set X, x \<in> U \<and> is_open U \<and> (\<exists> K : set X, U \<subset> K \<and> is_compact K))
  (U : set X) (hU : is_open U) (hxU : x \<in> U) :
  \<exists> (V : set X), is_open V \<and> x \<in> V \<and> is_compact (closure V) \<and> closure V \<subseteq> U :=

codex statement:
theorem exists_compact_subset_of_neighborhood:
  fixes X::"'a::metric_space topology" and x::'a
  assumes "x\<in>topspace X" "t1_space X" "locally_compact_space X" "\<exists>U. openin X U \<and> x\<in>U"
  shows "\<exists>V. openin X V \<and> x\<in>V \<and> compact (closure V) \<and> closure V \<subseteq> U"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_29_10: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:30_10
natural language statement:
Show that if $X$ is a countable product of spaces having countable dense subsets, then $X$ has a countable dense subset.
lean statement:
theorem exercise_30_10
  {X : \<nat> \<rightarrow> Type*} [\<forall> i, topological_space (X i)]
  (h : \<forall> i, \<exists> (s : set (X i)), countable s \<and> dense s) :
  \<exists> (s : set (\<pi> i, X i)), countable s \<and> dense s :=

codex statement:
theorem countable_dense_subset_of_countable_product_of_countable_dense_subset:
  fixes X::"'a::{second_countable_topology, t2_space} set"
  assumes "countable X" "\<forall>x\<in>X. \<exists>D. countable D \<and> dense_in (top_of_set X) D"
  shows "\<exists>D. countable D \<and> dense_in (top_of_set X) D"
Our comment on the codex statement: plausible
 *)
theorem exercise_30_10:
  fixes Y :: "'a \<Rightarrow> 'b topology"
  assumes "countable I" "\<forall>i\<in>I. \<exists>D. countable D \<and> D \<subseteq> topspace (Y i) \<and> Y i closure_of D = topspace (Y i)"
  defines "X \<equiv> product_topology Y I"
  shows "\<exists>D. countable D \<and> D \<subseteq> topspace X \<and> X closure_of D = topspace X"
oops

(*
problem_number:30_13
natural language statement:
Show that if $X$ has a countable dense subset, every collection of disjoint open sets in $X$ is countable.
lean statement:
theorem exercise_30_13 {X : Type*} [topological_space X]
  (h : \<exists> (s : set X), countable s \<and> dense s) (U : set (set X))
  (hU : \<forall> (x y : set X), x \<in> U \<rightarrow> y \<in> U \<rightarrow> x \<noteq> y \<rightarrow> x \<inter> y = \<emptyset>) :
  countable U :=

codex statement:
theorem countable_of_dense_countable:
  fixes X::"'a::metric_space set"
  assumes "countable (UNIV::'a set)" "\<forall>x\<in>X. \<exists>U. open U \<and> x\<in>U \<and> U \<subseteq> X"
  shows "countable X"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_30_13:
  assumes "countable D" "D \<subseteq> topspace X" "X closure_of D = topspace X"
    "\<forall>A\<in>\<A>. openin X A" "disjoint \<A>"
  shows "countable \<A>"
  oops

(*
problem_number:31_1
natural language statement:
Show that if $X$ is regular, every pair of points of $X$ have neighborhoods whose closures are disjoint.
lean statement:
theorem exercise_31_1 {X : Type*} [topological_space X]
  (hX : regular_space X) (x y : X) :
  \<exists> (U V : set X), is_open U \<and> is_open V \<and> x \<in> U \<and> y \<in> V \<and> closure U \<inter> closure V = \<emptyset> :=

codex statement:
theorem regular_implies_disjoint_closure_of_neighborhoods:
  fixes X::"'a::t1_space topology"
  assumes "regular_space X"
  shows "\<forall>x y. x \<in> topspace X \<and> y \<in> topspace X \<longrightarrow> \<exists>U V. openin X U \<and> openin X V \<and> x\<in>U \<and> y\<in>V \<and> closure U \<inter> closure V = {}"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_31_1: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:31_2
natural language statement:
Show that if $X$ is normal, every pair of disjoint closed sets have neighborhoods whose closures are disjoint.
lean statement:
theorem exercise_31_2 {X : Type*}
  [topological_space X] [normal_space X] {A B : set X}
  (hA : is_closed A) (hB : is_closed B) (hAB : disjoint A B) :
  \<exists> (U V : set X), is_open U \<and> is_open V \<and> A \<subseteq> U \<and> B \<subseteq> V \<and> closure U \<inter> closure V = \<emptyset> :=

codex statement:
theorem disjoint_closed_sets_have_disjoint_neighborhoods:
  fixes X::"'a::t2_space topology" and A B::"'a set"
  assumes "normal_space X" "closedin X A" "closedin X B" "A \<inter> B = {}"
  shows "\<exists>U V. openin X U \<and> openin X V \<and> A \<subseteq> U \<and> B \<subseteq> V \<and> closure U \<inter> closure V = {}"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_31_2: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:31_3
natural language statement:
Show that every order topology is regular.
lean statement:
theorem exercise_31_3 {\<alpha> : Type*} [partial_order \<alpha>]
  [topological_space \<alpha>] (h : order_topology \<alpha>) : regular_space \<alpha> :=

codex statement:
theorem regular_of_order_topology:
  fixes T::"'a::order topology"
  shows "regular_space T"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_31_3: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:32_1
natural language statement:
Show that a closed subspace of a normal space is normal.
lean statement:
theorem exercise_32_1 {X : Type*} [topological_space X]
  (hX : normal_space X) (A : set X) (hA : is_closed A) :
  normal_space {x // x \<in> A} :=

codex statement:
theorem closed_subspace_of_normal_is_normal:
  fixes X::"'a::t2_space set" and Y::"'b::t2_space set"
  assumes "closed_in (subtopology euclidean X) Y" "normal_space X"
  shows "normal_space Y"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_32_1: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:32_2
natural language statement:
Show that if $\prod X_\alpha$ is Hausdorff, or regular, or normal, then so is $X_\alpha$. Assume that each $X_\alpha$ is nonempty.
lean statement:
theorem exercise_32_2a
  {\<iota> : Type*} {X : \<iota> \<rightarrow> Type*} [\<forall> i, topological_space (X i)]
  (h : \<forall> i, nonempty (X i)) (h2 : t2_space (\<pi> i, X i)) :
  \<forall> i, t2_space (X i) :=

codex statement:
theorem prod_topology_of_topology_is_topology:
  fixes \<alpha>::"'a" and X::"'a \<Rightarrow> 'b::topological_space"
  assumes "\<forall>\<alpha>. x \<in> X \<alpha>"
  shows "\<forall>\<alpha>. openin (prod_topology (\<alpha>::'a) X) {x} \<longrightarrow> openin (X \<alpha>) {x \<alpha>}"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_32_2:
    fixes X :: "'a \<Rightarrow> 'b topology"
  assumes "\<forall>i\<in>I. topspace (X i) \<noteq> {}" "Hausdorff_space (product_topology X I)" "i \<in> I"
  shows "Hausdorff_space (X i)"
oops

(*
problem_number:32_2
natural language statement:
Show that every locally compact Hausdorff space is regular.
lean statement:
theorem exercise_32_2a
  {\<iota> : Type*} {X : \<iota> \<rightarrow> Type*} [\<forall> i, topological_space (X i)]
  (h : \<forall> i, nonempty (X i)) (h2 : t2_space (\<pi> i, X i)) :
  \<forall> i, t2_space (X i) :=

codex statement:
theorem regular_of_locally_compact_hausdorff:
  fixes X::"'a::metric_space topology"
  assumes "locally_compact_space X" "hausdorff_space X"
  shows "regular_space X"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_32_2: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:33_7
natural language statement:
Show that every locally compact Hausdorff space is completely regular.
lean statement:
theorem exercise_33_7 {X : Type*} [topological_space X]
  (hX : locally_compact_space X) (hX' : t2_space X) :
  \<forall> x A, is_closed A \<and> \<not> x \<in> A \<rightarrow>
  \<exists> (f : X \<rightarrow> I), continuous f \<and> f x = 1 \<and> f '' A = {0}
  :=

codex statement:
theorem locally_compact_hausdorff_is_completely_regular:
  fixes T::"'a::metric_space topology"
  assumes "locally_compact T" "T_2_space T"
  shows "completely_regular_space T"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_33_7: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:33_8
natural language statement:
Let $X$ be completely regular, let $A$ and $B$ be disjoint closed subsets of $X$. Show that if $A$ is compact, there is a continuous function $f \colon X \rightarrow [0, 1]$ such that $f(A) = \{0\}$ and $f(B) = \{1\}$.
lean statement:
theorem exercise_33_8
  (X : Type* ) [topological_space X] [regular_space X]
  (h : \<forall> x A, is_closed A \<and> \<not> x \<in> A \<rightarrow>
  \<exists> (f : X \<rightarrow> I), continuous f \<and> f x = (1 : I) \<and> f '' A = {0})
  (A B : set X) (hA : is_closed A) (hB : is_closed B)
  (hAB : disjoint A B)
  (hAc : is_compact A) :
  \<exists> (f : X \<rightarrow> I), continuous f \<and> f '' A = {0} \<and> f '' B = {1} :=

codex statement:
theorem exists_continuous_function_of_disjoint_compact_closed_sets:
  fixes X::"'a::t2_space" and A B::"'a set"
  assumes "compact A" "closed A" "closed B" "A \<inter> B = \<emptyset>"
  shows "\<exists>f. continuous_on X f \<and> f ` X \<subseteq> {0..1} \<and> f ` A = {0} \<and> f ` B = {1}"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_33_8: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:34_9
natural language statement:
Let $X$ be a compact Hausdorif space that is the union of the closed subspaces $X_1$ and $X_2$. If $X_1$ and $X_2$ are metrizable, show that $X$ is metrizable.
lean statement:
theorem exercise_34_9
  (X : Type* ) [topological_space X] [compact_space X]
  (X1 X2 : set X) (hX1 : is_closed X1) (hX2 : is_closed X2)
  (hX : X1 \<union> X2 = univ) (hX1m : metrizable_space X1)
  (hX2m : metrizable_space X2) : metrizable_space X :=

codex statement:
theorem metrizable_of_compact_union_of_metrizable:
  fixes X::"'a::metric_space set" and X1 X2::"'a set"
  assumes "compact X" "closed X1" "closed X2" "X = X1 \<union> X2" "metrizable X1" "metrizable X2"
  shows "metrizable X"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_34_9: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:37_2
natural language statement:
A collection $\mathcal{A}$ of subsets of $X$ has the countable intersection property if every countable intersection of elements of $\mathcal{A}$ is nonempty. Show that $X$ is a Lindelöf space if and only if for every collection $\mathcal{A}$ of subsets of $X$ having the countable intersection property, $\bigcap_{A \in \mathcal{A}} \bar{A}$ is nonempty.
lean statement:

codex statement:
theorem lindelof_iff_countable_intersection_property:
  fixes X::"'a::metric_space topology"
  assumes "countable_basis X"
  shows "Lindelöf_space X \<longleftrightarrow> (\<forall>A. (\<forall>a\<in>A. openin X a) \<longrightarrow> (\<exists>b. openin X b \<and> \<forall>a\<in>A. a \<subseteq> b) \<longrightarrow> (\<exists>x. \<forall>a\<in>A. x\<in>a))"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_37_2: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:38_4
natural language statement:
Let $Y$ be an arbitrary compactification of $X$; let $\beta(X)$ be the Stone-Čech compactification. Show there is a continuous surjective closed map $g \colon \beta(X)\rightarrow Y$ that equals the identity on $X$.
lean statement:

codex statement:
theorem exists_continuous_surjective_closed_map_of_compactification:
  fixes X::"'a::t1_space set" and Y::"'b::t1_space set"
  assumes "compactification X Y"
  shows "\<exists>g. continuous_on (UNIV::'b set) g \<and> g ` (UNIV::'b set) = UNIV \<and> closed_in (subtopology (top_of_set (UNIV::'b set)) (UNIV::'b set)) (g -` (UNIV::'a set)) \<and> g ` (UNIV::'a set) = (UNIV::'a set)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_38_4: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:38_6
natural language statement:
Let $X$ be completely regular. Show that $X$ is connected if and only if $\beta(X)$ is connected.
lean statement:
theorem exercise_38_6 {X : Type*}
  (X : Type* ) [topological_space X] [regular_space X]
  (h : \<forall> x A, is_closed A \<and> \<not> x \<in> A \<rightarrow>
  \<exists> (f : X \<rightarrow> I), continuous f \<and> f x = (1 : I) \<and> f '' A = {0}) :
  is_connected (univ : set X) \<longleftrightarrow> is_connected (univ : set (stone_cech X)) :=

codex statement:
theorem connected_of_completely_regular_iff_connected_beta:
  fixes X::"'a::t2_space topology"
  assumes "completely_regular_space X"
  shows "connected X \<longleftrightarrow> connected (\<beta> X)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_38_6: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:39_5
natural language statement:
Show that if X has a countable basis, a collection $\mathcal{A}$ of subsets of $X$ is countably locally finite if and only if it is countable.
lean statement:

codex statement:
theorem countable_of_countably_locally_finite:
  fixes X::"'a::metric_space set" and A::"'a set set"
  assumes "countable_basis X" "countably_locally_finite A"
  shows "countable A"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_39_5: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:43_2
natural language statement:
Let $(X, d_X)$ and $(Y, d_Y)$ be metric spaces; let $Y$ be complete. Let $A \subset X$. Show that if $f \colon A \rightarrow Y$ is uniformly continuous, then $f$ can be uniquely extended to a continuous function $g \colon \bar{A} \rightarrow Y$, and $g$ is uniformly continuous.
lean statement:
theorem exercise_43_2 {X : Type*} [metric_space X]
  {Y : Type*} [metric_space Y] [complete_space Y] (A : set X)
  (f : X \<rightarrow> Y) (hf : uniform_continuous_on f A) :
  \<exists>! (g : X \<rightarrow> Y), continuous_on g (closure A) \<and>
  uniform_continuous_on g (closure A) \<and> \<forall> (x : A), g x = f x :=

codex statement:
theorem uniformly_continuous_extends_to_continuous_uniformly_continuous:
  fixes f::"'a::metric_space \<Rightarrow> 'b::complete_space"
  assumes "uniformly_continuous_on A f"
  shows "\<exists>g. continuous_on (closure A) g \<and> g|`A = f \<and> uniformly_continuous_on (closure A) g"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_43_2: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

(*
problem_number:43_7
natural language statement:
Show that the set of all sequences $(x_1, x_2, \ldots)$ such that $\sum x_i^2$ converges is complete in $l^2$-metric.
lean statement:

codex statement:
theorem complete_of_sum_square_converges:
  fixes X::"nat \<Rightarrow> 'a::real_normed_vector"
  assumes "\<forall>n. norm (X n) < \<infinity>"
  shows "\<exists>l. (\<forall>n. norm (X n - l) < e) \<longrightarrow> (\<exists>N. \<forall>n\<ge>N. norm (X n - l) < e)"
Our comment on the codex statement: <YOU CAN LEAVE YOUR COMMENT HERE>
 *)
theorem exercise_43_7: undefined oops (*NOT EASILY EXPRESSIBLE using our primitives*)

end


theory Part_2 imports Main

begin

inductive ev :: "nat \<Rightarrow> bool" where
ev0: "ev 0" |
evSS: "ev n \<Longrightarrow> ev(Suc(Suc n))"

(* 5.3 *)

lemma assumes a: "ev(Suc(Suc n))" shows "ev n"
proof -
  show ?thesis using a
  proof cases
    case evSS thus ?thesis by auto
  qed
qed

(* 5.4 *)

lemma "\<not> ev(Suc(Suc(Suc 0)))" (is "\<not> ?P")
proof
  assume "?P"
  hence "ev (Suc 0)" using ev.cases by blast
  thus "False" using ev.cases by blast
qed

(* 5.5 *)

inductive star :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" for r where
refl: "star r x x" |
step: "r x y \<Longrightarrow> star r y z \<Longrightarrow> star r x z"

inductive iter :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> nat \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" where
it0: "iter r 0 x x" |
it_SS: "r x y \<Longrightarrow> iter r n y z \<Longrightarrow> iter r (Suc n) x z"

lemma "iter r n x y \<Longrightarrow> star r x y"
proof (induction rule: iter.induct)
  case it0
    show ?case by (simp add: star.refl)
next
  case it_SS
  thus ?case by (meson star.step)
qed

(* 5.6 *)

fun elems :: "'a list \<Rightarrow> 'a set" where
"elems [] = {}" |
"elems (x#xs) = {x} \<union> elems xs"

lemma "x \<in> elems xs \<Longrightarrow> \<exists>ys zs. xs = ys @ x # zs \<and> x \<notin> elems ys"
proof (induction xs)
  case Nil
  thus ?case by auto
next
  case (Cons a xs)
  show ?case
  proof cases
    assume "a = x"
    obtain ys where ys:"(ys::'a list) = []" by auto
    obtain zs where "zs = xs" by auto
    have "a \<notin> elems ys" by (simp add: ys)
    thus ?thesis using ys using \<open>a = x\<close> by blast
  next
    assume "a \<noteq> x"
    hence "x \<in> elems xs" using Cons.prems by auto
    obtain ys where ys:"ys = [a]" by auto
    obtain zs where zs:"zs = xs" by auto
    thus ?thesis using ys zs
      by (metis Cons.IH Cons_eq_appendI Un_iff \<open>a \<noteq> x\<close> \<open>x \<in> elems xs\<close> elems.simps(2) ex_in_conv insert_iff)
  qed
qed

(* 5.7 *)

datatype alpha = a | b (* a == '(', b == ')' *)

(*
Grammar for balanced parentheses S
  S \<rightarrow> \<epsilon> | aSb | SS
*)
inductive S :: "alpha list \<Rightarrow> bool" where
S0: "S []" |
S1: "S w \<Longrightarrow> S (a # w @ [b])" (*S [a,b,a,b] \<rightarrow> S [a,b] \<rightarrow> S [] \<rightarrow> true *) |
S2: "S w \<Longrightarrow> S x \<Longrightarrow> S (w @ x)" (* S [a,b,a,b] \<rightarrow> S [a,b] \<and> S [a,b] \<rightarrow> true *)

(*
Second grammar for balanced parentheses T
  T \<rightarrow> \<epsilon> | TaTb
*)
inductive T :: "alpha list \<Rightarrow> bool" where
T0: "T []" |
T1: "T w \<Longrightarrow> T x \<Longrightarrow> T (w @ [a] @ x @ [b])"

lemma TS : "T w \<Longrightarrow> S w"
  apply(induction rule: T.induct)
   apply(auto intro: S0 S1 S2)
  done

lemma ST : "S w \<Longrightarrow> T w"
proof (induction rule: S.induct)
  case S0
  thus ?case by (simp add: T0)
next
  case S1
  thus ?case using T1 by blast
next
  case S2
  thus ?case using T1 by blast
qed

corollary SeqT: "S w \<longleftrightarrow> T w"
  apply(auto intro: ST TS)
  done

fun balanced :: "nat \<Rightarrow> alpha list \<Rightarrow> bool" where
"balanced 0 w = S w" |
"balanced n w = balanced (n - 1) (a # w)"

corollary "balanced n w \<longleftrightarrow> S (replicate n a @ w)" (is "?P \<longleftrightarrow> ?Q")
proof
  assume "?P"
  from this show "?Q"
  proof (induction n)
    case 0
    thus ?case by simp
  next
    case (Suc m)
    thus ?case using S0 and S2 by blast
  qed
next
  assume "?Q"
  from this show "?P"
  proof (induction n)
    case 0
    thus ?case by auto
  next
    case (Suc m)
    thus ?case using S0 and S1 and S2 by blast
  qed
qed

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.
\:w
   Some proofs were added by Yutaka Nagashima.*)
  theory TIP_sort_nat_HSortSorts
  imports "../../Test_Base"
begin

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

datatype Nat = Z | S "Nat"

datatype Heap = Node "Heap" "Nat" "Heap" | Nil

fun toHeap :: "Nat list => Heap list" where
  "toHeap (nil2) = nil2"
| "toHeap (cons2 y z) = cons2 (Node Nil y Nil) (toHeap z)"

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

fun ordered :: "Nat list => bool" where
  "ordered (nil2) = True"
| "ordered (cons2 y (nil2)) = True"
| "ordered (cons2 y (cons2 y2 xs)) =
     ((le y y2) & (ordered (cons2 y2 xs)))"

fun hmerge :: "Heap => Heap => Heap" where
  "hmerge (Node z x2 x3) (Node x4 x5 x6) =
   (if le x2 x5 then Node (hmerge x3 (Node x4 x5 x6)) x2 z else
      Node (hmerge (Node z x2 x3) x6) x5 x4)"
| "hmerge (Node z x2 x3) (Nil) = Node z x2 x3"
| "hmerge (Nil) y = y"

fun hpairwise :: "Heap list => Heap list" where
  "hpairwise (nil2) = nil2"
| "hpairwise (cons2 q (nil2)) = cons2 q (nil2)"
| "hpairwise (cons2 q (cons2 r qs)) =
     cons2 (hmerge q r) (hpairwise qs)"

(*fun did not finish the proof*)
function hmerging :: "Heap list => Heap" where
  "hmerging (nil2) = Nil"
| "hmerging (cons2 q (nil2)) = q"
| "hmerging (cons2 q (cons2 z x2)) =
     hmerging (hpairwise (cons2 q (cons2 z x2)))"
  by pat_completeness auto

fun toHeap2 :: "Nat list => Heap" where
  "toHeap2 x = hmerging (toHeap x)"

(*fun did not finish the proof*)
function toList :: "Heap => Nat list" where
  "toList (Node q y r) = cons2 y (toList (hmerge q r))"
| "toList (Nil) = nil2"
  by pat_completeness auto

fun hsort :: "Nat list => Nat list" where
  "hsort x = toList (toHeap2 x)"

theorem property0 :
  "ordered (hsort xs)"
  oops

end


(*  Title:       Defintion and basics facts about Cantor pairing function
    Author:      Michael Nedzelsky <MichaelNedzelsky at yandex.ru>, 2008
    Maintainer:  Michael Nedzelsky <MichaelNedzelsky at yandex.ru>
*)

section \<open>Cantor pairing function\<close>

theory CPair
imports Main
begin

text \<open>
  We introduce a particular coding \<open>c_pair\<close> from ordered pairs
  of natural numbers to natural numbers.  See \cite{Rogers} and the
  Isabelle documentation for more information.
\<close>

subsection \<open>Pairing function\<close>

definition
  sf :: "nat \<Rightarrow> nat" where
  sf_def: "sf x = x * (x+1) div 2"

definition
  c_pair :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
  "c_pair x y = sf (x+y) + x"

lemma sf_at_0: "sf 0 = 0" by (simp add: sf_def)

lemma sf_at_1: "sf 1 = 1" by (simp add: sf_def)

lemma sf_at_Suc: "sf (x+1) = sf x + x + 1"
proof -
  have S1: "sf(x+1) = ((x+1)*(x+2)) div 2" by (simp add: sf_def)
  have S2: "(x+1)*(x+2) = x*(x+1) + 2*(x+1)" by (auto)
  have S2_1: "\<And> x y. x=y \<Longrightarrow> x div 2 = y div 2" by auto
  from S2 have S3: "(x+1)*(x+2) div 2 = (x*(x+1) + 2*(x+1)) div 2" by (rule S2_1)
  have S4: "(0::nat) < 2" by (auto)
  from S4 have S5: "(x*(x+1) + 2*(x+1)) div 2 = (x+1) + x*(x+1) div 2" by simp
  from S1 S3 S5 show ?thesis by (simp add: sf_def)
qed

lemma arg_le_sf: "x \<le> sf x"
proof -
  have "x + x \<le> x*(x + 1)" by simp
  hence "(x + x) div 2 \<le> x*(x+1) div 2" by (rule div_le_mono)
  hence "x \<le> x*(x+1) div 2" by simp
  thus ?thesis by (simp add: sf_def)
qed

lemma sf_mono: "x \<le> y \<Longrightarrow> sf x \<le> sf y"
proof -
  assume A1: "x \<le> y"
  then have "x+1 \<le> y+1" by (auto)
  with A1 have "x*(x+1) \<le> y*(y+1)" by (rule mult_le_mono)
  then have "x*(x+1) div 2 \<le> y*(y+1) div 2" by (rule div_le_mono)
  thus ?thesis by (simp add: sf_def)
qed

lemma sf_strict_mono: "x < y \<Longrightarrow> sf x < sf y"
proof -
  assume A1: "x < y"
  from A1 have S1: "x+1 \<le> y" by simp
  from S1 sf_mono have S2: "sf (x+1) \<le> sf y" by (auto)
  from sf_at_Suc have S3: "sf x < sf (x+1)" by (auto)
  from S2 S3 show ?thesis by (auto)
qed

lemma sf_posI: "x > 0 \<Longrightarrow> sf(x) > 0"
proof -
  assume A1: "x > 0"
  then have "sf(0) < sf(x)" by (rule sf_strict_mono)
  then show ?thesis by simp
qed

lemma arg_less_sf: "x > 1 \<Longrightarrow> x < sf(x)"
proof -
  assume A1: "x > 1"
  let ?y = "x-(1::nat)"
  from A1 have S1: "x = ?y+1" by simp
  from A1 have "?y > 0" by simp
  then have S2: "sf(?y) > 0" by (rule sf_posI)
  have "sf(?y+1) = sf(?y) + ?y + 1" by (rule sf_at_Suc)
  with S1 have "sf(x) = sf(?y) + x" by simp
  with S2  show ?thesis by simp
qed

lemma sf_eq_arg: "sf x = x \<Longrightarrow> x \<le> 1"
proof -
  assume "sf(x) = x"
  then have "\<not> (x < sf(x))" by simp
  then have "(\<not> (x > 1))" by (auto simp add: arg_less_sf)
  then show ?thesis by simp
qed

lemma sf_le_sfD: "sf x \<le> sf y \<Longrightarrow> x \<le> y"
proof -
  assume A1: "sf x \<le> sf y"
  have S1: "y < x \<Longrightarrow> sf y < sf x" by (rule sf_strict_mono)
  have S2: "y < x \<or> x \<le> y" by (auto)
  from A1 S1 S2 show ?thesis by (auto)
qed

lemma sf_less_sfD: "sf x < sf y \<Longrightarrow> x < y"
proof -
  assume A1: "sf x < sf y"
  have S1: "y \<le> x \<Longrightarrow> sf y \<le> sf x" by (rule sf_mono)
  have S2: "y \<le> x \<or> x < y" by (auto)
  from A1 S1 S2 show ?thesis by (auto)
qed

lemma sf_inj: "sf x = sf y \<Longrightarrow> x = y"
proof -
  assume A1: "sf x = sf y"
  have S1: "sf x \<le> sf y \<Longrightarrow> x \<le> y" by (rule sf_le_sfD)
  have S2: "sf y \<le> sf x \<Longrightarrow> y \<le> x" by (rule sf_le_sfD)
  from A1 have S3: "sf x \<le> sf y \<and> sf y \<le> sf x" by (auto)
  from S3 S1 S2 have S4: "x \<le> y \<and> y \<le> x" by (auto)
  from S4 show ?thesis by (auto)
qed

text \<open>Auxiliary lemmas\<close>

lemma sf_aux1: "x + y < z \<Longrightarrow> sf(x+y) + x < sf(z)"
proof -
  assume A1: "x+y < z"
  from A1 have S1: "x+y+1 \<le> z" by (auto)
  from S1 have S2: "sf(x+y+1) \<le> sf(z)" by (rule sf_mono)
  have S3: "sf(x+y+1) = sf(x+y) + (x+y)+1" by (rule sf_at_Suc)
  from S3 S2 have S4: "sf(x+y) + (x+y) + 1 \<le> sf(z)" by (auto)
  from S4 show ?thesis by (auto)
qed

lemma sf_aux2: "sf(z) \<le> sf(x+y) + x \<Longrightarrow> z \<le> x+y"
proof -
  assume A1: "sf(z) \<le> sf(x+y) + x"
  from A1 have S1: "\<not> sf(x+y) +x < sf(z)" by (auto)
  from S1 sf_aux1 have S2: "\<not> x+y < z" by (auto)
  from S2 show ?thesis by (auto)
qed

lemma sf_aux3: "sf(z) + m < sf(z+1) \<Longrightarrow> m \<le> z"
proof -
  assume A1: "sf(z) + m < sf(z+1)"
  have S1: "sf(z+1) = sf(z) + z + 1" by (rule sf_at_Suc)
  from A1 S1 have S2: "sf(z) + m < sf(z) + z + 1" by (auto)
  from S2 have S3: "m < z + 1" by (auto)
  from S3 show ?thesis by (auto)
qed

lemma sf_aux4: "(s::nat) < t \<Longrightarrow> (sf s) + s < sf t"
proof -
  assume A1: "(s::nat) < t"
  have "s*(s + 1) + 2*(s+1) \<le> t*(t+1)"
  proof -
    from A1 have S1: "(s::nat) + 1 \<le> t" by (auto)
    from A1 have "(s::nat) + 2 \<le> t+1" by (auto)
    with S1 have "((s::nat)+1)*(s+2) \<le> t*(t+1)" by (rule mult_le_mono)
    thus ?thesis by (auto)
  qed
  then have S1: "(s*(s+1) + 2*(s+1)) div 2 \<le>  t*(t+1) div 2" by (rule div_le_mono)
  have "(0::nat) < 2" by (auto)
  then have "(s*(s+1) + 2*(s+1)) div 2 = (s+1) + (s*(s+1)) div 2" by simp
  with S1 have "(s*(s+1)) div 2 + (s+1) \<le> t*(t+1) div 2" by (auto)
  then have "(s*(s+1)) div 2 + s < t*(t+1) div 2" by (auto)
  thus ?thesis by (simp add: sf_def)
qed

text \<open>Basic properties of c\_pair function\<close>

lemma sum_le_c_pair: "x + y \<le> c_pair x y"
proof -
  have "x+y \<le> sf(x+y)" by (rule arg_le_sf)
  thus ?thesis by (simp add: c_pair_def)
qed

lemma arg1_le_c_pair: "x \<le> c_pair x y"
proof -
  have "(x::nat) \<le> x + y" by (simp)
  moreover have "x + y \<le> c_pair x y" by (rule sum_le_c_pair)
  ultimately show ?thesis by (simp)
qed

lemma arg2_le_c_pair: "y \<le> c_pair x y"
proof -
  have "(y::nat) \<le> x + y" by (simp)
  moreover have "x + y \<le> c_pair x y" by (rule sum_le_c_pair)
  ultimately show ?thesis by (simp)
qed

lemma c_pair_sum_mono: "(x1::nat) + y1 < x2 + y2 \<Longrightarrow> c_pair x1 y1 < c_pair x2 y2"
proof -
  assume "(x1::nat) + y1 < x2 + y2"
  hence "sf (x1+y1) + (x1+y1) < sf(x2+y2)" by (rule sf_aux4)
  hence "sf (x1+y1) + x1 < sf(x2+y2) + x2" by (auto)
  thus ?thesis by (simp add: c_pair_def)
qed

lemma c_pair_sum_inj: "c_pair x1 y1 = c_pair x2 y2 \<Longrightarrow> x1 + y1 = x2 + y2"
proof -
  assume A1: "c_pair x1 y1 = c_pair x2 y2"
  have S1: "(x1::nat) + y1 < x2 + y2 \<Longrightarrow> c_pair x1 y1 \<noteq> c_pair x2 y2" by (rule less_not_refl3, rule c_pair_sum_mono, auto)
  have S2: "(x2::nat) + y2 < x1 + y1 \<Longrightarrow> c_pair x1 y1 \<noteq> c_pair x2 y2" by (rule less_not_refl2, rule c_pair_sum_mono, auto)
  from S1 S2 have "(x1::nat) + y1 \<noteq> x2 + y2 \<Longrightarrow> c_pair x1 y1 \<noteq> c_pair x2 y2" by (arith)
  with A1 show ?thesis by (auto)
qed

lemma c_pair_inj: "c_pair x1 y1 = c_pair x2 y2 \<Longrightarrow> x1 = x2 \<and> y1 = y2"
proof -
  assume A1: "c_pair x1 y1 = c_pair x2 y2"
  from A1 have S1: "x1 + y1 = x2 + y2" by (rule c_pair_sum_inj)
  from A1 have S2: "sf (x1+y1) + x1 = sf (x2+y2) + x2" by (unfold c_pair_def)
  from S1 S2 have S3: "x1 = x2" by (simp)
  from S1 S3 have S4: "y1 = y2" by (simp)
  from S3 S4 show ?thesis by (auto)
qed

lemma c_pair_inj1: "c_pair x1 y1 = c_pair x2 y2 \<Longrightarrow> x1 = x2" by (frule c_pair_inj, drule conjunct1)

lemma c_pair_inj2: "c_pair x1 y1 = c_pair x2 y2 \<Longrightarrow> y1 = y2" by (frule c_pair_inj, drule conjunct2)

lemma c_pair_strict_mono1: "x1 < x2 \<Longrightarrow> c_pair x1 y < c_pair x2 y"
proof -
  assume "x1 < x2"
  then have "x1 + y < x2 + y" by simp
  then show ?thesis by (rule c_pair_sum_mono)
qed

lemma c_pair_mono1: "x1 \<le> x2 \<Longrightarrow> c_pair x1 y \<le> c_pair x2 y"
proof -
  assume A1: "x1 \<le> x2"
  show ?thesis
  proof cases
    assume "x1 < x2"
    then have "c_pair x1 y < c_pair x2 y" by (rule c_pair_strict_mono1)
    then show ?thesis by simp
  next
    assume "\<not> x1 < x2"
    with A1 have "x1 = x2" by simp
    then show ?thesis by simp
  qed
qed

lemma c_pair_strict_mono2: "y1 < y2 \<Longrightarrow> c_pair x y1 < c_pair x y2"
proof -
  assume A1: "y1 < y2"
  from A1 have S1: "x + y1 < x + y2" by simp
  then show ?thesis by (rule c_pair_sum_mono)
qed

lemma c_pair_mono2: "y1 \<le> y2 \<Longrightarrow> c_pair x y1 \<le> c_pair x y2"
proof -
  assume A1: "y1 \<le> y2"
  show ?thesis
  proof cases
    assume "y1 < y2"
    then have "c_pair x y1 < c_pair x y2" by (rule c_pair_strict_mono2)
    then show ?thesis by simp
  next
    assume "\<not> y1 < y2"
    with A1 have "y1 = y2" by simp
    then show ?thesis by simp
  qed
qed

subsection \<open>Inverse mapping\<close>

text \<open>
  \<open>c_fst\<close> and \<open>c_snd\<close> are the functions which yield
  the inverse mapping to \<open>c_pair\<close>.
\<close>

definition
  c_sum :: "nat \<Rightarrow> nat" where
  "c_sum u = (LEAST z. u < sf (z+1))"

definition
  c_fst :: "nat \<Rightarrow> nat" where
  "c_fst u = u - sf (c_sum u)"

definition
  c_snd :: "nat \<Rightarrow> nat" where
  "c_snd u = c_sum u - c_fst u"

lemma arg_less_sf_at_Suc_of_c_sum: "u < sf ((c_sum u) + 1)"
proof -
  have "u+1 \<le> sf(u+1)" by (rule arg_le_sf)
  hence "u < sf(u+1)" by simp
  thus ?thesis by (unfold c_sum_def, rule LeastI)
qed

lemma arg_less_sf_imp_c_sum_less_arg: "u < sf(x) \<Longrightarrow> c_sum u < x"
proof -
  assume A1: "u < sf(x)"
  then show ?thesis
  proof (cases x)
    assume "x=0"
    with A1 show ?thesis by (simp add: sf_def)
  next
    fix y
    assume A2: "x = Suc y"
    show ?thesis
    proof -
      from A1 A2 have "u < sf(y+1)" by simp
      hence "(Least (%z. u < sf (z+1))) \<le> y" by (rule Least_le)
      hence "c_sum u \<le> y" by (fold c_sum_def)
      with A2 show ?thesis by simp
    qed
  qed
qed

lemma sf_c_sum_le_arg: "u \<ge> sf (c_sum u)"
proof -
  let ?z = "c_sum u"
  from arg_less_sf_at_Suc_of_c_sum have S1: "u < sf (?z+1)" by (auto)
  have S2: "\<not> c_sum u < c_sum u" by (auto)
  from arg_less_sf_imp_c_sum_less_arg S2 have S3: "\<not> u < sf (c_sum u) " by (auto)
  from S3 show ?thesis by (auto)
qed

lemma c_sum_le_arg: "c_sum u \<le> u"
proof -
  have "c_sum u \<le> sf (c_sum u)" by (rule arg_le_sf)
  moreover have "sf(c_sum u) \<le> u" by (rule sf_c_sum_le_arg)
  ultimately show ?thesis by simp
qed

lemma c_sum_of_c_pair [simp]: "c_sum (c_pair x y) = x + y"
proof -
  let ?u = "c_pair x y"
  let ?z = "c_sum ?u"
  have S1: "?u < sf(?z+1)" by (rule arg_less_sf_at_Suc_of_c_sum)
  have S2: "sf(?z) \<le> ?u" by (rule sf_c_sum_le_arg)
  from S1 have S3: "sf(x+y)+x < sf(?z+1)" by (simp add: c_pair_def)
  from S2 have S4: "sf(?z) \<le> sf(x+y) + x" by (simp add: c_pair_def)
  from S3 have S5: "sf(x+y) < sf(?z+1)" by (auto)
  from S5 have S6: "x+y < ?z+1" by (rule sf_less_sfD)
  from S6 have S7: "x+y \<le> ?z" by (auto)
  from S4 have S8: "?z \<le> x+y" by (rule sf_aux2)
  from S7 S8 have S9: "?z = x+y" by (auto)
  from S9 show ?thesis by (simp)
qed

lemma c_fst_of_c_pair[simp]: "c_fst (c_pair x y) = x"
proof -
  let ?u = "c_pair x y"
  have "c_sum ?u = x + y" by simp
  hence "c_fst ?u = ?u - sf(x+y)" by (simp add: c_fst_def)
  moreover have "?u = sf(x+y) + x" by (simp add: c_pair_def)
  ultimately show ?thesis by (simp)
qed

lemma c_snd_of_c_pair[simp]: "c_snd (c_pair x y) = y"
proof -
  let ?u = "c_pair x y"
  have "c_sum ?u = x + y" by simp
  moreover have "c_fst ?u = x" by simp
  ultimately show ?thesis by (simp add: c_snd_def)
qed

lemma c_pair_at_0: "c_pair 0 0 = 0" by (simp add: sf_def c_pair_def)

lemma c_fst_at_0: "c_fst 0 = 0"
proof -
  have "c_pair 0 0 = 0" by (rule c_pair_at_0)
  hence "c_fst 0 = c_fst (c_pair 0 0)" by simp
  thus ?thesis by simp
qed

lemma c_snd_at_0: "c_snd 0 = 0"
proof -
  have "c_pair 0 0 = 0" by (rule c_pair_at_0)
  hence "c_snd 0 = c_snd (c_pair 0 0)" by simp
  thus ?thesis by simp
qed

lemma sf_c_sum_plus_c_fst: "sf(c_sum u) + c_fst u = u"
proof -
  have S1: "sf(c_sum u) \<le> u" by (rule sf_c_sum_le_arg)
  have S2: "c_fst u = u - sf(c_sum u)" by (simp add: c_fst_def)
  from S1 S2 show ?thesis by (auto)
qed

lemma c_fst_le_c_sum: "c_fst u \<le> c_sum u"
proof -
  have S1: "sf(c_sum u) + c_fst u = u" by (rule sf_c_sum_plus_c_fst)
  have S2: "u < sf((c_sum u) + 1)" by (rule arg_less_sf_at_Suc_of_c_sum)
  from S1 S2 sf_aux3 show ?thesis by (auto)
qed

lemma c_snd_le_c_sum: "c_snd u \<le> c_sum u" by (simp add: c_snd_def)

lemma c_fst_le_arg: "c_fst u \<le> u"
proof -
  have "c_fst u \<le> c_sum u" by (rule c_fst_le_c_sum)
  moreover have "c_sum u \<le> u" by (rule c_sum_le_arg)
  ultimately show ?thesis by simp
qed

lemma c_snd_le_arg: "c_snd u \<le> u"
proof -
  have "c_snd u \<le> c_sum u" by (rule c_snd_le_c_sum)
  moreover have "c_sum u \<le> u" by (rule c_sum_le_arg)
  ultimately show ?thesis by simp
qed

lemma c_sum_is_sum: "c_sum u = c_fst u + c_snd u" by (simp add: c_snd_def c_fst_le_c_sum)

lemma proj_eq_imp_arg_eq: "\<lbrakk> c_fst u = c_fst v; c_snd u = c_snd v\<rbrakk> \<Longrightarrow> u = v"
proof -
  assume A1: "c_fst u = c_fst v"
  assume A2: "c_snd u = c_snd v"
  from A1 A2 c_sum_is_sum have S1: "c_sum u = c_sum v" by (auto)
  have S2: "sf(c_sum u) + c_fst u = u" by (rule sf_c_sum_plus_c_fst)
  from A1 S1 S2 have S3: "sf(c_sum v) + c_fst v = u" by (auto)
  from S3 sf_c_sum_plus_c_fst show ?thesis by (auto)
qed

lemma c_pair_of_c_fst_c_snd[simp]: "c_pair (c_fst u) (c_snd u) = u"
proof -
  let ?x = "c_fst u"
  let ?y = "c_snd u"
  have S1: "c_pair ?x ?y = sf(?x + ?y) + ?x" by (simp add: c_pair_def)
  have S2: "c_sum u = ?x + ?y" by (rule c_sum_is_sum)
  from S1 S2 have "c_pair ?x ?y = sf(c_sum u) + c_fst u" by (auto)
  thus ?thesis by (simp add: sf_c_sum_plus_c_fst)
qed

lemma c_sum_eq_arg: "c_sum x = x \<Longrightarrow> x \<le> 1"
proof -
  assume A1: "c_sum x = x"
  have S1: "sf(c_sum x) + c_fst x = x" by (rule sf_c_sum_plus_c_fst)
  from A1 S1 have S2: "sf x + c_fst x = x" by simp
  have S3: "x \<le> sf x" by (rule arg_le_sf)
  from S2 S3 have "sf(x)=x" by simp
  thus ?thesis by (rule sf_eq_arg)
qed

lemma c_sum_eq_arg_2: "c_sum x = x \<Longrightarrow> c_fst x = 0"
proof -
  assume A1: "c_sum x = x"
  have S1: "sf(c_sum x) + c_fst x = x" by (rule sf_c_sum_plus_c_fst)
  from A1 S1 have S2: "sf x + c_fst x = x" by simp
  have S3: "x \<le> sf x" by (rule arg_le_sf)
  from S2 S3 show ?thesis by simp
qed

lemma c_fst_eq_arg: "c_fst x = x \<Longrightarrow> x = 0"
proof -
  assume A1: "c_fst x = x"
  have S1: "c_fst x \<le> c_sum x" by (rule c_fst_le_c_sum)
  have S2: "c_sum x \<le> x" by (rule c_sum_le_arg)
  from A1 S1 S2 have "c_sum x = x" by simp
  then have "c_fst x = 0" by (rule c_sum_eq_arg_2)
  with A1 show ?thesis by simp
qed

lemma c_snd_eq_arg: "c_snd x = x \<Longrightarrow> x \<le> 1"
proof -
  assume A1: "c_snd x = x"
  have S1: "c_snd x \<le> c_sum x" by (rule c_snd_le_c_sum)
  have S2: "c_sum x \<le> x" by (rule c_sum_le_arg)
  from A1 S1 S2 have "c_sum x = x" by simp
  then show ?thesis by (rule c_sum_eq_arg)
qed

end


(*<*)theory AB imports Main begin(*>*)

section{*Case Study: A Context Free Grammar*}

text{*\label{sec:CFG}
\index{grammars!defining inductively|(}%
Grammars are nothing but shorthands for inductive definitions of nonterminals
which represent sets of strings. For example, the production
$A \to B c$ is short for
\[ w \in B \Longrightarrow wc \in A \]
This section demonstrates this idea with an example
due to Hopcroft and Ullman, a grammar for generating all words with an
equal number of $a$'s and~$b$'s:
\begin{eqnarray}
S &\to& \epsilon \mid b A \mid a B \nonumber\\
A &\to& a S \mid b A A \nonumber\\
B &\to& b S \mid a B B \nonumber
\end{eqnarray}
At the end we say a few words about the relationship between
the original proof @{cite \<open>p.\ts81\<close> HopcroftUllman} and our formal version.

We start by fixing the alphabet, which consists only of @{term a}'s
and~@{term b}'s:
*}

datatype alfa = a | b

text{*\noindent
For convenience we include the following easy lemmas as simplification rules:
*}

text{*\noindent
Words over this alphabet are of type @{typ"alfa list"}, and
the three nonterminals are declared as sets of such words.
The productions above are recast as a \emph{mutual} inductive
definition\index{inductive definition!simultaneous}
of @{term S}, @{term A} and~@{term B}:
*}

inductive_set
  S :: "alfa list set" and
  A :: "alfa list set" and
  B :: "alfa list set"
where
  "[] \<in> S"
| "w \<in> A \<Longrightarrow> b#w \<in> S"
| "w \<in> B \<Longrightarrow> a#w \<in> S"

| "w \<in> S        \<Longrightarrow> a#w   \<in> A"
| "\<lbrakk> v\<in>A; w\<in>A \<rbrakk> \<Longrightarrow> b#v@w \<in> A"

| "w \<in> S            \<Longrightarrow> b#w   \<in> B"
| "\<lbrakk> v \<in> B; w \<in> B \<rbrakk> \<Longrightarrow> a#v@w \<in> B"

text{*\noindent
First we show that all words in @{term S} contain the same number of @{term
a}'s and @{term b}'s. Since the definition of @{term S} is by mutual
induction, so is the proof: we show at the same time that all words in
@{term A} contain one more @{term a} than @{term b} and all words in @{term
B} contain one more @{term b} than @{term a}.
*}

lemma correctness:
  "(w \<in> S \<longrightarrow> size[x\<leftarrow>w. x=a] = size[x\<leftarrow>w. x=b])     \<and>
   (w \<in> A \<longrightarrow> size[x\<leftarrow>w. x=a] = size[x\<leftarrow>w. x=b] + 1) \<and>
   (w \<in> B \<longrightarrow> size[x\<leftarrow>w. x=b] = size[x\<leftarrow>w. x=a] + 1)"

txt{*\noindent
These propositions are expressed with the help of the predefined @{term
filter} function on lists, which has the convenient syntax @{text"[x\<leftarrow>xs. P
x]"}, the list of all elements @{term x} in @{term xs} such that @{prop"P x"}
holds. Remember that on lists @{text size} and @{text length} are synonymous.

The proof itself is by rule induction and afterwards automatic:
*}

by (rule S_A_B.induct, auto)

text{*\noindent
This may seem surprising at first, and is indeed an indication of the power
of inductive definitions. But it is also quite straightforward. For example,
consider the production $A \to b A A$: if $v,w \in A$ and the elements of $A$
contain one more $a$ than~$b$'s, then $bvw$ must again contain one more $a$
than~$b$'s.

As usual, the correctness of syntactic descriptions is easy, but completeness
is hard: does @{term S} contain \emph{all} words with an equal number of
@{term a}'s and @{term b}'s? It turns out that this proof requires the
following lemma: every string with two more @{term a}'s than @{term
b}'s can be cut somewhere such that each half has one more @{term a} than
@{term b}. This is best seen by imagining counting the difference between the
number of @{term a}'s and @{term b}'s starting at the left end of the
word. We start with 0 and end (at the right end) with 2. Since each move to the
right increases or decreases the difference by 1, we must have passed through
1 on our way from 0 to 2. Formally, we appeal to the following discrete
intermediate value theorem @{thm[source]nat0_intermed_int_val}
@{thm[display,margin=60]nat0_intermed_int_val[no_vars]}
where @{term f} is of type @{typ"nat \<Rightarrow> int"}, @{typ int} are the integers,
@{text"\<bar>.\<bar>"} is the absolute value function\footnote{See
Table~\ref{tab:ascii} in the Appendix for the correct \textsc{ascii}
syntax.}, and @{term"1::int"} is the integer 1 (see \S\ref{sec:numbers}).

First we show that our specific function, the difference between the
numbers of @{term a}'s and @{term b}'s, does indeed only change by 1 in every
move to the right. At this point we also start generalizing from @{term a}'s
and @{term b}'s to an arbitrary property @{term P}. Otherwise we would have
to prove the desired lemma twice, once as stated above and once with the
roles of @{term a}'s and @{term b}'s interchanged.
*}

lemma step1: "\<forall>i < size w.
  \<bar>(int(size[x\<leftarrow>take (i+1) w. P x])-int(size[x\<leftarrow>take (i+1) w. \<not>P x]))
   - (int(size[x\<leftarrow>take i w. P x])-int(size[x\<leftarrow>take i w. \<not>P x]))\<bar> \<le> 1"

txt{*\noindent
The lemma is a bit hard to read because of the coercion function
@{text"int :: nat \<Rightarrow> int"}. It is required because @{term size} returns
a natural number, but subtraction on type~@{typ nat} will do the wrong thing.
Function @{term take} is predefined and @{term"take i xs"} is the prefix of
length @{term i} of @{term xs}; below we also need @{term"drop i xs"}, which
is what remains after that prefix has been dropped from @{term xs}.

The proof is by induction on @{term w}, with a trivial base case, and a not
so trivial induction step. Since it is essentially just arithmetic, we do not
discuss it.
*}

apply(induct_tac w)
apply(auto simp add: abs_if take_Cons split: nat.split)
done

text{*
Finally we come to the above-mentioned lemma about cutting in half a word with two more elements of one sort than of the other sort:
*}

lemma part1:
 "size[x\<leftarrow>w. P x] = size[x\<leftarrow>w. \<not>P x]+2 \<Longrightarrow>
  \<exists>i\<le>size w. size[x\<leftarrow>take i w. P x] = size[x\<leftarrow>take i w. \<not>P x]+1"

txt{*\noindent
This is proved by @{text force} with the help of the intermediate value theorem,
instantiated appropriately and with its first premise disposed of by lemma
@{thm[source]step1}:
*}

apply(insert nat0_intermed_int_val[OF step1, of "P" "w" "1"])
by force

text{*\noindent

Lemma @{thm[source]part1} tells us only about the prefix @{term"take i w"}.
An easy lemma deals with the suffix @{term"drop i w"}:
*}

lemma part2:
  "\<lbrakk>size[x\<leftarrow>take i w @ drop i w. P x] =
    size[x\<leftarrow>take i w @ drop i w. \<not>P x]+2;
    size[x\<leftarrow>take i w. P x] = size[x\<leftarrow>take i w. \<not>P x]+1\<rbrakk>
   \<Longrightarrow> size[x\<leftarrow>drop i w. P x] = size[x\<leftarrow>drop i w. \<not>P x]+1"
by(simp del: append_take_drop_id)

text{*\noindent
In the proof we have disabled the normally useful lemma
\begin{isabelle}
@{thm append_take_drop_id[no_vars]}
\rulename{append_take_drop_id}
\end{isabelle}
to allow the simplifier to apply the following lemma instead:
@{text[display]"[x\<in>xs@ys. P x] = [x\<in>xs. P x] @ [x\<in>ys. P x]"}

To dispose of trivial cases automatically, the rules of the inductive
definition are declared simplification rules:
*}

declare S_A_B.intros[simp]

text{*\noindent
This could have been done earlier but was not necessary so far.

The completeness theorem tells us that if a word has the same number of
@{term a}'s and @{term b}'s, then it is in @{term S}, and similarly
for @{term A} and @{term B}:
*}

theorem completeness:
  "(size[x\<leftarrow>w. x=a] = size[x\<leftarrow>w. x=b]     \<longrightarrow> w \<in> S) \<and>
   (size[x\<leftarrow>w. x=a] = size[x\<leftarrow>w. x=b] + 1 \<longrightarrow> w \<in> A) \<and>
   (size[x\<leftarrow>w. x=b] = size[x\<leftarrow>w. x=a] + 1 \<longrightarrow> w \<in> B)"

txt{*\noindent
The proof is by induction on @{term w}. Structural induction would fail here
because, as we can see from the grammar, we need to make bigger steps than
merely appending a single letter at the front. Hence we induct on the length
of @{term w}, using the induction rule @{thm[source]length_induct}:
*}

apply(induct_tac w rule: length_induct)
apply(rename_tac w)

txt{*\noindent
The @{text rule} parameter tells @{text induct_tac} explicitly which induction
rule to use. For details see \S\ref{sec:complete-ind} below.
In this case the result is that we may assume the lemma already
holds for all words shorter than @{term w}. Because the induction step renames
the induction variable we rename it back to @{text w}.

The proof continues with a case distinction on @{term w},
on whether @{term w} is empty or not.
*}

apply(case_tac w)
 apply(simp_all)
(*<*)apply(rename_tac x v)(*>*)

txt{*\noindent
Simplification disposes of the base case and leaves only a conjunction
of two step cases to be proved:
if @{prop"w = a#v"} and @{prop[display]"size[x\<in>v. x=a] = size[x\<in>v. x=b]+2"} then
@{prop"b#v \<in> A"}, and similarly for @{prop"w = b#v"}.
We only consider the first case in detail.

After breaking the conjunction up into two cases, we can apply
@{thm[source]part1} to the assumption that @{term w} contains two more @{term
a}'s than @{term b}'s.
*}

apply(rule conjI)
 apply(clarify)
 apply(frule part1[of "\<lambda>x. x=a", simplified])
 apply(clarify)
txt{*\noindent
This yields an index @{prop"i \<le> length v"} such that
@{prop[display]"length [x\<leftarrow>take i v . x = a] = length [x\<leftarrow>take i v . x = b] + 1"}
With the help of @{thm[source]part2} it follows that
@{prop[display]"length [x\<leftarrow>drop i v . x = a] = length [x\<leftarrow>drop i v . x = b] + 1"}
*}

 apply(drule part2[of "\<lambda>x. x=a", simplified])
  apply(assumption)

txt{*\noindent
Now it is time to decompose @{term v} in the conclusion @{prop"b#v \<in> A"}
into @{term"take i v @ drop i v"},
*}

 apply(rule_tac n1=i and t=v in subst[OF append_take_drop_id])

txt{*\noindent
(the variables @{term n1} and @{term t} are the result of composing the
theorems @{thm[source]subst} and @{thm[source]append_take_drop_id})
after which the appropriate rule of the grammar reduces the goal
to the two subgoals @{prop"take i v \<in> A"} and @{prop"drop i v \<in> A"}:
*}

 apply(rule S_A_B.intros)

txt{*
Both subgoals follow from the induction hypothesis because both @{term"take i
v"} and @{term"drop i v"} are shorter than @{term w}:
*}

  apply(force simp add: min_less_iff_disj)
 apply(force split: nat_diff_split)

txt{*
The case @{prop"w = b#v"} is proved analogously:
*}

apply(clarify)
apply(frule part1[of "\<lambda>x. x=b", simplified])
apply(clarify)
apply(drule part2[of "\<lambda>x. x=b", simplified])
 apply(assumption)
apply(rule_tac n1=i and t=v in subst[OF append_take_drop_id])
apply(rule S_A_B.intros)
 apply(force simp add: min_less_iff_disj)
by(force simp add: min_less_iff_disj split: nat_diff_split)

text{*
We conclude this section with a comparison of our proof with
Hopcroft\index{Hopcroft, J. E.} and Ullman's\index{Ullman, J. D.}
@{cite \<open>p.\ts81\<close> HopcroftUllman}.
For a start, the textbook
grammar, for no good reason, excludes the empty word, thus complicating
matters just a little bit: they have 8 instead of our 7 productions.

More importantly, the proof itself is different: rather than
separating the two directions, they perform one induction on the
length of a word. This deprives them of the beauty of rule induction,
and in the easy direction (correctness) their reasoning is more
detailed than our @{text auto}. For the hard part (completeness), they
consider just one of the cases that our @{text simp_all} disposes of
automatically. Then they conclude the proof by saying about the
remaining cases: ``We do this in a manner similar to our method of
proof for part (1); this part is left to the reader''. But this is
precisely the part that requires the intermediate value theorem and
thus is not at all similar to the other cases (which are automatic in
Isabelle). The authors are at least cavalier about this point and may
even have overlooked the slight difficulty lurking in the omitted
cases.  Such errors are found in many pen-and-paper proofs when they
are scrutinized formally.%
\index{grammars!defining inductively|)}
*}

(*<*)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_sort_nat_MSortTDSorts
  imports "../../Test_Base"
begin

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

datatype Nat = Z | S "Nat"

fun plus :: "Nat => Nat => Nat" where
  "plus (Z) y = y"
| "plus (S z) y = S (plus z y)"

fun minus :: "Nat => Nat => Nat" where
  "minus (Z) y = Z"
| "minus (S z) (S y2) = minus z y2"

fun lt :: "Nat => Nat => bool" where
  "lt x (Z) = False"
| "lt (Z) (S z) = True"
| "lt (S n) (S z) = lt n z"

fun length :: "'a list => Nat" where
  "length (nil2) = Z"
| "length (cons2 y l) = plus (S Z) (length l)"

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

fun lmerge :: "Nat list => Nat list => Nat list" where
  "lmerge (nil2) y = y"
| "lmerge (cons2 z x2) (nil2) = cons2 z x2"
| "lmerge (cons2 z x2) (cons2 x3 x4) =
     (if le z x3 then cons2 z (lmerge x2 (cons2 x3 x4)) else
        cons2 x3 (lmerge (cons2 z x2) x4))"

fun ordered :: "Nat list => bool" where
  "ordered (nil2) = True"
| "ordered (cons2 y (nil2)) = True"
| "ordered (cons2 y (cons2 y2 xs)) =
     ((le y y2) & (ordered (cons2 y2 xs)))"

fun take :: "Nat => 'a list => 'a list" where
  "take x y =
   (if le x Z then nil2 else
      (case y of
         nil2 => nil2
         | cons2 z xs => (case x of S x2 => cons2 z (take x2 xs))))"

(*fun did not finish the proof*)
function idiv :: "Nat => Nat => Nat" where
  "idiv x y = (if lt x y then Z else S (idiv (minus x y) y))"
  by pat_completeness auto

fun drop :: "Nat => 'a list => 'a list" where
  "drop x y =
   (if le x Z then y else
      (case y of
         nil2 => nil2
         | cons2 z xs1 => (case x of S x2 => drop x2 xs1)))"

(*fun did not finish the proof*)
function msorttd :: "Nat list => Nat list" where
  "msorttd (nil2) = nil2"
| "msorttd (cons2 y (nil2)) = cons2 y (nil2)"
| "msorttd (cons2 y (cons2 x2 x3)) =
     (let k :: Nat = idiv (length (cons2 y (cons2 x2 x3))) (S (S Z))
     in lmerge
          (msorttd (take k (cons2 y (cons2 x2 x3))))
          (msorttd (drop k (cons2 y (cons2 x2 x3)))))"
  by pat_completeness auto

theorem property0 :
  "ordered (msorttd xs)"
  oops

end