/- Copyright (c) 2022 Anatole Dedecker. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: SΓ©bastien GouΓ«zel, Anatole Dedecker -/ module public import Mathlib.Analysis.LocallyConvex.BalancedCoreHull public import Mathlib.Analysis.LocallyConvex.Bounded public import Mathlib.Analysis.Normed.Module.Basic public import Mathlib.Analysis.SpecificLimits.Normed public import Mathlib.LinearAlgebra.FiniteDimensional.Lemmas public import Mathlib.RingTheory.LocalRing.Basic public import Mathlib.Topology.Algebra.Module.Determinant public import Mathlib.Topology.Algebra.Module.ModuleTopology public import Mathlib.Topology.Algebra.Module.Simple public import Mathlib.Topology.Algebra.Module.Complement public import Mathlib.Topology.Algebra.SeparationQuotient.FiniteDimensional public import Mathlib.Topology.Maps.Strict.Basic /-! # Finite-dimensional topological vector spaces over complete fields Let `π•œ` be a complete nontrivially normed field, and `E` a topological vector space (TVS) over `π•œ` (i.e we have `[AddCommGroup E] [Module π•œ E] [TopologicalSpace E] [IsTopologicalAddGroup E]` and `[ContinuousSMul π•œ E]`). If `E` is finite dimensional and Hausdorff, then all linear maps from `E` to any other TVS are continuous. When `E` is a normed space, this gets us the equivalence of norms in finite dimension. ## Main results : * `LinearMap.continuous_iff_isClosed_ker` : a linear form is continuous if and only if its kernel is closed. * `LinearMap.continuous_of_finiteDimensional` : a linear map on a finite-dimensional Hausdorff space over a complete field is continuous. ## TODO Generalize more of `Mathlib/Analysis/Normed/Module/FiniteDimension.lean` to general TVSs. ## Implementation detail The main result from which everything follows is the fact that, if `ΞΎ : ΞΉ β†’ E` is a finite basis, then `ΞΎ.equivFun : E β†’β‚— (ΞΉ β†’ π•œ)` is continuous. However, for technical reasons, it is easier to prove this when `ΞΉ` and `E` live in the same universe. So we start by doing that as a private lemma, then we deduce `LinearMap.continuous_of_finiteDimensional` from it, and then the general result follows as `continuous_equivFun_basis`. -/ @[expose] public section open Filter Module Set TopologicalSpace Topology universe u v w x noncomputable section section FiniteDimensional variable {π•œ E F : Type*} [AddCommGroup E] [TopologicalSpace E] [AddCommGroup F] [TopologicalSpace F] [IsTopologicalAddGroup F] /-- The space of continuous linear maps between finite-dimensional spaces is finite-dimensional. -/ instance ContinuousLinearMap.instModuleFinite [CommRing π•œ] [Module π•œ E] [Module.Finite π•œ E] [Module π•œ F] [IsNoetherian π•œ F] [ContinuousConstSMul π•œ F] : Module.Finite π•œ (E β†’L[π•œ] F) := .of_injective (ContinuousLinearMap.coeLM π•œ : (E β†’L[π•œ] F) β†’β‚—[π•œ] E β†’β‚—[π•œ] F) ContinuousLinearMap.coe_injective /-- The space of continuous linear maps between finite-dimensional spaces is finite-dimensional. This theorem is here to match searches looking for `FiniteDimensional` instead of `Module.Finite`. We use a strictly more general `ContinuousLinearMap.instModuleFinite` as an instance. -/ protected theorem ContinuousLinearMap.finiteDimensional [Field π•œ] [Module π•œ E] [FiniteDimensional π•œ E] [Module π•œ F] [FiniteDimensional π•œ F] [ContinuousConstSMul π•œ F] : FiniteDimensional π•œ (E β†’L[π•œ] F) := inferInstance end FiniteDimensional section NormedField variable {π•œ : Type u} [hnorm : NontriviallyNormedField π•œ] {E : Type v} [AddCommGroup E] [Module π•œ E] [TopologicalSpace E] [IsTopologicalAddGroup E] [ContinuousSMul π•œ E] {F : Type w} [AddCommGroup F] [Module π•œ F] [TopologicalSpace F] [IsTopologicalAddGroup F] [ContinuousSMul π•œ F] {F' : Type x} [AddCommGroup F'] [Module π•œ F'] [TopologicalSpace F'] [IsTopologicalAddGroup F'] [ContinuousSMul π•œ F'] /-- If `π•œ` is a nontrivially normed field, any T2 topology on `π•œ` which makes it a topological vector space over itself (with the norm topology) is *equal* to the norm topology. -/ theorem unique_topology_of_t2 {t : TopologicalSpace π•œ} (h₁ : @IsTopologicalAddGroup π•œ t _) (hβ‚‚ : @ContinuousSMul π•œ π•œ _ hnorm.toUniformSpace.toTopologicalSpace t) (h₃ : @T2Space π•œ t) : t = hnorm.toUniformSpace.toTopologicalSpace := by -- Let `𝓣₀` denote the topology on `π•œ` induced by the norm, and `𝓣` be any T2 vector -- topology on `π•œ`. To show that `𝓣₀ = 𝓣`, it suffices to show that they have the same -- neighborhoods of 0. refine IsTopologicalAddGroup.ext h₁ inferInstance (le_antisymm ?_ ?_) Β· -- To show `𝓣 ≀ 𝓣₀`, we have to show that closed balls are `𝓣`-neighborhoods of 0. rw [Metric.nhds_basis_closedBall.ge_iff] -- Let `Ξ΅ > 0`. Since `π•œ` is nontrivially normed, we have `0 < β€–ΞΎβ‚€β€– < Ξ΅` for some `ΞΎβ‚€ : π•œ`. intro Ξ΅ hΞ΅ rcases NormedField.exists_norm_lt π•œ hΞ΅ with βŸ¨ΞΎβ‚€, hΞΎβ‚€, hΞΎβ‚€Ξ΅βŸ© -- Since `ΞΎβ‚€ β‰  0` and `𝓣` is T2, we know that `{ΞΎβ‚€}ᢜ` is a `𝓣`-neighborhood of 0. have : {ΞΎβ‚€}ᢜ ∈ @nhds π•œ t 0 := IsOpen.mem_nhds isOpen_compl_singleton <| mem_compl_singleton_iff.mpr <| Ne.symm <| norm_ne_zero_iff.mp hΞΎβ‚€.ne.symm -- Thus, its balanced core `𝓑` is too. Let's show that the closed ball of radius `Ξ΅` contains -- `𝓑`, which will imply that the closed ball is indeed a `𝓣`-neighborhood of 0. have : balancedCore π•œ {ΞΎβ‚€}ᢜ ∈ @nhds π•œ t 0 := balancedCore_mem_nhds_zero this refine mem_of_superset this fun ΞΎ hΞΎ => ?_ -- Let `ΞΎ ∈ 𝓑`. We want to show `β€–ΞΎβ€– < Ξ΅`. If `ΞΎ = 0`, this is trivial. by_cases hΞΎ0 : ΞΎ = 0 Β· rw [hΞΎ0] exact Metric.mem_closedBall_self hΞ΅.le Β· rw [mem_closedBall_zero_iff] -- Now suppose `ΞΎ β‰  0`. By contradiction, let's assume `Ξ΅ < β€–ΞΎβ€–`, and show that -- `ΞΎβ‚€ ∈ 𝓑 βŠ† {ΞΎβ‚€}ᢜ`, which is a contradiction. by_contra! h suffices (ΞΎβ‚€ * ξ⁻¹) β€’ ΞΎ ∈ balancedCore π•œ {ΞΎβ‚€}ᢜ by rw [smul_eq_mul, mul_assoc, inv_mul_cancelβ‚€ hΞΎ0, mul_one] at this exact notMem_compl_iff.mpr (mem_singleton ΞΎβ‚€) ((balancedCore_subset _) this) -- For that, we use that `𝓑` is balanced : since `β€–ΞΎβ‚€β€– < Ξ΅ < β€–ΞΎβ€–`, we have `β€–ΞΎβ‚€ / ΞΎβ€– ≀ 1`, -- hence `ΞΎβ‚€ = (ΞΎβ‚€ / ΞΎ) β€’ ΞΎ ∈ 𝓑` because `ΞΎ ∈ 𝓑`. refine (balancedCore_balanced _).smul_mem ?_ hΞΎ rw [norm_mul, norm_inv, mul_inv_le_iffβ‚€ (norm_pos_iff.mpr hΞΎ0), one_mul] exact (hΞΎβ‚€Ξ΅.trans h).le Β· -- Finally, to show `𝓣₀ ≀ 𝓣`, we simply argue that `id = (fun x ↦ x β€’ 1)` is continuous from -- `(π•œ, 𝓣₀)` to `(π•œ, 𝓣)` because `(β€’) : (π•œ, 𝓣₀) Γ— (π•œ, 𝓣) β†’ (π•œ, 𝓣)` is continuous. calc @nhds π•œ hnorm.toUniformSpace.toTopologicalSpace 0 = map id (@nhds π•œ hnorm.toUniformSpace.toTopologicalSpace 0) := map_id.symm _ = map (fun x => id x β€’ (1 : π•œ)) (@nhds π•œ hnorm.toUniformSpace.toTopologicalSpace 0) := by simp _ ≀ @nhds π•œ t ((0 : π•œ) β€’ (1 : π•œ)) := (@Tendsto.smul_const _ _ _ hnorm.toUniformSpace.toTopologicalSpace t _ _ _ _ _ tendsto_id (1 : π•œ)) _ = @nhds π•œ t 0 := by rw [zero_smul] /-- Any linear form on a topological vector space over a nontrivially normed field is continuous if its kernel is closed. -/ theorem LinearMap.continuous_of_isClosed_ker (l : E β†’β‚—[π•œ] π•œ) (hl : IsClosed (LinearMap.ker l : Set E)) : Continuous l := by -- `l` is either constant or surjective. If it is constant, the result is trivial. by_cases H : finrank π•œ (LinearMap.range l) = 0 Β· rw [Submodule.finrank_eq_zero, LinearMap.range_eq_bot] at H rw [H] exact continuous_zero Β· -- In the case where `l` is surjective, we factor it as `Ο† : (E β§Έ l.ker) ≃ₗ[π•œ] π•œ`. Note that -- `E β§Έ l.ker` is T2 since `l.ker` is closed. have : finrank π•œ (LinearMap.range l) = 1 := le_antisymm (finrank_self π•œ β–Έ (LinearMap.range l).finrank_le) (zero_lt_iff.mpr H) have hi : Function.Injective ((LinearMap.ker l).liftQ l (le_refl _)) := by rw [← LinearMap.ker_eq_bot] exact Submodule.ker_liftQ_eq_bot _ _ _ (le_refl _) have hs : Function.Surjective ((LinearMap.ker l).liftQ l (le_refl _)) := by rw [← LinearMap.range_eq_top, Submodule.range_liftQ] exact Submodule.eq_top_of_finrank_eq ((finrank_self π•œ).symm β–Έ this) let Ο† : (E β§Έ LinearMap.ker l) ≃ₗ[π•œ] π•œ := LinearEquiv.ofBijective ((LinearMap.ker l).liftQ l (le_refl _)) ⟨hi, hs⟩ have hlΟ† : (l : E β†’ π•œ) = Ο† ∘ (LinearMap.ker l).mkQ := by ext; rfl -- Since the quotient map `E β†’β‚—[π•œ] (E β§Έ l.ker)` is continuous, the continuity of `l` will follow -- form the continuity of `Ο†`. suffices Continuous Ο†.toEquiv by rw [hlΟ†] exact this.comp continuous_quot_mk -- The pullback by `Ο†.symm` of the quotient topology is a T2 topology on `π•œ`, because `Ο†.symm` -- is injective. Since `Ο†.symm` is linear, it is also a vector space topology. -- Hence, we know that it is equal to the topology induced by the norm. have : induced Ο†.toEquiv.symm inferInstance = hnorm.toUniformSpace.toTopologicalSpace := by refine unique_topology_of_t2 (topologicalAddGroup_induced Ο†.symm.toLinearMap) (continuousSMul_induced Ο†.symm.toMulActionHom) ?_ rw [t2Space_iff] exact fun x y hxy => @separated_by_continuous _ _ (induced _ _) _ _ _ continuous_induced_dom _ _ (Ο†.toEquiv.symm.injective.ne hxy) -- Finally, the pullback by `Ο†.symm` is exactly the pushforward by `Ο†`, so we have to prove -- that `Ο†` is continuous when `π•œ` is endowed with the pushforward by `Ο†` of the quotient -- topology, which is trivial by definition of the pushforward. simp_rw +instances [this.symm, Equiv.induced_symm] exact continuous_coinduced_rng /-- Any linear form on a topological vector space over a nontrivially normed field is continuous if and only if its kernel is closed. -/ theorem LinearMap.continuous_iff_isClosed_ker (l : E β†’β‚—[π•œ] π•œ) : Continuous l ↔ IsClosed (LinearMap.ker l : Set E) := ⟨fun h => isClosed_singleton.preimage h, l.continuous_of_isClosed_ker⟩ /-- Over a nontrivially normed field, any linear form which is nonzero on a nonempty open set is automatically continuous. -/ theorem LinearMap.continuous_of_nonzero_on_open (l : E β†’β‚—[π•œ] π•œ) (s : Set E) (hs₁ : IsOpen s) (hsβ‚‚ : s.Nonempty) (hs₃ : βˆ€ x ∈ s, l x β‰  0) : Continuous l := by refine l.continuous_of_isClosed_ker (l.isClosed_or_dense_ker.resolve_right fun hl => ?_) rcases hsβ‚‚ with ⟨x, hx⟩ have : x ∈ interior (LinearMap.ker l : Set E)ᢜ := by rw [mem_interior_iff_mem_nhds] exact mem_of_superset (hs₁.mem_nhds hx) hs₃ rwa [hl.interior_compl] at this variable [CompleteSpace π•œ] /-- This version imposes `ΞΉ` and `E` to live in the same universe, so you should instead use `continuous_equivFun_basis` which gives the same result without universe restrictions. -/ private theorem continuous_equivFun_basis_aux [T2Space E] {ΞΉ : Type v} [Finite ΞΉ] (ΞΎ : Basis ΞΉ π•œ E) : Continuous ΞΎ.equivFun := by have := Fintype.ofFinite ΞΉ letI : UniformSpace E := IsTopologicalAddGroup.rightUniformSpace E letI : IsUniformAddGroup E := isUniformAddGroup_of_addCommGroup suffices βˆ€ n, Fintype.card ΞΉ = n β†’ Continuous ΞΎ.equivFun by exact this _ rfl intro n hn induction n generalizing ΞΉ E with | zero => rw [Fintype.card_eq_zero_iff] at hn exact continuous_of_const fun x y => funext hn.elim | succ n IH => haveI : FiniteDimensional π•œ E := ΞΎ.finiteDimensional_of_finite -- first step: thanks to the induction hypothesis, 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, finrank π•œ s = n β†’ IsClosed (s : Set E) := by intro s s_dim letI : IsUniformAddGroup s := s.toAddSubgroup.isUniformAddGroup let b := Basis.ofVectorSpace π•œ s have U : IsUniformEmbedding b.equivFun.symm.toEquiv := by have : Fintype.card (Basis.ofVectorSpaceIndex π•œ s) = n := by rw [← s_dim] exact (finrank_eq_card_basis b).symm have : Continuous b.equivFun := IH b inferInstance this exact b.equivFun.symm.isUniformEmbedding b.equivFun.symm.toLinearMap.continuous_on_pi this have : IsComplete (s : Set E) := completeSpace_coe_iff_isComplete.1 ((completeSpace_congr U).1 inferInstance) exact this.isClosed -- second step: any linear form is continuous, as its kernel is closed by the first step have Hβ‚‚ : βˆ€ f : E β†’β‚—[π•œ] π•œ, Continuous f := by intro f by_cases H : finrank π•œ (LinearMap.range f) = 0 Β· rw [Submodule.finrank_eq_zero, LinearMap.range_eq_bot] at H rw [H] exact continuous_zero Β· have : finrank π•œ (LinearMap.ker f) = n := by have Z := f.finrank_range_add_finrank_ker rw [finrank_eq_card_basis ΞΎ, hn] at Z have : finrank π•œ (LinearMap.range f) = 1 := le_antisymm (finrank_self π•œ β–Έ (LinearMap.range f).finrank_le) (zero_lt_iff.mpr H) rw [this, add_comm, Nat.add_one] at Z exact Nat.succ.inj Z have : IsClosed (LinearMap.ker f : Set E) := H₁ _ this exact LinearMap.continuous_of_isClosed_ker f this rw [continuous_pi_iff] intro i change Continuous (ΞΎ.coord i) exact Hβ‚‚ (ΞΎ.coord i) /-- A finite-dimensional t2 vector space over a complete field must carry the module topology. Not declared as a global instance only for performance reasons. -/ @[local instance] lemma isModuleTopologyOfFiniteDimensional [T2Space E] [FiniteDimensional π•œ E] : IsModuleTopology π•œ E := -- for the proof, go to a model vector space `b β†’ π•œ` thanks to `continuous_equivFun_basis`, and -- use that it has the module topology let b := Basis.ofVectorSpace π•œ E have continuousEquiv : E ≃L[π•œ] (Basis.ofVectorSpaceIndex π•œ E) β†’ π•œ := { __ := b.equivFun continuous_toFun := continuous_equivFun_basis_aux b continuous_invFun := IsModuleTopology.continuous_of_linearMap (R := π•œ) (A := (Basis.ofVectorSpaceIndex π•œ E) β†’ π•œ) (B := E) b.equivFun.symm } IsModuleTopology.iso continuousEquiv.symm /-- Any linear map on a finite-dimensional space over a complete field is continuous. -/ theorem LinearMap.continuous_of_finiteDimensional [T2Space E] [FiniteDimensional π•œ E] (f : E β†’β‚—[π•œ] F') : Continuous f := IsModuleTopology.continuous_of_linearMap f instance LinearMap.continuousLinearMapClassOfFiniteDimensional [T2Space E] [FiniteDimensional π•œ E] : ContinuousLinearMapClass (E β†’β‚—[π•œ] F') π•œ E F' := { LinearMap.semilinearMapClass with map_continuous := fun f => f.continuous_of_finiteDimensional } /-- In finite dimensions over a non-discrete complete normed field, the canonical identification (in terms of a basis) with `π•œ^n` (endowed with the product topology) is continuous. This is the key fact which makes all linear maps from a T2 finite-dimensional TVS over such a field continuous (see `LinearMap.continuous_of_finiteDimensional`), which in turn implies that all norms are equivalent in finite dimensions. -/ theorem continuous_equivFun_basis [T2Space E] {ΞΉ : Type*} [Finite ΞΉ] (ΞΎ : Basis ΞΉ π•œ E) : Continuous ΞΎ.equivFun := haveI : FiniteDimensional π•œ E := ΞΎ.finiteDimensional_of_finite ΞΎ.equivFun.toLinearMap.continuous_of_finiteDimensional namespace LinearMap variable [T2Space E] [FiniteDimensional π•œ E] /-- The continuous linear map induced by a linear map on a finite-dimensional space -/ def toContinuousLinearMap : (E β†’β‚—[π•œ] F') ≃ₗ[π•œ] E β†’L[π•œ] F' where toFun f := ⟨f, f.continuous_of_finiteDimensional⟩ invFun := (↑) map_add' _ _ := rfl map_smul' _ _ := rfl right_inv _ := ContinuousLinearMap.coe_injective rfl /-- Algebra equivalence between the linear maps and continuous linear maps on a finite-dimensional space. -/ def _root_.Module.End.toContinuousLinearMap (E : Type v) [NormedAddCommGroup E] [NormedSpace π•œ E] [FiniteDimensional π•œ E] : (E β†’β‚—[π•œ] E) ≃ₐ[π•œ] (E β†’L[π•œ] E) := { LinearMap.toContinuousLinearMap with map_mul' := fun _ _ ↦ rfl commutes' := fun _ ↦ rfl } @[simp] theorem coe_toContinuousLinearMap' (f : E β†’β‚—[π•œ] F') : ⇑(LinearMap.toContinuousLinearMap f) = f := rfl @[simp] theorem coe_toContinuousLinearMap (f : E β†’β‚—[π•œ] F') : ((LinearMap.toContinuousLinearMap f) : E β†’β‚—[π•œ] F') = f := rfl @[simp] theorem coe_toContinuousLinearMap_symm : ⇑(toContinuousLinearMap : (E β†’β‚—[π•œ] F') ≃ₗ[π•œ] E β†’L[π•œ] F').symm = ((↑) : (E β†’L[π•œ] F') β†’ E β†’β‚—[π•œ] F') := rfl @[simp] theorem det_toContinuousLinearMap (f : E β†’β‚—[π•œ] E) : (LinearMap.toContinuousLinearMap f).det = LinearMap.det f := rfl @[deprecated coe_toContinuousLinearMap (since := "2025-12-23")] theorem ker_toContinuousLinearMap (f : E β†’β‚—[π•œ] F') : (LinearMap.toContinuousLinearMap f).ker = ker f := by simp @[deprecated coe_toContinuousLinearMap (since := "2025-12-23")] theorem range_toContinuousLinearMap (f : E β†’β‚—[π•œ] F') : (LinearMap.toContinuousLinearMap f).range = range f := rfl /-- A surjective linear map `f` with finite-dimensional codomain is an open map. -/ theorem isOpenMap_of_finiteDimensional (f : F β†’β‚—[π•œ] E) (hf : Function.Surjective f) : IsOpenMap f := IsModuleTopology.isOpenMap_of_surjective hf instance canLiftContinuousLinearMap : CanLift (E β†’β‚—[π•œ] F) (E β†’L[π•œ] F) (↑) fun _ => True := ⟨fun f _ => ⟨LinearMap.toContinuousLinearMap f, rfl⟩⟩ lemma toContinuousLinearMap_eq_iff_eq_toLinearMap (f : E β†’β‚—[π•œ] E) (g : E β†’L[π•œ] E) : f.toContinuousLinearMap = g ↔ f = g.toLinearMap := by simp [ContinuousLinearMap.ext_iff, LinearMap.ext_iff] lemma _root_.ContinuousLinearMap.toLinearMap_eq_iff_eq_toContinuousLinearMap (g : E β†’L[π•œ] E) (f : E β†’β‚—[π•œ] E) : g.toLinearMap = f ↔ g = f.toContinuousLinearMap := by simp [ContinuousLinearMap.ext_iff, LinearMap.ext_iff] end LinearMap section variable [T2Space E] [T2Space F] [FiniteDimensional π•œ E] namespace LinearEquiv /-- The continuous linear equivalence induced by a linear equivalence on a finite-dimensional space. -/ def toContinuousLinearEquiv (e : E ≃ₗ[π•œ] F) : E ≃L[π•œ] F := { e with continuous_toFun := e.toLinearMap.continuous_of_finiteDimensional continuous_invFun := haveI : FiniteDimensional π•œ F := e.finiteDimensional e.symm.toLinearMap.continuous_of_finiteDimensional } @[simp] theorem coe_toContinuousLinearEquiv (e : E ≃ₗ[π•œ] F) : (e.toContinuousLinearEquiv : E β†’β‚—[π•œ] F) = e := rfl @[simp] theorem coe_toContinuousLinearEquiv' (e : E ≃ₗ[π•œ] F) : (e.toContinuousLinearEquiv : E β†’ F) = e := rfl @[simp] theorem coe_toContinuousLinearEquiv_symm (e : E ≃ₗ[π•œ] F) : (e.toContinuousLinearEquiv.toLinearEquiv.symm : F β†’β‚—[π•œ] E) = e.symm := rfl @[simp] theorem coe_toContinuousLinearEquiv_symm' (e : E ≃ₗ[π•œ] F) : (e.toContinuousLinearEquiv.symm : F β†’ E) = e.symm := rfl @[simp] theorem toLinearEquiv_toContinuousLinearEquiv (e : E ≃ₗ[π•œ] F) : e.toContinuousLinearEquiv.toLinearEquiv = e := by ext x rfl theorem toLinearEquiv_toContinuousLinearEquiv_symm (e : E ≃ₗ[π•œ] F) : e.toContinuousLinearEquiv.symm.toLinearEquiv = e.symm := by ext x rfl instance canLiftContinuousLinearEquiv : CanLift (E ≃ₗ[π•œ] F) (E ≃L[π•œ] F) ContinuousLinearEquiv.toLinearEquiv fun _ => True := ⟨fun f _ => ⟨_, f.toLinearEquiv_toContinuousLinearEquiv⟩⟩ end LinearEquiv variable [FiniteDimensional π•œ F] /-- Two finite-dimensional topological vector spaces over a complete normed field are continuously linearly equivalent if they have the same (finite) dimension. -/ theorem FiniteDimensional.nonempty_continuousLinearEquiv_of_finrank_eq (cond : finrank π•œ E = finrank π•œ F) : Nonempty (E ≃L[π•œ] F) := (nonempty_linearEquiv_of_finrank_eq cond).map LinearEquiv.toContinuousLinearEquiv /-- Two finite-dimensional topological vector spaces over a complete normed field are continuously linearly equivalent if and only if they have the same (finite) dimension. -/ theorem FiniteDimensional.nonempty_continuousLinearEquiv_iff_finrank_eq : Nonempty (E ≃L[π•œ] F) ↔ finrank π•œ E = finrank π•œ F := ⟨fun ⟨h⟩ => h.toLinearEquiv.finrank_eq, fun h => FiniteDimensional.nonempty_continuousLinearEquiv_of_finrank_eq h⟩ /-- A continuous linear equivalence between two finite-dimensional topological vector spaces over a complete normed field of the same (finite) dimension. -/ def ContinuousLinearEquiv.ofFinrankEq (cond : finrank π•œ E = finrank π•œ F) : E ≃L[π•œ] F := (LinearEquiv.ofFinrankEq E F cond).toContinuousLinearEquiv end namespace Module.Basis variable {ΞΉ : Type*} [Finite ΞΉ] [T2Space E] /-- Construct a continuous linear map given the value at a finite basis. -/ def constrL (v : Basis ΞΉ π•œ E) (f : ΞΉ β†’ F) : E β†’L[π•œ] F := haveI : FiniteDimensional π•œ E := v.finiteDimensional_of_finite LinearMap.toContinuousLinearMap (v.constr π•œ f) @[simp] theorem coe_constrL (v : Basis ΞΉ π•œ E) (f : ΞΉ β†’ F) : (v.constrL f : E β†’β‚—[π•œ] F) = v.constr π•œ f := rfl /-- The continuous linear equivalence between a vector space over `π•œ` with a finite basis and functions from its basis indexing type to `π•œ`. -/ @[simps! apply] def equivFunL (v : Basis ΞΉ π•œ E) : E ≃L[π•œ] ΞΉ β†’ π•œ := { v.equivFun with continuous_toFun := haveI : FiniteDimensional π•œ E := v.finiteDimensional_of_finite v.equivFun.toLinearMap.continuous_of_finiteDimensional continuous_invFun := by change Continuous v.equivFun.symm.toFun exact v.equivFun.symm.toLinearMap.continuous_of_finiteDimensional } @[simp] lemma equivFunL_symm_apply_repr (v : Basis ΞΉ π•œ E) (x : E) : v.equivFunL.symm (v.repr x) = x := v.equivFunL.symm_apply_apply x @[simp] theorem constrL_apply {ΞΉ : Type*} [Fintype ΞΉ] (v : Basis ΞΉ π•œ E) (f : ΞΉ β†’ F) (e : E) : v.constrL f e = βˆ‘ i, v.equivFun e i β€’ f i := v.constr_apply_fintype π•œ _ _ @[simp 1100] theorem constrL_basis (v : Basis ΞΉ π•œ E) (f : ΞΉ β†’ F) (i : ΞΉ) : v.constrL f (v i) = f i := v.constr_basis π•œ _ _ end Module.Basis namespace ContinuousLinearMap variable [T2Space E] [FiniteDimensional π•œ E] /-- Builds a continuous linear equivalence from a continuous linear map on a finite-dimensional vector space whose determinant is nonzero. -/ def toContinuousLinearEquivOfDetNeZero (f : E β†’L[π•œ] E) (hf : f.det β‰  0) : E ≃L[π•œ] E := ((f : E β†’β‚—[π•œ] E).equivOfDetNeZero hf).toContinuousLinearEquiv @[simp] theorem coe_toContinuousLinearEquivOfDetNeZero (f : E β†’L[π•œ] E) (hf : f.det β‰  0) : (f.toContinuousLinearEquivOfDetNeZero hf : E β†’L[π•œ] E) = f := by ext x rfl @[simp] theorem toContinuousLinearEquivOfDetNeZero_apply (f : E β†’L[π•œ] E) (hf : f.det β‰  0) (x : E) : f.toContinuousLinearEquivOfDetNeZero hf x = f x := rfl theorem _root_.Matrix.toLin_finTwoProd_toContinuousLinearMap (a b c d : π•œ) : LinearMap.toContinuousLinearMap (Matrix.toLin (Basis.finTwoProd π•œ) (Basis.finTwoProd π•œ) !![a, b; c, d]) = (a β€’ ContinuousLinearMap.fst π•œ π•œ π•œ + b β€’ ContinuousLinearMap.snd π•œ π•œ π•œ).prod (c β€’ ContinuousLinearMap.fst π•œ π•œ π•œ + d β€’ ContinuousLinearMap.snd π•œ π•œ π•œ) := ContinuousLinearMap.ext <| Matrix.toLin_finTwoProd_apply _ _ _ _ end ContinuousLinearMap end NormedField section IsUniformAddGroup variable (π•œ E : Type*) [NontriviallyNormedField π•œ] [CompleteSpace π•œ] [AddCommGroup E] [UniformSpace E] [T2Space E] [IsUniformAddGroup E] [Module π•œ E] [ContinuousSMul π•œ E] include π•œ in theorem FiniteDimensional.complete [FiniteDimensional π•œ E] : CompleteSpace E := by set e := ContinuousLinearEquiv.ofFinrankEq (@finrank_fin_fun π•œ _ _ (finrank π•œ E)).symm have : IsUniformEmbedding e.toEquiv.symm := e.symm.isUniformEmbedding exact (completeSpace_congr this).1 inferInstance variable {π•œ E} /-- A finite-dimensional subspace is complete. -/ theorem Submodule.complete_of_finiteDimensional (s : Submodule π•œ E) [FiniteDimensional π•œ s] : IsComplete (s : Set E) := haveI : IsUniformAddGroup s := s.toAddSubgroup.isUniformAddGroup completeSpace_coe_iff_isComplete.1 (FiniteDimensional.complete π•œ s) end IsUniformAddGroup variable {π•œ E F : Type*} [NontriviallyNormedField π•œ] [CompleteSpace π•œ] [AddCommGroup E] [TopologicalSpace E] [IsTopologicalAddGroup E] [Module π•œ E] [ContinuousSMul π•œ E] [AddCommGroup F] [TopologicalSpace F] [IsTopologicalAddGroup F] [Module π•œ F] [ContinuousSMul π•œ F] /-- A finite-dimensional subspace is closed. -/ theorem Submodule.closed_of_finiteDimensional [T2Space E] (s : Submodule π•œ E) [FiniteDimensional π•œ s] : IsClosed (s : Set E) := letI := IsTopologicalAddGroup.rightUniformSpace E haveI : IsUniformAddGroup E := isUniformAddGroup_of_addCommGroup s.complete_of_finiteDimensional.isClosed /-- If `s` is a closed subspace with finite codimension, any subspace containing `s` is closed. -/ theorem Submodule.isClosed_mono_of_finiteDimensional_quotient {s t : Submodule π•œ E} [FiniteDimensional π•œ (E β§Έ s)] (s_closed : IsClosed (s : Set E)) (s_le_t : s ≀ t) : IsClosed (t : Set E) := by rw [show t = comap s.mkQ (map s.mkQ t) by simpa] exact (map s.mkQ t).closed_of_finiteDimensional.preimage continuous_quot_mk /-- The supremum of a closed subspace and a finite dimensional subspace is closed. -/ theorem Submodule.isClosed_sup_finiteDimensional (s t : Submodule π•œ E) (hs : IsClosed (s : Set E)) [ht : FiniteDimensional π•œ t] : IsClosed ((s βŠ” t : Submodule π•œ E) : Set E) := by rw [← comap_map_mkQ] exact (map s.mkQ t).closed_of_finiteDimensional.preimage continuous_quot_mk /-- An injective linear map with finite-dimensional domain is a closed embedding. -/ theorem LinearMap.isClosedEmbedding_of_injective [T2Space E] [FiniteDimensional π•œ E] [T2Space F] {f : E β†’β‚—[π•œ] F} (hf : LinearMap.ker f = βŠ₯) : IsClosedEmbedding f := let g := LinearEquiv.ofInjective f (LinearMap.ker_eq_bot.mp hf) { IsEmbedding.subtypeVal.comp g.toContinuousLinearEquiv.toHomeomorph.isEmbedding with isClosed_range := by simpa [LinearMap.coe_range f] using (LinearMap.range f).closed_of_finiteDimensional } theorem isClosedEmbedding_smul_left [T2Space E] {c : E} (hc : c β‰  0) : IsClosedEmbedding fun x : π•œ => x β€’ c := LinearMap.isClosedEmbedding_of_injective (LinearMap.ker_toSpanSingleton π•œ hc) -- `smul` is a closed map in the first argument. theorem isClosedMap_smul_left [T2Space E] (c : E) : IsClosedMap fun x : π•œ => x β€’ c := by by_cases hc : c = 0 Β· simp_rw [hc, smul_zero] exact isClosedMap_const Β· exact (isClosedEmbedding_smul_left hc).isClosedMap theorem ContinuousLinearMap.exists_rightInverse_of_surjective [T2Space F] [FiniteDimensional π•œ F] (f : E β†’L[π•œ] F) (hf : f.range = ⊀) : βˆƒ g : F β†’L[π•œ] E, f.comp g = ContinuousLinearMap.id π•œ F := let ⟨g, hg⟩ := (f : E β†’β‚—[π•œ] F).exists_rightInverse_of_surjective hf ⟨LinearMap.toContinuousLinearMap g, ContinuousLinearMap.coe_inj.1 hg⟩ @[deprecated (since := "2026-04-24")] alias ContinuousLinearMap.exists_right_inverse_of_surjective := ContinuousLinearMap.exists_rightInverse_of_surjective theorem ContinuousLinearMap.isQuotientMap_of_finiteDimensional [T2Space F] [FiniteDimensional π•œ F] (f : E β†’L[π•œ] F) (hf : f.range = ⊀) : IsQuotientMap f := let ⟨g, hg⟩ := f.exists_rightInverse_of_surjective hf .of_inverse g.continuous f.continuous (fun _ ↦ congr($hg _)) theorem ContinuousLinearMap.isStrictMap_of_finiteDimensional [T2Space F] [FiniteDimensional π•œ F] (f : E β†’L[π•œ] F) : IsStrictMap f := by rw [isStrictMap_iff_isQuotientMap_rangeFactorization] exact f.rangeRestrict.isQuotientMap_of_finiteDimensional (by simp) /-- If `K` is a complete field and `V` is a finite-dimensional vector space over `K` (equipped with any topology so that `V` is a topological `K`-module, meaning `[IsTopologicalAddGroup V]` and `[ContinuousSMul K V]`), and `K` is locally compact, then `V` is locally compact. This is not an instance because `K` cannot be inferred. -/ theorem LocallyCompactSpace.of_finiteDimensional_of_complete (K V : Type*) [NontriviallyNormedField K] [CompleteSpace K] [LocallyCompactSpace K] [AddCommGroup V] [TopologicalSpace V] [IsTopologicalAddGroup V] [Module K V] [ContinuousSMul K V] [FiniteDimensional K V] : LocallyCompactSpace V := -- Reduce to `SeparationQuotient V`, which is a `T2Space`. suffices LocallyCompactSpace (SeparationQuotient V) from SeparationQuotient.isInducing_mk.locallyCompactSpace <| SeparationQuotient.range_mk (X := V) β–Έ isClosed_univ.isLocallyClosed let ⟨_, ⟨b⟩⟩ := Basis.exists_basis K (SeparationQuotient V) have := FiniteDimensional.fintypeBasisIndex b b.equivFun.toContinuousLinearEquiv.toHomeomorph.isOpenEmbedding.locallyCompactSpace section Riesz variable (π•œ : Type*) [NontriviallyNormedField π•œ] [CompleteSpace π•œ] {E Eα΅€ : Type*} [AddCommGroup E] [AddCommGroup Eα΅€] [Module π•œ E] [Module π•œ Eα΅€] [TopologicalSpace E] [UniformSpace Eα΅€] [T2Space E] [T2Space Eα΅€] [IsTopologicalAddGroup E] [IsUniformAddGroup Eα΅€] [ContinuousSMul π•œ E] [ContinuousSMul π•œ Eα΅€] open scoped Pointwise in /-- **Riesz's theorem**: a T2 topological vector space over a complete non-trivial normed field which admits a totally bounded neighborhood of `0` is finite-dimensional. -/ theorem FiniteDimensional.of_totallyBounded_nhds_zero {U : Set Eα΅€} (hU_nhds : U ∈ 𝓝 (0 : Eα΅€)) (hU_tb : TotallyBounded U) : FiniteDimensional π•œ Eα΅€ := by obtain ⟨c, hc0, hc1⟩ : βˆƒ c : π•œ, 0 < β€–cβ€– ∧ β€–cβ€– < 1 := NormedField.exists_norm_lt π•œ zero_lt_one have hc_ne : c β‰  0 := norm_pos_iff.mp hc0 obtain ⟨F, hF_finite, hF_cover⟩ := totallyBounded_iff_subset_finite_iUnion_nhds_zero.mp hU_tb (c β€’ U) ((set_smul_mem_nhds_zero_iff hc_ne).mpr hU_nhds) let M : Submodule π•œ Eα΅€ := Submodule.span π•œ F letI : FiniteDimensional π•œ M := Finite.span_of_finite π•œ hF_finite have h_cover : U βŠ† M + c β€’ U := fun x hx ↦ by obtain ⟨f, hf, y, hy, rfl⟩ := Set.mem_iUnionβ‚‚.mp <| hF_cover hx exact ⟨f, Submodule.subset_span hf, y, hy, rfl⟩ have h_ind (n : β„•) : U βŠ† M + c ^ n β€’ U := by induction n with | zero => simpa using! fun x hx ↦ ⟨0, M.zero_mem, x, hx, zero_add x⟩ | succ n ih => calc U βŠ† M + c ^ n β€’ U := ih _ βŠ† M + c ^ n β€’ (M + c β€’ U) := by gcongr _ βŠ† M + c ^ (n + 1) β€’ U := by rw [smul_add, smul_smul, pow_succ, ← add_assoc] congr! lift c to π•œΛ£ using isUnit_iff_ne_zero.mpr hc_ne simp [← Units.val_pow_eq_pow_val, ← Units.smul_def] have h_small : Tendsto (fun n ↦ c ^ n β€’ U) atTop (𝓝 0).smallSets := (TotallyBounded.isVonNBounded π•œ hU_tb).tendsto_smallSets_nhds.comp (tendsto_pow_atTop_nhds_zero_of_norm_lt_one hc1) have hU_sub_M : U βŠ† M := by intro x hx choose m hm u hu h_eq using fun n ↦ h_ind n hx have hu_tendsto : Tendsto u atTop (𝓝 0) := by intro W hW exact (tendsto_smallSets_iff.mp h_small W hW).mono fun n hn ↦ hn (hu n) have hm_tendsto : Tendsto m atTop (𝓝 x) := by simpa [show m = fun n ↦ x - u n by grind] using! tendsto_const_nhds.sub hu_tendsto exact M.closed_of_finiteDimensional.mem_of_tendsto hm_tendsto (Eventually.of_forall hm) have hM_top : M = ⊀ := absorbent_nhds_zero (π•œ := π•œ) hU_nhds |>.mono hU_sub_M |>.submodule_eq_top exact FiniteDimensional.of_surjective M.subtype fun x ↦ ⟨⟨x, by simp [hM_top]⟩, rfl⟩ open scoped Pointwise in /-- **Riesz's theorem**: if a T2 topological vector space over a complete non-trivial normed field admits a totally bounded neighborhood of some point, then it is finite-dimensional. -/ theorem FiniteDimensional.of_totallyBounded_nhds {x : Eα΅€} {U : Set Eα΅€} (hU_nhds : U ∈ 𝓝 x) (hU_tb : TotallyBounded U) : FiniteDimensional π•œ Eα΅€ := by replace hU_nhds : x +α΅₯ (-x) +α΅₯ U ∈ 𝓝 x := by simpa rw [vadd_mem_nhds_self] at hU_nhds refine .of_totallyBounded_nhds_zero _ hU_nhds ?_ have : -x +α΅₯ U = (Β· - x) '' U := by simp [← Set.image_vadd, neg_add_eq_sub] exact this β–Έ hU_tb.image (uniformContinuous_id.sub uniformContinuous_const) /-- **Riesz's theorem**: in a T2 topological vector space over a complete non-trivial normed field, if there exists a totally bounded neighborhood of some point, then the space is finite-dimensional. -/ theorem FiniteDimensional.of_exists_totallyBounded_nhds (h : βˆƒ x : Eα΅€, βˆƒ U ∈ 𝓝 x, TotallyBounded U) : FiniteDimensional π•œ Eα΅€ := by rcases h with ⟨x, U, hU_nhds, hU_tb⟩ exact FiniteDimensional.of_totallyBounded_nhds (π•œ := π•œ) hU_nhds hU_tb /-- **Riesz's theorem**: a locally compact topological vector space is finite-dimensional. -/ theorem FiniteDimensional.of_locallyCompactSpace [WeaklyLocallyCompactSpace E] : FiniteDimensional π•œ E := let : UniformSpace E := IsTopologicalAddGroup.rightUniformSpace E have : IsUniformAddGroup E := isUniformAddGroup_of_addCommGroup let ⟨_, hU_compact, hU_nhds⟩ := exists_compact_mem_nhds (0 : E) .of_totallyBounded_nhds_zero π•œ hU_nhds hU_compact.totallyBounded /-- If a function has compact support, then either the function is trivial or the space is finite-dimensional. -/ theorem HasCompactSupport.eq_zero_or_finiteDimensional {X : Type*} [TopologicalSpace X] [Zero X] [T1Space X] {f : E β†’ X} (hf : HasCompactSupport f) (h'f : Continuous f) : f = 0 ∨ FiniteDimensional π•œ E := (HasCompactSupport.eq_zero_or_locallyCompactSpace_of_addGroup hf h'f).imp_right fun h ↦ have : LocallyCompactSpace E := h; .of_locallyCompactSpace π•œ /-- If a function has compact multiplicative support, then either the function is trivial or the space is finite-dimensional. -/ theorem HasCompactMulSupport.eq_one_or_finiteDimensional {X : Type*} [TopologicalSpace X] [One X] [T1Space X] {f : E β†’ X} (hf : HasCompactMulSupport f) (h'f : Continuous f) : f = 1 ∨ FiniteDimensional π•œ E := have : T1Space (Additive X) := β€Ή_β€Ί HasCompactSupport.eq_zero_or_finiteDimensional π•œ (X := Additive X) hf h'f end Riesz section Compl open Submodule /-- If `p` is a closed subspace with finite codimension, then any algebraic complement `q` to `p` is a topological complement. -/ theorem Submodule.IsCompl.isTopCompl_of_finiteDimensional_quotient {p q : Submodule π•œ E} (h : IsCompl p q) (hp : IsClosed (p : Set E)) [FiniteDimensional π•œ (E β§Έ p)] : IsTopCompl p q := by let Ο† : E β§Έ p β†’L[π•œ] q := (p.quotientEquivOfIsCompl q h).toLinearMap.toContinuousLinearMap have := (Ο† ∘L p.mkQL).isTopCompl_of_proj fun x ↦ by simp [Ο†] simpa [Ο†] using this.symm /-- Assume that `p q : Submodule π•œ E` are algebraic complements. If `p` is closed and `q` has finite dimension, then they are in fact topological complements. Note that this theorem does not help you to build a closed complement to a finite dimensional subspace. That requires the Hahn-Banach theorem, and you don't get much control over what the complement is. See `Submodule.ClosedComplemented.of_finiteDimensional`. -/ theorem Submodule.IsCompl.isTopCompl_of_isClosed_of_finiteDimensional {p q : Submodule π•œ E} (h : IsCompl p q) (hp : IsClosed (p : Set E)) [hq : FiniteDimensional π•œ q] : IsTopCompl p q := by suffices FiniteDimensional π•œ (E β§Έ p) from h.isTopCompl_of_finiteDimensional_quotient hp exact (p.quotientEquivOfIsCompl q h).symm.finiteDimensional theorem Submodule.ClosedComplemented.of_finiteDimensional_quotient {p : Submodule π•œ E} (hp : IsClosed (p : Set E)) [hq : FiniteDimensional π•œ (E β§Έ p)] : p.ClosedComplemented := by obtain ⟨q, hq⟩ : βˆƒ q, IsCompl p q := p.exists_isCompl exact hq.isTopCompl_of_finiteDimensional_quotient hp |>.closedComplemented @[deprecated (since := "2026-05-09")] alias Submodule.ClosedComplemented.of_quotient_finiteDimensional := Submodule.ClosedComplemented.of_finiteDimensional_quotient lemma Submodule.ClosedComplemented.of_finiteDimensional_of_le {A B : Submodule π•œ E} [FiniteDimensional π•œ A] (hA : A.ClosedComplemented) [T2Space A] (hB : B ≀ A) : B.ClosedComplemented := by obtain ⟨p, hp⟩ := hA obtain ⟨C, hBC⟩ := B.exists_isCompl refine ⟨((projectionOnto B C hBC).domRestrict A).toContinuousLinearMap ∘SL p, fun x ↦ ?_⟩ simp [hp ⟨x, hB x.2⟩] omit [IsTopologicalAddGroup F] [ContinuousSMul π•œ F] in theorem ContinuousLinearMap.ker_closedComplemented_of_finiteDimensional_range [T2Space F] (f : E β†’L[π•œ] F) [FiniteDimensional π•œ f.range] : f.ker.ClosedComplemented := by suffices FiniteDimensional π•œ (E β§Έ f.ker) from .of_finiteDimensional_quotient f.isClosed_ker exact f.toLinearMap.quotKerEquivRange.symm.finiteDimensional end Compl