# HG changeset patch # User immler # Date 1519626845 -3600 # Node ID ce3e87a514884bbc9f306034e0d160c39b53516d # Parent 0cd2fd0c2dcfd49d1e3da7f87d985c13f000ed2e moved Lipschitz continuity from AFP/Ordinary_Differential_Equations and AFP/Gromov_Hyperbolicity; moved lemmas from AFP/Gromov_Hyperbolicity/Library_Complements diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Analysis/Analysis.thy --- a/src/HOL/Analysis/Analysis.thy Sun Feb 25 20:05:05 2018 +0100 +++ b/src/HOL/Analysis/Analysis.thy Mon Feb 26 07:34:05 2018 +0100 @@ -23,6 +23,7 @@ Generalised_Binomial_Theorem Gamma_Function Ball_Volume + Lipschitz begin end diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Analysis/Connected.thy --- a/src/HOL/Analysis/Connected.thy Sun Feb 25 20:05:05 2018 +0100 +++ b/src/HOL/Analysis/Connected.thy Mon Feb 26 07:34:05 2018 +0100 @@ -2727,6 +2727,13 @@ using diameter_bounded_bound[of s] diameter_lower_bounded[of s] assms by auto +lemma bounded_two_points: + "bounded S \ (\e. \x\S. \y\S. dist x y \ e)" + apply (rule iffI) + subgoal using diameter_bounded(1) by auto + subgoal using bounded_any_center[of S] by meson + done + lemma diameter_compact_attained: assumes "compact s" and "s \ {}" @@ -3797,6 +3804,14 @@ using assms homeomorphic_ball01_UNIV homeomorphic_balls(1) homeomorphic_trans zero_less_one by blast +text \Connectedness is invariant under homeomorphisms.\ + +lemma homeomorphic_connectedness: + assumes "s homeomorphic t" + shows "connected s \ connected t" +using assms unfolding homeomorphic_def homeomorphism_def by (metis connected_continuous_image) + + subsection\Inverse function property for open/closed maps\ lemma continuous_on_inverse_open_map: diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Analysis/Extended_Real_Limits.thy --- a/src/HOL/Analysis/Extended_Real_Limits.thy Sun Feb 25 20:05:05 2018 +0100 +++ b/src/HOL/Analysis/Extended_Real_Limits.thy Mon Feb 26 07:34:05 2018 +0100 @@ -936,6 +936,18 @@ subsubsection \Further limits\ +text \The assumptions of @{thm tendsto_diff_ereal} are too strong, we weaken them here.\ + +lemma tendsto_diff_ereal_general [tendsto_intros]: + fixes u v::"'a \ ereal" + assumes "(u \ l) F" "(v \ m) F" "\((l = \ \ m = \) \ (l = -\ \ m = -\))" + shows "((\n. u n - v n) \ l - m) F" +proof - + have "((\n. u n + (-v n)) \ l + (-m)) F" + apply (intro tendsto_intros assms) using assms by (auto simp add: ereal_uminus_eq_reorder) + then show ?thesis by (simp add: minus_ereal_def) +qed + lemma id_nat_ereal_tendsto_PInf [tendsto_intros]: "(\ n::nat. real n) \ \" by (simp add: filterlim_real_sequentially tendsto_PInfty_eq_at_top) @@ -1091,6 +1103,62 @@ qed(simp) +lemma continuous_ereal_abs: + "continuous_on (UNIV::ereal set) abs" +proof - + have "continuous_on ({..0} \ {(0::ereal)..}) abs" + apply (rule continuous_on_closed_Un, auto) + apply (rule iffD1[OF continuous_on_cong, of "{..0}" _ "\x. -x"]) + using less_eq_ereal_def apply (auto simp add: continuous_uminus_ereal) + apply (rule iffD1[OF continuous_on_cong, of "{0..}" _ "\x. x"]) + apply (auto simp add: continuous_on_id) + done + moreover have "(UNIV::ereal set) = {..0} \ {(0::ereal)..}" by auto + ultimately show ?thesis by auto +qed + +lemmas continuous_on_compose_ereal_abs[continuous_intros] = + continuous_on_compose2[OF continuous_ereal_abs _ subset_UNIV] + +lemma tendsto_abs_ereal [tendsto_intros]: + assumes "(u \ (l::ereal)) F" + shows "((\n. abs(u n)) \ abs l) F" +using continuous_ereal_abs assms by (metis UNIV_I continuous_on tendsto_compose) + +lemma ereal_minus_real_tendsto_MInf [tendsto_intros]: + "(\x. ereal (- real x)) \ - \" +by (subst uminus_ereal.simps(1)[symmetric], intro tendsto_intros) + + +subsection \Extended-Nonnegative-Real.thy\ + +lemma tendsto_diff_ennreal_general [tendsto_intros]: + fixes u v::"'a \ ennreal" + assumes "(u \ l) F" "(v \ m) F" "\(l = \ \ m = \)" + shows "((\n. u n - v n) \ l - m) F" +proof - + have "((\n. e2ennreal(enn2ereal(u n) - enn2ereal(v n))) \ e2ennreal(enn2ereal l - enn2ereal m)) F" + apply (intro tendsto_intros) using assms by auto + then show ?thesis by auto +qed + +lemma tendsto_mult_ennreal [tendsto_intros]: + fixes l m::ennreal + assumes "(u \ l) F" "(v \ m) F" "\((l = 0 \ m = \) \ (l = \ \ m = 0))" + shows "((\n. u n * v n) \ l * m) F" +proof - + have "((\n. e2ennreal(enn2ereal (u n) * enn2ereal (v n))) \ e2ennreal(enn2ereal l * enn2ereal m)) F" + apply (intro tendsto_intros) using assms apply auto + using enn2ereal_inject zero_ennreal.rep_eq by fastforce+ + moreover have "e2ennreal(enn2ereal (u n) * enn2ereal (v n)) = u n * v n" for n + by (subst times_ennreal.abs_eq[symmetric], auto simp add: eq_onp_same_args) + moreover have "e2ennreal(enn2ereal l * enn2ereal m) = l * m" + by (subst times_ennreal.abs_eq[symmetric], auto simp add: eq_onp_same_args) + ultimately show ?thesis + by auto +qed + + subsection \monoset\ definition (in order) mono_set: diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Analysis/Lipschitz.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Analysis/Lipschitz.thy Mon Feb 26 07:34:05 2018 +0100 @@ -0,0 +1,834 @@ +(* Title: HOL/Analysis/Lipschitz.thy + Author: Sébastien Gouëzel sebastien.gouezel@univ-rennes1.fr + Author: Fabian Immler, TU München +*) +section \Lipschitz continuity\ +theory Lipschitz + imports Borel_Space +begin + +definition lipschitz_on + where "lipschitz_on C U f \ (0 \ C \ (\x \ U. \y\U. dist (f x) (f y) \ C * dist x y))" + +bundle lipschitz_syntax begin +notation lipschitz_on ("_-lipschitz'_on" [1000]) +end +bundle no_lipschitz_syntax begin +no_notation lipschitz_on ("_-lipschitz'_on" [1000]) +end + +unbundle lipschitz_syntax + +lemma lipschitz_onI: "L-lipschitz_on X f" + if "\x y. x \ X \ y \ X \ dist (f x) (f y) \ L * dist x y" "0 \ L" + using that by (auto simp: lipschitz_on_def) + +lemma lipschitz_onD: + "dist (f x) (f y) \ L * dist x y" + if "L-lipschitz_on X f" "x \ X" "y \ X" + using that by (auto simp: lipschitz_on_def) + +lemma lipschitz_on_nonneg: + "0 \ L" if "L-lipschitz_on X f" + using that by (auto simp: lipschitz_on_def) + +lemma lipschitz_on_normD: + "norm (f x - f y) \ L * norm (x - y)" + if "lipschitz_on L X f" "x \ X" "y \ X" + using lipschitz_onD[OF that] + by (simp add: dist_norm) + +lemma lipschitz_on_mono: "L-lipschitz_on D f" if "M-lipschitz_on E f" "D \ E" "M \ L" + using that + by (force simp: lipschitz_on_def intro: order_trans[OF _ mult_right_mono]) + +lemmas lipschitz_on_subset = lipschitz_on_mono[OF _ _ order_refl] + and lipschitz_on_le = lipschitz_on_mono[OF _ order_refl] + +lemma lipschitz_on_leI: + "L-lipschitz_on X f" + if "\x y. x \ X \ y \ X \ x \ y \ dist (f x) (f y) \ L * dist x y" + "0 \ L" + for f::"'a::{linorder_topology, ordered_real_vector, metric_space} \ 'b::metric_space" +proof (rule lipschitz_onI) + fix x y assume xy: "x \ X" "y \ X" + consider "y \ x" | "x \ y" + by (rule le_cases) + then show "dist (f x) (f y) \ L * dist x y" + proof cases + case 1 + then have "dist (f y) (f x) \ L * dist y x" + by (auto intro!: that xy) + then show ?thesis + by (simp add: dist_commute) + qed (auto intro!: that xy) +qed fact + +lemma lipschitz_on_concat: + fixes a b c::real + assumes f: "L-lipschitz_on {a .. b} f" + assumes g: "L-lipschitz_on {b .. c} g" + assumes fg: "f b = g b" + shows "lipschitz_on L {a .. c} (\x. if x \ b then f x else g x)" + (is "lipschitz_on _ _ ?f") +proof (rule lipschitz_on_leI) + fix x y + assume x: "x \ {a..c}" and y: "y \ {a..c}" and xy: "x \ y" + consider "x \ b \ b < y" | "x \ b \ y \ b" by arith + then show "dist (?f x) (?f y) \ L * dist x y" + proof cases + case 1 + have "dist (f x) (g y) \ dist (f x) (f b) + dist (g b) (g y)" + unfolding fg by (rule dist_triangle) + also have "dist (f x) (f b) \ L * dist x b" + using 1 x + by (auto intro!: lipschitz_onD[OF f]) + also have "dist (g b) (g y) \ L * dist b y" + using 1 x y + by (auto intro!: lipschitz_onD[OF g] lipschitz_onD[OF f]) + finally have "dist (f x) (g y) \ L * dist x b + L * dist b y" + by simp + also have "\ = L * (dist x b + dist b y)" + by (simp add: algebra_simps) + also have "dist x b + dist b y = dist x y" + using 1 x y + by (auto simp: dist_real_def abs_real_def) + finally show ?thesis + using 1 by simp + next + case 2 + with lipschitz_onD[OF f, of x y] lipschitz_onD[OF g, of x y] x y xy + show ?thesis + by (auto simp: fg) + qed +qed (rule lipschitz_on_nonneg[OF f]) + +proposition lipschitz_on_concat_max: + fixes a b c::real + assumes f: "L-lipschitz_on {a .. b} f" + assumes g: "M-lipschitz_on {b .. c} g" + assumes fg: "f b = g b" + shows "(max L M)-lipschitz_on {a .. c} (\x. if x \ b then f x else g x)" +proof - + have "lipschitz_on (max L M) {a .. b} f" "lipschitz_on (max L M) {b .. c} g" + by (auto intro!: lipschitz_on_mono[OF f order_refl] lipschitz_on_mono[OF g order_refl]) + from lipschitz_on_concat[OF this fg] show ?thesis . +qed + + +subsubsection \Continuity\ + +lemma lipschitz_on_uniformly_continuous: + assumes "L-lipschitz_on X f" + shows "uniformly_continuous_on X f" + unfolding uniformly_continuous_on_def +proof safe + fix e::real + assume "0 < e" + from assms have l: "(L+1)-lipschitz_on X f" + by (rule lipschitz_on_mono) auto + show "\d>0. \x\X. \x'\X. dist x' x < d \ dist (f x') (f x) < e" + using lipschitz_onD[OF l] lipschitz_on_nonneg[OF assms] \0 < e\ + by (force intro!: exI[where x="e/(L + 1)"] simp: field_simps) +qed + +lemma lipschitz_on_continuous_on: + "continuous_on X f" if "L-lipschitz_on X f" + by (rule uniformly_continuous_imp_continuous[OF lipschitz_on_uniformly_continuous[OF that]]) + +lemma lipschitz_on_continuous_within: + "continuous (at x within X) f" if "L-lipschitz_on X f" "x \ X" + using lipschitz_on_continuous_on[OF that(1)] that(2) + by (auto simp: continuous_on_eq_continuous_within) + +subsubsection \Differentiable functions\ + +lemma bounded_derivative_imp_lipschitz: + assumes "\x. x \ X \ (f has_derivative f' x) (at x within X)" + assumes convex: "convex X" + assumes "\x. x \ X \ onorm (f' x) \ C" "0 \ C" + shows "C-lipschitz_on X f" +proof (rule lipschitz_onI) + show "\x y. x \ X \ y \ X \ dist (f x) (f y) \ C * dist x y" + by (auto intro!: assms differentiable_bound[unfolded dist_norm[symmetric], OF convex]) +qed fact + + +subsubsection \Structural introduction rules\ + +named_theorems lipschitz_intros "structural introduction rules for Lipschitz controls" + +lemma lipschitz_on_compose [lipschitz_intros]: + "(D * C)-lipschitz_on U (g o f)" + if f: "C-lipschitz_on U f" and g: "D-lipschitz_on (f`U) g" +proof (rule lipschitz_onI) + show "D* C \ 0" using lipschitz_on_nonneg[OF f] lipschitz_on_nonneg[OF g] by auto + fix x y assume H: "x \ U" "y \ U" + have "dist (g (f x)) (g (f y)) \ D * dist (f x) (f y)" + apply (rule lipschitz_onD[OF g]) using H by auto + also have "... \ D * C * dist x y" + using mult_left_mono[OF lipschitz_onD(1)[OF f H] lipschitz_on_nonneg[OF g]] by auto + finally show "dist ((g \ f) x) ((g \ f) y) \ D * C* dist x y" + unfolding comp_def by (auto simp add: mult.commute) +qed + +lemma lipschitz_on_compose2: + "(D * C)-lipschitz_on U (\x. g (f x))" + if "C-lipschitz_on U f" "D-lipschitz_on (f`U) g" + using lipschitz_on_compose[OF that] by (simp add: o_def) + +lemma lipschitz_on_cong[cong]: + "C-lipschitz_on U g \ D-lipschitz_on V f" + if "C = D" "U = V" "\x. x \ V \ g x = f x" + using that by (auto simp: lipschitz_on_def) + +lemma lipschitz_on_transform: + "C-lipschitz_on U g" + if "C-lipschitz_on U f" + "\x. x \ U \ g x = f x" + using that + by simp + +lemma lipschitz_on_empty_iff[simp]: "C-lipschitz_on {} f \ C \ 0" + by (auto simp: lipschitz_on_def) + +lemma lipschitz_on_insert_iff[simp]: + "C-lipschitz_on (insert y X) f \ + C-lipschitz_on X f \ (\x \ X. dist (f x) (f y) \ C * dist x y)" + by (auto simp: lipschitz_on_def dist_commute) + +lemma lipschitz_on_singleton [lipschitz_intros]: "C \ 0 \ C-lipschitz_on {x} f" + and lipschitz_on_empty [lipschitz_intros]: "C \ 0 \ C-lipschitz_on {} f" + by simp_all + +lemma lipschitz_on_id [lipschitz_intros]: "1-lipschitz_on U (\x. x)" + by (auto simp: lipschitz_on_def) + +lemma lipschitz_on_constant [lipschitz_intros]: "0-lipschitz_on U (\x. c)" + by (auto simp: lipschitz_on_def) + +lemma lipschitz_on_add [lipschitz_intros]: + fixes f::"'a::metric_space \'b::real_normed_vector" + assumes "C-lipschitz_on U f" + "D-lipschitz_on U g" + shows "(C+D)-lipschitz_on U (\x. f x + g x)" +proof (rule lipschitz_onI) + show "C + D \ 0" + using lipschitz_on_nonneg[OF assms(1)] lipschitz_on_nonneg[OF assms(2)] by auto + fix x y assume H: "x \ U" "y \ U" + have "dist (f x + g x) (f y + g y) \ dist (f x) (f y) + dist (g x) (g y)" + by (simp add: dist_triangle_add) + also have "... \ C * dist x y + D * dist x y" + using lipschitz_onD(1)[OF assms(1) H] lipschitz_onD(1)[OF assms(2) H] by auto + finally show "dist (f x + g x) (f y + g y) \ (C+D) * dist x y" by (auto simp add: algebra_simps) +qed + +lemma lipschitz_on_cmult [lipschitz_intros]: + fixes f::"'a::metric_space \ 'b::real_normed_vector" + assumes "C-lipschitz_on U f" + shows "(abs(a) * C)-lipschitz_on U (\x. a *\<^sub>R f x)" +proof (rule lipschitz_onI) + show "abs(a) * C \ 0" using lipschitz_on_nonneg[OF assms(1)] by auto + fix x y assume H: "x \ U" "y \ U" + have "dist (a *\<^sub>R f x) (a *\<^sub>R f y) = abs(a) * dist (f x) (f y)" + by (metis dist_norm norm_scaleR real_vector.scale_right_diff_distrib) + also have "... \ abs(a) * C * dist x y" + using lipschitz_onD(1)[OF assms(1) H] by (simp add: Groups.mult_ac(1) mult_left_mono) + finally show "dist (a *\<^sub>R f x) (a *\<^sub>R f y) \ \a\ * C * dist x y" by auto +qed + +lemma lipschitz_on_cmult_real [lipschitz_intros]: + fixes f::"'a::metric_space \ real" + assumes "C-lipschitz_on U f" + shows "(abs(a) * C)-lipschitz_on U (\x. a * f x)" + using lipschitz_on_cmult[OF assms] by auto + +lemma lipschitz_on_cmult_nonneg [lipschitz_intros]: + fixes f::"'a::metric_space \ 'b::real_normed_vector" + assumes "C-lipschitz_on U f" + "a \ 0" + shows "(a * C)-lipschitz_on U (\x. a *\<^sub>R f x)" + using lipschitz_on_cmult[OF assms(1), of a] assms(2) by auto + +lemma lipschitz_on_cmult_real_nonneg [lipschitz_intros]: + fixes f::"'a::metric_space \ real" + assumes "C-lipschitz_on U f" + "a \ 0" + shows "(a * C)-lipschitz_on U (\x. a * f x)" + using lipschitz_on_cmult_nonneg[OF assms] by auto + +lemma lipschitz_on_cmult_upper [lipschitz_intros]: + fixes f::"'a::metric_space \ 'b::real_normed_vector" + assumes "C-lipschitz_on U f" + "abs(a) \ D" + shows "(D * C)-lipschitz_on U (\x. a *\<^sub>R f x)" + apply (rule lipschitz_on_mono[OF lipschitz_on_cmult[OF assms(1), of a], of _ "D * C"]) + using assms(2) lipschitz_on_nonneg[OF assms(1)] mult_right_mono by auto + +lemma lipschitz_on_cmult_real_upper [lipschitz_intros]: + fixes f::"'a::metric_space \ real" + assumes "C-lipschitz_on U f" + "abs(a) \ D" + shows "(D * C)-lipschitz_on U (\x. a * f x)" + using lipschitz_on_cmult_upper[OF assms] by auto + +lemma lipschitz_on_minus[lipschitz_intros]: + fixes f::"'a::metric_space \'b::real_normed_vector" + assumes "C-lipschitz_on U f" + shows "C-lipschitz_on U (\x. - f x)" + by (metis (mono_tags, lifting) assms dist_minus lipschitz_on_def) + +lemma lipschitz_on_minus_iff[simp]: + "L-lipschitz_on X (\x. - f x) \ L-lipschitz_on X f" + "L-lipschitz_on X (- f) \ L-lipschitz_on X f" + for f::"'a::metric_space \'b::real_normed_vector" + using lipschitz_on_minus[of L X f] lipschitz_on_minus[of L X "-f"] + by auto + +lemma lipschitz_on_diff[lipschitz_intros]: + fixes f::"'a::metric_space \'b::real_normed_vector" + assumes "C-lipschitz_on U f" "D-lipschitz_on U g" + shows "(C + D)-lipschitz_on U (\x. f x - g x)" + using lipschitz_on_add[OF assms(1) lipschitz_on_minus[OF assms(2)]] by auto + +lemma lipschitz_on_closure [lipschitz_intros]: + assumes "C-lipschitz_on U f" "continuous_on (closure U) f" + shows "C-lipschitz_on (closure U) f" +proof (rule lipschitz_onI) + show "C \ 0" using lipschitz_on_nonneg[OF assms(1)] by simp + fix x y assume "x \ closure U" "y \ closure U" + obtain u v::"nat \ 'a" where *: "\n. u n \ U" "u \ x" + "\n. v n \ U" "v \ y" + using \x \ closure U\ \y \ closure U\ unfolding closure_sequential by blast + have a: "(\n. f (u n)) \ f x" + using *(1) *(2) \x \ closure U\ \continuous_on (closure U) f\ + unfolding comp_def continuous_on_closure_sequentially[of U f] by auto + have b: "(\n. f (v n)) \ f y" + using *(3) *(4) \y \ closure U\ \continuous_on (closure U) f\ + unfolding comp_def continuous_on_closure_sequentially[of U f] by auto + have l: "(\n. C * dist (u n) (v n) - dist (f (u n)) (f (v n))) \ C * dist x y - dist (f x) (f y)" + by (intro tendsto_intros * a b) + have "C * dist (u n) (v n) - dist (f (u n)) (f (v n)) \ 0" for n + using lipschitz_onD(1)[OF assms(1) \u n \ U\ \v n \ U\] by simp + then have "C * dist x y - dist (f x) (f y) \ 0" using LIMSEQ_le_const[OF l, of 0] by auto + then show "dist (f x) (f y) \ C * dist x y" by auto +qed + +lemma lipschitz_on_Pair[lipschitz_intros]: + assumes f: "L-lipschitz_on A f" + assumes g: "M-lipschitz_on A g" + shows "(sqrt (L\<^sup>2 + M\<^sup>2))-lipschitz_on A (\a. (f a, g a))" +proof (rule lipschitz_onI, goal_cases) + case (1 x y) + have "dist (f x, g x) (f y, g y) = sqrt ((dist (f x) (f y))\<^sup>2 + (dist (g x) (g y))\<^sup>2)" + by (auto simp add: dist_Pair_Pair real_le_lsqrt) + also have "\ \ sqrt ((L * dist x y)\<^sup>2 + (M * dist x y)\<^sup>2)" + by (auto intro!: real_sqrt_le_mono add_mono power_mono 1 lipschitz_onD f g) + also have "\ \ sqrt (L\<^sup>2 + M\<^sup>2) * dist x y" + by (auto simp: power_mult_distrib ring_distribs[symmetric] real_sqrt_mult) + finally show ?case . +qed simp + +lemma lipschitz_extend_closure: + fixes f::"('a::metric_space) \ ('b::complete_space)" + assumes "C-lipschitz_on U f" + shows "\g. C-lipschitz_on (closure U) g \ (\x\U. g x = f x)" +proof - + obtain g where g: "\x. x \ U \ g x = f x" "uniformly_continuous_on (closure U) g" + using uniformly_continuous_on_extension_on_closure[OF lipschitz_on_uniformly_continuous[OF assms]] by metis + have "C-lipschitz_on (closure U) g" + apply (rule lipschitz_on_closure, rule lipschitz_on_transform[OF assms]) + using g uniformly_continuous_imp_continuous[OF g(2)] by auto + then show ?thesis using g(1) by auto +qed + +lemma (in bounded_linear) lipschitz_boundE: + obtains B where "B-lipschitz_on A f" +proof - + from nonneg_bounded + obtain B where B: "B \ 0" "\x. norm (f x) \ B * norm x" + by (auto simp: ac_simps) + have "B-lipschitz_on A f" + by (auto intro!: lipschitz_onI B simp: dist_norm diff[symmetric]) + thus ?thesis .. +qed + + +subsection \Local Lipschitz continuity\ + +text \Given a function defined on a real interval, it is Lipschitz-continuous if and only if +it is locally so, as proved in the following lemmas. It is useful especially for +piecewise-defined functions: if each piece is Lipschitz, then so is the whole function. +The same goes for functions defined on geodesic spaces, or more generally on geodesic subsets +in a metric space (for instance convex subsets in a real vector space), and this follows readily +from the real case, but we will not prove it explicitly. + +We give several variations around this statement. This is essentially a connectedness argument.\ + +lemma locally_lipschitz_imp_lispchitz_aux: + fixes f::"real \ ('a::metric_space)" + assumes "a \ b" + "continuous_on {a..b} f" + "\x. x \ {a.. \y \ {x<..b}. dist (f y) (f x) \ M * (y-x)" + shows "dist (f b) (f a) \ M * (b-a)" +proof - + define A where "A = {x \ {a..b}. dist (f x) (f a) \ M * (x-a)}" + have *: "A = (\x. M * (x-a) - dist (f x) (f a))-`{0..} \ {a..b}" + unfolding A_def by auto + have "a \ A" unfolding A_def using \a \ b\ by auto + then have "A \ {}" by auto + moreover have "bdd_above A" unfolding A_def by auto + moreover have "closed A" unfolding * by (rule closed_vimage_Int, auto intro!: continuous_intros assms) + ultimately have "Sup A \ A" by (rule closed_contains_Sup) + have "Sup A = b" + proof (rule ccontr) + assume "Sup A \ b" + define x where "x = Sup A" + have I: "dist (f x) (f a) \ M * (x-a)" using \Sup A \ A\ x_def A_def by auto + have "x \ {a..Sup A \ A\ \Sup A \ b\ A_def by auto + then obtain y where J: "y \ {x<..b}" "dist (f y) (f x) \ M * (y-x)" using assms(3) by blast + have "dist (f y) (f a) \ dist (f y) (f x) + dist (f x) (f a)" by (rule dist_triangle) + also have "... \ M * (y-x) + M * (x-a)" using I J(2) by auto + finally have "dist (f y) (f a) \ M * (y-a)" by (auto simp add: algebra_simps) + then have "y \ A" unfolding A_def using \y \ {x<..b}\ \x \ {a.. by auto + then have "y \ Sup A" by (rule cSup_upper, auto simp: A_def) + then show False using \y \ {x<..b}\ x_def by auto + qed + then show ?thesis using \Sup A \ A\ A_def by auto +qed + +lemma locally_lipschitz_imp_lipschitz: + fixes f::"real \ ('a::metric_space)" + assumes "continuous_on {a..b} f" + "\x y. x \ {a.. y > x \ \z \ {x<..y}. dist (f z) (f x) \ M * (z-x)" + "M \ 0" + shows "lipschitz_on M {a..b} f" +proof (rule lipschitz_onI[OF _ \M \ 0\]) + have *: "dist (f t) (f s) \ M * (t-s)" if "s \ t" "s \ {a..b}" "t \ {a..b}" for s t + proof (rule locally_lipschitz_imp_lispchitz_aux, simp add: \s \ t\) + show "continuous_on {s..t} f" using continuous_on_subset[OF assms(1)] that by auto + fix x assume "x \ {s.. {a..z\{x<..t}. dist (f z) (f x) \ M * (z - x)" + using assms(2)[OF \x \ {a.., of t] \x \ {s.. by auto + qed + fix x y assume "x \ {a..b}" "y \ {a..b}" + consider "x \ y" | "y \ x" by linarith + then show "dist (f x) (f y) \ M * dist x y" + apply (cases) + using *[OF _ \x \ {a..b}\ \y \ {a..b}\] *[OF _ \y \ {a..b}\ \x \ {a..b}\] + by (auto simp add: dist_commute dist_real_def) +qed + +text \We deduce that if a function is Lipschitz on finitely many closed sets on the real line, then +it is Lipschitz on any interval contained in their union. The difficulty in the proof is to show +that any point $z$ in this interval (except the maximum) has a point arbitrarily close to it on its +right which is contained in a common initial closed set. Otherwise, we show that there is a small +interval $(z, T)$ which does not intersect any of the initial closed sets, a contradiction.\ + +proposition lipschitz_on_closed_Union: + assumes "\i. i \ I \ lipschitz_on M (U i) f" + "\i. i \ I \ closed (U i)" + "finite I" + "M \ 0" + "{u..(v::real)} \ (\i\I. U i)" + shows "lipschitz_on M {u..v} f" +proof (rule locally_lipschitz_imp_lipschitz[OF _ _ \M \ 0\]) + have *: "continuous_on (U i) f" if "i \ I" for i + by (rule lipschitz_on_continuous_on[OF assms(1)[OF \i\ I\]]) + have "continuous_on (\i\I. U i) f" + apply (rule continuous_on_closed_Union) using \finite I\ * assms(2) by auto + then show "continuous_on {u..v} f" + using \{u..(v::real)} \ (\i\I. U i)\ continuous_on_subset by auto + + fix z Z assume z: "z \ {u.. v" by auto + define T where "T = min Z v" + then have T: "T > z" "T \ v" "T \ u" "T \ Z" using z by auto + define A where "A = (\i\ I \ {i. U i \ {z<..T} \ {}}. U i \ {z..T})" + have a: "closed A" + unfolding A_def apply (rule closed_UN) using \finite I\ \\i. i \ I \ closed (U i)\ by auto + have b: "bdd_below A" unfolding A_def using \finite I\ by auto + have "\i \ I. T \ U i" using \{u..v} \ (\i\I. U i)\ T by auto + then have c: "T \ A" unfolding A_def using T by (auto, fastforce) + have "Inf A \ z" + apply (rule cInf_greatest, auto) using c unfolding A_def by auto + moreover have "Inf A \ z" + proof (rule ccontr) + assume "\(Inf A \ z)" + then obtain w where w: "w > z" "w < Inf A" by (meson dense not_le_imp_less) + have "Inf A \ T" using a b c by (simp add: cInf_lower) + then have "w \ T" using w by auto + then have "w \ {u..v}" using w \z \ {u.. T by auto + then obtain j where j: "j \ I" "w \ U j" using \{u..v} \ (\i\I. U i)\ by fastforce + then have "w \ U j \ {z..T}" "U j \ {z<..T} \ {}" using j T w \w \ T\ by auto + then have "w \ A" unfolding A_def using \j \ I\ by auto + then have "Inf A \ w" using a b by (simp add: cInf_lower) + then show False using w by auto + qed + ultimately have "Inf A = z" by simp + moreover have "Inf A \ A" + apply (rule closed_contains_Inf) using a b c by auto + ultimately have "z \ A" by simp + then obtain i where i: "i \ I" "U i \ {z<..T} \ {}" "z \ U i" unfolding A_def by auto + then obtain t where "t \ U i \ {z<..T}" by blast + then have "dist (f t) (f z) \ M * (t - z)" + using lipschitz_onD(1)[OF assms(1)[of i], of t z] i dist_real_def by auto + then show "\t\{z<..Z}. dist (f t) (f z) \ M * (t - z)" using \T \ Z\ \t \ U i \ {z<..T}\ by auto +qed + + +subsection \Local Lipschitz continuity (uniform for a family of functions)\ + +definition local_lipschitz:: + "'a::metric_space set \ 'b::metric_space set \ ('a \ 'b \ 'c::metric_space) \ bool" + where + "local_lipschitz T X f \ \x \ X. \t \ T. + \u>0. \L. \t \ cball t u \ T. L-lipschitz_on (cball x u \ X) (f t)" + +lemma local_lipschitzI: + assumes "\t x. t \ T \ x \ X \ \u>0. \L. \t \ cball t u \ T. L-lipschitz_on (cball x u \ X) (f t)" + shows "local_lipschitz T X f" + using assms + unfolding local_lipschitz_def + by auto + +lemma local_lipschitzE: + assumes local_lipschitz: "local_lipschitz T X f" + assumes "t \ T" "x \ X" + obtains u L where "u > 0" "\s. s \ cball t u \ T \ L-lipschitz_on (cball x u \ X) (f s)" + using assms local_lipschitz_def + by metis + +lemma local_lipschitz_continuous_on: + assumes local_lipschitz: "local_lipschitz T X f" + assumes "t \ T" + shows "continuous_on X (f t)" + unfolding continuous_on_def +proof safe + fix x assume "x \ X" + from local_lipschitzE[OF local_lipschitz \t \ T\ \x \ X\] obtain u L + where "0 < u" + and L: "\s. s \ cball t u \ T \ L-lipschitz_on (cball x u \ X) (f s)" + by metis + have "x \ ball x u" using \0 < u\ by simp + from lipschitz_on_continuous_on[OF L] + have tendsto: "(f t \ f t x) (at x within cball x u \ X)" + using \0 < u\ \x \ X\ \t \ T\ + by (auto simp: continuous_on_def) + moreover have "\\<^sub>F xa in at x. (xa \ cball x u \ X) = (xa \ X)" + using eventually_at_ball[OF \0 < u\, of x UNIV] + by eventually_elim auto + ultimately show "(f t \ f t x) (at x within X)" + by (rule Lim_transform_within_set) +qed + +lemma + local_lipschitz_compose1: + assumes ll: "local_lipschitz (g ` T) X (\t. f t)" + assumes g: "continuous_on T g" + shows "local_lipschitz T X (\t. f (g t))" +proof (rule local_lipschitzI) + fix t x + assume "t \ T" "x \ X" + then have "g t \ g ` T" by simp + from local_lipschitzE[OF assms(1) this \x \ X\] + obtain u L where "0 < u" and l: "(\s. s \ cball (g t) u \ g ` T \ L-lipschitz_on (cball x u \ X) (f s))" + by auto + from g[unfolded continuous_on_eq_continuous_within, rule_format, OF \t \ T\, + unfolded continuous_within_eps_delta, rule_format, OF \0 < u\] + obtain d where d: "d>0" "\x'. x'\T \ dist x' t < d \ dist (g x') (g t) < u" + by (auto) + show "\u>0. \L. \t\cball t u \ T. L-lipschitz_on (cball x u \ X) (f (g t))" + using d \0 < u\ + by (fastforce intro: exI[where x="(min d u)/2"] exI[where x=L] + intro!: less_imp_le[OF d(2)] lipschitz_on_subset[OF l] simp: dist_commute mem_ball mem_cball) +qed + +context + fixes T::"'a::metric_space set" and X f + assumes local_lipschitz: "local_lipschitz T X f" +begin + +lemma continuous_on_TimesI: + assumes y: "\x. x \ X \ continuous_on T (\t. f t x)" + shows "continuous_on (T \ X) (\(t, x). f t x)" + unfolding continuous_on_iff +proof (safe, simp) + fix a b and e::real + assume H: "a \ T" "b \ X" "0 < e" + hence "0 < e/2" by simp + from y[unfolded continuous_on_iff, OF \b \ X\, rule_format, OF \a \ T\ \0 < e/2\] + obtain d where d: "d > 0" "\t. t \ T \ dist t a < d \ dist (f t b) (f a b) < e/2" + by auto + + from \a : T\ \b \ X\ + obtain u L where u: "0 < u" + and L: "\t. t \ cball a u \ T \ L-lipschitz_on (cball b u \ X) (f t)" + by (erule local_lipschitzE[OF local_lipschitz]) + + have "a \ cball a u \ T" by (auto simp: \0 < u\ \a \ T\ less_imp_le) + from lipschitz_on_nonneg[OF L[OF \a \ cball _ _ \ _\]] have "0 \ L" . + + let ?d = "Min {d, u, (e/2/(L + 1))}" + show "\d>0. \x\T. \y\X. dist (x, y) (a, b) < d \ dist (f x y) (f a b) < e" + proof (rule exI[where x = ?d], safe) + show "0 < ?d" + using \0 \ L\ \0 < u\ \0 < e\ \0 < d\ + by (auto intro!: divide_pos_pos ) + fix x y + assume "x \ T" "y \ X" + assume dist_less: "dist (x, y) (a, b) < ?d" + have "dist y b \ dist (x, y) (a, b)" + using dist_snd_le[of "(x, y)" "(a, b)"] + by auto + also + note dist_less + also + { + note calculation + also have "?d \ u" by simp + finally have "dist y b < u" . + } + have "?d \ e/2/(L + 1)" by simp + also have "(L + 1) * \ \ e / 2" + using \0 < e\ \L \ 0\ + by (auto simp: divide_simps) + finally have le1: "(L + 1) * dist y b < e / 2" using \L \ 0\ by simp + + have "dist x a \ dist (x, y) (a, b)" + using dist_fst_le[of "(x, y)" "(a, b)"] + by auto + also note dist_less + finally have "dist x a < ?d" . + also have "?d \ d" by simp + finally have "dist x a < d" . + note \dist x a < ?d\ + also have "?d \ u" by simp + finally have "dist x a < u" . + then have "x \ cball a u \ T" + using \x \ T\ + by (auto simp: dist_commute mem_cball) + have "dist (f x y) (f a b) \ dist (f x y) (f x b) + dist (f x b) (f a b)" + by (rule dist_triangle) + also have "(L + 1)-lipschitz_on (cball b u \ X) (f x)" + using L[OF \x \ cball a u \ T\] + by (rule lipschitz_on_le) simp + then have "dist (f x y) (f x b) \ (L + 1) * dist y b" + apply (rule lipschitz_onD) + subgoal + using \y \ X\ \dist y b < u\ + by (simp add: dist_commute) + subgoal + using \0 < u\ \b \ X\ + by (simp add: ) + done + also have "(L + 1) * dist y b \ e / 2" + using le1 \0 \ L\ by simp + also have "dist (f x b) (f a b) < e / 2" + by (rule d; fact) + also have "e / 2 + e / 2 = e" by simp + finally show "dist (f x y) (f a b) < e" by simp + qed +qed + +lemma local_lipschitz_compact_implies_lipschitz: + assumes "compact X" "compact T" + assumes cont: "\x. x \ X \ continuous_on T (\t. f t x)" + obtains L where "\t. t \ T \ L-lipschitz_on X (f t)" +proof - + { + assume *: "\n::nat. \(\t\T. n-lipschitz_on X (f t))" + { + fix n::nat + from *[of n] have "\x y t. t \ T \ x \ X \ y \ X \ dist (f t y) (f t x) > n * dist y x" + by (force simp: lipschitz_on_def) + } then obtain t and x y::"nat \ 'b" where xy: "\n. x n \ X" "\n. y n \ X" + and t: "\n. t n \ T" + and d: "\n. dist (f (t n) (y n)) (f (t n) (x n)) > n * dist (y n) (x n)" + by metis + from xy assms obtain lx rx where lx': "lx \ X" "strict_mono (rx :: nat \ nat)" "(x o rx) \ lx" + by (metis compact_def) + with xy have "\n. (y o rx) n \ X" by auto + with assms obtain ly ry where ly': "ly \ X" "strict_mono (ry :: nat \ nat)" "((y o rx) o ry) \ ly" + by (metis compact_def) + with t have "\n. ((t o rx) o ry) n \ T" by simp + with assms obtain lt rt where lt': "lt \ T" "strict_mono (rt :: nat \ nat)" "(((t o rx) o ry) o rt) \ lt" + by (metis compact_def) + from lx' ly' + have lx: "(x o (rx o ry o rt)) \ lx" (is "?x \ _") + and ly: "(y o (rx o ry o rt)) \ ly" (is "?y \ _") + and lt: "(t o (rx o ry o rt)) \ lt" (is "?t \ _") + subgoal by (simp add: LIMSEQ_subseq_LIMSEQ o_assoc lt'(2)) + subgoal by (simp add: LIMSEQ_subseq_LIMSEQ ly'(3) o_assoc lt'(2)) + subgoal by (simp add: o_assoc lt'(3)) + done + hence "(\n. dist (?y n) (?x n)) \ dist ly lx" + by (metis tendsto_dist) + moreover + let ?S = "(\(t, x). f t x) ` (T \ X)" + have "eventually (\n::nat. n > 0) sequentially" + by (metis eventually_at_top_dense) + hence "eventually (\n. norm (dist (?y n) (?x n)) \ norm (\diameter ?S\ / n) * 1) sequentially" + proof eventually_elim + case (elim n) + have "0 < rx (ry (rt n))" using \0 < n\ + by (metis dual_order.strict_trans1 lt'(2) lx'(2) ly'(2) seq_suble) + have compact: "compact ?S" + by (auto intro!: compact_continuous_image continuous_on_subset[OF continuous_on_TimesI] + compact_Times \compact X\ \compact T\ cont) + have "norm (dist (?y n) (?x n)) = dist (?y n) (?x n)" by simp + also + from this elim d[of "rx (ry (rt n))"] + have "\ < dist (f (?t n) (?y n)) (f (?t n) (?x n)) / rx (ry (rt (n)))" + using lx'(2) ly'(2) lt'(2) \0 < rx _\ + by (auto simp add: divide_simps algebra_simps strict_mono_def) + also have "\ \ diameter ?S / n" + by (force intro!: \0 < n\ strict_mono_def xy diameter_bounded_bound frac_le + compact_imp_bounded compact t + intro: le_trans[OF seq_suble[OF lt'(2)]] + le_trans[OF seq_suble[OF ly'(2)]] + le_trans[OF seq_suble[OF lx'(2)]]) + also have "\ \ abs (diameter ?S) / n" + by (auto intro!: divide_right_mono) + finally show ?case by simp + qed + with _ have "(\n. dist (?y n) (?x n)) \ 0" + by (rule tendsto_0_le) + (metis tendsto_divide_0[OF tendsto_const] filterlim_at_top_imp_at_infinity + filterlim_real_sequentially) + ultimately have "lx = ly" + using LIMSEQ_unique by fastforce + with assms lx' have "lx \ X" by auto + from \lt \ T\ this obtain u L where L: "u > 0" "\t. t \ cball lt u \ T \ L-lipschitz_on (cball lx u \ X) (f t)" + by (erule local_lipschitzE[OF local_lipschitz]) + hence "L \ 0" by (force intro!: lipschitz_on_nonneg \lt \ T\) + + from L lt ly lx \lx = ly\ + have + "eventually (\n. ?t n \ ball lt u) sequentially" + "eventually (\n. ?y n \ ball lx u) sequentially" + "eventually (\n. ?x n \ ball lx u) sequentially" + by (auto simp: dist_commute Lim mem_ball) + moreover have "eventually (\n. n > L) sequentially" + by (metis filterlim_at_top_dense filterlim_real_sequentially) + ultimately + have "eventually (\_. False) sequentially" + proof eventually_elim + case (elim n) + hence "dist (f (?t n) (?y n)) (f (?t n) (?x n)) \ L * dist (?y n) (?x n)" + using assms xy t + unfolding dist_norm[symmetric] + by (intro lipschitz_onD[OF L(2)]) (auto simp: mem_ball mem_cball) + also have "\ \ n * dist (?y n) (?x n)" + using elim by (intro mult_right_mono) auto + also have "\ \ rx (ry (rt n)) * dist (?y n) (?x n)" + by (intro mult_right_mono[OF _ zero_le_dist]) + (meson lt'(2) lx'(2) ly'(2) of_nat_le_iff order_trans seq_suble) + also have "\ < dist (f (?t n) (?y n)) (f (?t n) (?x n))" + by (auto intro!: d) + finally show ?case by simp + qed + hence False + by simp + } then obtain L where "\t. t \ T \ L-lipschitz_on X (f t)" + by metis + thus ?thesis .. +qed + +lemma local_lipschitz_subset: + assumes "S \ T" "Y \ X" + shows "local_lipschitz S Y f" +proof (rule local_lipschitzI) + fix t x assume "t \ S" "x \ Y" + then have "t \ T" "x \ X" using assms by auto + from local_lipschitzE[OF local_lipschitz, OF this] + obtain u L where u: "0 < u" and L: "\s. s \ cball t u \ T \ L-lipschitz_on (cball x u \ X) (f s)" + by blast + show "\u>0. \L. \t\cball t u \ S. L-lipschitz_on (cball x u \ Y) (f t)" + using assms + by (auto intro: exI[where x=u] exI[where x=L] + intro!: u lipschitz_on_subset[OF _ Int_mono[OF order_refl \Y \ X\]] L) +qed + +end + +lemma local_lipschitz_minus: + fixes f::"'a::metric_space \ 'b::metric_space \ 'c::real_normed_vector" + shows "local_lipschitz T X (\t x. - f t x) = local_lipschitz T X f" + by (auto simp: local_lipschitz_def lipschitz_on_minus) + +lemma local_lipschitz_PairI: + assumes f: "local_lipschitz A B (\a b. f a b)" + assumes g: "local_lipschitz A B (\a b. g a b)" + shows "local_lipschitz A B (\a b. (f a b, g a b))" +proof (rule local_lipschitzI) + fix t x assume "t \ A" "x \ B" + from local_lipschitzE[OF f this] local_lipschitzE[OF g this] + obtain u L v M where "0 < u" "(\s. s \ cball t u \ A \ L-lipschitz_on (cball x u \ B) (f s))" + "0 < v" "(\s. s \ cball t v \ A \ M-lipschitz_on (cball x v \ B) (g s))" + by metis + then show "\u>0. \L. \t\cball t u \ A. L-lipschitz_on (cball x u \ B) (\b. (f t b, g t b))" + by (intro exI[where x="min u v"]) + (force intro: lipschitz_on_subset intro!: lipschitz_on_Pair simp: mem_cball) +qed + +lemma local_lipschitz_constI: "local_lipschitz S T (\t x. f t)" + by (auto simp: intro!: local_lipschitzI lipschitz_on_constant intro: exI[where x=1]) + +lemma (in bounded_linear) local_lipschitzI: + shows "local_lipschitz A B (\_. f)" +proof (rule local_lipschitzI, goal_cases) + case (1 t x) + from lipschitz_boundE[of "(cball x 1 \ B)"] obtain C where "C-lipschitz_on (cball x 1 \ B) f" by auto + then show ?case + by (auto intro: exI[where x=1]) +qed + +lemma c1_implies_local_lipschitz: + fixes T::"real set" and X::"'a::{banach,heine_borel} set" + and f::"real \ 'a \ 'a" + assumes f': "\t x. t \ T \ x \ X \ (f t has_derivative blinfun_apply (f' (t, x))) (at x)" + assumes cont_f': "continuous_on (T \ X) f'" + assumes "open T" + assumes "open X" + shows "local_lipschitz T X f" +proof (rule local_lipschitzI) + fix t x + assume "t \ T" "x \ X" + from open_contains_cball[THEN iffD1, OF \open X\, rule_format, OF \x \ X\] + obtain u where u: "u > 0" "cball x u \ X" by auto + moreover + from open_contains_cball[THEN iffD1, OF \open T\, rule_format, OF \t \ T\] + obtain v where v: "v > 0" "cball t v \ T" by auto + ultimately + have "compact (cball t v \ cball x u)" "cball t v \ cball x u \ T \ X" + by (auto intro!: compact_Times) + then have "compact (f' ` (cball t v \ cball x u))" + by (auto intro!: compact_continuous_image continuous_on_subset[OF cont_f']) + then obtain B where B: "B > 0" "\s y. s \ cball t v \ y \ cball x u \ norm (f' (s, y)) \ B" + by (auto dest!: compact_imp_bounded simp: bounded_pos simp: mem_ball) + + have lipschitz: "B-lipschitz_on (cball x (min u v) \ X) (f s)" if s: "s \ cball t v" for s + proof - + note s + also note \cball t v \ T\ + finally + have deriv: "\y\cball x u. (f s has_derivative blinfun_apply (f' (s, y))) (at y within cball x u)" + using \_ \ X\ + by (auto intro!: has_derivative_at_within[OF f']) + have "norm (f s y - f s z) \ B * norm (y - z)" + if "y \ cball x u" "z \ cball x u" + for y z + using s that + by (intro differentiable_bound[OF convex_cball deriv]) + (auto intro!: B simp: norm_blinfun.rep_eq[symmetric] mem_cball) + then show ?thesis + using \0 < B\ + by (auto intro!: lipschitz_onI simp: dist_norm mem_cball) + qed + show "\u>0. \L. \t\cball t u \ T. L-lipschitz_on (cball x u \ X) (f t)" + by (force intro: exI[where x="min u v"] exI[where x=B] intro!: lipschitz simp: u v mem_cball) +qed + +end diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Analysis/Topology_Euclidean_Space.thy --- a/src/HOL/Analysis/Topology_Euclidean_Space.thy Sun Feb 25 20:05:05 2018 +0100 +++ b/src/HOL/Analysis/Topology_Euclidean_Space.thy Mon Feb 26 07:34:05 2018 +0100 @@ -2527,6 +2527,14 @@ \ connected S \ (\A B. closed A \ closed B \ A \ {} \ B \ {} \ A \ B = S \ A \ B = {})" unfolding connected_closedin_eq closedin_closed_eq connected_closedin_eq by blast +text \If a connnected set is written as the union of two nonempty closed sets, then these sets +have to intersect.\ + +lemma connected_as_closed_union: + assumes "connected C" "C = A \ B" "closed A" "closed B" "A \ {}" "B \ {}" + shows "A \ B \ {}" +by (metis assms closed_Un connected_closed_set) + lemma closedin_subset_trans: "closedin (subtopology euclidean U) S \ S \ T \ T \ U \ closedin (subtopology euclidean T) S" @@ -3285,6 +3293,11 @@ unfolding closure_approachable using dense by force +lemma closure_approachableD: + assumes "x \ closure S" "e>0" + shows "\y\S. dist x y < e" + using assms unfolding closure_approachable by (auto simp add: dist_commute) + lemma closed_approachable: fixes S :: "'a::metric_space set" shows "closed S \ (\e>0. \y\S. dist y x < e) \ x \ S" @@ -5249,38 +5262,48 @@ text \Characterization of various kinds of continuity in terms of sequences.\ +lemma continuous_within_sequentiallyI: + fixes f :: "'a::{first_countable_topology, t2_space} \ 'b::topological_space" + assumes "\u::nat \ 'a. u \ a \ (\n. u n \ s) \ (\n. f (u n)) \ f a" + shows "continuous (at a within s) f" + using assms unfolding continuous_within tendsto_def[where l = "f a"] + by (auto intro!: sequentially_imp_eventually_within) + +lemma continuous_within_tendsto_compose: + fixes f::"'a::t2_space \ 'b::topological_space" + assumes "continuous (at a within s) f" + "eventually (\n. x n \ s) F" + "(x \ a) F " + shows "((\n. f (x n)) \ f a) F" +proof - + have *: "filterlim x (inf (nhds a) (principal s)) F" + using assms(2) assms(3) unfolding at_within_def filterlim_inf by (auto simp add: filterlim_principal eventually_mono) + show ?thesis + by (auto simp add: assms(1) continuous_within[symmetric] tendsto_at_within_iff_tendsto_nhds[symmetric] intro!: filterlim_compose[OF _ *]) +qed + +lemma continuous_within_tendsto_compose': + fixes f::"'a::t2_space \ 'b::topological_space" + assumes "continuous (at a within s) f" + "\n. x n \ s" + "(x \ a) F " + shows "((\n. f (x n)) \ f a) F" + by (auto intro!: continuous_within_tendsto_compose[OF assms(1)] simp add: assms) + lemma continuous_within_sequentially: - fixes f :: "'a::metric_space \ 'b::topological_space" + fixes f :: "'a::{first_countable_topology, t2_space} \ 'b::topological_space" shows "continuous (at a within s) f \ (\x. (\n::nat. x n \ s) \ (x \ a) sequentially \ ((f \ x) \ f a) sequentially)" - (is "?lhs = ?rhs") -proof - assume ?lhs - { - fix x :: "nat \ 'a" - assume x: "\n. x n \ s" "\e>0. eventually (\n. dist (x n) a < e) sequentially" - fix T :: "'b set" - assume "open T" and "f a \ T" - with \?lhs\ obtain d where "d>0" and d:"\x\s. 0 < dist x a \ dist x a < d \ f x \ T" - unfolding continuous_within tendsto_def eventually_at by auto - have "eventually (\n. dist (x n) a < d) sequentially" - using x(2) \d>0\ by simp - then have "eventually (\n. (f \ x) n \ T) sequentially" - proof eventually_elim - case (elim n) - then show ?case - using d x(1) \f a \ T\ by auto - qed - } - then show ?rhs - unfolding tendsto_iff tendsto_def by simp -next - assume ?rhs - then show ?lhs - unfolding continuous_within tendsto_def [where l="f a"] - by (simp add: sequentially_imp_eventually_within) -qed + using continuous_within_tendsto_compose'[of a s f _ sequentially] + continuous_within_sequentiallyI[of a s f] + by (auto simp: o_def) + +lemma continuous_at_sequentiallyI: + fixes f :: "'a::{first_countable_topology, t2_space} \ 'b::topological_space" + assumes "\u. u \ a \ (\n. f (u n)) \ f a" + shows "continuous (at a) f" + using continuous_within_sequentiallyI[of a UNIV f] assms by auto lemma continuous_at_sequentially: fixes f :: "'a::metric_space \ 'b::topological_space" @@ -5288,12 +5311,19 @@ (\x. (x \ a) sequentially --> ((f \ x) \ f a) sequentially)" using continuous_within_sequentially[of a UNIV f] by simp +lemma continuous_on_sequentiallyI: + fixes f :: "'a::{first_countable_topology, t2_space} \ 'b::topological_space" + assumes "\u a. (\n. u n \ s) \ a \ s \ u \ a \ (\n. f (u n)) \ f a" + shows "continuous_on s f" + using assms unfolding continuous_on_eq_continuous_within + using continuous_within_sequentiallyI[of _ s f] by auto + lemma continuous_on_sequentially: fixes f :: "'a::metric_space \ 'b::topological_space" shows "continuous_on s f \ (\x. \a \ s. (\n. x(n) \ s) \ (x \ a) sequentially --> ((f \ x) \ f a) sequentially)" - (is "?lhs = ?rhs") + (is "?lhs = ?rhs") proof assume ?rhs then show ?lhs diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Lattices.thy --- a/src/HOL/Lattices.thy Sun Feb 25 20:05:05 2018 +0100 +++ b/src/HOL/Lattices.thy Mon Feb 26 07:34:05 2018 +0100 @@ -757,6 +757,11 @@ end +lemma max_of_antimono: "antimono f \ max (f x) (f y) = f (min x y)" + and min_of_antimono: "antimono f \ min (f x) (f y) = f (max x y)" + for f::"'a::linorder \ 'b::linorder" + by (auto simp: antimono_def Orderings.max_def min_def intro!: antisym) + lemma inf_min: "inf = (min :: 'a::{semilattice_inf,linorder} \ 'a \ 'a)" by (auto intro: antisym simp add: min_def fun_eq_iff) diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Library/Extended_Nonnegative_Real.thy --- a/src/HOL/Library/Extended_Nonnegative_Real.thy Sun Feb 25 20:05:05 2018 +0100 +++ b/src/HOL/Library/Extended_Nonnegative_Real.thy Mon Feb 26 07:34:05 2018 +0100 @@ -1547,11 +1547,32 @@ by (rule continuous_on_tendsto_compose[where g=f, OF ennreal_continuous_on_cmult, where s=UNIV]) (auto simp: continuous_on_id) -lemma tendsto_ennrealI[intro, simp]: +lemma tendsto_ennrealI[intro, simp, tendsto_intros]: "(f \ x) F \ ((\x. ennreal (f x)) \ ennreal x) F" by (auto simp: ennreal_def intro!: continuous_on_tendsto_compose[OF continuous_on_e2ennreal[of UNIV]] tendsto_max) +lemma tendsto_enn2erealI [tendsto_intros]: + assumes "(f \ l) F" + shows "((\i. enn2ereal(f i)) \ enn2ereal l) F" +using tendsto_enn2ereal_iff assms by auto + +lemma tendsto_e2ennrealI [tendsto_intros]: + assumes "(f \ l) F" + shows "((\i. e2ennreal(f i)) \ e2ennreal l) F" +proof - + have *: "e2ennreal (max x 0) = e2ennreal x" for x + by (simp add: e2ennreal_def max.commute) + have "((\i. max (f i) 0) \ max l 0) F" + apply (intro tendsto_intros) using assms by auto + then have "((\i. enn2ereal(e2ennreal (max (f i) 0))) \ enn2ereal (e2ennreal (max l 0))) F" + by (subst enn2ereal_e2ennreal, auto)+ + then have "((\i. e2ennreal (max (f i) 0)) \ e2ennreal (max l 0)) F" + using tendsto_enn2ereal_iff by auto + then show ?thesis + unfolding * by auto +qed + lemma ennreal_suminf_minus: fixes f g :: "nat \ ennreal" shows "(\i. g i \ f i) \ suminf f \ top \ suminf g \ top \ (\i. f i - g i) = suminf f - suminf g" @@ -1914,6 +1935,18 @@ shows "a - b = a - c \ (b = c \ (a \ b \ a \ c) \ a = top)" by (cases a; cases b; cases c) (auto simp: ennreal_minus_if) +text \The next lemma is wrong for $a = top$, for $b = c = 1$ for instance.\ + +lemma ennreal_right_diff_distrib: + fixes a b c::ennreal + assumes "a \ top" + shows "a * (b - c) = a * b - a * c" + apply (cases a, cases b, cases c, auto simp add: assms) + apply (metis (mono_tags, lifting) ennreal_minus ennreal_mult' linordered_field_class.sign_simps(38) split_mult_pos_le) + apply (metis ennreal_minus_zero ennreal_mult_cancel_left ennreal_top_eq_mult_iff minus_top_ennreal mult_eq_0_iff top_neq_ennreal) + apply (metis ennreal_minus_eq_top ennreal_minus_zero ennreal_mult_eq_top_iff mult_eq_0_iff) + done + lemma SUP_diff_ennreal: "c < top \ (SUP i:I. f i - c :: ennreal) = (SUP i:I. f i) - c" by (auto intro!: SUP_eqI ennreal_minus_mono SUP_least intro: SUP_upper @@ -1950,14 +1983,7 @@ lemma enn2real_eq_0_iff: "enn2real x = 0 \ x = 0 \ x = top" by (cases x) auto -lemma (in -) continuous_on_diff_ereal: - "continuous_on A f \ continuous_on A g \ (\x. x \ A \ \f x\ \ \) \ (\x. x \ A \ \g x\ \ \) \ continuous_on A (\z. f z - g z::ereal)" - apply (auto simp: continuous_on_def) - apply (intro tendsto_diff_ereal) - apply metis+ - done - -lemma (in -) continuous_on_diff_ennreal: +lemma continuous_on_diff_ennreal: "continuous_on A f \ continuous_on A g \ (\x. x \ A \ f x \ top) \ (\x. x \ A \ g x \ top) \ continuous_on A (\z. f z - g z::ennreal)" including ennreal.lifting proof (transfer fixing: A, simp add: top_ereal_def) @@ -1967,10 +1993,20 @@ by (intro continuous_on_max continuous_on_const continuous_on_diff_ereal) auto qed -lemma (in -) tendsto_diff_ennreal: +lemma tendsto_diff_ennreal: "(f \ x) F \ (g \ y) F \ x \ top \ y \ top \ ((\z. f z - g z::ennreal) \ x - y) F" using continuous_on_tendsto_compose[where f="\x. fst x - snd x::ennreal" and s="{(x, y). x \ top \ y \ top}" and g="\x. (f x, g x)" and l="(x, y)" and F="F", OF continuous_on_diff_ennreal] by (auto simp: tendsto_Pair eventually_conj_iff less_top order_tendstoD continuous_on_fst continuous_on_snd continuous_on_id) +declare lim_real_of_ereal [tendsto_intros] + +lemma tendsto_enn2real [tendsto_intros]: + assumes "(u \ ennreal l) F" "l \ 0" + shows "((\n. enn2real (u n)) \ l) F" + unfolding enn2real_def + apply (intro tendsto_intros) + apply (subst enn2ereal_ennreal[symmetric]) + by (intro tendsto_intros assms)+ + end diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Library/Extended_Real.thy --- a/src/HOL/Library/Extended_Real.thy Sun Feb 25 20:05:05 2018 +0100 +++ b/src/HOL/Library/Extended_Real.thy Mon Feb 26 07:34:05 2018 +0100 @@ -4297,6 +4297,14 @@ by (simp add: x' y' cong: filterlim_cong) qed +lemma continuous_on_diff_ereal: + "continuous_on A f \ continuous_on A g \ (\x. x \ A \ \f x\ \ \) \ (\x. x \ A \ \g x\ \ \) \ continuous_on A (\z. f z - g z::ereal)" + apply (auto simp: continuous_on_def) + apply (intro tendsto_diff_ereal) + apply metis+ + done + + subsubsection \Tests for code generator\ text \A small list of simple arithmetic expressions.\ diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Real_Vector_Spaces.thy --- a/src/HOL/Real_Vector_Spaces.thy Sun Feb 25 20:05:05 2018 +0100 +++ b/src/HOL/Real_Vector_Spaces.thy Mon Feb 26 07:34:05 2018 +0100 @@ -1751,6 +1751,10 @@ lemma (in metric_space) tendsto_iff: "(f \ l) F \ (\e>0. eventually (\x. dist (f x) l < e) F)" unfolding nhds_metric filterlim_INF filterlim_principal by auto +lemma tendsto_dist_iff: + "((f \ l) F) \ (((\x. dist (f x) l) \ 0) F)" + unfolding tendsto_iff by simp + lemma (in metric_space) tendstoI [intro?]: "(\e. 0 < e \ eventually (\x. dist (f x) l < e) F) \ (f \ l) F" by (auto simp: tendsto_iff) @@ -2168,6 +2172,40 @@ for X :: "nat \ 'a::complete_space" by (blast intro: Cauchy_convergent convergent_Cauchy) +text \To prove that a Cauchy sequence converges, it suffices to show that a subsequence converges.\ + +lemma Cauchy_converges_subseq: + fixes u::"nat \ 'a::metric_space" + assumes "Cauchy u" + "strict_mono r" + "(u o r) \ l" + shows "u \ l" +proof - + have *: "eventually (\n. dist (u n) l < e) sequentially" if "e > 0" for e + proof - + have "e/2 > 0" using that by auto + then obtain N1 where N1: "\m n. m \ N1 \ n \ N1 \ dist (u m) (u n) < e/2" + using \Cauchy u\ unfolding Cauchy_def by blast + obtain N2 where N2: "\n. n \ N2 \ dist ((u o r) n) l < e / 2" + using order_tendstoD(2)[OF iffD1[OF tendsto_dist_iff \(u o r) \ l\] \e/2 > 0\] + unfolding eventually_sequentially by auto + have "dist (u n) l < e" if "n \ max N1 N2" for n + proof - + have "dist (u n) l \ dist (u n) ((u o r) n) + dist ((u o r) n) l" + by (rule dist_triangle) + also have "... < e/2 + e/2" + apply (intro add_strict_mono) + using N1[of n "r n"] N2[of n] that unfolding comp_def + by (auto simp add: less_imp_le) (meson assms(2) less_imp_le order.trans seq_suble) + finally show ?thesis by simp + qed + then show ?thesis unfolding eventually_sequentially by blast + qed + have "(\n. dist (u n) l) \ 0" + apply (rule order_tendstoI) + using * by auto (meson eventually_sequentiallyI less_le_trans zero_le_dist) + then show ?thesis using tendsto_dist_iff by auto +qed subsection \The set of real numbers is a complete metric space\ diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Set_Interval.thy --- a/src/HOL/Set_Interval.thy Sun Feb 25 20:05:05 2018 +0100 +++ b/src/HOL/Set_Interval.thy Mon Feb 26 07:34:05 2018 +0100 @@ -1013,7 +1013,7 @@ finally show ?thesis by simp qed -lemma image_minus_const_greaterThanAtMost_real[simp]: +lemma image_minus_const_greaterThanAtMost[simp]: fixes a b c::"'a::linordered_idom" shows "(-) c ` {a<..b} = {c - b..t. t-d)`{a..b} = {a-d..b-d}" for d::"'a::linordered_idom" + by (metis (no_types, lifting) diff_conv_add_uminus image_add_atLeastAtMost' image_cong) + context linordered_field begin lemma image_mult_atLeastAtMost [simp]: diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Topological_Spaces.thy --- a/src/HOL/Topological_Spaces.thy Sun Feb 25 20:05:05 2018 +0100 +++ b/src/HOL/Topological_Spaces.thy Mon Feb 26 07:34:05 2018 +0100 @@ -1289,6 +1289,9 @@ lemma strict_mono_o: "strict_mono r \ strict_mono s \ strict_mono (r \ s)" unfolding strict_mono_def by simp +lemma strict_mono_compose: "strict_mono r \ strict_mono s \ strict_mono (\x. r (s x))" + using strict_mono_o[of r s] by (simp add: o_def) + lemma incseq_imp_monoseq: "incseq X \ monoseq X" by (simp add: incseq_def monoseq_def) @@ -1884,6 +1887,14 @@ "closed s \ closed t \ continuous_on s f \ continuous_on t f \ continuous_on (s \ t) f" by (auto simp add: continuous_on_closed_vimage closed_Un Int_Un_distrib) +lemma continuous_on_closed_Union: + assumes "finite I" + "\i. i \ I \ closed (U i)" + "\i. i \ I \ continuous_on (U i) f" + shows "continuous_on (\ i \ I. U i) f" + using assms + by (induction I) (auto intro!: continuous_on_closed_Un) + lemma continuous_on_If: assumes closed: "closed s" "closed t" and cont: "continuous_on s f" "continuous_on t g" diff -r 0cd2fd0c2dcf -r ce3e87a51488 src/HOL/Transcendental.thy --- a/src/HOL/Transcendental.thy Sun Feb 25 20:05:05 2018 +0100 +++ b/src/HOL/Transcendental.thy Mon Feb 26 07:34:05 2018 +0100 @@ -2910,13 +2910,8 @@ lemma log_base_root: "n > 0 \ b > 0 \ log (root n b) x = n * (log b x)" by (simp add: log_def ln_root) -lemma ln_bound: "1 \ x \ ln x \ x" - for x :: real - apply (subgoal_tac "ln (1 + (x - 1)) \ x - 1") - apply simp - apply (rule ln_add_one_self_le_self) - apply simp - done +lemma ln_bound: "0 < x \ ln x \ x" for x :: real + using ln_le_minus_one by force lemma powr_mono: "a \ b \ 1 \ x \ x powr a \ x powr b" for x :: real