src/HOL/Multivariate_Analysis/Derivative.thy
author hoelzl
Thu, 17 Jan 2013 12:21:24 +0100
changeset 51954 ae7cd20ed118
parent 51541 899c9c4e4a4c
child 52500 d4d00c804645
permissions -rw-r--r--
replace convergent_imp_cauchy by LIMSEQ_imp_Cauchy
     1 (*  Title:                       HOL/Multivariate_Analysis/Derivative.thy
     2     Author:                      John Harrison
     3     Translation from HOL Light:  Robert Himmelmann, TU Muenchen
     4 *)
     5 
     6 header {* Multivariate calculus in Euclidean space. *}
     7 
     8 theory Derivative
     9 imports Brouwer_Fixpoint Operator_Norm
    10 begin
    11 
    12 (* Because I do not want to type this all the time *)
    13 lemmas linear_linear = linear_conv_bounded_linear[THEN sym]
    14 
    15 subsection {* Derivatives *}
    16 
    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.) *}
    20 
    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"
    25 
    26 lemma derivative_linear[dest]:
    27   "(f has_derivative f') net \<Longrightarrow> bounded_linear f'"
    28   unfolding has_derivative_def by auto
    29 
    30 lemma netlimit_at_vector:
    31   (* TODO: move *)
    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
    38     apply clarsimp
    39     apply (rule_tac x="a + scaleR (d / 2) (sgn (x - a))" in exI)
    40     apply (simp add: norm_sgn sgn_zero_iff x)
    41     done
    42   thus ?thesis
    43     by (rule netlimit_within [of a UNIV, unfolded within_UNIV])
    44 qed simp
    45 
    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])
    51 
    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)
    56 
    57 text {* These are the only cases we'll care about, probably. *}
    58 
    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)
    62 
    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
    66 
    67 text {* More explicit epsilon-delta forms. *}
    68 
    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)
    75 
    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
    81 
    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
    84 
    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)
    88 
    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))"
    93 proof -
    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)
   101   finally show ?thesis
   102     by (simp add: bounded_linear_mult_right has_derivative_within)
   103 qed
   104 
   105 lemma bounded_linear_imp_linear: "bounded_linear f \<Longrightarrow> linear f" (* TODO: move elsewhere *)
   106 proof -
   107   assume "bounded_linear f"
   108   then interpret f: bounded_linear f .
   109   show "linear f"
   110     by (simp add: f.add f.scaleR linear_def)
   111 qed
   112 
   113 lemma derivative_is_linear:
   114   "(f has_derivative f') net \<Longrightarrow> linear f'"
   115   by (rule derivative_linear [THEN bounded_linear_imp_linear])
   116 
   117 subsubsection {* Combining theorems. *}
   118 
   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)
   122 
   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)
   126 
   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)
   130 
   131 lemma (in bounded_linear) bounded_linear: "bounded_linear f" ..
   132 
   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
   137   apply safe
   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)
   141   done
   142 
   143 lemmas scaleR_right_has_derivative =
   144   bounded_linear.has_derivative [OF bounded_linear_scaleR_right]
   145 
   146 lemmas scaleR_left_has_derivative =
   147   bounded_linear.has_derivative [OF bounded_linear_scaleR_left]
   148 
   149 lemmas inner_right_has_derivative =
   150   bounded_linear.has_derivative [OF bounded_linear_inner_right]
   151 
   152 lemmas inner_left_has_derivative =
   153   bounded_linear.has_derivative [OF bounded_linear_inner_left]
   154 
   155 lemmas mult_right_has_derivative =
   156   bounded_linear.has_derivative [OF bounded_linear_mult_right]
   157 
   158 lemmas mult_left_has_derivative =
   159   bounded_linear.has_derivative [OF bounded_linear_mult_left]
   160 
   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
   165 
   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"
   169 proof-
   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)
   174 qed
   175 
   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)
   179 
   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)
   184 
   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. *}
   190 
   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
   197 
   198 subsubsection {* Limit transformation for derivatives *}
   199 
   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
   206 
   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
   211 
   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
   218 
   219 subsection {* Differentiability *}
   220 
   221 no_notation Deriv.differentiable (infixl "differentiable" 60)
   222 
   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)"
   225 
   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))"
   228 
   229 lemma differentiableI: "(f has_derivative f') net \<Longrightarrow> f differentiable net"
   230   unfolding differentiable_def by auto
   231 
   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
   234 
   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)
   239 
   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)
   244 
   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)])
   251 
   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
   257 
   258 subsection {* Frechet derivative and Jacobian matrix. *}
   259 
   260 definition "frechet_derivative f net = (SOME f'. (f has_derivative f') net)"
   261 
   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"] ..
   265 
   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)
   270 
   271 subsection {* Differentiability implies continuity *}
   272 
   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])
   281 
   282 lemma differentiable_imp_continuous_within:
   283   assumes "f differentiable (at x within s)" 
   284   shows "continuous (at x within s) f"
   285 proof-
   286   from assms guess f' unfolding differentiable_def has_derivative_within ..
   287   note f'=this
   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"
   290     using zero by auto
   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
   299     apply (rule, rule)
   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 *)
   304 qed
   305 
   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])
   309 
   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
   314 
   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
   318 
   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
   322 
   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
   326 
   327 lemma differentiable_on_empty: "f differentiable_on {}"
   328   unfolding differentiable_on_def by auto
   329 
   330 text {* Several results are easier using a "multiplied-out" variant.
   331 (I got this idea from Dieudonne's proof of the chain rule). *}
   332 
   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")
   336 proof
   337   assume ?lhs thus ?rhs
   338     unfolding has_derivative_within apply-apply(erule conjE,rule,assumption)
   339     unfolding Lim_within
   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)
   343   proof-
   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)
   349     next
   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)
   355     qed
   356   qed
   357 next
   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)
   365   proof-
   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)
   371   qed auto
   372 qed
   373 
   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
   378 
   379 subsection {* The chain rule. *}
   380 
   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)
   389 proof(rule,rule)
   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
   399 
   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)
   403 
   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
   408 
   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 
   419 
   420     hence "norm (f y - f x) \<le> d * (1 + B1)" apply-
   421       apply(rule order_trans,assumption,rule mult_right_mono)
   422       using as B1 by auto 
   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
   431     
   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
   442     
   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)"
   444       using 5 4 by auto
   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)
   447       by assumption
   448   qed
   449 qed
   450 
   451 lemma diff_chain_at:
   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"]
   455   by simp
   456 
   457 subsection {* Composition rules stated just for differentiability. *}
   458 
   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
   462 
   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
   466 
   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
   472 
   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
   478 
   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
   483 
   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
   489 
   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"
   493 proof-
   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
   497 qed
   498 
   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
   502 
   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)
   506 
   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)
   511 
   512 subsection {* Uniqueness of derivative *}
   513 
   514 text {*
   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.
   517 *}
   518     
   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)"
   524   shows "f' = f''"
   525 proof-
   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
   530   proof(rule,rule)
   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)
   536   qed
   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"]
   558       unfolding dist_norm
   559       unfolding f'.scaleR f''.scaleR f'.add f''.add f'.diff f''.diff
   560         scaleR_scaleR scaleR_right_diff_distrib scaleR_right_distrib
   561       using i by auto
   562   qed
   563 qed
   564 
   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)
   569 
   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
   573 
   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})"
   579   shows "f' = f''"
   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)
   591   next 
   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
   594     moreover {
   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"
   596         by auto
   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
   600     }
   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)
   608   qed
   609 qed
   610 
   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})"
   616   shows "f' = f''"
   617 proof -
   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)
   622 qed
   623 
   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
   628 
   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 
   637 
   638 subsection {* The traditional Rolle theorem in one dimension. *}
   639 
   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")
   644 proof -
   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)
   648   then show ?thesis
   649     unfolding linear_setsum_mul[OF lf fA, symmetric]
   650     unfolding euclidean_representation ..
   651 qed
   652 
   653 text {* We do not introduce @{text jacobian}, which is defined on matrices, instead we use
   654   the unfolding of it. *}
   655 
   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")
   661 proof
   662   assume *: ?differentiable
   663   { fix h i
   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)
   670 
   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")
   677 proof (rule ccontr)
   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
   693       by simp
   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>"
   696       using j k
   697       by (simp add: inner_simps field_simps inner_Basis setsum_cases if_dist) }
   698   note * = this
   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)
   710 qed
   711 
   712 text {* In particular if we have a mapping into @{typ "real"}. *}
   713 
   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)"
   720 proof -
   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)
   731 qed
   732 
   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)"
   737 proof-
   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))"
   739   proof-
   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
   744     show ?thesis
   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)
   749         using d c by auto
   750     next
   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
   755       thus ?thesis
   756         apply(rule_tac x=e in bexI) unfolding e_def using assms(1) by auto
   757     qed
   758   qed
   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
   767 qed
   768 
   769 subsection {* One-dimensional mean value theorem. *}
   770 
   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))"
   775 proof-
   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"])
   778     defer
   779     apply(rule continuous_on_intros assms(2))+
   780   proof
   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)
   786   then guess x ..
   787   thus ?thesis apply(rule_tac x=x in bexI)
   788     apply(drule fun_cong[of _ _ "b - a"]) by auto
   789 qed
   790 
   791 lemma mvt_simple:
   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)"
   795   apply(rule mvt)
   796   apply(rule assms(1), rule differentiable_imp_continuous_on)
   797   unfolding differentiable_on_def differentiable_def defer
   798 proof
   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])
   803     using x by auto
   804 qed(insert assms(2), auto)
   805 
   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
   816 qed
   817 
   818 text {* A nice generalization (see Havin's proof of 5.19 from Rudin's book). *}
   819 
   820 lemma mvt_general:
   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))"
   825 proof-
   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")
   833     case False
   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)
   843   next
   844     case True thus ?thesis using assms(1)
   845       apply (rule_tac x="(a + b) /2" in bexI) by auto
   846   qed
   847 qed
   848 
   849 text {* Still more general bound theorem. *}
   850 
   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)"
   856 proof-
   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)"
   870   proof rule
   871     case goal1
   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
   877     thus ?case
   878       unfolding has_derivative_within_open[OF goal1 open_interval] by auto
   879   qed
   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"
   882   proof-
   883     case goal1
   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
   891   qed
   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)
   897 qed
   898 
   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
   906 
   907 text {* In particular. *}
   908 
   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"
   913 proof(cases "s={}")
   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
   916     thus ?case
   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
   920 qed auto
   921 
   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"
   925   shows "f x = c"
   926   using has_derivative_zero_constant[OF assms(1,4)] using assms(2-3,5) by auto
   927 
   928 subsection {* Differentiability of inverse function (most basic form). *}
   929 
   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)"
   936 proof-
   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)"
   943   proof(rule,rule)
   944     case goal1
   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
   951     proof(rule,rule)
   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)"
   970         by simp
   971     qed auto
   972   qed
   973   have *:"(0::real) < 1 / 2" by auto
   974   guess d using lem1[rule_format,OF *] .. note d=this
   975   def B\<equiv>"C*2"
   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)
   986   qed
   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
   992     show ?case
   993       apply(rule_tac x=k in exI,rule) defer
   994     proof(rule,rule)
   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)"
   997         using d' k by auto
   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)
  1004   qed
  1005 qed
  1006 
  1007 text {* Simply rewrite that based on the domain point x. *}
  1008 
  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
  1015 
  1016 text {* This is the version in Dieudonne', assuming continuity of f and g. *}
  1017 
  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
  1026 
  1027 text {* Here's the simplest way of not assuming much about g. *}
  1028 
  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))"
  1034 proof-
  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`] ..
  1039   } note * = this
  1040   show ?thesis
  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)
  1046 qed
  1047 
  1048 subsection {* Proving surjectivity via Brouwer fixpoint theorem. *}
  1049 
  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"
  1055 proof-
  1056   have *:"\<And>x y. f y = x \<longleftrightarrow> x + (y - f y) = y"
  1057     by(auto simp add:algebra_simps)
  1058   show ?thesis
  1059     unfolding *
  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
  1062 qed
  1063 
  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
  1072 
  1073 text {* See Sussmann: "Multidifferential calculus", Theorem 2.1.1 *}
  1074 
  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)"
  1081 proof- 
  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)
  1095   proof-
  1096     show "continuous_on (cball (f x) e) (\<lambda>y. f (x + g' (y - f x)))"
  1097       unfolding g'.diff
  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)
  1102     proof-
  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
  1113     qed
  1114   next
  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
  1143   proof
  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
  1157   qed(insert e, auto)
  1158 qed
  1159 
  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. *}
  1164 
  1165 (* move  before left_inverse_linear in Euclidean_Space*)
  1166 
  1167  lemma right_inverse_linear:
  1168    fixes f::"'a::euclidean_space => 'a"
  1169    assumes lf: "linear f" and gf: "f o g = id"
  1170    shows "linear g"
  1171  proof-
  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
  1179  qed
  1180  
  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))"
  1186 proof-
  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
  1199   proof(rule,rule)
  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)
  1216     qed
  1217   qed
  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"
  1223   proof- case goal1
  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
  1227   qed
  1228   ultimately show ?thesis
  1229     apply- apply(rule has_derivative_inverse_basic_x[OF assms(5)])
  1230     using assms by auto
  1231 qed
  1232 
  1233 text {* A rewrite based on the other domain. *}
  1234 
  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
  1242 
  1243 text {* On a region. *}
  1244 
  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])
  1251   apply(rule assms)+
  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
  1255 
  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. *}
  1261 
  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)
  1266 
  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)"
  1273 proof-
  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`] ..
  1285   note d2=this
  1286   guess d using real_lbound_gt_zero[OF d1[THEN conjunct1] d2[THEN conjunct1]] ..
  1287   note d = this
  1288   show ?thesis
  1289   proof
  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"
  1292     proof (intro strip)
  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)
  1301       proof-
  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
  1330       qed
  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
  1335     qed
  1336   qed auto
  1337 qed
  1338 
  1339 subsection {* Uniformly convergent sequence of derivatives. *}
  1340 
  1341 lemma has_derivative_sequence_lipschitz_lemma:
  1342   fixes f::"nat \<Rightarrow> 'm::euclidean_space \<Rightarrow> 'n::euclidean_space"
  1343   assumes "convex s"
  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)"
  1347 proof (default)+
  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)
  1352   proof-
  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`)+
  1356     { fix h
  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]
  1369       by auto
  1370   qed
  1371 qed
  1372 
  1373 lemma has_derivative_sequence_lipschitz:
  1374   fixes f::"nat \<Rightarrow> 'm::euclidean_space \<Rightarrow> 'n::euclidean_space"
  1375   assumes "convex s"
  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)"
  1378   assumes "0 < e"
  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)"
  1380 proof(rule,rule)
  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)] ..
  1383   thus ?case
  1384     apply(rule_tac x=N in exI)
  1385     apply(rule has_derivative_sequence_lipschitz_lemma[where e="1/2 *e", unfolded *])
  1386     using assms by auto
  1387 qed
  1388 
  1389 lemma has_derivative_sequence:
  1390   fixes f::"nat\<Rightarrow> 'm::euclidean_space \<Rightarrow> 'n::euclidean_space"
  1391   assumes "convex s"
  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)"
  1397 proof-
  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
  1403   proof
  1404     fix x assume "x\<in>s" show "Cauchy (\<lambda>n. f n x)"
  1405     proof(cases "x=x0")
  1406       case True thus ?thesis using LIMSEQ_imp_Cauchy[OF assms(5)] by auto
  1407     next
  1408       case False show ?thesis unfolding Cauchy_def
  1409       proof(rule,rule)
  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)
  1417         proof(default+)
  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
  1423             by auto
  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
  1428         qed
  1429       qed
  1430     qed
  1431   qed
  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)"
  1434   proof(rule,rule)
  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)
  1439     proof(default+)
  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)
  1444       proof(rule,rule)
  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)
  1449       qed
  1450       thus "norm (f n x - f n y - (g x - g y)) \<le> e * norm (x - y)"
  1451         apply-
  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
  1454     qed
  1455   qed
  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"
  1464       proof(cases "u=0")
  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
  1468       next
  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)
  1477         qed
  1478       qed
  1479     qed
  1480     show "bounded_linear (g' x)"
  1481       unfolding linear_linear linear_def
  1482       apply(rule,rule,rule) defer
  1483     proof(rule,rule)
  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])+
  1496     qed
  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])
  1504       proof(rule,rule)
  1505         fix y assume as:"y \<in> s" "norm (y - x) < d1"
  1506         let ?N ="max N1 N2"
  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
  1510         moreover
  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
  1513         ultimately
  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)
  1517         moreover
  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)
  1523       qed
  1524     qed
  1525   qed
  1526 qed
  1527 
  1528 text {* Can choose to line up antiderivatives if we want. *}
  1529 
  1530 lemma has_antiderivative_sequence:
  1531   fixes f::"nat\<Rightarrow> 'm::euclidean_space \<Rightarrow> 'n::euclidean_space"
  1532   assumes "convex s"
  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)"
  1536 proof(cases "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
  1539   show ?thesis
  1540     apply(rule *)
  1541     apply(rule has_derivative_sequence[OF assms(1) _ assms(3), of "\<lambda>n x. f n x + (f 0 a - f n a)"])
  1542     apply(rule,rule)
  1543     apply(rule has_derivative_add_const, rule assms(2)[rule_format], assumption)  
  1544     apply(rule `a\<in>s`) by auto
  1545 qed auto
  1546 
  1547 lemma has_antiderivative_limit:
  1548   fixes g'::"'m::euclidean_space \<Rightarrow> 'm \<Rightarrow> 'n::euclidean_space"
  1549   assumes "convex s"
  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)"
  1552 proof-
  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
  1559   proof(rule,rule)
  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)
  1563     proof(default+)
  1564       case goal1
  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) 
  1567       show ?case
  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
  1570     qed
  1571   qed(insert f,auto)
  1572 qed
  1573 
  1574 subsection {* Differentiation of a series. *}
  1575 
  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"
  1578 
  1579 lemma has_derivative_series:
  1580   fixes f::"nat \<Rightarrow> 'm::euclidean_space \<Rightarrow> 'n::euclidean_space"
  1581   assumes "convex s"
  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)])
  1588   apply(rule,rule)
  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
  1592 
  1593 subsection {* Derivative with composed bilinear function. *}
  1594 
  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)"
  1600 proof-
  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
  1604   moreover
  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
  1610     using assms by auto
  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"]
  1618     by auto
  1619   ultimately
  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)
  1649     qed
  1650   qed
  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'`])
  1655     done
  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)
  1661 qed
  1662 
  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
  1669 
  1670 subsection {* Considering derivative @{typ "real \<Rightarrow> 'b\<Colon>real_normed_vector"} as a vector. *}
  1671 
  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"
  1675 
  1676 definition "vector_derivative f net \<equiv> (SOME f'. (f has_vector_derivative f') net)"
  1677 
  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")
  1681 proof
  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
  1687 next
  1688   assume ?r thus ?l
  1689     unfolding vector_derivative_def has_vector_derivative_def differentiable_def
  1690     by auto
  1691 qed
  1692 
  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) .
  1699 
  1700 lemma vector_derivative_unique_at:
  1701   assumes "(f has_vector_derivative f') (at x)"
  1702   assumes "(f has_vector_derivative f'') (at x)"
  1703   shows "f' = f''"
  1704 proof-
  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
  1709 qed
  1710 
  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})"
  1716   shows "f' = f''"
  1717 proof-
  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)
  1722   show ?thesis
  1723   proof(rule ccontr)
  1724     assume "f' \<noteq> f''"
  1725     moreover
  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
  1729   qed
  1730 qed
  1731 
  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
  1737 
  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)
  1746 
  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
  1750 
  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
  1754 
  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
  1757 
  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)
  1763 
  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
  1769 
  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
  1773 
  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
  1780 
  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
  1787 
  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)"
  1793 proof-
  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
  1798     by auto
  1799 qed
  1800 
  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
  1807 
  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)
  1812 
  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)
  1819 
  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)
  1826 
  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)
  1833 
  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 .
  1841 
  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 .
  1849 
  1850 end