|
| 1 | +/- |
| 2 | +Copyright (c) 2024 Jujian Zhang. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Jujian Zhang |
| 5 | +-/ |
| 6 | + |
| 7 | +import Mathlib.LinearAlgebra.PiTensorProduct |
| 8 | +import Mathlib.Algebra.Algebra.Bilinear |
| 9 | + |
| 10 | +/-! |
| 11 | +# Tensor product of `R`-algebras and rings |
| 12 | +
|
| 13 | +If `(Aᵢ)` is a family of `R`-algebras then the `R`-tensor product `⨂ᵢ Aᵢ` is an `R`-algebra as well |
| 14 | +with structure map defined by `r ↦ r • 1`. |
| 15 | +
|
| 16 | +In particular if we take `R` to be `ℤ`, then this collapses into the tensor product of rings. |
| 17 | +-/ |
| 18 | + |
| 19 | +open TensorProduct Function |
| 20 | + |
| 21 | +variable {ι R' R : Type*} {A : ι → Type*} |
| 22 | + |
| 23 | +namespace PiTensorProduct |
| 24 | + |
| 25 | +noncomputable section AddCommMonoidWithOne |
| 26 | + |
| 27 | +variable [CommSemiring R] [∀ i, AddCommMonoidWithOne (A i)] [∀ i, Module R (A i)] |
| 28 | + |
| 29 | +instance instOne : One (⨂[R] i, A i) where |
| 30 | + one := tprod R 1 |
| 31 | + |
| 32 | +lemma one_def : 1 = tprod R (1 : Π i, A i) := rfl |
| 33 | + |
| 34 | +instance instAddCommMonoidWithOne : AddCommMonoidWithOne (⨂[R] i, A i) where |
| 35 | + __ := inferInstanceAs (AddCommMonoid (⨂[R] i, A i)) |
| 36 | + __ := instOne |
| 37 | + |
| 38 | +end AddCommMonoidWithOne |
| 39 | + |
| 40 | +noncomputable section NonUnitalNonAssocSemiring |
| 41 | + |
| 42 | +variable [CommSemiring R] [∀ i, NonUnitalNonAssocSemiring (A i)] |
| 43 | +variable [∀ i, Module R (A i)] [∀ i, SMulCommClass R (A i) (A i)] [∀ i, IsScalarTower R (A i) (A i)] |
| 44 | + |
| 45 | +attribute [aesop safe] mul_add mul_smul_comm smul_mul_assoc add_mul in |
| 46 | +/-- |
| 47 | +The multiplication in tensor product of rings is induced by `(xᵢ) * (yᵢ) = (xᵢ * yᵢ)` |
| 48 | +-/ |
| 49 | +def mul : (⨂[R] i, A i) →ₗ[R] (⨂[R] i, A i) →ₗ[R] (⨂[R] i, A i) := |
| 50 | + PiTensorProduct.piTensorHomMap₂ <| tprod R fun _ ↦ LinearMap.mul _ _ |
| 51 | + |
| 52 | +@[simp] lemma mul_tprod_tprod (x y : (i : ι) → A i) : |
| 53 | + mul (tprod R x) (tprod R y) = tprod R (x * y) := by |
| 54 | + simp only [mul, piTensorHomMap₂_tprod_tprod_tprod, LinearMap.mul_apply'] |
| 55 | + rfl |
| 56 | + |
| 57 | +instance instMul : Mul (⨂[R] i, A i) where |
| 58 | + mul x y := mul x y |
| 59 | + |
| 60 | +lemma mul_def (x y : ⨂[R] i, A i) : x * y = mul x y := rfl |
| 61 | + |
| 62 | +@[simp] lemma tprod_mul_tprod (x y : (i : ι) → A i) : |
| 63 | + tprod R x * tprod R y = tprod R (x * y) := |
| 64 | + mul_tprod_tprod x y |
| 65 | + |
| 66 | +lemma smul_tprod_mul_smul_tprod (r s : R) (x y : Π i, A i) : |
| 67 | + (r • tprod R x) * (s • tprod R y) = (r * s) • tprod R (x * y) := by |
| 68 | + change mul _ _ = _ |
| 69 | + rw [map_smul, map_smul, mul_comm r s, mul_smul] |
| 70 | + simp only [LinearMap.smul_apply, mul_tprod_tprod] |
| 71 | + |
| 72 | +instance instNonUnitalNonAssocSemiring : NonUnitalNonAssocSemiring (⨂[R] i, A i) where |
| 73 | + __ := instMul |
| 74 | + __ := inferInstanceAs (AddCommMonoid (⨂[R] i, A i)) |
| 75 | + left_distrib _ _ _ := (mul _).map_add _ _ |
| 76 | + right_distrib _ _ _ := mul.map_add₂ _ _ _ |
| 77 | + zero_mul _ := mul.map_zero₂ _ |
| 78 | + mul_zero _ := map_zero (mul _) |
| 79 | + |
| 80 | +end NonUnitalNonAssocSemiring |
| 81 | + |
| 82 | +noncomputable section NonAssocSemiring |
| 83 | + |
| 84 | +variable [CommSemiring R] [∀ i, NonAssocSemiring (A i)] |
| 85 | +variable [∀ i, Module R (A i)] [∀ i, SMulCommClass R (A i) (A i)] [∀ i, IsScalarTower R (A i) (A i)] |
| 86 | + |
| 87 | +protected lemma one_mul (x : ⨂[R] i, A i) : mul (tprod R 1) x = x := by |
| 88 | + induction x using PiTensorProduct.induction_on with |
| 89 | + | smul_tprod => simp |
| 90 | + | add _ _ h1 h2 => simp [map_add, h1, h2] |
| 91 | + |
| 92 | +protected lemma mul_one (x : ⨂[R] i, A i) : mul x (tprod R 1) = x := by |
| 93 | + induction x using PiTensorProduct.induction_on with |
| 94 | + | smul_tprod => simp |
| 95 | + | add _ _ h1 h2 => simp [h1, h2] |
| 96 | + |
| 97 | +instance instNonAssocSemiring : NonAssocSemiring (⨂[R] i, A i) where |
| 98 | + __ := instNonUnitalNonAssocSemiring |
| 99 | + one_mul := PiTensorProduct.one_mul |
| 100 | + mul_one := PiTensorProduct.mul_one |
| 101 | + |
| 102 | +end NonAssocSemiring |
| 103 | + |
| 104 | +noncomputable section NonUnitalSemiring |
| 105 | + |
| 106 | +variable [CommSemiring R] [∀ i, NonUnitalSemiring (A i)] |
| 107 | +variable [∀ i, Module R (A i)] [∀ i, SMulCommClass R (A i) (A i)] [∀ i, IsScalarTower R (A i) (A i)] |
| 108 | + |
| 109 | +protected lemma mul_assoc (x y z : ⨂[R] i, A i) : mul (mul x y) z = mul x (mul y z) := by |
| 110 | + -- restate as an equality of morphisms so that we can use `ext` |
| 111 | + suffices LinearMap.llcomp R _ _ _ mul ∘ₗ mul = |
| 112 | + (LinearMap.llcomp R _ _ _ LinearMap.lflip <| LinearMap.llcomp R _ _ _ mul.flip ∘ₗ mul).flip by |
| 113 | + exact DFunLike.congr_fun (DFunLike.congr_fun (DFunLike.congr_fun this x) y) z |
| 114 | + ext x y z |
| 115 | + dsimp [← mul_def] |
| 116 | + simpa only [tprod_mul_tprod] using congr_arg (tprod R) (mul_assoc x y z) |
| 117 | + |
| 118 | +instance instNonUnitalSemiring : NonUnitalSemiring (⨂[R] i, A i) where |
| 119 | + __ := instNonUnitalNonAssocSemiring |
| 120 | + mul_assoc := PiTensorProduct.mul_assoc |
| 121 | + |
| 122 | +end NonUnitalSemiring |
| 123 | + |
| 124 | +noncomputable section Semiring |
| 125 | + |
| 126 | +variable [CommSemiring R'] [CommSemiring R] [∀ i, Semiring (A i)] |
| 127 | +variable [Algebra R' R] [∀ i, Algebra R (A i)] [∀ i, Algebra R' (A i)] |
| 128 | +variable [∀ i, IsScalarTower R' R (A i)] |
| 129 | + |
| 130 | +instance instSemiring : Semiring (⨂[R] i, A i) where |
| 131 | + __ := instNonUnitalSemiring |
| 132 | + __ := instNonAssocSemiring |
| 133 | + |
| 134 | +instance instAlgebra : Algebra R' (⨂[R] i, A i) where |
| 135 | + __ := hasSMul' |
| 136 | + toFun := (· • 1) |
| 137 | + map_one' := by simp |
| 138 | + map_mul' r s := show (r * s) • 1 = mul (r • 1) (s • 1) by |
| 139 | + rw [LinearMap.map_smul_of_tower, LinearMap.map_smul_of_tower, LinearMap.smul_apply, mul_comm, |
| 140 | + mul_smul] |
| 141 | + congr |
| 142 | + show (1 : ⨂[R] i, A i) = 1 * 1 |
| 143 | + rw [mul_one] |
| 144 | + map_zero' := by simp |
| 145 | + map_add' := by simp [add_smul] |
| 146 | + commutes' r x := by |
| 147 | + simp only [RingHom.coe_mk, MonoidHom.coe_mk, OneHom.coe_mk] |
| 148 | + change mul _ _ = mul _ _ |
| 149 | + rw [LinearMap.map_smul_of_tower, LinearMap.map_smul_of_tower, LinearMap.smul_apply] |
| 150 | + change r • (1 * x) = r • (x * 1) |
| 151 | + rw [mul_one, one_mul] |
| 152 | + smul_def' r x := by |
| 153 | + simp only [RingHom.coe_mk, MonoidHom.coe_mk, OneHom.coe_mk] |
| 154 | + change _ = mul _ _ |
| 155 | + rw [LinearMap.map_smul_of_tower, LinearMap.smul_apply] |
| 156 | + change _ = r • (1 * x) |
| 157 | + rw [one_mul] |
| 158 | + |
| 159 | +lemma algebraMap_apply (r : R') (i : ι) [DecidableEq ι] : |
| 160 | + algebraMap R' (⨂[R] i, A i) r = tprod R (Pi.mulSingle i (algebraMap R' (A i) r)) := by |
| 161 | + change r • tprod R 1 = _ |
| 162 | + have : Pi.mulSingle i (algebraMap R' (A i) r) = update (fun i ↦ 1) i (r • 1) := by |
| 163 | + rw [Algebra.algebraMap_eq_smul_one]; rfl |
| 164 | + rw [this, ← smul_one_smul R r (1 : A i), MultilinearMap.map_smul, update_eq_self, smul_one_smul] |
| 165 | + congr |
| 166 | + |
| 167 | +/-- |
| 168 | +The map `Aᵢ ⟶ ⨂ᵢ Aᵢ` given by `a ↦ 1 ⊗ ... ⊗ a ⊗ 1 ⊗ ...` |
| 169 | +-/ |
| 170 | +@[simps] |
| 171 | +def singleAlgHom [DecidableEq ι] (i : ι) : A i →ₐ[R] ⨂[R] i, A i where |
| 172 | + toFun a := tprod R (MonoidHom.single _ i a) |
| 173 | + map_one' := by simp only [_root_.map_one]; rfl |
| 174 | + map_mul' a a' := by simp |
| 175 | + map_zero' := MultilinearMap.map_update_zero _ _ _ |
| 176 | + map_add' _ _ := MultilinearMap.map_add _ _ _ _ _ |
| 177 | + commutes' r := show tprodCoeff R _ _ = r • tprodCoeff R _ _ by |
| 178 | + rw [Algebra.algebraMap_eq_smul_one] |
| 179 | + erw [smul_tprodCoeff] |
| 180 | + rfl |
| 181 | + |
| 182 | +/-- |
| 183 | +Lifting a multilinear map to an algebra homomorphism from tensor product |
| 184 | +-/ |
| 185 | +@[simps!] |
| 186 | +def liftAlgHom {S : Type*} [Semiring S] [Algebra R S] |
| 187 | + (f : MultilinearMap R A S) |
| 188 | + (one : f 1 = 1) (mul : ∀ x y, f (x * y) = f x * f y) : (⨂[R] i, A i) →ₐ[R] S := |
| 189 | + AlgHom.ofLinearMap (lift f) (show lift f (tprod R 1) = 1 by simp [one]) <| |
| 190 | + LinearMap.map_mul_iff _ |>.mpr <| by aesop |
| 191 | + |
| 192 | +end Semiring |
| 193 | + |
| 194 | +noncomputable section Ring |
| 195 | + |
| 196 | +variable [CommRing R] [∀ i, Ring (A i)] [∀ i, Algebra R (A i)] |
| 197 | + |
| 198 | +instance instRing : Ring (⨂[R] i, A i) where |
| 199 | + __ := instSemiring |
| 200 | + __ := inferInstanceAs <| AddCommGroup (⨂[R] i, A i) |
| 201 | + |
| 202 | +end Ring |
| 203 | + |
| 204 | +noncomputable section CommSemiring |
| 205 | + |
| 206 | +variable [CommSemiring R] [∀ i, CommSemiring (A i)] [∀ i, Algebra R (A i)] |
| 207 | + |
| 208 | +protected lemma mul_comm (x y : ⨂[R] i, A i) : mul x y = mul y x := by |
| 209 | + suffices mul (R := R) (A := A) = mul.flip from |
| 210 | + DFunLike.congr_fun (DFunLike.congr_fun this x) y |
| 211 | + ext x y |
| 212 | + dsimp |
| 213 | + simp only [mul_tprod_tprod, mul_tprod_tprod, mul_comm x y] |
| 214 | + |
| 215 | +instance instCommSemiring : CommSemiring (⨂[R] i, A i) where |
| 216 | + __ := instSemiring |
| 217 | + __ := inferInstanceAs <| AddCommMonoid (⨂[R] i, A i) |
| 218 | + mul_comm := PiTensorProduct.mul_comm |
| 219 | + |
| 220 | +end CommSemiring |
| 221 | + |
| 222 | +noncomputable section CommRing |
| 223 | + |
| 224 | +variable [CommRing R] [∀ i, CommRing (A i)] [∀ i, Algebra R (A i)] |
| 225 | +instance instCommRing : CommRing (⨂[R] i, A i) where |
| 226 | + __ := instCommSemiring |
| 227 | + __ := inferInstanceAs <| AddCommGroup (⨂[R] i, A i) |
| 228 | + |
| 229 | +end CommRing |
| 230 | + |
| 231 | +end PiTensorProduct |
0 commit comments