src/HOL/Analysis/Weierstrass_Theorems.thy
changeset 68833 fde093888c16
parent 68601 7828f3b85156
child 69260 0a9688695a1b
equal deleted inserted replaced
68824:7414ce0256e1 68833:fde093888c16
     4 
     4 
     5 theory Weierstrass_Theorems
     5 theory Weierstrass_Theorems
     6 imports Uniform_Limit Path_Connected Derivative
     6 imports Uniform_Limit Path_Connected Derivative
     7 begin
     7 begin
     8 
     8 
     9 subsection \<open>Bernstein polynomials\<close>
     9 subsection%important \<open>Bernstein polynomials\<close>
    10 
    10 
    11 definition Bernstein :: "[nat,nat,real] \<Rightarrow> real" where
    11 definition%important Bernstein :: "[nat,nat,real] \<Rightarrow> real" where
    12   "Bernstein n k x \<equiv> of_nat (n choose k) * x ^ k * (1 - x) ^ (n - k)"
    12   "Bernstein n k x \<equiv> of_nat (n choose k) * x ^ k * (1 - x) ^ (n - k)"
    13 
    13 
    14 lemma Bernstein_nonneg: "\<lbrakk>0 \<le> x; x \<le> 1\<rbrakk> \<Longrightarrow> 0 \<le> Bernstein n k x"
    14 lemma%unimportant Bernstein_nonneg: "\<lbrakk>0 \<le> x; x \<le> 1\<rbrakk> \<Longrightarrow> 0 \<le> Bernstein n k x"
    15   by (simp add: Bernstein_def)
    15   by (simp add: Bernstein_def)
    16 
    16 
    17 lemma Bernstein_pos: "\<lbrakk>0 < x; x < 1; k \<le> n\<rbrakk> \<Longrightarrow> 0 < Bernstein n k x"
    17 lemma%unimportant Bernstein_pos: "\<lbrakk>0 < x; x < 1; k \<le> n\<rbrakk> \<Longrightarrow> 0 < Bernstein n k x"
    18   by (simp add: Bernstein_def)
    18   by (simp add: Bernstein_def)
    19 
    19 
    20 lemma sum_Bernstein [simp]: "(\<Sum>k\<le>n. Bernstein n k x) = 1"
    20 lemma%unimportant sum_Bernstein [simp]: "(\<Sum>k\<le>n. Bernstein n k x) = 1"
    21   using binomial_ring [of x "1-x" n]
    21   using binomial_ring [of x "1-x" n]
    22   by (simp add: Bernstein_def)
    22   by (simp add: Bernstein_def)
    23 
    23 
    24 lemma binomial_deriv1:
    24 lemma%unimportant binomial_deriv1:
    25     "(\<Sum>k\<le>n. (of_nat k * of_nat (n choose k)) * a^(k-1) * b^(n-k)) = real_of_nat n * (a+b) ^ (n-1)"
    25     "(\<Sum>k\<le>n. (of_nat k * of_nat (n choose k)) * a^(k-1) * b^(n-k)) = real_of_nat n * (a+b) ^ (n-1)"
    26   apply (rule DERIV_unique [where f = "\<lambda>a. (a+b)^n" and x=a])
    26   apply (rule DERIV_unique [where f = "\<lambda>a. (a+b)^n" and x=a])
    27   apply (subst binomial_ring)
    27   apply (subst binomial_ring)
    28   apply (rule derivative_eq_intros sum.cong | simp add: atMost_atLeast0)+
    28   apply (rule derivative_eq_intros sum.cong | simp add: atMost_atLeast0)+
    29   done
    29   done
    30 
    30 
    31 lemma binomial_deriv2:
    31 lemma%unimportant binomial_deriv2:
    32     "(\<Sum>k\<le>n. (of_nat k * of_nat (k-1) * of_nat (n choose k)) * a^(k-2) * b^(n-k)) =
    32     "(\<Sum>k\<le>n. (of_nat k * of_nat (k-1) * of_nat (n choose k)) * a^(k-2) * b^(n-k)) =
    33      of_nat n * of_nat (n-1) * (a+b::real) ^ (n-2)"
    33      of_nat n * of_nat (n-1) * (a+b::real) ^ (n-2)"
    34   apply (rule DERIV_unique [where f = "\<lambda>a. of_nat n * (a+b::real) ^ (n-1)" and x=a])
    34   apply (rule DERIV_unique [where f = "\<lambda>a. of_nat n * (a+b::real) ^ (n-1)" and x=a])
    35   apply (subst binomial_deriv1 [symmetric])
    35   apply (subst binomial_deriv1 [symmetric])
    36   apply (rule derivative_eq_intros sum.cong | simp add: Num.numeral_2_eq_2)+
    36   apply (rule derivative_eq_intros sum.cong | simp add: Num.numeral_2_eq_2)+
    37   done
    37   done
    38 
    38 
    39 lemma sum_k_Bernstein [simp]: "(\<Sum>k\<le>n. real k * Bernstein n k x) = of_nat n * x"
    39 lemma%important sum_k_Bernstein [simp]: "(\<Sum>k\<le>n. real k * Bernstein n k x) = of_nat n * x"
    40   apply (subst binomial_deriv1 [of n x "1-x", simplified, symmetric])
    40   apply (subst binomial_deriv1 [of n x "1-x", simplified, symmetric])
    41   apply (simp add: sum_distrib_right)
    41   apply (simp add: sum_distrib_right)
    42   apply (auto simp: Bernstein_def algebra_simps power_eq_if intro!: sum.cong)
    42   apply (auto simp: Bernstein_def algebra_simps power_eq_if intro!: sum.cong)
    43   done
    43   done
    44 
    44 
    45 lemma sum_kk_Bernstein [simp]: "(\<Sum>k\<le>n. real k * (real k - 1) * Bernstein n k x) = real n * (real n - 1) * x\<^sup>2"
    45 lemma%important sum_kk_Bernstein [simp]: "(\<Sum>k\<le>n. real k * (real k - 1) * Bernstein n k x) = real n * (real n - 1) * x\<^sup>2"
    46 proof -
    46 proof%unimportant -
    47   have "(\<Sum>k\<le>n. real k * (real k - 1) * Bernstein n k x) =
    47   have "(\<Sum>k\<le>n. real k * (real k - 1) * Bernstein n k x) =
    48         (\<Sum>k\<le>n. real k * real (k - Suc 0) * real (n choose k) * x ^ (k - 2) * (1 - x) ^ (n - k) * x\<^sup>2)"
    48         (\<Sum>k\<le>n. real k * real (k - Suc 0) * real (n choose k) * x ^ (k - 2) * (1 - x) ^ (n - k) * x\<^sup>2)"
    49   proof (rule sum.cong [OF refl], simp)
    49   proof (rule sum.cong [OF refl], simp)
    50     fix k
    50     fix k
    51     assume "k \<le> n"
    51     assume "k \<le> n"
    63     by auto
    63     by auto
    64   finally show ?thesis
    64   finally show ?thesis
    65     by auto
    65     by auto
    66 qed
    66 qed
    67 
    67 
    68 subsection \<open>Explicit Bernstein version of the 1D Weierstrass approximation theorem\<close>
    68 subsection%important \<open>Explicit Bernstein version of the 1D Weierstrass approximation theorem\<close>
    69 
    69 
    70 lemma Bernstein_Weierstrass:
    70 lemma%important Bernstein_Weierstrass:
    71   fixes f :: "real \<Rightarrow> real"
    71   fixes f :: "real \<Rightarrow> real"
    72   assumes contf: "continuous_on {0..1} f" and e: "0 < e"
    72   assumes contf: "continuous_on {0..1} f" and e: "0 < e"
    73     shows "\<exists>N. \<forall>n x. N \<le> n \<and> x \<in> {0..1}
    73     shows "\<exists>N. \<forall>n x. N \<le> n \<and> x \<in> {0..1}
    74                     \<longrightarrow> \<bar>f x - (\<Sum>k\<le>n. f(k/n) * Bernstein n k x)\<bar> < e"
    74                     \<longrightarrow> \<bar>f x - (\<Sum>k\<le>n. f(k/n) * Bernstein n k x)\<bar> < e"
    75 proof -
    75 proof%unimportant -
    76   have "bounded (f ` {0..1})"
    76   have "bounded (f ` {0..1})"
    77     using compact_continuous_image compact_imp_bounded contf by blast
    77     using compact_continuous_image compact_imp_bounded contf by blast
    78   then obtain M where M: "\<And>x. 0 \<le> x \<Longrightarrow> x \<le> 1 \<Longrightarrow> \<bar>f x\<bar> \<le> M"
    78   then obtain M where M: "\<And>x. 0 \<le> x \<Longrightarrow> x \<le> 1 \<Longrightarrow> \<bar>f x\<bar> \<le> M"
    79     by (force simp add: bounded_iff)
    79     by (force simp add: bounded_iff)
    80   then have Mge0: "0 \<le> M" by force
    80   then have Mge0: "0 \<le> M" by force
   165   then show ?thesis
   165   then show ?thesis
   166     by auto
   166     by auto
   167 qed
   167 qed
   168 
   168 
   169 
   169 
   170 subsection \<open>General Stone-Weierstrass theorem\<close>
   170 subsection%important \<open>General Stone-Weierstrass theorem\<close>
   171 
   171 
   172 text\<open>Source:
   172 text\<open>Source:
   173 Bruno Brosowski and Frank Deutsch.
   173 Bruno Brosowski and Frank Deutsch.
   174 An Elementary Proof of the Stone-Weierstrass Theorem.
   174 An Elementary Proof of the Stone-Weierstrass Theorem.
   175 Proceedings of the American Mathematical Society
   175 Proceedings of the American Mathematical Society
   176 Volume 81, Number 1, January 1981.
   176 Volume 81, Number 1, January 1981.
   177 DOI: 10.2307/2043993  https://www.jstor.org/stable/2043993\<close>
   177 DOI: 10.2307/2043993  https://www.jstor.org/stable/2043993\<close>
   178 
   178 
   179 locale function_ring_on =
   179 locale%important function_ring_on =
   180   fixes R :: "('a::t2_space \<Rightarrow> real) set" and S :: "'a set"
   180   fixes R :: "('a::t2_space \<Rightarrow> real) set" and S :: "'a set"
   181   assumes compact: "compact S"
   181   assumes compact: "compact S"
   182   assumes continuous: "f \<in> R \<Longrightarrow> continuous_on S f"
   182   assumes continuous: "f \<in> R \<Longrightarrow> continuous_on S f"
   183   assumes add: "f \<in> R \<Longrightarrow> g \<in> R \<Longrightarrow> (\<lambda>x. f x + g x) \<in> R"
   183   assumes add: "f \<in> R \<Longrightarrow> g \<in> R \<Longrightarrow> (\<lambda>x. f x + g x) \<in> R"
   184   assumes mult: "f \<in> R \<Longrightarrow> g \<in> R \<Longrightarrow> (\<lambda>x. f x * g x) \<in> R"
   184   assumes mult: "f \<in> R \<Longrightarrow> g \<in> R \<Longrightarrow> (\<lambda>x. f x * g x) \<in> R"
   185   assumes const: "(\<lambda>_. c) \<in> R"
   185   assumes const: "(\<lambda>_. c) \<in> R"
   186   assumes separable: "x \<in> S \<Longrightarrow> y \<in> S \<Longrightarrow> x \<noteq> y \<Longrightarrow> \<exists>f\<in>R. f x \<noteq> f y"
   186   assumes separable: "x \<in> S \<Longrightarrow> y \<in> S \<Longrightarrow> x \<noteq> y \<Longrightarrow> \<exists>f\<in>R. f x \<noteq> f y"
   187 
   187 
   188 begin
   188 begin
   189   lemma minus: "f \<in> R \<Longrightarrow> (\<lambda>x. - f x) \<in> R"
   189   lemma%unimportant minus: "f \<in> R \<Longrightarrow> (\<lambda>x. - f x) \<in> R"
   190     by (frule mult [OF const [of "-1"]]) simp
   190     by (frule mult [OF const [of "-1"]]) simp
   191 
   191 
   192   lemma diff: "f \<in> R \<Longrightarrow> g \<in> R \<Longrightarrow> (\<lambda>x. f x - g x) \<in> R"
   192   lemma%unimportant diff: "f \<in> R \<Longrightarrow> g \<in> R \<Longrightarrow> (\<lambda>x. f x - g x) \<in> R"
   193     unfolding diff_conv_add_uminus by (metis add minus)
   193     unfolding diff_conv_add_uminus by (metis add minus)
   194 
   194 
   195   lemma power: "f \<in> R \<Longrightarrow> (\<lambda>x. f x ^ n) \<in> R"
   195   lemma%unimportant power: "f \<in> R \<Longrightarrow> (\<lambda>x. f x ^ n) \<in> R"
   196     by (induct n) (auto simp: const mult)
   196     by (induct n) (auto simp: const mult)
   197 
   197 
   198   lemma sum: "\<lbrakk>finite I; \<And>i. i \<in> I \<Longrightarrow> f i \<in> R\<rbrakk> \<Longrightarrow> (\<lambda>x. \<Sum>i \<in> I. f i x) \<in> R"
   198   lemma%unimportant sum: "\<lbrakk>finite I; \<And>i. i \<in> I \<Longrightarrow> f i \<in> R\<rbrakk> \<Longrightarrow> (\<lambda>x. \<Sum>i \<in> I. f i x) \<in> R"
   199     by (induct I rule: finite_induct; simp add: const add)
   199     by (induct I rule: finite_induct; simp add: const add)
   200 
   200 
   201   lemma prod: "\<lbrakk>finite I; \<And>i. i \<in> I \<Longrightarrow> f i \<in> R\<rbrakk> \<Longrightarrow> (\<lambda>x. \<Prod>i \<in> I. f i x) \<in> R"
   201   lemma%unimportant prod: "\<lbrakk>finite I; \<And>i. i \<in> I \<Longrightarrow> f i \<in> R\<rbrakk> \<Longrightarrow> (\<lambda>x. \<Prod>i \<in> I. f i x) \<in> R"
   202     by (induct I rule: finite_induct; simp add: const mult)
   202     by (induct I rule: finite_induct; simp add: const mult)
   203 
   203 
   204   definition normf :: "('a::t2_space \<Rightarrow> real) \<Rightarrow> real"
   204   definition%important normf :: "('a::t2_space \<Rightarrow> real) \<Rightarrow> real"
   205     where "normf f \<equiv> SUP x:S. \<bar>f x\<bar>"
   205     where "normf f \<equiv> SUP x:S. \<bar>f x\<bar>"
   206 
   206 
   207   lemma normf_upper: "\<lbrakk>continuous_on S f; x \<in> S\<rbrakk> \<Longrightarrow> \<bar>f x\<bar> \<le> normf f"
   207   lemma%unimportant normf_upper: "\<lbrakk>continuous_on S f; x \<in> S\<rbrakk> \<Longrightarrow> \<bar>f x\<bar> \<le> normf f"
   208     apply (simp add: normf_def)
   208     apply (simp add: normf_def)
   209     apply (rule cSUP_upper, assumption)
   209     apply (rule cSUP_upper, assumption)
   210     by (simp add: bounded_imp_bdd_above compact compact_continuous_image compact_imp_bounded continuous_on_rabs)
   210     by (simp add: bounded_imp_bdd_above compact compact_continuous_image compact_imp_bounded continuous_on_rabs)
   211 
   211 
   212   lemma normf_least: "S \<noteq> {} \<Longrightarrow> (\<And>x. x \<in> S \<Longrightarrow> \<bar>f x\<bar> \<le> M) \<Longrightarrow> normf f \<le> M"
   212   lemma%unimportant normf_least: "S \<noteq> {} \<Longrightarrow> (\<And>x. x \<in> S \<Longrightarrow> \<bar>f x\<bar> \<le> M) \<Longrightarrow> normf f \<le> M"
   213     by (simp add: normf_def cSUP_least)
   213     by (simp add: normf_def cSUP_least)
   214 
   214 
   215 end
   215 end
   216 
   216 
   217 lemma (in function_ring_on) one:
   217 lemma%important (in function_ring_on) one:
   218   assumes U: "open U" and t0: "t0 \<in> S" "t0 \<in> U" and t1: "t1 \<in> S-U"
   218   assumes U: "open U" and t0: "t0 \<in> S" "t0 \<in> U" and t1: "t1 \<in> S-U"
   219     shows "\<exists>V. open V \<and> t0 \<in> V \<and> S \<inter> V \<subseteq> U \<and>
   219     shows "\<exists>V. open V \<and> t0 \<in> V \<and> S \<inter> V \<subseteq> U \<and>
   220                (\<forall>e>0. \<exists>f \<in> R. f ` S \<subseteq> {0..1} \<and> (\<forall>t \<in> S \<inter> V. f t < e) \<and> (\<forall>t \<in> S - U. f t > 1 - e))"
   220                (\<forall>e>0. \<exists>f \<in> R. f ` S \<subseteq> {0..1} \<and> (\<forall>t \<in> S \<inter> V. f t < e) \<and> (\<forall>t \<in> S - U. f t > 1 - e))"
   221 proof -
   221 proof%unimportant -
   222   have "\<exists>pt \<in> R. pt t0 = 0 \<and> pt t > 0 \<and> pt ` S \<subseteq> {0..1}" if t: "t \<in> S - U" for t
   222   have "\<exists>pt \<in> R. pt t0 = 0 \<and> pt t > 0 \<and> pt ` S \<subseteq> {0..1}" if t: "t \<in> S - U" for t
   223   proof -
   223   proof -
   224     have "t \<noteq> t0" using t t0 by auto
   224     have "t \<noteq> t0" using t t0 by auto
   225     then obtain g where g: "g \<in> R" "g t \<noteq> g t0"
   225     then obtain g where g: "g \<in> R" "g t \<noteq> g t0"
   226       using separable t0  by (metis Diff_subset subset_eq t)
   226       using separable t0  by (metis Diff_subset subset_eq t)
   435   ultimately show ?thesis using V t0V
   435   ultimately show ?thesis using V t0V
   436     by blast
   436     by blast
   437 qed
   437 qed
   438 
   438 
   439 text\<open>Non-trivial case, with @{term A} and @{term B} both non-empty\<close>
   439 text\<open>Non-trivial case, with @{term A} and @{term B} both non-empty\<close>
   440 lemma (in function_ring_on) two_special:
   440 lemma%unimportant (in function_ring_on) two_special:
   441   assumes A: "closed A" "A \<subseteq> S" "a \<in> A"
   441   assumes A: "closed A" "A \<subseteq> S" "a \<in> A"
   442       and B: "closed B" "B \<subseteq> S" "b \<in> B"
   442       and B: "closed B" "B \<subseteq> S" "b \<in> B"
   443       and disj: "A \<inter> B = {}"
   443       and disj: "A \<inter> B = {}"
   444       and e: "0 < e" "e < 1"
   444       and e: "0 < e" "e < 1"
   445     shows "\<exists>f \<in> R. f ` S \<subseteq> {0..1} \<and> (\<forall>x \<in> A. f x < e) \<and> (\<forall>x \<in> B. f x > 1 - e)"
   445     shows "\<exists>f \<in> R. f ` S \<subseteq> {0..1} \<and> (\<forall>x \<in> A. f x < e) \<and> (\<forall>x \<in> B. f x > 1 - e)"
   540   }
   540   }
   541   ultimately
   541   ultimately
   542   show ?thesis by blast
   542   show ?thesis by blast
   543 qed
   543 qed
   544 
   544 
   545 lemma (in function_ring_on) two:
   545 lemma%unimportant (in function_ring_on) two:
   546   assumes A: "closed A" "A \<subseteq> S"
   546   assumes A: "closed A" "A \<subseteq> S"
   547       and B: "closed B" "B \<subseteq> S"
   547       and B: "closed B" "B \<subseteq> S"
   548       and disj: "A \<inter> B = {}"
   548       and disj: "A \<inter> B = {}"
   549       and e: "0 < e" "e < 1"
   549       and e: "0 < e" "e < 1"
   550     shows "\<exists>f \<in> R. f ` S \<subseteq> {0..1} \<and> (\<forall>x \<in> A. f x < e) \<and> (\<forall>x \<in> B. f x > 1 - e)"
   550     shows "\<exists>f \<in> R. f ` S \<subseteq> {0..1} \<and> (\<forall>x \<in> A. f x < e) \<and> (\<forall>x \<in> B. f x > 1 - e)"
   564     apply (auto simp: const)
   564     apply (auto simp: const)
   565     done
   565     done
   566 qed
   566 qed
   567 
   567 
   568 text\<open>The special case where @{term f} is non-negative and @{term"e<1/3"}\<close>
   568 text\<open>The special case where @{term f} is non-negative and @{term"e<1/3"}\<close>
   569 lemma (in function_ring_on) Stone_Weierstrass_special:
   569 lemma%important (in function_ring_on) Stone_Weierstrass_special:
   570   assumes f: "continuous_on S f" and fpos: "\<And>x. x \<in> S \<Longrightarrow> f x \<ge> 0"
   570   assumes f: "continuous_on S f" and fpos: "\<And>x. x \<in> S \<Longrightarrow> f x \<ge> 0"
   571       and e: "0 < e" "e < 1/3"
   571       and e: "0 < e" "e < 1/3"
   572   shows "\<exists>g \<in> R. \<forall>x\<in>S. \<bar>f x - g x\<bar> < 2*e"
   572   shows "\<exists>g \<in> R. \<forall>x\<in>S. \<bar>f x - g x\<bar> < 2*e"
   573 proof -
   573 proof%unimportant -
   574   define n where "n = 1 + nat \<lceil>normf f / e\<rceil>"
   574   define n where "n = 1 + nat \<lceil>normf f / e\<rceil>"
   575   define A where "A j = {x \<in> S. f x \<le> (j - 1/3)*e}" for j :: nat
   575   define A where "A j = {x \<in> S. f x \<le> (j - 1/3)*e}" for j :: nat
   576   define B where "B j = {x \<in> S. f x \<ge> (j + 1/3)*e}" for j :: nat
   576   define B where "B j = {x \<in> S. f x \<ge> (j + 1/3)*e}" for j :: nat
   577   have ngt: "(n-1) * e \<ge> normf f" "n\<ge>1"
   577   have ngt: "(n-1) * e \<ge> normf f" "n\<ge>1"
   578     using e
   578     using e
   709   then show ?thesis
   709   then show ?thesis
   710     by (rule_tac x=g in bexI) (auto intro: gR)
   710     by (rule_tac x=g in bexI) (auto intro: gR)
   711 qed
   711 qed
   712 
   712 
   713 text\<open>The ``unpretentious'' formulation\<close>
   713 text\<open>The ``unpretentious'' formulation\<close>
   714 lemma (in function_ring_on) Stone_Weierstrass_basic:
   714 lemma%important (in function_ring_on) Stone_Weierstrass_basic:
   715   assumes f: "continuous_on S f" and e: "e > 0"
   715   assumes f: "continuous_on S f" and e: "e > 0"
   716   shows "\<exists>g \<in> R. \<forall>x\<in>S. \<bar>f x - g x\<bar> < e"
   716   shows "\<exists>g \<in> R. \<forall>x\<in>S. \<bar>f x - g x\<bar> < e"
   717 proof -
   717 proof%unimportant -
   718   have "\<exists>g \<in> R. \<forall>x\<in>S. \<bar>(f x + normf f) - g x\<bar> < 2 * min (e/2) (1/4)"
   718   have "\<exists>g \<in> R. \<forall>x\<in>S. \<bar>(f x + normf f) - g x\<bar> < 2 * min (e/2) (1/4)"
   719     apply (rule Stone_Weierstrass_special)
   719     apply (rule Stone_Weierstrass_special)
   720     apply (rule Limits.continuous_on_add [OF f Topological_Spaces.continuous_on_const])
   720     apply (rule Limits.continuous_on_add [OF f Topological_Spaces.continuous_on_const])
   721     using normf_upper [OF f] apply force
   721     using normf_upper [OF f] apply force
   722     apply (simp add: e, linarith)
   722     apply (simp add: e, linarith)
   728     apply (auto simp: algebra_simps intro: diff const)
   728     apply (auto simp: algebra_simps intro: diff const)
   729     done
   729     done
   730 qed
   730 qed
   731 
   731 
   732 
   732 
   733 theorem (in function_ring_on) Stone_Weierstrass:
   733 theorem%important (in function_ring_on) Stone_Weierstrass:
   734   assumes f: "continuous_on S f"
   734   assumes f: "continuous_on S f"
   735   shows "\<exists>F\<in>UNIV \<rightarrow> R. LIM n sequentially. F n :> uniformly_on S f"
   735   shows "\<exists>F\<in>UNIV \<rightarrow> R. LIM n sequentially. F n :> uniformly_on S f"
   736 proof -
   736 proof%unimportant -
   737   { fix e::real
   737   { fix e::real
   738     assume e: "0 < e"
   738     assume e: "0 < e"
   739     then obtain N::nat where N: "0 < N" "0 < inverse N" "inverse N < e"
   739     then obtain N::nat where N: "0 < N" "0 < inverse N" "inverse N < e"
   740       by (auto simp: real_arch_inverse [of e])
   740       by (auto simp: real_arch_inverse [of e])
   741     { fix n :: nat and x :: 'a and g :: "'a \<Rightarrow> real"
   741     { fix n :: nat and x :: 'a and g :: "'a \<Rightarrow> real"
   760     apply (auto simp: dist_norm abs_minus_commute)
   760     apply (auto simp: dist_norm abs_minus_commute)
   761     done
   761     done
   762 qed
   762 qed
   763 
   763 
   764 text\<open>A HOL Light formulation\<close>
   764 text\<open>A HOL Light formulation\<close>
   765 corollary Stone_Weierstrass_HOL:
   765 corollary%important Stone_Weierstrass_HOL:
   766   fixes R :: "('a::t2_space \<Rightarrow> real) set" and S :: "'a set"
   766   fixes R :: "('a::t2_space \<Rightarrow> real) set" and S :: "'a set"
   767   assumes "compact S"  "\<And>c. P(\<lambda>x. c::real)"
   767   assumes "compact S"  "\<And>c. P(\<lambda>x. c::real)"
   768           "\<And>f. P f \<Longrightarrow> continuous_on S f"
   768           "\<And>f. P f \<Longrightarrow> continuous_on S f"
   769           "\<And>f g. P(f) \<and> P(g) \<Longrightarrow> P(\<lambda>x. f x + g x)"  "\<And>f g. P(f) \<and> P(g) \<Longrightarrow> P(\<lambda>x. f x * g x)"
   769           "\<And>f g. P(f) \<and> P(g) \<Longrightarrow> P(\<lambda>x. f x + g x)"  "\<And>f g. P(f) \<and> P(g) \<Longrightarrow> P(\<lambda>x. f x * g x)"
   770           "\<And>x y. x \<in> S \<and> y \<in> S \<and> ~(x = y) \<Longrightarrow> \<exists>f. P(f) \<and> ~(f x = f y)"
   770           "\<And>x y. x \<in> S \<and> y \<in> S \<and> ~(x = y) \<Longrightarrow> \<exists>f. P(f) \<and> ~(f x = f y)"
   771           "continuous_on S f"
   771           "continuous_on S f"
   772        "0 < e"
   772        "0 < e"
   773     shows "\<exists>g. P(g) \<and> (\<forall>x \<in> S. \<bar>f x - g x\<bar> < e)"
   773     shows "\<exists>g. P(g) \<and> (\<forall>x \<in> S. \<bar>f x - g x\<bar> < e)"
   774 proof -
   774 proof%unimportant -
   775   interpret PR: function_ring_on "Collect P"
   775   interpret PR: function_ring_on "Collect P"
   776     apply unfold_locales
   776     apply unfold_locales
   777     using assms
   777     using assms
   778     by auto
   778     by auto
   779   show ?thesis
   779   show ?thesis
   780     using PR.Stone_Weierstrass_basic [OF \<open>continuous_on S f\<close> \<open>0 < e\<close>]
   780     using PR.Stone_Weierstrass_basic [OF \<open>continuous_on S f\<close> \<open>0 < e\<close>]
   781     by blast
   781     by blast
   782 qed
   782 qed
   783 
   783 
   784 
   784 
   785 subsection \<open>Polynomial functions\<close>
   785 subsection%important \<open>Polynomial functions\<close>
   786 
   786 
   787 inductive real_polynomial_function :: "('a::real_normed_vector \<Rightarrow> real) \<Rightarrow> bool" where
   787 inductive real_polynomial_function :: "('a::real_normed_vector \<Rightarrow> real) \<Rightarrow> bool" where
   788     linear: "bounded_linear f \<Longrightarrow> real_polynomial_function f"
   788     linear: "bounded_linear f \<Longrightarrow> real_polynomial_function f"
   789   | const: "real_polynomial_function (\<lambda>x. c)"
   789   | const: "real_polynomial_function (\<lambda>x. c)"
   790   | add:   "\<lbrakk>real_polynomial_function f; real_polynomial_function g\<rbrakk> \<Longrightarrow> real_polynomial_function (\<lambda>x. f x + g x)"
   790   | add:   "\<lbrakk>real_polynomial_function f; real_polynomial_function g\<rbrakk> \<Longrightarrow> real_polynomial_function (\<lambda>x. f x + g x)"
   791   | mult:  "\<lbrakk>real_polynomial_function f; real_polynomial_function g\<rbrakk> \<Longrightarrow> real_polynomial_function (\<lambda>x. f x * g x)"
   791   | mult:  "\<lbrakk>real_polynomial_function f; real_polynomial_function g\<rbrakk> \<Longrightarrow> real_polynomial_function (\<lambda>x. f x * g x)"
   792 
   792 
   793 declare real_polynomial_function.intros [intro]
   793 declare real_polynomial_function.intros [intro]
   794 
   794 
   795 definition polynomial_function :: "('a::real_normed_vector \<Rightarrow> 'b::real_normed_vector) \<Rightarrow> bool"
   795 definition%important polynomial_function :: "('a::real_normed_vector \<Rightarrow> 'b::real_normed_vector) \<Rightarrow> bool"
   796   where
   796   where
   797    "polynomial_function p \<equiv> (\<forall>f. bounded_linear f \<longrightarrow> real_polynomial_function (f o p))"
   797    "polynomial_function p \<equiv> (\<forall>f. bounded_linear f \<longrightarrow> real_polynomial_function (f o p))"
   798 
   798 
   799 lemma real_polynomial_function_eq: "real_polynomial_function p = polynomial_function p"
   799 lemma%unimportant real_polynomial_function_eq: "real_polynomial_function p = polynomial_function p"
   800 unfolding polynomial_function_def
   800 unfolding polynomial_function_def
   801 proof
   801 proof
   802   assume "real_polynomial_function p"
   802   assume "real_polynomial_function p"
   803   then show " \<forall>f. bounded_linear f \<longrightarrow> real_polynomial_function (f \<circ> p)"
   803   then show " \<forall>f. bounded_linear f \<longrightarrow> real_polynomial_function (f \<circ> p)"
   804   proof (induction p rule: real_polynomial_function.induct)
   804   proof (induction p rule: real_polynomial_function.induct)
   818   assume [rule_format, OF bounded_linear_ident]: "\<forall>f. bounded_linear f \<longrightarrow> real_polynomial_function (f \<circ> p)"
   818   assume [rule_format, OF bounded_linear_ident]: "\<forall>f. bounded_linear f \<longrightarrow> real_polynomial_function (f \<circ> p)"
   819   then show "real_polynomial_function p"
   819   then show "real_polynomial_function p"
   820     by (simp add: o_def)
   820     by (simp add: o_def)
   821 qed
   821 qed
   822 
   822 
   823 lemma polynomial_function_const [iff]: "polynomial_function (\<lambda>x. c)"
   823 lemma%unimportant polynomial_function_const [iff]: "polynomial_function (\<lambda>x. c)"
   824   by (simp add: polynomial_function_def o_def const)
   824   by (simp add: polynomial_function_def o_def const)
   825 
   825 
   826 lemma polynomial_function_bounded_linear:
   826 lemma%unimportant polynomial_function_bounded_linear:
   827   "bounded_linear f \<Longrightarrow> polynomial_function f"
   827   "bounded_linear f \<Longrightarrow> polynomial_function f"
   828   by (simp add: polynomial_function_def o_def bounded_linear_compose real_polynomial_function.linear)
   828   by (simp add: polynomial_function_def o_def bounded_linear_compose real_polynomial_function.linear)
   829 
   829 
   830 lemma polynomial_function_id [iff]: "polynomial_function(\<lambda>x. x)"
   830 lemma%unimportant polynomial_function_id [iff]: "polynomial_function(\<lambda>x. x)"
   831   by (simp add: polynomial_function_bounded_linear)
   831   by (simp add: polynomial_function_bounded_linear)
   832 
   832 
   833 lemma polynomial_function_add [intro]:
   833 lemma%unimportant polynomial_function_add [intro]:
   834     "\<lbrakk>polynomial_function f; polynomial_function g\<rbrakk> \<Longrightarrow> polynomial_function (\<lambda>x. f x + g x)"
   834     "\<lbrakk>polynomial_function f; polynomial_function g\<rbrakk> \<Longrightarrow> polynomial_function (\<lambda>x. f x + g x)"
   835   by (auto simp: polynomial_function_def bounded_linear_def linear_add real_polynomial_function.add o_def)
   835   by (auto simp: polynomial_function_def bounded_linear_def linear_add real_polynomial_function.add o_def)
   836 
   836 
   837 lemma polynomial_function_mult [intro]:
   837 lemma%unimportant polynomial_function_mult [intro]:
   838   assumes f: "polynomial_function f" and g: "polynomial_function g"
   838   assumes f: "polynomial_function f" and g: "polynomial_function g"
   839     shows "polynomial_function (\<lambda>x. f x *\<^sub>R g x)"
   839     shows "polynomial_function (\<lambda>x. f x *\<^sub>R g x)"
   840   using g
   840   using g
   841   apply (auto simp: polynomial_function_def bounded_linear_def Real_Vector_Spaces.linear.scaleR  const real_polynomial_function.mult o_def)
   841   apply (auto simp: polynomial_function_def bounded_linear_def Real_Vector_Spaces.linear.scaleR  const real_polynomial_function.mult o_def)
   842   apply (rule mult)
   842   apply (rule mult)
   843   using f
   843   using f
   844   apply (auto simp: real_polynomial_function_eq)
   844   apply (auto simp: real_polynomial_function_eq)
   845   done
   845   done
   846 
   846 
   847 lemma polynomial_function_cmul [intro]:
   847 lemma%unimportant polynomial_function_cmul [intro]:
   848   assumes f: "polynomial_function f"
   848   assumes f: "polynomial_function f"
   849     shows "polynomial_function (\<lambda>x. c *\<^sub>R f x)"
   849     shows "polynomial_function (\<lambda>x. c *\<^sub>R f x)"
   850   by (rule polynomial_function_mult [OF polynomial_function_const f])
   850   by (rule polynomial_function_mult [OF polynomial_function_const f])
   851 
   851 
   852 lemma polynomial_function_minus [intro]:
   852 lemma%unimportant polynomial_function_minus [intro]:
   853   assumes f: "polynomial_function f"
   853   assumes f: "polynomial_function f"
   854     shows "polynomial_function (\<lambda>x. - f x)"
   854     shows "polynomial_function (\<lambda>x. - f x)"
   855   using polynomial_function_cmul [OF f, of "-1"] by simp
   855   using polynomial_function_cmul [OF f, of "-1"] by simp
   856 
   856 
   857 lemma polynomial_function_diff [intro]:
   857 lemma%unimportant polynomial_function_diff [intro]:
   858     "\<lbrakk>polynomial_function f; polynomial_function g\<rbrakk> \<Longrightarrow> polynomial_function (\<lambda>x. f x - g x)"
   858     "\<lbrakk>polynomial_function f; polynomial_function g\<rbrakk> \<Longrightarrow> polynomial_function (\<lambda>x. f x - g x)"
   859   unfolding add_uminus_conv_diff [symmetric]
   859   unfolding add_uminus_conv_diff [symmetric]
   860   by (metis polynomial_function_add polynomial_function_minus)
   860   by (metis polynomial_function_add polynomial_function_minus)
   861 
   861 
   862 lemma polynomial_function_sum [intro]:
   862 lemma%unimportant polynomial_function_sum [intro]:
   863     "\<lbrakk>finite I; \<And>i. i \<in> I \<Longrightarrow> polynomial_function (\<lambda>x. f x i)\<rbrakk> \<Longrightarrow> polynomial_function (\<lambda>x. sum (f x) I)"
   863     "\<lbrakk>finite I; \<And>i. i \<in> I \<Longrightarrow> polynomial_function (\<lambda>x. f x i)\<rbrakk> \<Longrightarrow> polynomial_function (\<lambda>x. sum (f x) I)"
   864 by (induct I rule: finite_induct) auto
   864 by (induct I rule: finite_induct) auto
   865 
   865 
   866 lemma real_polynomial_function_minus [intro]:
   866 lemma%unimportant real_polynomial_function_minus [intro]:
   867     "real_polynomial_function f \<Longrightarrow> real_polynomial_function (\<lambda>x. - f x)"
   867     "real_polynomial_function f \<Longrightarrow> real_polynomial_function (\<lambda>x. - f x)"
   868   using polynomial_function_minus [of f]
   868   using polynomial_function_minus [of f]
   869   by (simp add: real_polynomial_function_eq)
   869   by (simp add: real_polynomial_function_eq)
   870 
   870 
   871 lemma real_polynomial_function_diff [intro]:
   871 lemma%unimportant real_polynomial_function_diff [intro]:
   872     "\<lbrakk>real_polynomial_function f; real_polynomial_function g\<rbrakk> \<Longrightarrow> real_polynomial_function (\<lambda>x. f x - g x)"
   872     "\<lbrakk>real_polynomial_function f; real_polynomial_function g\<rbrakk> \<Longrightarrow> real_polynomial_function (\<lambda>x. f x - g x)"
   873   using polynomial_function_diff [of f]
   873   using polynomial_function_diff [of f]
   874   by (simp add: real_polynomial_function_eq)
   874   by (simp add: real_polynomial_function_eq)
   875 
   875 
   876 lemma real_polynomial_function_sum [intro]:
   876 lemma%unimportant real_polynomial_function_sum [intro]:
   877     "\<lbrakk>finite I; \<And>i. i \<in> I \<Longrightarrow> real_polynomial_function (\<lambda>x. f x i)\<rbrakk> \<Longrightarrow> real_polynomial_function (\<lambda>x. sum (f x) I)"
   877     "\<lbrakk>finite I; \<And>i. i \<in> I \<Longrightarrow> real_polynomial_function (\<lambda>x. f x i)\<rbrakk> \<Longrightarrow> real_polynomial_function (\<lambda>x. sum (f x) I)"
   878   using polynomial_function_sum [of I f]
   878   using polynomial_function_sum [of I f]
   879   by (simp add: real_polynomial_function_eq)
   879   by (simp add: real_polynomial_function_eq)
   880 
   880 
   881 lemma real_polynomial_function_power [intro]:
   881 lemma%unimportant real_polynomial_function_power [intro]:
   882     "real_polynomial_function f \<Longrightarrow> real_polynomial_function (\<lambda>x. f x ^ n)"
   882     "real_polynomial_function f \<Longrightarrow> real_polynomial_function (\<lambda>x. f x ^ n)"
   883   by (induct n) (simp_all add: const mult)
   883   by (induct n) (simp_all add: const mult)
   884 
   884 
   885 lemma real_polynomial_function_compose [intro]:
   885 lemma%unimportant real_polynomial_function_compose [intro]:
   886   assumes f: "polynomial_function f" and g: "real_polynomial_function g"
   886   assumes f: "polynomial_function f" and g: "real_polynomial_function g"
   887     shows "real_polynomial_function (g o f)"
   887     shows "real_polynomial_function (g o f)"
   888   using g
   888   using g
   889   apply (induction g rule: real_polynomial_function.induct)
   889   apply (induction g rule: real_polynomial_function.induct)
   890   using f
   890   using f
   891   apply (simp_all add: polynomial_function_def o_def const add mult)
   891   apply (simp_all add: polynomial_function_def o_def const add mult)
   892   done
   892   done
   893 
   893 
   894 lemma polynomial_function_compose [intro]:
   894 lemma%unimportant polynomial_function_compose [intro]:
   895   assumes f: "polynomial_function f" and g: "polynomial_function g"
   895   assumes f: "polynomial_function f" and g: "polynomial_function g"
   896     shows "polynomial_function (g o f)"
   896     shows "polynomial_function (g o f)"
   897   using g real_polynomial_function_compose [OF f]
   897   using g real_polynomial_function_compose [OF f]
   898   by (auto simp: polynomial_function_def o_def)
   898   by (auto simp: polynomial_function_def o_def)
   899 
   899 
   900 lemma sum_max_0:
   900 lemma%unimportant sum_max_0:
   901   fixes x::real (*in fact "'a::comm_ring_1"*)
   901   fixes x::real (*in fact "'a::comm_ring_1"*)
   902   shows "(\<Sum>i\<le>max m n. x^i * (if i \<le> m then a i else 0)) = (\<Sum>i\<le>m. x^i * a i)"
   902   shows "(\<Sum>i\<le>max m n. x^i * (if i \<le> m then a i else 0)) = (\<Sum>i\<le>m. x^i * a i)"
   903 proof -
   903 proof -
   904   have "(\<Sum>i\<le>max m n. x^i * (if i \<le> m then a i else 0)) = (\<Sum>i\<le>max m n. (if i \<le> m then x^i * a i else 0))"
   904   have "(\<Sum>i\<le>max m n. x^i * (if i \<le> m then a i else 0)) = (\<Sum>i\<le>max m n. (if i \<le> m then x^i * a i else 0))"
   905     by (auto simp: algebra_simps intro: sum.cong)
   905     by (auto simp: algebra_simps intro: sum.cong)
   908   also have "... = (\<Sum>i\<le>m. x^i * a i)"
   908   also have "... = (\<Sum>i\<le>m. x^i * a i)"
   909     by (auto simp: algebra_simps intro: sum.cong)
   909     by (auto simp: algebra_simps intro: sum.cong)
   910   finally show ?thesis .
   910   finally show ?thesis .
   911 qed
   911 qed
   912 
   912 
   913 lemma real_polynomial_function_imp_sum:
   913 lemma%unimportant real_polynomial_function_imp_sum:
   914   assumes "real_polynomial_function f"
   914   assumes "real_polynomial_function f"
   915     shows "\<exists>a n::nat. f = (\<lambda>x. \<Sum>i\<le>n. a i * x ^ i)"
   915     shows "\<exists>a n::nat. f = (\<lambda>x. \<Sum>i\<le>n. a i * x ^ i)"
   916 using assms
   916 using assms
   917 proof (induct f)
   917 proof (induct f)
   918   case (linear f)
   918   case (linear f)
   953     using polynomial_product [of n1 b1 n2 b2]
   953     using polynomial_product [of n1 b1 n2 b2]
   954     apply (simp add: Set_Interval.atLeast0AtMost)
   954     apply (simp add: Set_Interval.atLeast0AtMost)
   955     done
   955     done
   956 qed
   956 qed
   957 
   957 
   958 lemma real_polynomial_function_iff_sum:
   958 lemma%unimportant real_polynomial_function_iff_sum:
   959      "real_polynomial_function f \<longleftrightarrow> (\<exists>a n::nat. f = (\<lambda>x. \<Sum>i\<le>n. a i * x ^ i))"
   959      "real_polynomial_function f \<longleftrightarrow> (\<exists>a n::nat. f = (\<lambda>x. \<Sum>i\<le>n. a i * x ^ i))"
   960   apply (rule iffI)
   960   apply (rule iffI)
   961   apply (erule real_polynomial_function_imp_sum)
   961   apply (erule real_polynomial_function_imp_sum)
   962   apply (auto simp: linear mult const real_polynomial_function_power real_polynomial_function_sum)
   962   apply (auto simp: linear mult const real_polynomial_function_power real_polynomial_function_sum)
   963   done
   963   done
   964 
   964 
   965 lemma polynomial_function_iff_Basis_inner:
   965 lemma%important polynomial_function_iff_Basis_inner:
   966   fixes f :: "'a::real_normed_vector \<Rightarrow> 'b::euclidean_space"
   966   fixes f :: "'a::real_normed_vector \<Rightarrow> 'b::euclidean_space"
   967   shows "polynomial_function f \<longleftrightarrow> (\<forall>b\<in>Basis. real_polynomial_function (\<lambda>x. inner (f x) b))"
   967   shows "polynomial_function f \<longleftrightarrow> (\<forall>b\<in>Basis. real_polynomial_function (\<lambda>x. inner (f x) b))"
   968         (is "?lhs = ?rhs")
   968         (is "?lhs = ?rhs")
   969 unfolding polynomial_function_def
   969 unfolding polynomial_function_def
   970 proof (intro iffI allI impI)
   970 proof%unimportant (intro iffI allI impI)
   971   assume "\<forall>h. bounded_linear h \<longrightarrow> real_polynomial_function (h \<circ> f)"
   971   assume "\<forall>h. bounded_linear h \<longrightarrow> real_polynomial_function (h \<circ> f)"
   972   then show ?rhs
   972   then show ?rhs
   973     by (force simp add: bounded_linear_inner_left o_def)
   973     by (force simp add: bounded_linear_inner_left o_def)
   974 next
   974 next
   975   fix h :: "'b \<Rightarrow> real"
   975   fix h :: "'b \<Rightarrow> real"
   981     done
   981     done
   982   then show "real_polynomial_function (h \<circ> f)"
   982   then show "real_polynomial_function (h \<circ> f)"
   983     by (simp add: euclidean_representation_sum_fun)
   983     by (simp add: euclidean_representation_sum_fun)
   984 qed
   984 qed
   985 
   985 
   986 subsection \<open>Stone-Weierstrass theorem for polynomial functions\<close>
   986 subsection%important \<open>Stone-Weierstrass theorem for polynomial functions\<close>
   987 
   987 
   988 text\<open>First, we need to show that they are continous, differentiable and separable.\<close>
   988 text\<open>First, we need to show that they are continous, differentiable and separable.\<close>
   989 
   989 
   990 lemma continuous_real_polymonial_function:
   990 lemma%unimportant continuous_real_polymonial_function:
   991   assumes "real_polynomial_function f"
   991   assumes "real_polynomial_function f"
   992     shows "continuous (at x) f"
   992     shows "continuous (at x) f"
   993 using assms
   993 using assms
   994 by (induct f) (auto simp: linear_continuous_at)
   994 by (induct f) (auto simp: linear_continuous_at)
   995 
   995 
   996 lemma continuous_polymonial_function:
   996 lemma%unimportant continuous_polymonial_function:
   997   fixes f :: "'a::real_normed_vector \<Rightarrow> 'b::euclidean_space"
   997   fixes f :: "'a::real_normed_vector \<Rightarrow> 'b::euclidean_space"
   998   assumes "polynomial_function f"
   998   assumes "polynomial_function f"
   999     shows "continuous (at x) f"
   999     shows "continuous (at x) f"
  1000   apply (rule euclidean_isCont)
  1000   apply (rule euclidean_isCont)
  1001   using assms apply (simp add: polynomial_function_iff_Basis_inner)
  1001   using assms apply (simp add: polynomial_function_iff_Basis_inner)
  1002   apply (force dest: continuous_real_polymonial_function intro: isCont_scaleR)
  1002   apply (force dest: continuous_real_polymonial_function intro: isCont_scaleR)
  1003   done
  1003   done
  1004 
  1004 
  1005 lemma continuous_on_polymonial_function:
  1005 lemma%unimportant continuous_on_polymonial_function:
  1006   fixes f :: "'a::real_normed_vector \<Rightarrow> 'b::euclidean_space"
  1006   fixes f :: "'a::real_normed_vector \<Rightarrow> 'b::euclidean_space"
  1007   assumes "polynomial_function f"
  1007   assumes "polynomial_function f"
  1008     shows "continuous_on S f"
  1008     shows "continuous_on S f"
  1009   using continuous_polymonial_function [OF assms] continuous_at_imp_continuous_on
  1009   using continuous_polymonial_function [OF assms] continuous_at_imp_continuous_on
  1010   by blast
  1010   by blast
  1011 
  1011 
  1012 lemma has_real_derivative_polynomial_function:
  1012 lemma%unimportant has_real_derivative_polynomial_function:
  1013   assumes "real_polynomial_function p"
  1013   assumes "real_polynomial_function p"
  1014     shows "\<exists>p'. real_polynomial_function p' \<and>
  1014     shows "\<exists>p'. real_polynomial_function p' \<and>
  1015                  (\<forall>x. (p has_real_derivative (p' x)) (at x))"
  1015                  (\<forall>x. (p has_real_derivative (p' x)) (at x))"
  1016 using assms
  1016 using assms
  1017 proof (induct p)
  1017 proof (induct p)
  1041     apply (rule_tac x="\<lambda>x. f1 x * p2 x + f2 x * p1 x" in exI)
  1041     apply (rule_tac x="\<lambda>x. f1 x * p2 x + f2 x * p1 x" in exI)
  1042     apply (auto intro!: derivative_eq_intros)
  1042     apply (auto intro!: derivative_eq_intros)
  1043     done
  1043     done
  1044 qed
  1044 qed
  1045 
  1045 
  1046 lemma has_vector_derivative_polynomial_function:
  1046 lemma%unimportant has_vector_derivative_polynomial_function:
  1047   fixes p :: "real \<Rightarrow> 'a::euclidean_space"
  1047   fixes p :: "real \<Rightarrow> 'a::euclidean_space"
  1048   assumes "polynomial_function p"
  1048   assumes "polynomial_function p"
  1049   obtains p' where "polynomial_function p'" "\<And>x. (p has_vector_derivative (p' x)) (at x)"
  1049   obtains p' where "polynomial_function p'" "\<And>x. (p has_vector_derivative (p' x)) (at x)"
  1050 proof -
  1050 proof -
  1051   { fix b :: 'a
  1051   { fix b :: 'a
  1072     apply (subst euclidean_representation_sum_fun [of p, symmetric])
  1072     apply (subst euclidean_representation_sum_fun [of p, symmetric])
  1073      apply (auto intro: has_vector_derivative_sum qf)
  1073      apply (auto intro: has_vector_derivative_sum qf)
  1074     done
  1074     done
  1075 qed
  1075 qed
  1076 
  1076 
  1077 lemma real_polynomial_function_separable:
  1077 lemma%unimportant real_polynomial_function_separable:
  1078   fixes x :: "'a::euclidean_space"
  1078   fixes x :: "'a::euclidean_space"
  1079   assumes "x \<noteq> y" shows "\<exists>f. real_polynomial_function f \<and> f x \<noteq> f y"
  1079   assumes "x \<noteq> y" shows "\<exists>f. real_polynomial_function f \<and> f x \<noteq> f y"
  1080 proof -
  1080 proof -
  1081   have "real_polynomial_function (\<lambda>u. \<Sum>b\<in>Basis. (inner (x-u) b)^2)"
  1081   have "real_polynomial_function (\<lambda>u. \<Sum>b\<in>Basis. (inner (x-u) b)^2)"
  1082     apply (rule real_polynomial_function_sum)
  1082     apply (rule real_polynomial_function_sum)
  1088     using assms
  1088     using assms
  1089     apply (force simp add: euclidean_eq_iff [of x y] sum_nonneg_eq_0_iff algebra_simps)
  1089     apply (force simp add: euclidean_eq_iff [of x y] sum_nonneg_eq_0_iff algebra_simps)
  1090     done
  1090     done
  1091 qed
  1091 qed
  1092 
  1092 
  1093 lemma Stone_Weierstrass_real_polynomial_function:
  1093 lemma%important Stone_Weierstrass_real_polynomial_function:
  1094   fixes f :: "'a::euclidean_space \<Rightarrow> real"
  1094   fixes f :: "'a::euclidean_space \<Rightarrow> real"
  1095   assumes "compact S" "continuous_on S f" "0 < e"
  1095   assumes "compact S" "continuous_on S f" "0 < e"
  1096   obtains g where "real_polynomial_function g" "\<And>x. x \<in> S \<Longrightarrow> \<bar>f x - g x\<bar> < e"
  1096   obtains g where "real_polynomial_function g" "\<And>x. x \<in> S \<Longrightarrow> \<bar>f x - g x\<bar> < e"
  1097 proof -
  1097 proof%unimportant -
  1098   interpret PR: function_ring_on "Collect real_polynomial_function"
  1098   interpret PR: function_ring_on "Collect real_polynomial_function"
  1099     apply unfold_locales
  1099     apply unfold_locales
  1100     using assms continuous_on_polymonial_function real_polynomial_function_eq
  1100     using assms continuous_on_polymonial_function real_polynomial_function_eq
  1101     apply (auto intro: real_polynomial_function_separable)
  1101     apply (auto intro: real_polynomial_function_separable)
  1102     done
  1102     done
  1103   show ?thesis
  1103   show ?thesis
  1104     using PR.Stone_Weierstrass_basic [OF \<open>continuous_on S f\<close> \<open>0 < e\<close>] that
  1104     using PR.Stone_Weierstrass_basic [OF \<open>continuous_on S f\<close> \<open>0 < e\<close>] that
  1105     by blast
  1105     by blast
  1106 qed
  1106 qed
  1107 
  1107 
  1108 lemma Stone_Weierstrass_polynomial_function:
  1108 lemma%important Stone_Weierstrass_polynomial_function:
  1109   fixes f :: "'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
  1109   fixes f :: "'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
  1110   assumes S: "compact S"
  1110   assumes S: "compact S"
  1111       and f: "continuous_on S f"
  1111       and f: "continuous_on S f"
  1112       and e: "0 < e"
  1112       and e: "0 < e"
  1113     shows "\<exists>g. polynomial_function g \<and> (\<forall>x \<in> S. norm(f x - g x) < e)"
  1113     shows "\<exists>g. polynomial_function g \<and> (\<forall>x \<in> S. norm(f x - g x) < e)"
  1114 proof -
  1114 proof%unimportant -
  1115   { fix b :: 'b
  1115   { fix b :: 'b
  1116     assume "b \<in> Basis"
  1116     assume "b \<in> Basis"
  1117     have "\<exists>p. real_polynomial_function p \<and> (\<forall>x \<in> S. \<bar>f x \<bullet> b - p x\<bar> < e / DIM('b))"
  1117     have "\<exists>p. real_polynomial_function p \<and> (\<forall>x \<in> S. \<bar>f x \<bullet> b - p x\<bar> < e / DIM('b))"
  1118       apply (rule exE [OF Stone_Weierstrass_real_polynomial_function [OF S _, of "\<lambda>x. f x \<bullet> b" "e / card Basis"]])
  1118       apply (rule exE [OF Stone_Weierstrass_real_polynomial_function [OF S _, of "\<lambda>x. f x \<bullet> b" "e / card Basis"]])
  1119       using e f
  1119       using e f
  1149     apply (rule_tac x="\<lambda>x. \<Sum>b\<in>Basis. pf b x *\<^sub>R b" in exI)
  1149     apply (rule_tac x="\<lambda>x. \<Sum>b\<in>Basis. pf b x *\<^sub>R b" in exI)
  1150     apply (auto simp flip: sum_subtractf)
  1150     apply (auto simp flip: sum_subtractf)
  1151     done
  1151     done
  1152 qed
  1152 qed
  1153 
  1153 
  1154 lemma Stone_Weierstrass_uniform_limit:
  1154 lemma%important Stone_Weierstrass_uniform_limit:
  1155   fixes f :: "'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
  1155   fixes f :: "'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
  1156   assumes S: "compact S"
  1156   assumes S: "compact S"
  1157     and f: "continuous_on S f"
  1157     and f: "continuous_on S f"
  1158   obtains g where "uniform_limit S g f sequentially" "\<And>n. polynomial_function (g n)"
  1158   obtains g where "uniform_limit S g f sequentially" "\<And>n. polynomial_function (g n)"
  1159 proof -
  1159 proof%unimportant -
  1160   have pos: "inverse (Suc n) > 0" for n by auto
  1160   have pos: "inverse (Suc n) > 0" for n by auto
  1161   obtain g where g: "\<And>n. polynomial_function (g n)" "\<And>x n. x \<in> S \<Longrightarrow> norm(f x - g n x) < inverse (Suc n)"
  1161   obtain g where g: "\<And>n. polynomial_function (g n)" "\<And>x n. x \<in> S \<Longrightarrow> norm(f x - g n x) < inverse (Suc n)"
  1162     using Stone_Weierstrass_polynomial_function[OF S f pos]
  1162     using Stone_Weierstrass_polynomial_function[OF S f pos]
  1163     by metis
  1163     by metis
  1164   have "uniform_limit S g f sequentially"
  1164   have "uniform_limit S g f sequentially"
  1173   qed
  1173   qed
  1174   then show ?thesis using g(1) ..
  1174   then show ?thesis using g(1) ..
  1175 qed
  1175 qed
  1176 
  1176 
  1177 
  1177 
  1178 subsection\<open>Polynomial functions as paths\<close>
  1178 subsection%important\<open>Polynomial functions as paths\<close>
  1179 
  1179 
  1180 text\<open>One application is to pick a smooth approximation to a path,
  1180 text\<open>One application is to pick a smooth approximation to a path,
  1181 or just pick a smooth path anyway in an open connected set\<close>
  1181 or just pick a smooth path anyway in an open connected set\<close>
  1182 
  1182 
  1183 lemma path_polynomial_function:
  1183 lemma%unimportant path_polynomial_function:
  1184     fixes g  :: "real \<Rightarrow> 'b::euclidean_space"
  1184     fixes g  :: "real \<Rightarrow> 'b::euclidean_space"
  1185     shows "polynomial_function g \<Longrightarrow> path g"
  1185     shows "polynomial_function g \<Longrightarrow> path g"
  1186   by (simp add: path_def continuous_on_polymonial_function)
  1186   by (simp add: path_def continuous_on_polymonial_function)
  1187 
  1187 
  1188 lemma path_approx_polynomial_function:
  1188 lemma%unimportant path_approx_polynomial_function:
  1189     fixes g :: "real \<Rightarrow> 'b::euclidean_space"
  1189     fixes g :: "real \<Rightarrow> 'b::euclidean_space"
  1190     assumes "path g" "0 < e"
  1190     assumes "path g" "0 < e"
  1191     shows "\<exists>p. polynomial_function p \<and>
  1191     shows "\<exists>p. polynomial_function p \<and>
  1192                 pathstart p = pathstart g \<and>
  1192                 pathstart p = pathstart g \<and>
  1193                 pathfinish p = pathfinish g \<and>
  1193                 pathfinish p = pathfinish g \<and>
  1209     using *
  1209     using *
  1210     apply (auto simp add: pathstart_def pathfinish_def algebra_simps)
  1210     apply (auto simp add: pathstart_def pathfinish_def algebra_simps)
  1211     done
  1211     done
  1212 qed
  1212 qed
  1213 
  1213 
  1214 lemma connected_open_polynomial_connected:
  1214 lemma%important connected_open_polynomial_connected:
  1215   fixes S :: "'a::euclidean_space set"
  1215   fixes S :: "'a::euclidean_space set"
  1216   assumes S: "open S" "connected S"
  1216   assumes S: "open S" "connected S"
  1217       and "x \<in> S" "y \<in> S"
  1217       and "x \<in> S" "y \<in> S"
  1218     shows "\<exists>g. polynomial_function g \<and> path_image g \<subseteq> S \<and>
  1218     shows "\<exists>g. polynomial_function g \<and> path_image g \<subseteq> S \<and>
  1219                pathstart g = x \<and> pathfinish g = y"
  1219                pathstart g = x \<and> pathfinish g = y"
  1220 proof -
  1220 proof%unimportant -
  1221   have "path_connected S" using assms
  1221   have "path_connected S" using assms
  1222     by (simp add: connected_open_path_connected)
  1222     by (simp add: connected_open_path_connected)
  1223   with \<open>x \<in> S\<close> \<open>y \<in> S\<close> obtain p where p: "path p" "path_image p \<subseteq> S" "pathstart p = x" "pathfinish p = y"
  1223   with \<open>x \<in> S\<close> \<open>y \<in> S\<close> obtain p where p: "path p" "path_image p \<subseteq> S" "pathstart p = x" "pathfinish p = y"
  1224     by (force simp: path_connected_def)
  1224     by (force simp: path_connected_def)
  1225   have "\<exists>e. 0 < e \<and> (\<forall>x \<in> path_image p. ball x e \<subseteq> S)"
  1225   have "\<exists>e. 0 < e \<and> (\<forall>x \<in> path_image p. ball x e \<subseteq> S)"
  1245     using p
  1245     using p
  1246     apply (fastforce simp add: dist_norm path_image_def norm_minus_commute intro: eb [THEN subsetD])+
  1246     apply (fastforce simp add: dist_norm path_image_def norm_minus_commute intro: eb [THEN subsetD])+
  1247     done
  1247     done
  1248 qed
  1248 qed
  1249 
  1249 
  1250 lemma has_derivative_componentwise_within:
  1250 lemma%unimportant has_derivative_componentwise_within:
  1251    "(f has_derivative f') (at a within S) \<longleftrightarrow>
  1251    "(f has_derivative f') (at a within S) \<longleftrightarrow>
  1252     (\<forall>i \<in> Basis. ((\<lambda>x. f x \<bullet> i) has_derivative (\<lambda>x. f' x \<bullet> i)) (at a within S))"
  1252     (\<forall>i \<in> Basis. ((\<lambda>x. f x \<bullet> i) has_derivative (\<lambda>x. f' x \<bullet> i)) (at a within S))"
  1253   apply (simp add: has_derivative_within)
  1253   apply (simp add: has_derivative_within)
  1254   apply (subst tendsto_componentwise_iff)
  1254   apply (subst tendsto_componentwise_iff)
  1255   apply (simp add: bounded_linear_componentwise_iff [symmetric] ball_conj_distrib)
  1255   apply (simp add: bounded_linear_componentwise_iff [symmetric] ball_conj_distrib)
  1256   apply (simp add: algebra_simps)
  1256   apply (simp add: algebra_simps)
  1257   done
  1257   done
  1258 
  1258 
  1259 lemma differentiable_componentwise_within:
  1259 lemma%unimportant differentiable_componentwise_within:
  1260    "f differentiable (at a within S) \<longleftrightarrow>
  1260    "f differentiable (at a within S) \<longleftrightarrow>
  1261     (\<forall>i \<in> Basis. (\<lambda>x. f x \<bullet> i) differentiable at a within S)"
  1261     (\<forall>i \<in> Basis. (\<lambda>x. f x \<bullet> i) differentiable at a within S)"
  1262 proof -
  1262 proof -
  1263   { assume "\<forall>i\<in>Basis. \<exists>D. ((\<lambda>x. f x \<bullet> i) has_derivative D) (at a within S)"
  1263   { assume "\<forall>i\<in>Basis. \<exists>D. ((\<lambda>x. f x \<bullet> i) has_derivative D) (at a within S)"
  1264     then obtain f' where f':
  1264     then obtain f' where f':
  1275     apply (simp add: differentiable_def)
  1275     apply (simp add: differentiable_def)
  1276     using has_derivative_componentwise_within
  1276     using has_derivative_componentwise_within
  1277     by blast
  1277     by blast
  1278 qed
  1278 qed
  1279 
  1279 
  1280 lemma polynomial_function_inner [intro]:
  1280 lemma%unimportant polynomial_function_inner [intro]:
  1281   fixes i :: "'a::euclidean_space"
  1281   fixes i :: "'a::euclidean_space"
  1282   shows "polynomial_function g \<Longrightarrow> polynomial_function (\<lambda>x. g x \<bullet> i)"
  1282   shows "polynomial_function g \<Longrightarrow> polynomial_function (\<lambda>x. g x \<bullet> i)"
  1283   apply (subst euclidean_representation [where x=i, symmetric])
  1283   apply (subst euclidean_representation [where x=i, symmetric])
  1284   apply (force simp: inner_sum_right polynomial_function_iff_Basis_inner polynomial_function_sum)
  1284   apply (force simp: inner_sum_right polynomial_function_iff_Basis_inner polynomial_function_sum)
  1285   done
  1285   done
  1286 
  1286 
  1287 text\<open> Differentiability of real and vector polynomial functions.\<close>
  1287 text\<open> Differentiability of real and vector polynomial functions.\<close>
  1288 
  1288 
  1289 lemma differentiable_at_real_polynomial_function:
  1289 lemma%unimportant differentiable_at_real_polynomial_function:
  1290    "real_polynomial_function f \<Longrightarrow> f differentiable (at a within S)"
  1290    "real_polynomial_function f \<Longrightarrow> f differentiable (at a within S)"
  1291   by (induction f rule: real_polynomial_function.induct)
  1291   by (induction f rule: real_polynomial_function.induct)
  1292      (simp_all add: bounded_linear_imp_differentiable)
  1292      (simp_all add: bounded_linear_imp_differentiable)
  1293 
  1293 
  1294 lemma differentiable_on_real_polynomial_function:
  1294 lemma%unimportant differentiable_on_real_polynomial_function:
  1295    "real_polynomial_function p \<Longrightarrow> p differentiable_on S"
  1295    "real_polynomial_function p \<Longrightarrow> p differentiable_on S"
  1296 by (simp add: differentiable_at_imp_differentiable_on differentiable_at_real_polynomial_function)
  1296 by (simp add: differentiable_at_imp_differentiable_on differentiable_at_real_polynomial_function)
  1297 
  1297 
  1298 lemma differentiable_at_polynomial_function:
  1298 lemma%unimportant differentiable_at_polynomial_function:
  1299   fixes f :: "_ \<Rightarrow> 'a::euclidean_space"
  1299   fixes f :: "_ \<Rightarrow> 'a::euclidean_space"
  1300   shows "polynomial_function f \<Longrightarrow> f differentiable (at a within S)"
  1300   shows "polynomial_function f \<Longrightarrow> f differentiable (at a within S)"
  1301   by (metis differentiable_at_real_polynomial_function polynomial_function_iff_Basis_inner differentiable_componentwise_within)
  1301   by (metis differentiable_at_real_polynomial_function polynomial_function_iff_Basis_inner differentiable_componentwise_within)
  1302 
  1302 
  1303 lemma differentiable_on_polynomial_function:
  1303 lemma%unimportant differentiable_on_polynomial_function:
  1304   fixes f :: "_ \<Rightarrow> 'a::euclidean_space"
  1304   fixes f :: "_ \<Rightarrow> 'a::euclidean_space"
  1305   shows "polynomial_function f \<Longrightarrow> f differentiable_on S"
  1305   shows "polynomial_function f \<Longrightarrow> f differentiable_on S"
  1306 by (simp add: differentiable_at_polynomial_function differentiable_on_def)
  1306 by (simp add: differentiable_at_polynomial_function differentiable_on_def)
  1307 
  1307 
  1308 lemma vector_eq_dot_span:
  1308 lemma%unimportant vector_eq_dot_span:
  1309   assumes "x \<in> span B" "y \<in> span B" and i: "\<And>i. i \<in> B \<Longrightarrow> i \<bullet> x = i \<bullet> y"
  1309   assumes "x \<in> span B" "y \<in> span B" and i: "\<And>i. i \<in> B \<Longrightarrow> i \<bullet> x = i \<bullet> y"
  1310   shows "x = y"
  1310   shows "x = y"
  1311 proof -
  1311 proof -
  1312   have "\<And>i. i \<in> B \<Longrightarrow> orthogonal (x - y) i"
  1312   have "\<And>i. i \<in> B \<Longrightarrow> orthogonal (x - y) i"
  1313     by (simp add: i inner_commute inner_diff_right orthogonal_def)
  1313     by (simp add: i inner_commute inner_diff_right orthogonal_def)
  1316   ultimately have "x - y = 0"
  1316   ultimately have "x - y = 0"
  1317     using orthogonal_to_span orthogonal_self by blast
  1317     using orthogonal_to_span orthogonal_self by blast
  1318     then show ?thesis by simp
  1318     then show ?thesis by simp
  1319 qed
  1319 qed
  1320 
  1320 
  1321 lemma orthonormal_basis_expand:
  1321 lemma%unimportant orthonormal_basis_expand:
  1322   assumes B: "pairwise orthogonal B"
  1322   assumes B: "pairwise orthogonal B"
  1323       and 1: "\<And>i. i \<in> B \<Longrightarrow> norm i = 1"
  1323       and 1: "\<And>i. i \<in> B \<Longrightarrow> norm i = 1"
  1324       and "x \<in> span B"
  1324       and "x \<in> span B"
  1325       and "finite B"
  1325       and "finite B"
  1326     shows "(\<Sum>i\<in>B. (x \<bullet> i) *\<^sub>R i) = x"
  1326     shows "(\<Sum>i\<in>B. (x \<bullet> i) *\<^sub>R i) = x"
  1341     finally show ?thesis .
  1341     finally show ?thesis .
  1342   qed
  1342   qed
  1343 qed
  1343 qed
  1344 
  1344 
  1345 
  1345 
  1346 lemma Stone_Weierstrass_polynomial_function_subspace:
  1346 lemma%important Stone_Weierstrass_polynomial_function_subspace:
  1347   fixes f :: "'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
  1347   fixes f :: "'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
  1348   assumes "compact S"
  1348   assumes "compact S"
  1349       and contf: "continuous_on S f"
  1349       and contf: "continuous_on S f"
  1350       and "0 < e"
  1350       and "0 < e"
  1351       and "subspace T" "f ` S \<subseteq> T"
  1351       and "subspace T" "f ` S \<subseteq> T"
  1352     obtains g where "polynomial_function g" "g ` S \<subseteq> T"
  1352     obtains g where "polynomial_function g" "g ` S \<subseteq> T"
  1353                     "\<And>x. x \<in> S \<Longrightarrow> norm(f x - g x) < e"
  1353                     "\<And>x. x \<in> S \<Longrightarrow> norm(f x - g x) < e"
  1354 proof -
  1354 proof%unimportant -
  1355   obtain B where "B \<subseteq> T" and orthB: "pairwise orthogonal B"
  1355   obtain B where "B \<subseteq> T" and orthB: "pairwise orthogonal B"
  1356              and B1: "\<And>x. x \<in> B \<Longrightarrow> norm x = 1"
  1356              and B1: "\<And>x. x \<in> B \<Longrightarrow> norm x = 1"
  1357              and "independent B" and cardB: "card B = dim T"
  1357              and "independent B" and cardB: "card B = dim T"
  1358              and spanB: "span B = T"
  1358              and spanB: "span B = T"
  1359     using orthonormal_basis_subspace \<open>subspace T\<close> by metis
  1359     using orthonormal_basis_subspace \<open>subspace T\<close> by metis