Theory Analysis_More
section ‹Library Additions›
theory Analysis_More
imports "HOL-Analysis.Equivalence_Lebesgue_Henstock_Integration"
"HOL-Library.Function_Algebras"
"HOL-Types_To_Sets.Linear_Algebra_On"
begin
lemma openin_open_Int'[intro]:
"open S ⟹ openin (top_of_set U) (S ∩ U)"
by (auto simp: openin_open)
subsection ‹Parametricity rules for topology›
text ‹TODO: also check with theory ‹Transfer_Euclidean_Space_Vector› in AFP/ODE...›
context includes lifting_syntax begin
lemma Sigma_transfer[transfer_rule]:
"(rel_set A ===> (A ===> rel_set B) ===> rel_set (rel_prod A B)) Sigma Sigma"
unfolding Sigma_def
by transfer_prover
lemma filterlim_transfer[transfer_rule]:
"((A ===> B) ===> rel_filter B ===> rel_filter A ===> (=)) filterlim filterlim"
if [transfer_rule]: "bi_unique B"
unfolding filterlim_iff
by transfer_prover
lemma nhds_transfer[transfer_rule]:
"(A ===> rel_filter A) nhds nhds"
if [transfer_rule]: "bi_unique A" "bi_total A" "(rel_set A ===> (=)) open open"
unfolding nhds_def
by transfer_prover
lemma at_within_transfer[transfer_rule]:
"(A ===> rel_set A ===> rel_filter A) at_within at_within"
if [transfer_rule]: "bi_unique A" "bi_total A" "(rel_set A ===> (=)) open open"
unfolding at_within_def
by transfer_prover
lemma continuous_on_transfer[transfer_rule]:
"(rel_set A ===> (A ===> B) ===> (=)) continuous_on continuous_on"
if [transfer_rule]: "bi_unique A" "bi_total A" "(rel_set A ===> (=)) open open"
"bi_unique B" "bi_total B" "(rel_set B ===> (=)) open open"
unfolding continuous_on_def
by transfer_prover
lemma continuous_on_transfer_right_total[transfer_rule]:
"(rel_set A ===> (A ===> B) ===> (=)) (λX::'a::t2_space set. continuous_on (X ∩ Collect AP)) (λY::'b::t2_space set. continuous_on Y)"
if DomainA: "Domainp A = AP"
and [folded DomainA, transfer_rule]: "bi_unique A" "right_total A" "(rel_set A ===> (=)) (openin (top_of_set (Collect AP))) open"
"bi_unique B" "bi_total B" "(rel_set B ===> (=)) open open"
unfolding DomainA[symmetric]
proof (intro rel_funI)
fix X Y f g
assume H[transfer_rule]: "rel_set A X Y" "(A ===> B) f g"
from H(1) have XA: "x ∈ X ⟹ Domainp A x" for x
by (auto simp: rel_set_def)
then have *: "X ∩ Collect (Domainp A) = X" by auto
have "openin (top_of_set (Collect (Domainp A))) (Collect (Domainp A))" by auto
show " continuous_on (X ∩ Collect (Domainp A)) f = continuous_on Y g"
unfolding continuous_on_eq_continuous_within continuous_within_topological *
apply transfer
apply safe
subgoal for x B
apply (drule bspec, assumption, drule spec, drule mp, assumption, drule mp, assumption)
apply clarsimp
subgoal for AA
apply (rule exI[where x="AA ∩ Collect (Domainp A)"])
by (auto intro: XA)
done
subgoal using XA by (force simp: openin_subtopology)
done
qed
lemma continuous_on_transfer_right_total2[transfer_rule]:
"(rel_set A ===> (A ===> B) ===> (=)) (λX::'a::t2_space set. continuous_on X) (λY::'b::t2_space set. continuous_on Y)"
if DomainB: "Domainp B = BP"
and [folded DomainB, transfer_rule]: "bi_unique A" "bi_total A" "(rel_set A ===> (=)) open open"
"bi_unique B" "right_total B" "(rel_set B ===> (=)) ((openin (top_of_set (Collect BP)))) open"
unfolding DomainB[symmetric]
proof (intro rel_funI)
fix X Y f g
assume H[transfer_rule]: "rel_set A X Y" "(A ===> B) f g"
show "continuous_on X f = continuous_on Y g"
unfolding continuous_on_eq_continuous_within continuous_within_topological
apply transfer
apply safe
subgoal for x C
apply (clarsimp simp: openin_subtopology)
apply (drule bspec, assumption, drule spec, drule mp, assumption, drule mp, assumption)
apply clarsimp
by (meson Domainp_applyI H(1) H(2) rel_setD1)
subgoal for x C
proof -
let ?sub = "top_of_set (Collect (Domainp B))"
assume cont: "∀x∈X. ∀Ba∈{A. Ball A (Domainp B)}.
openin (top_of_set (Collect (Domainp B))) Ba ⟶ f x ∈ Ba ⟶ (∃Aa. open Aa ∧ x ∈ Aa ∧ (∀y∈X. y ∈ Aa ⟶ f y ∈ Ba))"
and x: "x ∈ X" "open C" "f x ∈ C"
let ?B = "C ∩ Collect (Domainp B)"
have "?B ∈ {A. Ball A (Domainp B)}" by auto
have "openin ?sub (Collect (Domainp B))" by auto
then have "openin ?sub ?B" using ‹open C› by auto
moreover have "f x ∈ ?B" using x
apply transfer apply auto
by (meson Domainp_applyI H(1) H(2) rel_setD1)
ultimately obtain D where "open D ∧ x ∈ D ∧ (∀y∈X. y ∈ D ⟶ f y ∈ ?B)"
using cont x
by blast
then show "∃A. open A ∧ x ∈ A ∧ (∀y∈X. y ∈ A ⟶ f y ∈ C)" by auto
qed
done
qed
lemma generate_topology_transfer[transfer_rule]:
includes lifting_syntax
assumes [transfer_rule]: "right_total A" "bi_unique A"
shows "(rel_set (rel_set A) ===> rel_set A ===> (=)) (generate_topology o (insert (Collect (Domainp A)))) generate_topology"
proof (intro rel_funI)
fix B C X Y assume t[transfer_rule]: "rel_set (rel_set A) B C" "rel_set A X Y"
then have "X ⊆ Collect (Domainp A)" by (auto simp: rel_set_def)
with t have rI: "rel_set A (X ∩ Collect (Domainp A)) Y"
by (auto simp: inf_absorb1)
have eq_UNIV_I: "Z = UNIV" if [transfer_rule]: "rel_set A {a. Domainp A a} Z" for Z
using that assms
apply (auto simp: right_total_def rel_set_def)
using bi_uniqueDr by fastforce
show "(generate_topology ∘ insert (Collect (Domainp A))) B X = generate_topology C Y"
unfolding o_def
proof (rule iffI)
fix x
assume "generate_topology (insert (Collect (Domainp A)) B) X"
then show "generate_topology C Y" unfolding o_def
using rI
proof (induction X arbitrary: Y)
case [transfer_rule]: UNIV
with eq_UNIV_I[of Y] show ?case
by (simp add: generate_topology.UNIV)
next
case (Int a b)
note [transfer_rule] = Int(5)
obtain a' where a'[transfer_rule]: "rel_set A (a ∩ Collect (Domainp A)) a'"
by (metis Domainp_iff Domainp_set Int_Collect)
obtain b' where b'[transfer_rule]: "rel_set A (b ∩ Collect (Domainp A)) b'"
by (metis Domainp_iff Domainp_set Int_Collect)
from Int.IH(1)[OF a'] Int.IH(2)[OF b']
have "generate_topology C a'" "generate_topology C b'" by auto
from generate_topology.Int[OF this] have "generate_topology C (a' ∩ b')" .
also have "a' ∩ b' = Y"
by transfer auto
finally show ?case
by (simp add: generate_topology.Int)
next
case (UN K)
note [transfer_rule] = UN(3)
have "∃K'. ∀k. rel_set A (k ∩ Collect (Domainp A)) (K' k)"
by (rule choice) (metis Domainp_iff Domainp_set Int_Collect)
then obtain K' where K': "⋀k. rel_set A (k ∩ Collect (Domainp A)) (K' k)" by metis
from UN.IH[OF _ this] have "generate_topology C k'" if "k' ∈ K'`K" for k' using that by auto
from generate_topology.UN[OF this] have "generate_topology C (⋃(K' ` K))" .
also
from K' have [transfer_rule]: "(rel_set (=) ===> rel_set A) (λx. x ∩ Collect (Domainp A)) K'"
by (fastforce simp: rel_fun_def rel_set_def)
have "⋃(K' ` K) = Y"
by transfer auto
finally show ?case
by (simp add: generate_topology.UN)
next
case (Basis s)
from this(1) show ?case
proof
assume "s = Collect (Domainp A)"
with eq_UNIV_I[of Y] Basis(2)
show ?case
by (simp add: generate_topology.UNIV)
next
assume "s ∈ B"
with Basis(2) obtain t where [transfer_rule]: "rel_set A (s ∩ Collect (Domainp A)) t" by auto
from Basis(1) t(1) have s: "s ∩ Collect (Domainp A) = s"
by (force simp: rel_set_def)
have "t ∈ C" using ‹s ∈ B› s
by transfer auto
also note [transfer_rule] = Basis(2)
have "t = Y"
by transfer auto
finally show ?case
by (rule generate_topology.Basis)
qed
qed
next
assume "generate_topology C Y"
then show "generate_topology (insert (Collect (Domainp A)) B) X"
using ‹rel_set A X Y›
proof (induction arbitrary: X)
case [transfer_rule]: UNIV
have "UNIV = (UNIV::'b set)" by auto
then have "X = {a. Domainp A a}" by transfer
then show ?case by (intro generate_topology.Basis) auto
next
case (Int a b)
obtain a' b' where [transfer_rule]: "rel_set A a' a" "rel_set A b' b"
by (meson assms(1) right_total_def right_total_rel_set)
from generate_topology.Int[OF Int.IH(1)[OF this(1)] Int.IH(2)[OF this(2)]]
have "generate_topology (insert {a. Domainp A a} B) (a' ∩ b')" by simp
also
define I where "I = a ∩ b"
from ‹rel_set A X (a ∩ b)› have [transfer_rule]: "rel_set A X I" by (simp add: I_def)
from I_def
have "a' ∩ b' = X" by transfer simp
finally show ?case .
next
case (UN K)
have "∃K'. ∀k. rel_set A (K' k) k"
by (rule choice) (meson assms(1) right_total_def right_total_rel_set)
then obtain K' where K': "⋀k. rel_set A (K' k) k" by metis
from UN.IH[OF _ this] have "generate_topology (insert {a. Domainp A a} B) k"
if "k ∈ K'`K" for k using that by auto
from generate_topology.UN[OF this]
have "generate_topology (insert {a. Domainp A a} B) (⋃(K'`K))" by auto
also
from K' have [transfer_rule]: "(rel_set (=) ===> rel_set A) K' id"
by (fastforce simp: rel_fun_def rel_set_def)
define U where "U = (⋃(id ` K))"
from ‹rel_set A X _› have [transfer_rule]: "rel_set A X U" by (simp add: U_def)
from U_def have "⋃(K' ` K) = X" by transfer simp
finally show ?case .
next
case (Basis s)
note [transfer_rule] = ‹rel_set A X s›
from ‹s ∈ C› have "X ∈ B" by transfer
then show ?case by (intro generate_topology.Basis) auto
qed
qed
qed
end
subsection ‹Miscellaneous›
lemmas [simp del] = mem_ball
lemma in_closureI[intro, simp]: "x ∈ X ⟹ x ∈ closure X"
using closure_subset by auto
lemmas open_continuous_vimage = continuous_on_open_vimage[THEN iffD1, rule_format]
lemma open_continuous_vimage': "open s ⟹ continuous_on s f ⟹ open B ⟹ open (s ∩ f -` B)"
using open_continuous_vimage[of s f B] by (auto simp: Int_commute)
lemma support_on_mono: "support_on carrier f ⊆ support_on carrier g"
if "⋀x. x ∈ carrier ⟹ f x ≠ 0 ⟹ g x ≠ 0"
using that
by (auto simp: support_on_def)
lemma image_prod: "(λ(x, y). (f x, g y)) ` (A × B) = f ` A × g ` B" by auto
subsection ‹Closed support›
definition "csupport_on X S = closure (support_on X S)"
lemma closed_csupport_on[intro, simp]: "closed (csupport_on carrier φ)"
by (auto simp: csupport_on_def)
lemma not_in_csupportD: "x ∉ csupport_on carrier φ ⟹ x ∈ carrier ⟹ φ x = 0"
by (auto simp: csupport_on_def support_on_def)
lemma csupport_on_mono: "csupport_on carrier f ⊆ csupport_on carrier g"
if "⋀x. x ∈ carrier ⟹ f x ≠ 0 ⟹ g x ≠ 0"
unfolding csupport_on_def
apply (rule closure_mono)
using that
by (rule support_on_mono)
subsection ‹Homeomorphism›
lemma homeomorphism_empty[simp]:
"homeomorphism {} t f f' ⟷ t = {}"
"homeomorphism s {} f f' ⟷ s = {}"
by (auto simp: homeomorphism_def)
lemma homeomorphism_add:
"homeomorphism UNIV UNIV (λx. x + c) (λx. x - c)"
for c::"_::real_normed_vector"
unfolding homeomorphism_def
by (auto simp: algebra_simps continuous_intros intro!: image_eqI[where x="x - c" for x])
lemma in_range_scaleR_iff: "x ∈ range ((*⇩R) c) ⟷ c = 0 ⟶ x = 0"
for x::"_::real_vector"
by (auto simp: intro!: image_eqI[where x="x /⇩R c"])
lemma homeomorphism_scaleR:
"homeomorphism UNIV UNIV (λx. c *⇩R x::_::real_normed_vector) (λx. x /⇩R c)"
if "c ≠ 0"
using that
unfolding homeomorphism_def
by (auto simp: in_range_scaleR_iff algebra_simps intro!: continuous_intros)
lemma homeomorphism_prod:
"homeomorphism (a × b) (c × d) (λ(x, y). (f x, g y)) (λ(x, y). (f' x, g' y))"
if "homeomorphism a c f f'"
"homeomorphism b d g g'"
using that by (simp add: homeomorphism_def image_prod)
(auto simp add: split_beta intro!: continuous_intros elim: continuous_on_compose2)
subsection ‹Generalizations›
lemma openin_subtopology_eq_generate_topology:
"openin (top_of_set S) x = generate_topology (insert S ((λB. B ∩ S) ` BB)) x"
if open_gen: "open = generate_topology BB" and subset: "x ⊆ S"
proof -
have "generate_topology (insert S ((λB. B ∩ S) ` BB)) (T ∩ S)"
if "generate_topology BB T"
for T
using that
proof (induction)
case UNIV
then show ?case by (auto intro!: generate_topology.Basis)
next
case (Int a b)
have "generate_topology (insert S ((λB. B ∩ S) ` BB)) (a ∩ S ∩ (b ∩ S))"
by (rule generate_topology.Int) (use Int in auto)
then show ?case by (simp add: ac_simps)
next
case (UN K)
then have "generate_topology (insert S ((λB. B ∩ S) ` BB)) (⋃k∈K. k ∩ S)"
by (intro generate_topology.UN) auto
then show ?case by simp
next
case (Basis s)
then show ?case
by (intro generate_topology.Basis) auto
qed
moreover
have "∃T. generate_topology BB T ∧ x = T ∩ S"
if "generate_topology (insert S ((λB. B ∩ S) ` BB)) x" "x ≠ UNIV"
using that
proof (induction)
case UNIV
then show ?case by simp
next
case (Int a b)
then show ?case
using generate_topology.Int
by auto
next
case (UN K)
from UN.IH have "∀k∈K-{UNIV}. ∃T. generate_topology BB T ∧ k = T ∩ S" by auto
from this[THEN bchoice] obtain T where T: "⋀k. k ∈ T ` (K - {UNIV}) ⟹ generate_topology BB k" "⋀k. k ∈ K - {UNIV} ⟹ k = (T k) ∩ S"
by auto
from generate_topology.UN[OF T(1)]
have "generate_topology BB (⋃(T ` (K - {UNIV})))" by auto
moreover have "⋃K = (⋃(T ` (K - {UNIV}))) ∩ S" if "UNIV ∉ K" using T(2) UN that by auto
ultimately show ?case
apply (cases "UNIV ∈ K") subgoal using UN by auto
subgoal by auto
done
next
case (Basis s)
then show ?case
using generate_topology.UNIV generate_topology.Basis by blast
qed
moreover
have "∃T. generate_topology BB T ∧ UNIV = T ∩ S" if "generate_topology (insert S ((λB. B ∩ S) ` BB)) x"
"x = UNIV"
proof -
have "S = UNIV"
using that ‹x ⊆ S›
by auto
then show ?thesis by (simp add: generate_topology.UNIV)
qed
ultimately show ?thesis
by (metis open_gen open_openin openin_open_Int' openin_subtopology)
qed
subsection ‹Equal topologies›
lemma topology_eq_iff: "t = s ⟷ (topspace t = topspace s ∧
(∀x⊆topspace t. openin t x = openin s x))"
by (metis (full_types) openin_subset topology_eq)
subsection ‹Finer topologies›
definition finer_than (infix "(finer'_than)" 50)
where "T1 finer_than T2 ⟷ continuous_map T1 T2 (λx. x)"
lemma finer_than_iff_nhds:
"T1 finer_than T2 ⟷ (∀X. openin T2 X ⟶ openin T1 (X ∩ topspace T1)) ∧ (topspace T1 ⊆ topspace T2)"
by (auto simp: finer_than_def continuous_map_alt)
lemma continuous_on_finer_topo:
"continuous_map s t f"
if "continuous_map s' t f" "s finer_than s'"
using that
by (auto simp: finer_than_def o_def dest: continuous_map_compose)
lemma continuous_on_finer_topo2:
"continuous_map s t f"
if "continuous_map s t' f" "t' finer_than t"
using that
by (auto simp: finer_than_def o_def dest: continuous_map_compose)
lemma antisym_finer_than: "S = T" if "S finer_than T" "T finer_than S"
using that
apply (auto simp: finer_than_def topology_eq_iff continuous_map_alt)
apply (metis inf.orderE)+
done
lemma subtopology_finer_than[simp]: "top_of_set X finer_than euclidean"
by (auto simp: finer_than_iff_nhds openin_subtopology)
subsection ‹Support›
lemma support_on_nonneg_sum:
"support_on X (λx. ∑i∈S. f i x) = (⋃i∈S. support_on X (f i))"
if "finite S" "⋀x i . x ∈ X ⟹ i ∈ S ⟹ f i x ≥ 0"
for f::"_⇒_⇒_::ordered_comm_monoid_add"
using that by (auto simp: support_on_def sum_nonneg_eq_0_iff)
lemma support_on_nonneg_sum_subset:
"support_on X (λx. ∑i∈S. f i x) ⊆ (⋃i∈S. support_on X (f i))"
for f::"_⇒_⇒_::ordered_comm_monoid_add"
by (cases "finite S") (auto simp: support_on_def, meson sum.neutral)
lemma support_on_nonneg_sum_subset':
"support_on X (λx. ∑i∈S x. f i x) ⊆ (⋃x∈X. (⋃i∈S x. support_on X (f i)))"
for f::"_⇒_⇒_::ordered_comm_monoid_add"
by (auto simp: support_on_def, meson sum.neutral)
subsection ‹Final topology (Bourbaki, General Topology I, 4.)›
definition "final_topology X Y f =
topology (λU. U ⊆ X ∧
(∀i. openin (Y i) (f i -` U ∩ topspace (Y i))))"
lemma openin_final_topology:
"openin (final_topology X Y f) =
(λU. U ⊆ X ∧ (∀i. openin (Y i) (f i -` U ∩ topspace (Y i))))"
unfolding final_topology_def
apply (rule topology_inverse')
unfolding istopology_def
proof safe
fix S T i
assume "∀i. openin (Y i) (f i -` S ∩ topspace (Y i))"
"∀i. openin (Y i) (f i -` T ∩ topspace (Y i))"
then have "openin (Y i) (f i -` S ∩ topspace (Y i) ∩ (f i -` T ∩ topspace (Y i)))"
(is "openin _ ?I")
by auto
also have "?I = f i -` (S ∩ T) ∩ topspace (Y i)"
(is "_ = ?R")
by auto
finally show "openin (Y i) ?R" .
next
fix K i
assume "∀U∈K. U ⊆ X ∧ (∀i. openin (Y i) (f i -` U ∩ topspace (Y i)))"
then have "openin (Y i) (⋃X∈K. f i -` X ∩ topspace (Y i))"
by (intro openin_Union) auto
then show "openin (Y i) (f i -` ⋃K ∩ topspace (Y i))"
by (auto simp: vimage_Union)
qed force+
lemma topspace_final_topology:
"topspace (final_topology X Y f) = X"
if "⋀i. f i ∈ topspace (Y i) → X"
proof -
have *: "f i -` X ∩ topspace (Y i) = topspace (Y i)" for i
using that
by auto
show ?thesis
unfolding topspace_def
unfolding openin_final_topology
apply (rule antisym)
apply force
apply (rule subsetI)
apply (rule UnionI[where X=X])
using that
by (auto simp: *)
qed
lemma continuous_on_final_topologyI2:
"continuous_map (Y i) (final_topology X Y f) (f i)"
if "⋀i. f i ∈ topspace (Y i) → X"
using that
by (auto simp: openin_final_topology continuous_map_alt topspace_final_topology)
lemma continuous_on_final_topologyI1:
"continuous_map (final_topology X Y f) Z g"
if hyp: "⋀i. continuous_map (Y i) Z (g o f i)"
and that: "⋀i. f i ∈ topspace (Y i) → X" "g ∈ X → topspace Z"
unfolding continuous_map_alt
proof safe
fix V assume V: "openin Z V"
have oV: "openin (Y i) (f i -` g -` V ∩ topspace (Y i))"
for i
using hyp[rule_format, of i] V
by (auto simp: continuous_map_alt vimage_comp dest!: spec[where x=V])
have *: "f i -` g -` V ∩ f i -` X ∩ topspace (Y i) =
f i -` g -` V ∩ topspace (Y i)"
(is "_ = ?rhs i")
for i using that
by auto
show "openin (final_topology X Y f) (g -` V ∩ topspace (final_topology X Y f))"
by (auto simp: openin_final_topology oV topspace_final_topology that *)
qed (use that in ‹auto simp: topspace_final_topology›)
lemma continuous_on_final_topology_iff:
"continuous_map (final_topology X Y f) Z g ⟷ (∀i. continuous_map (Y i) Z (g o f i))"
if "⋀i. f i ∈ topspace (Y i) → X" "g ∈ X → topspace Z"
using that
by (auto intro!: continuous_on_final_topologyI1[OF _ that]
intro: continuous_map_compose[OF continuous_on_final_topologyI2[OF that(1)]])
subsection ‹Quotient topology›
definition map_topology :: "('a ⇒ 'b) ⇒ 'a topology ⇒ 'b topology" where
"map_topology p X = final_topology (p ` topspace X) (λ_. X) (λ(_::unit). p)"
lemma openin_map_topology:
"openin (map_topology p X) = (λU. U ⊆ p ` topspace X ∧ openin X (p -` U ∩ topspace X))"
by (auto simp: map_topology_def openin_final_topology)
lemma topspace_map_topology[simp]: "topspace (map_topology f T) = f ` topspace T"
unfolding map_topology_def
by (subst topspace_final_topology) auto
lemma continuous_on_map_topology:
"continuous_map T (map_topology f T) f"
unfolding continuous_map_alt openin_map_topology
by auto
lemma continuous_map_composeD:
"continuous_map T X (g ∘ f) ⟹ g ∈ f ` topspace T → topspace X"
by (auto simp: continuous_map_def)
lemma continuous_on_map_topology2:
"continuous_map T X (g ∘ f) ⟷ continuous_map (map_topology f T) X g"
unfolding map_topology_def
apply safe
subgoal
apply (rule continuous_on_final_topologyI1)
subgoal by assumption
subgoal by force
subgoal by (rule continuous_map_composeD)
done
subgoal
apply (erule continuous_map_compose[rotated])
apply (rule continuous_on_final_topologyI2)
by force
done
lemma map_sub_finer_than_commute:
"map_topology f (subtopology T (f -` X)) finer_than subtopology (map_topology f T) X"
by (auto simp: finer_than_def continuous_map_def openin_subtopology openin_map_topology
topspace_subtopology)
lemma sub_map_finer_than_commute:
"subtopology (map_topology f T) X finer_than map_topology f (subtopology T (f -` X))"
if "openin T (f -` X)"
unfolding finer_than_def continuous_map_alt
proof (rule conjI, clarsimp)
fix U
assume "openin (map_topology f (subtopology T (f -` X))) U"
then obtain W where W: "U ⊆ f ` (topspace T ∩ f -` X)" "openin T W" "f -` U ∩ (topspace T ∩ f -` X) = W ∩ f -` X"
by (auto simp: topspace_subtopology openin_subtopology openin_map_topology)
have "(f -` f ` W ∩ f -` X) ∩ topspace T = W ∩ topspace T ∩ f -` X"
apply auto
by (metis Int_iff W(3) vimage_eq)
also have "openin T …"
by (auto intro!: W that)
finally show "openin (subtopology (map_topology f T) X) (U ∩ (f ` topspace T ∩ X))"
using W
unfolding topspace_subtopology topspace_map_topology openin_subtopology openin_map_topology
by (intro exI[where x="(f ` W ∩ X)"]) auto
qed auto
lemma subtopology_map_topology:
"subtopology (map_topology f T) X = map_topology f (subtopology T (f -` X))"
if "openin T (f -` X)"
apply (rule antisym_finer_than)
using sub_map_finer_than_commute[OF that] map_sub_finer_than_commute[of f T X]
by auto
lemma quotient_map_map_topology:
"quotient_map X (map_topology f X) f"
by (auto simp: quotient_map_def openin_map_topology ac_simps)
(simp_all add: vimage_def Int_def)
lemma topological_space_quotient: "class.topological_space (openin (map_topology f euclidean))"
if "surj f"
apply standard
apply (auto simp: )
using that
by (auto simp: openin_map_topology)
lemma t2_space_quotient: "class.t2_space (open::'b set ⇒ bool)"
if open_def: "open = (openin (map_topology (p::'a::t2_space⇒'b::topological_space) euclidean))"
"surj p" and open_p: "⋀X. open X ⟹ open (p ` X)" and "closed {(x, y). p x = p y}" (is "closed ?R")
apply (rule class.t2_space.intro)
subgoal by (unfold open_def, rule topological_space_quotient; fact)
proof standard
fix a b::'b
obtain x y where a_def: "a = p x" and b_def: "b = p y" using ‹surj p› by fastforce
assume "a ≠ b"
with ‹closed ?R› have "open (-?R)" "(x, y) ∈ -?R" by (auto simp add: a_def b_def)
from open_prod_elim[OF this]
obtain N⇩x N⇩y where "open N⇩x" "open N⇩y" "(x, y) ∈ N⇩x × N⇩y" "N⇩x × N⇩y ⊆ -?R" .
then have "p ` N⇩x ∩ p ` N⇩y = {}" by auto
moreover
from ‹open N⇩x› ‹open N⇩y› have "open (p ` N⇩x)" "open (p ` N⇩y)"
using open_p by blast+
moreover have "a ∈ p ` N⇩x" "b ∈ p ` N⇩y" using ‹(x, y) ∈ _ × _› by (auto simp: a_def b_def)
ultimately show "∃U V. open U ∧ open V ∧ a ∈ U ∧ b ∈ V ∧ U ∩ V = {}" by blast
qed
lemma second_countable_topology_quotient: "class.second_countable_topology (open::'b set ⇒ bool)"
if open_def: "open = (openin (map_topology (p::'a::second_countable_topology⇒'b::topological_space) euclidean))"
"surj p" and open_p: "⋀X. open X ⟹ open (p ` X)"
apply (rule class.second_countable_topology.intro)
subgoal by (unfold open_def, rule topological_space_quotient; fact)
proof standard
have euclidean_def: "euclidean = map_topology p euclidean"
by (simp add: openin_inverse open_def)
have continuous_on: "continuous_on UNIV p"
using continuous_map_iff_continuous2 continuous_on_map_topology euclidean_def by fastforce
from ex_countable_basis[where 'a='a] obtain A::"'a set set" where "countable A" "topological_basis A"
by auto
define B where "B = (λX. p ` X) ` A"
have "countable (B::'b set set)"
by (auto simp: B_def intro!: ‹countable A›)
moreover have "topological_basis B"
proof (rule topological_basisI)
fix B' assume "B' ∈ B" then show "open B'" using ‹topological_basis A›
by (auto simp: B_def topological_basis_open intro!: open_p)
next
fix x::'b and O' assume "open O'" "x ∈ O'"
have "open (p -` O')"
using ‹open O'›
by (rule open_vimage) (auto simp: continuous_on)
obtain y where y: "y ∈ p -` {x}"
using ‹x ∈ O'›
by auto (metis UNIV_I open_def(2) rangeE)
then have "y ∈ p -` O'" using ‹x ∈ O'› by auto
from topological_basisE[OF ‹topological_basis A› ‹open (p -` O')› this]
obtain C where "C ∈ A" "y ∈ C" "C ⊆ p -` O'" .
let ?B' = "p ` C"
have "?B' ∈ B"
using ‹C ∈ A› by (auto simp: B_def)
moreover
have "x ∈ ?B'" using y ‹y ∈ C› ‹x ∈ O'›
by auto
moreover
have "?B' ⊆ O'"
using ‹C ⊆ _› by auto
ultimately show "∃B'∈B. x ∈ B' ∧ B' ⊆ O'" by metis
qed
ultimately show "∃B::'b set set. countable B ∧ open = generate_topology B"
by (auto simp: topological_basis_imp_subbasis)
qed
subsection ‹Closure›
lemma closure_Union: "closure (⋃X) = (⋃x∈X. closure x)" if "finite X"
using that
by (induction X) auto
subsection ‹Compactness›
lemma compact_if_closed_subset_of_compact:
"compact S" if "closed S" "compact T" "S ⊆ T"
proof (rule compactI)
fix UU assume UU: "∀t∈UU. open t" "S ⊆ ⋃UU"
have "T ⊆ ⋃(insert (- S) (UU))" "⋀B. B ∈ insert (- S) UU ⟹ open B"
using UU ‹S ⊆ T›
by (auto simp: open_Compl ‹closed S›)
from compactE[OF ‹compact T› this]
obtain 𝒯' where 𝒯: "𝒯' ⊆ insert (- S) UU" "finite 𝒯'" "T ⊆ ⋃𝒯'"
by metis
show "∃C'⊆UU. finite C' ∧ S ⊆ ⋃C'"
apply (rule exI[where x="𝒯' - {-S}"])
using 𝒯 UU
apply auto
proof -
fix x assume "x ∈ S"
with 𝒯 ‹S ⊆ T› obtain U where "x ∈ U" "U ∈ 𝒯'" using 𝒯
by auto
then show "∃X∈𝒯' - {- S}. x ∈ X"
using 𝒯 UU ‹x ∈ S›
apply -
apply (rule bexI[where x=U])
by auto
qed
qed
subsection ‹Locally finite›
definition "locally_finite_on X I U ⟷ (∀p∈X. ∃N. p∈N ∧ open N ∧ finite {i∈I. U i ∩ N ≠ {}})"
lemmas locally_finite_onI = locally_finite_on_def[THEN iffD2, rule_format]
lemma locally_finite_onE:
assumes "locally_finite_on X I U"
assumes "p ∈ X"
obtains N where "p ∈ N" "open N" "finite {i∈I. U i ∩ N ≠ {}}"
using assms
by (auto simp: locally_finite_on_def)
lemma locally_finite_onD:
assumes "locally_finite_on X I U"
assumes "p ∈ X"
shows "finite {i∈I. p ∈ U i}"
apply (rule locally_finite_onE[OF assms])
apply (rule finite_subset)
by auto
lemma locally_finite_on_open_coverI: "locally_finite_on X I U"
if fin: "⋀j. j ∈ I ⟹ finite {i∈I. U i ∩ U j ≠ {}}"
and open_cover: "X ⊆ (⋃i∈I. U i)" "⋀i. i ∈ I ⟹ open (U i)"
proof (rule locally_finite_onI)
fix p assume "p ∈ X"
then obtain i where i: "i ∈ I" "p ∈ U i" "open (U i)"
using open_cover
by blast
show "∃N. p ∈ N ∧ open N ∧ finite {i ∈ I. U i ∩ N ≠ {}}"
by (intro exI[where x="U i"] conjI i fin)
qed
lemma locally_finite_compactD:
"finite {i∈I. U i ∩ V ≠ {}}"
if lf: "locally_finite_on X I U"
and compact: "compact V"
and subset: "V ⊆ X"
proof -
have "∃N. ∀p ∈ X. p ∈ N p ∧ open (N p) ∧ finite {i∈I. U i ∩ N p ≠ {}}"
by (rule bchoice) (auto elim!: locally_finite_onE[OF lf, rule_format])
then obtain N where N: "⋀p. p ∈ X ⟹ p ∈ N p"
"⋀p. p ∈ X ⟹ open (N p)"
"⋀p. p ∈ X ⟹ finite {i∈I. U i ∩ N p ≠ {}}"
by blast
have "V ⊆ (⋃p∈X. N p)" "⋀B. B ∈ N ` X ⟹ open B"
using N subset by force+
from compactE[OF compact this]
obtain C where C: "C ⊆ X" "finite C" "V ⊆ ⋃(N ` C)"
by (metis finite_subset_image)
then have "{i∈I. U i ∩ V ≠ {}} ⊆ {i∈I. U i ∩ ⋃(N ` C) ≠ {}}"
by force
also have "… ⊆ (⋃c∈C. {i∈I. U i ∩ N c ≠ {}})"
by force
also have "finite …"
apply (rule finite_Union)
using C by (auto intro!: C N)
finally (finite_subset) show ?thesis .
qed
lemma closure_Int_open_eq_empty: "open S ⟹ (closure T ∩ S) = {} ⟷ T ∩ S = {}"
by (auto simp: open_Int_closure_eq_empty ac_simps)
lemma locally_finite_on_subset:
assumes "locally_finite_on X J U"
assumes "⋀i. i ∈ I ⟹ V i ⊆ U i" "I ⊆ J"
shows "locally_finite_on X I V"
proof (rule locally_finite_onI)
fix p assume "p ∈ X"
from locally_finite_onE[OF assms(1) this]
obtain N where "p ∈ N" "open N" "finite {i ∈ J. U i ∩ N ≠ {}}" .
then show "∃N. p ∈ N ∧ open N ∧ finite {i ∈ I. V i ∩ N ≠ {}}"
apply (intro exI[where x=N])
using assms
by (auto elim!: finite_subset[rotated])
qed
lemma locally_finite_on_closure:
"locally_finite_on X I (λx. closure (U x))"
if "locally_finite_on X I U"
proof (rule locally_finite_onI)
fix p assume "p ∈ X"
from locally_finite_onE[OF that this] obtain N
where "p ∈ N" "open N" "finite {i ∈ I. U i ∩ N ≠ {}}" .
then show "∃N. p ∈ N ∧ open N ∧ finite {i ∈ I. closure (U i) ∩ N ≠ {}}"
by (auto intro!: exI[where x=N] simp: closure_Int_open_eq_empty)
qed
lemma locally_finite_on_closedin_Union_closure:
"closedin (top_of_set X) (⋃i∈I. closure (U i))"
if "locally_finite_on X I U" "⋀i. i ∈ I ⟹ closure (U i) ⊆ X"
unfolding closedin_def
apply safe
subgoal using that(2) by auto
subgoal
apply (subst openin_subopen)
proof clarsimp
fix x
assume x: "x ∈ X" "∀i∈I. x ∉ closure (U i)"
from locally_finite_onE[OF that(1) ‹x ∈ X›]
obtain N where N: "x ∈ N" "open N" "finite {i ∈ I. U i ∩ N ≠ {}}" (is "finite ?I").
define N' where "N' = N - (⋃i ∈ ?I. closure (U i))"
have "open N'"
by (auto simp: N'_def intro!: N)
then have "openin (top_of_set X) (X ∩ N')"
by (rule openin_open_Int)
moreover
have "x ∈ X ∩ N'" using x
by (auto simp: N'_def N)
moreover
have "X ∩ N' ⊆ X - (⋃i∈I. closure (U i))"
using x that(2)
apply (auto simp: N'_def)
by (meson N(2) closure_iff_nhds_not_empty dual_order.refl)
ultimately show "∃T. openin (top_of_set X) T ∧ x ∈ T ∧ T ⊆ X - (⋃i∈I. closure (U i))"
by auto
qed
done
lemma closure_subtopology_minimal:
"S ⊆ T ⟹ closedin (top_of_set X) T ⟹ closure S ∩ X ⊆ T"
apply (auto simp: closedin_closed)
using closure_minimal by blast
lemma locally_finite_on_closure_Union:
"(⋃i∈I. closure (U i)) = closure (⋃i∈I. (U i)) ∩ X"
if "locally_finite_on X I U" "⋀i. i ∈ I ⟹ closure (U i) ⊆ X"
proof (rule antisym)
show "(⋃i∈I. closure (U i)) ⊆ closure (⋃i∈I. U i) ∩ X"
using that
apply auto
by (metis (no_types, lifting) SUP_le_iff closed_closure closure_minimal closure_subset subsetCE)
show "closure (⋃i∈I. U i) ∩ X ⊆ (⋃i∈I. closure (U i))"
apply (rule closure_subtopology_minimal)
apply auto
using that
by (auto intro!: locally_finite_on_closedin_Union_closure)
qed
subsection ‹Refinement of cover›
definition refines :: "'a set set ⇒ 'a set set ⇒ bool" (infix "refines" 50)
where "A refines B ⟷ (∀s∈A. (∃t. t ∈ B ∧ s ⊆ t))"
lemma refines_subset: "x refines y" if "z refines y" "x ⊆ z"
using that by (auto simp: refines_def)
subsection ‹Functions as vector space›
instantiation "fun" :: (type, scaleR) scaleR begin
definition scaleR_fun :: "real ⇒ ('a ⇒ 'b) ⇒ 'a ⇒ 'b" where
"scaleR_fun r f = (λx. r *⇩R f x)"
lemma scaleR_fun_beta[simp]: "(r *⇩R f) x = r *⇩R f x"
by (simp add: scaleR_fun_def)
instance ..
end
instance "fun" :: (type, real_vector) real_vector
by standard (auto simp: scaleR_fun_def algebra_simps)
subsection ‹Additional lemmas›
lemmas [simp del] = vimage_Un vimage_Int
lemma finite_Collect_imageI: "finite {U ∈ f ` X. P U}" if "finite {x∈X. P (f x)}"
proof -
have "{d ∈ f ` X. P d} ⊆ f ` {c ∈ X. P (f c)}"
by blast
then show ?thesis
using finite_surj that by blast
qed
lemma plus_compose: "(x + y) ∘ f = (x ∘ f) + (y ∘ f)"
by auto
lemma mult_compose: "(x * y) ∘ f = (x ∘ f) * (y ∘ f)"
by auto
lemma scaleR_compose: "(c *⇩R x) ∘ f = c *⇩R (x ∘ f)"
by (auto simp:)
lemma image_scaleR_ball:
fixes a :: "'a::real_normed_vector"
shows "c ≠ 0 ⟹ (*⇩R) c ` ball a r = ball (c *⇩R a) (abs c *⇩R r)"
proof (auto simp: mem_ball dist_norm, goal_cases)
case (1 b)
have "norm (c *⇩R a - c *⇩R b) = abs c * norm (a - b)"
by (auto simp: norm_scaleR[symmetric] algebra_simps simp del: norm_scaleR)
also have "… < abs c * r"
apply (rule mult_strict_left_mono)
using 1 by auto
finally show ?case .
next
case (2 x)
have "norm (a - x /⇩R c) < r"
proof -
have "norm (a - x /⇩R c) = abs c *⇩R norm (a - x /⇩R c) /⇩R abs c"
using 2 by auto
also have "abs c *⇩R norm (a - x /⇩R c) = norm (c *⇩R a - x)"
using 2
by (auto simp: norm_scaleR[symmetric] algebra_simps simp del: norm_scaleR)
also have "… < ¦c¦ * r"
by fact
also have "¦c¦ * r /⇩R ¦c¦ = r" using 2 by auto
finally show ?thesis using 2 by auto
qed
then have xdc: "x /⇩R c ∈ ball a r"
by (auto simp: mem_ball dist_norm)
show ?case
apply (rule image_eqI[OF _ xdc])
using 2 by simp
qed
subsection ‹Continuity›
lemma continuous_within_topologicalE:
assumes "continuous (at x within s) f"
"open B" "f x ∈ B"
obtains A where "open A" "x ∈ A" "⋀y. y ∈ s ⟹ y ∈ A ⟹ f y ∈ B"
using assms continuous_within_topological by metis
lemma continuous_within_topologicalE':
assumes "continuous (at x) f"
"open B" "f x ∈ B"
obtains A where "open A" "x ∈ A" "f ` A ⊆ B"
using assms continuous_within_topologicalE[OF assms]
by (metis UNIV_I image_subsetI)
lemma continuous_on_inverse: "continuous_on S f ⟹ 0 ∉ f ` S ⟹ continuous_on S (λx. inverse (f x))"
for f::"_⇒_::real_normed_div_algebra"
by (auto simp: continuous_on_def intro!: tendsto_inverse)
subsection ‹@{term "(has_derivative)"}›
lemma has_derivative_plus_fun[derivative_intros]:
"(x + y has_derivative x' + y') (at a within A)"
if [derivative_intros]:
"(x has_derivative x') (at a within A)"
"(y has_derivative y') (at a within A)"
by (auto simp: plus_fun_def intro!: derivative_eq_intros)
lemma has_derivative_scaleR_fun[derivative_intros]:
"(x *⇩R y has_derivative x *⇩R y') (at a within A)"
if [derivative_intros]:
"(y has_derivative y') (at a within A)"
by (auto simp: scaleR_fun_def intro!: derivative_eq_intros)
lemma has_derivative_times_fun[derivative_intros]:
"(x * y has_derivative (λh. x a * y' h + x' h * y a)) (at a within A)"
if [derivative_intros]:
"(x has_derivative x') (at a within A)"
"(y has_derivative y') (at a within A)"
for x y::"_⇒'a::real_normed_algebra"
by (auto simp: times_fun_def intro!: derivative_eq_intros)
lemma real_sqrt_has_derivative_generic:
"x ≠ 0 ⟹ (sqrt has_derivative (*) ((if x > 0 then 1 else -1) * inverse (sqrt x) / 2)) (at x within S)"
apply (rule has_derivative_at_withinI)
using DERIV_real_sqrt_generic[of x "(if x > 0 then 1 else -1) * inverse (sqrt x) / 2"] at_within_open[of x "UNIV - {0}"]
by (auto simp: has_field_derivative_def open_delete ac_simps split: if_splits)
lemma sqrt_has_derivative:
"((λx. sqrt (f x)) has_derivative (λxa. (if 0 < f x then 1 else - 1) / (2 * sqrt (f x)) * f' xa)) (at x within S)"
if "(f has_derivative f') (at x within S)" "f x ≠ 0"
by (rule has_derivative_eq_rhs[OF has_derivative_compose[OF that(1) real_sqrt_has_derivative_generic, OF that(2)]])
(auto simp: divide_simps)
lemmas has_derivative_norm_compose[derivative_intros] = has_derivative_compose[OF _ has_derivative_norm]
subsection ‹Differentiable›
lemmas differentiable_on_empty[simp]
lemma differentiable_transform_eventually: "f differentiable (at x within X)"
if "g differentiable (at x within X)"
"f x = g x"
"∀⇩F x in (at x within X). f x = g x"
using that
apply (auto simp: differentiable_def)
subgoal for D
apply (rule exI[where x=D])
apply (auto simp: has_derivative_within)
by (simp add: eventually_mono Lim_transform_eventually)
done
lemma differentiable_within_eqI: "f differentiable at x within X"
if "g differentiable at x within X" "⋀x. x ∈ X ⟹ f x = g x"
"x ∈ X" "open X"
apply (rule differentiable_transform_eventually)
apply (rule that)
apply (auto simp: that)
proof -
have "∀⇩F x in at x within X. x ∈ X"
using ‹open X›
using eventually_at_topological by blast
then show " ∀⇩F x in at x within X. f x = g x"
by eventually_elim (auto simp: that)
qed
lemma differentiable_eqI: "f differentiable at x"
if "g differentiable at x" "⋀x. x ∈ X ⟹ f x = g x" "x ∈ X" "open X"
using that
unfolding at_within_open[OF that(3,4), symmetric]
by (rule differentiable_within_eqI)
lemma differentiable_on_eqI:
"f differentiable_on S"
if "g differentiable_on S" "⋀x. x ∈ S ⟹ f x = g x" "open S"
using that differentiable_eqI[of g _ S f]
by (auto simp: differentiable_on_eq_differentiable_at)
lemma differentiable_on_comp: "(f o g) differentiable_on S"
if "g differentiable_on S" "f differentiable_on (g ` S)"
using that
by (auto simp: differentiable_on_def intro: differentiable_chain_within)
lemma differentiable_on_comp2: "(f o g) differentiable_on S"
if "f differentiable_on T" "g differentiable_on S" "g ` S ⊆ T"
apply (rule differentiable_on_comp)
apply (rule that)
apply (rule differentiable_on_subset)
apply (rule that)
apply (rule that)
done
lemmas differentiable_on_compose2 = differentiable_on_comp2[unfolded o_def]
lemma differentiable_on_openD: "f differentiable at x"
if "f differentiable_on X" "open X" "x ∈ X"
using differentiable_on_eq_differentiable_at that by blast
lemma differentiable_on_add_fun[intro, simp]:
"x differentiable_on UNIV ⟹ y differentiable_on UNIV ⟹ x + y differentiable_on UNIV"
by (auto simp: plus_fun_def)
lemma differentiable_on_mult_fun[intro, simp]:
"x differentiable_on UNIV ⟹ y differentiable_on UNIV ⟹ x * y differentiable_on UNIV"
for x y::"_⇒'a::real_normed_algebra"
by (auto simp: times_fun_def)
lemma differentiable_on_scaleR_fun[intro, simp]:
"y differentiable_on UNIV ⟹ x *⇩R y differentiable_on UNIV"
by (auto simp: scaleR_fun_def)
lemma sqrt_differentiable:
"(λx. sqrt (f x)) differentiable (at x within S)"
if "f differentiable (at x within S)" "f x ≠ 0"
using that
using sqrt_has_derivative[of f _ x S]
by (auto simp: differentiable_def)
lemma sqrt_differentiable_on: "(λx. sqrt (f x)) differentiable_on S"
if "f differentiable_on S" "0 ∉ f ` S"
using sqrt_differentiable[of f _ S] that
by (force simp: differentiable_on_def)
lemma differentiable_on_inverse: "f differentiable_on S ⟹ 0 ∉ f ` S ⟹ (λx. inverse (f x)) differentiable_on S"
for f::"_⇒_::real_normed_field"
by (auto simp: differentiable_on_def intro!: differentiable_inverse)
lemma differentiable_on_openI:
"f differentiable_on S"
if "open S" "⋀x. x ∈ S ⟹ ∃f'. (f has_derivative f') (at x)"
using that
by (auto simp: differentiable_on_def at_within_open[where S=S] differentiable_def)
lemmas differentiable_norm_compose_at = differentiable_compose[OF differentiable_norm_at]
lemma differentiable_on_Pair:
"f differentiable_on S ⟹ g differentiable_on S ⟹ (λx. (f x, g x)) differentiable_on S"
unfolding differentiable_on_def
using differentiable_Pair[of f _ S g] by auto
lemma differentiable_at_fst:
"(λx. fst (f x)) differentiable at x within X" if "f differentiable at x within X"
using that
by (auto simp: differentiable_def dest!: has_derivative_fst)
lemma differentiable_at_snd:
"(λx. snd (f x)) differentiable at x within X" if "f differentiable at x within X"
using that
by (auto simp: differentiable_def dest!: has_derivative_snd)
lemmas frechet_derivative_worksI = frechet_derivative_works[THEN iffD1]
lemma sin_differentiable_at: "(λx. sin (f x::real)) differentiable at x within X"
if "f differentiable at x within X"
using differentiable_def has_derivative_sin that by blast
lemma cos_differentiable_at: "(λx. cos (f x::real)) differentiable at x within X"
if "f differentiable at x within X"
using differentiable_def has_derivative_cos that by blast
subsection ‹Frechet derivative›
lemmas frechet_derivative_transform_within_open_ext =
fun_cong[OF frechet_derivative_transform_within_open]
lemmas frechet_derivative_at' = frechet_derivative_at[symmetric]
lemma frechet_derivative_plus_fun:
"x differentiable at a ⟹ y differentiable at a ⟹
frechet_derivative (x + y) (at a) =
frechet_derivative x (at a) + frechet_derivative y (at a)"
by (rule frechet_derivative_at')
(auto intro!: derivative_eq_intros frechet_derivative_worksI)
lemmas frechet_derivative_plus = frechet_derivative_plus_fun[unfolded plus_fun_def]
lemma frechet_derivative_zero_fun: "frechet_derivative 0 (at a) = 0"
by (auto simp: frechet_derivative_const zero_fun_def)
lemma frechet_derivative_sin:
"frechet_derivative (λx. sin (f x)) (at x) = (λxa. frechet_derivative f (at x) xa * cos (f x))"
if "f differentiable (at x)"
for f::"_⇒real"
by (rule frechet_derivative_at'[OF has_derivative_sin[OF frechet_derivative_worksI[OF that]]])
lemma frechet_derivative_cos:
"frechet_derivative (λx. cos (f x)) (at x) = (λxa. frechet_derivative f (at x) xa * - sin (f x))"
if "f differentiable (at x)"
for f::"_⇒real"
by (rule frechet_derivative_at'[OF has_derivative_cos[OF frechet_derivative_worksI[OF that]]])
lemma differentiable_sum_fun:
"(⋀i. i ∈ I ⟹ (f i differentiable at a)) ⟹ sum f I differentiable at a"
by (induction I rule: infinite_finite_induct) (auto simp: zero_fun_def plus_fun_def)
lemma frechet_derivative_sum_fun:
"(⋀i. i ∈ I ⟹ (f i differentiable at a)) ⟹
frechet_derivative (∑i∈I. f i) (at a) = (∑i∈I. frechet_derivative (f i) (at a))"
by (induction I rule: infinite_finite_induct)
(auto simp: frechet_derivative_zero_fun frechet_derivative_plus_fun differentiable_sum_fun)
lemma sum_fun_def: "(∑i∈I. f i) = (λx. ∑i∈I. f i x)"
by (induction I rule: infinite_finite_induct) auto
lemmas frechet_derivative_sum = frechet_derivative_sum_fun[unfolded sum_fun_def]
lemma frechet_derivative_times_fun:
"f differentiable at a ⟹ g differentiable at a ⟹
frechet_derivative (f * g) (at a) =
(λx. f a * frechet_derivative g (at a) x + frechet_derivative f (at a) x * g a)"
for f g::"_⇒'a::real_normed_algebra"
by (rule frechet_derivative_at') (auto intro!: derivative_eq_intros frechet_derivative_worksI)
lemmas frechet_derivative_times = frechet_derivative_times_fun[unfolded times_fun_def]
lemma frechet_derivative_scaleR_fun:
"y differentiable at a ⟹
frechet_derivative (x *⇩R y) (at a) =
x *⇩R frechet_derivative y (at a)"
by (rule frechet_derivative_at')
(auto intro!: derivative_eq_intros frechet_derivative_worksI)
lemmas frechet_derivative_scaleR = frechet_derivative_scaleR_fun[unfolded scaleR_fun_def]
lemma frechet_derivative_compose:
"frechet_derivative (f o g) (at x) = frechet_derivative (f) (at (g x)) o frechet_derivative g (at x)"
if "g differentiable at x" "f differentiable at (g x)"
by (meson diff_chain_at frechet_derivative_at' frechet_derivative_works that)
lemma frechet_derivative_compose_eucl:
"frechet_derivative (f o g) (at x) =
(λv. ∑i∈Basis. ((frechet_derivative g (at x) v) ∙ i) *⇩R frechet_derivative f (at (g x)) i)"
(is "?l = ?r")
if "g differentiable at x" "f differentiable at (g x)"
proof (rule ext)
fix v
interpret g: linear "frechet_derivative g (at x)"
using that(1)
by (rule linear_frechet_derivative)
interpret f: linear "frechet_derivative f (at (g x))"
using that(2)
by (rule linear_frechet_derivative)
have "frechet_derivative (f o g) (at x) v =
frechet_derivative f (at (g x)) (∑i∈Basis. (frechet_derivative g (at x) v ∙ i) *⇩R i)"
unfolding frechet_derivative_compose[OF that] o_apply
by (simp add: euclidean_representation)
also have "… = ?r v"
by (auto simp: g.sum g.scaleR f.sum f.scaleR)
finally show "?l v = ?r v" .
qed
lemma frechet_derivative_works_on_open:
"f differentiable_on X ⟹ open X ⟹ x ∈ X ⟹
(f has_derivative frechet_derivative f (at x)) (at x)"
and frechet_derivative_works_on:
"f differentiable_on X ⟹ x ∈ X ⟹
(f has_derivative frechet_derivative f (at x within X)) (at x within X)"
by (auto simp: differentiable_onD differentiable_on_openD frechet_derivative_worksI)
lemma frechet_derivative_inverse: "frechet_derivative (λx. inverse (f x)) (at x) =
(λh. - 1 / (f x)⇧2 * frechet_derivative f (at x) h)"
if "f differentiable at x" "f x ≠ 0" for f::"_⇒_::real_normed_field"
apply (rule frechet_derivative_at')
using that
by (auto intro!: derivative_eq_intros frechet_derivative_worksI
simp: divide_simps algebra_simps power2_eq_square)
lemma frechet_derivative_sqrt: "frechet_derivative (λx. sqrt (f x)) (at x) =
(λv. (if f x > 0 then 1 else -1) / (2 * sqrt (f x)) * frechet_derivative f (at x) v)"
if "f differentiable at x" "f x ≠ 0"
apply (rule frechet_derivative_at')
apply (rule sqrt_has_derivative[THEN has_derivative_eq_rhs])
by (auto intro!: frechet_derivative_worksI that simp: divide_simps)
lemma frechet_derivative_norm: "frechet_derivative (λx. norm (f x)) (at x) =
(λv. frechet_derivative f (at x) v ∙ sgn (f x))"
if "f differentiable at x" "f x ≠ 0"
for f::"_⇒_::real_inner"
apply (rule frechet_derivative_at')
by (auto intro!: derivative_eq_intros frechet_derivative_worksI that simp: divide_simps)
lemma (in bounded_linear) frechet_derivative:
"frechet_derivative f (at x) = f"
apply (rule frechet_derivative_at')
apply (rule has_derivative_eq_rhs)
apply (rule has_derivative)
by (auto intro!: derivative_eq_intros)
bundle no_matrix_mult begin
no_notation matrix_matrix_mult (infixl "**" 70)
end
lemma (in bounded_bilinear) frechet_derivative:
includes no_matrix_mult
shows
"x differentiable at a ⟹ y differentiable at a ⟹
frechet_derivative (λa. x a ** y a) (at a) =
(λh. x a ** frechet_derivative y (at a) h + frechet_derivative x (at a) h ** y a)"
by (rule frechet_derivative_at') (auto intro!: FDERIV frechet_derivative_worksI)
lemma frechet_derivative_divide: "frechet_derivative (λx. f x / g x) (at x) =
(λh. frechet_derivative f (at x) h / (g x) -frechet_derivative g (at x) h * f x / (g x)⇧2)"
if "f differentiable at x" "g differentiable at x" "g x ≠ 0" for f::"_⇒_::real_normed_field"
using that
by (auto simp: divide_inverse_commute bounded_bilinear.frechet_derivative[OF bounded_bilinear_mult]
frechet_derivative_inverse)
lemma frechet_derivative_pair:
"frechet_derivative (λx. (f x, g x)) (at x) = (λv. (frechet_derivative f (at x) v, frechet_derivative g (at x) v))"
if "f differentiable (at x)" "g differentiable (at x)"
apply (rule frechet_derivative_at')
apply (rule derivative_eq_intros)
apply (rule frechet_derivative_worksI) apply fact
apply (rule frechet_derivative_worksI) apply fact
..
lemma frechet_derivative_fst:
"frechet_derivative (λx. fst (f x)) (at x) = (λxa. fst (frechet_derivative f (at x) xa))"
if "(f differentiable at x)"
for f::"_⇒(_::real_normed_vector × _::real_normed_vector)"
apply (rule frechet_derivative_at')
using that
by (auto intro!: derivative_eq_intros frechet_derivative_worksI)
lemma frechet_derivative_snd:
"frechet_derivative (λx. snd (f x)) (at x) = (λxa. snd (frechet_derivative f (at x) xa))"
if "(f differentiable at x)"
for f::"_⇒(_::real_normed_vector × _::real_normed_vector)"
apply (rule frechet_derivative_at')
using that
by (auto intro!: derivative_eq_intros frechet_derivative_worksI)
lemma frechet_derivative_eq_vector_derivative_1:
assumes "f differentiable at t"
shows "frechet_derivative f (at t) 1 = vector_derivative f (at t)"
apply (subst frechet_derivative_eq_vector_derivative)
apply (rule assms) by auto
subsection ‹Linear algebra›
lemma (in vector_space) dim_pos_finite_dimensional_vector_spaceE:
assumes "dim (UNIV::'b set) > 0"
obtains basis where "finite_dimensional_vector_space scale basis"
proof -
from assms obtain b where b: "local.span b = local.span UNIV" "local.independent b"
by (auto simp: dim_def split: if_splits)
then have "dim UNIV = card b"
by (rule dim_eq_card)
with assms have "finite b" by (auto simp: card_ge_0_finite)
then have "finite_dimensional_vector_space scale b"
by unfold_locales (auto simp: b)
then show ?thesis ..
qed
context vector_space_on begin
context includes lifting_syntax assumes "∃(Rep::'s ⇒ 'b) (Abs::'b ⇒ 's). type_definition Rep Abs S" begin
interpretation local_typedef_vector_space_on S scale "TYPE('s)" by unfold_locales fact
lemmas_with [var_simplified explicit_ab_group_add,
unoverload_type 'd,
OF type.ab_group_add_axioms type_vector_space_on_with,
folded dim_S_def,
untransferred,
var_simplified implicit_ab_group_add]:
lt_dim_pos_finite_dimensional_vector_spaceE = vector_space.dim_pos_finite_dimensional_vector_spaceE
end
lemmas_with [cancel_type_definition,
OF S_ne,
folded subset_iff',
simplified pred_fun_def, folded finite_dimensional_vector_space_on_with,
simplified]:
dim_pos_finite_dimensional_vector_spaceE = lt_dim_pos_finite_dimensional_vector_spaceE
end
subsection ‹Extensional function space›
text ‹f is zero outside A. We use such functions to canonically represent
functions whose domain is A›
definition extensional0 :: "'a set ⇒ ('a ⇒ 'b::zero) ⇒ bool"
where "extensional0 A f = (∀x. x ∉ A ⟶ f x = 0)"
lemma extensional0_0[intro, simp]: "extensional0 X 0"
by (auto simp: extensional0_def)
lemma extensional0_UNIV[intro, simp]: "extensional0 UNIV f"
by (auto simp: extensional0_def)
lemma ext_extensional0:
"f = g" if "extensional0 S f" "extensional0 S g" "⋀x. x ∈ S ⟹ f x = g x"
using that by (force simp: extensional0_def fun_eq_iff)
lemma extensional0_add[intro, simp]:
"extensional0 S f ⟹ extensional0 S g ⟹ extensional0 S (f + g::_⇒'a::comm_monoid_add)"
by (auto simp: extensional0_def)
lemma extensinoal0_mult[intro, simp]:
"extensional0 S x ⟹ extensional0 S y ⟹ extensional0 S (x * y)"
for x y::"_⇒'a::mult_zero"
by (auto simp: extensional0_def)
lemma extensional0_scaleR[intro, simp]: "extensional0 S f ⟹ extensional0 S (c *⇩R f::_⇒'a::real_vector)"
by (auto simp: extensional0_def)
lemma extensional0_outside: "x ∉ S ⟹ extensional0 S f ⟹ f x = 0"
by (auto simp: extensional0_def)
lemma subspace_extensional0: "subspace (Collect (extensional0 X))"
by (auto simp: subspace_def)
text ‹Send the function f to its canonical representative as a function with domain A›
definition restrict0 :: "'a set ⇒ ('a ⇒ 'b::zero) ⇒ 'a ⇒ 'b"
where "restrict0 A f x = (if x ∈ A then f x else 0)"
lemma restrict0_UNIV[simp]: "restrict0 UNIV = (λx. x)"
by (intro ext) (auto simp: restrict0_def)
lemma extensional0_restrict0[intro, simp]: "extensional0 A (restrict0 A f)"
by (auto simp: extensional0_def restrict0_def)
lemma restrict0_times: "restrict0 A (x * y) = restrict0 A x * restrict0 A y"
for x::"'a⇒'b::mult_zero"
by (auto simp: restrict0_def[abs_def])
lemma restrict0_apply_in[simp]: "x ∈ A ⟹ restrict0 A f x = f x"
by (auto simp: restrict0_def)
lemma restrict0_apply_out[simp]: "x ∉ A ⟹ restrict0 A f x = 0"
by (auto simp: restrict0_def)
lemma restrict0_scaleR: "restrict0 A (c *⇩R f::_⇒'a::real_vector) = c *⇩R restrict0 A f"
by (auto simp: restrict0_def[abs_def])
lemma restrict0_add: "restrict0 A (f + g::_⇒'a::real_vector) = restrict0 A f + restrict0 A g"
by (auto simp: restrict0_def[abs_def])
lemma restrict0_restrict0: "restrict0 X (restrict0 Y f) = restrict0 (X ∩ Y) f"
by (auto simp: restrict0_def)
end
Theory Smooth
section ‹Smooth Functions between Normed Vector Spaces›
theory Smooth
imports
Analysis_More
begin
subsection ‹From/To ‹Multivariate_Taylor.thy››
lemma multivariate_Taylor_integral:
fixes f::"'a::real_normed_vector ⇒ 'b::banach"
and Df::"'a ⇒ nat ⇒ 'a ⇒ 'b"
assumes "n > 0"
assumes Df_Nil: "⋀a x. Df a 0 H = f a"
assumes Df_Cons: "⋀a i d. a ∈ closed_segment X (X + H) ⟹ i < n ⟹
((λa. Df a i H) has_derivative (Df a (Suc i))) (at a within G)"
assumes cs: "closed_segment X (X + H) ⊆ G"
defines "i ≡ λx.
((1 - x) ^ (n - 1) / fact (n - 1)) *⇩R Df (X + x *⇩R H) n H"
shows multivariate_Taylor_has_integral:
"(i has_integral f (X + H) - (∑i<n. (1 / fact i) *⇩R Df X i H)) {0..1}"
and multivariate_Taylor:
"f (X + H) = (∑i<n. (1 / fact i) *⇩R Df X i H) + integral {0..1} i"
and multivariate_Taylor_integrable:
"i integrable_on {0..1}"
proof goal_cases
case 1
let ?G = "closed_segment X (X + H)"
define line where "line t = X + t *⇩R H" for t
have segment_eq: "closed_segment X (X + H) = line ` {0 .. 1}"
by (auto simp: line_def closed_segment_def algebra_simps)
have line_deriv: "⋀x. (line has_derivative (λt. t *⇩R H)) (at x)"
by (auto intro!: derivative_eq_intros simp: line_def [abs_def])
define g where "g = f o line"
define Dg where "Dg n t = Df (line t) n H" for n :: nat and t :: real
note ‹n > 0›
moreover
have Dg0: "Dg 0 = g" by (auto simp add: Dg_def Df_Nil g_def)
moreover
have DgSuc: "(Dg m has_vector_derivative Dg (Suc m) t) (at t within {0..1})"
if "m < n" "0 ≤ t" "t ≤ 1" for m::nat and t::real
proof -
from that have [intro]: "line t ∈ ?G" using assms
by (auto simp: segment_eq)
note [derivative_intros] = has_derivative_in_compose[OF _ has_derivative_subset[OF Df_Cons]]
interpret Df: linear "(λd. Df (line t) (Suc m) d)"
by (auto intro!: has_derivative_linear derivative_intros ‹m < n›)
note [derivative_intros] =
has_derivative_compose[OF _ line_deriv]
show ?thesis
using Df.scaleR ‹m < n›
by (auto simp: Dg_def [abs_def] has_vector_derivative_def g_def segment_eq
intro!: derivative_eq_intros subsetD[OF cs])
qed
ultimately
have g_Taylor: "(i has_integral g 1 - (∑i<n. ((1 - 0) ^ i / fact i) *⇩R Dg i 0)) {0 .. 1}"
unfolding i_def Dg_def [abs_def] line_def
by (rule Taylor_has_integral) auto
then show c: ?case using ‹n > 0› by (auto simp: g_def line_def Dg_def)
case 2 show ?case using c
by (simp add: integral_unique add.commute)
case 3 show ?case using c by force
qed
subsection ‹Higher-order differentiable›
fun higher_differentiable_on ::
"'a::real_normed_vector set ⇒ ('a ⇒ 'b::real_normed_vector) ⇒ nat ⇒ bool" where
"higher_differentiable_on S f 0 ⟷ continuous_on S f"
| "higher_differentiable_on S f (Suc n) ⟷
(∀x∈S. f differentiable (at x)) ∧
(∀v. higher_differentiable_on S (λx. frechet_derivative f (at x) v) n)"
lemma ball_differentiable_atD: "∀x∈S. f differentiable at x ⟹ f differentiable_on S"
by (auto simp: differentiable_on_def differentiable_at_withinI)
lemma higher_differentiable_on_imp_continuous_on:
"continuous_on S f" if "higher_differentiable_on S f n"
using that
by (cases n) (auto simp: differentiable_imp_continuous_on ball_differentiable_atD)
lemma higher_differentiable_on_imp_differentiable_on:
"f differentiable_on S" if "higher_differentiable_on S f k" "k > 0"
using that
by (cases k) (auto simp: ball_differentiable_atD)
lemma higher_differentiable_on_congI:
assumes "open S" "higher_differentiable_on S g n"
and "⋀x. x ∈ S ⟹ f x = g x"
shows "higher_differentiable_on S f n"
using assms(2,3)
proof (induction n arbitrary: f g)
case 0
then show ?case by auto
next
case (Suc n)
have 1: "∀x∈S. g differentiable (at x)" and
2: "higher_differentiable_on S (λx. frechet_derivative g (at x) v) n" for v
using Suc by auto
have 3: "∀x∈S. f differentiable (at x)" using 1 Suc(3) assms(1)
by (metis differentiable_eqI)
have 4: "frechet_derivative f (at x) v = frechet_derivative g (at x) v" if "x ∈ S" for x v
using "3" Suc.prems(2) assms(1) frechet_derivative_transform_within_open_ext that by blast
from 2 3 4 show ?case
using Suc.IH[OF 2 4] by auto
qed
lemma higher_differentiable_on_cong:
assumes "open S" "S = T"
and "⋀x. x ∈ T ⟹ f x = g x"
shows "higher_differentiable_on S f n ⟷ higher_differentiable_on T g n"
using higher_differentiable_on_congI assms by auto
lemma higher_differentiable_on_SucD:
"higher_differentiable_on S f n" if "higher_differentiable_on S f (Suc n)"
using that
by (induction n arbitrary: f) (auto simp: differentiable_imp_continuous_on ball_differentiable_atD)
lemma higher_differentiable_on_addD:
"higher_differentiable_on S f n" if "higher_differentiable_on S f (n + m)"
using that
by (induction m arbitrary: f n)
(auto simp del: higher_differentiable_on.simps dest!: higher_differentiable_on_SucD)
lemma higher_differentiable_on_le:
"higher_differentiable_on S f n" if "higher_differentiable_on S f m" "n ≤ m"
using higher_differentiable_on_addD[of S f n "m - n"] that
by auto
lemma higher_differentiable_on_open_subsetsI:
"higher_differentiable_on S f n"
if "⋀x. x ∈ S ⟹ ∃T. x ∈ T ∧ open T ∧ higher_differentiable_on T f n"
using that
proof (induction n arbitrary: f)
case 0
show ?case
by (force simp: continuous_on_def
dest!: 0
dest: at_within_open
intro!: Lim_at_imp_Lim_at_within[where S=S])
next
case (Suc n)
have "f differentiable at x" if "x ∈ S" for x
using Suc.prems[OF ‹x ∈ S›]
by (auto simp: differentiable_on_def dest: at_within_open dest!: bspec)
then have "f differentiable_on S"
by (auto simp: differentiable_on_def intro!: differentiable_at_withinI[where s=S])
with Suc show ?case
by fastforce
qed
lemma higher_differentiable_on_const: "higher_differentiable_on S (λx. c) n"
by (induction n arbitrary: c) (auto simp: continuous_intros frechet_derivative_const)
lemma higher_differentiable_on_id: "higher_differentiable_on S (λx. x) n"
by (cases n) (auto simp: frechet_derivative_works higher_differentiable_on_const)
lemma higher_differentiable_on_add:
"higher_differentiable_on S (λx. f x + g x) n"
if "higher_differentiable_on S f n"
"higher_differentiable_on S g n"
"open S"
using that
proof (induction n arbitrary: f g)
case 0
then show ?case by (auto intro!: continuous_intros)
next
case (Suc n)
from Suc.prems have
f: "⋀x. x∈S ⟹ f differentiable (at x)"
and hf: "higher_differentiable_on S (λx. frechet_derivative f (at x) v) n"
and g: "⋀x. x∈S ⟹ g differentiable (at x)"
and hg: "higher_differentiable_on S (λx. frechet_derivative g (at x) v) n"
for v
by auto
show ?case
using f g ‹open S›
by (auto simp: frechet_derivative_plus
intro!: derivative_intros f g Suc.IH hf hg
cong: higher_differentiable_on_cong)
qed
lemma (in bounded_bilinear) differentiable:
"(λx. prod (f x) (g x)) differentiable at x within S"
if "f differentiable at x within S"
"g differentiable at x within S"
by (blast intro: differentiableI frechet_derivative_worksI that FDERIV)
context begin
private lemmas d = bounded_bilinear.differentiable
lemmas differentiable_inner = bounded_bilinear_inner[THEN d]
and differentiable_scaleR = bounded_bilinear_scaleR[THEN d]
and differentiable_mult = bounded_bilinear_mult[THEN d]
end
lemma (in bounded_bilinear) differentiable_on:
"(λx. prod (f x) (g x)) differentiable_on S"
if "f differentiable_on S" "g differentiable_on S"
using that by (auto simp: differentiable_on_def differentiable)
context begin
private lemmas do = bounded_bilinear.differentiable_on
lemmas differentiable_on_inner = bounded_bilinear_inner[THEN do]
and differentiable_on_scaleR = bounded_bilinear_scaleR[THEN do]
and differentiable_on_mult = bounded_bilinear_mult[THEN do]
end
lemma (in bounded_bilinear) higher_differentiable_on:
"higher_differentiable_on S (λx. prod (f x) (g x)) n"
if
"higher_differentiable_on S f n"
"higher_differentiable_on S g n"
"open S"
using that
proof (induction n arbitrary: f g)
case 0
then show ?case by (auto intro!: continuous_intros continuous_on)
next
case (Suc n)
from Suc.prems have
f: "⋀x. x∈S ⟹ f differentiable (at x)"
and hf: "higher_differentiable_on S (λx. frechet_derivative f (at x) v) n"
and g: "⋀x. x∈S ⟹ g differentiable (at x)"
and hg: "higher_differentiable_on S (λx. frechet_derivative g (at x) v) n"
for v
by auto
show ?case
using f g ‹open S› Suc
by (auto simp: frechet_derivative
intro!: derivative_intros f g differentiable higher_differentiable_on_add Suc.IH
intro: higher_differentiable_on_SucD
cong: higher_differentiable_on_cong)
qed
context begin
private lemmas hdo = bounded_bilinear.higher_differentiable_on
lemmas higher_differentiable_on_inner = bounded_bilinear_inner[THEN hdo]
and higher_differentiable_on_scaleR = bounded_bilinear_scaleR[THEN hdo]
and higher_differentiable_on_mult = bounded_bilinear_mult[THEN hdo]
end
lemma higher_differentiable_on_sum:
"higher_differentiable_on S (λx. ∑i∈F. f i x) n"
if "⋀i. i ∈ F ⟹ finite F ⟹ higher_differentiable_on S (f i) n" "open S"
using that
by (induction F rule: infinite_finite_induct)
(auto intro!: higher_differentiable_on_const higher_differentiable_on_add)
lemma higher_differentiable_on_subset:
"higher_differentiable_on S f n"
if "higher_differentiable_on T f n" "S ⊆ T"
using that
by (induction n arbitrary: f) (auto intro: continuous_on_subset differentiable_on_subset)
lemma higher_differentiable_on_compose:
"higher_differentiable_on S (f o g) n"
if "higher_differentiable_on T f n" "higher_differentiable_on S g n" "g ` S ⊆ T" "open S" "open T"
for g::"_⇒_::euclidean_space"
using that(1-3)
proof (induction n arbitrary: f g)
case 0
then show ?case using that(4-)
by (auto simp: continuous_on_compose2)
next
case (Suc n)
from Suc.prems
have
f: "⋀x. x ∈ T ⟹ f differentiable (at x)"
and g: "⋀x. x ∈ S ⟹ g differentiable (at x)"
and hf: "higher_differentiable_on T (λx. frechet_derivative f (at x) v) n"
and hg: "higher_differentiable_on S (λx. frechet_derivative g (at x) w) n"
for v w
by auto
show ?case
using ‹g ` _ ⊆ _› ‹open S› f g ‹open T› Suc
Suc.IH[where f="λx. frechet_derivative f (at x) v"
and g = "λx. g x" for v, unfolded o_def]
higher_differentiable_on_SucD[OF Suc.prems(2)]
by (auto
simp: frechet_derivative_compose_eucl subset_iff
simp del: o_apply
intro!: differentiable_chain_within higher_differentiable_on_sum
higher_differentiable_on_scaleR higher_differentiable_on_inner
higher_differentiable_on_const
intro: differentiable_at_withinI
cong: higher_differentiable_on_cong)
qed
lemma higher_differentiable_on_uminus:
"higher_differentiable_on S (λx. - f x) n"
if "higher_differentiable_on S f n" "open S"
using higher_differentiable_on_scaleR[of S "λx. -1" n f] that
by (auto simp: higher_differentiable_on_const)
lemma higher_differentiable_on_minus:
"higher_differentiable_on S (λx. f x - g x) n"
if "higher_differentiable_on S f n"
"higher_differentiable_on S g n"
"open S"
using higher_differentiable_on_add[OF _ higher_differentiable_on_uminus, OF that(1,2,3,3)]
by simp
lemma higher_differentiable_on_inverse:
"higher_differentiable_on S (λx. inverse (f x)) n"
if "higher_differentiable_on S f n" "0 ∉ f ` S" "open S"
for f::"_⇒_::real_normed_field"
using that
proof (induction n arbitrary: f)
case 0
then show ?case by (auto simp: continuous_on_inverse)
next
case (Suc n)
from Suc.prems(1) have fn: "higher_differentiable_on S f n" by (rule higher_differentiable_on_SucD)
from Suc show ?case
by (auto simp: continuous_on_inverse image_iff power2_eq_square
frechet_derivative_inverse divide_inverse
intro!: differentiable_inverse higher_differentiable_on_uminus higher_differentiable_on_mult
Suc.IH fn
cong: higher_differentiable_on_cong)
qed
lemma higher_differentiable_on_divide:
"higher_differentiable_on S (λx. f x / g x) n"
if
"higher_differentiable_on S f n"
"higher_differentiable_on S g n"
"⋀x. x ∈ S ⟹ g x ≠ 0"
"open S"
for f::"_⇒_::real_normed_field"
using higher_differentiable_on_mult[OF _ higher_differentiable_on_inverse, OF that(1,2) _ that(4,4)]
that(3)
by (auto simp: divide_inverse image_iff)
lemma differentiable_on_open_Union:
"f differentiable_on ⋃S"
if "⋀s. s ∈ S ⟹ f differentiable_on s"
"⋀s. s ∈ S ⟹ open s"
using that
unfolding differentiable_on_def
by (metis Union_iff at_within_open open_Union)
lemma higher_differentiable_on_open_Union: "higher_differentiable_on (⋃S) f n"
if "⋀s. s ∈ S ⟹ higher_differentiable_on s f n"
"⋀s. s ∈ S ⟹ open s"
using that
proof (induction n arbitrary: f)
case 0
then show ?case by (auto simp: continuous_on_open_Union)
next
case (Suc n)
then show ?case
by (auto simp: differentiable_on_open_Union)
qed
lemma differentiable_on_open_Un:
"f differentiable_on S ∪ T"
if "f differentiable_on S"
"f differentiable_on T"
"open S" "open T"
using that differentiable_on_open_Union[of "{S, T}" f]
by auto
lemma higher_differentiable_on_open_Un: "higher_differentiable_on (S ∪ T) f n"
if "higher_differentiable_on S f n"
"higher_differentiable_on T f n"
"open S" "open T"
using higher_differentiable_on_open_Union[of "{S, T}" f n] that
by auto
lemma higher_differentiable_on_sqrt: "higher_differentiable_on S (λx. sqrt (f x)) n"
if "higher_differentiable_on S f n" "0 ∉ f ` S" "open S"
using that
proof (induction n arbitrary: f)
case 0
then show ?case by (auto simp: continuous_intros)
next
case (Suc n)
from Suc.prems(1) have fn: "higher_differentiable_on S f n" by (rule higher_differentiable_on_SucD)
then have "continuous_on S f"
by (rule higher_differentiable_on_imp_continuous_on)
with ‹open S› have op: "open (S ∩ f -` {0<..})" (is "open ?op")
by (rule open_continuous_vimage') simp
from ‹open S› ‹continuous_on S f› have on: "open (S ∩ f -` {..<0})" (is "open ?on")
by (rule open_continuous_vimage') simp
have op': "higher_differentiable_on ?op (λx. 1) n" and on': "higher_differentiable_on ?on (λx. -1) n"
by (rule higher_differentiable_on_const)+
then have i: "higher_differentiable_on (?op ∪ ?on) (λx. if 0 < f x then 1::real else - 1) n"
by (auto intro!: higher_differentiable_on_open_Un op on
higher_differentiable_on_congI[OF _ op'] higher_differentiable_on_congI[OF _ on'])
also have "?op ∪ ?on = S" using Suc by auto
finally have i: "higher_differentiable_on S (λx. if 0 < f x then 1::real else - 1) n" .
from fn i Suc show ?case
by (auto simp: sqrt_differentiable_on image_iff frechet_derivative_sqrt
intro!: sqrt_differentiable higher_differentiable_on_mult higher_differentiable_on_inverse
higher_differentiable_on_divide higher_differentiable_on_const
cong: higher_differentiable_on_cong)
qed
lemma higher_differentiable_on_frechet_derivativeI:
"higher_differentiable_on X (λx. frechet_derivative f (at x) h) i"
if "higher_differentiable_on X f (Suc i)" "open X" "x ∈ X"
using that(1)
by (induction i arbitrary: f h) auto
lemma higher_differentiable_on_norm:
"higher_differentiable_on S (λx. norm (f x)) n"
if "higher_differentiable_on S f n" "0 ∉ f ` S" "open S"
for f::"_⇒_::real_inner"
using that
proof (induction n arbitrary: f)
case 0
then show ?case by (auto simp: continuous_on_norm)
next
case (Suc n)
from Suc.prems(1) have fn: "higher_differentiable_on S f n" by (rule higher_differentiable_on_SucD)
from Suc show ?case
by (auto simp: continuous_on_norm frechet_derivative_norm image_iff sgn_div_norm
cong: higher_differentiable_on_cong
intro!: differentiable_norm_compose_at higher_differentiable_on_inner
higher_differentiable_on_inverse
higher_differentiable_on_mult Suc.IH fn)
qed
declare higher_differentiable_on.simps [simp del]
lemma higher_differentiable_on_Pair:
"higher_differentiable_on S f k ⟹ higher_differentiable_on S g k ⟹
higher_differentiable_on S (λx. (f x, g x)) k"
if "open S"
proof (induction k arbitrary: f g)
case 0
then show ?case
unfolding higher_differentiable_on.simps
by (auto intro!: continuous_intros)
next
case (Suc k)
then show ?case using that
unfolding higher_differentiable_on.simps
by (auto simp: frechet_derivative_pair[of f _ g] cong: higher_differentiable_on_cong)
qed
lemma higher_differentiable_on_compose':
"higher_differentiable_on S (λx. f (g x)) n"
if "higher_differentiable_on T f n" "higher_differentiable_on S g n" "g ` S ⊆ T" "open S" "open T"
for g::"_⇒_::euclidean_space"
using higher_differentiable_on_compose[of T f n S g] comp_def that
by (metis (no_types, lifting) higher_differentiable_on_cong)
lemma higher_differentiable_on_fst:
"higher_differentiable_on (S × T) fst k"
proof (induction k)
case (Suc k)
then show ?case
unfolding higher_differentiable_on.simps
by (auto simp: differentiable_at_fst frechet_derivative_fst frechet_derivative_id higher_differentiable_on_const)
qed (auto simp: higher_differentiable_on.simps continuous_on_fst)
lemma higher_differentiable_on_snd:
"higher_differentiable_on (S × T) snd k"
proof (induction k)
case (Suc k)
then show ?case
unfolding higher_differentiable_on.simps
by (auto intro!: continuous_intros
simp: differentiable_at_snd frechet_derivative_snd frechet_derivative_id higher_differentiable_on_const)
qed (auto simp: higher_differentiable_on.simps continuous_on_snd)
lemma higher_differentiable_on_fst_comp:
"higher_differentiable_on S (λx. fst (f x)) k"
if "higher_differentiable_on S f k" "open S"
using that
by (induction k arbitrary: f)
(auto intro!: continuous_intros differentiable_at_fst
cong: higher_differentiable_on_cong
simp: higher_differentiable_on.simps frechet_derivative_fst)
lemma higher_differentiable_on_snd_comp:
"higher_differentiable_on S (λx. snd (f x)) k"
if "higher_differentiable_on S f k" "open S"
using that
by (induction k arbitrary: f)
(auto intro!: continuous_intros differentiable_at_snd
cong: higher_differentiable_on_cong
simp: higher_differentiable_on.simps frechet_derivative_snd)
lemma higher_differentiable_on_Pair':
"higher_differentiable_on S f k ⟹ higher_differentiable_on T g k ⟹
higher_differentiable_on (S × T) (λx. (f (fst x), g (snd x))) k"
if S: "open S" and T: "open T"
for f::"_::euclidean_space⇒_" and g::"_::euclidean_space⇒_"
by (auto intro!: higher_differentiable_on_Pair open_Times S T
higher_differentiable_on_fst
higher_differentiable_on_snd
higher_differentiable_on_compose'[where f=f and T=S]
higher_differentiable_on_compose'[where f=g and T=T])
lemma higher_differentiable_on_sin: "higher_differentiable_on S (λx. sin (f x::real)) n"
and higher_differentiable_on_cos: "higher_differentiable_on S (λx. cos (f x::real)) n"
if f: "higher_differentiable_on S f n" and S: "open S"
unfolding atomize_conj
using f
proof (induction n)
case (Suc n)
then have "higher_differentiable_on S f n"
"higher_differentiable_on S (λx. sin (f x)) n"
"higher_differentiable_on S (λx. cos (f x)) n"
"⋀x. x ∈ S ⟹ f differentiable at x"
using higher_differentiable_on_SucD
by (auto simp: higher_differentiable_on.simps)
with Suc show ?case
by (auto simp: higher_differentiable_on.simps sin_differentiable_at cos_differentiable_at
frechet_derivative_sin frechet_derivative_cos S
intro!: higher_differentiable_on_mult higher_differentiable_on_uminus
cong: higher_differentiable_on_cong[OF S])
qed (auto simp: higher_differentiable_on.simps intro!: continuous_intros)
subsection ‹Higher directional derivatives›
primrec nth_derivative :: "nat ⇒ ('a::real_normed_vector ⇒ 'b::real_normed_vector) ⇒ 'a ⇒ 'a ⇒ 'b" where
"nth_derivative 0 f x h = f x"
| "nth_derivative (Suc i) f x h = nth_derivative i (λx. frechet_derivative f (at x) h) x h"
lemma frechet_derivative_nth_derivative_commute:
"frechet_derivative (λx. nth_derivative i f x h) (at x) h =
nth_derivative i (λx. frechet_derivative f (at x) h) x h"
by (induction i arbitrary: f) auto
lemma nth_derivative_funpow:
"nth_derivative i f x h = ((λf x. frechet_derivative f (at x) h) ^^ i) f x"
by (induction i arbitrary: f) (auto simp del: funpow.simps simp: funpow_Suc_right)
lemma nth_derivative_exists:
"∃f'. ((λx. nth_derivative i f x h) has_derivative f') (at x) ∧
f' h = nth_derivative (Suc i) f x h"
if "higher_differentiable_on X f (Suc i)" "open X" "x ∈ X"
using that(1)
proof (induction i arbitrary: f)
case 0
with that show ?case
by (auto simp: higher_differentiable_on.simps that dest!: frechet_derivative_worksI)
next
case (Suc i)
from Suc.prems
have "⋀x. x ∈ X ⟹ f differentiable at x" "higher_differentiable_on X (λx. frechet_derivative f (at x) h) (Suc i)"
unfolding higher_differentiable_on.simps(2)[where n = "Suc i"]
by auto
from Suc.IH[OF this(2)] show ?case
by auto
qed
lemma higher_derivatives_exists:
assumes "higher_differentiable_on X f n" "open X"
obtains Df where
"⋀a h. Df a 0 h = f a"
"⋀a h i. i < n ⟹ a ∈ X ⟹ ((λa. Df a i H) has_derivative Df a (Suc i)) (at a)"
"⋀a i. i ≤ n ⟹ a ∈ X ⟹ Df a i H = nth_derivative i f a H"
proof -
have "higher_differentiable_on X f (Suc i)" if "i < n" for i
apply (rule higher_differentiable_on_le[OF assms(1)])
using that by simp
from nth_derivative_exists[OF this assms(2)]
have "∀i∈{..<n}. ∀x ∈ X. ∃f'. ((λx. nth_derivative i f x H) has_derivative f') (at x) ∧ f' H = nth_derivative (Suc i) f x H"
by blast
from this[unfolded bchoice_iff]
obtain f' where f': "i < n ⟹ x ∈ X ⟹ ((λx. nth_derivative i f x H) has_derivative f' x i) (at x)"
"i < n ⟹ x ∈ X ⟹ f' x i H = nth_derivative (Suc i) f x H" for x i
by force
define Df where "Df a i h = (if i = 0 then f a else f' a (i - 1) h)" for a i h
have "Df a 0 h = f a" for a h
by (auto simp: Df_def)
moreover have "i < n ⟹ a ∈ X ⟹ ((λa. Df a i H) has_derivative Df a (Suc i)) (at a)"
for i a
apply (auto simp: Df_def[abs_def])
using _ ‹open X›
apply (rule has_derivative_transform_within_open)
apply (rule f')
apply (auto simp: f')
done
moreover have "i ≤ n ⟹ a ∈ X ⟹ Df a i H = nth_derivative i f a H" for i a
by (auto simp: Df_def f')
ultimately show ?thesis ..
qed
lemma nth_derivative_differentiable:
assumes "higher_differentiable_on S f (Suc n)" "x ∈ S"
shows "(λx. nth_derivative n f x v) differentiable at x"
using assms
by (induction n arbitrary: f) (auto simp: higher_differentiable_on.simps)
lemma higher_differentiable_on_imp_continuous_nth_derivative:
assumes "higher_differentiable_on S f n"
shows "continuous_on S (λx. nth_derivative n f x v)"
using assms
by (induction n arbitrary: f) (auto simp: higher_differentiable_on.simps)
lemma frechet_derivative_at_real_eq_scaleR:
"frechet_derivative f (at x) v = v *⇩R frechet_derivative f (at x) 1"
if "f differentiable (at x)" "NO_MATCH 1 v"
by (simp add: frechet_derivative_eq_vector_derivative that)
lemma higher_differentiable_on_real_Suc:
"higher_differentiable_on S f (Suc n) ⟷
(∀x∈S. f differentiable (at x)) ∧
(higher_differentiable_on S (λx. frechet_derivative f (at x) 1) n)"
if "open S"
for S::"real set"
using ‹open S›
by (auto simp: higher_differentiable_on.simps frechet_derivative_at_real_eq_scaleR
intro!: higher_differentiable_on_scaleR higher_differentiable_on_const
cong: higher_differentiable_on_cong)
lemma higher_differentiable_on_real_SucI:
fixes S::"real set"
assumes
"⋀x. x ∈ S ⟹ (λx. nth_derivative n f x 1) differentiable at x"
"continuous_on S (λx. nth_derivative (Suc n) f x 1)"
"higher_differentiable_on S f n"
and o: "open S"
shows "higher_differentiable_on S f (Suc n)"
using assms
proof (induction n arbitrary: f)
case 0
then show ?case
by (auto simp: higher_differentiable_on_real_Suc higher_differentiable_on.simps(1) o)
qed (fastforce simp: higher_differentiable_on_real_Suc)
lemma higher_differentiable_on_real_Suc':
"open S ⟹ higher_differentiable_on S f (Suc n) ⟷
(∀v. continuous_on S (λx. nth_derivative (Suc n) f x 1)) ∧
(∀x∈S. ∀v. (λx. nth_derivative n f x 1) differentiable (at x)) ∧ higher_differentiable_on S f n"
for S::"real set"
apply (auto simp: nth_derivative_differentiable
dest: higher_differentiable_on_SucD
intro: higher_differentiable_on_real_SucI)
by (auto simp: higher_differentiable_on_real_Suc higher_differentiable_on.simps(1)
higher_differentiable_on_imp_continuous_nth_derivative)
lemma closed_segment_subsetD:
"0 ≤ x ⟹ x ≤ 1 ⟹ (X + x *⇩R H) ∈ S"
if "closed_segment X (X + H) ⊆ S"
using that
by (rule subsetD) (auto simp: closed_segment_def algebra_simps intro!: exI[where x=x])
lemma higher_differentiable_Taylor:
fixes f::"'a::real_normed_vector ⇒ 'b::banach"
and H::"'a"
and Df::"'a ⇒ nat ⇒ 'a ⇒ 'a ⇒ 'b"
assumes "n > 0"
assumes hd: "higher_differentiable_on S f n" "open S"
assumes cs: "closed_segment X (X + H) ⊆ S"
defines "i ≡ λx. ((1 - x) ^ (n - 1) / fact (n - 1)) *⇩R nth_derivative n f (X + x *⇩R H) H"
shows "(i has_integral f (X + H) - (∑i<n. (1 / fact i) *⇩R nth_derivative i f X H)) {0..1}" (is ?th1)
and "f (X + H) = (∑i<n. (1 / fact i) *⇩R nth_derivative i f X H) + integral {0..1} i" (is ?th2)
and "i integrable_on {0..1}" (is ?th3)
proof -
from higher_derivatives_exists[OF hd]
obtain Df where Df: "(⋀a h. Df a 0 h = f a)"
"(⋀a h i. i < n ⟹ a ∈ S ⟹ ((λa. Df a i H) has_derivative Df a (Suc i)) (at a))"
"⋀a i. i ≤ n ⟹ a ∈ S ⟹ Df a i H = nth_derivative i f a H"
by blast
from multivariate_Taylor_integral[OF ‹n > 0›, of Df H f X, OF Df(1,2)] cs
have mt: "((λx. ((1 - x) ^ (n - 1) / fact (n - 1)) *⇩R Df (X + x *⇩R H) n H) has_integral
f (X + H) - (∑i<n. (1 / fact i) *⇩R Df X i H))
{0..1}"
by force
from cs have "X ∈ S" by auto
show ?th1
apply (rule has_integral_eq_rhs)
unfolding i_def
using negligible_empty _ mt
apply (rule has_integral_spike)
using closed_segment_subsetD[OF cs]
by (auto simp: Df ‹X ∈ S›)
then show ?th2 ?th3
unfolding has_integral_iff
by auto
qed
lemma frechet_derivative_componentwise:
"frechet_derivative f (at a) v = (∑i∈Basis. (v ∙ i) * (frechet_derivative f (at a) i))"
if "f differentiable at a"
for f::"'a::euclidean_space ⇒ real"
proof -
have "linear (frechet_derivative f (at a))"
using that
by (rule linear_frechet_derivative)
from Linear_Algebra.linear_componentwise[OF this, of v 1]
show ?thesis
by simp
qed
lemma second_derivative_componentwise:
"nth_derivative 2 f a v =
(∑i∈Basis. (∑j∈Basis. frechet_derivative (λa. frechet_derivative f (at a) j) (at a) i * (v ∙ j)) * (v ∙ i))"
if "higher_differentiable_on S f 2" and S: "open S" "a ∈ S"
for f::"'a::euclidean_space ⇒ real"
proof -
have diff: "(λx. frechet_derivative f (at x) v) differentiable at a" for v
using that
by (auto simp: numeral_2_eq_2 higher_differentiable_on.simps differentiable_on_openD
dest!: spec[where x=v])
have d1: "x ∈ S ⟹ f differentiable at x" for x
using that
by (auto simp: numeral_2_eq_2 higher_differentiable_on.simps dest!: differentiable_on_openD)
have eq: "⋀x. x ∈ Basis ⟹
frechet_derivative
(λx. ∑i∈Basis. v ∙ i * frechet_derivative f (at x) i) (at a) x =
(∑j∈Basis. frechet_derivative (λa. frechet_derivative f (at a) j) (at a) x * (v ∙ j))"
apply (subst frechet_derivative_sum)
subgoal by (auto intro!: differentiable_mult diff)
apply (rule sum.cong)
apply simp
apply (subst frechet_derivative_times)
subgoal by simp
subgoal by (rule diff)
by (simp add: frechet_derivative_const)
show ?thesis
apply (simp add: numeral_2_eq_2)
apply (subst frechet_derivative_componentwise[OF diff])
apply (rule sum.cong)
apply simp
apply simp
apply (rule disjI2)
apply (rule trans)
apply (rule frechet_derivative_transform_within_open_ext [OF _ S frechet_derivative_componentwise])
apply (simp add: diff)
apply (rule d1, assumption)
apply (simp add: eq)
done
qed
lemma higher_differentiable_Taylor1:
fixes f::"'a::real_normed_vector ⇒ 'b::banach"
assumes hd: "higher_differentiable_on S f 2" "open S"
assumes cs: "closed_segment X (X + H) ⊆ S"
defines "i ≡ λx. ((1 - x)) *⇩R nth_derivative 2 f (X + x *⇩R H) H"
shows "(i has_integral f (X + H) - (f X + nth_derivative 1 f X H)) {0..1}"
and "f (X + H) = f X + nth_derivative 1 f X H + integral {0..1} i"
and "i integrable_on {0..1}"
using higher_differentiable_Taylor[OF _ hd cs]
by (auto simp: numeral_2_eq_2 i_def)
lemma differentiable_on_open_blinfunE:
assumes "f differentiable_on S" "open S"
obtains f' where "⋀x. x ∈ S ⟹ (f has_derivative blinfun_apply (f' x)) (at x)"
proof -
{
fix x assume "x ∈ S"
with assms obtain f' where f': "(f has_derivative f') (at x)"
by (auto dest!: differentiable_on_openD simp: differentiable_def)
then have "bounded_linear f'"
by (rule has_derivative_bounded_linear)
then obtain bf' where "f' = blinfun_apply bf'"
by (metis bounded_linear_Blinfun_apply)
then have "∃bf'. (f has_derivative blinfun_apply bf') (at x)" using f'
by blast
} then obtain f' where "⋀x. x ∈ S ⟹ (f has_derivative blinfun_apply (f' x)) (at x)"
by metis
then show ?thesis ..
qed
lemma continuous_on_blinfunI1:
"continuous_on X f"
if "⋀i. i ∈ Basis ⟹ continuous_on X (λx. blinfun_apply (f x) i)"
using that
by (auto simp: continuous_on_def intro: tendsto_componentwise1)
lemma c1_euclidean_blinfunE:
fixes f::"'a::euclidean_space⇒'b::real_normed_vector"
assumes "⋀x. x ∈ S ⟹ (f has_derivative f' x) (at x within S)"
assumes "⋀i. i ∈ Basis ⟹ continuous_on S (λx. f' x i)"
obtains bf' where
"⋀x. x ∈ S ⟹ (f has_derivative blinfun_apply (bf' x)) (at x within S)"
"continuous_on S bf'"
"⋀x. x ∈ S ⟹ blinfun_apply (bf' x) = f' x"
proof -
from assms have "bounded_linear (f' x)" if "x ∈ S" for x
by (auto intro!: has_derivative_bounded_linear that)
then obtain bf' where bf': "∀x ∈ S. f' x = blinfun_apply (bf' x)"
apply atomize_elim
apply (rule bchoice)
apply auto
by (metis bounded_linear_Blinfun_apply)
with assms have "⋀x. x ∈ S ⟹ (f has_derivative blinfun_apply (bf' x)) (at x within S)"
by simp
moreover
have f_tendsto: "((λn. f' n j) ⤏ f' x j) (at x within S)"
if "x ∈ S" "j ∈ Basis"
for x j
using assms by (auto simp: continuous_on_def that)
have "continuous_on S bf'"
by (rule continuous_on_blinfunI1) (simp add: bf'[rule_format, symmetric] assms)
moreover have "⋀x. x ∈ S ⟹ blinfun_apply (bf' x) = f' x" using bf' by auto
ultimately show ?thesis ..
qed
lemma continuous_Sigma:
assumes defined: "y ∈ Pi T X"
assumes f_cont: "continuous_on (Sigma T X) (λ(t, x). f t x)"
assumes y_cont: "continuous_on T y"
shows "continuous_on T (λx. f x (y x))"
using
defined
continuous_on_compose2[OF
continuous_on_subset[where t="(λx. (x, y x)) ` T", OF f_cont]
continuous_on_Pair[OF continuous_on_id y_cont]]
by auto
lemma continuous_on_Times_swap:
"continuous_on (X × Y) (λ(x, y). f x y)"
if "continuous_on (Y × X) (λ(y, x). f x y)"
using continuous_on_compose2[OF that continuous_on_swap, where s="X × Y"]
by (auto simp: split_beta' product_swap)
lemma leibniz_rule':
"⋀x. x ∈ S ⟹
((λx. integral (cbox a b) (f x)) has_derivative (λv. integral (cbox a b) (λt. fx x t v)))
(at x within S)"
"(λx. integral (cbox a b) (f x)) differentiable_on S"
if "convex S"
and c1: "⋀t x. t ∈ cbox a b ⟹ x ∈ S ⟹ ((λx. f x t) has_derivative fx x t) (at x within S)"
"⋀i. i ∈ Basis ⟹ continuous_on (S × cbox a b) (λ(x, t). fx x t i)"
and i: "⋀x. x ∈ S ⟹ f x integrable_on cbox a b"
for S::"'a::euclidean_space set"
and f::"'a ⇒ 'b::euclidean_space ⇒ 'c::euclidean_space"
proof -
have fx1: "continuous_on S (λx. fx x t i)" if "t ∈ cbox a b" "i ∈ Basis" for i t
by (rule continuous_Sigma[OF _ c1(2), where y="λ_. t"]) (auto simp: continuous_intros that)
{
fix x assume "x ∈ S"
have fx2: "continuous_on (cbox a b) (λt. fx x t i)" if "i ∈ Basis" for i
by (rule continuous_Sigma[OF _ continuous_on_Times_swap[OF c1(2)]])
(auto simp: continuous_intros that ‹x ∈ S›)
{
fix t
assume "t ∈ cbox a b"
have "∃f'. (∀x ∈ S. ((λx. f x t) has_derivative blinfun_apply (f' x)) (at x within S) ∧
blinfun_apply (f' x) = fx x t) ∧
continuous_on S f'"
by (rule c1_euclidean_blinfunE[OF c1(1)[OF ‹t ∈ _›] fx1[OF ‹t ∈ _›]]) (auto, metis)
} then obtain fx' where
fx':
"⋀t x. t ∈ cbox a b ⟹ x ∈ S ⟹ ((λx. f x t) has_derivative blinfun_apply (fx' t x)) (at x within S)"
"⋀t x. t ∈ cbox a b ⟹ x ∈ S ⟹ blinfun_apply (fx' t x) = fx x t"
"⋀t. t ∈ cbox a b ⟹ continuous_on S (fx' t)"
by metis
have c: "continuous_on (S × cbox a b) (λ(x, t). fx' t x)"
apply (rule continuous_on_blinfunI1)
using c1(2)
apply (rule continuous_on_eq) apply assumption
by (auto simp: fx' split_beta')
from leibniz_rule[of S a b f "λx t. fx' t x" x, OF fx'(1) i c ‹x ∈ S› ‹convex S›]
have "((λx. integral (cbox a b) (f x)) has_derivative blinfun_apply (integral (cbox a b) (λt. fx' t x))) (at x within S)"
by auto
then have "((λx. integral (cbox a b) (f x)) has_derivative blinfun_apply (integral (cbox a b) (λt. fx' t x))) (at x within S)"
by auto
also
have fx'xi: "(λt. fx' t x) integrable_on cbox a b"
apply (rule integrable_continuous)
apply (rule continuous_on_blinfunI1)
by (simp add: fx' ‹x ∈ S› fx2)
have "blinfun_apply (integral (cbox a b) (λt. fx' t x)) = (λv. integral (cbox a b) (λxb. fx x xb v))"
apply (rule ext)
apply (subst blinfun_apply_integral)
apply (rule fx'xi)
by (simp add: ‹x ∈ S› fx' cong: integral_cong)
finally show "((λx. integral (cbox a b) (f x)) has_derivative (λc. integral (cbox a b) (λxb. fx x xb c))) (at x within S)"
by simp
} then show "(λx. integral (cbox a b) (f x)) differentiable_on S"
by (auto simp: differentiable_on_def differentiable_def)
qed
lemmas leibniz_rule'_interval = leibniz_rule'[where 'b="_::ordered_euclidean_space",
unfolded cbox_interval]
lemma leibniz_rule'_higher:
"higher_differentiable_on S (λx. integral (cbox a b) (f x)) k"
if "convex S" "open S"
and c1: "higher_differentiable_on (S×cbox a b) (λ(x, t). f x t) k"
for S::"'a::euclidean_space set"
and f::"'a ⇒ 'b::euclidean_space ⇒ 'c::euclidean_space"
using c1
proof (induction k arbitrary: f)
case 0
then show ?case
by (auto simp: higher_differentiable_on.simps intro!: integral_continuous_on_param)
next
case (Suc k)
define D where "D x = frechet_derivative (λ(x, y). f x y) (at x)" for x
note [continuous_intros] =
Suc.prems[THEN higher_differentiable_on_imp_continuous_on, THEN continuous_on_compose2,
of _ "λx. (f x, g x)" for f g, unfolded split_beta' fst_conv snd_conv]
from Suc.prems have prems:
"⋀xt. xt ∈ S × cbox a b ⟹ (λ(x, y). f x y) differentiable at xt"
"higher_differentiable_on (S × cbox a b) (λx. D x (dx, dt)) k"
for dx dt
by (auto simp: higher_differentiable_on.simps D_def)
from frechet_derivative_worksI[OF this(1), folded D_def]
have D: "x ∈ S ⟹ t ∈ cbox a b ⟹ ((λ(x, y). f x y) has_derivative D (x, t)) (at (x, t))" for x t
by auto
have p1: "((λx. (x, t::'b)) has_derivative (λh. (h, 0))) (at x within S)" for x t
by (auto intro!: derivative_eq_intros)
have Dx: "x ∈ S ⟹ t ∈ cbox a b ⟹ ((λx. f x t) has_derivative (λdx. D (x, t) (dx, 0))) (at x within S)" for x t
by (drule has_derivative_compose[OF p1 D], assumption) auto
have cD: "continuous_on (S × cbox a b) (λ(x, t). D (x, t) v)" for v
apply (rule higher_differentiable_on_imp_continuous_on[where n=k])
using prems(2)[of "fst v" "snd v"]
by (auto simp: split_beta')
have fi: "x ∈ S ⟹ f x integrable_on cbox a b" for x
by (rule integrable_continuous) (auto intro!: continuous_intros)
from leibniz_rule'[OF ‹convex S› Dx cD fi]
have ihd: "x ∈ S ⟹ ((λx. integral (cbox a b) (f x)) has_derivative (λv. integral (cbox a b) (λt. D (x, t) (v, 0))))
(at x within S)"
and "(λx. integral (cbox a b) (f x)) differentiable_on S"
for x
by auto
then have "x ∈ S ⟹ (λx. integral (cbox a b) (f x)) differentiable at x" for x
using ‹open S›
by (auto simp: differentiable_on_openD)
moreover
have "higher_differentiable_on S (λx. frechet_derivative (λx. integral (cbox a b) (f x)) (at x) v) k" for v
proof -
have *: "frechet_derivative (λx. integral (cbox a b) (f x)) (at x) =
(λv. integral (cbox a b) (λt. D (x, t) (v, 0)))"
if "x ∈ S"
for x
apply (rule frechet_derivative_at')
using ihd(1)[OF that] at_within_open[OF that ‹open S›]
by auto
have **: "higher_differentiable_on S (λx. integral (cbox a b) (λt. D (x, t) (v, 0))) k"
apply (rule Suc.IH)
using prems by auto
show ?thesis
using ‹open S›
by (auto simp: * ** cong: higher_differentiable_on_cong)
qed
ultimately
show ?case
by (auto simp: higher_differentiable_on.simps)
qed
lemmas leibniz_rule'_higher_interval = leibniz_rule'_higher[where 'b="_::ordered_euclidean_space",
unfolded cbox_interval]
subsection ‹Smoothness›
definition k_smooth_on :: "enat ⇒'a::real_normed_vector set ⇒ ('a ⇒ 'b::real_normed_vector) ⇒ bool"
("_-smooth'_on" [1000]) where
smooth_on_def: "k-smooth_on S f = (∀n≤k. higher_differentiable_on S f n)"
abbreviation "smooth_on S f ≡ ∞-smooth_on S f"
lemma derivative_is_smooth':
assumes "(k+1)-smooth_on S f"
shows "k-smooth_on S (λx. frechet_derivative f (at x) v)"
unfolding smooth_on_def
proof (intro allI impI)
fix n assume "enat n ≤ k" then have "Suc n ≤ k + 1"
unfolding plus_1_eSuc
by (auto simp: eSuc_def split: enat.splits)
then have "higher_differentiable_on S f (Suc n)"
using assms(1) by (auto simp: smooth_on_def)
then show "higher_differentiable_on S (λx. frechet_derivative f (at x) v) n"
by (auto simp: higher_differentiable_on.simps(2))
qed
lemma derivative_is_smooth: "smooth_on S f ⟹ smooth_on S (λx. frechet_derivative f (at x) v)"
using derivative_is_smooth'[of ∞ S f] by simp
lemma smooth_on_imp_continuous_on: "continuous_on S f" if "k-smooth_on S f"
apply (rule higher_differentiable_on_imp_continuous_on[where n=0])
using that
by (simp add: smooth_on_def enat_0)
lemma smooth_on_imp_differentiable_on[simp]: "f differentiable_on S" if "k-smooth_on S f" "k ≠ 0"
using that
by (auto simp: smooth_on_def Suc_ile_eq enat_0
dest!: spec[where x=1]
intro!: higher_differentiable_on_imp_differentiable_on[where k=1])
lemma smooth_on_cong:
assumes "k-smooth_on S g" "open S"
and "⋀x. x ∈ S ⟹ f x = g x"
shows "k-smooth_on S f"
using assms unfolding smooth_on_def
by (auto cong: higher_differentiable_on_cong)
lemma smooth_on_open_Un:
"k-smooth_on S f ⟹ k-smooth_on T f ⟹ open S ⟹ open T ⟹ k-smooth_on (S ∪ T) f"
by (auto simp: smooth_on_def higher_differentiable_on_open_Un)
lemma smooth_on_open_subsetsI:
"k-smooth_on S f"
if "⋀x. x ∈ S ⟹ ∃T. x ∈ T ∧ open T ∧ k-smooth_on T f"
using that
unfolding smooth_on_def
by (force intro: higher_differentiable_on_open_subsetsI)
lemma smooth_on_const[intro]: "k-smooth_on S (λx. c)"
by (auto simp: smooth_on_def higher_differentiable_on_const)
lemma smooth_on_id[intro]: "k-smooth_on S (λx. x)"
by (auto simp: smooth_on_def higher_differentiable_on_id)
lemma smooth_on_add_fun: "k-smooth_on S f ⟹ k-smooth_on S g ⟹ open S ⟹ k-smooth_on S (f + g)"
by (auto simp: smooth_on_def higher_differentiable_on_add plus_fun_def)
lemmas smooth_on_add = smooth_on_add_fun[unfolded plus_fun_def]
lemma smooth_on_sum:
"n-smooth_on S (λx. ∑i∈F. f i x)"
if "⋀i. i ∈ F ⟹ finite F ⟹ n-smooth_on S (f i)" "open S"
using that
by (auto simp: smooth_on_def higher_differentiable_on_sum)
lemma (in bounded_bilinear) smooth_on:
includes no_matrix_mult
assumes "k-smooth_on S f" "k-smooth_on S g" "open S"
shows "k-smooth_on S (λx. (f x) ** (g x))"
using assms
by (auto simp: smooth_on_def higher_differentiable_on)
lemma smooth_on_compose2:
fixes g::"_⇒_::euclidean_space"
assumes "k-smooth_on T f" "k-smooth_on S g" "open U" "open T" "g ` U ⊆ T" "U ⊆ S"
shows "k-smooth_on U (f o g)"
using assms
by (auto simp: smooth_on_def intro!: higher_differentiable_on_compose intro: higher_differentiable_on_subset)
lemma smooth_on_compose:
fixes g::"_⇒_::euclidean_space"
assumes "k-smooth_on T f" "k-smooth_on S g" "open S" "open T" "g ` S ⊆ T"
shows "k-smooth_on S (f o g)"
using assms by (rule smooth_on_compose2) auto
lemma smooth_on_subset:
"k-smooth_on S f"
if "k-smooth_on T f" "S ⊆ T"
using higher_differentiable_on_subset[of T f _ S] that
by (auto simp: smooth_on_def)
context begin
private lemmas s = bounded_bilinear.smooth_on
lemmas smooth_on_inner = bounded_bilinear_inner[THEN s]
and smooth_on_scaleR = bounded_bilinear_scaleR[THEN s]
and smooth_on_mult = bounded_bilinear_mult[THEN s]
end
lemma smooth_on_divide:"k-smooth_on S f ⟹ k-smooth_on S g ⟹ open S ⟹(⋀x. x ∈ S ⟹ g x ≠ 0) ⟹
k-smooth_on S (λx. f x / g x)"
for f::"_⇒_::real_normed_field"
by (auto simp: smooth_on_def higher_differentiable_on_divide)
lemma smooth_on_scaleR_fun: "k-smooth_on S g ⟹ open S ⟹ k-smooth_on S (c *⇩R g)"
by (auto simp: scaleR_fun_def intro!: smooth_on_scaleR )
lemma smooth_on_uminus_fun: "k-smooth_on S g ⟹ open S ⟹ k-smooth_on S (- g)"
using smooth_on_scaleR_fun[where c="-1", of k S g]
by auto
lemmas smooth_on_uminus = smooth_on_uminus_fun[unfolded fun_Compl_def]
lemma smooth_on_minus_fun: "k-smooth_on S f ⟹ k-smooth_on S g ⟹ open S ⟹ k-smooth_on S (f - g)"
unfolding diff_conv_add_uminus
apply (rule smooth_on_add_fun)
apply assumption
apply (rule smooth_on_uminus_fun)
by auto
lemmas smooth_on_minus = smooth_on_minus_fun[unfolded fun_diff_def]
lemma smooth_on_times_fun: "k-smooth_on S f ⟹ k-smooth_on S g ⟹ open S ⟹ k-smooth_on S (f * g)"
for f g::"_ ⇒_::real_normed_algebra"
by (auto simp: times_fun_def intro!: smooth_on_mult)
lemma smooth_on_le:
"l-smooth_on S f"
if "k-smooth_on S f" "l ≤ k"
using that
by (auto simp: smooth_on_def)
lemma smooth_on_inverse: "k-smooth_on S (λx. inverse (f x))"
if "k-smooth_on S f" "0 ∉ f ` S" "open S"
for f::"_ ⇒_::real_normed_field"
using that
by (auto simp: smooth_on_def intro!: higher_differentiable_on_inverse)
lemma smooth_on_norm: "k-smooth_on S (λx. norm (f x))"
if "k-smooth_on S f" "0 ∉ f ` S" "open S"
for f::"_ ⇒_::real_inner"
using that
by (auto simp: smooth_on_def intro!: higher_differentiable_on_norm)
lemma smooth_on_sqrt: "k-smooth_on S (λx. sqrt (f x))"
if "k-smooth_on S f" "0 ∉ f ` S" "open S"
using that
by (auto simp: smooth_on_def intro!: higher_differentiable_on_sqrt)
lemma smooth_on_frechet_derivative:
"∞-smooth_on UNIV (λx. frechet_derivative f (at x) v)"
if "∞-smooth_on UNIV f"
using that
apply (auto simp: smooth_on_def)
apply (rule higher_differentiable_on_frechet_derivativeI)
by auto
lemmas smooth_on_frechet_derivivative_comp = smooth_on_compose2[OF smooth_on_frechet_derivative, unfolded o_def]
lemma smooth_onD: "higher_differentiable_on S f n" if "m-smooth_on S f" "enat n ≤ m"
using that
by (auto simp: smooth_on_def)
lemma (in bounded_linear) higher_differentiable_on: "higher_differentiable_on S f n"
proof (induction n)
case 0
then show ?case
by (auto simp: higher_differentiable_on.simps linear_continuous_on bounded_linear_axioms)
next
case (Suc n)
then show ?case
apply (auto simp: higher_differentiable_on.simps frechet_derivative higher_differentiable_on_const)
using bounded_linear_axioms apply (rule bounded_linear_imp_differentiable)
done
qed
lemma (in bounded_linear) smooth_on: "k-smooth_on S f"
by (auto simp: smooth_on_def higher_differentiable_on)
lemma smooth_on_snd:
"k-smooth_on S (λx. snd (f x))"
if "k-smooth_on S f" "open S"
using higher_differentiable_on_snd_comp that
by (auto simp: smooth_on_def)
lemma smooth_on_fst:
"k-smooth_on S (λx. fst (f x))"
if "k-smooth_on S f" "open S"
using higher_differentiable_on_fst_comp that
by (auto simp: smooth_on_def)
lemma smooth_on_sin: "n-smooth_on S (λx. sin (f x::real))" if "n-smooth_on S f" "open S"
using that
by (auto simp: smooth_on_def intro!: higher_differentiable_on_sin)
lemma smooth_on_cos: "n-smooth_on S (λx. cos (f x::real))" if "n-smooth_on S f" "open S"
using that
by (auto simp: smooth_on_def intro!: higher_differentiable_on_cos)
lemma smooth_on_Taylor2E:
fixes f::"'a::euclidean_space ⇒ real"
assumes hd: "∞-smooth_on UNIV f"
obtains g where "⋀Y.
f Y = f X + frechet_derivative f (at X) (Y - X) + (∑i∈Basis. (∑j∈Basis. ((Y - X) ∙ j) * ((Y - X) ∙ i) * g i j Y))"
"⋀i j. i ∈ Basis ⟹ j ∈ Basis ⟹ ∞-smooth_on UNIV (g i j)"
proof -
define S::"'a set" where "S = UNIV"
have "open S" and "convex S" "X ∈ S" by (auto simp: S_def)
have hd: "∞-smooth_on S f"
using hd by (auto simp: S_def)
define i where "i H x = ((1 - x)) *⇩R nth_derivative 2 f (X + x *⇩R H) H" for x H
define d2 where "d2 v v' = (λx. frechet_derivative (λx. frechet_derivative f (at x) v') (at x) v)" for v v'
define g where "g H x i j = d2 i j (X + x *⇩R H)" for i j x H
define g' where "g' i j H = integral {0 .. 1} (λx. (1 - x) * g H x i j)" for i j H
have "higher_differentiable_on S f 2"
using hd(1) by (auto simp: smooth_on_def dest!: spec[where x=2])
note hd2 = this ‹open S›
have d2_cont: "continuous_on S (d2 i j)" for i j
using hd2(1)
by (auto simp: g_def numeral_2_eq_2 higher_differentiable_on.simps d2_def)
note [continuous_intros] = continuous_on_compose2[OF d2_cont]
have hdiff2: "∞-smooth_on S (d2 v v')" for v v'
apply (auto simp: d2_def)
apply (rule smooth_on_frechet_derivivative_comp)
apply (rule smooth_on_frechet_derivivative_comp)
by (auto simp: S_def assms)
{
fix Y
assume "Y ∈ S"
define H where "H = Y - X"
from ‹Y ∈ S› have "X + H ∈ S" by (simp add: H_def)
with ‹X ∈ S› have cs: "closed_segment X (X + H) ⊆ S"
using ‹convex S›
by (rule closed_segment_subset)
have i: "(i H has_integral f (X + H) - (f X + nth_derivative 1 f X H)) {0..1}"
"f (X + H) = f X + nth_derivative 1 f X H + integral {0..1} (i H)"
"i H integrable_on {0..1}"
unfolding i_def
using higher_differentiable_Taylor1[OF hd2 cs]
by auto
note i(2)
also
have integrable: "(λx. ∑n∈Basis. (1 - x) * (g H x a n * (H ∙ n) * (H ∙ a))) integrable_on {0..1}"
"(λx. (1 - x) * (g H x n a * (H ∙ a) * (H ∙ n))) integrable_on {0..1}"
for a n
by (auto intro!: integrable_continuous_interval continuous_intros closed_segment_subsetD
cs simp: g_def)
have i_eq: "i H x = (1 - x) *⇩R (∑i∈Basis. (∑j∈Basis. g H x i j * (H ∙ j)) * (H ∙ i))"
if "0 ≤ x" "x ≤ 1"
for x
unfolding i_def
apply (subst second_derivative_componentwise[OF hd2])
apply (rule closed_segment_subsetD, rule cs, rule that, rule that)
by (simp add: g_def d2_def)
have "integral {0 .. 1} (i H) = integral {0..1} (λx. (1 - x) * (∑i∈Basis. (∑j∈Basis. g H x i j * (H ∙ j)) * (H ∙ i)))"
apply (subst integral_spike[OF negligible_empty])
apply (rule sym)
apply (rule i_eq)
by (auto simp: that)
also
have "… = (∑i∈Basis. (∑j∈Basis. (H ∙ j) * (H ∙ i) * g' i j H))"
apply (simp add: sum_distrib_left sum_distrib_right integral_sum integrable g'_def)
apply (simp add: integral_mult_right[symmetric] del: integral_mult_right)
by (simp only: ac_simps)
finally have "f (X + H) = f X + nth_derivative 1 f X H + (∑i∈Basis. ∑j∈Basis. H ∙ j * (H ∙ i) * g' i j H)" .
} note * = this
have "f Y = f X + frechet_derivative f (at X) (Y - X) + (∑i∈Basis. ∑j∈Basis. (Y - X) ∙ j * ((Y - X) ∙ i) * g' i j (Y - X))"
for Y
using *[of Y]
by (auto simp: S_def)
moreover
define T::"real set" where "T = {- 1<..<2}"
have "open T"
by (auto simp: T_def)
have "{0 .. 1} ⊆ T"
by (auto simp: T_def)
have T_small: "a ∈ S ⟹ b ∈ T ⟹ X + b *⇩R (a - X) ∈ S" for a b
by (auto simp: S_def)
have "open (S × T)"
by (auto intro: open_Times ‹open S› ‹open T›)
have "smooth_on S (λY. g' i j (Y - X))" if i: "i ∈ Basis" and j: "j ∈ Basis" for i j
unfolding smooth_on_def
apply safe
apply (simp add: g'_def)
apply (rule leibniz_rule'_higher_interval)
apply fact
apply fact
apply (rule higher_differentiable_on_subset[where T="S × T"])
apply (auto intro!: higher_differentiable_on_mult simp: split_beta')
apply (subst diff_conv_add_uminus)
apply (rule higher_differentiable_on_add)
apply (rule higher_differentiable_on_const)
apply (subst scaleR_minus1_left[symmetric])
apply (rule higher_differentiable_on_scaleR)
apply (rule higher_differentiable_on_const)
apply (rule higher_differentiable_on_snd_comp)
apply (rule higher_differentiable_on_id)
apply fact apply fact apply fact
apply (auto simp: g_def)
apply (rule smooth_onD)
apply (rule smooth_on_compose2[OF hdiff2, unfolded o_def])
using ‹open S› ‹open T›
using T_small ‹_ ⊆ T›
by (auto intro!: open_Times smooth_on_add smooth_on_scaleR smooth_on_snd
smooth_on_minus smooth_on_fst)
ultimately show ?thesis unfolding S_def ..
qed
lemma smooth_on_Pair:
"k-smooth_on S (λx. (f x, g x))"
if "open S" "k-smooth_on S f" "k-smooth_on S g"
proof (auto simp: smooth_on_def)
fix n assume n: "enat n ≤ k"
have 1: "higher_differentiable_on S f n"
using that(2) n unfolding smooth_on_def by auto
have 2: "higher_differentiable_on S g n"
using that(3) n unfolding smooth_on_def by auto
show "higher_differentiable_on S (λx. (f x, g x)) n"
by (rule higher_differentiable_on_Pair [OF that(1) 1 2])
qed
lemma smooth_on_Pair':
"k-smooth_on (S × T) (λx. (f (fst x), g (snd x)))"
if "open S" "open T" "k-smooth_on S f" "k-smooth_on T g"
for f::"_::euclidean_space⇒_" and g::"_::euclidean_space⇒_"
proof (auto simp: smooth_on_def)
fix n assume n: "enat n ≤ k"
have 1: "higher_differentiable_on S f n"
using that(3) n unfolding smooth_on_def by auto
have 2: "higher_differentiable_on T g n"
using that(4) n unfolding smooth_on_def by auto
show "higher_differentiable_on (S × T) (λx. (f (fst x), g (snd x))) n"
by (rule higher_differentiable_on_Pair'[OF that(1,2) 1 2])
qed
subsection ‹Diffeomorphism›
definition "diffeomorphism k S T p p' ⟷
k-smooth_on S p ∧ k-smooth_on T p' ∧ homeomorphism S T p p'"
lemma diffeomorphism_imp_homeomorphism:
assumes "diffeomorphism k s t p p'"
shows "homeomorphism s t p p'"
using assms
by (auto simp: diffeomorphism_def)
lemma diffeomorphismD:
assumes "diffeomorphism k S T f g"
shows diffeomorphism_smoothD: "k-smooth_on S f" "k-smooth_on T g"
and diffeomorphism_inverseD: "⋀x. x ∈ S ⟹ g (f x) = x" "⋀y. y ∈ T ⟹ f (g y) = y"
and diffeomorphism_image_eq: "(f ` S = T)" "(g ` T = S)"
using assms by (auto simp: diffeomorphism_def homeomorphism_def)
lemma diffeomorphism_compose:
"diffeomorphism n S T f g ⟹ diffeomorphism n T U h k ⟹ open S ⟹ open T ⟹ open U ⟹
diffeomorphism n S U (h ∘ f) (g ∘ k)"
for f::"_⇒_::euclidean_space"
by (auto simp: diffeomorphism_def intro!: smooth_on_compose homeomorphism_compose)
(auto simp: homeomorphism_def)
lemma diffeomorphism_add: "diffeomorphism k UNIV UNIV (λx. x + c) (λx. x - c)"
by (auto simp: diffeomorphism_def homeomorphism_add intro!: smooth_on_minus smooth_on_add)
lemma diffeomorphism_scaleR: "diffeomorphism k UNIV UNIV (λx. c *⇩R x) (λx. x /⇩R c)"
if "c ≠ 0"
by (auto simp: that diffeomorphism_def homeomorphism_scaleR
intro!: smooth_on_minus smooth_on_scaleR)
end
Theory Bump_Function
section ‹Bump Functions›
theory Bump_Function
imports Smooth
"HOL-Analysis.Weierstrass_Theorems"
begin
subsection ‹Construction›
context begin
qualified definition f :: "real ⇒ real" where
"f t = (if t > 0 then exp(-inverse t) else 0)"
lemma f_nonpos[simp]: "x ≤ 0 ⟹ f x = 0"
by (auto simp: f_def)
lemma exp_inv_limit_0_right:
"((λ(t::real). exp(-inverse t)) ⤏ 0) (at_right 0)"
apply (rule filterlim_compose[where g = exp])
apply (rule exp_at_bot)
apply (rule filterlim_compose[where g = uminus])
apply (rule filterlim_uminus_at_bot_at_top)
by (rule filterlim_inverse_at_top_right)
lemma "∀⇩F t in at_right 0. ((λx. inverse (x ^ Suc k)) has_real_derivative
- (inverse (t ^ Suc k) * ((1 + real k) * t ^ k) * inverse (t ^ Suc k))) (at t)"
unfolding eventually_at_filter
by (auto simp del: power_Suc intro!: derivative_eq_intros eventuallyI)
lemma exp_inv_limit_0_right_gen':
"((λ(t::real). inverse (t ^ k) / exp(inverse t)) ⤏ 0) (at_right 0)"
proof (induct k)
case 0
then show ?case
using exp_inv_limit_0_right
by (auto simp: exp_minus inverse_eq_divide)
next
case (Suc k)
have df: "∀⇩F t in at_right 0. ((λx. inverse (x ^ Suc k)) has_real_derivative
- (inverse (t ^ k) * ((1 + real k)) * (inverse t ^ 2))) (at t)"
unfolding eventually_at_filter
apply (auto simp del: power_Suc intro!: derivative_eq_intros eventuallyI)
by (auto simp: power2_eq_square)
have dg: "∀⇩F t in at_right 0. ((λx. exp (inverse x)) has_real_derivative
- (exp (inverse t) * (inverse t ^ 2))) (at t)"
unfolding eventually_at_filter
by (auto simp del: power_Suc intro!: derivative_eq_intros eventuallyI simp: power2_eq_square)
show ?case
apply (rule lhopital_right_0_at_top [OF _ _ df dg])
apply (rule filterlim_compose[where g = exp])
apply (rule exp_at_top)
apply (rule filterlim_inverse_at_top_right)
subgoal by (auto simp: eventually_at_filter)
subgoal
apply (rule Lim_transform_eventually[where f = "λx. (1 + real k) * (inverse (x ^ k) / exp (inverse x))"])
using Suc.hyps tendsto_mult_right_zero apply blast
by (auto simp: eventually_at_filter)
done
qed
lemma exp_inv_limit_0_right_gen:
"((λ(t::real). exp(-inverse t) / t ^ k) ⤏ 0) (at_right 0)"
using exp_inv_limit_0_right_gen'[of k]
by (metis (no_types, lifting) Groups.mult_ac(2) Lim_cong_within divide_inverse exp_minus)
lemma f_limit_0_right: "(f ⤏ 0) (at_right 0)"
proof -
have "∀⇩F t in at_right 0. (t::real) > 0"
by (rule eventually_at_right_less)
then have "∀⇩F t in at_right 0. exp(-inverse t) = f t"
by (eventually_elim) (auto simp: f_def)
moreover have "((λ(t::real). exp(-inverse t)) ⤏ 0) (at_right 0)"
by (rule exp_inv_limit_0_right)
ultimately show ?thesis
by (blast intro: Lim_transform_eventually)
qed
lemma f_limit_0: "(f ⤏ 0) (at 0)"
using _ f_limit_0_right
proof (rule filterlim_split_at_real)
have "∀⇩F t in at_left 0. 0 = f t"
by (auto simp: f_def eventually_at_filter)
then show "(f ⤏ 0) (at_left 0)"
by (blast intro: Lim_transform_eventually)
qed
lemma f_tendsto: "(f ⤏ f x) (at x)"
proof -
consider "x = 0" | "x < 0" | "x > 0" by arith
then show ?thesis
proof cases
case 1
then show ?thesis by (auto simp: f_limit_0 f_def)
next
case 2
have "∀⇩F t in at x. t < 0"
apply (rule order_tendstoD)
by (rule tendsto_intros) fact
then have "∀⇩F t in at x. 0 = f t"
by (eventually_elim) (auto simp: f_def)
then show ?thesis
using ‹x < 0› by (auto simp: f_def intro: Lim_transform_eventually)
next
case 3
have "∀⇩F t in at x. t > 0"
apply (rule order_tendstoD)
by (rule tendsto_intros) fact
then have "∀⇩F t in at x. exp(-inverse t) = f t"
by (eventually_elim) (auto simp: f_def)
moreover have "(λt. exp (- inverse t)) ─x→ f x"
using ‹x > 0› by (auto simp: f_def tendsto_intros )
ultimately show ?thesis
by (blast intro: Lim_transform_eventually)
qed
qed
lemma f_continuous: "continuous_on S f"
using f_tendsto continuous_on continuous_on_subset subset_UNIV by metis
lemma continuous_on_real_polynomial_function:
"continuous_on S p" if "real_polynomial_function p"
using that
by induction (auto intro: continuous_intros linear_continuous_on)
lemma f_nth_derivative_is_poly:
"higher_differentiable_on {0<..} f k ∧
(∃p. real_polynomial_function p ∧ (∀t>0. nth_derivative k f t 1 = p t / (t ^ (2 * k)) * exp(-inverse t)))"
proof (induction k)
case 0
then show ?case
apply (auto simp: higher_differentiable_on.simps f_continuous)
by (auto simp: f_def)
next
case (Suc k)
obtain p where fk: "higher_differentiable_on {0<..} f k"
and p1: "real_polynomial_function p"
and p2: "∀t>0. nth_derivative k f t 1 = p t / t ^ (2 * k) * exp (- inverse t)"
using Suc by auto
obtain p' where p'1: "real_polynomial_function p'"
and p'2: "∀t. (p has_real_derivative (p' t)) (at t)"
using has_real_derivative_polynomial_function[of p] p1 by auto
define rp where "rp t = (t⇧2 * p' t - 2 * real k * t * p t + p t)" for t
have rp: "real_polynomial_function rp"
unfolding rp_def
by (auto intro!: real_polynomial_function.intros(2-) real_polynomial_function_diff
p1 p'1 simp: power2_eq_square)
moreover
have fk': "(λx. nth_derivative k f x 1) differentiable at t" (is ?a)
"frechet_derivative (λx. nth_derivative k f x 1) (at t) 1 =
rp t * (exp (-inverse t) / t^(2*k+2))" (is ?b)
if "0 < t" for t
proof -
from p'2 that have dp: "(p has_derivative ((*) (p' t))) (at t within {0<..})"
by (auto simp: at_within_open[of _ "{0<..}"] has_field_derivative_def ac_simps)
have "((λt. p t / t ^ (2 * k) * exp (- inverse t)) has_derivative
(λv. v * rp t * (exp (-inverse t) / t^(2*k+2)))) (at t within {0<..})"
using that
apply (auto intro!: derivative_eq_intros dp ext)
apply (simp add: divide_simps algebra_simps rp_def power2_eq_square)
by (metis Suc_pred mult_is_0 neq0_conv power_Suc zero_neq_numeral)
then have "((λx. nth_derivative k f x 1) has_derivative
(λv. v * rp t * (exp (-inverse t) / t^(2*k+2)))) (at t within {0<..})"
apply (rule has_derivative_transform_within[OF _ zero_less_one])
using that p2 by (auto simp: )
then have "((λx. nth_derivative k f x 1) has_derivative
(λv. v * rp t * (exp (-inverse t) / t^(2*k+2)))) (at t)"
using that
by (auto simp: at_within_open[of _ "{0<..}"])
from frechet_derivative_at'[OF this] this
show ?a ?b
by (auto simp: differentiable_def)
qed
have hdS: "higher_differentiable_on {0<..} f (Suc k)"
apply (subst higher_differentiable_on_real_Suc')
apply (auto simp: fk fk' frechet_derivative_nth_derivative_commute[symmetric])
apply (subst continuous_on_cong[OF refl])
apply (rule fk')
by (auto intro!: continuous_intros p'1 p1 rp
intro: continuous_on_real_polynomial_function)
moreover
have "nth_derivative (Suc k) f t 1 = rp t / t ^ (2 * (Suc k)) * exp (- inverse t)"
if "t > 0" for t
proof -
have "nth_derivative (Suc k) f t 1 = frechet_derivative (λx. nth_derivative k f x 1) (at t) 1"
by (simp add: frechet_derivative_nth_derivative_commute)
also have "… = rp t / t^(2*k+2) * (exp (-inverse t))"
using fk'[OF ‹t > 0›] by simp
finally show ?thesis by simp
qed
ultimately show ?case by blast
qed
lemma f_has_derivative_at_neg:
" x < 0 ⟹ (f has_derivative (λx. 0)) (at x)"
by (rule has_derivative_transform_within_open[where f="λx. 0" and s="{..<0}"])
(auto simp: f_def)
lemma f_differentiable_at_neg:
"x < 0 ⟹ f differentiable at x"
using f_has_derivative_at_neg
by (auto simp: differentiable_def)
lemma frechet_derivative_f_at_neg:
"x ∈ {..<0} ⟹ frechet_derivative f (at x) = (λx. 0)"
by (rule frechet_derivative_at') (rule f_has_derivative_at_neg, simp)
lemma f_nth_derivative_lt_0:
"higher_differentiable_on {..<0} f k ∧ (∀t<0. nth_derivative k f t 1 = 0)"
proof (induction k)
case 0
have rewr: "a ∈ {..<0} ⟹ ¬0 < a" for a::real by simp
show ?case
by (auto simp: higher_differentiable_on.simps f_def rewr
simp del: lessThan_iff
cong: continuous_on_cong)
next
case (Suc k)
have "t < 0 ⟹ (λx. nth_derivative k f x 1) differentiable at t" for t
by (rule differentiable_eqI[where g=0 and X="{..<0}"])
(auto simp: zero_fun_def frechet_derivative_const Suc.IH)
then have "frechet_derivative (λx. nth_derivative k f x 1) (at t) 1 = 0" if "t < 0" for t
using that Suc.IH
by (subst frechet_derivative_transform_within_open[where X="{..<0}" and g =0])
(auto simp: frechet_derivative_zero_fun)
with Suc show ?case
by (auto simp: higher_differentiable_on.simps f_differentiable_at_neg
frechet_derivative_f_at_neg zero_fun_def
simp flip: frechet_derivative_nth_derivative_commute
simp del: lessThan_iff
intro!: higher_differentiable_on_const
cong: higher_differentiable_on_cong)
qed
lemma netlimit_at_left: "netlimit (at_left x) = x" for x::real
by (rule Lim_ident_at) simp
lemma netlimit_at_right: "netlimit (at_right x) = x" for x::real
by (rule Lim_ident_at) simp
lemma has_derivative_split_at:
"(g has_derivative g') (at x)"
if
"(g has_derivative g') (at_left x)"
"(g has_derivative g') (at_right x)"
for x::real
using that
unfolding has_derivative_def netlimit_at netlimit_at_right netlimit_at_left
by (auto intro: filterlim_split_at)
lemma has_derivative_at_left_at_right':
"(g has_derivative g') (at x)"
if
"(g has_derivative g') (at x within {..x})"
"(g has_derivative g') (at x within {x..})"
for x::real
apply (rule has_derivative_split_at)
subgoal by (rule has_derivative_subset) (fact, auto)
subgoal by (rule has_derivative_subset) (fact, auto)
done
lemma real_polynomial_function_tendsto:
"(p ⤏ p x) (at x within X)" if "real_polynomial_function p"
using that
by (induction p) (auto intro!: tendsto_eq_intros intro: bounded_linear.tendsto)
lemma f_nth_derivative_cases:
"higher_differentiable_on UNIV f k ∧
(∀t≤0. nth_derivative k f t 1 = 0) ∧
(∃p. real_polynomial_function p ∧
(∀t>0. nth_derivative k f t 1 = p t / (t ^ (2 * k)) * exp(-inverse t)))"
proof (induction k)
case 0
then show ?case
apply (auto simp: higher_differentiable_on.simps f_continuous)
by (auto simp: f_def)
next
case (Suc k)
from Suc.IH obtain pk where IH:
"higher_differentiable_on UNIV f k"
"⋀t. t ≤ 0 ⟹ nth_derivative k f t 1 = 0"
"real_polynomial_function pk"
"⋀t. t > 0 ⟹ nth_derivative k f t 1 = pk t / t ^ (2 * k) * exp (- inverse t)"
by auto
from f_nth_derivative_lt_0[of "Suc k"]
local.f_nth_derivative_is_poly[of "Suc k"]
obtain p where neg: "higher_differentiable_on {..<0} f (Suc k)"
and neg0: "(∀t<0. nth_derivative (Suc k) f t 1 = 0)"
and pos: "higher_differentiable_on {0<..} f (Suc k)"
and p: "real_polynomial_function p"
"⋀t. t > 0 ⟹ nth_derivative (Suc k) f t 1 = p t / t ^ (2 * Suc k) * exp (- inverse t)"
by auto
moreover
have at_within_eq_at_right: "(at 0 within {0..}) = at_right (0::real)"
apply (auto simp: filter_eq_iff eventually_at_filter )
apply (simp add: eventually_mono)
apply (simp add: eventually_mono)
done
have [simp]: "{0..} - {0} = {0::real<..}" by auto
have [simp]: "(at (0::real) within {0..}) ≠ bot"
by (auto simp: at_within_eq_bot_iff)
have k_th_has_derivative_at_left:
"((λx. nth_derivative k f x 1) has_derivative (λx. 0)) (at 0 within {..0})"
apply (rule has_derivative_transform_within[OF _ zero_less_one])
prefer 2
apply force
prefer 2
apply (simp add: IH)
by (rule derivative_intros)
have k_th_has_derivative_at_right:
"((λx. nth_derivative k f x 1) has_derivative (λx. 0)) (at 0 within {0..})"
apply (rule has_derivative_transform_within[where
f="λx'. if x' = 0 then 0 else pk x' / x' ^ (2 * k) * exp (- inverse x')", OF _ zero_less_one])
subgoal
unfolding has_derivative_def
apply (auto simp: Lim_ident_at)
apply (rule Lim_transform_eventually[where f="λx. (pk x * (exp (- inverse x) / x ^ (2 * k + 1)))"])
apply (rule tendsto_eq_intros)
apply (rule real_polynomial_function_tendsto[THEN tendsto_eq_rhs])
apply fact
apply (rule refl)
apply (subst at_within_eq_at_right)
apply (rule exp_inv_limit_0_right_gen)
apply (auto simp add: eventually_at_filter divide_simps)
done
subgoal by force
subgoal by (auto simp: IH(2) IH(4))
done
have k_th_has_derivative: "((λx. nth_derivative k f x 1) has_derivative (λx. 0)) (at 0)"
apply (rule has_derivative_at_left_at_right')
apply (rule k_th_has_derivative_at_left)
apply (rule k_th_has_derivative_at_right)
done
have nth_Suc_zero: "nth_derivative (Suc k) f 0 1 = 0"
apply (auto simp: frechet_derivative_nth_derivative_commute[symmetric])
apply (subst frechet_derivative_at')
apply (rule k_th_has_derivative)
by simp
moreover have "higher_differentiable_on UNIV f (Suc k)"
proof -
have "continuous_on UNIV (λx. nth_derivative (Suc k) f x 1)"
unfolding continuous_on_eq_continuous_within
proof
fix x::real
consider "x < 0" | "x > 0" | "x = 0" by arith
then show "isCont (λx. nth_derivative (Suc k) f x 1) x"
proof cases
case 1
then have at_eq: "at x = at x within {..<0}"
using at_within_open[of x "{..<0}"] by auto
show ?thesis
unfolding at_eq
apply (rule continuous_transform_within[OF _ zero_less_one])
using neg0 1 by (auto simp: at_eq)
next
case 2
then have at_eq: "at x = at x within {0<..}"
using at_within_open[of x "{0<..}"] by auto
show ?thesis
unfolding at_eq
apply (rule continuous_transform_within[OF _ zero_less_one])
using p 2 by (auto intro!: continuous_intros
intro: continuous_real_polymonial_function continuous_at_imp_continuous_within)
next
case 3
have "((λx. nth_derivative (Suc k) f x 1) ⤏ 0) (at_left 0)"
proof -
have "∀⇩F x in at_left 0. 0 = nth_derivative (Suc k) f x 1"
using neg0
by (auto simp: eventually_at_filter)
then show ?thesis
by (blast intro: Lim_transform_eventually)
qed
moreover have "((λx. nth_derivative (Suc k) f x 1) ⤏ 0) (at_right 0)"
proof -
have "((λx. p x * (exp (- inverse x) / x ^ (2 * Suc k))) ⤏ 0) (at_right 0)"
apply (rule tendsto_eq_intros)
apply (rule real_polynomial_function_tendsto)
apply fact
apply (rule exp_inv_limit_0_right_gen)
by simp
moreover
have "∀⇩F x in at_right 0. p x * (exp (- inverse x) / x ^ (2 * Suc k)) =
nth_derivative (Suc k) f x 1"
using p
by (auto simp: eventually_at_filter)
ultimately show ?thesis
by (rule Lim_transform_eventually)
qed
ultimately show ?thesis
by (auto simp: continuous_def nth_Suc_zero 3 filterlim_split_at
simp del: nth_derivative.simps)
qed
qed
moreover have "(λx. nth_derivative k f x 1) differentiable at x" for x
proof -
consider "x = 0" | "x < 0" | "x > 0"by arith
then show ?thesis
proof cases
case 1
then show ?thesis
using k_th_has_derivative by (auto simp: differentiable_def)
next
case 2
with neg show ?thesis
by (subst (asm) higher_differentiable_on_real_Suc') (auto simp: )
next
case 3
with pos show ?thesis
by (subst (asm) higher_differentiable_on_real_Suc') (auto simp: )
qed
qed
moreover have "higher_differentiable_on UNIV f k" by fact
ultimately
show ?thesis
by (subst higher_differentiable_on_real_Suc'[OF open_UNIV]) auto
qed
ultimately
show ?case
by (auto simp: less_eq_real_def)
qed
lemma f_smooth_on: "k-smooth_on S f"
and f_higher_differentiable_on: "higher_differentiable_on S f n"
using f_nth_derivative_cases
by (auto simp: smooth_on_def higher_differentiable_on_subset[OF _ subset_UNIV])
lemma f_compose_smooth_on: "k-smooth_on S (λx. f (g x))"
if "k-smooth_on S g" "open S"
using smooth_on_compose[OF f_smooth_on that open_UNIV subset_UNIV]
by (auto simp: o_def)
lemma f_nonneg: "f x ≥ 0"
by (auto simp: f_def)
lemma f_pos_iff: "f x > 0 ⟷ x > 0"
by (auto simp: f_def)
lemma f_eq_zero_iff: "f x = 0 ⟷ x ≤ 0"
by (auto simp: f_def)
subsection ‹Cutoff function›
definition "h t = f (2 - t) / (f (2 - t) + f (t - 1))"
lemma denominator_pos: "f (2 - t) + f (t - 1) > 0"
by (auto simp: f_def add_pos_pos)
lemma denominator_nonzero: "f (2 - t) + f (t - 1) = 0 ⟷ False"
using denominator_pos[of t] by auto
lemma h_range: "0 ≤ h t" "h t ≤ 1"
by (auto simp: h_def f_nonneg denominator_pos)
lemma h_pos: "t < 2 ⟹ 0 < h t"
and h_less_one: "1 < t ⟹ h t < 1"
by (auto simp: h_def f_pos_iff denominator_pos)
lemma h_eq_0: "h t = 0" if "t ≥ 2"
using that
by (auto simp: h_def)
lemma h_eq_1: "h t = 1" if "t ≤ 1"
using that
by (auto simp: h_def f_eq_zero_iff)
lemma h_compose_smooth_on: "k-smooth_on S (λx. h (g x))"
if "k-smooth_on S g" "open S"
by (auto simp: h_def[abs_def] denominator_nonzero
intro!: smooth_on_divide f_compose_smooth_on smooth_on_minus smooth_on_add
that)
subsection ‹Bump function›
definition H::"_::real_inner ⇒ real" where "H x = h (norm x)"
lemma H_range: "0 ≤ H x" "H x ≤ 1"
by (auto simp: H_def h_range)
lemma H_eq_one: "H x = 1" if "x ∈ cball 0 1"
using that
by (auto simp: H_def h_eq_1)
lemma H_pos: "H x > 0" if "x ∈ ball 0 2"
using that
by (auto simp: H_def h_pos)
lemma H_eq_zero: "H x = 0" if "x ∉ ball 0 2"
using that
by (auto simp: H_def h_eq_0)
lemma H_neq_zeroD: "H x ≠ 0 ⟹ x ∈ ball 0 2"
using H_eq_zero by blast
lemma H_smooth_on: "k-smooth_on UNIV H"
proof -
have 1: "k-smooth_on (ball 0 1) H"
by (rule smooth_on_cong[where g="λx. 1"]) (auto simp: H_eq_one)
have 2: "k-smooth_on (UNIV - cball 0 (1/2)) H"
by (auto simp: H_def[abs_def]
intro!: h_compose_smooth_on smooth_on_norm)
have O: "open (ball 0 1)" "open (UNIV - cball 0 (1 / 2))"
by auto
have *: "ball 0 1 ∪ (UNIV - cball 0 (1 / 2)) = UNIV" by (auto simp: mem_ball)
from smooth_on_open_Un[OF 1 2 O, unfolded *]
show ?thesis
by (rule smooth_on_subset) auto
qed
lemma H_compose_smooth_on: "k-smooth_on S (λx. H (g x))" if "k-smooth_on S g" "open S"
for g :: "_ ⇒ _::euclidean_space"
using smooth_on_compose[OF H_smooth_on that]
by (auto simp: o_def)
end
end
Theory Chart
section ‹Charts›
theory Chart
imports Analysis_More
begin
subsection ‹Definition›
text ‹A chart on ‹M› is a homeomorphism from an open subset of ‹M› to an open subset
of some Euclidean space ‹E›. Here ‹d› and ‹d'› are open subsets of ‹M› and ‹E›, respectively,
‹f: d → d'› is the mapping, and ‹f': d' → d› is the inverse mapping.›
typedef (overloaded) ('a::topological_space, 'e::euclidean_space) chart =
"{(d::'a set, d'::'e set, f, f').
open d ∧ open d' ∧ homeomorphism d d' f f'}"
by (rule exI[where x="({}, {}, (λx. undefined), (λx. undefined))"]) simp
setup_lifting type_definition_chart
lift_definition apply_chart::"('a::topological_space, 'e::euclidean_space) chart ⇒ 'a ⇒ 'e"
is "λ(d, d', f, f'). f" .
declare [[coercion apply_chart]]
lift_definition inv_chart::"('a::topological_space, 'e::euclidean_space) chart ⇒ 'e ⇒ 'a"
is "λ(d, d', f, f'). f'" .
lift_definition domain::"('a::topological_space, 'e::euclidean_space) chart ⇒ 'a set"
is "λ(d, d', f, f'). d" .
lift_definition codomain::"('a::topological_space, 'e::euclidean_space) chart ⇒ 'e set"
is "λ(d, d', f, f'). d'" .
subsection ‹Properties›
lemma open_domain[intro, simp]: "open (domain c)"
and open_codomain[intro, simp]: "open (codomain c)"
and chart_homeomorphism: "homeomorphism (domain c) (codomain c) c (inv_chart c)"
by (transfer, auto)+
lemma at_within_domain: "at x within domain c = at x" if "x ∈ domain c"
by (rule at_within_open[OF that open_domain])
lemma at_within_codomain: "at x within codomain c = at x" if "x ∈ codomain c"
by (rule at_within_open[OF that open_codomain])
lemma
chart_in_codomain[intro, simp]: "x ∈ domain c ⟹ c x ∈ codomain c"
and inv_chart_inverse[simp]: "x ∈ domain c ⟹ inv_chart c (c x) = x"
and inv_chart_in_domain[intro, simp]:"y ∈ codomain c ⟹ inv_chart c y ∈ domain c"
and chart_inverse_inv_chart[simp]: "y ∈ codomain c ⟹ c (inv_chart c y) = y"
and image_domain_eq: "c ` (domain c) = codomain c"
and inv_image_codomain_eq[simp]: "inv_chart c ` (codomain c) = domain c"
and continuous_on_domain: "continuous_on (domain c) c"
and continuous_on_codomain: "continuous_on (codomain c) (inv_chart c)"
using chart_homeomorphism[of c]
by (auto simp: homeomorphism_def)
lemma chart_eqI: "c = d"
if "domain c = domain d"
"codomain c = codomain d"
"⋀x. c x = d x"
"⋀x. inv_chart c x = inv_chart d x"
using that
by transfer auto
lemmas continuous_on_chart[continuous_intros] =
continuous_on_compose2[OF continuous_on_domain]
continuous_on_compose2[OF continuous_on_codomain]
lemma continuous_apply_chart: "continuous (at x within X) c" if "x ∈ domain c"
apply (rule continuous_at_imp_continuous_within)
using continuous_on_domain[of c] that at_within_domain[OF that]
by (auto simp: continuous_on_eq_continuous_within)
lemma continuous_inv_chart: "continuous (at x within X) (inv_chart c)" if "x ∈ codomain c"
apply (rule continuous_at_imp_continuous_within)
using continuous_on_codomain[of c] that at_within_codomain[OF that]
by (auto simp: continuous_on_eq_continuous_within)
lemmas apply_chart_tendsto[tendsto_intros] = isCont_tendsto_compose[OF continuous_apply_chart, rotated]
lemmas inv_chart_tendsto[tendsto_intros] = isCont_tendsto_compose[OF continuous_inv_chart, rotated]
lemma continuous_within_compose2':
"continuous (at (f x) within t) g ⟹ f ` s ⊆ t ⟹
continuous (at x within s) f ⟹
continuous (at x within s) (λx. g (f x))"
by (simp add: continuous_within_compose2 continuous_within_subset)
lemmas continuous_chart[continuous_intros] =
continuous_within_compose2'[OF continuous_apply_chart]
continuous_within_compose2'[OF continuous_inv_chart]
lemma continuous_on_chart_inv:
assumes "continuous_on s (apply_chart c o f)"
"f ` s ⊆ domain c"
shows "continuous_on s f"
proof -
have "continuous_on s (inv_chart c o apply_chart c o f)"
using assms by (auto intro!: continuous_on_chart(2))
moreover have "⋀x. x ∈ s ⟹ (inv_chart c o apply_chart c o f) x = f x"
using assms by auto
ultimately show ?thesis by auto
qed
lemma continuous_on_chart_inv':
assumes "continuous_on (apply_chart c ` s) (f o inv_chart c)"
"s ⊆ domain c"
shows "continuous_on s f"
proof -
have "continuous_on s (apply_chart c)"
using assms continuous_on_domain continuous_on_subset by blast
then have "continuous_on s (f o inv_chart c o apply_chart c)"
apply (rule continuous_on_compose) using assms by auto
moreover have "(f o inv_chart c o apply_chart c) x = f x" if "x ∈ s" for x
using assms that by auto
ultimately show ?thesis by auto
qed
lemma inj_on_apply_chart: "inj_on (apply_chart f) (domain f)"
by (auto simp: intro!: inj_on_inverseI[where g="inv_chart f"])
lemma apply_chart_Int: "f ` (X ∩ Y) = f ` X ∩ f ` Y" if "X ⊆ domain f" "Y ⊆ domain f"
using inj_on_apply_chart that
by (rule inj_on_image_Int)
lemma chart_image_eq_vimage: "c ` X = inv_chart c -` X ∩ codomain c"
if "X ⊆ domain c"
using that
by force
lemma open_chart_image[simp, intro]: "open (c ` X)"
if "open X" "X ⊆ domain c"
proof -
have "c ` X = inv_chart c -` X ∩ codomain c"
using that(2)
by (rule chart_image_eq_vimage)
also have "open …"
using that
by (metis continuous_on_codomain continuous_on_open_vimage open_codomain)
finally show ?thesis .
qed
lemma open_inv_chart_image[simp, intro]: "open (inv_chart c ` X)"
if "open X" "X ⊆ codomain c"
proof -
have "inv_chart c ` X = c -` X ∩ domain c"
using that(2)
apply (auto simp: )
using image_iff by fastforce
also have "open …"
using that
by (metis continuous_on_domain continuous_on_open_vimage open_domain)
finally show ?thesis .
qed
lemma homeomorphism_UNIV_imp_open_map:
"homeomorphism UNIV UNIV p p' ⟹ open f' ⟹ open (p ` f')"
by (auto dest: homeomorphism_imp_open_map[where U=f'])
subsection ‹Restriction›
lemma homeomorphism_restrict:
"homeomorphism (a ∩ s) (b ∩ f' -` s) f f'" if "homeomorphism a b f f'"
using that
by (fastforce simp: homeomorphism_def intro: continuous_on_subset intro!: imageI)
lift_definition restrict_chart::"'a set ⇒ ('a::t2_space, 'e::euclidean_space) chart ⇒ ('a, 'e) chart"
is "λS. λ(d, d', f, f'). if open S then (d ∩ S, d' ∩ f' -` S, f, f') else ({}, {}, f, f')"
by (auto simp: split: if_splits intro!: open_continuous_vimage' homeomorphism_restrict
intro: homeomorphism_cont2 homeomorphism_cont1 )
lemma restrict_chart_restrict_chart:
"restrict_chart X (restrict_chart Y c) = restrict_chart (X ∩ Y) c"
if "open X" "open Y"
using that
by transfer auto
lemma domain_restrict_chart[simp]: "open S ⟹ domain (restrict_chart S c) = domain c ∩ S"
and domain_restrict_chart_if: "domain (restrict_chart S c) = (if open S then domain c ∩ S else {})"
and codomain_restrict_chart[simp]: "open S ⟹ codomain (restrict_chart S c) = codomain c ∩ inv_chart c -` S"
and codomain_restrict_chart_if: "codomain (restrict_chart S c) = (if open S then codomain c ∩ inv_chart c -` S else {})"
and apply_chart_restrict_chart[simp]: "apply_chart (restrict_chart S c) = apply_chart c"
and inv_chart_restrict_chart[simp]: "inv_chart (restrict_chart S c) = inv_chart c"
by (transfer, auto)+
subsection ‹Composition›
lift_definition compose_chart::"('e⇒'e) ⇒ ('e⇒'e) ⇒
('a::topological_space, 'e::euclidean_space) chart ⇒ ('a, 'e) chart"
is "λp p'. λ(d, d', f, f'). if homeomorphism UNIV UNIV p p' then (d, p ` d', p o f, f' o p')
else ({}, {}, f, f')"
by (auto split: if_splits)
(auto intro: homeomorphism_UNIV_imp_open_map homeomorphism_compose homeomorphism_of_subsets)
lemma compose_chart_apply_chart[simp]: "apply_chart (compose_chart p p' c) = p o apply_chart c"
and compose_chart_inv_chart[simp]: "inv_chart (compose_chart p p' c) = inv_chart c o p'"
and domain_compose_chart[simp]: "domain (compose_chart p p' c) = domain c"
and codomain_compose_chart[simp]: "codomain (compose_chart p p' c) = p ` codomain c"
if "homeomorphism UNIV UNIV p p'"
using that by (transfer, auto)+
end
Theory Topological_Manifold
section ‹Topological Manifolds›
theory Topological_Manifold
imports Chart
begin
text ‹Definition of topological manifolds. Existence of locally finite cover.›
subsection ‹Defintition›
text ‹We define topological manifolds as a second-countable Hausdorff space, where
every point in the carrier set has a neighborhood that is homeomorphic to an open
subset of the Euclidean space. Here topological manifolds are specified by a set
of charts, and the carrier set is simply defined to be the union of the domain of
the charts.›
locale manifold =
fixes charts::"('a::{second_countable_topology, t2_space}, 'e::euclidean_space) chart set"
begin
definition "carrier = (⋃(domain ` charts))"
lemma open_carrier[intro, simp]: "open carrier"
by (auto simp: carrier_def)
lemma carrierE:
assumes "x ∈ carrier"
obtains c where "c ∈ charts" "x ∈ domain c"
using assms by (auto simp: carrier_def)
lemma domain_subset_carrier[simp]: "domain c ⊆ carrier" if "c ∈ charts"
using that
by (auto simp: carrier_def)
lemma in_domain_in_carrier[intro, simp]: "c ∈ charts ⟹ x ∈ domain c ⟹ x ∈ carrier"
by (auto simp: carrier_def)
subsection ‹Existence of locally finite cover›
text ‹Every point has a precompact neighborhood.›
lemma precompact_neighborhoodE:
assumes "x ∈ carrier"
obtains C where "x ∈ C" "open C" "compact (closure C)" "closure C ⊆ carrier"
proof -
from carrierE[OF assms] obtain c where c: "c ∈ charts" "x ∈ domain c" by auto
then have "c x ∈ codomain c" by auto
with open_contains_cball[of "codomain c"]
obtain e where e: "0 < e" "cball (apply_chart c x) e ⊆ codomain c"
by auto
then have e': "ball (apply_chart c x) e ⊆ codomain c"
by (auto simp: mem_ball)
define C where "C = inv_chart c ` ball (c x) e"
have "x ∈ C"
using c ‹e > 0›
unfolding C_def
by (auto intro!: image_eqI[where x="apply_chart c x"])
moreover have "open C"
using e'
by (auto simp: C_def)
moreover
have compact: "compact (inv_chart c ` cball (apply_chart c x) e)"
using e
by (intro compact_continuous_image continuous_on_chart) auto
have closure_subset: "closure C ⊆ inv_chart c ` cball (apply_chart c x) e"
apply (rule closure_minimal)
subgoal by (auto simp: C_def mem_ball)
subgoal by (rule compact_imp_closed) (rule compact)
done
have "compact (closure C)"
apply (rule compact_if_closed_subset_of_compact[where T="inv_chart c ` cball (c x) e"])
subgoal by simp
subgoal by (rule compact)
subgoal by (rule closure_subset)
done
moreover have "closure C ⊆ carrier"
using closure_subset c e
by force
ultimately show ?thesis ..
qed
text ‹There exists a covering of the carrier by precompact sets.›
lemma precompact_open_coverE:
obtains U::"nat⇒'a set"
where "(⋃i. U i) = carrier" "⋀i. open (U i)" "⋀i. compact (closure (U i))"
"⋀i. closure (U i) ⊆ carrier"
proof cases
assume "carrier = {}"
then have "(⋃i. {}) = carrier" "open {}" "compact (closure {})" "closure {} ⊆ carrier"
by auto
then show ?thesis ..
next
assume "carrier ≠ {}"
have "∃b. x ∈ b ∧ open b ∧ compact (closure b) ∧ closure b ⊆ carrier" if "x ∈ carrier" for x
using that
by (rule precompact_neighborhoodE) auto
then obtain balls where balls:
"⋀x. x ∈ carrier ⟹ x ∈ balls x"
"⋀x. x ∈ carrier ⟹ open (balls x)"
"⋀x. x ∈ carrier ⟹ compact (closure (balls x))"
"⋀x. x ∈ carrier ⟹ closure (balls x) ⊆ carrier"
by metis
let ?balls = "balls ` carrier"
have *: "⋀x::'a set. x ∈ ?balls ⟹ open x" by (auto simp: balls)
from Lindelof[of "?balls", OF this]
obtain