diff --git a/thys/Gromov_Hyperbolicity/Library_Complements.thy b/thys/Gromov_Hyperbolicity/Library_Complements.thy --- a/thys/Gromov_Hyperbolicity/Library_Complements.thy +++ b/thys/Gromov_Hyperbolicity/Library_Complements.thy @@ -1,1760 +1,1684 @@ (* Author: Sébastien Gouëzel sebastien.gouezel@univ-rennes1.fr License: BSD *) section \Additions to the library\ theory Library_Complements imports "HOL-Analysis.Analysis" "HOL-Cardinals.Cardinal_Order_Relation" begin subsection \Mono intros\ text \We have a lot of (large) inequalities to prove. It is very convenient to have a set of introduction rules for this purpose (a lot should be added to it, I have put here all the ones I needed). The typical use case is when one wants to prove some inequality, say $ \exp (x*x) \leq y + \exp(1 + z * z + y)$, assuming $y \geq 0$ and $0 \leq x \leq z$. One would write it has \begin{verbatim} have "0 + \exp(0 + x * x + 0) < = y + \exp(1 + z * z + y)" using `y > = 0` `x < = z` by (intro mono_intros) \end{verbatim} When the left and right hand terms are written in completely analogous ways as above, then the introduction rules (that contain monotonicity of addition, of the exponential, and so on) reduce this to comparison of elementary terms in the formula. This is a very naive strategy, that fails in many situations, but that is very efficient when used correctly. \ named_theorems mono_intros "structural introduction rules to prove inequalities" declare le_imp_neg_le [mono_intros] declare add_left_mono [mono_intros] declare add_right_mono [mono_intros] declare add_strict_left_mono [mono_intros] declare add_strict_right_mono [mono_intros] declare add_mono [mono_intros] declare add_less_le_mono [mono_intros] declare diff_right_mono [mono_intros] declare diff_left_mono [mono_intros] declare diff_mono [mono_intros] declare mult_left_mono [mono_intros] declare mult_right_mono [mono_intros] declare mult_mono [mono_intros] declare max.mono [mono_intros] declare min.mono [mono_intros] declare power_mono [mono_intros] declare ln_ge_zero [mono_intros] declare ln_le_minus_one [mono_intros] declare ennreal_minus_mono [mono_intros] declare ennreal_leI [mono_intros] declare e2ennreal_mono [mono_intros] declare enn2ereal_nonneg [mono_intros] declare zero_le [mono_intros] declare top_greatest [mono_intros] declare bot_least [mono_intros] declare dist_triangle [mono_intros] declare dist_triangle2 [mono_intros] declare dist_triangle3 [mono_intros] declare exp_ge_add_one_self [mono_intros] declare exp_gt_one [mono_intros] declare exp_less_mono [mono_intros] declare dist_triangle [mono_intros] declare abs_triangle_ineq [mono_intros] declare abs_triangle_ineq2 [mono_intros] declare abs_triangle_ineq2_sym [mono_intros] declare abs_triangle_ineq3 [mono_intros] declare abs_triangle_ineq4 [mono_intros] declare Liminf_le_Limsup [mono_intros] declare ereal_liminf_add_mono [mono_intros] declare le_of_int_ceiling [mono_intros] declare ereal_minus_mono [mono_intros] declare infdist_triangle [mono_intros] declare divide_right_mono [mono_intros] declare self_le_power [mono_intros] lemma ln_le_cancelI [mono_intros]: assumes "(0::real) < x" "x \ y" shows "ln x \ ln y" using assms by auto lemma exp_le_cancelI [mono_intros]: assumes "x \ (y::real)" shows "exp x \ exp y" using assms by simp lemma mult_ge1_mono [mono_intros]: assumes "a \ (0::'a::linordered_idom)" "b \ 1" shows "a \ a * b" "a \ b * a" using assms mult_le_cancel_left1 mult_le_cancel_right1 by force+ text \A few convexity inequalities we will need later on.\ lemma xy_le_uxx_vyy [mono_intros]: assumes "u > 0" "u * v = (1::real)" shows "x * y \ u * x^2/2 + v * y^2/2" proof - have "v > 0" using assms by (metis (full_types) dual_order.strict_implies_order le_less_linear mult_nonneg_nonpos not_one_le_zero) then have *: "sqrt u * sqrt v = 1" using assms by (metis real_sqrt_mult real_sqrt_one) have "(sqrt u * x - sqrt v * y)^2 \ 0" by auto then have "u * x^2 + v * y^2 - 2 * 1 * x * y \ 0" unfolding power2_eq_square *[symmetric] using \u > 0\ \v > 0\ by (auto simp add: algebra_simps) then show ?thesis by (auto simp add: algebra_simps divide_simps) qed lemma xy_le_xx_yy [mono_intros]: "x * y \ x^2/2 + y^2/2" for x y::real using xy_le_uxx_vyy[of 1 1] by auto lemma ln_squared_bound [mono_intros]: "(ln x)^2 \ 2 * x - 2" if "x \ 1" for x::real proof - define f where "f = (\x::real. 2 * x - 2 - ln x * ln x)" have *: "DERIV f x :> 2 - 2 * ln x / x" if "x > 0" for x::real unfolding f_def using that by (auto intro!: derivative_eq_intros) have "f 1 \ f x" if "x \ 1" for x proof (rule DERIV_nonneg_imp_nondecreasing[OF that]) fix t::real assume "t \ 1" show "\y. (f has_real_derivative y) (at t) \ 0 \ y" apply (rule exI[of _ "2 - 2 * ln t / t"]) using *[of t] \t \ 1\ by (auto simp add: divide_simps ln_bound) qed then show ?thesis unfolding f_def power2_eq_square using that by auto qed text \In the next lemma, the assumptions are too strong (negative numbers less than $-1$ also work well to have a square larger than $1$), but in practice one proves inequalities with nonnegative numbers, so this version is really the useful one for \verb+mono_intros+.\ lemma mult_ge1_powers [mono_intros]: assumes "a \ (1::'a::linordered_idom)" shows "1 \ a * a" "1 \ a * a * a" "1 \ a * a * a * a" using assms by (meson assms dual_order.trans mult_ge1_mono(1) zero_le_one)+ lemmas [mono_intros] = ln_bound lemma mono_cSup: fixes f :: "'a::conditionally_complete_lattice \ 'b::conditionally_complete_lattice" assumes "bdd_above A" "A \ {}" "mono f" shows "Sup (f`A) \ f (Sup A)" by (metis assms(1) assms(2) assms(3) cSUP_least cSup_upper mono_def) lemma mono_cSup_bij: fixes f :: "'a::conditionally_complete_linorder \ 'b::conditionally_complete_linorder" assumes "bdd_above A" "A \ {}" "mono f" "bij f" shows "Sup (f`A) = f(Sup A)" proof - have "Sup ((inv f)`(f`A)) \ (inv f) (Sup (f`A))" apply (rule mono_cSup) using mono_inv[OF assms(3) assms(4)] assms(2) bdd_above_image_mono[OF assms(3) assms(1)] by auto then have "f (Sup ((inv f)`(f`A))) \ Sup (f`A)" using assms mono_def by (metis (no_types, hide_lams) bij_betw_imp_surj_on surj_f_inv_f) moreover have "f (Sup ((inv f)`(f`A))) = f(Sup A)" using assms by (simp add: bij_is_inj) ultimately show ?thesis using mono_cSup[OF assms(1) assms(2) assms(3)] by auto qed subsection \More topology\ text \In situations of interest to us later on, convergence is well controlled only for sequences living in some dense subset of the space (but the limit can be anywhere). This is enough to establish continuity of the function, if the target space is well enough separated. The statement we give below is very general, as we do not assume that the function is continuous inside the original set $S$, it will typically only be continuous at a set $T$ contained in the closure of $S$. In many applications, $T$ will be the closure of $S$, but we are also thinking of the case where one constructs an extension of a function inside a space, to its boundary, and the behaviour at the boundary is better than inside the space. The example we have in mind is the extension of a quasi-isometry to the boundary of a Gromov hyperbolic space. In the following criterion, we assume that if $u_n$ inside $S$ converges to a point at the boundary $T$, then $f(u_n)$ converges (where $f$ is some function inside). Then, we can extend the function $f$ at the boundary, by picking the limit value of $f(u_n)$ for some sequence converging to $u_n$. Then the lemma asserts that $f$ is continuous at every point $b$ on the boundary. The proof is done in two steps: \begin{enumerate} \item First, if $v_n$ is another inside sequence tending to the same point $b$ on the boundary, then $f(v_n)$ converges to the same value as $f(u_n)$: this is proved by considering the sequence $w$ equal to $u$ at even times and to $v$ at odd times, and saying that $f(w_n)$ converges. Its limit is equal to the limit of $f(u_n)$ and of $f(v_n)$, so they have to coincide. \item Now, consider a general sequence $v$ (in the space or the boundary) converging to $b$. We want to show that $f(v_n)$ tends to $f(b)$. If $v_n$ is inside $S$, we have already done it in the first step. If it is on the boundary, on the other hand, we can approximate it by an inside point $w_n$ for which $f(w_n)$ is very close to $f(v_n)$. Then $w_n$ is an inside sequence converging to $b$, hence $f(w_n)$ converges to $f(b)$ by the first step, and then $f(v_n)$ also converges to $f(b)$. The precise argument is more conveniently written by contradiction. It requires good separation properties of the target space. \end{enumerate}\ text \First, we introduce the material to interpolate between two sequences, one at even times and the other one at odd times.\ definition even_odd_interpolate::"(nat \ 'a) \ (nat \ 'a) \ (nat \ 'a)" where "even_odd_interpolate u v n = (if even n then u (n div 2) else v (n div 2))" lemma even_odd_interpolate_compose: "even_odd_interpolate (f o u) (f o v) = f o (even_odd_interpolate u v)" unfolding even_odd_interpolate_def comp_def by auto lemma even_odd_interpolate_filterlim: "filterlim u F sequentially \ filterlim v F sequentially \ filterlim (even_odd_interpolate u v) F sequentially" proof (auto) assume H: "filterlim (even_odd_interpolate u v) F sequentially" define r::"nat \ nat" where "r = (\n. 2 * n)" have "strict_mono r" unfolding r_def strict_mono_def by auto then have "filterlim r sequentially sequentially" by (simp add: filterlim_subseq) have "filterlim (\n. (even_odd_interpolate u v) (r n)) F sequentially" by (rule filterlim_compose[OF H filterlim_subseq[OF \strict_mono r\]]) moreover have "even_odd_interpolate u v (r n) = u n" for n unfolding r_def even_odd_interpolate_def by auto ultimately show "filterlim u F sequentially" by auto define r::"nat \ nat" where "r = (\n. 2 * n + 1)" have "strict_mono r" unfolding r_def strict_mono_def by auto then have "filterlim r sequentially sequentially" by (simp add: filterlim_subseq) have "filterlim (\n. (even_odd_interpolate u v) (r n)) F sequentially" by (rule filterlim_compose[OF H filterlim_subseq[OF \strict_mono r\]]) moreover have "even_odd_interpolate u v (r n) = v n" for n unfolding r_def even_odd_interpolate_def by auto ultimately show "filterlim v F sequentially" by auto next assume H: "filterlim u F sequentially" "filterlim v F sequentially" show "filterlim (even_odd_interpolate u v) F sequentially" unfolding filterlim_iff eventually_sequentially proof (auto) fix P assume *: "eventually P F" obtain N1 where N1: "\n. n \ N1 \ P (u n)" using H(1) unfolding filterlim_iff eventually_sequentially using * by auto obtain N2 where N2: "\n. n \ N2 \ P (v n)" using H(2) unfolding filterlim_iff eventually_sequentially using * by auto have "P (even_odd_interpolate u v n)" if "n \ 2 * N1 + 2 * N2" for n proof (cases "even n") case True have "n div 2 \ N1" using that by auto then show ?thesis unfolding even_odd_interpolate_def using True N1 by auto next case False have "n div 2 \ N2" using that by auto then show ?thesis unfolding even_odd_interpolate_def using False N2 by auto qed then show "\N. \n \ N. P (even_odd_interpolate u v n)" by auto qed qed text \Then, we prove the continuity criterion for extensions of functions to the boundary $T$ of a set $S$. The first assumption is that $f(u_n)$ converges when $f$ converges to the boundary, and the second one that the extension of $f$ to the boundary has been defined using the limit along some sequence tending to the point under consideration. The following criterion is the most general one, but this is not the version that is most commonly applied so we use a prime in its name.\ lemma continuous_at_extension_sequentially': fixes f :: "'a::{first_countable_topology, t2_space} \ 'b::t3_space" assumes "b \ T" "\u b. (\n. u n \ S) \ b \ T \ u \ b \ convergent (\n. f (u n))" "\b. b \ T \ \u. (\n. u n \ S) \ u \ b \ ((\n. f (u n)) \ f b)" shows "continuous (at b within (S \ T)) f" proof - have first_step: "(\n. f (u n)) \ f c" if "\n. u n \ S" "u \ c" "c \ T" for u c proof - obtain v where v: "\n. v n \ S" "v \ c" "(\n. f (v n)) \ f c" using assms(3)[OF \c \ T\] by blast then have A: "even_odd_interpolate u v \ c" unfolding even_odd_interpolate_filterlim[symmetric] using \u \ c\ by auto moreover have B: "\n. even_odd_interpolate u v n \ S" using \\n. u n \ S\ \\n. v n \ S\ unfolding even_odd_interpolate_def by auto have "convergent (\n. f (even_odd_interpolate u v n))" by (rule assms(2)[OF B \c \ T\ A]) then obtain m where "(\n. f (even_odd_interpolate u v n)) \ m" unfolding convergent_def by auto then have "even_odd_interpolate (f o u) (f o v) \ m" unfolding even_odd_interpolate_compose unfolding comp_def by auto then have "(f o u) \ m" "(f o v) \ m" unfolding even_odd_interpolate_filterlim[symmetric] by auto then have "m = f c" using v(3) unfolding comp_def using LIMSEQ_unique by auto then show ?thesis using \(f o u) \ m\ unfolding comp_def by auto qed show "continuous (at b within (S \ T)) f" proof (rule ccontr) assume "\ ?thesis" then obtain U where U: "open U" "f b \ U" "\(\\<^sub>F x in at b within S \ T. f x \ U)" unfolding continuous_within tendsto_def[where l = "f b"] using sequentially_imp_eventually_nhds_within by auto have "\V W. open V \ open W \ f b \ V \ (UNIV - U) \ W \ V \ W = {}" apply (rule t3_space) using U by auto then obtain V W where VW: "open V" "open W" "f b \ V" "UNIV - U \ W" "V \ W = {}" by auto obtain A :: "nat \ 'a set" where *: "\i. open (A i)" "\i. b \ A i" "\F. \n. F n \ A n \ F \ b" by (rule first_countable_topology_class.countable_basis) blast with * U(3) have "\F. \n. F n \ S \ T \ F n \ A n \ \ (f(F n) \ U)" unfolding at_within_def eventually_inf_principal eventually_nhds by (intro choice) (meson DiffE) then obtain F where F: "\n. F n \ S \ T" "\n. F n \ A n" "\n. f(F n) \ U" by auto have "\y. y \ S \ y \ A n \ f y \ W" for n proof (cases "F n \ S") case True show ?thesis apply (rule exI[of _ "F n"]) using F VW True by auto next case False then have "F n \ T" using \F n \ S \ T\ by auto obtain u where u: "\p. u p \ S" "u \ F n" "(\p. f (u p)) \ f(F n)" using assms(3)[OF \F n \ T\] by auto moreover have "f(F n) \ W" using F VW by auto ultimately have "eventually (\p. f (u p) \ W) sequentially" using \open W\ by (simp add: tendsto_def) moreover have "eventually (\p. u p \ A n) sequentially" using \F n \ A n\ u \open (A n)\ by (simp add: tendsto_def) ultimately have "\p. f(u p) \ W \ u p \ A n" using eventually_False_sequentially eventually_elim2 by blast then show ?thesis using u(1) by auto qed then have "\u. \n. u n \ S \ u n \ A n \ f (u n) \ W" by (auto intro: choice) then obtain u where u: "\n. u n \ S" "\n. u n \ A n" "\n. f (u n) \ W" by blast then have "u \ b" using *(3) by auto then have "(\n. f (u n)) \ f b" using first_step assms u by auto then have "eventually (\n. f (u n) \ V) sequentially" using VW by (simp add: tendsto_def) then have "\n. f (u n) \ V" using eventually_False_sequentially eventually_elim2 by blast then show False using u(3) \V \ W = {}\ by auto qed qed text \We can specialize the previous statement to the common case where one already knows the sequential continuity of $f$ along sequences in $S$ converging to a point in $T$. This will be the case in most --but not all-- applications. This is a straightforward application of the above criterion.\ proposition continuous_at_extension_sequentially: fixes f :: "'a::{first_countable_topology, t2_space} \ 'b::t3_space" assumes "a \ T" "T \ closure S" "\u b. (\n. u n \ S) \ b \ T \ u \ b \ (\n. f (u n)) \ f b" shows "continuous (at a within (S \ T)) f" apply (rule continuous_at_extension_sequentially'[OF \a \ T\]) using assms(3) convergent_def apply blast by (metis assms(2) assms(3) closure_sequential subset_iff) text \We also give global versions. We can only express the continuity on $T$, so this is slightly weaker than the previous statements since we are not saying anything on inside sequences tending to $T$ -- but in cases where $T$ contains $S$ these statements contain all the information.\ lemma continuous_on_extension_sequentially': fixes f :: "'a::{first_countable_topology, t2_space} \ 'b::t3_space" assumes "\u b. (\n. u n \ S) \ b \ T \ u \ b \ convergent (\n. f (u n))" "\b. b \ T \ \u. (\n. u n \ S) \ u \ b \ ((\n. f (u n)) \ f b)" shows "continuous_on T f" unfolding continuous_on_eq_continuous_within apply (auto intro!: continuous_within_subset[of _ "S \ T" f T]) by (intro continuous_at_extension_sequentially'[OF _ assms], auto) lemma continuous_on_extension_sequentially: fixes f :: "'a::{first_countable_topology, t2_space} \ 'b::t3_space" assumes "T \ closure S" "\u b. (\n. u n \ S) \ b \ T \ u \ b \ (\n. f (u n)) \ f b" shows "continuous_on T f" unfolding continuous_on_eq_continuous_within apply (auto intro!: continuous_within_subset[of _ "S \ T" f T]) by (intro continuous_at_extension_sequentially[OF _ assms], auto) subsubsection \Homeomorphisms\ -lemma homeomorphism_cong: - "homeomorphism X' Y' f' g'" if "homeomorphism X Y f g" - "X' = X" "Y' = Y" "\x. x \ X \ f' x = f x" "\y. y \ Y \ g' y = g y" - using that by (auto simp add: homeomorphism_def) - -lemma homeomorphism_empty [simp]: - "homeomorphism {} {} f g" -unfolding homeomorphism_def by auto - text \A variant around the notion of homeomorphism, which is only expressed in terms of the function and not of its inverse.\ definition homeomorphism_on::"'a set \ ('a::topological_space \ 'b::topological_space) \ bool" where "homeomorphism_on S f = (\g. homeomorphism S (f`S) f g)" lemma homeomorphism_on_continuous: assumes "homeomorphism_on S f" shows "continuous_on S f" using assms unfolding homeomorphism_on_def homeomorphism_def by auto lemma homeomorphism_on_bij: assumes "homeomorphism_on S f" shows "bij_betw f S (f`S)" using assms unfolding homeomorphism_on_def homeomorphism_def by auto (metis inj_on_def inj_on_imp_bij_betw) lemma homeomorphism_on_homeomorphic: assumes "homeomorphism_on S f" shows "S homeomorphic (f`S)" using assms unfolding homeomorphism_on_def homeomorphic_def by auto lemma homeomorphism_on_compact: fixes f::"'a::topological_space \ 'b::t2_space" assumes "continuous_on S f" "compact S" "inj_on f S" shows "homeomorphism_on S f" unfolding homeomorphism_on_def using homeomorphism_compact[OF assms(2) assms(1) _ assms(3)] by auto lemma homeomorphism_on_subset: assumes "homeomorphism_on S f" "T \ S" shows "homeomorphism_on T f" using assms homeomorphism_of_subsets unfolding homeomorphism_on_def by blast lemma homeomorphism_on_empty [simp]: "homeomorphism_on {} f" unfolding homeomorphism_on_def using homeomorphism_empty[of f] by auto lemma homeomorphism_on_cong: assumes "homeomorphism_on X f" "X' = X" "\x. x \ X \ f' x = f x" shows "homeomorphism_on X' f'" proof - obtain g where g:"homeomorphism X (f`X) f g" using assms unfolding homeomorphism_on_def by auto have "homeomorphism X' (f'`X') f' g" apply (rule homeomorphism_cong[OF g]) using assms by (auto simp add: rev_image_eqI) then show ?thesis unfolding homeomorphism_on_def by auto qed lemma homeomorphism_on_inverse: fixes f::"'a::topological_space \ 'b::topological_space" assumes "homeomorphism_on X f" shows "homeomorphism_on (f`X) (inv_into X f)" proof - obtain g where g: "homeomorphism X (f`X) f g" using assms unfolding homeomorphism_on_def by auto then have "g`f`X = X" by (simp add: homeomorphism_def) then have "homeomorphism_on (f`X) g" unfolding homeomorphism_on_def using homeomorphism_symD[OF g] by auto moreover have "g x = inv_into X f x" if "x \ f`X" for x using g that unfolding homeomorphism_def by (auto, metis f_inv_into_f inv_into_into that) ultimately show ?thesis using homeomorphism_on_cong by force qed text \Characterization of homeomorphisms in terms of sequences: a map is a homeomorphism if and only if it respects convergent sequences.\ lemma homeomorphism_on_compose: assumes "homeomorphism_on S f" "x \ S" "eventually (\n. u n \ S) F" shows "(u \ x) F \ ((\n. f (u n)) \ f x) F" proof assume "(u \ x) F" then show "((\n. f (u n)) \ f x) F" using continuous_on_tendsto_compose[OF homeomorphism_on_continuous[OF assms(1)] _ assms(2) assms(3)] by simp next assume *: "((\n. f (u n)) \ f x) F" have I: "inv_into S f (f y) = y" if "y \ S" for y using homeomorphism_on_bij[OF assms(1)] by (meson bij_betw_inv_into_left that) then have A: "eventually (\n. u n = inv_into S f (f (u n))) F" using assms eventually_mono by force have "((\n. (inv_into S f) (f (u n))) \ (inv_into S f) (f x)) F" apply (rule continuous_on_tendsto_compose[OF homeomorphism_on_continuous[OF homeomorphism_on_inverse[OF assms(1)]] *]) using assms eventually_mono by (auto) fastforce then show "(u \ x) F" unfolding tendsto_cong[OF A] I[OF \x \ S\] by simp qed lemma homeomorphism_on_sequentially: fixes f::"'a::{first_countable_topology, t2_space} \ 'b::{first_countable_topology, t2_space}" assumes "\x u. x \ S \ (\n. u n \ S) \ u \ x \ (\n. f (u n)) \ f x" shows "homeomorphism_on S f" proof - have "x = y" if "f x = f y" "x \ S" "y \ S" for x y proof - have "(\n. f x) \ f y" using that by auto then have "(\n. x) \ y" using assms(1) that by auto then show "x = y" using LIMSEQ_unique by auto qed then have "inj_on f S" by (simp add: inj_on_def) have Cf: "continuous_on S f" apply (rule continuous_on_sequentiallyI) using assms by auto define g where "g = inv_into S f" have Cg: "continuous_on (f`S) g" proof (rule continuous_on_sequentiallyI) fix v b assume H: "\n. v n \ f ` S" "b \ f ` S" "v \ b" define u where "u = (\n. g (v n))" define a where "a = g b" have "u n \ S" "f (u n) = v n" for n unfolding u_def g_def using H(1) by (auto simp add: inv_into_into f_inv_into_f) have "a \ S" "f a = b" unfolding a_def g_def using H(2) by (auto simp add: inv_into_into f_inv_into_f) show "(\n. g(v n)) \ g b" unfolding u_def[symmetric] a_def[symmetric] apply (rule iffD2[OF assms]) using \\n. u n \ S\ \a \ S\ \v \ b\ unfolding \\n. f (u n) = v n\ \f a = b\ by auto qed have "homeomorphism S (f`S) f g" apply (rule homeomorphismI[OF Cf Cg]) unfolding g_def using \inj_on f S\ by auto then show ?thesis unfolding homeomorphism_on_def by auto qed lemma homeomorphism_on_UNIV_sequentially: fixes f::"'a::{first_countable_topology, t2_space} \ 'b::{first_countable_topology, t2_space}" assumes "\x u. u \ x \ (\n. f (u n)) \ f x" shows "homeomorphism_on UNIV f" using assms by (auto intro!: homeomorphism_on_sequentially) text \Now, we give similar characterizations in terms of sequences living in a dense subset. As in the sequential continuity criteria above, we first give a very general criterion, where the map does not have to be continuous on the approximating set $S$, only on the limit set $T$, without any a priori identification of the limit. Then, we specialize this statement to a less general but often more usable version.\ lemma homeomorphism_on_extension_sequentially_precise: fixes f::"'a::{first_countable_topology, t3_space} \ 'b::{first_countable_topology, t3_space}" assumes "\u b. (\n. u n \ S) \ b \ T \ u \ b \ convergent (\n. f (u n))" "\u c. (\n. u n \ S) \ c \ f`T \ (\n. f (u n)) \ c \ convergent u" "\b. b \ T \ \u. (\n. u n \ S) \ u \ b \ ((\n. f (u n)) \ f b)" "\n. u n \ S \ T" "l \ T" shows "u \ l \ (\n. f (u n)) \ f l" proof assume H: "u \ l" have "continuous (at l within (S \ T)) f" apply (rule continuous_at_extension_sequentially'[OF \l \ T\]) using assms(1) assms(3) by auto then show "(\n. f (u n)) \ f l" apply (rule continuous_within_tendsto_compose) using H assms(4) by auto next text \For the reverse implication, we would like to use the continuity criterion \verb+ continuous_at_extension_sequentially'+ applied to the inverse of $f$. Unfortunately, this inverse is only well defined on $T$, while our sequence takes values in $S \cup T$. So, instead, we redo by hand the proof of the continuity criterion, but in the opposite direction.\ assume H: "(\n. f (u n)) \ f l" show "u \ l" proof (rule ccontr) assume "\ ?thesis" then obtain U where U: "open U" "l \ U" "\(\\<^sub>F n in sequentially. u n \ U)" unfolding continuous_within tendsto_def[where l = l] using sequentially_imp_eventually_nhds_within by auto obtain A :: "nat \ 'b set" where *: "\i. open (A i)" "\i. f l \ A i" "\F. \n. F n \ A n \ F \ f l" by (rule first_countable_topology_class.countable_basis) blast have B: "eventually (\n. f (u n) \ A i) sequentially" for i using \open (A i)\ \f l \ A i\ H topological_tendstoD by fastforce have M: "\r. r \ N \ (u r \ U) \ f (u r) \ A i" for N i using U(3) B[of i] unfolding eventually_sequentially by (meson dual_order.trans le_cases) have "\r. \n. (u (r n) \ U \ f (u (r n)) \ A n) \ r (Suc n) \ r n + 1" apply (rule dependent_nat_choice) using M by auto then obtain r where r: "\n. u (r n) \ U" "\n. f (u (r n)) \ A n" "\n. r (Suc n) \ r n + 1" by auto then have "strict_mono r" by (metis Suc_eq_plus1 Suc_le_lessD strict_monoI_Suc) have "\V W. open V \ open W \ l \ V \ (UNIV - U) \ W \ V \ W = {}" apply (rule t3_space) using U by auto then obtain V W where VW: "open V" "open W" "l \ V" "UNIV - U \ W" "V \ W = {}" by auto have "\z. z \ S \ f z \ A n \ z \ W" for n proof - define z where "z = u (r n)" have "f z \ A n" unfolding z_def using r(2) by auto have "z \ S \ T" "z \ U" unfolding z_def using r(1) assms(4) by auto then have "z \ W" using VW by auto show ?thesis proof (cases "z \ T") case True obtain u::"nat \ 'a" where u: "\p. u p \ S" "u \ z" "(\p. f (u p)) \ f z" using assms(3)[OF \z \ T\] by auto then have "eventually (\p. f (u p) \ A n) sequentially" using \open (A n)\ \f z \ A n\ unfolding tendsto_def by simp moreover have "eventually (\p. u p \ W) sequentially" using \open W\ \z \ W\ u unfolding tendsto_def by simp ultimately have "\p. u p \ W \ f (u p) \ A n" using eventually_False_sequentially eventually_elim2 by blast then show ?thesis using u(1) by auto next case False then have "z \ S" using \z \ S \ T\ by auto then show ?thesis using \f z \ A n\ \z \ W\ by auto qed qed then have "\v. \n. v n \ S \ f (v n) \ A n \ v n \ W" by (auto intro: choice) then obtain v where v: "\n. v n \ S" "\n. f (v n) \ A n" "\n. v n \ W" by blast then have I: "(\n. f (v n)) \ f l" using *(3) by auto obtain w where w: "\n. w n \ S" "w \ l" "((\n. f (w n)) \ f l)" using assms(3)[OF \l \ T\] by auto have "even_odd_interpolate (f o v) (f o w) \ f l" unfolding even_odd_interpolate_filterlim[symmetric] comp_def using v w I by auto then have *: "(\n. f (even_odd_interpolate v w n)) \ f l" unfolding even_odd_interpolate_compose unfolding comp_def by auto have "convergent (even_odd_interpolate v w)" apply (rule assms(2)[OF _ _ *]) unfolding even_odd_interpolate_def using v(1) w(1) \l \ T\ by auto then obtain z where "even_odd_interpolate v w \ z" unfolding convergent_def by auto then have *: "v \ z" "w \ z" unfolding even_odd_interpolate_filterlim[symmetric] by auto then have "z = l" using v(2) w(2) LIMSEQ_unique by auto then have "v \ l" using * by simp then have "eventually (\n. v n \ V) sequentially" using VW by (simp add: tendsto_def) then have "\n. v n \ V" using eventually_False_sequentially eventually_elim2 by blast then show False using v(3) \V \ W = {}\ by auto qed qed lemma homeomorphism_on_extension_sequentially': fixes f::"'a::{first_countable_topology, t3_space} \ 'b::{first_countable_topology, t3_space}" assumes "\u b. (\n. u n \ S) \ b \ T \ u \ b \ convergent (\n. f (u n))" "\u c. (\n. u n \ S) \ c \ f`T \ (\n. f (u n)) \ c \ convergent u" "\b. b \ T \ \u. (\n. u n \ S) \ u \ b \ ((\n. f (u n)) \ f b)" shows "homeomorphism_on T f" apply (rule homeomorphism_on_sequentially, rule homeomorphism_on_extension_sequentially_precise[of S T]) using assms by auto proposition homeomorphism_on_extension_sequentially: fixes f::"'a::{first_countable_topology, t3_space} \ 'b::{first_countable_topology, t3_space}" assumes "\u b. (\n. u n \ S) \ u \ b \ (\n. f (u n)) \ f b" "T \ closure S" shows "homeomorphism_on T f" apply (rule homeomorphism_on_extension_sequentially'[of S]) using assms(1) convergent_def apply fastforce using assms(1) convergent_def apply blast by (metis assms(1) assms(2) closure_sequential subsetCE) lemma homeomorphism_on_UNIV_extension_sequentially: fixes f::"'a::{first_countable_topology, t3_space} \ 'b::{first_countable_topology, t3_space}" assumes "\u b. (\n. u n \ S) \ u \ b \ (\n. f (u n)) \ f b" "closure S = UNIV" shows "homeomorphism_on UNIV f" apply (rule homeomorphism_on_extension_sequentially[of S]) using assms by auto subsubsection \Proper spaces\ text \Proper spaces, i.e., spaces in which every closed ball is compact -- or, equivalently, any closed bounded set is compact.\ definition proper::"('a::metric_space) set \ bool" where "proper S \ (\ x r. compact (cball x r \ S))" lemma properI: assumes "\x r. compact (cball x r \ S)" shows "proper S" using assms unfolding proper_def by auto lemma proper_compact_cball: assumes "proper (UNIV::'a::metric_space set)" shows "compact (cball (x::'a) r)" using assms unfolding proper_def by auto lemma proper_compact_bounded_closed: assumes "proper (UNIV::'a::metric_space set)" "closed (S::'a set)" "bounded S" shows "compact S" proof - obtain x r where "S \ cball x r" using \bounded S\ bounded_subset_cball by blast then have *: "S = S \ cball x r" by auto show ?thesis apply (subst *, rule closed_Int_compact) using assms unfolding proper_def by auto qed lemma proper_real [simp]: "proper (UNIV::real set)" unfolding proper_def by auto lemma complete_of_proper: assumes "proper S" shows "complete S" proof - have "\l\S. u \ l" if "Cauchy u" "\n. u n \ S" for u proof - have "bounded (range u)" using \Cauchy u\ cauchy_imp_bounded by auto then obtain x r where *: "\n. dist x (u n) \ r" unfolding bounded_def by auto then have "u n \ (cball x r) \ S" for n using \u n \ S\ by auto moreover have "complete ((cball x r) \ S)" apply (rule compact_imp_complete) using assms unfolding proper_def by auto ultimately show ?thesis unfolding complete_def using \Cauchy u\ by auto qed then show ?thesis unfolding complete_def by auto qed lemma proper_of_compact: assumes "compact S" shows "proper S" using assms by (auto intro: properI) lemma proper_Un: assumes "proper A" "proper B" shows "proper (A \ B)" using assms unfolding proper_def by (auto simp add: compact_Un inf_sup_distrib1) subsubsection \Miscellaneous topology\ text \When manipulating the triangle inequality, it is very frequent to deal with 4 points (and automation has trouble doing it automatically). Even sometimes with 5 points...\ lemma dist_triangle4 [mono_intros]: "dist x t \ dist x y + dist y z + dist z t" using dist_triangle[of x z y] dist_triangle[of x t z] by auto lemma dist_triangle5 [mono_intros]: "dist x u \ dist x y + dist y z + dist z t + dist t u" using dist_triangle4[of x u y z] dist_triangle[of z u t] by auto text \A thickening of a compact set is closed.\ lemma compact_has_closed_thickening: assumes "compact C" "continuous_on C f" shows "closed (\x\C. cball x (f x))" proof (auto simp add: closed_sequential_limits) fix u l assume *: "\n::nat. \x\C. dist x (u n) \ f x" "u \ l" have "\x::nat\'a. \n. x n \ C \ dist (x n) (u n) \ f (x n)" apply (rule choice) using * by auto then obtain x::"nat \ 'a" where x: "\n. x n \ C" "\n. dist (x n) (u n) \ f (x n)" by blast obtain r c where "strict_mono r" "c \ C" "(x o r) \ c" using x(1) \compact C\ by (meson compact_eq_seq_compact_metric seq_compact_def) then have "c \ C" using x(1) \compact C\ by auto have lim: "(\n. f (x (r n)) - dist (x (r n)) (u (r n))) \ f c - dist c l" apply (intro tendsto_intros, rule continuous_on_tendsto_compose[of C f]) using *(2) x(1) \(x o r) \ c\ \continuous_on C f\ \c \ C\ \strict_mono r\ LIMSEQ_subseq_LIMSEQ unfolding comp_def by auto have "f c - dist c l \ 0" apply (rule LIMSEQ_le_const[OF lim]) using x(2) by auto then show "\x\C. dist x l \ f x" using \c \ C\ by auto qed text \congruence rule for continuity. The assumption that $f y = g y$ is necessary since \verb+at x+ is the pointed neighborhood at $x$.\ lemma continuous_within_cong: assumes "continuous (at y within S) f" "eventually (\x. f x = g x) (at y within S)" "f y = g y" shows "continuous (at y within S) g" -using assms(1) assms(2) Lim_transform_eventually unfolding continuous_within assms(3) by auto + using assms continuous_within filterlim_cong by fastforce text \A function which tends to infinity at infinity, on a proper set, realizes its infimum\ lemma continuous_attains_inf_proper: fixes f :: "'a::metric_space \ 'b::linorder_topology" assumes "proper s" "a \ s" "continuous_on s f" "\z. z \ s - cball a r \ f z \ f a" shows "\x\s. \y\s. f x \ f y" proof (cases "r \ 0") case True have "\x\cball a r \ s. \y \ cball a r \ s. f x \ f y" apply (rule continuous_attains_inf) using assms True unfolding proper_def apply (auto simp add: continuous_on_subset) using centre_in_cball by blast then obtain x where x: "x \ cball a r \ s" "\y. y \ cball a r \ s \ f x \ f y" by auto have "f x \ f y" if "y \ s" for y proof (cases "y \ cball a r") case True then show ?thesis using x(2) that by auto next case False have "f x \ f a" apply (rule x(2)) using assms True by auto then show ?thesis using assms(4)[of y] that False by auto qed then show ?thesis using x(1) by auto next case False show ?thesis apply (rule bexI[of _ a]) using assms False by auto qed subsubsection \Measure of balls\ -text \The image of a ball by an affine map is still a ball, with explicit center and radius.\ +text \The image of a ball by an affine map is still a ball, with explicit center and radius. (Now unused)\ lemma affine_image_ball [simp]: "(\y. R *\<^sub>R y + x) ` cball 0 1 = cball (x::('a::real_normed_vector)) \R\" proof have "dist x (R *\<^sub>R y + x) \ \R\" if "dist 0 y \ 1" for y proof - have "dist x (R *\<^sub>R y + x) = norm ((R *\<^sub>R y + x) - x)" by (simp add: dist_norm) also have "... = \R\ * norm y" by auto finally show ?thesis using that by (simp add: mult_left_le) qed then show "(\y. R *\<^sub>R y + x) ` cball 0 1 \ cball x \R\" by auto show "cball x \R\ \ (\y. R *\<^sub>R y + x) ` cball 0 1" proof (cases "\R\ = 0") case True then have "cball x \R\ = {x}" by auto moreover have "x = R *\<^sub>R 0 + x \ 0 \ cball 0 1" by auto ultimately show ?thesis by auto next case False have "z \ (\y. R *\<^sub>R y + x) ` cball 0 1" if "z \ cball x \R\" for z proof - define y where "y = (z - x) /\<^sub>R R" have "R *\<^sub>R y + x = z" unfolding y_def using False by auto moreover have "y \ cball 0 1" using \z \ cball x \R\\ False unfolding y_def by (auto simp add: dist_norm[symmetric] divide_simps dist_commute) ultimately show ?thesis by auto qed then show ?thesis by auto qed qed text \From the rescaling properties of Lebesgue measure in a euclidean space, it follows that the measure of any ball can be expressed in terms of the measure of the unit ball.\ lemma lebesgue_measure_ball: assumes "R \ 0" shows "measure lborel (cball (x::('a::euclidean_space)) R) = R^(DIM('a)) * measure lborel (cball (0::'a) 1)" "emeasure lborel (cball (x::('a::euclidean_space)) R) = R^(DIM('a)) * emeasure lborel (cball (0::'a) 1)" -using measure_lebesgue_affine[of R x "cball 0 1"] emeasure_lebesgue_affine[of R x "cball 0 1"] assms -unfolding affine_image_ball by (auto simp add: ennreal_power) + apply (simp add: assms content_cball) + by (simp add: assms emeasure_cball ennreal_mult' ennreal_power mult.commute) text \We show that the unit ball has positive measure -- this is obvious, but useful. We could show it by arguing that it contains a box, whose measure can be computed, but instead we say that if the measure vanished then the measure of any ball would also vanish, contradicting the fact that the space has infinite measure. This avoids all computations.\ lemma lebesgue_measure_ball_pos: "emeasure lborel (cball (0::'a::euclidean_space) 1) > 0" "measure lborel (cball (0::'a::euclidean_space) 1) > 0" proof - show "emeasure lborel (cball (0::'a::euclidean_space) 1) > 0" proof (rule ccontr) assume "\(emeasure lborel (cball (0::'a::euclidean_space) 1) > 0)" then have "emeasure lborel (cball (0::'a) 1) = 0" by auto then have "emeasure lborel (cball (0::'a) n) = 0" for n::nat using lebesgue_measure_ball(2)[of "real n" 0] by (metis mult_zero_right of_nat_0_le_iff) then have "emeasure lborel (\n. cball (0::'a) (real n)) = 0" by (metis (mono_tags, lifting) borel_closed closed_cball emeasure_UN_eq_0 imageE sets_lborel subsetI) moreover have "(\n. cball (0::'a) (real n)) = UNIV" by (auto simp add: real_arch_simple) ultimately show False by simp qed moreover have "emeasure lborel (cball (0::'a::euclidean_space) 1) < \" by (rule emeasure_bounded_finite, auto) ultimately show "measure lborel (cball (0::'a::euclidean_space) 1) > 0" by (metis borel_closed closed_cball ennreal_0 has_integral_iff_emeasure_lborel has_integral_measure_lborel less_irrefl order_refl zero_less_measure_iff) qed subsubsection \infdist and closest point projection\ text \The distance to a union of two sets is the minimum of the distance to the two sets.\ lemma infdist_union_min [mono_intros]: assumes "A \ {}" "B \ {}" shows "infdist x (A \ B) = min (infdist x A) (infdist x B)" using assms by (simp add: infdist_def cINF_union inf_real_def) text \The distance to a set is non-increasing with the set.\ lemma infdist_mono [mono_intros]: assumes "A \ B" "A \ {}" shows "infdist x B \ infdist x A" -proof - - have "(INF a\B. dist x a) \ (INF a\A. dist x a)" - by (rule cINF_superset_mono[OF assms(2) _ assms(1)], auto) - then show ?thesis - unfolding infdist_def using assms by auto -qed + by (simp add: assms infdist_eq_setdist setdist_subset_right) text \If a set is proper, then the infimum of the distances to this set is attained.\ lemma infdist_proper_attained: assumes "proper C" "C \ {}" shows "\c\C. infdist x C = dist x c" proof - obtain a where "a \ C" using assms by auto have *: "dist x a \ dist x z" if "dist a z \ 2 * dist a x" for z proof - have "2 * dist a x \ dist a z" using that by simp also have "... \ dist a x + dist x z" by (intro mono_intros) finally show ?thesis by (simp add: dist_commute) qed have "\c\C. \d\C. dist x c \ dist x d" apply (rule continuous_attains_inf_proper[OF assms(1) \a \ C\, of _ "2 * dist a x"]) using * by (auto intro: continuous_intros) then show ?thesis unfolding infdist_def using \C \ {}\ by (metis antisym bdd_below_image_dist cINF_lower le_cINF_iff) qed lemma infdist_almost_attained: assumes "infdist x X < a" "X \ {}" shows "\y\X. dist x y < a" using assms using cInf_less_iff[of "(dist x)`X"] unfolding infdist_def by auto lemma infdist_triangle_abs [mono_intros]: "\infdist x A - infdist y A\ \ dist x y" by (metis (full_types) abs_diff_le_iff diff_le_eq dist_commute infdist_triangle) text \The next lemma is missing in the library, contrary to its cousin \verb+continuous_infdist+.\ text \The infimum of the distance to a singleton set is simply the distance to the unique member of the set.\ -lemma infdist_point [simp]: - "infdist x {y} = dist x y" -unfolding infdist_def by (metis cInf_singleton image_empty image_insert insert_not_empty) - text \The closest point projection of $x$ on $A$. It is not unique, so we choose one point realizing the minimal distance. And if there is no such point, then we use $x$, to make some statements true without any assumption.\ definition proj_set::"'a::metric_space \ 'a set \ 'a set" where "proj_set x A = {y \ A. dist x y = infdist x A}" definition distproj::"'a::metric_space \ 'a set \ 'a" where "distproj x A = (if proj_set x A \ {} then SOME y. y \ proj_set x A else x)" lemma proj_setD: assumes "y \ proj_set x A" shows "y \ A" "dist x y = infdist x A" using assms unfolding proj_set_def by auto lemma proj_setI: assumes "y \ A" "dist x y \ infdist x A" shows "y \ proj_set x A" using assms infdist_le[OF \y \ A\, of x] unfolding proj_set_def by auto lemma proj_setI': assumes "y \ A" "\z. z \ A \ dist x y \ dist x z" shows "y \ proj_set x A" proof (rule proj_setI[OF \y \ A\]) show "dist x y \ infdist x A" apply (subst infdist_notempty) using assms by (auto intro!: cInf_greatest) qed lemma distproj_in_proj_set: assumes "proj_set x A \ {}" shows "distproj x A \ proj_set x A" "distproj x A \ A" "dist x (distproj x A) = infdist x A" proof - show "distproj x A \ proj_set x A" using assms unfolding distproj_def using some_in_eq by auto then show "distproj x A \ A" "dist x (distproj x A) = infdist x A" unfolding proj_set_def by auto qed lemma proj_set_nonempty_of_proper: assumes "proper A" "A \ {}" shows "proj_set x A \ {}" proof - have "\y. y \ A \ dist x y = infdist x A" using infdist_proper_attained[OF assms, of x] by auto then show "proj_set x A \ {}" unfolding proj_set_def by auto qed lemma distproj_self [simp]: assumes "x \ A" shows "proj_set x A = {x}" "distproj x A = x" proof - show "proj_set x A = {x}" unfolding proj_set_def using assms by auto then show "distproj x A = x" unfolding distproj_def by auto qed lemma distproj_closure [simp]: assumes "x \ closure A" shows "distproj x A = x" proof (cases "proj_set x A \ {}") case True show ?thesis using distproj_in_proj_set(3)[OF True] assms by (metis closure_empty dist_eq_0_iff distproj_self(2) in_closure_iff_infdist_zero) next case False then show ?thesis unfolding distproj_def by auto qed lemma distproj_le: assumes "y \ A" shows "dist x (distproj x A) \ dist x y" proof (cases "proj_set x A \ {}") case True show ?thesis using distproj_in_proj_set(3)[OF True] infdist_le[OF assms] by auto next case False then show ?thesis unfolding distproj_def by auto qed lemma proj_set_dist_le: assumes "y \ A" "p \ proj_set x A" shows "dist x p \ dist x y" using assms infdist_le unfolding proj_set_def by auto subsection \Material on ereal and ennreal\ text \We add the simp rules that we needed to make all computations become more or less automatic.\ lemma ereal_of_real_of_ereal_iff [simp]: "ereal(real_of_ereal x) = x \ x \ \ \ x \ - \" "x = ereal(real_of_ereal x) \ x \ \ \ x \ - \" by (metis MInfty_neq_ereal(1) PInfty_neq_ereal(2) real_of_ereal.elims)+ -lemma inverse_eq_infinity_iff_eq_zero [simp]: - "1/(x::ereal) = \ \ x = 0" -by (simp add: divide_ereal_def) - declare ereal_inverse_eq_0 [simp] declare ereal_0_gt_inverse [simp] declare ereal_inverse_le_0_iff [simp] declare ereal_divide_eq_0_iff [simp] declare ereal_mult_le_0_iff [simp] declare ereal_zero_le_0_iff [simp] declare ereal_mult_less_0_iff [simp] declare ereal_zero_less_0_iff [simp] declare ereal_uminus_eq_reorder [simp] declare ereal_minus_le_iff [simp] lemma ereal_inverse_noteq_minus_infinity [simp]: "1/(x::ereal) \ -\" by (simp add: divide_ereal_def) lemma ereal_inverse_positive_iff_nonneg_not_infinity [simp]: "0 < 1/(x::ereal) \ (x \ 0 \ x \ \)" by (cases x, auto simp add: one_ereal_def) lemma ereal_inverse_negative_iff_nonpos_not_infinity' [simp]: "0 > inverse (x::ereal) \ (x < 0 \ x \ -\)" by (cases x, auto simp add: one_ereal_def) lemma ereal_divide_pos_iff [simp]: "0 < x/(y::ereal) \ (y \ \ \ y \ -\) \ ((x > 0 \ y > 0) \ (x < 0 \ y < 0) \ (y = 0 \ x > 0))" unfolding divide_ereal_def by auto lemma ereal_divide_neg_iff [simp]: "0 > x/(y::ereal) \ (y \ \ \ y \ -\) \ ((x > 0 \ y < 0) \ (x < 0 \ y > 0) \ (y = 0 \ x < 0))" unfolding divide_ereal_def by auto -lemma ereal_distrib_left: - fixes a b c :: ereal - assumes "a \ \ \ b \ -\" - and "a \ -\ \ b \ \" - and "\c\ \ \" - shows "c * (a + b) = c * a + c * b" -using assms -by (cases rule: ereal3_cases[of a b c]) (simp_all add: field_simps) - -lemma ereal_distrib_minus_left: - fixes a b c :: ereal - assumes "a \ \ \ b \ \" - and "a \ -\ \ b \ -\" - and "\c\ \ \" - shows "c * (a - b) = c * a - c * b" -using assms -by (cases rule: ereal3_cases[of a b c]) (simp_all add: field_simps) - -lemma ereal_distrib_minus_right: - fixes a b c :: ereal - assumes "a \ \ \ b \ \" - and "a \ -\ \ b \ -\" - and "\c\ \ \" - shows "(a - b) * c = a * c - b * c" -using assms -by (cases rule: ereal3_cases[of a b c]) (simp_all add: field_simps) - -text \The next one is missing close to its friend \verb+Liminf_ereal_mult_right+.\ - -lemma Liminf_ereal_mult_left: - assumes "F \ bot" "(c::real) \ 0" - shows "Liminf F (\n. ereal c * f n) = ereal c * Liminf F f" -using Liminf_ereal_mult_right[OF assms] by (subst (1 2) mult.commute) - - text \More additions to \verb+mono_intros+.\ lemma ereal_leq_imp_neg_leq [mono_intros]: fixes x y::ereal assumes "x \ y" shows "-y \ -x" using assms by auto lemma ereal_le_imp_neg_le [mono_intros]: fixes x y::ereal assumes "x < y" shows "-y < -x" using assms by auto declare ereal_mult_left_mono [mono_intros] declare ereal_mult_right_mono [mono_intros] declare ereal_mult_strict_right_mono [mono_intros] declare ereal_mult_strict_left_mono [mono_intros] text \Monotonicity of basic inclusions.\ lemma ennreal_mono': "mono ennreal" by (simp add: ennreal_leI monoI) lemma enn2ereal_mono': "mono enn2ereal" by (simp add: less_eq_ennreal.rep_eq mono_def) lemma e2ennreal_mono': "mono e2ennreal" by (simp add: e2ennreal_mono mono_def) lemma enn2ereal_mono [mono_intros]: assumes "x \ y" shows "enn2ereal x \ enn2ereal y" using assms less_eq_ennreal.rep_eq by auto lemma ereal_mono: "mono ereal" unfolding mono_def by auto lemma ereal_strict_mono: "strict_mono ereal" unfolding strict_mono_def by auto lemma ereal_mono2 [mono_intros]: assumes "x \ y" shows "ereal x \ ereal y" by (simp add: assms) lemma ereal_strict_mono2 [mono_intros]: assumes "x < y" shows "ereal x < ereal y" using assms by auto lemma enn2ereal_a_minus_b_plus_b [mono_intros]: "enn2ereal a \ enn2ereal (a - b) + enn2ereal b" by (metis diff_add_self_ennreal less_eq_ennreal.rep_eq linear plus_ennreal.rep_eq) text \The next lemma follows from the same assertion in ereals.\ lemma enn2ereal_strict_mono [mono_intros]: assumes "x < y" shows "enn2ereal x < enn2ereal y" using assms less_ennreal.rep_eq by auto declare ennreal_mult_strict_left_mono [mono_intros] declare ennreal_mult_strict_right_mono [mono_intros] lemma ennreal_ge_0 [mono_intros]: assumes "0 < x" shows "0 < ennreal x" by (simp add: assms) text \The next lemma is true and useful in ereal. Note that variants such as $a + b \leq c + d$ implies $a-d \leq c -b$ are not true -- take $a = c = \infty$ and $b = d = 0$...\ lemma ereal_minus_le_minus_plus [mono_intros]: fixes a b c::ereal assumes "a \ b + c" shows "-b \ -a + c" using assms apply (cases a, cases b, cases c, auto) using ereal_infty_less_eq2(2) ereal_plus_1(4) by fastforce lemma tendsto_ennreal_0 [tendsto_intros]: assumes "(u \ 0) F" shows "((\n. ennreal(u n)) \ 0) F" unfolding ennreal_0[symmetric] by (intro tendsto_intros assms) lemma tendsto_ennreal_1 [tendsto_intros]: assumes "(u \ 1) F" shows "((\n. ennreal(u n)) \ 1) F" unfolding ennreal_1[symmetric] by (intro tendsto_intros assms) subsection \Miscellaneous\ -declare lim_1_over_n [tendsto_intros] -declare lim_ln_over_n [tendsto_intros] - -lemma lim_log_over_n [tendsto_intros]: - "(\n. log k n/n) \ 0" -proof - - have *: "log k n/n = (1/ln k) * (ln n / n)" for n - unfolding log_def by auto - have "(\n. (1/ln k) * (ln n / n)) \ (1/ln k) * 0" - by (intro tendsto_intros) - then show ?thesis - unfolding * by auto -qed - lemma lim_ceiling_over_n [tendsto_intros]: assumes "(\n. u n/n) \ l" shows "(\n. ceiling(u n)/n) \ l" proof (rule tendsto_sandwich[of "\n. u n/n" _ _ "\n. u n/n + 1/n"]) show "\\<^sub>F n in sequentially. u n / real n \ real_of_int \u n\ / real n" unfolding eventually_sequentially by (rule exI[of _ 1], auto simp add: divide_simps) show "\\<^sub>F n in sequentially. real_of_int \u n\ / real n \ u n / real n + 1 / real n" unfolding eventually_sequentially by (rule exI[of _ 1], auto simp add: divide_simps) have "(\n. u n / real n + 1 / real n) \ l + 0" by (intro tendsto_intros assms) then show "(\n. u n / real n + 1 / real n) \ l" by auto qed (simp add: assms) -lemma power4_eq_xxxx: - fixes x::"'a::monoid_mult" - shows "x^4 = x * x * x * x" -by (simp add: mult.assoc power_numeral_even) - subsubsection \Liminfs and Limsups\ text \More facts on liminfs and limsups\ lemma Limsup_obtain': fixes u::"'a \ 'b::complete_linorder" assumes "Limsup F u > c" "eventually P F" shows "\n. P n \ u n > c" proof - have *: "(INF P\{P. eventually P F}. SUP x\{x. P x}. u x) > c" using assms by (simp add: Limsup_def) have **: "c < (SUP x\{x. P x}. u x)" using less_INF_D[OF *, of P] assms by auto then show ?thesis by (simp add: less_SUP_iff) qed lemma limsup_obtain: fixes u::"nat \ 'a :: complete_linorder" assumes "limsup u > c" shows "\n \ N. u n > c" using Limsup_obtain'[OF assms, of "\n. n \ N"] unfolding eventually_sequentially by auto lemma Liminf_obtain': fixes u::"'a \ 'b::complete_linorder" assumes "Liminf F u < c" "eventually P F" shows "\n. P n \ u n < c" proof - have *: "(SUP P\{P. eventually P F}. INF x\{x. P x}. u x) < c" using assms by (simp add: Liminf_def) have **: "(INF x\{x. P x}. u x) < c" using SUP_lessD[OF *, of P] assms by auto then show ?thesis by (simp add: INF_less_iff) qed lemma liminf_obtain: fixes u::"nat \ 'a :: complete_linorder" assumes "liminf u < c" shows "\n \ N. u n < c" using Liminf_obtain'[OF assms, of "\n. n \ N"] unfolding eventually_sequentially by auto text \The Liminf of a minimum is the minimum of the Liminfs.\ lemma Liminf_min_eq_min_Liminf: fixes u v::"nat \ 'a::complete_linorder" shows "Liminf F (\n. min (u n) (v n)) = min (Liminf F u) (Liminf F v)" proof (rule order_antisym) show "Liminf F (\n. min (u n) (v n)) \ min (Liminf F u) (Liminf F v)" by (auto simp add: Liminf_mono) have "Liminf F (\n. min (u n) (v n)) > w" if H: "min (Liminf F u) (Liminf F v) > w" for w proof (cases "{w<..n. u n > w) F" "eventually (\n. v n > w) F" using H le_Liminf_iff by fastforce+ then have "eventually (\n. min (u n) (v n) > w) F" apply auto using eventually_elim2 by fastforce moreover have "z > w \ z \ min (Liminf F u) (Liminf F v)" for z using H True not_le_imp_less by fastforce ultimately have "eventually (\n. min (u n) (v n) \ min (Liminf F u) (Liminf F v)) F" by (simp add: eventually_mono) then have "min (Liminf F u) (Liminf F v) \ Liminf F (\n. min (u n) (v n))" by (metis Liminf_bounded) then show ?thesis using H less_le_trans by blast next case False then obtain z where "z \ {w<..n. u n > z) F" "eventually (\n. v n > z) F" using le_Liminf_iff by fastforce+ then have "eventually (\n. min (u n) (v n) > z) F" apply auto using eventually_elim2 by fastforce then have "Liminf F (\n. min (u n) (v n)) \ z" by (simp add: Liminf_bounded eventually_mono less_imp_le) then show ?thesis using H(1) by auto qed then show "min (Liminf F u) (Liminf F v) \ Liminf F (\n. min (u n) (v n))" using not_le_imp_less by blast qed text \The Limsup of a maximum is the maximum of the Limsups.\ lemma Limsup_max_eq_max_Limsup: fixes u::"'a \ 'b::complete_linorder" shows "Limsup F (\n. max (u n) (v n)) = max (Limsup F u) (Limsup F v)" proof (rule order_antisym) show "max (Limsup F u) (Limsup F v) \ Limsup F (\n. max (u n) (v n))" by (auto intro: Limsup_mono) have "Limsup F (\n. max (u n) (v n)) < e" if "max (Limsup F u) (Limsup F v) < e" for e proof (cases "\t. max (Limsup F u) (Limsup F v) < t \ t < e") case True then obtain t where t: "t < e" "max (Limsup F u) (Limsup F v) < t" by auto then have "Limsup F u < t" "Limsup F v < t" using that max_def by auto then have *: "eventually (\n. u n < t) F" "eventually (\n. v n < t) F" by (auto simp: Limsup_lessD) have "eventually (\n. max (u n) (v n) < t) F" using eventually_mono[OF eventually_conj[OF *]] by auto then have "Limsup F (\n. max (u n) (v n)) \ t" by (meson Limsup_obtain' not_le_imp_less order.asym) then show ?thesis using t by auto next case False have "Limsup F u < e" "Limsup F v < e" using that max_def by auto then have *: "eventually (\n. u n < e) F" "eventually (\n. v n < e) F" by (auto simp: Limsup_lessD) have "eventually (\n. max (u n) (v n) \ max (Limsup F u) (Limsup F v)) F" apply (rule eventually_mono[OF eventually_conj[OF *]]) using False not_le_imp_less by force then have "Limsup F (\n. max (u n) (v n)) \ max (Limsup F u) (Limsup F v)" by (meson Limsup_obtain' leD leI) then show ?thesis using that le_less_trans by blast qed then show "Limsup F (\n. max (u n) (v n)) \ max (Limsup F u) (Limsup F v)" using not_le_imp_less by blast qed subsubsection \Bounding the cardinality of a finite set\ text \A variation with real bounds.\ lemma finite_finite_subset_caract': fixes C::real assumes "\G. G \ F \ finite G \ card G \ C" shows "finite F \ card F \ C" by (meson assms finite_if_finite_subsets_card_bdd le_nat_floor order_refl) text \To show that a set has cardinality at most one, it suffices to show that any two of its elements coincide.\ lemma finite_at_most_singleton: assumes "\x y. x \ F \ y \ F \ x = y" shows "finite F \ card F \ 1" proof (cases "F = {}") case True then show ?thesis by auto next case False then obtain x where "x \ F" by auto then have "F = {x}" using assms by auto then show ?thesis by auto qed text \Bounded sets of integers are finite.\ lemma finite_real_int_interval [simp]: "finite (range real_of_int \ {a..b})" proof - have "range real_of_int \ {a..b} \ real_of_int`{floor a..ceiling b}" by (auto, metis atLeastAtMost_iff ceiling_mono ceiling_of_int floor_mono floor_of_int image_eqI) then show ?thesis using finite_subset by blast qed text \Well separated sets of real numbers are finite, with controlled cardinality.\ lemma separated_in_real_card_bound: assumes "T \ {a..(b::real)}" "d > 0" "\x y. x \ T \ y \ T \ y > x \ y \ x + d" shows "finite T" "card T \ nat (floor ((b-a)/d) + 1)" proof - define f where "f = (\x. floor ((x-a) / d))" have "f`{a..b} \ {0..floor ((b-a)/d)}" unfolding f_def using \d > 0\ by (auto simp add: floor_mono frac_le) then have *: "f`T \ {0..floor ((b-a)/d)}" using \T \ {a..b}\ by auto then have "finite (f`T)" by (rule finite_subset, auto) have "card (f`T) \ card {0..floor ((b-a)/d)}" apply (rule card_mono) using * by auto then have card_le: "card (f`T) \ nat (floor ((b-a)/d) + 1)" using card_atLeastAtMost_int by auto have *: "f x \ f y" if "y \ x + d" for x y proof - have "(y-a)/d \ (x-a)/d + 1" using \d > 0\ that by (auto simp add: divide_simps) then show ?thesis unfolding f_def by linarith qed have "inj_on f T" unfolding inj_on_def using * assms(3) by (auto, metis not_less_iff_gr_or_eq) show "finite T" using \finite (f`T)\ \inj_on f T\ finite_image_iff by blast have "card T = card (f`T)" using \inj_on f T\ by (simp add: card_image) then show "card T \ nat (floor ((b-a)/d) + 1)" using card_le by auto qed subsection \Manipulating finite ordered sets\ -text \We will need below to contruct finite sets of real numbers with good properties expressed +text \We will need below to construct finite sets of real numbers with good properties expressed in terms of consecutive elements of the set. We introduce tools to manipulate such sets, expressing in particular the next and the previous element of the set and controlling how they evolve when one inserts a new element in the set. It works in fact in any linorder, and could also prove useful to construct sets of integer numbers. Manipulating the next and previous elements work well, except at the top (respectively bottom). In our constructions, these will be fixed and called $b$ and $a$.\ text \Notations for the next and the previous elements.\ definition next_in::"'a set \ 'a \ ('a::linorder)" where "next_in A u = Min (A \ {u<..})" definition prev_in::"'a set \ 'a \ ('a::linorder)" where "prev_in A u = Max (A \ {.. {a..b}" "a \ A" "b \ A" "a < b" begin text \Basic properties of the next element, when one starts from an element different from top.\ lemma next_in_basics: assumes "u \ {a.. A" "next_in A u > u" "A \ {u<.. A \ {u<..}" unfolding next_in_def apply (rule Min_in) using assms \finite A\ \b \ A\ by auto then show "next_in A u \ A" "next_in A u > u" by auto show "A \ {u<.. {a.. A" "v > u" "{u<.. A = {}" shows "next_in A u = v" using assms next_in_basics[OF \u \ {a..] by fastforce text \Basic properties of the previous element, when one starts from an element different from bottom.\ lemma prev_in_basics: assumes "u \ {a<..b}" shows "prev_in A u \ A" "prev_in A u < u" "A \ {prev_in A u<.. A \ {..finite A\ \a \ A\ by auto then show "prev_in A u \ A" "prev_in A u < u" by auto show "A \ {prev_in A u<.. {a<..b}" "v \ A" "v < u" "{v<.. A = {}" shows "prev_in A u = v" using assms prev_in_basics[OF \u \ {a<..b}\] by (meson disjoint_iff_not_equal greaterThanLessThan_iff less_linear) text \The interval $[a,b]$ is covered by the intervals between the consecutive elements of $A$.\ lemma intervals_decomposition: "(\ U \ {{u..next_in A u} | u. u \ A - {b}}. U) = {a..b}" proof show "(\U\{{u..next_in A u} |u. u \ A - {b}}. U) \ {a..b}" using \A \ {a..b}\ next_in_basics(1) apply auto apply fastforce by (metis \A \ {a..b}\ atLeastAtMost_iff eq_iff le_less_trans less_eq_real_def not_less subset_eq subset_iff_psubset_eq) have "x \ (\U\{{u..next_in A u} |u. u \ A - {b}}. U)" if "x \ {a..b}" for x proof - consider "x = b" | "x \ A - {b}" | "x \ A" by blast then show ?thesis proof(cases) case 1 define u where "u = prev_in A b" have "b \ {a<..b}" using \a < b\ by simp have "u \ A - {b}" unfolding u_def using prev_in_basics[OF \b \ {a<..b}\] by simp then have "u \ {a..A \ {a..b}\ \a < b\ by fastforce have "next_in A u = b" using prev_in_basics[OF \b \ {a<..b}\] next_in_basics[OF \u \ {a..] \A \ {a..b}\ unfolding u_def by force then have "x \ {u..next_in A u}" unfolding 1 using prev_in_basics[OF \b \ {a<..b}\] u_def by auto then show ?thesis using \u \ A - {b}\ by auto next case 2 then have "x \ {a..A \ {a..b}\ \a < b\ by fastforce have "x \ {x.. next_in A x}" using next_in_basics[OF \x \ {a..] by auto then show ?thesis using 2 by auto next case 3 then have "x \ {a<..b}" using that \a \ A\ leI by fastforce define u where "u = prev_in A x" have "u \ A - {b}" unfolding u_def using prev_in_basics[OF \x \ {a<..b}\] that by auto then have "u \ {a..A \ {a..b}\ \a < b\ by fastforce have "x \ {u..next_in A u}" using prev_in_basics[OF \x \ {a<..b}\] next_in_basics[OF \u \ {a..] unfolding u_def by auto then show ?thesis using \u \ A - {b}\ by auto qed qed then show "{a..b} \ (\U\{{u..next_in A u} |u. u \ A - {b}}. U)" by auto qed end text \If one inserts an additional element, then next and previous elements are not modified, except at the location of the insertion.\ lemma next_in_insert: assumes A: "finite A" "A \ {a..b}" "a \ A" "b \ A" "a < b" and "x \ {a..b} - A" shows "\u. u \ A - {b, prev_in A x} \ next_in (insert x A) u = next_in A u" "next_in (insert x A) x = next_in A x" "next_in (insert x A) (prev_in A x) = x" proof - define B where "B = insert x A" have B: "finite B" "B \ {a..b}" "a \ B" "b \ B" "a < b" using assms unfolding B_def by auto have x: "x \ {a.. {a<..b}" using assms leI by fastforce+ show "next_in B x = next_in A x" unfolding B_def by (auto simp add: next_in_def) show "next_in B (prev_in A x) = x" apply (rule next_inI[OF B]) unfolding B_def using prev_in_basics[OF A \x \ {a<..b}\] \A \ {a..b}\ x by auto fix u assume "u \ A - {b, prev_in A x}" then have "u \ {a.. {u<..(x \ {u<.. {u<..x \ {a<..b}\]) using \u \ A - {b, prev_in A x}\ * next_in_basics[OF A \u \ {a..] apply auto by (meson disjoint_iff_not_equal greaterThanLessThan_iff less_trans) then show False using \u \ A - {b, prev_in A x}\ by auto qed show "next_in B u = next_in A u" apply (rule next_inI[OF B \u \ {a..]) unfolding B_def using next_in_basics[OF A \u \ {a..] \x \ {u<.. by auto qed text \If consecutive elements are enough separated, this implies a simple bound on the cardinality of the set.\ lemma separated_in_real_card_bound2: fixes A::"real set" assumes A: "finite A" "A \ {a..b}" "a \ A" "b \ A" "a < b" and B: "\u. u \ A - {b} \ next_in A u \ u + d" "d > 0" shows "card A \ nat (floor ((b-a)/d) + 1)" proof (rule separated_in_real_card_bound[OF \A \ {a..b}\ \d > 0\]) fix x y assume "x \ A" "y \ A" "y > x" then have "x \ A - {b}" "x \ {a..A \ {a..b}\ by auto have "y \ next_in A x" using next_in_basics[OF A \x \ {a..] \y \ A\ \y > x\ by auto then show "y \ x + d" using B(1)[OF \x \ A - {b}\] by auto qed subsection \Well-orders\ text \In this subsection, we give additional lemmas on well-orders or cardinals or whatever, that would well belong to the library, and will be needed below.\ lemma (in wo_rel) max2_underS [simp]: assumes "x \ underS z" "y \ underS z" shows "max2 x y \ underS z" using assms max2_def by auto lemma (in wo_rel) max2_underS' [simp]: assumes "x \ underS y" shows "max2 x y = y" "max2 y x = y" apply (simp add: underS_E assms max2_def) using assms max2_def ANTISYM antisym_def underS_E by fastforce lemma (in wo_rel) max2_xx [simp]: "max2 x x = x" using max2_def by auto declare underS_notIn [simp] text \The abbrevation $=o$ is used both in \verb+Set_Algebras+ and Cardinals. We disable the one from \verb+Set_Algebras+.\ no_notation elt_set_eq (infix "=o" 50) lemma regularCard_ordIso: assumes "Card_order r" "regularCard r" "s =o r" shows "regularCard s" unfolding regularCard_def proof (auto) fix K assume K: "K \ Field s" "cofinal K s" obtain f where f: "bij_betw f (Field s) (Field r)" "embed s r f" using \s =o r\ unfolding ordIso_def iso_def by auto have "f`K \ Field r" using K(1) f(1) bij_betw_imp_surj_on by blast have "cofinal (f`K) r" unfolding cofinal_def proof fix a assume "a \ Field r" then obtain a' where a: "a' \ Field s" "f a' = a" using f by (metis bij_betw_imp_surj_on imageE) then obtain b' where b: "b' \ K" "a' \ b' \ (a', b') \ s" using \cofinal K s\ unfolding cofinal_def by auto have P1: "f b' \ f`K" using b(1) by auto have "a' \ b'" "a' \ Field s" "b' \ Field s" using a(1) b K(1) by auto then have P2: "a \ f b'" unfolding a(2)[symmetric] using f(1) unfolding bij_betw_def inj_on_def by auto have "(a', b') \ s" using b by auto then have P3: "(a, f b') \ r" unfolding a(2)[symmetric] using f by (meson FieldI1 FieldI2 Card_order_ordIso[OF assms(1) assms(3)] card_order_on_def iso_defs(1) iso_iff2) show "\b\f ` K. a \ b \ (a, b) \ r" using P1 P2 P3 by blast qed then have "|f`K| =o r" using \regularCard r\ \f`K \ Field r\ unfolding regularCard_def by auto moreover have "|f`K| =o |K|" using f(1) K(1) by (meson bij_betw_subset card_of_ordIsoI ordIso_symmetric) ultimately show "|K| =o s" using \s =o r\ by (meson ordIso_symmetric ordIso_transitive) qed lemma AboveS_not_empty_in_regularCard: assumes "|S| Field r" assumes r: "Card_order r" "regularCard r" "\finite (Field r)" shows "AboveS r S \ {}" proof - have "\(cofinal S r)" using assms not_ordLess_ordIso unfolding regularCard_def by auto then obtain a where a: "a \ Field r" "\b\S. \(a \ b \ (a,b) \ r)" unfolding cofinal_def by auto have *: "a = b \ (b, a) \ r" if "b \ S" for b proof - have "a = b \ (a,b) \ r" using a that by auto then show ?thesis using \Card_order r\ \a \ Field r\ \b \ S\ \S \ Field r\ unfolding card_order_on_def well_order_on_def linear_order_on_def total_on_def by auto qed obtain c where "c \ Field r" "c \ a" "(a, c) \ r" using a(1) r infinite_Card_order_limit by fastforce then have "c \ AboveS r S" unfolding AboveS_def apply simp using Card_order_trans[OF r(1)] by (metis *) then show ?thesis by auto qed lemma AboveS_not_empty_in_regularCard': assumes "|S| Field r" "T \ S" assumes r: "Card_order r" "regularCard r" "\finite (Field r)" shows "AboveS r (f`T) \ {}" proof - have "|f`T| \o |T|" by simp moreover have "|T| \o |S|" using \T \ S\ by simp ultimately have *: "|f`T| |S| by (meson ordLeq_ordLess_trans) show ?thesis using AboveS_not_empty_in_regularCard[OF * _ r] \T \ S\ \f`S \ Field r\ by auto qed lemma Well_order_extend: assumes WELL: "well_order_on A r" and SUB: "A \ B" shows "\r'. well_order_on B r' \ r \ r'" proof- have r: "Well_order r \ Field r = A" using WELL well_order_on_Well_order by blast let ?C = "B - A" obtain r'' where "well_order_on ?C r''" using well_order_on by blast then have r'': "Well_order r'' \ Field r'' = ?C" using well_order_on_Well_order by blast let ?r' = "r Osum r''" have "Field r Int Field r'' = {}" using r r'' by auto then have "r \o ?r'" using Osum_ordLeq[of r r''] r r'' by blast then have "Well_order ?r'" unfolding ordLeq_def by auto moreover have "Field ?r' = B" using r r'' SUB by (auto simp add: Field_Osum) ultimately have "well_order_on B ?r'" by auto moreover have "r \ ?r'" by (simp add: Osum_def subrelI) ultimately show ?thesis by blast qed text \The next lemma shows that, if the range of a function is endowed with a wellorder, then one can pull back this wellorder by the function, and then extend it in the fibers of the function in order to keep the wellorder property. The proof is done by taking an arbitrary family of wellorders on each of the fibers, and using the lexicographic order: one has $x < y$ if $f x < f y$, or if $f x = f y$ and, in the corresponding fiber of $f$, one has $x < y$. To formalize it, it is however more efficient to use one single wellorder, and restrict it to each fiber.\ lemma Well_order_pullback: assumes "Well_order r" shows "\s. Well_order s \ Field s = UNIV \ (\x y. (f x, f y) \ (r-Id) \ (x, y) \ s)" proof - obtain r2 where r2: "Well_order r2" "Field r2 = UNIV" "r \ r2" using Well_order_extend[OF assms, of UNIV] well_order_on_Well_order by auto obtain s2 where s2: "Well_order s2" "Field s2 = (UNIV::'b set)" by (meson well_ordering) have r2s2: "\x y z. (x, y) \ s2 \ (y, z) \ s2 \ (x, z) \ s2" "\x. (x, x) \ s2" "\x y. (x, y) \ s2 \ (y, x) \ s2" "\x y. (x, y) \ s2 \ (y, x) \ s2 \ x = y" "\x y z. (x, y) \ r2 \ (y, z) \ r2 \ (x, z) \ r2" "\x. (x, x) \ r2" "\x y. (x, y) \ r2 \ (y, x) \ r2" "\x y. (x, y) \ r2 \ (y, x) \ r2 \ x = y" using r2 s2 unfolding well_order_on_def linear_order_on_def partial_order_on_def total_on_def preorder_on_def antisym_def refl_on_def trans_def by (metis UNIV_I)+ define s where "s = {(x,y). (f x, f y) \ r2 \ (f x = f y \ (x, y) \ s2)}" have "linear_order s" unfolding linear_order_on_def partial_order_on_def preorder_on_def proof (auto) show "total_on UNIV s" unfolding s_def apply (rule total_onI, auto) using r2s2 by metis+ show "refl_on UNIV s" unfolding s_def apply (rule refl_onI, auto) using r2s2 by blast+ show "trans s" unfolding s_def apply (rule transI, auto) using r2s2 by metis+ show "antisym s" unfolding s_def apply (rule antisymI, auto) using r2s2 by metis+ qed moreover have "wf (s - Id)" proof (rule wfI_min) fix x::'b and Q assume "x \ Q" obtain z' where z': "z' \ f`Q" "\y. (y, z') \ r2 - Id \ y \ f`Q" proof (rule wfE_min[of "r2-Id" "f x" "f`Q"], auto) show "wf(r2-Id)" using \Well_order r2\ unfolding well_order_on_def by auto show "f x \ f`Q" using \x \ Q\ by auto qed define Q2 where "Q2 = Q \ f-`{z'}" obtain z where z: "z \ Q2" "\y. (y, z) \ s2 - Id \ y \ Q2" proof (rule wfE_min'[of "s2-Id" "Q2"], auto) show "wf(s2-Id)" using \Well_order s2\ unfolding well_order_on_def by auto assume "Q2 = {}" then show False unfolding Q2_def using \z' \ f`Q\ by blast qed have "(y, z) \ (s-Id) \ y \ Q" for y unfolding s_def using z' z Q2_def by auto then show "\z\Q. \y. (y, z) \ s - Id \ y \ Q" using \z \ Q2\ Q2_def by auto qed ultimately have "well_order_on UNIV s" unfolding well_order_on_def by simp moreover have "(f x, f y) \ (r-Id) \ (x, y) \ s" for x y unfolding s_def using \r \ r2\ by auto ultimately show ?thesis using well_order_on_Well_order by metis qed end (*of theory Library_Complements*) diff --git a/thys/Smooth_Manifolds/Analysis_More.thy b/thys/Smooth_Manifolds/Analysis_More.thy --- a/thys/Smooth_Manifolds/Analysis_More.thy +++ b/thys/Smooth_Manifolds/Analysis_More.thy @@ -1,1464 +1,1394 @@ section \Library Additions\ theory Analysis_More imports "HOL-Analysis.Equivalence_Lebesgue_Henstock_Integration" "HOL-Library.Function_Algebras" "HOL-Types_To_Sets.Linear_Algebra_On" begin lemma openin_open_Int'[intro]: "open S \ openin (top_of_set U) (S \ U)" by (auto simp: openin_open) subsection \Parametricity rules for topology\ text \TODO: also check with theory \Transfer_Euclidean_Space_Vector\ in AFP/ODE...\ context includes lifting_syntax begin lemma Sigma_transfer[transfer_rule]: "(rel_set A ===> (A ===> rel_set B) ===> rel_set (rel_prod A B)) Sigma Sigma" unfolding Sigma_def by transfer_prover lemma filterlim_transfer[transfer_rule]: "((A ===> B) ===> rel_filter B ===> rel_filter A ===> (=)) filterlim filterlim" if [transfer_rule]: "bi_unique B" unfolding filterlim_iff by transfer_prover lemma nhds_transfer[transfer_rule]: "(A ===> rel_filter A) nhds nhds" if [transfer_rule]: "bi_unique A" "bi_total A" "(rel_set A ===> (=)) open open" unfolding nhds_def by transfer_prover lemma at_within_transfer[transfer_rule]: "(A ===> rel_set A ===> rel_filter A) at_within at_within" if [transfer_rule]: "bi_unique A" "bi_total A" "(rel_set A ===> (=)) open open" unfolding at_within_def by transfer_prover lemma continuous_on_transfer[transfer_rule]: "(rel_set A ===> (A ===> B) ===> (=)) continuous_on continuous_on" if [transfer_rule]: "bi_unique A" "bi_total A" "(rel_set A ===> (=)) open open" "bi_unique B" "bi_total B" "(rel_set B ===> (=)) open open" unfolding continuous_on_def by transfer_prover lemma continuous_on_transfer_right_total[transfer_rule]: "(rel_set A ===> (A ===> B) ===> (=)) (\X::'a::t2_space set. continuous_on (X \ Collect AP)) (\Y::'b::t2_space set. continuous_on Y)" if DomainA: "Domainp A = AP" and [folded DomainA, transfer_rule]: "bi_unique A" "right_total A" "(rel_set A ===> (=)) (openin (top_of_set (Collect AP))) open" "bi_unique B" "bi_total B" "(rel_set B ===> (=)) open open" unfolding DomainA[symmetric] proof (intro rel_funI) fix X Y f g assume H[transfer_rule]: "rel_set A X Y" "(A ===> B) f g" from H(1) have XA: "x \ X \ Domainp A x" for x by (auto simp: rel_set_def) then have *: "X \ Collect (Domainp A) = X" by auto have "openin (top_of_set (Collect (Domainp A))) (Collect (Domainp A))" by auto show " continuous_on (X \ Collect (Domainp A)) f = continuous_on Y g" unfolding continuous_on_eq_continuous_within continuous_within_topological * apply transfer apply safe subgoal for x B apply (drule bspec, assumption, drule spec, drule mp, assumption, drule mp, assumption) apply clarsimp subgoal for AA apply (rule exI[where x="AA \ Collect (Domainp A)"]) by (auto intro: XA) done subgoal using XA by (force simp: openin_subtopology) done qed lemma continuous_on_transfer_right_total2[transfer_rule]: "(rel_set A ===> (A ===> B) ===> (=)) (\X::'a::t2_space set. continuous_on X) (\Y::'b::t2_space set. continuous_on Y)" if DomainB: "Domainp B = BP" and [folded DomainB, transfer_rule]: "bi_unique A" "bi_total A" "(rel_set A ===> (=)) open open" "bi_unique B" "right_total B" "(rel_set B ===> (=)) ((openin (top_of_set (Collect BP)))) open" unfolding DomainB[symmetric] proof (intro rel_funI) fix X Y f g assume H[transfer_rule]: "rel_set A X Y" "(A ===> B) f g" show "continuous_on X f = continuous_on Y g" unfolding continuous_on_eq_continuous_within continuous_within_topological apply transfer apply safe subgoal for x C apply (clarsimp simp: openin_subtopology) apply (drule bspec, assumption, drule spec, drule mp, assumption, drule mp, assumption) apply clarsimp by (meson Domainp_applyI H(1) H(2) rel_setD1) subgoal for x C proof - let ?sub = "top_of_set (Collect (Domainp B))" assume cont: "\x\X. \Ba\{A. Ball A (Domainp B)}. openin (top_of_set (Collect (Domainp B))) Ba \ f x \ Ba \ (\Aa. open Aa \ x \ Aa \ (\y\X. y \ Aa \ f y \ Ba))" and x: "x \ X" "open C" "f x \ C" let ?B = "C \ Collect (Domainp B)" have "?B \ {A. Ball A (Domainp B)}" by auto have "openin ?sub (Collect (Domainp B))" by auto then have "openin ?sub ?B" using \open C\ by auto moreover have "f x \ ?B" using x apply transfer apply auto by (meson Domainp_applyI H(1) H(2) rel_setD1) ultimately obtain D where "open D \ x \ D \ (\y\X. y \ D \ f y \ ?B)" using cont x by blast then show "\A. open A \ x \ A \ (\y\X. y \ A \ f y \ C)" by auto qed done qed lemma generate_topology_transfer[transfer_rule]: includes lifting_syntax assumes [transfer_rule]: "right_total A" "bi_unique A" shows "(rel_set (rel_set A) ===> rel_set A ===> (=)) (generate_topology o (insert (Collect (Domainp A)))) generate_topology" proof (intro rel_funI) fix B C X Y assume t[transfer_rule]: "rel_set (rel_set A) B C" "rel_set A X Y" then have "X \ Collect (Domainp A)" by (auto simp: rel_set_def) with t have rI: "rel_set A (X \ Collect (Domainp A)) Y" by (auto simp: inf_absorb1) have eq_UNIV_I: "Z = UNIV" if [transfer_rule]: "rel_set A {a. Domainp A a} Z" for Z using that assms apply (auto simp: right_total_def rel_set_def) using bi_uniqueDr by fastforce show "(generate_topology \ insert (Collect (Domainp A))) B X = generate_topology C Y" unfolding o_def proof (rule iffI) fix x assume "generate_topology (insert (Collect (Domainp A)) B) X" then show "generate_topology C Y" unfolding o_def using rI proof (induction X arbitrary: Y) case [transfer_rule]: UNIV with eq_UNIV_I[of Y] show ?case by (simp add: generate_topology.UNIV) next case (Int a b) note [transfer_rule] = Int(5) obtain a' where a'[transfer_rule]: "rel_set A (a \ Collect (Domainp A)) a'" by (metis Domainp_iff Domainp_set Int_Collect) obtain b' where b'[transfer_rule]: "rel_set A (b \ Collect (Domainp A)) b'" by (metis Domainp_iff Domainp_set Int_Collect) from Int.IH(1)[OF a'] Int.IH(2)[OF b'] have "generate_topology C a'" "generate_topology C b'" by auto from generate_topology.Int[OF this] have "generate_topology C (a' \ b')" . also have "a' \ b' = Y" by transfer auto finally show ?case by (simp add: generate_topology.Int) next case (UN K) note [transfer_rule] = UN(3) have "\K'. \k. rel_set A (k \ Collect (Domainp A)) (K' k)" by (rule choice) (metis Domainp_iff Domainp_set Int_Collect) then obtain K' where K': "\k. rel_set A (k \ Collect (Domainp A)) (K' k)" by metis from UN.IH[OF _ this] have "generate_topology C k'" if "k' \ K'`K" for k' using that by auto from generate_topology.UN[OF this] have "generate_topology C (\(K' ` K))" . also from K' have [transfer_rule]: "(rel_set (=) ===> rel_set A) (\x. x \ Collect (Domainp A)) K'" by (fastforce simp: rel_fun_def rel_set_def) have "\(K' ` K) = Y" by transfer auto finally show ?case by (simp add: generate_topology.UN) next case (Basis s) from this(1) show ?case proof assume "s = Collect (Domainp A)" with eq_UNIV_I[of Y] Basis(2) show ?case by (simp add: generate_topology.UNIV) next assume "s \ B" with Basis(2) obtain t where [transfer_rule]: "rel_set A (s \ Collect (Domainp A)) t" by auto from Basis(1) t(1) have s: "s \ Collect (Domainp A) = s" by (force simp: rel_set_def) have "t \ C" using \s \ B\ s by transfer auto also note [transfer_rule] = Basis(2) have "t = Y" by transfer auto finally show ?case by (rule generate_topology.Basis) qed qed next assume "generate_topology C Y" then show "generate_topology (insert (Collect (Domainp A)) B) X" using \rel_set A X Y\ proof (induction arbitrary: X) case [transfer_rule]: UNIV have "UNIV = (UNIV::'b set)" by auto then have "X = {a. Domainp A a}" by transfer then show ?case by (intro generate_topology.Basis) auto next case (Int a b) obtain a' b' where [transfer_rule]: "rel_set A a' a" "rel_set A b' b" by (meson assms(1) right_total_def right_total_rel_set) from generate_topology.Int[OF Int.IH(1)[OF this(1)] Int.IH(2)[OF this(2)]] have "generate_topology (insert {a. Domainp A a} B) (a' \ b')" by simp also define I where "I = a \ b" from \rel_set A X (a \ b)\ have [transfer_rule]: "rel_set A X I" by (simp add: I_def) from I_def have "a' \ b' = X" by transfer simp finally show ?case . next case (UN K) have "\K'. \k. rel_set A (K' k) k" by (rule choice) (meson assms(1) right_total_def right_total_rel_set) then obtain K' where K': "\k. rel_set A (K' k) k" by metis from UN.IH[OF _ this] have "generate_topology (insert {a. Domainp A a} B) k" if "k \ K'`K" for k using that by auto from generate_topology.UN[OF this] have "generate_topology (insert {a. Domainp A a} B) (\(K'`K))" by auto also from K' have [transfer_rule]: "(rel_set (=) ===> rel_set A) K' id" by (fastforce simp: rel_fun_def rel_set_def) define U where "U = (\(id ` K))" from \rel_set A X _\ have [transfer_rule]: "rel_set A X U" by (simp add: U_def) from U_def have "\(K' ` K) = X" by transfer simp finally show ?case . next case (Basis s) note [transfer_rule] = \rel_set A X s\ from \s \ C\ have "X \ B" by transfer then show ?case by (intro generate_topology.Basis) auto qed qed qed end subsection \Miscellaneous\ lemmas [simp del] = mem_ball lemma in_closureI[intro, simp]: "x \ X \ x \ closure X" using closure_subset by auto lemmas open_continuous_vimage = continuous_on_open_vimage[THEN iffD1, rule_format] lemma open_continuous_vimage': "open s \ continuous_on s f \ open B \ open (s \ f -` B)" using open_continuous_vimage[of s f B] by (auto simp: Int_commute) lemma support_on_mono: "support_on carrier f \ support_on carrier g" if "\x. x \ carrier \ f x \ 0 \ g x \ 0" using that by (auto simp: support_on_def) lemma image_prod: "(\(x, y). (f x, g y)) ` (A \ B) = f ` A \ g ` B" by auto subsection \Closed support\ definition "csupport_on X S = closure (support_on X S)" lemma closed_csupport_on[intro, simp]: "closed (csupport_on carrier \)" by (auto simp: csupport_on_def) lemma not_in_csupportD: "x \ csupport_on carrier \ \ x \ carrier \ \ x = 0" by (auto simp: csupport_on_def support_on_def) lemma csupport_on_mono: "csupport_on carrier f \ csupport_on carrier g" if "\x. x \ carrier \ f x \ 0 \ g x \ 0" unfolding csupport_on_def apply (rule closure_mono) using that by (rule support_on_mono) subsection \Homeomorphism\ lemma homeomorphism_empty[simp]: "homeomorphism {} t f f' \ t = {}" "homeomorphism s {} f f' \ s = {}" by (auto simp: homeomorphism_def) lemma homeomorphism_add: "homeomorphism UNIV UNIV (\x. x + c) (\x. x - c)" for c::"_::real_normed_vector" unfolding homeomorphism_def by (auto simp: algebra_simps continuous_intros intro!: image_eqI[where x="x - c" for x]) lemma in_range_scaleR_iff: "x \ range ((*\<^sub>R) c) \ c = 0 \ x = 0" for x::"_::real_vector" by (auto simp: intro!: image_eqI[where x="x /\<^sub>R c"]) lemma homeomorphism_scaleR: "homeomorphism UNIV UNIV (\x. c *\<^sub>R x::_::real_normed_vector) (\x. x /\<^sub>R c)" if "c \ 0" using that unfolding homeomorphism_def by (auto simp: in_range_scaleR_iff algebra_simps intro!: continuous_intros) lemma homeomorphism_prod: "homeomorphism (a \ b) (c \ d) (\(x, y). (f x, g y)) (\(x, y). (f' x, g' y))" if "homeomorphism a c f f'" "homeomorphism b d g g'" using that by (simp add: homeomorphism_def image_prod) (auto simp add: split_beta intro!: continuous_intros elim: continuous_on_compose2) subsection \Generalizations\ -lemma univ_second_countable: - obtains \ :: "'a::second_countable_topology set set" - where "countable \" "\C. C \ \ \ open C" - "\S. open S \ \U. U \ \ \ S = \U" - by (metis ex_countable_basis topological_basis_def) - -proposition Lindelof: - fixes \ :: "'a::second_countable_topology set set" - assumes \: "\S. S \ \ \ open S" - obtains \' where "\' \ \" "countable \'" "\\' = \\" -proof - - obtain \ :: "'a set set" - where "countable \" "\C. C \ \ \ open C" - and \: "\S. open S \ \U. U \ \ \ S = \U" - using univ_second_countable by auto - define \ where "\ \ {S. S \ \ \ (\U. U \ \ \ S \ U)}" - have "countable \" - apply (rule countable_subset [OF _ \countable \\]) - apply (force simp: \_def) - done - have "\S. \U. S \ \ \ U \ \ \ S \ U" - by (simp add: \_def) - then obtain G where G: "\S. S \ \ \ G S \ \ \ S \ G S" - by metis - have "\\ \ \\" - unfolding \_def by (blast dest: \ \) - moreover have "\\ \ \\" - using \_def by blast - ultimately have eq1: "\\ = \\" .. - have eq2: "\\ = \ (G ` \)" - using G eq1 by auto - show ?thesis - apply (rule_tac \' = "G ` \" in that) - using G \countable \\ apply (auto simp: eq1 eq2) - done -qed - - lemma openin_subtopology_eq_generate_topology: "openin (top_of_set S) x = generate_topology (insert S ((\B. B \ S) ` BB)) x" if open_gen: "open = generate_topology BB" and subset: "x \ S" proof - have "generate_topology (insert S ((\B. B \ S) ` BB)) (T \ S)" if "generate_topology BB T" for T using that proof (induction) case UNIV then show ?case by (auto intro!: generate_topology.Basis) next case (Int a b) have "generate_topology (insert S ((\B. B \ S) ` BB)) (a \ S \ (b \ S))" by (rule generate_topology.Int) (use Int in auto) then show ?case by (simp add: ac_simps) next case (UN K) then have "generate_topology (insert S ((\B. B \ S) ` BB)) (\k\K. k \ S)" by (intro generate_topology.UN) auto then show ?case by simp next case (Basis s) then show ?case by (intro generate_topology.Basis) auto qed moreover have "\T. generate_topology BB T \ x = T \ S" if "generate_topology (insert S ((\B. B \ S) ` BB)) x" "x \ UNIV" using that proof (induction) case UNIV then show ?case by simp next case (Int a b) then show ?case using generate_topology.Int by auto next case (UN K) from UN.IH have "\k\K-{UNIV}. \T. generate_topology BB T \ k = T \ S" by auto from this[THEN bchoice] obtain T where T: "\k. k \ T ` (K - {UNIV}) \ generate_topology BB k" "\k. k \ K - {UNIV} \ k = (T k) \ S" by auto from generate_topology.UN[OF T(1)] have "generate_topology BB (\(T ` (K - {UNIV})))" by auto moreover have "\K = (\(T ` (K - {UNIV}))) \ S" if "UNIV \ K" using T(2) UN that by auto ultimately show ?case apply (cases "UNIV \ K") subgoal using UN by auto subgoal by auto done next case (Basis s) - from this(1) show ?case - apply rule - subgoal - apply (rule exI[where x=UNIV]) - by (auto simp: generate_topology.UNIV) - subgoal - apply clarsimp - subgoal for B - apply (rule exI[where x="B"]) by (auto simp: generate_topology.Basis) - done - done + then show ?case + using generate_topology.UNIV generate_topology.Basis by blast qed moreover have "\T. generate_topology BB T \ UNIV = T \ S" if "generate_topology (insert S ((\B. B \ S) ` BB)) x" "x = UNIV" proof - have "S = UNIV" using that \x \ S\ by auto then show ?thesis by (simp add: generate_topology.UNIV) qed ultimately show ?thesis by (metis open_gen open_openin openin_open_Int' openin_subtopology) qed subsection \Equal topologies\ lemma topology_eq_iff: "t = s \ (topspace t = topspace s \ (\x\topspace t. openin t x = openin s x))" by (metis (full_types) openin_subset topology_eq) subsection \Finer topologies\ definition finer_than (infix "(finer'_than)" 50) where "T1 finer_than T2 \ continuous_map T1 T2 (\x. x)" lemma finer_than_iff_nhds: "T1 finer_than T2 \ (\X. openin T2 X \ openin T1 (X \ topspace T1)) \ (topspace T1 \ topspace T2)" by (auto simp: finer_than_def continuous_map_alt) lemma continuous_on_finer_topo: "continuous_map s t f" if "continuous_map s' t f" "s finer_than s'" using that by (auto simp: finer_than_def o_def dest: continuous_map_compose) lemma continuous_on_finer_topo2: "continuous_map s t f" if "continuous_map s t' f" "t' finer_than t" using that by (auto simp: finer_than_def o_def dest: continuous_map_compose) lemma antisym_finer_than: "S = T" if "S finer_than T" "T finer_than S" using that apply (auto simp: finer_than_def topology_eq_iff continuous_map_alt) apply (metis inf.orderE)+ done lemma subtopology_finer_than[simp]: "top_of_set X finer_than euclidean" by (auto simp: finer_than_iff_nhds openin_subtopology) subsection \Support\ lemma support_on_nonneg_sum: "support_on X (\x. \i\S. f i x) = (\i\S. support_on X (f i))" if "finite S" "\x i . x \ X \ i \ S \ f i x \ 0" for f::"_\_\_::ordered_comm_monoid_add" using that by (auto simp: support_on_def sum_nonneg_eq_0_iff) lemma support_on_nonneg_sum_subset: "support_on X (\x. \i\S. f i x) \ (\i\S. support_on X (f i))" for f::"_\_\_::ordered_comm_monoid_add" by (cases "finite S") (auto simp: support_on_def dest!: sum_not_0) lemma support_on_nonneg_sum_subset': "support_on X (\x. \i\S x. f i x) \ (\x\X. (\i\S x. support_on X (f i)))" for f::"_\_\_::ordered_comm_monoid_add" by (auto simp: support_on_def dest!: sum_not_0) subsection \Final topology (Bourbaki, General Topology I, 4.)\ definition "final_topology X Y f = topology (\U. U \ X \ (\i. openin (Y i) (f i -` U \ topspace (Y i))))" lemma openin_final_topology: "openin (final_topology X Y f) = (\U. U \ X \ (\i. openin (Y i) (f i -` U \ topspace (Y i))))" unfolding final_topology_def apply (rule topology_inverse') unfolding istopology_def proof safe fix S T i assume "\i. openin (Y i) (f i -` S \ topspace (Y i))" "\i. openin (Y i) (f i -` T \ topspace (Y i))" then have "openin (Y i) (f i -` S \ topspace (Y i) \ (f i -` T \ topspace (Y i)))" (is "openin _ ?I") by auto also have "?I = f i -` (S \ T) \ topspace (Y i)" (is "_ = ?R") by auto finally show "openin (Y i) ?R" . next fix K i assume "\U\K. U \ X \ (\i. openin (Y i) (f i -` U \ topspace (Y i)))" then have "openin (Y i) (\X\K. f i -` X \ topspace (Y i))" by (intro openin_Union) auto then show "openin (Y i) (f i -` \K \ topspace (Y i))" by (auto simp: vimage_Union) qed force+ lemma topspace_final_topology: "topspace (final_topology X Y f) = X" if "\i. f i \ topspace (Y i) \ X" proof - have *: "f i -` X \ topspace (Y i) = topspace (Y i)" for i using that by auto show ?thesis unfolding topspace_def unfolding openin_final_topology apply (rule antisym) apply force apply (rule subsetI) apply (rule UnionI[where X=X]) using that by (auto simp: *) qed lemma continuous_on_final_topologyI2: "continuous_map (Y i) (final_topology X Y f) (f i)" if "\i. f i \ topspace (Y i) \ X" using that by (auto simp: openin_final_topology continuous_map_alt topspace_final_topology) lemma continuous_on_final_topologyI1: "continuous_map (final_topology X Y f) Z g" if hyp: "\i. continuous_map (Y i) Z (g o f i)" and that: "\i. f i \ topspace (Y i) \ X" "g \ X \ topspace Z" unfolding continuous_map_alt proof safe fix V assume V: "openin Z V" have oV: "openin (Y i) (f i -` g -` V \ topspace (Y i))" for i using hyp[rule_format, of i] V by (auto simp: continuous_map_alt vimage_comp dest!: spec[where x=V]) have *: "f i -` g -` V \ f i -` X \ topspace (Y i) = f i -` g -` V \ topspace (Y i)" (is "_ = ?rhs i") for i using that by auto show "openin (final_topology X Y f) (g -` V \ topspace (final_topology X Y f))" by (auto simp: openin_final_topology oV topspace_final_topology that *) qed (use that in \auto simp: topspace_final_topology\) lemma continuous_on_final_topology_iff: "continuous_map (final_topology X Y f) Z g \ (\i. continuous_map (Y i) Z (g o f i))" if "\i. f i \ topspace (Y i) \ X" "g \ X \ topspace Z" using that by (auto intro!: continuous_on_final_topologyI1[OF _ that] intro: continuous_map_compose[OF continuous_on_final_topologyI2[OF that(1)]]) subsection \Quotient topology\ definition map_topology :: "('a \ 'b) \ 'a topology \ 'b topology" where "map_topology p X = final_topology (p ` topspace X) (\_. X) (\(_::unit). p)" lemma openin_map_topology: "openin (map_topology p X) = (\U. U \ p ` topspace X \ openin X (p -` U \ topspace X))" by (auto simp: map_topology_def openin_final_topology) lemma topspace_map_topology[simp]: "topspace (map_topology f T) = f ` topspace T" unfolding map_topology_def by (subst topspace_final_topology) auto lemma continuous_on_map_topology: "continuous_map T (map_topology f T) f" unfolding continuous_map_alt openin_map_topology by auto lemma continuous_map_composeD: "continuous_map T X (g \ f) \ g \ f ` topspace T \ topspace X" by (auto simp: continuous_map_def) lemma continuous_on_map_topology2: "continuous_map T X (g \ f) \ continuous_map (map_topology f T) X g" unfolding map_topology_def apply safe subgoal apply (rule continuous_on_final_topologyI1) subgoal by assumption subgoal by force subgoal by (rule continuous_map_composeD) done subgoal apply (erule continuous_map_compose[rotated]) apply (rule continuous_on_final_topologyI2) by force done lemma map_sub_finer_than_commute: "map_topology f (subtopology T (f -` X)) finer_than subtopology (map_topology f T) X" by (auto simp: finer_than_def continuous_map_def openin_subtopology openin_map_topology topspace_subtopology) lemma sub_map_finer_than_commute: "subtopology (map_topology f T) X finer_than map_topology f (subtopology T (f -` X))" if "openin T (f -` X)"\ \this is more or less the condition from \<^url>\https://math.stackexchange.com/questions/705840/quotient-topology-vs-subspace-topology\\ unfolding finer_than_def continuous_map_alt proof (rule conjI, clarsimp) fix U assume "openin (map_topology f (subtopology T (f -` X))) U" then obtain W where W: "U \ f ` (topspace T \ f -` X)" "openin T W" "f -` U \ (topspace T \ f -` X) = W \ f -` X" by (auto simp: topspace_subtopology openin_subtopology openin_map_topology) have "(f -` f ` W \ f -` X) \ topspace T = W \ topspace T \ f -` X" apply auto by (metis Int_iff W(3) vimage_eq) also have "openin T \" by (auto intro!: W that) finally show "openin (subtopology (map_topology f T) X) (U \ (f ` topspace T \ X))" using W unfolding topspace_subtopology topspace_map_topology openin_subtopology openin_map_topology by (intro exI[where x="(f ` W \ X)"]) auto qed auto lemma subtopology_map_topology: "subtopology (map_topology f T) X = map_topology f (subtopology T (f -` X))" if "openin T (f -` X)" apply (rule antisym_finer_than) using sub_map_finer_than_commute[OF that] map_sub_finer_than_commute[of f T X] by auto lemma quotient_map_map_topology: "quotient_map X (map_topology f X) f" by (auto simp: quotient_map_def openin_map_topology ac_simps) (simp_all add: vimage_def Int_def) lemma topological_space_quotient: "class.topological_space (openin (map_topology f euclidean))" if "surj f" apply standard apply (auto simp: ) using that by (auto simp: openin_map_topology) lemma t2_space_quotient: "class.t2_space (open::'b set \ bool)" if open_def: "open = (openin (map_topology (p::'a::t2_space\'b::topological_space) euclidean))" "surj p" and open_p: "\X. open X \ open (p ` X)" and "closed {(x, y). p x = p y}" (is "closed ?R") apply (rule class.t2_space.intro) subgoal by (unfold open_def, rule topological_space_quotient; fact) proof standard fix a b::'b obtain x y where a_def: "a = p x" and b_def: "b = p y" using \surj p\ by fastforce assume "a \ b" with \closed ?R\ have "open (-?R)" "(x, y) \ -?R" by (auto simp add: a_def b_def) from open_prod_elim[OF this] obtain N\<^sub>x N\<^sub>y where "open N\<^sub>x" "open N\<^sub>y" "(x, y) \ N\<^sub>x \ N\<^sub>y" "N\<^sub>x \ N\<^sub>y \ -?R" . then have "p ` N\<^sub>x \ p ` N\<^sub>y = {}" by auto moreover from \open N\<^sub>x\ \open N\<^sub>y\ have "open (p ` N\<^sub>x)" "open (p ` N\<^sub>y)" using open_p by blast+ moreover have "a \ p ` N\<^sub>x" "b \ p ` N\<^sub>y" using \(x, y) \ _ \ _\ by (auto simp: a_def b_def) ultimately show "\U V. open U \ open V \ a \ U \ b \ V \ U \ V = {}" by blast qed lemma second_countable_topology_quotient: "class.second_countable_topology (open::'b set \ bool)" if open_def: "open = (openin (map_topology (p::'a::second_countable_topology\'b::topological_space) euclidean))" "surj p" and open_p: "\X. open X \ open (p ` X)" apply (rule class.second_countable_topology.intro) subgoal by (unfold open_def, rule topological_space_quotient; fact) proof standard have euclidean_def: "euclidean = map_topology p euclidean" by (simp add: openin_inverse open_def) have continuous_on: "continuous_on UNIV p" using continuous_map_iff_continuous2 continuous_on_map_topology euclidean_def by fastforce from ex_countable_basis[where 'a='a] obtain A::"'a set set" where "countable A" "topological_basis A" by auto define B where "B = (\X. p ` X) ` A" have "countable (B::'b set set)" by (auto simp: B_def intro!: \countable A\) moreover have "topological_basis B" proof (rule topological_basisI) fix B' assume "B' \ B" then show "open B'" using \topological_basis A\ by (auto simp: B_def topological_basis_open intro!: open_p) next fix x::'b and O' assume "open O'" "x \ O'" have "open (p -` O')" using \open O'\ by (rule open_vimage) (auto simp: continuous_on) obtain y where y: "y \ p -` {x}" using \x \ O'\ by auto (metis UNIV_I open_def(2) rangeE) then have "y \ p -` O'" using \x \ O'\ by auto from topological_basisE[OF \topological_basis A\ \open (p -` O')\ this] obtain C where "C \ A" "y \ C" "C \ p -` O'" . let ?B' = "p ` C" have "?B' \ B" using \C \ A\ by (auto simp: B_def) moreover have "x \ ?B'" using y \y \ C\ \x \ O'\ by auto moreover have "?B' \ O'" using \C \ _\ by auto ultimately show "\B'\B. x \ B' \ B' \ O'" by metis qed ultimately show "\B::'b set set. countable B \ open = generate_topology B" by (auto simp: topological_basis_imp_subbasis) qed subsection \Closure\ lemma closure_Union: "closure (\X) = (\x\X. closure x)" if "finite X" using that by (induction X) auto subsection \Compactness\ lemma compact_if_closed_subset_of_compact: "compact S" if "closed S" "compact T" "S \ T" proof (rule compactI) fix UU assume UU: "\t\UU. open t" "S \ \UU" have "T \ \(insert (- S) (UU))" "\B. B \ insert (- S) UU \ open B" using UU \S \ T\ by (auto simp: open_Compl \closed S\) from compactE[OF \compact T\ this] obtain \' where \: "\' \ insert (- S) UU" "finite \'" "T \ \\'" by metis show "\C'\UU. finite C' \ S \ \C'" apply (rule exI[where x="\' - {-S}"]) using \ UU apply auto proof - fix x assume "x \ S" with \ \S \ T\ obtain U where "x \ U" "U \ \'" using \ by auto then show "\X\\' - {- S}. x \ X" using \ UU \x \ S\ apply - apply (rule bexI[where x=U]) by auto qed qed subsection \Locally finite\ definition "locally_finite_on X I U \ (\p\X. \N. p\N \ open N \ finite {i\I. U i \ N \ {}})" lemmas locally_finite_onI = locally_finite_on_def[THEN iffD2, rule_format] lemma locally_finite_onE: assumes "locally_finite_on X I U" assumes "p \ X" obtains N where "p \ N" "open N" "finite {i\I. U i \ N \ {}}" using assms by (auto simp: locally_finite_on_def) lemma locally_finite_onD: assumes "locally_finite_on X I U" assumes "p \ X" shows "finite {i\I. p \ U i}" apply (rule locally_finite_onE[OF assms]) apply (rule finite_subset) by auto lemma locally_finite_on_open_coverI: "locally_finite_on X I U" if fin: "\j. j \ I \ finite {i\I. U i \ U j \ {}}" and open_cover: "X \ (\i\I. U i)" "\i. i \ I \ open (U i)" proof (rule locally_finite_onI) fix p assume "p \ X" then obtain i where i: "i \ I" "p \ U i" "open (U i)" using open_cover by blast show "\N. p \ N \ open N \ finite {i \ I. U i \ N \ {}}" by (intro exI[where x="U i"] conjI i fin) qed lemma locally_finite_compactD: "finite {i\I. U i \ V \ {}}" if lf: "locally_finite_on X I U" and compact: "compact V" and subset: "V \ X" proof - have "\N. \p \ X. p \ N p \ open (N p) \ finite {i\I. U i \ N p \ {}}" by (rule bchoice) (auto elim!: locally_finite_onE[OF lf, rule_format]) then obtain N where N: "\p. p \ X \ p \ N p" "\p. p \ X \ open (N p)" "\p. p \ X \ finite {i\I. U i \ N p \ {}}" by blast have "V \ (\p\X. N p)" "\B. B \ N ` X \ open B" using N subset by force+ from compactE[OF compact this] obtain C where C: "C \ X" "finite C" "V \ \(N ` C)" by (metis finite_subset_image) then have "{i\I. U i \ V \ {}} \ {i\I. U i \ \(N ` C) \ {}}" by force also have "\ \ (\c\C. {i\I. U i \ N c \ {}})" by force also have "finite \" apply (rule finite_Union) using C by (auto intro!: C N) finally (finite_subset) show ?thesis . qed lemma closure_Int_open_eq_empty: "open S \ (closure T \ S) = {} \ T \ S = {}" by (auto simp: open_Int_closure_eq_empty ac_simps) lemma locally_finite_on_subset: assumes "locally_finite_on X J U" assumes "\i. i \ I \ V i \ U i" "I \ J" shows "locally_finite_on X I V" proof (rule locally_finite_onI) fix p assume "p \ X" from locally_finite_onE[OF assms(1) this] obtain N where "p \ N" "open N" "finite {i \ J. U i \ N \ {}}" . then show "\N. p \ N \ open N \ finite {i \ I. V i \ N \ {}}" apply (intro exI[where x=N]) using assms by (auto elim!: finite_subset[rotated]) qed lemma locally_finite_on_closure: "locally_finite_on X I (\x. closure (U x))" if "locally_finite_on X I U" proof (rule locally_finite_onI) fix p assume "p \ X" from locally_finite_onE[OF that this] obtain N where "p \ N" "open N" "finite {i \ I. U i \ N \ {}}" . then show "\N. p \ N \ open N \ finite {i \ I. closure (U i) \ N \ {}}" by (auto intro!: exI[where x=N] simp: closure_Int_open_eq_empty) qed lemma locally_finite_on_closedin_Union_closure: "closedin (top_of_set X) (\i\I. closure (U i))" if "locally_finite_on X I U" "\i. i \ I \ closure (U i) \ X" unfolding closedin_def apply safe subgoal using that(2) by auto subgoal apply (subst openin_subopen) proof clarsimp fix x assume x: "x \ X" "\i\I. x \ closure (U i)" from locally_finite_onE[OF that(1) \x \ X\] obtain N where N: "x \ N" "open N" "finite {i \ I. U i \ N \ {}}" (is "finite ?I"). define N' where "N' = N - (\i \ ?I. closure (U i))" have "open N'" by (auto simp: N'_def intro!: N) then have "openin (top_of_set X) (X \ N')" by (rule openin_open_Int) moreover have "x \ X \ N'" using x by (auto simp: N'_def N) moreover have "X \ N' \ X - (\i\I. closure (U i))" using x that(2) apply (auto simp: N'_def) by (meson N(2) closure_iff_nhds_not_empty dual_order.refl) ultimately show "\T. openin (top_of_set X) T \ x \ T \ T \ X - (\i\I. closure (U i))" by auto qed done lemma closure_subtopology_minimal: "S \ T \ closedin (top_of_set X) T \ closure S \ X \ T" apply (auto simp: closedin_closed) using closure_minimal by blast lemma locally_finite_on_closure_Union: "(\i\I. closure (U i)) = closure (\i\I. (U i)) \ X" if "locally_finite_on X I U" "\i. i \ I \ closure (U i) \ X" proof (rule antisym) show "(\i\I. closure (U i)) \ closure (\i\I. U i) \ X" using that apply auto by (metis (no_types, lifting) SUP_le_iff closed_closure closure_minimal closure_subset subsetCE) show "closure (\i\I. U i) \ X \ (\i\I. closure (U i))" apply (rule closure_subtopology_minimal) apply auto using that by (auto intro!: locally_finite_on_closedin_Union_closure) qed subsection \Refinement of cover\ definition refines :: "'a set set \ 'a set set \ bool" (infix "refines" 50) where "A refines B \ (\s\A. (\t. t \ B \ s \ t))" lemma refines_subset: "x refines y" if "z refines y" "x \ z" using that by (auto simp: refines_def) subsection \Functions as vector space\ instantiation "fun" :: (type, scaleR) scaleR begin definition scaleR_fun :: "real \ ('a \ 'b) \ 'a \ 'b" where "scaleR_fun r f = (\x. r *\<^sub>R f x)" lemma scaleR_fun_beta[simp]: "(r *\<^sub>R f) x = r *\<^sub>R f x" by (simp add: scaleR_fun_def) instance .. end instance "fun" :: (type, real_vector) real_vector by standard (auto simp: scaleR_fun_def algebra_simps) subsection \Additional lemmas\ lemmas [simp del] = vimage_Un vimage_Int lemma finite_Collect_imageI: "finite {U \ f ` X. P U}" if "finite {x\X. P (f x)}" proof - have "{d \ f ` X. P d} \ f ` {c \ X. P (f c)}" by blast then show ?thesis using finite_surj that by blast qed lemma plus_compose: "(x + y) \ f = (x \ f) + (y \ f)" by auto lemma mult_compose: "(x * y) \ f = (x \ f) * (y \ f)" by auto lemma scaleR_compose: "(c *\<^sub>R x) \ f = c *\<^sub>R (x \ f)" by (auto simp:) lemma image_scaleR_ball: fixes a :: "'a::real_normed_vector" shows "c \ 0 \ (*\<^sub>R) c ` ball a r = ball (c *\<^sub>R a) (abs c *\<^sub>R r)" proof (auto simp: mem_ball dist_norm, goal_cases) case (1 b) have "norm (c *\<^sub>R a - c *\<^sub>R b) = abs c * norm (a - b)" by (auto simp: norm_scaleR[symmetric] algebra_simps simp del: norm_scaleR) also have "\ < abs c * r" apply (rule mult_strict_left_mono) using 1 by auto finally show ?case . next case (2 x) have "norm (a - x /\<^sub>R c) < r" proof - have "norm (a - x /\<^sub>R c) = abs c *\<^sub>R norm (a - x /\<^sub>R c) /\<^sub>R abs c" using 2 by auto also have "abs c *\<^sub>R norm (a - x /\<^sub>R c) = norm (c *\<^sub>R a - x)" using 2 by (auto simp: norm_scaleR[symmetric] algebra_simps simp del: norm_scaleR) also have "\ < \c\ * r" by fact also have "\c\ * r /\<^sub>R \c\ = r" using 2 by auto finally show ?thesis using 2 by auto qed then have xdc: "x /\<^sub>R c \ ball a r" by (auto simp: mem_ball dist_norm) show ?case apply (rule image_eqI[OF _ xdc]) using 2 by simp qed subsection \Continuity\ lemma continuous_within_topologicalE: assumes "continuous (at x within s) f" "open B" "f x \ B" obtains A where "open A" "x \ A" "\y. y \ s \ y \ A \ f y \ B" using assms continuous_within_topological by metis lemma continuous_within_topologicalE': assumes "continuous (at x) f" "open B" "f x \ B" obtains A where "open A" "x \ A" "f ` A \ B" using assms continuous_within_topologicalE[OF assms] by (metis UNIV_I image_subsetI) lemma continuous_on_inverse: "continuous_on S f \ 0 \ f ` S \ continuous_on S (\x. inverse (f x))" for f::"_\_::real_normed_div_algebra" by (auto simp: continuous_on_def intro!: tendsto_inverse) subsection \@{term "(has_derivative)"}\ lemma has_derivative_plus_fun[derivative_intros]: "(x + y has_derivative x' + y') (at a within A)" if [derivative_intros]: "(x has_derivative x') (at a within A)" "(y has_derivative y') (at a within A)" by (auto simp: plus_fun_def intro!: derivative_eq_intros) lemma has_derivative_scaleR_fun[derivative_intros]: "(x *\<^sub>R y has_derivative x *\<^sub>R y') (at a within A)" if [derivative_intros]: "(y has_derivative y') (at a within A)" by (auto simp: scaleR_fun_def intro!: derivative_eq_intros) lemma has_derivative_times_fun[derivative_intros]: "(x * y has_derivative (\h. x a * y' h + x' h * y a)) (at a within A)" if [derivative_intros]: "(x has_derivative x') (at a within A)" "(y has_derivative y') (at a within A)" for x y::"_\'a::real_normed_algebra" by (auto simp: times_fun_def intro!: derivative_eq_intros) lemma real_sqrt_has_derivative_generic: "x \ 0 \ (sqrt has_derivative (*) ((if x > 0 then 1 else -1) * inverse (sqrt x) / 2)) (at x within S)" apply (rule has_derivative_at_withinI) using DERIV_real_sqrt_generic[of x "(if x > 0 then 1 else -1) * inverse (sqrt x) / 2"] at_within_open[of x "UNIV - {0}"] by (auto simp: has_field_derivative_def open_delete ac_simps split: if_splits) lemma sqrt_has_derivative: "((\x. sqrt (f x)) has_derivative (\xa. (if 0 < f x then 1 else - 1) / (2 * sqrt (f x)) * f' xa)) (at x within S)" if "(f has_derivative f') (at x within S)" "f x \ 0" by (rule has_derivative_eq_rhs[OF has_derivative_compose[OF that(1) real_sqrt_has_derivative_generic, OF that(2)]]) (auto simp: divide_simps) lemmas has_derivative_norm_compose[derivative_intros] = has_derivative_compose[OF _ has_derivative_norm] subsection \Differentiable\ lemmas differentiable_on_empty[simp] lemma differentiable_transform_eventually: "f differentiable (at x within X)" if "g differentiable (at x within X)" "f x = g x" "\\<^sub>F x in (at x within X). f x = g x" using that apply (auto simp: differentiable_def) subgoal for D apply (rule exI[where x=D]) apply (auto simp: has_derivative_within) by (simp add: eventually_mono Lim_transform_eventually) done lemma differentiable_within_eqI: "f differentiable at x within X" if "g differentiable at x within X" "\x. x \ X \ f x = g x" "x \ X" "open X" apply (rule differentiable_transform_eventually) apply (rule that) apply (auto simp: that) proof - have "\\<^sub>F x in at x within X. x \ X" using \open X\ using eventually_at_topological by blast then show " \\<^sub>F x in at x within X. f x = g x" by eventually_elim (auto simp: that) qed lemma differentiable_eqI: "f differentiable at x" if "g differentiable at x" "\x. x \ X \ f x = g x" "x \ X" "open X" using that unfolding at_within_open[OF that(3,4), symmetric] by (rule differentiable_within_eqI) lemma differentiable_on_eqI: "f differentiable_on S" if "g differentiable_on S" "\x. x \ S \ f x = g x" "open S" using that differentiable_eqI[of g _ S f] by (auto simp: differentiable_on_eq_differentiable_at) lemma differentiable_on_comp: "(f o g) differentiable_on S" if "g differentiable_on S" "f differentiable_on (g ` S)" using that by (auto simp: differentiable_on_def intro: differentiable_chain_within) lemma differentiable_on_comp2: "(f o g) differentiable_on S" if "f differentiable_on T" "g differentiable_on S" "g ` S \ T" apply (rule differentiable_on_comp) apply (rule that) apply (rule differentiable_on_subset) apply (rule that) apply (rule that) done lemmas differentiable_on_compose2 = differentiable_on_comp2[unfolded o_def] lemma differentiable_on_openD: "f differentiable at x" if "f differentiable_on X" "open X" "x \ X" using differentiable_on_eq_differentiable_at that by blast lemma differentiable_on_add_fun[intro, simp]: "x differentiable_on UNIV \ y differentiable_on UNIV \ x + y differentiable_on UNIV" by (auto simp: plus_fun_def) lemma differentiable_on_mult_fun[intro, simp]: "x differentiable_on UNIV \ y differentiable_on UNIV \ x * y differentiable_on UNIV" for x y::"_\'a::real_normed_algebra" by (auto simp: times_fun_def) lemma differentiable_on_scaleR_fun[intro, simp]: "y differentiable_on UNIV \ x *\<^sub>R y differentiable_on UNIV" by (auto simp: scaleR_fun_def) lemma sqrt_differentiable: "(\x. sqrt (f x)) differentiable (at x within S)" if "f differentiable (at x within S)" "f x \ 0" using that using sqrt_has_derivative[of f _ x S] by (auto simp: differentiable_def) lemma sqrt_differentiable_on: "(\x. sqrt (f x)) differentiable_on S" if "f differentiable_on S" "0 \ f ` S" using sqrt_differentiable[of f _ S] that by (force simp: differentiable_on_def) lemma differentiable_on_inverse: "f differentiable_on S \ 0 \ f ` S \ (\x. inverse (f x)) differentiable_on S" for f::"_\_::real_normed_field" by (auto simp: differentiable_on_def intro!: differentiable_inverse) lemma differentiable_on_openI: "f differentiable_on S" if "open S" "\x. x \ S \ \f'. (f has_derivative f') (at x)" using that by (auto simp: differentiable_on_def at_within_open[where S=S] differentiable_def) lemmas differentiable_norm_compose_at = differentiable_compose[OF differentiable_norm_at] lemma differentiable_on_Pair: "f differentiable_on S \ g differentiable_on S \ (\x. (f x, g x)) differentiable_on S" unfolding differentiable_on_def using differentiable_Pair[of f _ S g] by auto lemma differentiable_at_fst: "(\x. fst (f x)) differentiable at x within X" if "f differentiable at x within X" using that by (auto simp: differentiable_def dest!: has_derivative_fst) lemma differentiable_at_snd: "(\x. snd (f x)) differentiable at x within X" if "f differentiable at x within X" using that by (auto simp: differentiable_def dest!: has_derivative_snd) lemmas frechet_derivative_worksI = frechet_derivative_works[THEN iffD1] lemma sin_differentiable_at: "(\x. sin (f x::real)) differentiable at x within X" if "f differentiable at x within X" - by (auto intro!: differentiableI derivative_eq_intros frechet_derivative_worksI[OF that]) + using differentiable_def has_derivative_sin that by blast lemma cos_differentiable_at: "(\x. cos (f x::real)) differentiable at x within X" if "f differentiable at x within X" - by (auto intro!: differentiableI derivative_eq_intros frechet_derivative_worksI[OF that]) + using differentiable_def has_derivative_cos that by blast subsection \Frechet derivative\ -lemma frechet_derivative_transform_within_open: - "frechet_derivative f (at x) = frechet_derivative g (at x)" - if "open X" "x \ X" "\x. x \ X \ f x = g x" - "f differentiable at x" - apply (rule frechet_derivative_at) - apply (rule has_derivative_transform_within_open[OF _ that(1-3)]) - unfolding frechet_derivative_works[symmetric] - by fact - lemmas frechet_derivative_transform_within_open_ext = fun_cong[OF frechet_derivative_transform_within_open] lemmas frechet_derivative_at' = frechet_derivative_at[symmetric] -lemma frechet_derivative_const: "frechet_derivative (\x. c) (at a) = (\x. 0)" - by (rule frechet_derivative_at') - (auto intro!: derivative_eq_intros frechet_derivative_worksI) - -lemma frechet_derivative_id: "frechet_derivative (\x. x) (at a) = (\x. x)" - by (rule frechet_derivative_at') - (auto intro!: derivative_eq_intros frechet_derivative_worksI) - lemma frechet_derivative_plus_fun: "x differentiable at a \ y differentiable at a \ frechet_derivative (x + y) (at a) = frechet_derivative x (at a) + frechet_derivative y (at a)" by (rule frechet_derivative_at') (auto intro!: derivative_eq_intros frechet_derivative_worksI) lemmas frechet_derivative_plus = frechet_derivative_plus_fun[unfolded plus_fun_def] lemma frechet_derivative_zero_fun: "frechet_derivative 0 (at a) = 0" by (auto simp: frechet_derivative_const zero_fun_def) lemma frechet_derivative_sin: "frechet_derivative (\x. sin (f x)) (at x) = (\xa. frechet_derivative f (at x) xa * cos (f x))" if "f differentiable (at x)" for f::"_\real" by (rule frechet_derivative_at'[OF has_derivative_sin[OF frechet_derivative_worksI[OF that]]]) lemma frechet_derivative_cos: "frechet_derivative (\x. cos (f x)) (at x) = (\xa. frechet_derivative f (at x) xa * - sin (f x))" if "f differentiable (at x)" for f::"_\real" by (rule frechet_derivative_at'[OF has_derivative_cos[OF frechet_derivative_worksI[OF that]]]) lemma differentiable_sum_fun: "(\i. i \ I \ (f i differentiable at a)) \ sum f I differentiable at a" by (induction I rule: infinite_finite_induct) (auto simp: zero_fun_def plus_fun_def) lemma frechet_derivative_sum_fun: "(\i. i \ I \ (f i differentiable at a)) \ frechet_derivative (\i\I. f i) (at a) = (\i\I. frechet_derivative (f i) (at a))" by (induction I rule: infinite_finite_induct) (auto simp: frechet_derivative_zero_fun frechet_derivative_plus_fun differentiable_sum_fun) lemma sum_fun_def: "(\i\I. f i) = (\x. \i\I. f i x)" by (induction I rule: infinite_finite_induct) auto lemmas frechet_derivative_sum = frechet_derivative_sum_fun[unfolded sum_fun_def] lemma frechet_derivative_times_fun: "f differentiable at a \ g differentiable at a \ frechet_derivative (f * g) (at a) = (\x. f a * frechet_derivative g (at a) x + frechet_derivative f (at a) x * g a)" for f g::"_\'a::real_normed_algebra" by (rule frechet_derivative_at') (auto intro!: derivative_eq_intros frechet_derivative_worksI) lemmas frechet_derivative_times = frechet_derivative_times_fun[unfolded times_fun_def] lemma frechet_derivative_scaleR_fun: "y differentiable at a \ frechet_derivative (x *\<^sub>R y) (at a) = x *\<^sub>R frechet_derivative y (at a)" by (rule frechet_derivative_at') (auto intro!: derivative_eq_intros frechet_derivative_worksI) lemmas frechet_derivative_scaleR = frechet_derivative_scaleR_fun[unfolded scaleR_fun_def] lemma frechet_derivative_compose: "frechet_derivative (f o g) (at x) = frechet_derivative (f) (at (g x)) o frechet_derivative g (at x)" if "g differentiable at x" "f differentiable at (g x)" - apply (rule frechet_derivative_at') - apply (rule diff_chain_at) - apply (rule frechet_derivative_worksI) - apply (rule that) - apply (rule frechet_derivative_worksI) - apply (rule that) - done + by (meson diff_chain_at frechet_derivative_at' frechet_derivative_works that) lemma frechet_derivative_compose_eucl: "frechet_derivative (f o g) (at x) = (\v. \i\Basis. ((frechet_derivative g (at x) v) \ i) *\<^sub>R frechet_derivative f (at (g x)) i)" (is "?l = ?r") if "g differentiable at x" "f differentiable at (g x)" proof (rule ext) fix v interpret g: linear "frechet_derivative g (at x)" using that(1) by (rule linear_frechet_derivative) interpret f: linear "frechet_derivative f (at (g x))" using that(2) by (rule linear_frechet_derivative) have "frechet_derivative (f o g) (at x) v = frechet_derivative f (at (g x)) (\i\Basis. (frechet_derivative g (at x) v \ i) *\<^sub>R i)" unfolding frechet_derivative_compose[OF that] o_apply by (simp add: euclidean_representation) also have "\ = ?r v" by (auto simp: g.sum g.scaleR f.sum f.scaleR) finally show "?l v = ?r v" . qed lemma frechet_derivative_works_on_open: "f differentiable_on X \ open X \ x \ X \ (f has_derivative frechet_derivative f (at x)) (at x)" and frechet_derivative_works_on: "f differentiable_on X \ x \ X \ (f has_derivative frechet_derivative f (at x within X)) (at x within X)" by (auto simp: differentiable_onD differentiable_on_openD frechet_derivative_worksI) lemma frechet_derivative_inverse: "frechet_derivative (\x. inverse (f x)) (at x) = (\h. - 1 / (f x)\<^sup>2 * frechet_derivative f (at x) h)" if "f differentiable at x" "f x \ 0" for f::"_\_::real_normed_field" apply (rule frechet_derivative_at') using that by (auto intro!: derivative_eq_intros frechet_derivative_worksI simp: divide_simps algebra_simps power2_eq_square) lemma frechet_derivative_sqrt: "frechet_derivative (\x. sqrt (f x)) (at x) = (\v. (if f x > 0 then 1 else -1) / (2 * sqrt (f x)) * frechet_derivative f (at x) v)" if "f differentiable at x" "f x \ 0" apply (rule frechet_derivative_at') apply (rule sqrt_has_derivative[THEN has_derivative_eq_rhs]) by (auto intro!: frechet_derivative_worksI that simp: divide_simps) lemma frechet_derivative_norm: "frechet_derivative (\x. norm (f x)) (at x) = (\v. frechet_derivative f (at x) v \ sgn (f x))" if "f differentiable at x" "f x \ 0" for f::"_\_::real_inner" apply (rule frechet_derivative_at') by (auto intro!: derivative_eq_intros frechet_derivative_worksI that simp: divide_simps) lemma (in bounded_linear) frechet_derivative: "frechet_derivative f (at x) = f" apply (rule frechet_derivative_at') apply (rule has_derivative_eq_rhs) apply (rule has_derivative) by (auto intro!: derivative_eq_intros) bundle no_matrix_mult begin no_notation matrix_matrix_mult (infixl "**" 70) end lemma (in bounded_bilinear) frechet_derivative: includes no_matrix_mult shows "x differentiable at a \ y differentiable at a \ frechet_derivative (\a. x a ** y a) (at a) = (\h. x a ** frechet_derivative y (at a) h + frechet_derivative x (at a) h ** y a)" by (rule frechet_derivative_at') (auto intro!: FDERIV frechet_derivative_worksI) lemma frechet_derivative_divide: "frechet_derivative (\x. f x / g x) (at x) = (\h. frechet_derivative f (at x) h / (g x) -frechet_derivative g (at x) h * f x / (g x)\<^sup>2)" if "f differentiable at x" "g differentiable at x" "g x \ 0" for f::"_\_::real_normed_field" using that by (auto simp: divide_inverse_commute bounded_bilinear.frechet_derivative[OF bounded_bilinear_mult] frechet_derivative_inverse) lemma frechet_derivative_pair: "frechet_derivative (\x. (f x, g x)) (at x) = (\v. (frechet_derivative f (at x) v, frechet_derivative g (at x) v))" if "f differentiable (at x)" "g differentiable (at x)" apply (rule frechet_derivative_at') apply (rule derivative_eq_intros) apply (rule frechet_derivative_worksI) apply fact apply (rule frechet_derivative_worksI) apply fact .. lemma frechet_derivative_fst: "frechet_derivative (\x. fst (f x)) (at x) = (\xa. fst (frechet_derivative f (at x) xa))" if "(f differentiable at x)" for f::"_\(_::real_normed_vector \ _::real_normed_vector)" apply (rule frechet_derivative_at') using that by (auto intro!: derivative_eq_intros frechet_derivative_worksI) lemma frechet_derivative_snd: "frechet_derivative (\x. snd (f x)) (at x) = (\xa. snd (frechet_derivative f (at x) xa))" if "(f differentiable at x)" for f::"_\(_::real_normed_vector \ _::real_normed_vector)" apply (rule frechet_derivative_at') using that by (auto intro!: derivative_eq_intros frechet_derivative_worksI) lemma frechet_derivative_eq_vector_derivative_1: assumes "f differentiable at t" shows "frechet_derivative f (at t) 1 = vector_derivative f (at t)" apply (subst frechet_derivative_eq_vector_derivative) apply (rule assms) by auto subsection \Linear algebra\ lemma (in vector_space) dim_pos_finite_dimensional_vector_spaceE: assumes "dim (UNIV::'b set) > 0" obtains basis where "finite_dimensional_vector_space scale basis" proof - from assms obtain b where b: "local.span b = local.span UNIV" "local.independent b" by (auto simp: dim_def split: if_splits) then have "dim UNIV = card b" by (rule dim_eq_card) with assms have "finite b" by (auto simp: card_ge_0_finite) then have "finite_dimensional_vector_space scale b" by unfold_locales (auto simp: b) then show ?thesis .. qed context vector_space_on begin context includes lifting_syntax assumes "\(Rep::'s \ 'b) (Abs::'b \ 's). type_definition Rep Abs S" begin interpretation local_typedef_vector_space_on S scale "TYPE('s)" by unfold_locales fact lemmas_with [var_simplified explicit_ab_group_add, unoverload_type 'd, OF type.ab_group_add_axioms type_vector_space_on_with, folded dim_S_def, untransferred, var_simplified implicit_ab_group_add]: lt_dim_pos_finite_dimensional_vector_spaceE = vector_space.dim_pos_finite_dimensional_vector_spaceE end lemmas_with [cancel_type_definition, OF S_ne, folded subset_iff', simplified pred_fun_def, folded finite_dimensional_vector_space_on_with, simplified\\too much?\]: dim_pos_finite_dimensional_vector_spaceE = lt_dim_pos_finite_dimensional_vector_spaceE end subsection \Extensional function space\ text \f is zero outside A. We use such functions to canonically represent functions whose domain is A\ definition extensional0 :: "'a set \ ('a \ 'b::zero) \ bool" where "extensional0 A f = (\x. x \ A \ f x = 0)" lemma extensional0_0[intro, simp]: "extensional0 X 0" by (auto simp: extensional0_def) lemma extensional0_UNIV[intro, simp]: "extensional0 UNIV f" by (auto simp: extensional0_def) lemma ext_extensional0: "f = g" if "extensional0 S f" "extensional0 S g" "\x. x \ S \ f x = g x" using that by (force simp: extensional0_def fun_eq_iff) lemma extensional0_add[intro, simp]: "extensional0 S f \ extensional0 S g \ extensional0 S (f + g::_\'a::comm_monoid_add)" by (auto simp: extensional0_def) lemma extensinoal0_mult[intro, simp]: "extensional0 S x \ extensional0 S y \ extensional0 S (x * y)" for x y::"_\'a::mult_zero" by (auto simp: extensional0_def) lemma extensional0_scaleR[intro, simp]: "extensional0 S f \ extensional0 S (c *\<^sub>R f::_\'a::real_vector)" by (auto simp: extensional0_def) lemma extensional0_outside: "x \ S \ extensional0 S f \ f x = 0" by (auto simp: extensional0_def) lemma subspace_extensional0: "subspace (Collect (extensional0 X))" by (auto simp: subspace_def) text \Send the function f to its canonical representative as a function with domain A\ definition restrict0 :: "'a set \ ('a \ 'b::zero) \ 'a \ 'b" where "restrict0 A f x = (if x \ A then f x else 0)" lemma restrict0_UNIV[simp]: "restrict0 UNIV = (\x. x)" by (intro ext) (auto simp: restrict0_def) lemma extensional0_restrict0[intro, simp]: "extensional0 A (restrict0 A f)" by (auto simp: extensional0_def restrict0_def) lemma restrict0_times: "restrict0 A (x * y) = restrict0 A x * restrict0 A y" for x::"'a\'b::mult_zero" by (auto simp: restrict0_def[abs_def]) lemma restrict0_apply_in[simp]: "x \ A \ restrict0 A f x = f x" by (auto simp: restrict0_def) lemma restrict0_apply_out[simp]: "x \ A \ restrict0 A f x = 0" by (auto simp: restrict0_def) lemma restrict0_scaleR: "restrict0 A (c *\<^sub>R f::_\'a::real_vector) = c *\<^sub>R restrict0 A f" by (auto simp: restrict0_def[abs_def]) lemma restrict0_add: "restrict0 A (f + g::_\'a::real_vector) = restrict0 A f + restrict0 A g" by (auto simp: restrict0_def[abs_def]) lemma restrict0_restrict0: "restrict0 X (restrict0 Y f) = restrict0 (X \ Y) f" by (auto simp: restrict0_def) end