1 (* Title: HOL/Multivariate_Analysis/Derivative.thy
3 Translation from HOL Light: Robert Himmelmann, TU Muenchen
6 header {* Multivariate calculus in Euclidean space. *}
9 imports Brouwer_Fixpoint Operator_Norm
12 (* Because I do not want to type this all the time *)
13 lemmas linear_linear = linear_conv_bounded_linear[THEN sym]
15 subsection {* Derivatives *}
17 text {* The definition is slightly tricky since we make it work over
18 nets of a particular form. This lets us prove theorems generally and use
19 "at a" or "at a within s" for restriction to a set (1-sided on R etc.) *}
21 definition has_derivative :: "('a::real_normed_vector \<Rightarrow> 'b::real_normed_vector) \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> ('a filter \<Rightarrow> bool)"
22 (infixl "(has'_derivative)" 12) where
23 "(f has_derivative f') net \<equiv> bounded_linear f' \<and> ((\<lambda>y. (1 / (norm (y - netlimit net))) *\<^sub>R
24 (f y - (f (netlimit net) + f'(y - netlimit net)))) ---> 0) net"
26 lemma derivative_linear[dest]:
27 "(f has_derivative f') net \<Longrightarrow> bounded_linear f'"
28 unfolding has_derivative_def by auto
30 lemma netlimit_at_vector:
32 fixes a :: "'a::real_normed_vector"
33 shows "netlimit (at a) = a"
34 proof (cases "\<exists>x. x \<noteq> a")
35 case True then obtain x where x: "x \<noteq> a" ..
36 have "\<not> trivial_limit (at a)"
37 unfolding trivial_limit_def eventually_at dist_norm
39 apply (rule_tac x="a + scaleR (d / 2) (sgn (x - a))" in exI)
40 apply (simp add: norm_sgn sgn_zero_iff x)
43 by (rule netlimit_within [of a UNIV, unfolded within_UNIV])
46 lemma FDERIV_conv_has_derivative:
47 shows "FDERIV f x :> f' = (f has_derivative f') (at x)"
48 unfolding fderiv_def has_derivative_def netlimit_at_vector
49 by (simp add: diff_diff_eq Lim_at_zero [where a=x]
50 tendsto_norm_zero_iff [where 'b='b, symmetric])
52 lemma DERIV_conv_has_derivative:
53 "(DERIV f x :> f') = (f has_derivative op * f') (at x)"
54 unfolding deriv_fderiv FDERIV_conv_has_derivative
55 by (subst mult_commute, rule refl)
57 text {* These are the only cases we'll care about, probably. *}
59 lemma has_derivative_within: "(f has_derivative f') (at x within s) \<longleftrightarrow>
60 bounded_linear f' \<and> ((\<lambda>y. (1 / norm(y - x)) *\<^sub>R (f y - (f x + f' (y - x)))) ---> 0) (at x within s)"
61 unfolding has_derivative_def and Lim by(auto simp add:netlimit_within)
63 lemma has_derivative_at: "(f has_derivative f') (at x) \<longleftrightarrow>
64 bounded_linear f' \<and> ((\<lambda>y. (1 / (norm(y - x))) *\<^sub>R (f y - (f x + f' (y - x)))) ---> 0) (at x)"
65 using has_derivative_within [of f f' x UNIV] by simp
67 text {* More explicit epsilon-delta forms. *}
69 lemma has_derivative_within':
70 "(f has_derivative f')(at x within s) \<longleftrightarrow> bounded_linear f' \<and>
71 (\<forall>e>0. \<exists>d>0. \<forall>x'\<in>s. 0 < norm(x' - x) \<and> norm(x' - x) < d
72 \<longrightarrow> norm(f x' - f x - f'(x' - x)) / norm(x' - x) < e)"
73 unfolding has_derivative_within Lim_within dist_norm
74 unfolding diff_0_right by (simp add: diff_diff_eq)
76 lemma has_derivative_at':
77 "(f has_derivative f') (at x) \<longleftrightarrow> bounded_linear f' \<and>
78 (\<forall>e>0. \<exists>d>0. \<forall>x'. 0 < norm(x' - x) \<and> norm(x' - x) < d
79 \<longrightarrow> norm(f x' - f x - f'(x' - x)) / norm(x' - x) < e)"
80 using has_derivative_within' [of f f' x UNIV] by simp
82 lemma has_derivative_at_within: "(f has_derivative f') (at x) \<Longrightarrow> (f has_derivative f') (at x within s)"
83 unfolding has_derivative_within' has_derivative_at' by meson
85 lemma has_derivative_within_open:
86 "a \<in> s \<Longrightarrow> open s \<Longrightarrow> ((f has_derivative f') (at a within s) \<longleftrightarrow> (f has_derivative f') (at a))"
87 by (simp only: at_within_interior interior_open)
89 lemma has_derivative_right:
90 fixes f :: "real \<Rightarrow> real" and y :: "real"
91 shows "(f has_derivative (op * y)) (at x within ({x <..} \<inter> I)) \<longleftrightarrow>
92 ((\<lambda>t. (f x - f t) / (x - t)) ---> y) (at x within ({x <..} \<inter> I))"
94 have "((\<lambda>t. (f t - (f x + y * (t - x))) / \<bar>t - x\<bar>) ---> 0) (at x within ({x<..} \<inter> I)) \<longleftrightarrow>
95 ((\<lambda>t. (f t - f x) / (t - x) - y) ---> 0) (at x within ({x<..} \<inter> I))"
96 by (intro Lim_cong_within) (auto simp add: diff_divide_distrib add_divide_distrib)
97 also have "\<dots> \<longleftrightarrow> ((\<lambda>t. (f t - f x) / (t - x)) ---> y) (at x within ({x<..} \<inter> I))"
98 by (simp add: Lim_null[symmetric])
99 also have "\<dots> \<longleftrightarrow> ((\<lambda>t. (f x - f t) / (x - t)) ---> y) (at x within ({x<..} \<inter> I))"
100 by (intro Lim_cong_within) (simp_all add: field_simps)
102 by (simp add: bounded_linear_mult_right has_derivative_within)
105 lemma bounded_linear_imp_linear: "bounded_linear f \<Longrightarrow> linear f" (* TODO: move elsewhere *)
107 assume "bounded_linear f"
108 then interpret f: bounded_linear f .
110 by (simp add: f.add f.scaleR linear_def)
113 lemma derivative_is_linear:
114 "(f has_derivative f') net \<Longrightarrow> linear f'"
115 by (rule derivative_linear [THEN bounded_linear_imp_linear])
117 subsubsection {* Combining theorems. *}
119 lemma has_derivative_id: "((\<lambda>x. x) has_derivative (\<lambda>h. h)) net"
120 unfolding has_derivative_def
121 by (simp add: bounded_linear_ident tendsto_const)
123 lemma has_derivative_const: "((\<lambda>x. c) has_derivative (\<lambda>h. 0)) net"
124 unfolding has_derivative_def
125 by (simp add: bounded_linear_zero tendsto_const)
127 lemma (in bounded_linear) has_derivative': "(f has_derivative f) net"
128 unfolding has_derivative_def apply(rule,rule bounded_linear_axioms)
129 unfolding diff by (simp add: tendsto_const)
131 lemma (in bounded_linear) bounded_linear: "bounded_linear f" ..
133 lemma (in bounded_linear) has_derivative:
134 assumes "((\<lambda>x. g x) has_derivative (\<lambda>h. g' h)) net"
135 shows "((\<lambda>x. f (g x)) has_derivative (\<lambda>h. f (g' h))) net"
136 using assms unfolding has_derivative_def
138 apply (erule bounded_linear_compose [OF local.bounded_linear])
139 apply (drule local.tendsto)
140 apply (simp add: local.scaleR local.diff local.add local.zero)
143 lemmas scaleR_right_has_derivative =
144 bounded_linear.has_derivative [OF bounded_linear_scaleR_right]
146 lemmas scaleR_left_has_derivative =
147 bounded_linear.has_derivative [OF bounded_linear_scaleR_left]
149 lemmas inner_right_has_derivative =
150 bounded_linear.has_derivative [OF bounded_linear_inner_right]
152 lemmas inner_left_has_derivative =
153 bounded_linear.has_derivative [OF bounded_linear_inner_left]
155 lemmas mult_right_has_derivative =
156 bounded_linear.has_derivative [OF bounded_linear_mult_right]
158 lemmas mult_left_has_derivative =
159 bounded_linear.has_derivative [OF bounded_linear_mult_left]
161 lemma has_derivative_neg:
162 assumes "(f has_derivative f') net"
163 shows "((\<lambda>x. -(f x)) has_derivative (\<lambda>h. -(f' h))) net"
164 using scaleR_right_has_derivative [where r="-1", OF assms] by auto
166 lemma has_derivative_add:
167 assumes "(f has_derivative f') net" and "(g has_derivative g') net"
168 shows "((\<lambda>x. f(x) + g(x)) has_derivative (\<lambda>h. f'(h) + g'(h))) net"
170 note as = assms[unfolded has_derivative_def]
171 show ?thesis unfolding has_derivative_def apply(rule,rule bounded_linear_add)
172 using tendsto_add[OF as(1)[THEN conjunct2] as(2)[THEN conjunct2]] and as
173 by (auto simp add: algebra_simps)
176 lemma has_derivative_add_const:
177 "(f has_derivative f') net \<Longrightarrow> ((\<lambda>x. f x + c) has_derivative f') net"
178 by (drule has_derivative_add, rule has_derivative_const, auto)
180 lemma has_derivative_sub:
181 assumes "(f has_derivative f') net" and "(g has_derivative g') net"
182 shows "((\<lambda>x. f(x) - g(x)) has_derivative (\<lambda>h. f'(h) - g'(h))) net"
183 unfolding diff_minus by (intro has_derivative_add has_derivative_neg assms)
185 lemma has_derivative_setsum:
186 assumes "finite s" and "\<forall>a\<in>s. ((f a) has_derivative (f' a)) net"
187 shows "((\<lambda>x. setsum (\<lambda>a. f a x) s) has_derivative (\<lambda>h. setsum (\<lambda>a. f' a h) s)) net"
188 using assms by (induct, simp_all add: has_derivative_const has_derivative_add)
189 text {* Somewhat different results for derivative of scalar multiplier. *}
191 lemmas has_derivative_intros =
192 has_derivative_id has_derivative_const
193 has_derivative_add has_derivative_sub has_derivative_neg
194 has_derivative_add_const
195 scaleR_left_has_derivative scaleR_right_has_derivative
196 inner_left_has_derivative inner_right_has_derivative
198 subsubsection {* Limit transformation for derivatives *}
200 lemma has_derivative_transform_within:
201 assumes "0 < d" "x \<in> s" "\<forall>x'\<in>s. dist x' x < d \<longrightarrow> f x' = g x'" "(f has_derivative f') (at x within s)"
202 shows "(g has_derivative f') (at x within s)"
203 using assms(4) unfolding has_derivative_within apply- apply(erule conjE,rule,assumption)
204 apply(rule Lim_transform_within[OF assms(1)]) defer apply assumption
205 apply(rule,rule) apply(drule assms(3)[rule_format]) using assms(3)[rule_format, OF assms(2)] by auto
207 lemma has_derivative_transform_at:
208 assumes "0 < d" "\<forall>x'. dist x' x < d \<longrightarrow> f x' = g x'" "(f has_derivative f') (at x)"
209 shows "(g has_derivative f') (at x)"
210 using has_derivative_transform_within [of d x UNIV f g f'] assms by simp
212 lemma has_derivative_transform_within_open:
213 assumes "open s" "x \<in> s" "\<forall>y\<in>s. f y = g y" "(f has_derivative f') (at x)"
214 shows "(g has_derivative f') (at x)"
215 using assms(4) unfolding has_derivative_at apply- apply(erule conjE,rule,assumption)
216 apply(rule Lim_transform_within_open[OF assms(1,2)]) defer apply assumption
217 apply(rule,rule) apply(drule assms(3)[rule_format]) using assms(3)[rule_format, OF assms(2)] by auto
219 subsection {* Differentiability *}
221 no_notation Deriv.differentiable (infixl "differentiable" 60)
223 definition differentiable :: "('a::real_normed_vector \<Rightarrow> 'b::real_normed_vector) \<Rightarrow> 'a filter \<Rightarrow> bool" (infixr "differentiable" 30) where
224 "f differentiable net \<equiv> (\<exists>f'. (f has_derivative f') net)"
226 definition differentiable_on :: "('a::real_normed_vector \<Rightarrow> 'b::real_normed_vector) \<Rightarrow> 'a set \<Rightarrow> bool" (infixr "differentiable'_on" 30) where
227 "f differentiable_on s \<equiv> (\<forall>x\<in>s. f differentiable (at x within s))"
229 lemma differentiableI: "(f has_derivative f') net \<Longrightarrow> f differentiable net"
230 unfolding differentiable_def by auto
232 lemma differentiable_at_withinI: "f differentiable (at x) \<Longrightarrow> f differentiable (at x within s)"
233 unfolding differentiable_def using has_derivative_at_within by blast
235 lemma differentiable_within_open: (* TODO: delete *)
236 assumes "a \<in> s" and "open s"
237 shows "f differentiable (at a within s) \<longleftrightarrow> (f differentiable (at a))"
238 using assms by (simp only: at_within_interior interior_open)
240 lemma differentiable_on_eq_differentiable_at:
241 "open s \<Longrightarrow> (f differentiable_on s \<longleftrightarrow> (\<forall>x\<in>s. f differentiable at x))"
242 unfolding differentiable_on_def
243 by (auto simp add: at_within_interior interior_open)
245 lemma differentiable_transform_within:
246 assumes "0 < d" and "x \<in> s" and "\<forall>x'\<in>s. dist x' x < d \<longrightarrow> f x' = g x'"
247 assumes "f differentiable (at x within s)"
248 shows "g differentiable (at x within s)"
249 using assms(4) unfolding differentiable_def
250 by (auto intro!: has_derivative_transform_within[OF assms(1-3)])
252 lemma differentiable_transform_at:
253 assumes "0 < d" "\<forall>x'. dist x' x < d \<longrightarrow> f x' = g x'" "f differentiable at x"
254 shows "g differentiable at x"
255 using assms(3) unfolding differentiable_def
256 using has_derivative_transform_at[OF assms(1-2)] by auto
258 subsection {* Frechet derivative and Jacobian matrix. *}
260 definition "frechet_derivative f net = (SOME f'. (f has_derivative f') net)"
262 lemma frechet_derivative_works:
263 "f differentiable net \<longleftrightarrow> (f has_derivative (frechet_derivative f net)) net"
264 unfolding frechet_derivative_def differentiable_def and some_eq_ex[of "\<lambda> f' . (f has_derivative f') net"] ..
266 lemma linear_frechet_derivative:
267 shows "f differentiable net \<Longrightarrow> linear(frechet_derivative f net)"
268 unfolding frechet_derivative_works has_derivative_def
269 by (auto intro: bounded_linear_imp_linear)
271 subsection {* Differentiability implies continuity *}
273 lemma Lim_mul_norm_within:
274 fixes f::"'a::real_normed_vector \<Rightarrow> 'b::real_normed_vector"
275 shows "(f ---> 0) (at a within s) \<Longrightarrow> ((\<lambda>x. norm(x - a) *\<^sub>R f(x)) ---> 0) (at a within s)"
276 unfolding Lim_within apply(rule,rule)
277 apply(erule_tac x=e in allE,erule impE,assumption,erule exE,erule conjE)
278 apply(rule_tac x="min d 1" in exI) apply rule defer
279 apply(rule,erule_tac x=x in ballE) unfolding dist_norm diff_0_right
280 by(auto intro!: mult_strict_mono[of _ "1::real", unfolded mult_1_left])
282 lemma differentiable_imp_continuous_within:
283 assumes "f differentiable (at x within s)"
284 shows "continuous (at x within s) f"
286 from assms guess f' unfolding differentiable_def has_derivative_within ..
288 then interpret bounded_linear f' by auto
289 have *:"\<And>xa. x\<noteq>xa \<Longrightarrow> (f' \<circ> (\<lambda>y. y - x)) xa + norm (xa - x) *\<^sub>R ((1 / norm (xa - x)) *\<^sub>R (f xa - (f x + f' (xa - x)))) - ((f' \<circ> (\<lambda>y. y - x)) x + 0) = f xa - f x"
291 have **:"continuous (at x within s) (f' \<circ> (\<lambda>y. y - x))"
292 apply(rule continuous_within_compose) apply(rule continuous_intros)+
293 by(rule linear_continuous_within[OF f'[THEN conjunct1]])
294 show ?thesis unfolding continuous_within
295 using f'[THEN conjunct2, THEN Lim_mul_norm_within]
296 apply- apply(drule tendsto_add)
297 apply(rule **[unfolded continuous_within])
298 unfolding Lim_within and dist_norm
300 apply (erule_tac x=e in allE)
301 apply (erule impE | assumption)+
302 apply (erule exE, rule_tac x=d in exI)
303 by (auto simp add: zero *)
306 lemma differentiable_imp_continuous_at:
307 "f differentiable at x \<Longrightarrow> continuous (at x) f"
308 by(rule differentiable_imp_continuous_within[of _ x UNIV, unfolded within_UNIV])
310 lemma differentiable_imp_continuous_on:
311 "f differentiable_on s \<Longrightarrow> continuous_on s f"
312 unfolding differentiable_on_def continuous_on_eq_continuous_within
313 using differentiable_imp_continuous_within by blast
315 lemma has_derivative_within_subset:
316 "(f has_derivative f') (at x within s) \<Longrightarrow> t \<subseteq> s \<Longrightarrow> (f has_derivative f') (at x within t)"
317 unfolding has_derivative_within using Lim_within_subset by blast
319 lemma differentiable_within_subset:
320 "f differentiable (at x within t) \<Longrightarrow> s \<subseteq> t \<Longrightarrow> f differentiable (at x within s)"
321 unfolding differentiable_def using has_derivative_within_subset by blast
323 lemma differentiable_on_subset:
324 "f differentiable_on t \<Longrightarrow> s \<subseteq> t \<Longrightarrow> f differentiable_on s"
325 unfolding differentiable_on_def using differentiable_within_subset by blast
327 lemma differentiable_on_empty: "f differentiable_on {}"
328 unfolding differentiable_on_def by auto
330 text {* Several results are easier using a "multiplied-out" variant.
331 (I got this idea from Dieudonne's proof of the chain rule). *}
333 lemma has_derivative_within_alt:
334 "(f has_derivative f') (at x within s) \<longleftrightarrow> bounded_linear f' \<and>
335 (\<forall>e>0. \<exists>d>0. \<forall>y\<in>s. norm(y - x) < d \<longrightarrow> norm(f(y) - f(x) - f'(y - x)) \<le> e * norm(y - x))" (is "?lhs \<longleftrightarrow> ?rhs")
337 assume ?lhs thus ?rhs
338 unfolding has_derivative_within apply-apply(erule conjE,rule,assumption)
340 apply(rule,erule_tac x=e in allE,rule,erule impE,assumption)
341 apply(erule exE,rule_tac x=d in exI)
342 apply(erule conjE,rule,assumption,rule,rule)
344 fix x y e d assume as:"0 < e" "0 < d" "norm (y - x) < d" "\<forall>xa\<in>s. 0 < dist xa x \<and> dist xa x < d \<longrightarrow>
345 dist ((1 / norm (xa - x)) *\<^sub>R (f xa - (f x + f' (xa - x)))) 0 < e" "y \<in> s" "bounded_linear f'"
346 then interpret bounded_linear f' by auto
347 show "norm (f y - f x - f' (y - x)) \<le> e * norm (y - x)" proof(cases "y=x")
348 case True thus ?thesis using `bounded_linear f'` by(auto simp add: zero)
350 case False hence "norm (f y - (f x + f' (y - x))) < e * norm (y - x)" using as(4)[rule_format, OF `y\<in>s`]
351 unfolding dist_norm diff_0_right using as(3)
352 using pos_divide_less_eq[OF False[unfolded dist_nz], unfolded dist_norm]
353 by (auto simp add: linear_0 linear_sub)
354 thus ?thesis by(auto simp add:algebra_simps)
358 assume ?rhs thus ?lhs unfolding has_derivative_within Lim_within
359 apply-apply(erule conjE,rule,assumption)
360 apply(rule,erule_tac x="e/2" in allE,rule,erule impE) defer
361 apply(erule exE,rule_tac x=d in exI)
362 apply(erule conjE,rule,assumption,rule,rule)
363 unfolding dist_norm diff_0_right norm_scaleR
364 apply(erule_tac x=xa in ballE,erule impE)
366 fix e d y assume "bounded_linear f'" "0 < e" "0 < d" "y \<in> s" "0 < norm (y - x) \<and> norm (y - x) < d"
367 "norm (f y - f x - f' (y - x)) \<le> e / 2 * norm (y - x)"
368 thus "\<bar>1 / norm (y - x)\<bar> * norm (f y - (f x + f' (y - x))) < e"
369 apply(rule_tac le_less_trans[of _ "e/2"])
370 by(auto intro!:mult_imp_div_pos_le simp add:algebra_simps)
374 lemma has_derivative_at_alt:
375 "(f has_derivative f') (at x) \<longleftrightarrow> bounded_linear f' \<and>
376 (\<forall>e>0. \<exists>d>0. \<forall>y. norm(y - x) < d \<longrightarrow> norm(f y - f x - f'(y - x)) \<le> e * norm(y - x))"
377 using has_derivative_within_alt[where s=UNIV] by simp
379 subsection {* The chain rule. *}
381 lemma diff_chain_within:
382 assumes "(f has_derivative f') (at x within s)"
383 assumes "(g has_derivative g') (at (f x) within (f ` s))"
384 shows "((g o f) has_derivative (g' o f'))(at x within s)"
385 unfolding has_derivative_within_alt
386 apply(rule,rule bounded_linear_compose[unfolded o_def[THEN sym]])
387 apply(rule assms(2)[unfolded has_derivative_def,THEN conjE],assumption)
388 apply(rule assms(1)[unfolded has_derivative_def,THEN conjE],assumption)
390 note assms = assms[unfolded has_derivative_within_alt]
391 fix e::real assume "0<e"
392 guess B1 using bounded_linear.pos_bounded[OF assms(1)[THEN conjunct1, rule_format]] .. note B1 = this
393 guess B2 using bounded_linear.pos_bounded[OF assms(2)[THEN conjunct1, rule_format]] .. note B2 = this
394 have *:"e / 2 / B2 > 0" using `e>0` B2 apply-apply(rule divide_pos_pos) by auto
395 guess d1 using assms(1)[THEN conjunct2, rule_format, OF *] .. note d1 = this
396 have *:"e / 2 / (1 + B1) > 0" using `e>0` B1 apply-apply(rule divide_pos_pos) by auto
397 guess de using assms(2)[THEN conjunct2, rule_format, OF *] .. note de = this
398 guess d2 using assms(1)[THEN conjunct2, rule_format, OF zero_less_one] .. note d2 = this
400 def d0 \<equiv> "(min d1 d2)/2" have d0:"d0>0" "d0 < d1" "d0 < d2" unfolding d0_def using d1 d2 by auto
401 def d \<equiv> "(min d0 (de / (B1 + 1))) / 2" have "de * 2 / (B1 + 1) > de / (B1 + 1)" apply(rule divide_strict_right_mono) using B1 de by auto
402 hence d:"d>0" "d < d1" "d < d2" "d < (de / (B1 + 1))" unfolding d_def using d0 d1 d2 de B1 by(auto intro!: divide_pos_pos simp add:min_less_iff_disj not_less)
404 show "\<exists>d>0. \<forall>y\<in>s. norm (y - x) < d \<longrightarrow> norm ((g \<circ> f) y - (g \<circ> f) x - (g' \<circ> f') (y - x)) \<le> e * norm (y - x)" apply(rule_tac x=d in exI)
405 proof(rule,rule `d>0`,rule,rule)
406 fix y assume as:"y \<in> s" "norm (y - x) < d"
407 hence 1:"norm (f y - f x - f' (y - x)) \<le> min (norm (y - x)) (e / 2 / B2 * norm (y - x))" using d1 d2 d by auto
409 have "norm (f y - f x) \<le> norm (f y - f x - f' (y - x)) + norm (f' (y - x))"
410 using norm_triangle_sub[of "f y - f x" "f' (y - x)"]
411 by(auto simp add:algebra_simps)
412 also have "\<dots> \<le> norm (f y - f x - f' (y - x)) + B1 * norm (y - x)"
413 apply(rule add_left_mono) using B1 by(auto simp add:algebra_simps)
414 also have "\<dots> \<le> min (norm (y - x)) (e / 2 / B2 * norm (y - x)) + B1 * norm (y - x)"
415 apply(rule add_right_mono) using d1 d2 d as by auto
416 also have "\<dots> \<le> norm (y - x) + B1 * norm (y - x)" by auto
417 also have "\<dots> = norm (y - x) * (1 + B1)" by(auto simp add:field_simps)
418 finally have 3:"norm (f y - f x) \<le> norm (y - x) * (1 + B1)" by auto
420 hence "norm (f y - f x) \<le> d * (1 + B1)" apply-
421 apply(rule order_trans,assumption,rule mult_right_mono)
423 also have "\<dots> < de" using d B1 by(auto simp add:field_simps)
424 finally have "norm (g (f y) - g (f x) - g' (f y - f x)) \<le> e / 2 / (1 + B1) * norm (f y - f x)"
425 apply-apply(rule de[THEN conjunct2,rule_format])
426 using `y\<in>s` using d as by auto
427 also have "\<dots> = (e / 2) * (1 / (1 + B1) * norm (f y - f x))" by auto
428 also have "\<dots> \<le> e / 2 * norm (y - x)" apply(rule mult_left_mono)
429 using `e>0` and 3 using B1 and `e>0` by(auto simp add:divide_le_eq)
430 finally have 4:"norm (g (f y) - g (f x) - g' (f y - f x)) \<le> e / 2 * norm (y - x)" by auto
432 interpret g': bounded_linear g' using assms(2) by auto
433 interpret f': bounded_linear f' using assms(1) by auto
434 have "norm (- g' (f' (y - x)) + g' (f y - f x)) = norm (g' (f y - f x - f' (y - x)))"
435 by(auto simp add:algebra_simps f'.diff g'.diff g'.add)
436 also have "\<dots> \<le> B2 * norm (f y - f x - f' (y - x))" using B2
437 by (auto simp add: algebra_simps)
438 also have "\<dots> \<le> B2 * (e / 2 / B2 * norm (y - x))"
439 apply (rule mult_left_mono) using as d1 d2 d B2 by auto
440 also have "\<dots> \<le> e / 2 * norm (y - x)" using B2 by auto
441 finally have 5:"norm (- g' (f' (y - x)) + g' (f y - f x)) \<le> e / 2 * norm (y - x)" by auto
443 have "norm (g (f y) - g (f x) - g' (f y - f x)) + norm (g (f y) - g (f x) - g' (f' (y - x)) - (g (f y) - g (f x) - g' (f y - f x))) \<le> e * norm (y - x)"
445 thus "norm ((g \<circ> f) y - (g \<circ> f) x - (g' \<circ> f') (y - x)) \<le> e * norm (y - x)"
446 unfolding o_def apply- apply(rule order_trans, rule norm_triangle_sub)
452 "(f has_derivative f') (at x) \<Longrightarrow> (g has_derivative g') (at (f x)) \<Longrightarrow> ((g o f) has_derivative (g' o f')) (at x)"
453 using diff_chain_within[of f f' x UNIV g g']
454 using has_derivative_within_subset[of g g' "f x" UNIV "range f"]
457 subsection {* Composition rules stated just for differentiability. *}
459 lemma differentiable_const [intro]:
460 "(\<lambda>z. c) differentiable (net::'a::real_normed_vector filter)"
461 unfolding differentiable_def using has_derivative_const by auto
463 lemma differentiable_id [intro]:
464 "(\<lambda>z. z) differentiable (net::'a::real_normed_vector filter)"
465 unfolding differentiable_def using has_derivative_id by auto
467 lemma differentiable_cmul [intro]:
468 "f differentiable net \<Longrightarrow>
469 (\<lambda>x. c *\<^sub>R f(x)) differentiable (net::'a::real_normed_vector filter)"
470 unfolding differentiable_def
471 apply(erule exE, drule scaleR_right_has_derivative) by auto
473 lemma differentiable_neg [intro]:
474 "f differentiable net \<Longrightarrow>
475 (\<lambda>z. -(f z)) differentiable (net::'a::real_normed_vector filter)"
476 unfolding differentiable_def
477 apply(erule exE, drule has_derivative_neg) by auto
479 lemma differentiable_add: "f differentiable net \<Longrightarrow> g differentiable net
480 \<Longrightarrow> (\<lambda>z. f z + g z) differentiable (net::'a::real_normed_vector filter)"
481 unfolding differentiable_def apply(erule exE)+ apply(rule_tac x="\<lambda>z. f' z + f'a z" in exI)
482 apply(rule has_derivative_add) by auto
484 lemma differentiable_sub: "f differentiable net \<Longrightarrow> g differentiable net
485 \<Longrightarrow> (\<lambda>z. f z - g z) differentiable (net::'a::real_normed_vector filter)"
486 unfolding differentiable_def apply(erule exE)+
487 apply(rule_tac x="\<lambda>z. f' z - f'a z" in exI)
488 apply(rule has_derivative_sub) by auto
490 lemma differentiable_setsum:
491 assumes "finite s" "\<forall>a\<in>s. (f a) differentiable net"
492 shows "(\<lambda>x. setsum (\<lambda>a. f a x) s) differentiable net"
494 guess f' using bchoice[OF assms(2)[unfolded differentiable_def]] ..
495 thus ?thesis unfolding differentiable_def apply-
496 apply(rule,rule has_derivative_setsum[where f'=f'],rule assms(1)) by auto
499 lemma differentiable_setsum_numseg:
500 shows "\<forall>i. m \<le> i \<and> i \<le> n \<longrightarrow> (f i) differentiable net \<Longrightarrow> (\<lambda>x. setsum (\<lambda>a. f a x) {m::nat..n}) differentiable net"
501 apply(rule differentiable_setsum) using finite_atLeastAtMost[of n m] by auto
503 lemma differentiable_chain_at:
504 "f differentiable (at x) \<Longrightarrow> g differentiable (at(f x)) \<Longrightarrow> (g o f) differentiable (at x)"
505 unfolding differentiable_def by(meson diff_chain_at)
507 lemma differentiable_chain_within:
508 "f differentiable (at x within s) \<Longrightarrow> g differentiable (at(f x) within (f ` s))
509 \<Longrightarrow> (g o f) differentiable (at x within s)"
510 unfolding differentiable_def by(meson diff_chain_within)
512 subsection {* Uniqueness of derivative *}
515 The general result is a bit messy because we need approachability of the
516 limit point from any direction. But OK for nontrivial intervals etc.
519 lemma frechet_derivative_unique_within:
520 fixes f :: "'a::euclidean_space \<Rightarrow> 'b::real_normed_vector"
521 assumes "(f has_derivative f') (at x within s)"
522 assumes "(f has_derivative f'') (at x within s)"
523 assumes "(\<forall>i\<in>Basis. \<forall>e>0. \<exists>d. 0 < abs(d) \<and> abs(d) < e \<and> (x + d *\<^sub>R i) \<in> s)"
526 note as = assms(1,2)[unfolded has_derivative_def]
527 then interpret f': bounded_linear f' by auto
528 from as interpret f'': bounded_linear f'' by auto
529 have "x islimpt s" unfolding islimpt_approachable
531 fix e::real assume "0<e" guess d
532 using assms(3)[rule_format,OF SOME_Basis `e>0`] ..
533 thus "\<exists>x'\<in>s. x' \<noteq> x \<and> dist x' x < e"
534 apply(rule_tac x="x + d *\<^sub>R (SOME i. i \<in> Basis)" in bexI)
535 unfolding dist_norm by (auto simp: SOME_Basis nonzero_Basis)
537 hence *:"netlimit (at x within s) = x" apply-apply(rule netlimit_within)
538 unfolding trivial_limit_within by simp
539 show ?thesis apply(rule linear_eq_stdbasis)
540 unfolding linear_conv_bounded_linear
541 apply(rule as(1,2)[THEN conjunct1])+
542 proof(rule,rule ccontr)
543 fix i :: 'a assume i:"i \<in> Basis" def e \<equiv> "norm (f' i - f'' i)"
544 assume "f' i \<noteq> f'' i"
545 hence "e>0" unfolding e_def by auto
546 guess d using tendsto_diff [OF as(1,2)[THEN conjunct2], unfolded * Lim_within,rule_format,OF `e>0`] .. note d=this
547 guess c using assms(3)[rule_format,OF i d[THEN conjunct1]] .. note c=this
548 have *:"norm (- ((1 / \<bar>c\<bar>) *\<^sub>R f' (c *\<^sub>R i)) + (1 / \<bar>c\<bar>) *\<^sub>R f'' (c *\<^sub>R i)) = norm ((1 / abs c) *\<^sub>R (- (f' (c *\<^sub>R i)) + f'' (c *\<^sub>R i)))"
549 unfolding scaleR_right_distrib by auto
550 also have "\<dots> = norm ((1 / abs c) *\<^sub>R (c *\<^sub>R (- (f' i) + f'' i)))"
551 unfolding f'.scaleR f''.scaleR
552 unfolding scaleR_right_distrib scaleR_minus_right by auto
553 also have "\<dots> = e" unfolding e_def using c[THEN conjunct1]
554 using norm_minus_cancel[of "f' i - f'' i"]
555 by (auto simp add: add.commute ab_diff_minus)
556 finally show False using c
557 using d[THEN conjunct2,rule_format,of "x + c *\<^sub>R i"]
559 unfolding f'.scaleR f''.scaleR f'.add f''.add f'.diff f''.diff
560 scaleR_scaleR scaleR_right_diff_distrib scaleR_right_distrib
565 lemma frechet_derivative_unique_at:
566 shows "(f has_derivative f') (at x) \<Longrightarrow> (f has_derivative f'') (at x) \<Longrightarrow> f' = f''"
567 unfolding FDERIV_conv_has_derivative [symmetric]
568 by (rule FDERIV_unique)
570 lemma continuous_isCont: "isCont f x = continuous (at x) f"
571 unfolding isCont_def LIM_def
572 unfolding continuous_at Lim_at unfolding dist_nz by auto
574 lemma frechet_derivative_unique_within_closed_interval:
575 fixes f::"'a::ordered_euclidean_space \<Rightarrow> 'b::real_normed_vector"
576 assumes "\<forall>i\<in>Basis. a\<bullet>i < b\<bullet>i" "x \<in> {a..b}" (is "x\<in>?I")
577 assumes "(f has_derivative f' ) (at x within {a..b})"
578 assumes "(f has_derivative f'') (at x within {a..b})"
580 apply(rule frechet_derivative_unique_within)
581 apply(rule assms(3,4))+
582 proof(rule,rule,rule)
583 fix e::real and i :: 'a assume "e>0" and i:"i\<in>Basis"
584 thus "\<exists>d. 0 < \<bar>d\<bar> \<and> \<bar>d\<bar> < e \<and> x + d *\<^sub>R i \<in> {a..b}"
585 proof(cases "x\<bullet>i=a\<bullet>i")
586 case True thus ?thesis
587 apply(rule_tac x="(min (b\<bullet>i - a\<bullet>i) e) / 2" in exI)
588 using assms(1)[THEN bspec[where x=i]] and `e>0` and assms(2)
589 unfolding mem_interval
590 using i by (auto simp add: field_simps inner_simps inner_Basis)
592 note * = assms(2)[unfolded mem_interval, THEN bspec, OF i]
593 case False moreover have "a \<bullet> i < x \<bullet> i" using False * by auto
595 have "a \<bullet> i * 2 + min (x \<bullet> i - a \<bullet> i) e \<le> a\<bullet>i *2 + x\<bullet>i - a\<bullet>i"
597 also have "\<dots> = a\<bullet>i + x\<bullet>i" by auto
598 also have "\<dots> \<le> 2 * (x\<bullet>i)" using * by auto
599 finally have "a \<bullet> i * 2 + min (x \<bullet> i - a \<bullet> i) e \<le> x \<bullet> i * 2" by auto
601 moreover have "min (x \<bullet> i - a \<bullet> i) e \<ge> 0" using * and `e>0` by auto
602 hence "x \<bullet> i * 2 \<le> b \<bullet> i * 2 + min (x \<bullet> i - a \<bullet> i) e" using * by auto
603 ultimately show ?thesis
604 apply(rule_tac x="- (min (x\<bullet>i - a\<bullet>i) e) / 2" in exI)
605 using assms(1)[THEN bspec, OF i] and `e>0` and assms(2)
606 unfolding mem_interval
607 using i by (auto simp add: field_simps inner_simps inner_Basis)
611 lemma frechet_derivative_unique_within_open_interval:
612 fixes f::"'a::ordered_euclidean_space \<Rightarrow> 'b::real_normed_vector"
613 assumes "x \<in> {a<..<b}"
614 assumes "(f has_derivative f' ) (at x within {a<..<b})"
615 assumes "(f has_derivative f'') (at x within {a<..<b})"
618 from assms(1) have *: "at x within {a<..<b} = at x"
619 by (simp add: at_within_interior interior_open open_interval)
620 from assms(2,3) [unfolded *] show "f' = f''"
621 by (rule frechet_derivative_unique_at)
624 lemma frechet_derivative_at:
625 shows "(f has_derivative f') (at x) \<Longrightarrow> (f' = frechet_derivative f (at x))"
626 apply(rule frechet_derivative_unique_at[of f],assumption)
627 unfolding frechet_derivative_works[THEN sym] using differentiable_def by auto
629 lemma frechet_derivative_within_closed_interval:
630 fixes f::"'a::ordered_euclidean_space \<Rightarrow> 'b::real_normed_vector"
631 assumes "\<forall>i\<in>Basis. a\<bullet>i < b\<bullet>i" and "x \<in> {a..b}"
632 assumes "(f has_derivative f') (at x within {a.. b})"
633 shows "frechet_derivative f (at x within {a.. b}) = f'"
634 apply(rule frechet_derivative_unique_within_closed_interval[where f=f])
635 apply(rule assms(1,2))+ unfolding frechet_derivative_works[THEN sym]
636 unfolding differentiable_def using assms(3) by auto
638 subsection {* The traditional Rolle theorem in one dimension. *}
640 lemma linear_componentwise:
641 fixes f:: "'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
642 assumes lf: "linear f"
643 shows "(f x) \<bullet> j = (\<Sum>i\<in>Basis. (x\<bullet>i) * (f i\<bullet>j))" (is "?lhs = ?rhs")
645 have fA: "finite Basis" by simp
646 have "?rhs = (\<Sum>i\<in>Basis. (x\<bullet>i) *\<^sub>R (f i))\<bullet>j"
647 by (simp add: inner_setsum_left)
649 unfolding linear_setsum_mul[OF lf fA, symmetric]
650 unfolding euclidean_representation ..
653 text {* We do not introduce @{text jacobian}, which is defined on matrices, instead we use
654 the unfolding of it. *}
656 lemma jacobian_works:
657 "(f::('a::euclidean_space) \<Rightarrow> ('b::euclidean_space)) differentiable net \<longleftrightarrow>
658 (f has_derivative (\<lambda>h. \<Sum>i\<in>Basis.
659 (\<Sum>j\<in>Basis. frechet_derivative f net (j) \<bullet> i * (h \<bullet> j)) *\<^sub>R i)) net"
660 (is "?differentiable \<longleftrightarrow> (f has_derivative (\<lambda>h. \<Sum>i\<in>Basis. ?SUM h i *\<^sub>R i)) net")
662 assume *: ?differentiable
664 have "?SUM h i = frechet_derivative f net h \<bullet> i" using *
665 by (auto intro!: setsum_cong
666 simp: linear_componentwise[of _ h i] linear_frechet_derivative) }
667 with * show "(f has_derivative (\<lambda>h. \<Sum>i\<in>Basis. ?SUM h i *\<^sub>R i)) net"
668 by (simp add: frechet_derivative_works euclidean_representation)
669 qed (auto intro!: differentiableI)
671 lemma differential_zero_maxmin_component:
672 fixes f :: "'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
673 assumes k: "k \<in> Basis"
674 and ball: "0 < e" "((\<forall>y \<in> ball x e. (f y)\<bullet>k \<le> (f x)\<bullet>k) \<or> (\<forall>y\<in>ball x e. (f x)\<bullet>k \<le> (f y)\<bullet>k))"
675 and diff: "f differentiable (at x)"
676 shows "(\<Sum>j\<in>Basis. (frechet_derivative f (at x) j \<bullet> k) *\<^sub>R j) = (0::'a)" (is "?D k = 0")
678 assume "?D k \<noteq> 0"
679 then obtain j where j: "?D k \<bullet> j \<noteq> 0" "j \<in> Basis"
680 unfolding euclidean_eq_iff[of _ "0::'a"] by auto
681 hence *: "\<bar>?D k \<bullet> j\<bar> / 2 > 0" by auto
682 note as = diff[unfolded jacobian_works has_derivative_at_alt]
683 guess e' using as[THEN conjunct2, rule_format, OF *] .. note e' = this
684 guess d using real_lbound_gt_zero[OF ball(1) e'[THEN conjunct1]] .. note d = this
685 { fix c assume "abs c \<le> d"
686 hence *:"norm (x + c *\<^sub>R j - x) < e'" using norm_Basis[OF j(2)] d by auto
687 let ?v = "(\<Sum>i\<in>Basis. (\<Sum>l\<in>Basis. ?D i \<bullet> l * ((c *\<^sub>R j :: 'a) \<bullet> l)) *\<^sub>R i)"
688 have if_dist: "\<And> P a b c. a * (if P then b else c) = (if P then a * b else a * c)" by auto
689 have "\<bar>(f (x + c *\<^sub>R j) - f x - ?v) \<bullet> k\<bar> \<le>
690 norm (f (x + c *\<^sub>R j) - f x - ?v)" by (rule Basis_le_norm[OF k])
691 also have "\<dots> \<le> \<bar>?D k \<bullet> j\<bar> / 2 * \<bar>c\<bar>"
692 using e'[THEN conjunct2, rule_format, OF *] and norm_Basis[OF j(2)] j
694 finally have "\<bar>(f (x + c *\<^sub>R j) - f x - ?v) \<bullet> k\<bar> \<le> \<bar>?D k \<bullet> j\<bar> / 2 * \<bar>c\<bar>" by simp
695 hence "\<bar>f (x + c *\<^sub>R j) \<bullet> k - f x \<bullet> k - c * (?D k \<bullet> j)\<bar> \<le> \<bar>?D k \<bullet> j\<bar> / 2 * \<bar>c\<bar>"
697 by (simp add: inner_simps field_simps inner_Basis setsum_cases if_dist) }
699 have "x + d *\<^sub>R j \<in> ball x e" "x - d *\<^sub>R j \<in> ball x e"
700 unfolding mem_ball dist_norm using norm_Basis[OF j(2)] d by auto
701 hence **:"((f (x - d *\<^sub>R j))\<bullet>k \<le> (f x)\<bullet>k \<and> (f (x + d *\<^sub>R j))\<bullet>k \<le> (f x)\<bullet>k) \<or>
702 ((f (x - d *\<^sub>R j))\<bullet>k \<ge> (f x)\<bullet>k \<and> (f (x + d *\<^sub>R j))\<bullet>k \<ge> (f x)\<bullet>k)" using ball by auto
703 have ***: "\<And>y y1 y2 d dx::real.
704 (y1\<le>y\<and>y2\<le>y) \<or> (y\<le>y1\<and>y\<le>y2) \<Longrightarrow> d < abs dx \<Longrightarrow> abs(y1 - y - - dx) \<le> d \<Longrightarrow> (abs (y2 - y - dx) \<le> d) \<Longrightarrow> False" by arith
705 show False apply(rule ***[OF **, where dx="d * (?D k \<bullet> j)" and d="\<bar>?D k \<bullet> j\<bar> / 2 * \<bar>d\<bar>"])
706 using *[of "-d"] and *[of d] and d[THEN conjunct1] and j
707 unfolding mult_minus_left
708 unfolding abs_mult diff_minus_eq_add scaleR_minus_left
709 unfolding algebra_simps by (auto intro: mult_pos_pos)
712 text {* In particular if we have a mapping into @{typ "real"}. *}
714 lemma differential_zero_maxmin:
715 fixes f::"'a\<Colon>euclidean_space \<Rightarrow> real"
716 assumes "x \<in> s" "open s"
717 and deriv: "(f has_derivative f') (at x)"
718 and mono: "(\<forall>y\<in>s. f y \<le> f x) \<or> (\<forall>y\<in>s. f x \<le> f y)"
719 shows "f' = (\<lambda>v. 0)"
721 obtain e where e:"e>0" "ball x e \<subseteq> s"
722 using `open s`[unfolded open_contains_ball] and `x \<in> s` by auto
723 with differential_zero_maxmin_component[where 'b=real, of 1 e x f] mono deriv
724 have "(\<Sum>j\<in>Basis. frechet_derivative f (at x) j *\<^sub>R j) = (0::'a)"
725 by (auto simp: Basis_real_def differentiable_def)
726 with frechet_derivative_at[OF deriv, symmetric]
727 have "\<forall>i\<in>Basis. f' i = 0"
728 by (simp add: euclidean_eq_iff[of _ "0::'a"] inner_setsum_left_Basis)
729 with derivative_is_linear[OF deriv, THEN linear_componentwise, of _ 1]
730 show ?thesis by (simp add: fun_eq_iff)
733 lemma rolle: fixes f::"real\<Rightarrow>real"
734 assumes "a < b" and "f a = f b" and "continuous_on {a..b} f"
735 assumes "\<forall>x\<in>{a<..<b}. (f has_derivative f'(x)) (at x)"
736 shows "\<exists>x\<in>{a<..<b}. f' x = (\<lambda>v. 0)"
738 have "\<exists>x\<in>{a<..<b}. ((\<forall>y\<in>{a<..<b}. f x \<le> f y) \<or> (\<forall>y\<in>{a<..<b}. f y \<le> f x))"
740 have "(a + b) / 2 \<in> {a .. b}" using assms(1) by auto
741 hence *:"{a .. b}\<noteq>{}" by auto
742 guess d using continuous_attains_sup[OF compact_interval * assms(3)] .. note d=this
743 guess c using continuous_attains_inf[OF compact_interval * assms(3)] .. note c=this
745 proof(cases "d\<in>{a<..<b} \<or> c\<in>{a<..<b}")
746 case True thus ?thesis
747 apply(erule_tac disjE) apply(rule_tac x=d in bexI)
748 apply(rule_tac[3] x=c in bexI)
751 def e \<equiv> "(a + b) /2"
752 case False hence "f d = f c" using d c assms(2) by auto
753 hence "\<And>x. x\<in>{a..b} \<Longrightarrow> f x = f d"
754 using c d apply- apply(erule_tac x=x in ballE)+ by auto
756 apply(rule_tac x=e in bexI) unfolding e_def using assms(1) by auto
759 then guess x .. note x=this
760 hence "f' x = (\<lambda>v. 0)"
761 apply(rule_tac differential_zero_maxmin[of x "{a<..<b}" f "f' x"])
762 defer apply(rule open_interval)
763 apply(rule assms(4)[unfolded has_derivative_at[THEN sym],THEN bspec[where x=x]],assumption)
764 unfolding o_def apply(erule disjE,rule disjI2) by auto
765 thus ?thesis apply(rule_tac x=x in bexI) unfolding o_def apply rule
766 apply(drule_tac x=v in fun_cong) using x(1) by auto
769 subsection {* One-dimensional mean value theorem. *}
771 lemma mvt: fixes f::"real \<Rightarrow> real"
772 assumes "a < b" and "continuous_on {a .. b} f"
773 assumes "\<forall>x\<in>{a<..<b}. (f has_derivative (f' x)) (at x)"
774 shows "\<exists>x\<in>{a<..<b}. (f b - f a = (f' x) (b - a))"
776 have "\<exists>x\<in>{a<..<b}. (\<lambda>xa. f' x xa - (f b - f a) / (b - a) * xa) = (\<lambda>v. 0)"
777 apply(rule rolle[OF assms(1), of "\<lambda>x. f x - (f b - f a) / (b - a) * x"])
779 apply(rule continuous_on_intros assms(2))+
781 fix x assume x:"x \<in> {a<..<b}"
782 show "((\<lambda>x. f x - (f b - f a) / (b - a) * x) has_derivative (\<lambda>xa. f' x xa - (f b - f a) / (b - a) * xa)) (at x)"
783 by (intro has_derivative_intros assms(3)[rule_format,OF x]
784 mult_right_has_derivative)
785 qed(insert assms(1), auto simp add:field_simps)
787 thus ?thesis apply(rule_tac x=x in bexI)
788 apply(drule fun_cong[of _ _ "b - a"]) by auto
792 fixes f::"real \<Rightarrow> real"
793 assumes "a<b" and "\<forall>x\<in>{a..b}. (f has_derivative f' x) (at x within {a..b})"
794 shows "\<exists>x\<in>{a<..<b}. f b - f a = f' x (b - a)"
796 apply(rule assms(1), rule differentiable_imp_continuous_on)
797 unfolding differentiable_on_def differentiable_def defer
799 fix x assume x:"x \<in> {a<..<b}" show "(f has_derivative f' x) (at x)"
800 unfolding has_derivative_within_open[OF x open_interval,THEN sym]
801 apply(rule has_derivative_within_subset)
802 apply(rule assms(2)[rule_format])
804 qed(insert assms(2), auto)
806 lemma mvt_very_simple:
807 fixes f::"real \<Rightarrow> real"
808 assumes "a \<le> b" and "\<forall>x\<in>{a..b}. (f has_derivative f'(x)) (at x within {a..b})"
809 shows "\<exists>x\<in>{a..b}. f b - f a = f' x (b - a)"
810 proof (cases "a = b")
811 interpret bounded_linear "f' b" using assms(2) assms(1) by auto
812 case True thus ?thesis apply(rule_tac x=a in bexI)
813 using assms(2)[THEN bspec[where x=a]] unfolding has_derivative_def
814 unfolding True using zero by auto next
815 case False thus ?thesis using mvt_simple[OF _ assms(2)] using assms(1) by auto
818 text {* A nice generalization (see Havin's proof of 5.19 from Rudin's book). *}
821 fixes f::"real\<Rightarrow>'a::euclidean_space"
822 assumes "a<b" and "continuous_on {a..b} f"
823 assumes "\<forall>x\<in>{a<..<b}. (f has_derivative f'(x)) (at x)"
824 shows "\<exists>x\<in>{a<..<b}. norm(f b - f a) \<le> norm(f'(x) (b - a))"
826 have "\<exists>x\<in>{a<..<b}. (op \<bullet> (f b - f a) \<circ> f) b - (op \<bullet> (f b - f a) \<circ> f) a = (f b - f a) \<bullet> f' x (b - a)"
827 apply(rule mvt) apply(rule assms(1))
828 apply(rule continuous_on_inner continuous_on_intros assms(2))+
829 unfolding o_def apply(rule,rule has_derivative_intros)
830 using assms(3) by auto
831 then guess x .. note x=this
832 show ?thesis proof(cases "f a = f b")
834 have "norm (f b - f a) * norm (f b - f a) = norm (f b - f a)^2"
835 by (simp add: power2_eq_square)
836 also have "\<dots> = (f b - f a) \<bullet> (f b - f a)" unfolding power2_norm_eq_inner ..
837 also have "\<dots> = (f b - f a) \<bullet> f' x (b - a)"
838 using x unfolding inner_simps by (auto simp add: inner_diff_left)
839 also have "\<dots> \<le> norm (f b - f a) * norm (f' x (b - a))"
840 by (rule norm_cauchy_schwarz)
841 finally show ?thesis using False x(1)
842 by (auto simp add: real_mult_left_cancel)
844 case True thus ?thesis using assms(1)
845 apply (rule_tac x="(a + b) /2" in bexI) by auto
849 text {* Still more general bound theorem. *}
851 lemma differentiable_bound:
852 fixes f::"'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
853 assumes "convex s" and "\<forall>x\<in>s. (f has_derivative f'(x)) (at x within s)"
854 assumes "\<forall>x\<in>s. onorm(f' x) \<le> B" and x:"x\<in>s" and y:"y\<in>s"
855 shows "norm(f x - f y) \<le> B * norm(x - y)"
857 let ?p = "\<lambda>u. x + u *\<^sub>R (y - x)"
858 have *:"\<And>u. u\<in>{0..1} \<Longrightarrow> x + u *\<^sub>R (y - x) \<in> s"
859 using assms(1)[unfolded convex_alt,rule_format,OF x y]
860 unfolding scaleR_left_diff_distrib scaleR_right_diff_distrib
861 by (auto simp add: algebra_simps)
862 hence 1:"continuous_on {0..1} (f \<circ> ?p)" apply-
863 apply(rule continuous_on_intros)+
864 unfolding continuous_on_eq_continuous_within
865 apply(rule,rule differentiable_imp_continuous_within)
866 unfolding differentiable_def apply(rule_tac x="f' xa" in exI)
867 apply(rule has_derivative_within_subset)
868 apply(rule assms(2)[rule_format]) by auto
869 have 2:"\<forall>u\<in>{0<..<1}. ((f \<circ> ?p) has_derivative f' (x + u *\<^sub>R (y - x)) \<circ> (\<lambda>u. 0 + u *\<^sub>R (y - x))) (at u)"
872 let ?u = "x + u *\<^sub>R (y - x)"
873 have "(f \<circ> ?p has_derivative (f' ?u) \<circ> (\<lambda>u. 0 + u *\<^sub>R (y - x))) (at u within {0<..<1})"
874 apply(rule diff_chain_within) apply(rule has_derivative_intros)+
875 apply(rule has_derivative_within_subset)
876 apply(rule assms(2)[rule_format]) using goal1 * by auto
878 unfolding has_derivative_within_open[OF goal1 open_interval] by auto
880 guess u using mvt_general[OF zero_less_one 1 2] .. note u = this
881 have **:"\<And>x y. x\<in>s \<Longrightarrow> norm (f' x y) \<le> B * norm y"
884 have "norm (f' x y) \<le> onorm (f' x) * norm y"
885 using onorm(1)[OF derivative_is_linear[OF assms(2)[rule_format,OF goal1]]] by assumption
886 also have "\<dots> \<le> B * norm y"
887 apply(rule mult_right_mono)
888 using assms(3)[rule_format,OF goal1]
889 by(auto simp add:field_simps)
890 finally show ?case by simp
892 have "norm (f x - f y) = norm ((f \<circ> (\<lambda>u. x + u *\<^sub>R (y - x))) 1 - (f \<circ> (\<lambda>u. x + u *\<^sub>R (y - x))) 0)"
893 by(auto simp add:norm_minus_commute)
894 also have "\<dots> \<le> norm (f' (x + u *\<^sub>R (y - x)) (y - x))" using u by auto
895 also have "\<dots> \<le> B * norm(y - x)" apply(rule **) using * and u by auto
896 finally show ?thesis by(auto simp add:norm_minus_commute)
899 lemma differentiable_bound_real:
900 fixes f::"real \<Rightarrow> real"
901 assumes "convex s" and "\<forall>x\<in>s. (f has_derivative f' x) (at x within s)"
902 assumes "\<forall>x\<in>s. onorm(f' x) \<le> B" and x:"x\<in>s" and y:"y\<in>s"
903 shows "norm(f x - f y) \<le> B * norm(x - y)"
904 using differentiable_bound[of s f f' B x y]
905 unfolding Ball_def image_iff o_def using assms by auto
907 text {* In particular. *}
909 lemma has_derivative_zero_constant:
910 fixes f::"real\<Rightarrow>real"
911 assumes "convex s" "\<forall>x\<in>s. (f has_derivative (\<lambda>h. 0)) (at x within s)"
912 shows "\<exists>c. \<forall>x\<in>s. f x = c"
914 case False then obtain x where "x\<in>s" by auto
915 have "\<And>y. y\<in>s \<Longrightarrow> f x = f y" proof- case goal1
917 using differentiable_bound_real[OF assms(1-2), of 0 x y] and `x\<in>s`
918 unfolding onorm_const by auto qed
919 thus ?thesis apply(rule_tac x="f x" in exI) by auto
922 lemma has_derivative_zero_unique: fixes f::"real\<Rightarrow>real"
923 assumes "convex s" and "a \<in> s" and "f a = c"
924 assumes "\<forall>x\<in>s. (f has_derivative (\<lambda>h. 0)) (at x within s)" and "x\<in>s"
926 using has_derivative_zero_constant[OF assms(1,4)] using assms(2-3,5) by auto
928 subsection {* Differentiability of inverse function (most basic form). *}
930 lemma has_derivative_inverse_basic:
931 fixes f::"'b::euclidean_space \<Rightarrow> 'c::euclidean_space"
932 assumes "(f has_derivative f') (at (g y))"
933 assumes "bounded_linear g'" and "g' \<circ> f' = id" and "continuous (at y) g"
934 assumes "open t" and "y \<in> t" and "\<forall>z\<in>t. f(g z) = z"
935 shows "(g has_derivative g') (at y)"
937 interpret f': bounded_linear f'
938 using assms unfolding has_derivative_def by auto
939 interpret g': bounded_linear g' using assms by auto
940 guess C using bounded_linear.pos_bounded[OF assms(2)] .. note C = this
941 (* have fgid:"\<And>x. g' (f' x) = x" using assms(3) unfolding o_def id_def apply()*)
942 have lem1:"\<forall>e>0. \<exists>d>0. \<forall>z. norm(z - y) < d \<longrightarrow> norm(g z - g y - g'(z - y)) \<le> e * norm(g z - g y)"
945 have *:"e / C > 0" apply(rule divide_pos_pos) using `e>0` C by auto
946 guess d0 using assms(1)[unfolded has_derivative_at_alt,THEN conjunct2,rule_format,OF *] .. note d0=this
947 guess d1 using assms(4)[unfolded continuous_at Lim_at,rule_format,OF d0[THEN conjunct1]] .. note d1=this
948 guess d2 using assms(5)[unfolded open_dist,rule_format,OF assms(6)] .. note d2=this
949 guess d using real_lbound_gt_zero[OF d1[THEN conjunct1] d2[THEN conjunct1]] .. note d=this
950 thus ?case apply(rule_tac x=d in exI) apply rule defer
952 fix z assume as:"norm (z - y) < d" hence "z\<in>t"
953 using d2 d unfolding dist_norm by auto
954 have "norm (g z - g y - g' (z - y)) \<le> norm (g' (f (g z) - y - f' (g z - g y)))"
955 unfolding g'.diff f'.diff
956 unfolding assms(3)[unfolded o_def id_def, THEN fun_cong]
957 unfolding assms(7)[rule_format,OF `z\<in>t`]
958 apply(subst norm_minus_cancel[THEN sym]) by auto
959 also have "\<dots> \<le> norm(f (g z) - y - f' (g z - g y)) * C"
960 by (rule C [THEN conjunct2, rule_format])
961 also have "\<dots> \<le> (e / C) * norm (g z - g y) * C"
962 apply(rule mult_right_mono)
963 apply(rule d0[THEN conjunct2,rule_format,unfolded assms(7)[rule_format,OF `y\<in>t`]])
964 apply(cases "z=y") defer
965 apply(rule d1[THEN conjunct2, unfolded dist_norm,rule_format])
966 using as d C d0 by auto
967 also have "\<dots> \<le> e * norm (g z - g y)"
968 using C by (auto simp add: field_simps)
969 finally show "norm (g z - g y - g' (z - y)) \<le> e * norm (g z - g y)"
973 have *:"(0::real) < 1 / 2" by auto
974 guess d using lem1[rule_format,OF *] .. note d=this
976 have "B>0" unfolding B_def using C by auto
977 have lem2:"\<forall>z. norm(z - y) < d \<longrightarrow> norm(g z - g y) \<le> B * norm(z - y)"
978 proof(rule,rule) case goal1
979 have "norm (g z - g y) \<le> norm(g' (z - y)) + norm ((g z - g y) - g'(z - y))"
980 by(rule norm_triangle_sub)
981 also have "\<dots> \<le> norm(g' (z - y)) + 1 / 2 * norm (g z - g y)"
982 apply(rule add_left_mono) using d and goal1 by auto
983 also have "\<dots> \<le> norm (z - y) * C + 1 / 2 * norm (g z - g y)"
984 apply(rule add_right_mono) using C by auto
985 finally show ?case unfolding B_def by(auto simp add:field_simps)
987 show ?thesis unfolding has_derivative_at_alt
988 proof(rule,rule assms,rule,rule) case goal1
989 hence *:"e/B >0" apply-apply(rule divide_pos_pos) using `B>0` by auto
990 guess d' using lem1[rule_format,OF *] .. note d'=this
991 guess k using real_lbound_gt_zero[OF d[THEN conjunct1] d'[THEN conjunct1]] .. note k=this
993 apply(rule_tac x=k in exI,rule) defer
995 fix z assume as:"norm(z - y) < k"
996 hence "norm (g z - g y - g' (z - y)) \<le> e / B * norm(g z - g y)"
998 also have "\<dots> \<le> e * norm(z - y)"
999 unfolding times_divide_eq_left pos_divide_le_eq[OF `B>0`]
1000 using lem2[THEN spec[where x=z]] using k as using `e>0`
1001 by (auto simp add: field_simps)
1002 finally show "norm (g z - g y - g' (z - y)) \<le> e * norm (z - y)"
1003 by simp qed(insert k, auto)
1007 text {* Simply rewrite that based on the domain point x. *}
1009 lemma has_derivative_inverse_basic_x:
1010 fixes f::"'b::euclidean_space \<Rightarrow> 'c::euclidean_space"
1011 assumes "(f has_derivative f') (at x)" "bounded_linear g'" "g' o f' = id"
1012 "continuous (at (f x)) g" "g(f x) = x" "open t" "f x \<in> t" "\<forall>y\<in>t. f(g y) = y"
1013 shows "(g has_derivative g') (at (f(x)))"
1014 apply(rule has_derivative_inverse_basic) using assms by auto
1016 text {* This is the version in Dieudonne', assuming continuity of f and g. *}
1018 lemma has_derivative_inverse_dieudonne:
1019 fixes f::"'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
1020 assumes "open s" "open (f ` s)" "continuous_on s f" "continuous_on (f ` s) g" "\<forall>x\<in>s. g(f x) = x"
1021 (**) "x\<in>s" "(f has_derivative f') (at x)" "bounded_linear g'" "g' o f' = id"
1022 shows "(g has_derivative g') (at (f x))"
1023 apply(rule has_derivative_inverse_basic_x[OF assms(7-9) _ _ assms(2)])
1024 using assms(3-6) unfolding continuous_on_eq_continuous_at[OF assms(1)]
1025 continuous_on_eq_continuous_at[OF assms(2)] by auto
1027 text {* Here's the simplest way of not assuming much about g. *}
1029 lemma has_derivative_inverse:
1030 fixes f::"'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
1031 assumes "compact s" "x \<in> s" "f x \<in> interior(f ` s)" "continuous_on s f"
1032 "\<forall>y\<in>s. g(f y) = y" "(f has_derivative f') (at x)" "bounded_linear g'" "g' \<circ> f' = id"
1033 shows "(g has_derivative g') (at (f x))"
1035 { fix y assume "y\<in>interior (f ` s)"
1036 then obtain x where "x\<in>s" and *:"y = f x"
1037 unfolding image_iff using interior_subset by auto
1038 have "f (g y) = y" unfolding * and assms(5)[rule_format,OF `x\<in>s`] ..
1041 apply(rule has_derivative_inverse_basic_x[OF assms(6-8)])
1042 apply(rule continuous_on_interior[OF _ assms(3)])
1043 apply(rule continuous_on_inv[OF assms(4,1)])
1044 apply(rule assms(2,5) assms(5)[rule_format] open_interior assms(3))+
1045 by(rule, rule *, assumption)
1048 subsection {* Proving surjectivity via Brouwer fixpoint theorem. *}
1050 lemma brouwer_surjective:
1051 fixes f::"'n::ordered_euclidean_space \<Rightarrow> 'n"
1052 assumes "compact t" "convex t" "t \<noteq> {}" "continuous_on t f"
1053 "\<forall>x\<in>s. \<forall>y\<in>t. x + (y - f y) \<in> t" "x\<in>s"
1054 shows "\<exists>y\<in>t. f y = x"
1056 have *:"\<And>x y. f y = x \<longleftrightarrow> x + (y - f y) = y"
1057 by(auto simp add:algebra_simps)
1060 apply(rule brouwer[OF assms(1-3), of "\<lambda>y. x + (y - f y)"])
1061 apply(rule continuous_on_intros assms)+ using assms(4-6) by auto
1064 lemma brouwer_surjective_cball:
1065 fixes f::"'n::ordered_euclidean_space \<Rightarrow> 'n"
1066 assumes "0 < e" "continuous_on (cball a e) f"
1067 "\<forall>x\<in>s. \<forall>y\<in>cball a e. x + (y - f y) \<in> cball a e" "x\<in>s"
1068 shows "\<exists>y\<in>cball a e. f y = x"
1069 apply(rule brouwer_surjective)
1070 apply(rule compact_cball convex_cball)+
1071 unfolding cball_eq_empty using assms by auto
1073 text {* See Sussmann: "Multidifferential calculus", Theorem 2.1.1 *}
1075 lemma sussmann_open_mapping:
1076 fixes f::"'a::euclidean_space \<Rightarrow> 'b::ordered_euclidean_space"
1077 assumes "open s" "continuous_on s f" "x \<in> s"
1078 "(f has_derivative f') (at x)" "bounded_linear g'" "f' \<circ> g' = id"
1079 "t \<subseteq> s" "x \<in> interior t"
1080 shows "f x \<in> interior (f ` t)"
1082 interpret f':bounded_linear f'
1083 using assms unfolding has_derivative_def by auto
1084 interpret g':bounded_linear g' using assms by auto
1085 guess B using bounded_linear.pos_bounded[OF assms(5)] .. note B=this
1086 hence *:"1/(2*B)>0" by (auto intro!: divide_pos_pos)
1087 guess e0 using assms(4)[unfolded has_derivative_at_alt,THEN conjunct2,rule_format,OF *] .. note e0=this
1088 guess e1 using assms(8)[unfolded mem_interior_cball] .. note e1=this
1089 have *:"0<e0/B" "0<e1/B"
1090 apply(rule_tac[!] divide_pos_pos) using e0 e1 B by auto
1091 guess e using real_lbound_gt_zero[OF *] .. note e=this
1092 have "\<forall>z\<in>cball (f x) (e/2). \<exists>y\<in>cball (f x) e. f (x + g' (y - f x)) = z"
1093 apply(rule,rule brouwer_surjective_cball[where s="cball (f x) (e/2)"])
1094 prefer 3 apply(rule,rule)
1096 show "continuous_on (cball (f x) e) (\<lambda>y. f (x + g' (y - f x)))"
1098 apply(rule continuous_on_compose[of _ _ f, unfolded o_def])
1099 apply(rule continuous_on_intros linear_continuous_on[OF assms(5)])+
1100 apply(rule continuous_on_subset[OF assms(2)])
1101 apply(rule,unfold image_iff,erule bexE)
1103 fix y z assume as:"y \<in>cball (f x) e" "z = x + (g' y - g' (f x))"
1104 have "dist x z = norm (g' (f x) - g' y)"
1105 unfolding as(2) and dist_norm by auto
1106 also have "\<dots> \<le> norm (f x - y) * B"
1107 unfolding g'.diff[THEN sym] using B by auto
1108 also have "\<dots> \<le> e * B"
1109 using as(1)[unfolded mem_cball dist_norm] using B by auto
1110 also have "\<dots> \<le> e1" using e unfolding less_divide_eq using B by auto
1111 finally have "z\<in>cball x e1" unfolding mem_cball by force
1112 thus "z \<in> s" using e1 assms(7) by auto
1115 fix y z assume as:"y \<in> cball (f x) (e / 2)" "z \<in> cball (f x) e"
1116 have "norm (g' (z - f x)) \<le> norm (z - f x) * B" using B by auto
1117 also have "\<dots> \<le> e * B" apply(rule mult_right_mono)
1118 using as(2)[unfolded mem_cball dist_norm] and B
1119 unfolding norm_minus_commute by auto
1120 also have "\<dots> < e0" using e and B unfolding less_divide_eq by auto
1121 finally have *:"norm (x + g' (z - f x) - x) < e0" by auto
1122 have **:"f x + f' (x + g' (z - f x) - x) = z"
1123 using assms(6)[unfolded o_def id_def,THEN cong] by auto
1124 have "norm (f x - (y + (z - f (x + g' (z - f x))))) \<le> norm (f (x + g' (z - f x)) - z) + norm (f x - y)"
1125 using norm_triangle_ineq[of "f (x + g'(z - f x)) - z" "f x - y"]
1126 by (auto simp add: algebra_simps)
1127 also have "\<dots> \<le> 1 / (B * 2) * norm (g' (z - f x)) + norm (f x - y)"
1128 using e0[THEN conjunct2,rule_format,OF *]
1129 unfolding algebra_simps ** by auto
1130 also have "\<dots> \<le> 1 / (B * 2) * norm (g' (z - f x)) + e/2"
1131 using as(1)[unfolded mem_cball dist_norm] by auto
1132 also have "\<dots> \<le> 1 / (B * 2) * B * norm (z - f x) + e/2"
1133 using * and B by (auto simp add: field_simps)
1134 also have "\<dots> \<le> 1 / 2 * norm (z - f x) + e/2" by auto
1135 also have "\<dots> \<le> e/2 + e/2" apply(rule add_right_mono)
1136 using as(2)[unfolded mem_cball dist_norm]
1137 unfolding norm_minus_commute by auto
1138 finally show "y + (z - f (x + g' (z - f x))) \<in> cball (f x) e"
1139 unfolding mem_cball dist_norm by auto
1140 qed(insert e, auto) note lem = this
1141 show ?thesis unfolding mem_interior apply(rule_tac x="e/2" in exI)
1142 apply(rule,rule divide_pos_pos) prefer 3
1144 fix y assume "y \<in> ball (f x) (e/2)"
1145 hence *:"y\<in>cball (f x) (e/2)" by auto
1146 guess z using lem[rule_format,OF *] .. note z=this
1147 hence "norm (g' (z - f x)) \<le> norm (z - f x) * B"
1148 using B by (auto simp add: field_simps)
1149 also have "\<dots> \<le> e * B"
1150 apply (rule mult_right_mono) using z(1)
1151 unfolding mem_cball dist_norm norm_minus_commute using B by auto
1152 also have "\<dots> \<le> e1" using e B unfolding less_divide_eq by auto
1153 finally have "x + g'(z - f x) \<in> t" apply-
1154 apply(rule e1[THEN conjunct2,unfolded subset_eq,rule_format])
1155 unfolding mem_cball dist_norm by auto
1156 thus "y \<in> f ` t" using z by auto
1160 text {* Hence the following eccentric variant of the inverse function theorem. *)
1161 (* This has no continuity assumptions, but we do need the inverse function. *)
1162 (* We could put f' o g = I but this happens to fit with the minimal linear *)
1163 (* algebra theory I've set up so far. *}
1165 (* move before left_inverse_linear in Euclidean_Space*)
1167 lemma right_inverse_linear:
1168 fixes f::"'a::euclidean_space => 'a"
1169 assumes lf: "linear f" and gf: "f o g = id"
1172 from gf have fi: "surj f" by (auto simp add: surj_def o_def id_def) metis
1173 from linear_surjective_isomorphism[OF lf fi]
1174 obtain h:: "'a => 'a" where
1175 h: "linear h" "\<forall>x. h (f x) = x" "\<forall>x. f (h x) = x" by blast
1176 have "h = g" apply (rule ext) using gf h(2,3)
1177 by (simp add: o_def id_def fun_eq_iff) metis
1178 with h(1) show ?thesis by blast
1181 lemma has_derivative_inverse_strong:
1182 fixes f::"'n::ordered_euclidean_space \<Rightarrow> 'n"
1183 assumes "open s" and "x \<in> s" and "continuous_on s f"
1184 assumes "\<forall>x\<in>s. g(f x) = x" "(f has_derivative f') (at x)" and "f' o g' = id"
1185 shows "(g has_derivative g') (at (f x))"
1187 have linf:"bounded_linear f'"
1188 using assms(5) unfolding has_derivative_def by auto
1189 hence ling:"bounded_linear g'"
1190 unfolding linear_conv_bounded_linear[THEN sym]
1191 apply- apply(rule right_inverse_linear) using assms(6) by auto
1192 moreover have "g' \<circ> f' = id" using assms(6) linf ling
1193 unfolding linear_conv_bounded_linear[THEN sym]
1194 using linear_inverse_left by auto
1195 moreover have *:"\<forall>t\<subseteq>s. x\<in>interior t \<longrightarrow> f x \<in> interior (f ` t)"
1196 apply(rule,rule,rule,rule sussmann_open_mapping )
1197 apply(rule assms ling)+ by auto
1198 have "continuous (at (f x)) g" unfolding continuous_at Lim_at
1200 fix e::real assume "e>0"
1201 hence "f x \<in> interior (f ` (ball x e \<inter> s))"
1202 using *[rule_format,of "ball x e \<inter> s"] `x\<in>s`
1203 by(auto simp add: interior_open[OF open_ball] interior_open[OF assms(1)])
1204 then guess d unfolding mem_interior .. note d=this
1205 show "\<exists>d>0. \<forall>y. 0 < dist y (f x) \<and> dist y (f x) < d \<longrightarrow> dist (g y) (g (f x)) < e"
1206 apply(rule_tac x=d in exI)
1207 apply(rule,rule d[THEN conjunct1])
1208 proof(rule,rule) case goal1
1209 hence "g y \<in> g ` f ` (ball x e \<inter> s)"
1210 using d[THEN conjunct2,unfolded subset_eq,THEN bspec[where x=y]]
1211 by(auto simp add:dist_commute)
1212 hence "g y \<in> ball x e \<inter> s" using assms(4) by auto
1213 thus "dist (g y) (g (f x)) < e"
1214 using assms(4)[rule_format,OF `x\<in>s`]
1215 by (auto simp add: dist_commute)
1218 moreover have "f x \<in> interior (f ` s)"
1219 apply(rule sussmann_open_mapping)
1220 apply(rule assms ling)+
1221 using interior_open[OF assms(1)] and `x\<in>s` by auto
1222 moreover have "\<And>y. y \<in> interior (f ` s) \<Longrightarrow> f (g y) = y"
1224 hence "y\<in>f ` s" using interior_subset by auto
1225 then guess z unfolding image_iff ..
1226 thus ?case using assms(4) by auto
1228 ultimately show ?thesis
1229 apply- apply(rule has_derivative_inverse_basic_x[OF assms(5)])
1233 text {* A rewrite based on the other domain. *}
1235 lemma has_derivative_inverse_strong_x:
1236 fixes f::"'a::ordered_euclidean_space \<Rightarrow> 'a"
1237 assumes "open s" and "g y \<in> s" and "continuous_on s f"
1238 assumes "\<forall>x\<in>s. g(f x) = x" "(f has_derivative f') (at (g y))"
1239 assumes "f' o g' = id" and "f(g y) = y"
1240 shows "(g has_derivative g') (at y)"
1241 using has_derivative_inverse_strong[OF assms(1-6)] unfolding assms(7) by simp
1243 text {* On a region. *}
1245 lemma has_derivative_inverse_on:
1246 fixes f::"'n::ordered_euclidean_space \<Rightarrow> 'n"
1247 assumes "open s" and "\<forall>x\<in>s. (f has_derivative f'(x)) (at x)"
1248 assumes "\<forall>x\<in>s. g(f x) = x" and "f'(x) o g'(x) = id" and "x\<in>s"
1249 shows "(g has_derivative g'(x)) (at (f x))"
1250 apply(rule has_derivative_inverse_strong[where g'="g' x" and f=f])
1252 unfolding continuous_on_eq_continuous_at[OF assms(1)]
1253 apply(rule,rule differentiable_imp_continuous_at)
1254 unfolding differentiable_def using assms by auto
1256 text {* Invertible derivative continous at a point implies local
1257 injectivity. It's only for this we need continuity of the derivative,
1258 except of course if we want the fact that the inverse derivative is
1259 also continuous. So if we know for some other reason that the inverse
1260 function exists, it's OK. *}
1262 lemma bounded_linear_sub:
1263 "bounded_linear f \<Longrightarrow> bounded_linear g ==> bounded_linear (\<lambda>x. f x - g x)"
1264 using bounded_linear_add[of f "\<lambda>x. - g x"] bounded_linear_minus[of g]
1265 by (auto simp add: algebra_simps)
1267 lemma has_derivative_locally_injective:
1268 fixes f::"'n::euclidean_space \<Rightarrow> 'm::euclidean_space"
1269 assumes "a \<in> s" "open s" "bounded_linear g'" "g' o f'(a) = id"
1270 "\<forall>x\<in>s. (f has_derivative f'(x)) (at x)"
1271 "\<forall>e>0. \<exists>d>0. \<forall>x. dist a x < d \<longrightarrow> onorm(\<lambda>v. f' x v - f' a v) < e"
1272 obtains t where "a \<in> t" "open t" "\<forall>x\<in>t. \<forall>x'\<in>t. (f x' = f x) \<longrightarrow> (x' = x)"
1274 interpret bounded_linear g' using assms by auto
1275 note f'g' = assms(4)[unfolded id_def o_def,THEN cong]
1276 have "g' (f' a (\<Sum>Basis)) = (\<Sum>Basis)" "(\<Sum>Basis) \<noteq> (0::'n)" defer
1277 apply(subst euclidean_eq_iff) using f'g' by auto
1278 hence *:"0 < onorm g'"
1279 unfolding onorm_pos_lt[OF assms(3)[unfolded linear_linear]] by fastforce
1280 def k \<equiv> "1 / onorm g' / 2" have *:"k>0" unfolding k_def using * by auto
1281 guess d1 using assms(6)[rule_format,OF *] .. note d1=this
1282 from `open s` obtain d2 where "d2>0" "ball a d2 \<subseteq> s" using `a\<in>s` ..
1283 obtain d2 where "d2>0" "ball a d2 \<subseteq> s" using assms(2,1) ..
1284 guess d2 using assms(2)[unfolded open_contains_ball,rule_format,OF `a\<in>s`] ..
1286 guess d using real_lbound_gt_zero[OF d1[THEN conjunct1] d2[THEN conjunct1]] ..
1290 show "a\<in>ball a d" using d by auto
1291 show "\<forall>x\<in>ball a d. \<forall>x'\<in>ball a d. f x' = f x \<longrightarrow> x' = x"
1293 fix x y assume as:"x\<in>ball a d" "y\<in>ball a d" "f x = f y"
1294 def ph \<equiv> "\<lambda>w. w - g'(f w - f x)"
1295 have ph':"ph = g' \<circ> (\<lambda>w. f' a w - (f w - f x))"
1296 unfolding ph_def o_def unfolding diff using f'g'
1297 by (auto simp add: algebra_simps)
1298 have "norm (ph x - ph y) \<le> (1/2) * norm (x - y)"
1299 apply(rule differentiable_bound[OF convex_ball _ _ as(1-2), where f'="\<lambda>x v. v - g'(f' x v)"])
1300 apply(rule_tac[!] ballI)
1302 fix u assume u:"u \<in> ball a d"
1303 hence "u\<in>s" using d d2 by auto
1304 have *:"(\<lambda>v. v - g' (f' u v)) = g' \<circ> (\<lambda>w. f' a w - f' u w)"
1305 unfolding o_def and diff using f'g' by auto
1306 show "(ph has_derivative (\<lambda>v. v - g' (f' u v))) (at u within ball a d)"
1307 unfolding ph' * apply(rule diff_chain_within) defer
1308 apply(rule bounded_linear.has_derivative'[OF assms(3)])
1309 apply(rule has_derivative_intros) defer
1310 apply(rule has_derivative_sub[where g'="\<lambda>x.0",unfolded diff_0_right])
1311 apply(rule has_derivative_at_within)
1312 using assms(5) and `u\<in>s` `a\<in>s`
1313 by(auto intro!: has_derivative_intros bounded_linear.has_derivative' derivative_linear)
1314 have **:"bounded_linear (\<lambda>x. f' u x - f' a x)"
1315 "bounded_linear (\<lambda>x. f' a x - f' u x)"
1316 apply(rule_tac[!] bounded_linear_sub)
1317 apply(rule_tac[!] derivative_linear)
1318 using assms(5) `u\<in>s` `a\<in>s` by auto
1319 have "onorm (\<lambda>v. v - g' (f' u v)) \<le> onorm g' * onorm (\<lambda>w. f' a w - f' u w)"
1320 unfolding * apply(rule onorm_compose)
1321 unfolding linear_conv_bounded_linear by(rule assms(3) **)+
1322 also have "\<dots> \<le> onorm g' * k"
1323 apply(rule mult_left_mono)
1324 using d1[THEN conjunct2,rule_format,of u]
1325 using onorm_neg[OF **(1)[unfolded linear_linear]]
1326 using d and u and onorm_pos_le[OF assms(3)[unfolded linear_linear]]
1327 by (auto simp add: algebra_simps)
1328 also have "\<dots> \<le> 1/2" unfolding k_def by auto
1329 finally show "onorm (\<lambda>v. v - g' (f' u v)) \<le> 1 / 2" by assumption
1331 moreover have "norm (ph y - ph x) = norm (y - x)"
1332 apply(rule arg_cong[where f=norm])
1333 unfolding ph_def using diff unfolding as by auto
1334 ultimately show "x = y" unfolding norm_minus_commute by auto
1339 subsection {* Uniformly convergent sequence of derivatives. *}
1341 lemma has_derivative_sequence_lipschitz_lemma:
1342 fixes f::"nat \<Rightarrow> 'm::euclidean_space \<Rightarrow> 'n::euclidean_space"
1344 assumes "\<forall>n. \<forall>x\<in>s. ((f n) has_derivative (f' n x)) (at x within s)"
1345 assumes "\<forall>n\<ge>N. \<forall>x\<in>s. \<forall>h. norm(f' n x h - g' x h) \<le> e * norm(h)"
1346 shows "\<forall>m\<ge>N. \<forall>n\<ge>N. \<forall>x\<in>s. \<forall>y\<in>s. norm((f m x - f n x) - (f m y - f n y)) \<le> 2 * e * norm(x - y)"
1348 fix m n x y assume as:"N\<le>m" "N\<le>n" "x\<in>s" "y\<in>s"
1349 show "norm((f m x - f n x) - (f m y - f n y)) \<le> 2 * e * norm(x - y)"
1350 apply(rule differentiable_bound[where f'="\<lambda>x h. f' m x h - f' n x h", OF assms(1) _ _ as(3-4)])
1351 apply(rule_tac[!] ballI)
1353 fix x assume "x\<in>s"
1354 show "((\<lambda>a. f m a - f n a) has_derivative (\<lambda>h. f' m x h - f' n x h)) (at x within s)"
1355 by(rule has_derivative_intros assms(2)[rule_format] `x\<in>s`)+
1357 have "norm (f' m x h - f' n x h) \<le> norm (f' m x h - g' x h) + norm (f' n x h - g' x h)"
1358 using norm_triangle_ineq[of "f' m x h - g' x h" "- f' n x h + g' x h"]
1359 unfolding norm_minus_commute by (auto simp add: algebra_simps)
1360 also have "\<dots> \<le> e * norm h+ e * norm h"
1361 using assms(3)[rule_format,OF `N\<le>m` `x\<in>s`, of h]
1362 using assms(3)[rule_format,OF `N\<le>n` `x\<in>s`, of h]
1363 by(auto simp add:field_simps)
1364 finally have "norm (f' m x h - f' n x h) \<le> 2 * e * norm h" by auto }
1365 thus "onorm (\<lambda>h. f' m x h - f' n x h) \<le> 2 * e"
1366 apply-apply(rule onorm(2)) apply(rule linear_compose_sub)
1367 unfolding linear_conv_bounded_linear
1368 using assms(2)[rule_format,OF `x\<in>s`, THEN derivative_linear]
1373 lemma has_derivative_sequence_lipschitz:
1374 fixes f::"nat \<Rightarrow> 'm::euclidean_space \<Rightarrow> 'n::euclidean_space"
1376 assumes "\<forall>n. \<forall>x\<in>s. ((f n) has_derivative (f' n x)) (at x within s)"
1377 assumes "\<forall>e>0. \<exists>N. \<forall>n\<ge>N. \<forall>x\<in>s. \<forall>h. norm(f' n x h - g' x h) \<le> e * norm(h)"
1379 shows "\<forall>e>0. \<exists>N. \<forall>m\<ge>N. \<forall>n\<ge>N. \<forall>x\<in>s. \<forall>y\<in>s. norm((f m x - f n x) - (f m y - f n y)) \<le> e * norm(x - y)"
1381 case goal1 have *:"2 * (1/2* e) = e" "1/2 * e >0" using `e>0` by auto
1382 guess N using assms(3)[rule_format,OF *(2)] ..
1384 apply(rule_tac x=N in exI)
1385 apply(rule has_derivative_sequence_lipschitz_lemma[where e="1/2 *e", unfolded *])
1389 lemma has_derivative_sequence:
1390 fixes f::"nat\<Rightarrow> 'm::euclidean_space \<Rightarrow> 'n::euclidean_space"
1392 assumes "\<forall>n. \<forall>x\<in>s. ((f n) has_derivative (f' n x)) (at x within s)"
1393 assumes "\<forall>e>0. \<exists>N. \<forall>n\<ge>N. \<forall>x\<in>s. \<forall>h. norm(f' n x h - g' x h) \<le> e * norm(h)"
1394 assumes "x0 \<in> s" and "((\<lambda>n. f n x0) ---> l) sequentially"
1395 shows "\<exists>g. \<forall>x\<in>s. ((\<lambda>n. f n x) ---> g x) sequentially \<and>
1396 (g has_derivative g'(x)) (at x within s)"
1398 have lem1:"\<forall>e>0. \<exists>N. \<forall>m\<ge>N. \<forall>n\<ge>N. \<forall>x\<in>s. \<forall>y\<in>s. norm((f m x - f n x) - (f m y - f n y)) \<le> e * norm(x - y)"
1399 apply(rule has_derivative_sequence_lipschitz[where e="42::nat"])
1400 apply(rule assms)+ by auto
1401 have "\<exists>g. \<forall>x\<in>s. ((\<lambda>n. f n x) ---> g x) sequentially"
1402 apply(rule bchoice) unfolding convergent_eq_cauchy
1404 fix x assume "x\<in>s" show "Cauchy (\<lambda>n. f n x)"
1406 case True thus ?thesis using LIMSEQ_imp_Cauchy[OF assms(5)] by auto
1408 case False show ?thesis unfolding Cauchy_def
1410 fix e::real assume "e>0"
1411 hence *:"e/2>0" "e/2/norm(x-x0)>0"
1412 using False by (auto intro!: divide_pos_pos)
1413 guess M using LIMSEQ_imp_Cauchy[OF assms(5), unfolded Cauchy_def, rule_format,OF *(1)] .. note M=this
1414 guess N using lem1[rule_format,OF *(2)] .. note N = this
1415 show "\<exists>M. \<forall>m\<ge>M. \<forall>n\<ge>M. dist (f m x) (f n x) < e"
1416 apply(rule_tac x="max M N" in exI)
1418 fix m n assume as:"max M N \<le>m" "max M N\<le>n"
1419 have "dist (f m x) (f n x) \<le> norm (f m x0 - f n x0) + norm (f m x - f n x - (f m x0 - f n x0))"
1420 unfolding dist_norm by(rule norm_triangle_sub)
1421 also have "\<dots> \<le> norm (f m x0 - f n x0) + e / 2"
1422 using N[rule_format,OF _ _ `x\<in>s` `x0\<in>s`, of m n] and as and False
1424 also have "\<dots> < e / 2 + e / 2"
1425 apply(rule add_strict_right_mono)
1426 using as and M[rule_format] unfolding dist_norm by auto
1427 finally show "dist (f m x) (f n x) < e" by auto
1432 then guess g .. note g = this
1433 have lem2:"\<forall>e>0. \<exists>N. \<forall>n\<ge>N. \<forall>x\<in>s. \<forall>y\<in>s. norm((f n x - f n y) - (g x - g y)) \<le> e * norm(x - y)"
1435 fix e::real assume *:"e>0"
1436 guess N using lem1[rule_format,OF *] .. note N=this
1437 show "\<exists>N. \<forall>n\<ge>N. \<forall>x\<in>s. \<forall>y\<in>s. norm (f n x - f n y - (g x - g y)) \<le> e * norm (x - y)"
1438 apply(rule_tac x=N in exI)
1440 fix n x y assume as:"N \<le> n" "x \<in> s" "y \<in> s"
1441 have "eventually (\<lambda>xa. norm (f n x - f n y - (f xa x - f xa y)) \<le> e * norm (x - y)) sequentially"
1442 unfolding eventually_sequentially
1443 apply(rule_tac x=N in exI)
1445 fix m assume "N\<le>m"
1446 thus "norm (f n x - f n y - (f m x - f m y)) \<le> e * norm (x - y)"
1447 using N[rule_format, of n m x y] and as
1448 by (auto simp add: algebra_simps)
1450 thus "norm (f n x - f n y - (g x - g y)) \<le> e * norm (x - y)"
1452 apply(rule Lim_norm_ubound[OF trivial_limit_sequentially, where f="\<lambda>m. (f n x - f n y) - (f m x - f m y)"])
1453 apply(rule tendsto_intros g[rule_format] as)+ by assumption
1456 show ?thesis unfolding has_derivative_within_alt apply(rule_tac x=g in exI)
1457 apply(rule,rule,rule g[rule_format],assumption)
1458 proof fix x assume "x\<in>s"
1459 have lem3:"\<forall>u. ((\<lambda>n. f' n x u) ---> g' x u) sequentially"
1460 unfolding LIMSEQ_def
1461 proof(rule,rule,rule)
1462 fix u and e::real assume "e>0"
1463 show "\<exists>N. \<forall>n\<ge>N. dist (f' n x u) (g' x u) < e"
1465 case True guess N using assms(3)[rule_format,OF `e>0`] .. note N=this
1466 show ?thesis apply(rule_tac x=N in exI) unfolding True
1467 using N[rule_format,OF _ `x\<in>s`,of _ 0] and `e>0` by auto
1469 case False hence *:"e / 2 / norm u > 0"
1470 using `e>0` by (auto intro!: divide_pos_pos)
1471 guess N using assms(3)[rule_format,OF *] .. note N=this
1472 show ?thesis apply(rule_tac x=N in exI)
1473 proof(rule,rule) case goal1
1474 show ?case unfolding dist_norm
1475 using N[rule_format,OF goal1 `x\<in>s`, of u] False `e>0`
1476 by (auto simp add:field_simps)
1480 show "bounded_linear (g' x)"
1481 unfolding linear_linear linear_def
1482 apply(rule,rule,rule) defer
1484 fix x' y z::"'m" and c::real
1485 note lin = assms(2)[rule_format,OF `x\<in>s`,THEN derivative_linear]
1486 show "g' x (c *\<^sub>R x') = c *\<^sub>R g' x x'"
1487 apply(rule tendsto_unique[OF trivial_limit_sequentially])
1488 apply(rule lem3[rule_format])
1489 unfolding lin[unfolded bounded_linear_def bounded_linear_axioms_def,THEN conjunct2,THEN conjunct1,rule_format]
1490 apply (intro tendsto_intros) by(rule lem3[rule_format])
1491 show "g' x (y + z) = g' x y + g' x z"
1492 apply(rule tendsto_unique[OF trivial_limit_sequentially])
1493 apply(rule lem3[rule_format])
1494 unfolding lin[unfolded bounded_linear_def additive_def,THEN conjunct1,rule_format]
1495 apply(rule tendsto_add) by(rule lem3[rule_format])+
1497 show "\<forall>e>0. \<exists>d>0. \<forall>y\<in>s. norm (y - x) < d \<longrightarrow> norm (g y - g x - g' x (y - x)) \<le> e * norm (y - x)"
1498 proof(rule,rule) case goal1
1499 have *:"e/3>0" using goal1 by auto
1500 guess N1 using assms(3)[rule_format,OF *] .. note N1=this
1501 guess N2 using lem2[rule_format,OF *] .. note N2=this
1502 guess d1 using assms(2)[unfolded has_derivative_within_alt, rule_format,OF `x\<in>s`, of "max N1 N2",THEN conjunct2,rule_format,OF *] .. note d1=this
1503 show ?case apply(rule_tac x=d1 in exI) apply(rule,rule d1[THEN conjunct1])
1505 fix y assume as:"y \<in> s" "norm (y - x) < d1"
1507 have "norm (g y - g x - (f ?N y - f ?N x)) \<le> e /3 * norm (y - x)"
1508 apply(subst norm_minus_cancel[THEN sym])
1509 using N2[rule_format, OF _ `y\<in>s` `x\<in>s`, of ?N] by auto
1511 have "norm (f ?N y - f ?N x - f' ?N x (y - x)) \<le> e / 3 * norm (y - x)"
1512 using d1 and as by auto
1514 have "norm (g y - g x - f' ?N x (y - x)) \<le> 2 * e / 3 * norm (y - x)"
1515 using norm_triangle_le[of "g y - g x - (f ?N y - f ?N x)" "f ?N y - f ?N x - f' ?N x (y - x)" "2 * e / 3 * norm (y - x)"]
1516 by (auto simp add:algebra_simps)
1518 have " norm (f' ?N x (y - x) - g' x (y - x)) \<le> e / 3 * norm (y - x)"
1519 using N1 `x\<in>s` by auto
1520 ultimately show "norm (g y - g x - g' x (y - x)) \<le> e * norm (y - x)"
1521 using norm_triangle_le[of "g y - g x - f' (max N1 N2) x (y - x)" "f' (max N1 N2) x (y - x) - g' x (y - x)"]
1522 by(auto simp add:algebra_simps)
1528 text {* Can choose to line up antiderivatives if we want. *}
1530 lemma has_antiderivative_sequence:
1531 fixes f::"nat\<Rightarrow> 'm::euclidean_space \<Rightarrow> 'n::euclidean_space"
1533 assumes "\<forall>n. \<forall>x\<in>s. ((f n) has_derivative (f' n x)) (at x within s)"
1534 assumes "\<forall>e>0. \<exists>N. \<forall>n\<ge>N. \<forall>x\<in>s. \<forall>h. norm(f' n x h - g' x h) \<le> e * norm h"
1535 shows "\<exists>g. \<forall>x\<in>s. (g has_derivative g'(x)) (at x within s)"
1537 case False then obtain a where "a\<in>s" by auto
1538 have *:"\<And>P Q. \<exists>g. \<forall>x\<in>s. P g x \<and> Q g x \<Longrightarrow> \<exists>g. \<forall>x\<in>s. Q g x" by auto
1541 apply(rule has_derivative_sequence[OF assms(1) _ assms(3), of "\<lambda>n x. f n x + (f 0 a - f n a)"])
1543 apply(rule has_derivative_add_const, rule assms(2)[rule_format], assumption)
1544 apply(rule `a\<in>s`) by auto
1547 lemma has_antiderivative_limit:
1548 fixes g'::"'m::euclidean_space \<Rightarrow> 'm \<Rightarrow> 'n::euclidean_space"
1550 assumes "\<forall>e>0. \<exists>f f'. \<forall>x\<in>s. (f has_derivative (f' x)) (at x within s) \<and> (\<forall>h. norm(f' x h - g' x h) \<le> e * norm(h))"
1551 shows "\<exists>g. \<forall>x\<in>s. (g has_derivative g'(x)) (at x within s)"
1553 have *:"\<forall>n. \<exists>f f'. \<forall>x\<in>s. (f has_derivative (f' x)) (at x within s) \<and> (\<forall>h. norm(f' x h - g' x h) \<le> inverse (real (Suc n)) * norm(h))"
1554 apply(rule) using assms(2)
1555 apply(erule_tac x="inverse (real (Suc n))" in allE) by auto
1556 guess f using *[THEN choice] .. note * = this
1557 guess f' using *[THEN choice] .. note f=this
1558 show ?thesis apply(rule has_antiderivative_sequence[OF assms(1), of f f']) defer
1560 fix e::real assume "0<e" guess N using reals_Archimedean[OF `e>0`] .. note N=this
1561 show "\<exists>N. \<forall>n\<ge>N. \<forall>x\<in>s. \<forall>h. norm (f' n x h - g' x h) \<le> e * norm h"
1562 apply(rule_tac x=N in exI)
1565 have *:"inverse (real (Suc n)) \<le> e" apply(rule order_trans[OF _ N[THEN less_imp_le]])
1566 using goal1(1) by(auto simp add:field_simps)
1568 using f[rule_format,THEN conjunct2,OF goal1(2), of n, THEN spec[where x=h]]
1569 apply(rule order_trans) using N * apply(cases "h=0") by auto
1574 subsection {* Differentiation of a series. *}
1576 definition sums_seq :: "(nat \<Rightarrow> 'a::real_normed_vector) \<Rightarrow> 'a \<Rightarrow> (nat set) \<Rightarrow> bool"
1577 (infixl "sums'_seq" 12) where "(f sums_seq l) s \<equiv> ((\<lambda>n. setsum f (s \<inter> {0..n})) ---> l) sequentially"
1579 lemma has_derivative_series:
1580 fixes f::"nat \<Rightarrow> 'm::euclidean_space \<Rightarrow> 'n::euclidean_space"
1582 assumes "\<forall>n. \<forall>x\<in>s. ((f n) has_derivative (f' n x)) (at x within s)"
1583 assumes "\<forall>e>0. \<exists>N. \<forall>n\<ge>N. \<forall>x\<in>s. \<forall>h. norm(setsum (\<lambda>i. f' i x h) (k \<inter> {0..n}) - g' x h) \<le> e * norm(h)"
1584 assumes "x\<in>s" and "((\<lambda>n. f n x) sums_seq l) k"
1585 shows "\<exists>g. \<forall>x\<in>s. ((\<lambda>n. f n x) sums_seq (g x)) k \<and> (g has_derivative g'(x)) (at x within s)"
1586 unfolding sums_seq_def
1587 apply(rule has_derivative_sequence[OF assms(1) _ assms(3)])
1589 apply(rule has_derivative_setsum) defer
1590 apply(rule,rule assms(2)[rule_format],assumption)
1591 using assms(4-5) unfolding sums_seq_def by auto
1593 subsection {* Derivative with composed bilinear function. *}
1595 lemma has_derivative_bilinear_within:
1596 assumes "(f has_derivative f') (at x within s)"
1597 assumes "(g has_derivative g') (at x within s)"
1598 assumes "bounded_bilinear h"
1599 shows "((\<lambda>x. h (f x) (g x)) has_derivative (\<lambda>d. h (f x) (g' d) + h (f' d) (g x))) (at x within s)"
1601 have "(g ---> g x) (at x within s)"
1602 apply(rule differentiable_imp_continuous_within[unfolded continuous_within])
1603 using assms(2) unfolding differentiable_def by auto
1605 interpret f':bounded_linear f'
1606 using assms unfolding has_derivative_def by auto
1607 interpret g':bounded_linear g'
1608 using assms unfolding has_derivative_def by auto
1609 interpret h:bounded_bilinear h
1611 have "((\<lambda>y. f' (y - x)) ---> 0) (at x within s)"
1612 unfolding f'.zero[THEN sym]
1613 using bounded_linear.tendsto [of f' "\<lambda>y. y - x" 0 "at x within s"]
1614 using tendsto_diff [OF Lim_within_id tendsto_const, of x x s]
1615 unfolding id_def using assms(1) unfolding has_derivative_def by auto
1616 hence "((\<lambda>y. f x + f' (y - x)) ---> f x) (at x within s)"
1617 using tendsto_add[OF tendsto_const, of "\<lambda>y. f' (y - x)" 0 "at x within s" "f x"]
1620 have *:"((\<lambda>x'. h (f x + f' (x' - x)) ((1/(norm (x' - x))) *\<^sub>R (g x' - (g x + g' (x' - x))))
1621 + h ((1/ (norm (x' - x))) *\<^sub>R (f x' - (f x + f' (x' - x)))) (g x')) ---> h (f x) 0 + h 0 (g x)) (at x within s)"
1622 apply-apply(rule tendsto_add) apply(rule_tac[!] Lim_bilinear[OF _ _ assms(3)])
1623 using assms(1-2) unfolding has_derivative_within by auto
1624 guess B using bounded_bilinear.pos_bounded[OF assms(3)] .. note B=this
1625 guess C using f'.pos_bounded .. note C=this
1626 guess D using g'.pos_bounded .. note D=this
1627 have bcd:"B * C * D > 0" using B C D by (auto intro!: mult_pos_pos)
1628 have **:"((\<lambda>y. (1/(norm(y - x))) *\<^sub>R (h (f'(y - x)) (g'(y - x)))) ---> 0) (at x within s)"
1629 unfolding Lim_within
1630 proof(rule,rule) case goal1
1631 hence "e/(B*C*D)>0" using B C D by(auto intro!:divide_pos_pos mult_pos_pos)
1632 thus ?case apply(rule_tac x="e/(B*C*D)" in exI,rule)
1633 proof(rule,rule,erule conjE)
1634 fix y assume as:"y \<in> s" "0 < dist y x" "dist y x < e / (B * C * D)"
1635 have "norm (h (f' (y - x)) (g' (y - x))) \<le> norm (f' (y - x)) * norm (g' (y - x)) * B" using B by auto
1636 also have "\<dots> \<le> (norm (y - x) * C) * (D * norm (y - x)) * B"
1637 apply(rule mult_right_mono)
1638 apply(rule mult_mono) using B C D
1639 by (auto simp add: field_simps intro!:mult_nonneg_nonneg)
1640 also have "\<dots> = (B * C * D * norm (y - x)) * norm (y - x)"
1641 by (auto simp add: field_simps)
1642 also have "\<dots> < e * norm (y - x)"
1643 apply(rule mult_strict_right_mono)
1644 using as(3)[unfolded dist_norm] and as(2)
1645 unfolding pos_less_divide_eq[OF bcd] by (auto simp add: field_simps)
1646 finally show "dist ((1 / norm (y - x)) *\<^sub>R h (f' (y - x)) (g' (y - x))) 0 < e"
1647 unfolding dist_norm apply-apply(cases "y = x")
1648 by(auto simp add: field_simps)
1651 have "bounded_linear (\<lambda>d. h (f x) (g' d) + h (f' d) (g x))"
1652 apply (rule bounded_linear_add)
1653 apply (rule bounded_linear_compose [OF h.bounded_linear_right `bounded_linear g'`])
1654 apply (rule bounded_linear_compose [OF h.bounded_linear_left `bounded_linear f'`])
1656 thus ?thesis using tendsto_add[OF * **] unfolding has_derivative_within
1657 unfolding g'.add f'.scaleR f'.add g'.scaleR f'.diff g'.diff
1658 h.add_right h.add_left scaleR_right_distrib h.scaleR_left h.scaleR_right h.diff_right h.diff_left
1659 scaleR_right_diff_distrib h.zero_right h.zero_left
1660 by(auto simp add:field_simps)
1663 lemma has_derivative_bilinear_at:
1664 assumes "(f has_derivative f') (at x)"
1665 assumes "(g has_derivative g') (at x)"
1666 assumes "bounded_bilinear h"
1667 shows "((\<lambda>x. h (f x) (g x)) has_derivative (\<lambda>d. h (f x) (g' d) + h (f' d) (g x))) (at x)"
1668 using has_derivative_bilinear_within[of f f' x UNIV g g' h] assms by simp
1670 subsection {* Considering derivative @{typ "real \<Rightarrow> 'b\<Colon>real_normed_vector"} as a vector. *}
1672 definition has_vector_derivative :: "(real \<Rightarrow> 'b::real_normed_vector) \<Rightarrow> 'b \<Rightarrow> (real filter \<Rightarrow> bool)"
1673 (infixl "has'_vector'_derivative" 12) where
1674 "(f has_vector_derivative f') net \<equiv> (f has_derivative (\<lambda>x. x *\<^sub>R f')) net"
1676 definition "vector_derivative f net \<equiv> (SOME f'. (f has_vector_derivative f') net)"
1678 lemma vector_derivative_works:
1679 fixes f::"real \<Rightarrow> 'a::real_normed_vector"
1680 shows "f differentiable net \<longleftrightarrow> (f has_vector_derivative (vector_derivative f net)) net" (is "?l = ?r")
1682 assume ?l guess f' using `?l`[unfolded differentiable_def] .. note f' = this
1683 then interpret bounded_linear f' by auto
1684 show ?r unfolding vector_derivative_def has_vector_derivative_def
1685 apply-apply(rule someI_ex,rule_tac x="f' 1" in exI)
1686 using f' unfolding scaleR[THEN sym] by auto
1689 unfolding vector_derivative_def has_vector_derivative_def differentiable_def
1693 lemma has_vector_derivative_withinI_DERIV:
1694 assumes f: "DERIV f x :> y" shows "(f has_vector_derivative y) (at x within s)"
1695 unfolding has_vector_derivative_def real_scaleR_def
1696 apply (rule has_derivative_at_within)
1697 using DERIV_conv_has_derivative[THEN iffD1, OF f]
1698 apply (subst mult_commute) .
1700 lemma vector_derivative_unique_at:
1701 assumes "(f has_vector_derivative f') (at x)"
1702 assumes "(f has_vector_derivative f'') (at x)"
1705 have "(\<lambda>x. x *\<^sub>R f') = (\<lambda>x. x *\<^sub>R f'')"
1706 using assms [unfolded has_vector_derivative_def]
1707 by (rule frechet_derivative_unique_at)
1708 thus ?thesis unfolding fun_eq_iff by auto
1711 lemma vector_derivative_unique_within_closed_interval:
1712 fixes f::"real \<Rightarrow> 'n::ordered_euclidean_space"
1713 assumes "a < b" and "x \<in> {a..b}"
1714 assumes "(f has_vector_derivative f') (at x within {a..b})"
1715 assumes "(f has_vector_derivative f'') (at x within {a..b})"
1718 have *:"(\<lambda>x. x *\<^sub>R f') = (\<lambda>x. x *\<^sub>R f'')"
1719 apply(rule frechet_derivative_unique_within_closed_interval[of "a" "b"])
1720 using assms(3-)[unfolded has_vector_derivative_def] using assms(1-2)
1721 by (auto simp: Basis_real_def)
1724 assume "f' \<noteq> f''"
1726 hence "(\<lambda>x. x *\<^sub>R f') 1 = (\<lambda>x. x *\<^sub>R f'') 1"
1727 using * by (auto simp: fun_eq_iff)
1728 ultimately show False unfolding o_def by auto
1732 lemma vector_derivative_at:
1733 shows "(f has_vector_derivative f') (at x) \<Longrightarrow> vector_derivative f (at x) = f'"
1734 apply(rule vector_derivative_unique_at) defer apply assumption
1735 unfolding vector_derivative_works[THEN sym] differentiable_def
1736 unfolding has_vector_derivative_def by auto
1738 lemma vector_derivative_within_closed_interval:
1739 fixes f::"real \<Rightarrow> 'a::ordered_euclidean_space"
1740 assumes "a < b" and "x \<in> {a..b}"
1741 assumes "(f has_vector_derivative f') (at x within {a..b})"
1742 shows "vector_derivative f (at x within {a..b}) = f'"
1743 apply(rule vector_derivative_unique_within_closed_interval)
1744 using vector_derivative_works[unfolded differentiable_def]
1745 using assms by(auto simp add:has_vector_derivative_def)
1747 lemma has_vector_derivative_within_subset:
1748 "(f has_vector_derivative f') (at x within s) \<Longrightarrow> t \<subseteq> s \<Longrightarrow> (f has_vector_derivative f') (at x within t)"
1749 unfolding has_vector_derivative_def apply(rule has_derivative_within_subset) by auto
1751 lemma has_vector_derivative_const:
1752 "((\<lambda>x. c) has_vector_derivative 0) net"
1753 unfolding has_vector_derivative_def using has_derivative_const by auto
1755 lemma has_vector_derivative_id: "((\<lambda>x::real. x) has_vector_derivative 1) net"
1756 unfolding has_vector_derivative_def using has_derivative_id by auto
1758 lemma has_vector_derivative_cmul:
1759 "(f has_vector_derivative f') net \<Longrightarrow> ((\<lambda>x. c *\<^sub>R f x) has_vector_derivative (c *\<^sub>R f')) net"
1760 unfolding has_vector_derivative_def
1761 apply (drule scaleR_right_has_derivative)
1762 by (auto simp add: algebra_simps)
1764 lemma has_vector_derivative_cmul_eq:
1765 assumes "c \<noteq> 0"
1766 shows "(((\<lambda>x. c *\<^sub>R f x) has_vector_derivative (c *\<^sub>R f')) net \<longleftrightarrow> (f has_vector_derivative f') net)"
1767 apply rule apply(drule has_vector_derivative_cmul[where c="1/c"]) defer
1768 apply(rule has_vector_derivative_cmul) using assms by auto
1770 lemma has_vector_derivative_neg:
1771 "(f has_vector_derivative f') net \<Longrightarrow> ((\<lambda>x. -(f x)) has_vector_derivative (- f')) net"
1772 unfolding has_vector_derivative_def apply(drule has_derivative_neg) by auto
1774 lemma has_vector_derivative_add:
1775 assumes "(f has_vector_derivative f') net"
1776 assumes "(g has_vector_derivative g') net"
1777 shows "((\<lambda>x. f(x) + g(x)) has_vector_derivative (f' + g')) net"
1778 using has_derivative_add[OF assms[unfolded has_vector_derivative_def]]
1779 unfolding has_vector_derivative_def unfolding scaleR_right_distrib by auto
1781 lemma has_vector_derivative_sub:
1782 assumes "(f has_vector_derivative f') net"
1783 assumes "(g has_vector_derivative g') net"
1784 shows "((\<lambda>x. f(x) - g(x)) has_vector_derivative (f' - g')) net"
1785 using has_derivative_sub[OF assms[unfolded has_vector_derivative_def]]
1786 unfolding has_vector_derivative_def scaleR_right_diff_distrib by auto
1788 lemma has_vector_derivative_bilinear_within:
1789 assumes "(f has_vector_derivative f') (at x within s)"
1790 assumes "(g has_vector_derivative g') (at x within s)"
1791 assumes "bounded_bilinear h"
1792 shows "((\<lambda>x. h (f x) (g x)) has_vector_derivative (h (f x) g' + h f' (g x))) (at x within s)"
1794 interpret bounded_bilinear h using assms by auto
1795 show ?thesis using has_derivative_bilinear_within[OF assms(1-2)[unfolded has_vector_derivative_def], of h]
1796 unfolding o_def has_vector_derivative_def
1797 using assms(3) unfolding scaleR_right scaleR_left scaleR_right_distrib
1801 lemma has_vector_derivative_bilinear_at:
1802 assumes "(f has_vector_derivative f') (at x)"
1803 assumes "(g has_vector_derivative g') (at x)"
1804 assumes "bounded_bilinear h"
1805 shows "((\<lambda>x. h (f x) (g x)) has_vector_derivative (h (f x) g' + h f' (g x))) (at x)"
1806 using has_vector_derivative_bilinear_within[where s=UNIV] assms by simp
1808 lemma has_vector_derivative_at_within:
1809 "(f has_vector_derivative f') (at x) \<Longrightarrow> (f has_vector_derivative f') (at x within s)"
1810 unfolding has_vector_derivative_def
1811 by (rule has_derivative_at_within)
1813 lemma has_vector_derivative_transform_within:
1814 assumes "0 < d" and "x \<in> s" and "\<forall>x'\<in>s. dist x' x < d \<longrightarrow> f x' = g x'"
1815 assumes "(f has_vector_derivative f') (at x within s)"
1816 shows "(g has_vector_derivative f') (at x within s)"
1817 using assms unfolding has_vector_derivative_def
1818 by (rule has_derivative_transform_within)
1820 lemma has_vector_derivative_transform_at:
1821 assumes "0 < d" and "\<forall>x'. dist x' x < d \<longrightarrow> f x' = g x'"
1822 assumes "(f has_vector_derivative f') (at x)"
1823 shows "(g has_vector_derivative f') (at x)"
1824 using assms unfolding has_vector_derivative_def
1825 by (rule has_derivative_transform_at)
1827 lemma has_vector_derivative_transform_within_open:
1828 assumes "open s" and "x \<in> s" and "\<forall>y\<in>s. f y = g y"
1829 assumes "(f has_vector_derivative f') (at x)"
1830 shows "(g has_vector_derivative f') (at x)"
1831 using assms unfolding has_vector_derivative_def
1832 by (rule has_derivative_transform_within_open)
1834 lemma vector_diff_chain_at:
1835 assumes "(f has_vector_derivative f') (at x)"
1836 assumes "(g has_vector_derivative g') (at (f x))"
1837 shows "((g \<circ> f) has_vector_derivative (f' *\<^sub>R g')) (at x)"
1838 using assms(2) unfolding has_vector_derivative_def apply-
1839 apply(drule diff_chain_at[OF assms(1)[unfolded has_vector_derivative_def]])
1840 unfolding o_def real_scaleR_def scaleR_scaleR .
1842 lemma vector_diff_chain_within:
1843 assumes "(f has_vector_derivative f') (at x within s)"
1844 assumes "(g has_vector_derivative g') (at (f x) within f ` s)"
1845 shows "((g o f) has_vector_derivative (f' *\<^sub>R g')) (at x within s)"
1846 using assms(2) unfolding has_vector_derivative_def apply-
1847 apply(drule diff_chain_within[OF assms(1)[unfolded has_vector_derivative_def]])
1848 unfolding o_def real_scaleR_def scaleR_scaleR .