CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download

Try doing some basic maths questions in the Lean Theorem Prover. Functions, real numbers, equivalence relations and groups. Click on README.md and then on "Open in CoCalc with one click".

Project: Xena
Views: 18536
License: APACHE
/-
Copyright (c) 2019 SΓ©bastien GouΓ«zel. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: SΓ©bastien GouΓ«zel
-/

import analysis.normed_space.operator_norm linear_algebra.finite_dimensional tactic.omega

/-!
# Finite dimensional normed spaces over complete fields

Over a complete nondiscrete field, in finite dimension, all norms are equivalent and all linear maps
are continuous. Moreover, a finite-dimensional subspace is always complete and closed.

## Main results:

* `linear_map.continuous_of_finite_dimensional` : a linear map on a finite-dimensional space over a
  complete field is continuous.
* `finite_dimensional.complete` : a finite-dimensional space over a complete field is complete. This
  is not registered as an instance, as the field would be an unknown metavariable in typeclass
  resolution.
* `submodule.closed_of_finite_dimensional` : a finite-dimensional subspace over a complete field is
  closed
* `finite_dimensional.proper` : a finite-dimensional space over a proper field is proper. This
  is not registered as an instance, as the field would be an unknown metavariable in typeclass
  resolution. It is however registered as an instance for `π•œ = ℝ` and `π•œ = β„‚`. As properness
  implies completeness, there is no need to also register `finite_dimensional.complete` on `ℝ` or
  `β„‚`.

## Implementation notes

The fact that all norms are equivalent is not written explicitly, as it would mean having two norms
on a single space, which is not the way type classes work. However, if one has a
finite-dimensional vector space `E` with a norm, and a copy `E'` of this type with another norm,
then the identities from `E` to `E'` and from `E'`to `E` are continuous thanks to
`linear_map.continuous_of_finite_dimensional`. This gives the desired norm equivalence.
-/

universes u v w x

open set finite_dimensional
open_locale classical

-- To get a reasonable compile time for `continuous_equiv_fun_basis`, typeclass inference needs
-- to be guided.
local attribute [instance, priority 10000] pi.module normed_space.to_module
  submodule.add_comm_group submodule.module
  linear_map.finite_dimensional_range Pi.complete nondiscrete_normed_field.to_normed_field

set_option class.instance_max_depth 100

/-- A linear map on `ΞΉ β†’ π•œ` (where `ΞΉ` is a fintype) is continuous -/
lemma linear_map.continuous_on_pi {ΞΉ : Type w} [fintype ΞΉ] {π•œ : Type u} [normed_field π•œ]
  {E : Type v}  [add_comm_group E] [vector_space π•œ E] [topological_space E]
  [topological_add_group E] [topological_vector_space π•œ E] (f : (ΞΉ β†’ π•œ) β†’β‚—[π•œ] E) : continuous f :=
begin
  -- for the proof, write `f` in the standard basis, and use that each coordinate is a continuous
  -- function.
  have : (f : (ΞΉ β†’ π•œ) β†’ E) =
         (Ξ»x, finset.sum finset.univ (Ξ»i:ΞΉ, x i β€’ (f (Ξ»j, if i = j then 1 else 0)))),
    by { ext x, exact f.pi_apply_eq_sum_univ x },
  rw this,
  refine continuous_finset_sum _ (Ξ»i hi, _),
  exact (continuous_apply i).smul continuous_const
end

section complete_field

variables {π•œ : Type u} [nondiscrete_normed_field π•œ]
{E : Type v} [normed_group E] [normed_space π•œ E]
{F : Type w} [normed_group F] [normed_space π•œ F]
{F' : Type x} [add_comm_group F'] [vector_space π•œ F'] [topological_space F']
[topological_add_group F'] [topological_vector_space π•œ F']
[complete_space π•œ]

set_option class.instance_max_depth 150

