diff --git a/Mathlib/LinearAlgebra/Basis/HasCanonicalBasis.lean b/Mathlib/LinearAlgebra/Basis/HasCanonicalBasis.lean new file mode 100644 index 00000000000000..5b0b65efb66dd1 --- /dev/null +++ b/Mathlib/LinearAlgebra/Basis/HasCanonicalBasis.lean @@ -0,0 +1,104 @@ +/- +Copyright (c) 2025 Paul Lezeau. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Paul Lezeau, Eric Wieser +-/ +import Mathlib.Analysis.InnerProductSpace.PiL2 + +/-! # Canonical Bases for vector spaces + +This file introduces the notion of canonical bases for modules, +which allows us to work with an implicit notion of the canonical basis for familiar spaces. + +-/ + +universe u v w u' v' w' + +/-- `HasCanonicalBasis ๐•œ V ฮน f` means that the `๐•œ`-module `V` is canonically +represented by an `ฮน`-indexed basis with elements `f`. + +`f` is an outParam so that theorems about a particular basis can use the simp-normal `Pi.single` +rather than `Pi.basisFun`. -/ +class HasCanonicalBasis (๐•œ : Type u) (V : Type v) (ฮน : outParam <| Type w) + --TODO: can some of these be `semiOutParam`/regular params? + (f : outParam <| ฮน โ†’ V) [Semiring ๐•œ] [AddCommGroup V] + [Module ๐•œ V] where + /-- The underlying basis -/ + basis : Basis ฮน ๐•œ V + coe_basis_eq : basis = f + +namespace HasCanonicalBasis + +@[simp] +lemma basis_apply (๐•œ : Type u) (V : Type v) (ฮน : outParam <| Type w) + (f : outParam <| ฮน โ†’ V) [Semiring ๐•œ] [AddCommGroup V] + [Module ๐•œ V] [hc : HasCanonicalBasis ๐•œ V ฮน f] (i : ฮน) : + hc.basis i = f i := by + simp [coe_basis_eq] + +end HasCanonicalBasis + +variable {๐•œ : Type u} {ฮน : Type w} [DecidableEq ฮน] [Fintype ฮน] + +noncomputable instance EuclideanSpace.hasCanonicalBasis [RCLike ๐•œ] : + HasCanonicalBasis ๐•œ (EuclideanSpace ๐•œ ฮน) ฮน (EuclideanSpace.single ยท 1) where + basis := PiLp.basisFun 2 ๐•œ ฮน + coe_basis_eq := by ext : 1; simp + +variable [Ring ๐•œ] + +noncomputable instance Pi.hasCanonicalBasis : HasCanonicalBasis ๐•œ (ฮน โ†’ ๐•œ) ฮน (Pi.single ยท 1) where + basis := Pi.basisFun ๐•œ ฮน + coe_basis_eq := by ext; simp + +/- +Note: this could be generalised to a product of vector spaces that each have a +`HasCanonicalBasis` instance, but for now this isn't necessary, and the index +type would be a very ugly type, which is undesirable. +-/ +noncomputable instance [Ring ๐•œ] (p : ENNReal) : + HasCanonicalBasis ๐•œ (PiLp p (fun (_ : ฮน) โ†ฆ ๐•œ)) ฮน (Pi.single ยท 1) where + basis := (PiLp.basisFun p ๐•œ ฮน) + coe_basis_eq := by ext; simp + +noncomputable instance : HasCanonicalBasis ๐•œ ๐•œ (Fin 1) (fun _ โ†ฆ 1) where + basis := Basis.singleton _ ๐•œ + coe_basis_eq := by ext i; aesop + +/-- This abbrev provides us with a way of reindexing canonical bases, which is useful +in the context of defining canonical bases for products. -/ +noncomputable abbrev reindex {V : Type v} {ฮบ : Type w'} + {f : ฮน โ†’ V} {g : ฮบ โ†’ V} [Semiring ๐•œ] [AddCommGroup V] [Module ๐•œ V] + (hc : HasCanonicalBasis ๐•œ V ฮน f) (e : ฮน โ‰ƒ ฮบ) (he : โˆ€ (i : ฮบ), g i = hc.basis (e.symm i)) : + HasCanonicalBasis ๐•œ V ฮบ g where + basis := Basis.reindex (HasCanonicalBasis.basis) e + coe_basis_eq := by ext; simp [Basis.reindex_apply, he] + +variable (๐•œ) in +/-- Constructs a "canonical basis" on a product of two modules equipped with a canonical basis. +This isn't an instance since have a sum as the index type for our bases is in general undesirable +(e.g. this would force `๐•œ ร— ๐•œ` to have basis `Fin 1 โŠ• Fin 1` rather than `Fin 2`) -/ +noncomputable abbrev prod {V : Type v} {W : Type v'} {ฮบ : Type w'} + [AddCommGroup V] [AddCommGroup W] [Module ๐•œ V] [Module ๐•œ W] + (f : ฮน โ†’ V) (g : ฮบ โ†’ W) [HasCanonicalBasis ๐•œ V ฮน f] [HasCanonicalBasis ๐•œ W ฮบ g] : + HasCanonicalBasis ๐•œ (V ร— W) (ฮน โŠ• ฮบ) (Sum.elim (LinearMap.inl ๐•œ _ _ โˆ˜ f) + (LinearMap.inr ๐•œ _ _ โˆ˜ g)) where + basis := Basis.prod HasCanonicalBasis.basis HasCanonicalBasis.basis + coe_basis_eq := by ext <;> simp [Basis.prod_apply, Sum.elim] + +/-- +The canonical basis for `๐•œ ร— ๐•œ` +-/ +noncomputable instance : HasCanonicalBasis ๐•œ (๐•œ ร— ๐•œ) (Fin 2) (![(1, 0), (0, 1)]) := + reindex (prod ๐•œ _ _) finSumFinEquiv + (fun i โ†ฆ by fin_cases i <;> simp [finSumFinEquiv, prod, Sum.elim, Fin.addCases]) + +/-- +The canonical basis for `๐•œ ร— ๐•œ ร— ๐•œ`. +-/ +noncomputable instance : HasCanonicalBasis ๐•œ (๐•œ ร— ๐•œ ร— ๐•œ) (Fin 3) + (![(1, 0, 0), (0, 1, 0), (0, 0, 1)]) := + reindex (prod ๐•œ _ _) finSumFinEquiv + (fun i โ†ฆ by fin_cases i <;> simp [finSumFinEquiv, prod, Sum.elim, Fin.addCases]) + +-- TODO: maybe we also want to manually construct an instance on `๐•œ ร— ๐•œ ร— ๐•œ ร— ๐•œ`