|
| 1 | +/- |
| 2 | +Copyright (c) 2017 Johannes Hölzl. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Johannes Hölzl |
| 5 | +
|
| 6 | +! This file was ported from Lean 3 source module linear_algebra.std_basis |
| 7 | +! leanprover-community/mathlib commit f2edd790f6c6e1d660515f76768f63cb717434d7 |
| 8 | +! Please do not edit these lines, except to modify the commit id |
| 9 | +! if you have ported upstream changes. |
| 10 | +-/ |
| 11 | +import Mathlib.Data.Matrix.Basis |
| 12 | +import Mathlib.LinearAlgebra.Basis |
| 13 | +import Mathlib.LinearAlgebra.Pi |
| 14 | + |
| 15 | +/-! |
| 16 | +# The standard basis |
| 17 | +
|
| 18 | +This file defines the standard basis `Pi.basis (s : ∀ j, Basis (ι j) R (M j))`, |
| 19 | +which is the `Σ j, ι j`-indexed basis of `Π j, M j`. The basis vectors are given by |
| 20 | +`Pi.basis s ⟨j, i⟩ j' = LinearMap.stdBasis R M j' (s j) i = if j = j' then s i else 0`. |
| 21 | +
|
| 22 | +The standard basis on `R^η`, i.e. `η → R` is called `Pi.basisFun`. |
| 23 | +
|
| 24 | +To give a concrete example, `LinearMap.stdBasis R (λ (i : Fin 3), R) i 1` |
| 25 | +gives the `i`th unit basis vector in `R³`, and `Pi.basisFun R (Fin 3)` proves |
| 26 | +this is a basis over `Fin 3 → R`. |
| 27 | +
|
| 28 | +## Main definitions |
| 29 | +
|
| 30 | + - `LinearMap.stdBasis R M`: if `x` is a basis vector of `M i`, then |
| 31 | + `LinearMap.stdBasis R M i x` is the `i`th standard basis vector of `Π i, M i`. |
| 32 | + - `Pi.basis s`: given a basis `s i` for each `M i`, the standard basis on `Π i, M i` |
| 33 | + - `Pi.basisFun R η`: the standard basis on `R^η`, i.e. `η → R`, given by |
| 34 | + `Pi.basisFun R η i j = if i = j then 1 else 0`. |
| 35 | + - `Matrix.stdBasis R n m`: the standard basis on `Matrix n m R`, given by |
| 36 | + `Matrix.stdBasis R n m (i, j) i' j' = if (i, j) = (i', j') then 1 else 0`. |
| 37 | +
|
| 38 | +-/ |
| 39 | + |
| 40 | + |
| 41 | +open Function Submodule |
| 42 | + |
| 43 | +open BigOperators |
| 44 | + |
| 45 | +namespace LinearMap |
| 46 | + |
| 47 | +variable (R : Type _) {ι : Type _} [Semiring R] (φ : ι → Type _) [∀ i, AddCommMonoid (φ i)] |
| 48 | + [∀ i, Module R (φ i)] [DecidableEq ι] |
| 49 | + |
| 50 | +/-- The standard basis of the product of `φ`. -/ |
| 51 | +def stdBasis : ∀ i : ι, φ i →ₗ[R] ∀ i, φ i := |
| 52 | + single |
| 53 | +#align linear_map.std_basis LinearMap.stdBasis |
| 54 | + |
| 55 | +theorem stdBasis_apply (i : ι) (b : φ i) : stdBasis R φ i b = update (0 : (a : ι) → φ a) i b := |
| 56 | + rfl |
| 57 | +#align linear_map.std_basis_apply LinearMap.stdBasis_apply |
| 58 | + |
| 59 | +@[simp] |
| 60 | +theorem stdBasis_apply' (i i' : ι) : (stdBasis R (fun _x : ι => R) i) 1 i' = ite (i = i') 1 0 := by |
| 61 | + rw [LinearMap.stdBasis_apply, Function.update_apply, Pi.zero_apply] |
| 62 | + congr 1; rw [eq_iff_iff, eq_comm] |
| 63 | +#align linear_map.std_basis_apply' LinearMap.stdBasis_apply' |
| 64 | + |
| 65 | +theorem coe_stdBasis (i : ι) : ⇑(stdBasis R φ i) = Pi.single i := |
| 66 | + rfl |
| 67 | +#align linear_map.coe_std_basis LinearMap.coe_stdBasis |
| 68 | + |
| 69 | +@[simp] |
| 70 | +theorem stdBasis_same (i : ι) (b : φ i) : stdBasis R φ i b i = b := |
| 71 | + Pi.single_eq_same i b |
| 72 | +#align linear_map.std_basis_same LinearMap.stdBasis_same |
| 73 | + |
| 74 | +theorem stdBasis_ne (i j : ι) (h : j ≠ i) (b : φ i) : stdBasis R φ i b j = 0 := |
| 75 | + Pi.single_eq_of_ne h b |
| 76 | +#align linear_map.std_basis_ne LinearMap.stdBasis_ne |
| 77 | + |
| 78 | +theorem stdBasis_eq_pi_diag (i : ι) : stdBasis R φ i = pi (diag i) := by |
| 79 | + ext (x j) |
| 80 | + -- Porting note: made types explicit |
| 81 | + convert (update_apply (R := R) (φ := φ) (ι := ι) 0 x i j _).symm |
| 82 | + rfl |
| 83 | +#align linear_map.std_basis_eq_pi_diag LinearMap.stdBasis_eq_pi_diag |
| 84 | + |
| 85 | +theorem ker_stdBasis (i : ι) : ker (stdBasis R φ i) = ⊥ := |
| 86 | + ker_eq_bot_of_injective <| Pi.single_injective _ _ |
| 87 | +#align linear_map.ker_std_basis LinearMap.ker_stdBasis |
| 88 | + |
| 89 | +theorem proj_comp_stdBasis (i j : ι) : (proj i).comp (stdBasis R φ j) = diag j i := by |
| 90 | + rw [stdBasis_eq_pi_diag, proj_pi] |
| 91 | +#align linear_map.proj_comp_std_basis LinearMap.proj_comp_stdBasis |
| 92 | + |
| 93 | +theorem proj_stdBasis_same (i : ι) : (proj i).comp (stdBasis R φ i) = id := |
| 94 | + LinearMap.ext <| stdBasis_same R φ i |
| 95 | +#align linear_map.proj_std_basis_same LinearMap.proj_stdBasis_same |
| 96 | + |
| 97 | +theorem proj_stdBasis_ne (i j : ι) (h : i ≠ j) : (proj i).comp (stdBasis R φ j) = 0 := |
| 98 | + LinearMap.ext <| stdBasis_ne R φ _ _ h |
| 99 | +#align linear_map.proj_std_basis_ne LinearMap.proj_stdBasis_ne |
| 100 | + |
| 101 | +theorem supᵢ_range_stdBasis_le_infᵢ_ker_proj (I J : Set ι) (h : Disjoint I J) : |
| 102 | + (⨆ i ∈ I, range (stdBasis R φ i)) ≤ ⨅ i ∈ J, ker (proj i : (∀ i, φ i) →ₗ[R] φ i) := by |
| 103 | + refine' supᵢ_le fun i => supᵢ_le fun hi => range_le_iff_comap.2 _ |
| 104 | + simp only [←ker_comp, eq_top_iff, SetLike.le_def, mem_ker, comap_infᵢ, mem_infᵢ] |
| 105 | + rintro b - j hj |
| 106 | + rw [proj_stdBasis_ne R φ j i, zero_apply] |
| 107 | + rintro rfl |
| 108 | + exact h.le_bot ⟨hi, hj⟩ |
| 109 | +#align linear_map.supr_range_std_basis_le_infi_ker_proj LinearMap.supᵢ_range_stdBasis_le_infᵢ_ker_proj |
| 110 | + |
| 111 | +theorem infᵢ_ker_proj_le_supᵢ_range_stdBasis {I : Finset ι} {J : Set ι} (hu : Set.univ ⊆ ↑I ∪ J) : |
| 112 | + (⨅ i ∈ J, ker (proj i : (∀ i, φ i) →ₗ[R] φ i)) ≤ ⨆ i ∈ I, range (stdBasis R φ i) := |
| 113 | + SetLike.le_def.2 |
| 114 | + (by |
| 115 | + intro b hb |
| 116 | + simp only [mem_infᵢ, mem_ker, proj_apply] at hb |
| 117 | + rw [← |
| 118 | + show (∑ i in I, stdBasis R φ i (b i)) = b by |
| 119 | + ext i |
| 120 | + rw [Finset.sum_apply, ← stdBasis_same R φ i (b i)] |
| 121 | + refine Finset.sum_eq_single i (fun j _ ne => stdBasis_ne _ _ _ _ ne.symm _) ?_ |
| 122 | + intro hiI |
| 123 | + rw [stdBasis_same] |
| 124 | + exact hb _ ((hu trivial).resolve_left hiI)] |
| 125 | + exact sum_mem_bsupᵢ fun i _ => mem_range_self (stdBasis R φ i) (b i)) |
| 126 | +#align linear_map.infi_ker_proj_le_supr_range_std_basis LinearMap.infᵢ_ker_proj_le_supᵢ_range_stdBasis |
| 127 | + |
| 128 | +theorem supᵢ_range_stdBasis_eq_infᵢ_ker_proj {I J : Set ι} (hd : Disjoint I J) |
| 129 | + (hu : Set.univ ⊆ I ∪ J) (hI : Set.Finite I) : |
| 130 | + (⨆ i ∈ I, range (stdBasis R φ i)) = ⨅ i ∈ J, ker (proj i : (∀ i, φ i) →ₗ[R] φ i) := by |
| 131 | + refine' le_antisymm (supᵢ_range_stdBasis_le_infᵢ_ker_proj _ _ _ _ hd) _ |
| 132 | + have : Set.univ ⊆ ↑hI.toFinset ∪ J := by rwa [hI.coe_toFinset] |
| 133 | + refine' le_trans (infᵢ_ker_proj_le_supᵢ_range_stdBasis R φ this) (supᵢ_mono fun i => _) |
| 134 | + rw [Set.Finite.mem_toFinset] |
| 135 | +#align linear_map.supr_range_std_basis_eq_infi_ker_proj LinearMap.supᵢ_range_stdBasis_eq_infᵢ_ker_proj |
| 136 | + |
| 137 | +theorem supᵢ_range_stdBasis [Finite ι] : (⨆ i, range (stdBasis R φ i)) = ⊤ := by |
| 138 | + cases nonempty_fintype ι |
| 139 | + convert top_unique (infᵢ_emptyset.ge.trans <| infᵢ_ker_proj_le_supᵢ_range_stdBasis R φ _) |
| 140 | + · rename_i i |
| 141 | + exact ((@supᵢ_pos _ _ _ fun _ => range <| stdBasis R φ i) <| Finset.mem_univ i).symm |
| 142 | + · rw [Finset.coe_univ, Set.union_empty] |
| 143 | +#align linear_map.supr_range_std_basis LinearMap.supᵢ_range_stdBasis |
| 144 | + |
| 145 | +theorem disjoint_stdBasis_stdBasis (I J : Set ι) (h : Disjoint I J) : |
| 146 | + Disjoint (⨆ i ∈ I, range (stdBasis R φ i)) (⨆ i ∈ J, range (stdBasis R φ i)) := by |
| 147 | + refine' |
| 148 | + Disjoint.mono (supᵢ_range_stdBasis_le_infᵢ_ker_proj _ _ _ _ <| disjoint_compl_right) |
| 149 | + (supᵢ_range_stdBasis_le_infᵢ_ker_proj _ _ _ _ <| disjoint_compl_right) _ |
| 150 | + simp only [disjoint_iff_inf_le, SetLike.le_def, mem_infᵢ, mem_inf, mem_ker, mem_bot, proj_apply, |
| 151 | + funext_iff] |
| 152 | + rintro b ⟨hI, hJ⟩ i |
| 153 | + classical |
| 154 | + by_cases hiI : i ∈ I |
| 155 | + · by_cases hiJ : i ∈ J |
| 156 | + · exact (h.le_bot ⟨hiI, hiJ⟩).elim |
| 157 | + · exact hJ i hiJ |
| 158 | + · exact hI i hiI |
| 159 | +#align linear_map.disjoint_std_basis_std_basis LinearMap.disjoint_stdBasis_stdBasis |
| 160 | + |
| 161 | +theorem stdBasis_eq_single {a : R} : |
| 162 | + (fun i : ι => (stdBasis R (fun _ : ι => R) i) a) = fun i : ι => ↑(Finsupp.single i a) := |
| 163 | + funext fun i => (Finsupp.single_eq_pi_single i a).symm |
| 164 | +#align linear_map.std_basis_eq_single LinearMap.stdBasis_eq_single |
| 165 | + |
| 166 | +end LinearMap |
| 167 | + |
| 168 | +namespace Pi |
| 169 | + |
| 170 | +open LinearMap |
| 171 | + |
| 172 | +open Set |
| 173 | + |
| 174 | +variable {R : Type _} |
| 175 | + |
| 176 | +section Module |
| 177 | + |
| 178 | +variable {η : Type _} {ιs : η → Type _} {Ms : η → Type _} |
| 179 | + |
| 180 | +theorem linearIndependent_stdBasis [Ring R] [∀ i, AddCommGroup (Ms i)] [∀ i, Module R (Ms i)] |
| 181 | + [DecidableEq η] (v : ∀ j, ιs j → Ms j) (hs : ∀ i, LinearIndependent R (v i)) : |
| 182 | + LinearIndependent R fun ji : Σj, ιs j => stdBasis R Ms ji.1 (v ji.1 ji.2) := by |
| 183 | + have hs' : ∀ j : η, LinearIndependent R fun i : ιs j => stdBasis R Ms j (v j i) := by |
| 184 | + intro j |
| 185 | + exact (hs j).map' _ (ker_stdBasis _ _ _) |
| 186 | + apply linearIndependent_unionᵢ_finite hs' |
| 187 | + · intro j J _ hiJ |
| 188 | + simp only |
| 189 | + have h₀ : |
| 190 | + ∀ j, span R (range fun i : ιs j => stdBasis R Ms j (v j i)) ≤ |
| 191 | + LinearMap.range (stdBasis R Ms j) := by |
| 192 | + intro j |
| 193 | + rw [span_le, LinearMap.range_coe] |
| 194 | + apply range_comp_subset_range |
| 195 | + have h₁ : |
| 196 | + span R (range fun i : ιs j => stdBasis R Ms j (v j i)) ≤ |
| 197 | + ⨆ i ∈ ({j} : Set _), LinearMap.range (stdBasis R Ms i) := by |
| 198 | + rw [@supᵢ_singleton _ _ _ fun i => LinearMap.range (stdBasis R (Ms) i)] |
| 199 | + apply h₀ |
| 200 | + have h₂ : |
| 201 | + (⨆ j ∈ J, span R (range fun i : ιs j => stdBasis R Ms j (v j i))) ≤ |
| 202 | + ⨆ j ∈ J, LinearMap.range (stdBasis R (fun j : η => Ms j) j) := |
| 203 | + supᵢ₂_mono fun i _ => h₀ i |
| 204 | + have h₃ : Disjoint (fun i : η => i ∈ ({j} : Set _)) J := by |
| 205 | + convert Set.disjoint_singleton_left.2 hiJ using 0 |
| 206 | + exact (disjoint_stdBasis_stdBasis _ _ _ _ h₃).mono h₁ h₂ |
| 207 | +#align pi.linear_independent_std_basis Pi.linearIndependent_stdBasis |
| 208 | + |
| 209 | +variable [Semiring R] [∀ i, AddCommMonoid (Ms i)] [∀ i, Module R (Ms i)] |
| 210 | + |
| 211 | +variable [Fintype η] |
| 212 | + |
| 213 | +section |
| 214 | + |
| 215 | +open LinearEquiv |
| 216 | + |
| 217 | +/-- `Pi.basis (s : ∀ j, Basis (ιs j) R (Ms j))` is the `Σ j, ιs j`-indexed basis on `Π j, Ms j` |
| 218 | +given by `s j` on each component. |
| 219 | +
|
| 220 | +For the standard basis over `R` on the finite-dimensional space `η → R` see `Pi.basisFun`. |
| 221 | +-/ |
| 222 | +protected noncomputable def basis (s : ∀ j, Basis (ιs j) R (Ms j)) : |
| 223 | + Basis (Σj, ιs j) R (∀ j, Ms j) := |
| 224 | + Basis.ofRepr |
| 225 | + ((LinearEquiv.piCongrRight fun j => (s j).repr) ≪≫ₗ |
| 226 | + (Finsupp.sigmaFinsuppLEquivPiFinsupp R).symm) |
| 227 | + -- Porting note: was |
| 228 | + -- -- The `AddCommMonoid (Π j, Ms j)` instance was hard to find. |
| 229 | + -- -- Defining this in tactic mode seems to shake up instance search enough |
| 230 | + -- -- that it works by itself. |
| 231 | + -- refine Basis.ofRepr (?_ ≪≫ₗ (Finsupp.sigmaFinsuppLEquivPiFinsupp R).symm) |
| 232 | + -- exact LinearEquiv.piCongrRight fun j => (s j).repr |
| 233 | +#align pi.basis Pi.basis |
| 234 | + |
| 235 | +@[simp] |
| 236 | +theorem basis_repr_stdBasis [DecidableEq η] (s : ∀ j, Basis (ιs j) R (Ms j)) (j i) : |
| 237 | + (Pi.basis s).repr (stdBasis R _ j (s j i)) = Finsupp.single ⟨j, i⟩ 1 := by |
| 238 | + ext ⟨j', i'⟩ |
| 239 | + by_cases hj : j = j' |
| 240 | + · subst hj |
| 241 | + -- Porting note: needed to add more lemmas |
| 242 | + simp only [Pi.basis, LinearEquiv.trans_apply, Basis.repr_self, stdBasis_same, |
| 243 | + LinearEquiv.piCongrRight, Finsupp.sigmaFinsuppLEquivPiFinsupp_symm_apply, |
| 244 | + Basis.repr_symm_apply, LinearEquiv.coe_mk, ne_eq, Sigma.mk.inj_iff, heq_eq_eq, true_and] |
| 245 | + symm |
| 246 | + -- Porting note: `Sigma.mk.inj` not found in the following, replaced by `Sigma.mk.inj_iff.mp` |
| 247 | + exact |
| 248 | + Finsupp.single_apply_left |
| 249 | + (fun i i' (h : (⟨j, i⟩ : Σj, ιs j) = ⟨j, i'⟩) => eq_of_heq (Sigma.mk.inj_iff.mp h).2) _ _ _ |
| 250 | + simp only [Pi.basis, LinearEquiv.trans_apply, Finsupp.sigmaFinsuppLEquivPiFinsupp_symm_apply, |
| 251 | + LinearEquiv.piCongrRight] |
| 252 | + dsimp |
| 253 | + rw [stdBasis_ne _ _ _ _ (Ne.symm hj), LinearEquiv.map_zero, Finsupp.zero_apply, |
| 254 | + Finsupp.single_eq_of_ne] |
| 255 | + rintro ⟨⟩ |
| 256 | + contradiction |
| 257 | +#align pi.basis_repr_std_basis Pi.basis_repr_stdBasis |
| 258 | + |
| 259 | +@[simp] |
| 260 | +theorem basis_apply [DecidableEq η] (s : ∀ j, Basis (ιs j) R (Ms j)) (ji) : |
| 261 | + Pi.basis s ji = stdBasis R _ ji.1 (s ji.1 ji.2) := |
| 262 | + Basis.apply_eq_iff.mpr (by simp) |
| 263 | +#align pi.basis_apply Pi.basis_apply |
| 264 | + |
| 265 | +@[simp] |
| 266 | +theorem basis_repr (s : ∀ j, Basis (ιs j) R (Ms j)) (x) (ji) : |
| 267 | + (Pi.basis s).repr x ji = (s ji.1).repr (x ji.1) ji.2 := |
| 268 | + rfl |
| 269 | +#align pi.basis_repr Pi.basis_repr |
| 270 | + |
| 271 | +end |
| 272 | + |
| 273 | +section |
| 274 | + |
| 275 | +variable (R η) |
| 276 | + |
| 277 | +/-- The basis on `η → R` where the `i`th basis vector is `Function.update 0 i 1`. -/ |
| 278 | +noncomputable def basisFun : Basis η R (∀ _ : η, R) := |
| 279 | + Basis.ofEquivFun (LinearEquiv.refl _ _) |
| 280 | +#align pi.basis_fun Pi.basisFun |
| 281 | + |
| 282 | +@[simp] |
| 283 | +theorem basisFun_apply [DecidableEq η] (i) : basisFun R η i = stdBasis R (fun _ : η => R) i 1 := by |
| 284 | + simp only [basisFun, Basis.coe_ofEquivFun, LinearEquiv.refl_symm, LinearEquiv.refl_apply, |
| 285 | + stdBasis_apply] |
| 286 | +#align pi.basis_fun_apply Pi.basisFun_apply |
| 287 | + |
| 288 | +@[simp] |
| 289 | +theorem basisFun_repr (x : η → R) (i : η) : (Pi.basisFun R η).repr x i = x i := by simp [basisFun] |
| 290 | +#align pi.basis_fun_repr Pi.basisFun_repr |
| 291 | + |
| 292 | +end |
| 293 | + |
| 294 | +end Module |
| 295 | + |
| 296 | +end Pi |
| 297 | + |
| 298 | +namespace Matrix |
| 299 | + |
| 300 | +variable (R : Type _) (m n : Type _) [Fintype m] [Fintype n] [Semiring R] |
| 301 | + |
| 302 | +/-- The standard basis of `Matrix m n R`. -/ |
| 303 | +noncomputable def stdBasis : Basis (m × n) R (Matrix m n R) := |
| 304 | + Basis.reindex (Pi.basis fun _ : m => Pi.basisFun R n) (Equiv.sigmaEquivProd _ _) |
| 305 | +#align matrix.std_basis Matrix.stdBasis |
| 306 | + |
| 307 | +variable {n m} |
| 308 | + |
| 309 | +theorem stdBasis_eq_stdBasisMatrix (i : n) (j : m) [DecidableEq n] [DecidableEq m] : |
| 310 | + stdBasis R n m (i, j) = stdBasisMatrix i j (1 : R) := by |
| 311 | + -- Porting note: `simp` fails to apply `Pi.basis_apply` |
| 312 | + ext (a b) |
| 313 | + by_cases hi : i = a <;> by_cases hj : j = b |
| 314 | + · simp [stdBasis, hi, hj, Basis.coe_reindex, comp_apply, Equiv.sigmaEquivProd_symm_apply, |
| 315 | + StdBasisMatrix.apply_same] |
| 316 | + erw [Pi.basis_apply] |
| 317 | + simp |
| 318 | + · simp only [stdBasis, hi, Basis.coe_reindex, comp_apply, Equiv.sigmaEquivProd_symm_apply, |
| 319 | + hj, and_false, not_false_iff, StdBasisMatrix.apply_of_ne] |
| 320 | + erw [Pi.basis_apply] |
| 321 | + simp [hj] |
| 322 | + · simp only [stdBasis, hj, Basis.coe_reindex, comp_apply, Equiv.sigmaEquivProd_symm_apply, |
| 323 | + hi, and_true, not_false_iff, StdBasisMatrix.apply_of_ne] |
| 324 | + erw [Pi.basis_apply] |
| 325 | + simp [hi, hj, Ne.symm hi, LinearMap.stdBasis_ne] |
| 326 | + · simp only [stdBasis, Basis.coe_reindex, comp_apply, Equiv.sigmaEquivProd_symm_apply, |
| 327 | + hi, hj, and_self, not_false_iff, StdBasisMatrix.apply_of_ne] |
| 328 | + erw [Pi.basis_apply] |
| 329 | + simp [hi, hj, Ne.symm hj, Ne.symm hi, LinearMap.stdBasis_ne] |
| 330 | +#align matrix.std_basis_eq_std_basis_matrix Matrix.stdBasis_eq_stdBasisMatrix |
| 331 | + |
| 332 | +end Matrix |
0 commit comments