/-- In finite dimension over a complete field, the canonical identification (in terms of a basis)
with `π•œ^n` together with its sup norm is continuous. This is the nontrivial part in the fact that
all norms are equivalent in finite dimension.
Do not use this statement as its formulation is awkward (in terms of the dimension `n`, as the proof
is done by induction over `n`) and it is superceded by the fact that every linear map on a
finite-dimensional space is continuous, in `linear_map.continuous_of_finite_dimensional`. -/
lemma continuous_equiv_fun_basis {n : β„•} {ΞΉ : Type v} [fintype ΞΉ] (ΞΎ : ΞΉ β†’ E)
  (hn : fintype.card ΞΉ = n) (hΞΎ : is_basis π•œ ΞΎ) : continuous (equiv_fun_basis hΞΎ) :=
begin
  unfreezeI,
  induction n with n IH generalizing ΞΉ E,
  { apply linear_map.continuous_of_bound _ 0 (Ξ»x, _),
    have : equiv_fun_basis hΞΎ x = 0,
      by { ext i, exact (fintype.card_eq_zero_iff.1 hn i).elim },
    change βˆ₯equiv_fun_basis hΞΎ xβˆ₯ ≀ 0 * βˆ₯xβˆ₯,
    rw this,
    simp [norm_nonneg] },
  { haveI : finite_dimensional π•œ E := of_finite_basis hΞΎ,
    -- first step: thanks to the inductive assumption, any n-dimensional subspace is equivalent
    -- to a standard space of dimension n, hence it is complete and therefore closed.
    have H₁ : βˆ€s : submodule π•œ E, findim π•œ s = n β†’ is_closed (s : set E),
    { assume s s_dim,
      rcases exists_is_basis_finite π•œ s with ⟨b, b_basis, b_finite⟩,
      letI : fintype b := finite.fintype b_finite,
      have U : uniform_embedding (equiv_fun_basis b_basis).symm,
      { have : fintype.card b = n,
          by { rw ← s_dim, exact (findim_eq_card_basis b_basis).symm },
        have : continuous (equiv_fun_basis b_basis) := IH (subtype.val : b β†’ s) this b_basis,
        exact (equiv_fun_basis b_basis).symm.uniform_embedding (linear_map.continuous_on_pi _) this },
      have : is_complete (range ((equiv_fun_basis b_basis).symm)),
      { rw [← image_univ, is_complete_image_iff U],
        convert complete_univ,
        change complete_space (b β†’ π•œ),
        apply_instance },
      have : is_complete (range (subtype.val : s β†’ E)),
      { change is_complete (range ((equiv_fun_basis b_basis).symm.to_equiv)) at this,
        rw equiv.range_eq_univ at this,
        rwa [← image_univ, is_complete_image_iff],
        exact isometry_subtype_val.uniform_embedding },
      apply is_closed_of_is_complete,
      rwa subtype.val_range at this },
    -- second step: any linear form is continuous, as its kernel is closed by the first step
    have Hβ‚‚ : βˆ€f : E β†’β‚—[π•œ] π•œ, continuous f,
    { assume f,
      have : findim π•œ f.ker = n ∨ findim π•œ f.ker = n.succ,
      { have Z := f.findim_range_add_findim_ker,
        rw [findim_eq_card_basis hΞΎ, hn] at Z,
        have : findim π•œ f.range = 0 ∨ findim π•œ f.range = 1,
        { have I : βˆ€(k : β„•), k ≀ 1 ↔ k = 0 ∨ k = 1, by omega manual,
          have : findim π•œ f.range ≀ findim π•œ π•œ := submodule.findim_le _,
          rwa [findim_of_field, I] at this },
        cases this,
        { rw this at Z,
          right,
          simpa using Z },
        { left,
          rw [this, add_comm, nat.add_one] at Z,
          exact nat.succ_inj Z } },
      have : is_closed (f.ker : set E),
      { cases this,
        { exact H₁ _ this },
        { have : f.ker = ⊀,
            by { apply eq_top_of_findim_eq, rw [findim_eq_card_basis hΞΎ, hn, this] },
          simp [this] } },
      exact linear_map.continuous_iff_is_closed_ker.2 this },
    -- third step: applying the continuity to the linear form corresponding to a coefficient in the
    -- basis decomposition, deduce that all such coefficients are controlled in terms of the norm
    have : βˆ€i:ΞΉ, βˆƒC, 0 ≀ C ∧ βˆ€(x:E), βˆ₯equiv_fun_basis hΞΎ x iβˆ₯ ≀ C * βˆ₯xβˆ₯,
    { assume i,
      let f : E β†’β‚—[π•œ] π•œ := (linear_map.proj i).comp (equiv_fun_basis hΞΎ),
      let f' : E β†’L[π•œ] π•œ := { cont := Hβ‚‚ f, ..f },
      exact ⟨βˆ₯f'βˆ₯, norm_nonneg _, Ξ»x, continuous_linear_map.le_op_norm f' x⟩ },
    -- fourth step: combine the bound on each coefficient to get a global bound and the continuity
    choose C0 hC0 using this,
    let C := finset.sum finset.univ C0,
    have C_nonneg : 0 ≀ C := finset.sum_nonneg (Ξ»i hi, (hC0 i).1),
    have C0_le : βˆ€i, C0 i ≀ C :=
      Ξ»i, finset.single_le_sum (Ξ»j hj, (hC0 j).1) (finset.mem_univ _),
    apply linear_map.continuous_of_bound _ C (Ξ»x, _),
    rw pi_norm_le_iff,
    { exact Ξ»i, le_trans ((hC0 i).2 x) (mul_le_mul_of_nonneg_right (C0_le i) (norm_nonneg _)) },
    { exact mul_nonneg C_nonneg (norm_nonneg _) } }
end

/-- Any linear map on a finite dimensional space over a complete field is continuous. -/
theorem linear_map.continuous_of_finite_dimensional [finite_dimensional π•œ E] (f : E β†’β‚—[π•œ] F') :
  continuous f :=
begin
  -- for the proof, go to a model vector space `b β†’ π•œ` thanks to `continuous_equiv_fun_basis`, and
  -- argue that all linear maps there are continuous.
  rcases exists_is_basis_finite π•œ E with ⟨b, b_basis, b_finite⟩,
  letI : fintype b := finite.fintype b_finite,
  have A : continuous (equiv_fun_basis b_basis) :=
    continuous_equiv_fun_basis _ rfl b_basis,
  have B : continuous (f.comp ((equiv_fun_basis b_basis).symm : (b β†’ π•œ) β†’β‚—[π•œ] E)) :=
    linear_map.continuous_on_pi _,
  have : continuous ((f.comp ((equiv_fun_basis b_basis).symm : (b β†’ π•œ) β†’β‚—[π•œ] E))
                      ∘ (equiv_fun_basis b_basis)) := B.comp A,
  convert this,
  ext x,
  simp only [linear_equiv.coe_apply, function.comp_app, coe_fn_coe_base, linear_map.comp_apply],
  rw linear_equiv.symm_apply_apply
end

/-- The continuous linear map induced by a linear map on a finite dimensional space -/
def linear_map.to_continuous_linear_map [finite_dimensional π•œ E] (f : E β†’β‚—[π•œ] F') : E β†’L[π•œ] F' :=
{ cont := f.continuous_of_finite_dimensional, ..f }

/-- The continuous linear equivalence induced by a linear equivalence on a finite dimensional space. -/
def linear_equiv.to_continuous_linear_equiv [finite_dimensional π•œ E] (e : E ≃ₗ[π•œ] F) : E ≃L[π•œ] F :=
{ continuous_to_fun := e.to_linear_map.continuous_of_finite_dimensional,
  continuous_inv_fun := begin
    haveI : finite_dimensional π•œ F := e.finite_dimensional,
    exact e.symm.to_linear_map.continuous_of_finite_dimensional
  end,
  ..e }

/-- Any finite-dimensional vector space over a complete field is complete.
We do not register this as an instance to avoid an instance loop when trying to prove the
completeness of `π•œ`, and the search for `π•œ` as an unknown metavariable. Declare the instance
explicitly when needed. -/
variables (π•œ E)
lemma finite_dimensional.complete [finite_dimensional π•œ E] : complete_space E :=
begin
  rcases exists_is_basis_finite π•œ E with ⟨b, b_basis, b_finite⟩,
  letI : fintype b := finite.fintype b_finite,
  have : uniform_embedding (equiv_fun_basis b_basis).symm :=
    linear_equiv.uniform_embedding _ (linear_map.continuous_of_finite_dimensional _)
    (linear_map.continuous_of_finite_dimensional _),
  have : is_complete ((equiv_fun_basis b_basis).symm.to_equiv '' univ) :=
    (is_complete_image_iff this).mpr complete_univ,
  rw [image_univ, equiv.range_eq_univ] at this,
  exact complete_space_of_is_complete_univ this
end

variables {π•œ E}
/-- A finite-dimensional subspace is complete. -/
lemma submodule.complete_of_finite_dimensional (s : submodule π•œ E) [finite_dimensional π•œ s] :
  is_complete (s : set E) :=
begin
  haveI : complete_space s := finite_dimensional.complete π•œ s,
  have : is_complete (range (subtype.val : s β†’ E)),
  { rw [← image_univ, is_complete_image_iff],
    { exact complete_univ },
    { exact isometry_subtype_val.uniform_embedding } },
  rwa subtype.val_range at this
end

/-- A finite-dimensional subspace is closed. -/
lemma submodule.closed_of_finite_dimensional (s : submodule π•œ E) [finite_dimensional π•œ s] :
  is_closed (s : set E) :=
is_closed_of_is_complete s.complete_of_finite_dimensional

end complete_field

section proper_field
variables (π•œ : Type u) [nondiscrete_normed_field π•œ]
(E : Type v) [normed_group E] [normed_space π•œ E] [proper_space π•œ]

/-- Any finite-dimensional vector space over a proper field is proper.
We do not register this as an instance to avoid an instance loop when trying to prove the
properness of `π•œ`, and the search for `π•œ` as an unknown metavariable. Declare the instance
explicitly when needed. -/
lemma finite_dimensional.proper [finite_dimensional π•œ E] : proper_space E :=
begin
  rcases exists_is_basis_finite π•œ E with ⟨b, b_basis, b_finite⟩,
  letI : fintype b := finite.fintype b_finite,
  let e := equiv_fun_basis b_basis,
  let f : E β†’L[π•œ] (b β†’ π•œ) :=
    { cont := linear_map.continuous_of_finite_dimensional _, ..e.to_linear_map },
  refine metric.proper_image_of_proper e.symm
    (linear_map.continuous_of_finite_dimensional _) _ (βˆ₯fβˆ₯)  (Ξ»x y, _),
  { exact equiv.range_eq_univ e.symm.to_equiv },
  { have A : e (e.symm x) = x := linear_equiv.apply_symm_apply _ _,
    have B : e (e.symm y) = y := linear_equiv.apply_symm_apply _ _,
    conv_lhs { rw [← A, ← B] },
    change dist (f (e.symm x)) (f (e.symm y)) ≀ βˆ₯fβˆ₯ * dist (e.symm x) (e.symm y),
    exact f.lipschitz _ _ }
end

end proper_field

/- Over the real numbers, we can register the previous statement as an instance as it will not
cause problems in instance resolution since the properness of `ℝ` is already known. -/
instance finite_dimensional.proper_real
  (E : Type u) [normed_group E] [normed_space ℝ E] [finite_dimensional ℝ E] : proper_space E :=
finite_dimensional.proper ℝ E

attribute [instance, priority 900] finite_dimensional.proper_real