linear_algebra.pi_tensor_productMathlib.LinearAlgebra.PiTensorProduct

This file has been ported!

Changes since the initial port

The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.

Changes in mathlib3

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(last sync)

Changes in mathlib3port

mathlib3
mathlib3port
Diff
@@ -241,7 +241,7 @@ protected theorem induction_on' {C : ⨂[R] i, s i → Prop} (z : ⨂[R] i, s i)
   by
   have C0 : C 0 := by
     have h₁ := @C1 0 0
-    rwa [zero_tprod_coeff] at h₁ 
+    rwa [zero_tprod_coeff] at h₁
   refine' AddCon.induction_on z fun x => FreeAddMonoid.recOn x C0 _
   simp_rw [AddCon.coe_add]
   refine' fun f y ih => Cp _ ih
@@ -380,7 +380,7 @@ theorem tprodCoeff_eq_smul_tprod (z : R) (f : ∀ i, s i) : tprodCoeff R z f = z
 protected theorem induction_on {C : ⨂[R] i, s i → Prop} (z : ⨂[R] i, s i)
     (C1 : ∀ {r : R} {f : ∀ i, s i}, C (r • tprod R f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
     C z := by
-  simp_rw [← tprod_coeff_eq_smul_tprod] at C1 
+  simp_rw [← tprod_coeff_eq_smul_tprod] at C1
   exact PiTensorProduct.induction_on' z @C1 @Cp
 #align pi_tensor_product.induction_on PiTensorProduct.induction_on
 -/
Diff
@@ -3,8 +3,8 @@ Copyright (c) 2020 Frédéric Dupuis. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Frédéric Dupuis, Eric Wieser
 -/
-import Mathbin.GroupTheory.Congruence
-import Mathbin.LinearAlgebra.Multilinear.TensorProduct
+import GroupTheory.Congruence
+import LinearAlgebra.Multilinear.TensorProduct
 
 #align_import linear_algebra.pi_tensor_product from "leanprover-community/mathlib"@"5c1efce12ba86d4901463f61019832f6a4b1a0d0"
 
Diff
@@ -290,7 +290,7 @@ instance distribMulAction' : DistribMulAction R₁ (⨂[R] i, s i)
     where
   smul := (· • ·)
   smul_add r x y := AddMonoidHom.map_add _ _ _
-  mul_smul r r' x :=
+  hMul_smul r r' x :=
     PiTensorProduct.induction_on' x (fun r'' f => by simp [smul_tprod_coeff', smul_smul])
       fun x y ihx ihy => by simp_rw [PiTensorProduct.smul_add, ihx, ihy]
   one_smul x :=
Diff
@@ -2,15 +2,12 @@
 Copyright (c) 2020 Frédéric Dupuis. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Frédéric Dupuis, Eric Wieser
-
-! This file was ported from Lean 3 source module linear_algebra.pi_tensor_product
-! leanprover-community/mathlib commit 5c1efce12ba86d4901463f61019832f6a4b1a0d0
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathbin.GroupTheory.Congruence
 import Mathbin.LinearAlgebra.Multilinear.TensorProduct
 
+#align_import linear_algebra.pi_tensor_product from "leanprover-community/mathlib"@"5c1efce12ba86d4901463f61019832f6a4b1a0d0"
+
 /-!
 # Tensor product of an indexed family of modules over commutative semirings
 
Diff
@@ -259,21 +259,21 @@ variable [Monoid R₁] [DistribMulAction R₁ R] [SMulCommClass R₁ R R]
 
 variable [Monoid R₂] [DistribMulAction R₂ R] [SMulCommClass R₂ R R]
 
-#print PiTensorProduct.hasSmul' /-
+#print PiTensorProduct.hasSMul' /-
 -- Most of the time we want the instance below this one, which is easier for typeclass resolution
 -- to find.
-instance hasSmul' : SMul R₁ (⨂[R] i, s i) :=
+instance hasSMul' : SMul R₁ (⨂[R] i, s i) :=
   ⟨fun r =>
     liftAddHom (fun f : R × ∀ i, s i => tprodCoeff R (r • f.1) f.2)
       (fun r' f i hf => by simp_rw [zero_tprod_coeff' _ f i hf])
       (fun f => by simp [zero_tprod_coeff]) (fun r' f i m₁ m₂ => by simp [add_tprod_coeff])
       (fun r' r'' f => by simp [add_tprod_coeff', mul_add]) fun z f i r' => by
       simp [smul_tprod_coeff, mul_smul_comm]⟩
-#align pi_tensor_product.has_smul' PiTensorProduct.hasSmul'
+#align pi_tensor_product.has_smul' PiTensorProduct.hasSMul'
 -/
 
 instance : SMul R (⨂[R] i, s i) :=
-  PiTensorProduct.hasSmul'
+  PiTensorProduct.hasSMul'
 
 #print PiTensorProduct.smul_tprodCoeff' /-
 theorem smul_tprodCoeff' (r : R₁) (z : R) (f : ∀ i, s i) :
Diff
@@ -712,7 +712,7 @@ def tmulEquiv : (⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M ≃ₗ[R] ⨂[R] i
       -- Speed up the call to `simp`.
       simp only [tmul_symm_apply, tmul_apply, Sum.elim_comp_inl_inr])
     (by
-      ext (x y)
+      ext x y
       show tmul_symm (tmul (tprod R x ⊗ₜ[R] tprod R y)) = tprod R x ⊗ₜ[R] tprod R y
       simp only [tmul_apply, tmul_symm_apply, Sum.elim_inl, Sum.elim_inr])
 #align pi_tensor_product.tmul_equiv PiTensorProduct.tmulEquiv
Diff
@@ -88,8 +88,6 @@ variable {F : Type _} [AddCommMonoid F]
 
 namespace PiTensorProduct
 
-include R
-
 variable (R) (s)
 
 #print PiTensorProduct.Eqv /-
@@ -129,7 +127,6 @@ def PiTensorProduct : Type _ :=
 
 variable {R}
 
--- mathport name: pi_tensor_product
 -- This enables the notation `⨂[R] i : ι, s i` for the pi tensor product, given `s : ι → Type*`.
 scoped[TensorProduct] notation3:100"⨂["R"] "(...)", "r:67:(scoped f => PiTensorProduct R f) => r
 
@@ -161,30 +158,41 @@ def tprodCoeff (r : R) (f : ∀ i, s i) : ⨂[R] i, s i :=
 
 variable {R}
 
+#print PiTensorProduct.zero_tprodCoeff /-
 theorem zero_tprodCoeff (f : ∀ i, s i) : tprodCoeff R 0 f = 0 :=
   Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_zero_scalar _
 #align pi_tensor_product.zero_tprod_coeff PiTensorProduct.zero_tprodCoeff
+-/
 
+#print PiTensorProduct.zero_tprodCoeff' /-
 theorem zero_tprodCoeff' (z : R) (f : ∀ i, s i) (i : ι) (hf : f i = 0) : tprodCoeff R z f = 0 :=
   Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_zero _ _ i hf
 #align pi_tensor_product.zero_tprod_coeff' PiTensorProduct.zero_tprodCoeff'
+-/
 
+#print PiTensorProduct.add_tprodCoeff /-
 theorem add_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i) :
     tprodCoeff R z (update f i m₁) + tprodCoeff R z (update f i m₂) =
       tprodCoeff R z (update f i (m₁ + m₂)) :=
   Quotient.sound' <| AddConGen.Rel.of _ _ (Eqv.of_add _ z f i m₁ m₂)
 #align pi_tensor_product.add_tprod_coeff PiTensorProduct.add_tprodCoeff
+-/
 
+#print PiTensorProduct.add_tprodCoeff' /-
 theorem add_tprodCoeff' (z₁ z₂ : R) (f : ∀ i, s i) :
     tprodCoeff R z₁ f + tprodCoeff R z₂ f = tprodCoeff R (z₁ + z₂) f :=
   Quotient.sound' <| AddConGen.Rel.of _ _ (Eqv.of_add_scalar z₁ z₂ f)
 #align pi_tensor_product.add_tprod_coeff' PiTensorProduct.add_tprodCoeff'
+-/
 
+#print PiTensorProduct.smul_tprodCoeff_aux /-
 theorem smul_tprodCoeff_aux [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r : R) :
     tprodCoeff R z (update f i (r • f i)) = tprodCoeff R (r * z) f :=
   Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_smul _ _ _ _ _
 #align pi_tensor_product.smul_tprod_coeff_aux PiTensorProduct.smul_tprodCoeff_aux
+-/
 
+#print PiTensorProduct.smul_tprodCoeff /-
 theorem smul_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r : R₁) [SMul R₁ R]
     [IsScalarTower R₁ R R] [SMul R₁ (s i)] [IsScalarTower R₁ R (s i)] :
     tprodCoeff R z (update f i (r • f i)) = tprodCoeff R (r • z) f :=
@@ -194,7 +202,9 @@ theorem smul_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r :
   rw [h₁, h₂]
   exact smul_tprod_coeff_aux z f i _
 #align pi_tensor_product.smul_tprod_coeff PiTensorProduct.smul_tprodCoeff
+-/
 
+#print PiTensorProduct.liftAddHom /-
 /-- Construct an `add_monoid_hom` from `(⨂[R] i, s i)` to some space `F` from a function
 `φ : (R × Π i, s i) → F` with the appropriate properties. -/
 def liftAddHom (φ : (R × ∀ i, s i) → F)
@@ -224,7 +234,9 @@ def liftAddHom (φ : (R × ∀ i, s i) → F)
       | _, _, eqv.add_comm x y =>
         (AddCon.ker_rel _).2 <| by simp_rw [AddMonoidHom.map_add, add_comm]
 #align pi_tensor_product.lift_add_hom PiTensorProduct.liftAddHom
+-/
 
+#print PiTensorProduct.induction_on' /-
 @[elab_as_elim]
 protected theorem induction_on' {C : ⨂[R] i, s i → Prop} (z : ⨂[R] i, s i)
     (C1 : ∀ {r : R} {f : ∀ i, s i}, C (tprodCoeff R r f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
@@ -239,6 +251,7 @@ protected theorem induction_on' {C : ⨂[R] i, s i → Prop} (z : ⨂[R] i, s i)
   convert @C1 f.1 f.2
   simp only [Prod.mk.eta]
 #align pi_tensor_product.induction_on' PiTensorProduct.induction_on'
+-/
 
 section DistribMulAction
 
@@ -246,6 +259,7 @@ variable [Monoid R₁] [DistribMulAction R₁ R] [SMulCommClass R₁ R R]
 
 variable [Monoid R₂] [DistribMulAction R₂ R] [SMulCommClass R₂ R R]
 
+#print PiTensorProduct.hasSmul' /-
 -- Most of the time we want the instance below this one, which is easier for typeclass resolution
 -- to find.
 instance hasSmul' : SMul R₁ (⨂[R] i, s i) :=
@@ -256,19 +270,25 @@ instance hasSmul' : SMul R₁ (⨂[R] i, s i) :=
       (fun r' r'' f => by simp [add_tprod_coeff', mul_add]) fun z f i r' => by
       simp [smul_tprod_coeff, mul_smul_comm]⟩
 #align pi_tensor_product.has_smul' PiTensorProduct.hasSmul'
+-/
 
 instance : SMul R (⨂[R] i, s i) :=
   PiTensorProduct.hasSmul'
 
+#print PiTensorProduct.smul_tprodCoeff' /-
 theorem smul_tprodCoeff' (r : R₁) (z : R) (f : ∀ i, s i) :
     r • tprodCoeff R z f = tprodCoeff R (r • z) f :=
   rfl
 #align pi_tensor_product.smul_tprod_coeff' PiTensorProduct.smul_tprodCoeff'
+-/
 
+#print PiTensorProduct.smul_add /-
 protected theorem smul_add (r : R₁) (x y : ⨂[R] i, s i) : r • (x + y) = r • x + r • y :=
   AddMonoidHom.map_add _ _ _
 #align pi_tensor_product.smul_add PiTensorProduct.smul_add
+-/
 
+#print PiTensorProduct.distribMulAction' /-
 instance distribMulAction' : DistribMulAction R₁ (⨂[R] i, s i)
     where
   smul := (· • ·)
@@ -281,21 +301,27 @@ instance distribMulAction' : DistribMulAction R₁ (⨂[R] i, s i)
       simp_rw [PiTensorProduct.smul_add, ihz, ihy]
   smul_zero r := AddMonoidHom.map_zero _
 #align pi_tensor_product.distrib_mul_action' PiTensorProduct.distribMulAction'
+-/
 
+#print PiTensorProduct.smulCommClass' /-
 instance smulCommClass' [SMulCommClass R₁ R₂ R] : SMulCommClass R₁ R₂ (⨂[R] i, s i) :=
   ⟨fun r' r'' x =>
     PiTensorProduct.induction_on' x (fun xr xf => by simp only [smul_tprod_coeff', smul_comm])
       fun z y ihz ihy => by simp_rw [PiTensorProduct.smul_add, ihz, ihy]⟩
 #align pi_tensor_product.smul_comm_class' PiTensorProduct.smulCommClass'
+-/
 
+#print PiTensorProduct.isScalarTower' /-
 instance isScalarTower' [SMul R₁ R₂] [IsScalarTower R₁ R₂ R] : IsScalarTower R₁ R₂ (⨂[R] i, s i) :=
   ⟨fun r' r'' x =>
     PiTensorProduct.induction_on' x (fun xr xf => by simp only [smul_tprod_coeff', smul_assoc])
       fun z y ihz ihy => by simp_rw [PiTensorProduct.smul_add, ihz, ihy]⟩
 #align pi_tensor_product.is_scalar_tower' PiTensorProduct.isScalarTower'
+-/
 
 end DistribMulAction
 
+#print PiTensorProduct.module' /-
 -- Most of the time we want the instance below this one, which is easier for typeclass resolution
 -- to find.
 instance module' [Semiring R₁] [Module R₁ R] [SMulCommClass R₁ R R] : Module R₁ (⨂[R] i, s i) :=
@@ -310,6 +336,7 @@ instance module' [Semiring R₁] [Module R₁ R] [SMulCommClass R₁ R R] : Modu
         (fun r f => by simp_rw [smul_tprod_coeff' _ _, zero_smul]; exact zero_tprod_coeff _)
         fun x y ihx ihy => by rw [PiTensorProduct.smul_add, ihx, ihy, add_zero] }
 #align pi_tensor_product.module' PiTensorProduct.module'
+-/
 
 -- shortcut instances
 instance : Module R (⨂[R] i, s i) :=
@@ -325,6 +352,7 @@ variable {R}
 
 variable (R)
 
+#print PiTensorProduct.tprod /-
 /-- The canonical `multilinear_map R s (⨂[R] i, s i)`. -/
 def tprod : MultilinearMap R s (⨂[R] i, s i)
     where
@@ -333,12 +361,13 @@ def tprod : MultilinearMap R s (⨂[R] i, s i)
   map_smul' _ f i r x := by
     skip <;> simp_rw [smul_tprod_coeff', ← smul_tprod_coeff (1 : R) _ i, update_idem, update_same]
 #align pi_tensor_product.tprod PiTensorProduct.tprod
+-/
 
 variable {R}
 
--- mathport name: «expr⨂ₜ[ ] , »
 notation3:100"⨂ₜ["R"] "(...)", "r:67:(scoped f => tprod R f) => r
 
+#print PiTensorProduct.tprodCoeff_eq_smul_tprod /-
 @[simp]
 theorem tprodCoeff_eq_smul_tprod (z : R) (f : ∀ i, s i) : tprodCoeff R z f = z • tprod R f :=
   by
@@ -347,7 +376,9 @@ theorem tprodCoeff_eq_smul_tprod (z : R) (f : ∀ i, s i) : tprodCoeff R z f = z
   rw [← smul_tprod_coeff']
   rfl
 #align pi_tensor_product.tprod_coeff_eq_smul_tprod PiTensorProduct.tprodCoeff_eq_smul_tprod
+-/
 
+#print PiTensorProduct.induction_on /-
 @[elab_as_elim]
 protected theorem induction_on {C : ⨂[R] i, s i → Prop} (z : ⨂[R] i, s i)
     (C1 : ∀ {r : R} {f : ∀ i, s i}, C (r • tprod R f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
@@ -355,7 +386,9 @@ protected theorem induction_on {C : ⨂[R] i, s i → Prop} (z : ⨂[R] i, s i)
   simp_rw [← tprod_coeff_eq_smul_tprod] at C1 
   exact PiTensorProduct.induction_on' z @C1 @Cp
 #align pi_tensor_product.induction_on PiTensorProduct.induction_on
+-/
 
+#print PiTensorProduct.ext /-
 @[ext]
 theorem ext {φ₁ φ₂ : ⨂[R] i, s i →ₗ[R] E}
     (H : φ₁.compMultilinearMap (tprod R) = φ₂.compMultilinearMap (tprod R)) : φ₁ = φ₂ :=
@@ -368,6 +401,7 @@ theorem ext {φ₁ φ₂ : ⨂[R] i, s i →ₗ[R] E}
     apply _root_.congr_arg
     exact MultilinearMap.congr_fun H f
 #align pi_tensor_product.ext PiTensorProduct.ext
+-/
 
 end Module
 
@@ -377,6 +411,7 @@ open MultilinearMap
 
 variable {s}
 
+#print PiTensorProduct.liftAux /-
 /-- Auxiliary function to constructing a linear map `(⨂[R] i, s i) → E` given a
 `multilinear map R s E` with the property that its composition with the canonical
 `multilinear_map R s (⨂[R] i, s i)` is the given multilinear map. -/
@@ -386,17 +421,23 @@ def liftAux (φ : MultilinearMap R s E) : ⨂[R] i, s i →+ E :=
     (fun _ z f i m₁ m₂ => by skip; rw [← smul_add, φ.map_add]) (fun z₁ z₂ f => by rw [← add_smul])
     fun _ z f i r => by skip; simp [φ.map_smul, smul_smul, mul_comm]
 #align pi_tensor_product.lift_aux PiTensorProduct.liftAux
+-/
 
+#print PiTensorProduct.liftAux_tprod /-
 theorem liftAux_tprod (φ : MultilinearMap R s E) (f : ∀ i, s i) : liftAux φ (tprod R f) = φ f := by
   simp only [lift_aux, lift_add_hom, tprod, MultilinearMap.coe_mk, tprod_coeff,
     FreeAddMonoid.lift_eval_of, one_smul, AddCon.lift_mk']
 #align pi_tensor_product.lift_aux_tprod PiTensorProduct.liftAux_tprod
+-/
 
+#print PiTensorProduct.liftAux_tprodCoeff /-
 theorem liftAux_tprodCoeff (φ : MultilinearMap R s E) (z : R) (f : ∀ i, s i) :
     liftAux φ (tprodCoeff R z f) = z • φ f := by
   simp [lift_aux, lift_add_hom, tprod_coeff, FreeAddMonoid.lift_eval_of]
 #align pi_tensor_product.lift_aux_tprod_coeff PiTensorProduct.liftAux_tprodCoeff
+-/
 
+#print PiTensorProduct.liftAux.smul /-
 theorem liftAux.smul {φ : MultilinearMap R s E} (r : R) (x : ⨂[R] i, s i) :
     liftAux φ (r • x) = r • liftAux φ x :=
   by
@@ -406,7 +447,9 @@ theorem liftAux.smul {φ : MultilinearMap R s E} (r : R) (x : ⨂[R] i, s i) :
   · intro z y ihz ihy
     rw [smul_add, (lift_aux φ).map_add, ihz, ihy, (lift_aux φ).map_add, smul_add]
 #align pi_tensor_product.lift_aux.smul PiTensorProduct.liftAux.smul
+-/
 
+#print PiTensorProduct.lift /-
 /-- Constructing a linear map `(⨂[R] i, s i) → E` given a `multilinear_map R s E` with the
 property that its composition with the canonical `multilinear_map R s E` is
 the given multilinear map `φ`. -/
@@ -419,37 +462,49 @@ def lift : MultilinearMap R s E ≃ₗ[R] ⨂[R] i, s i →ₗ[R] E
   map_add' φ₁ φ₂ := by ext; simp [lift_aux_tprod]
   map_smul' r φ₂ := by ext; simp [lift_aux_tprod]
 #align pi_tensor_product.lift PiTensorProduct.lift
+-/
 
 variable {φ : MultilinearMap R s E}
 
+#print PiTensorProduct.lift.tprod /-
 @[simp]
 theorem lift.tprod (f : ∀ i, s i) : lift φ (tprod R f) = φ f :=
   liftAux_tprod φ f
 #align pi_tensor_product.lift.tprod PiTensorProduct.lift.tprod
+-/
 
+#print PiTensorProduct.lift.unique' /-
 theorem lift.unique' {φ' : ⨂[R] i, s i →ₗ[R] E} (H : φ'.compMultilinearMap (tprod R) = φ) :
     φ' = lift φ :=
   ext <| H.symm ▸ (lift.symm_apply_apply φ).symm
 #align pi_tensor_product.lift.unique' PiTensorProduct.lift.unique'
+-/
 
+#print PiTensorProduct.lift.unique /-
 theorem lift.unique {φ' : ⨂[R] i, s i →ₗ[R] E} (H : ∀ f, φ' (tprod R f) = φ f) : φ' = lift φ :=
   lift.unique' (MultilinearMap.ext H)
 #align pi_tensor_product.lift.unique PiTensorProduct.lift.unique
+-/
 
+#print PiTensorProduct.lift_symm /-
 @[simp]
 theorem lift_symm (φ' : ⨂[R] i, s i →ₗ[R] E) : lift.symm φ' = φ'.compMultilinearMap (tprod R) :=
   rfl
 #align pi_tensor_product.lift_symm PiTensorProduct.lift_symm
+-/
 
+#print PiTensorProduct.lift_tprod /-
 @[simp]
 theorem lift_tprod : lift (tprod R : MultilinearMap R s _) = LinearMap.id :=
   Eq.symm <| lift.unique' rfl
 #align pi_tensor_product.lift_tprod PiTensorProduct.lift_tprod
+-/
 
 section
 
 variable (R M)
 
+#print PiTensorProduct.reindex /-
 /-- Re-index the components of the tensor power by `e`.
 
 For simplicity, this is defined only for homogeneously- (rather than dependently-) typed components.
@@ -466,33 +521,43 @@ def reindex (e : ι ≃ ι₂) : ⨂[R] i : ι, M ≃ₗ[R] ⨂[R] i : ι₂, M
         LinearMap.compMultilinearMap_apply, lift.tprod, dom_dom_congr_apply,
         Equiv.symm_apply_apply])
 #align pi_tensor_product.reindex PiTensorProduct.reindex
+-/
 
 end
 
+#print PiTensorProduct.reindex_tprod /-
 @[simp]
 theorem reindex_tprod (e : ι ≃ ι₂) (f : ∀ i, M) :
     reindex R M e (tprod R f) = tprod R fun i => f (e.symm i) :=
   liftAux_tprod _ f
 #align pi_tensor_product.reindex_tprod PiTensorProduct.reindex_tprod
+-/
 
+#print PiTensorProduct.reindex_comp_tprod /-
 @[simp]
 theorem reindex_comp_tprod (e : ι ≃ ι₂) :
     (reindex R M e : ⨂[R] i : ι, M →ₗ[R] ⨂[R] i : ι₂, M).compMultilinearMap (tprod R) =
       (tprod R : MultilinearMap R (fun i => M) _).domDomCongr e.symm :=
   MultilinearMap.ext <| reindex_tprod e
 #align pi_tensor_product.reindex_comp_tprod PiTensorProduct.reindex_comp_tprod
+-/
 
+#print PiTensorProduct.lift_comp_reindex /-
 @[simp]
 theorem lift_comp_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ : ι₂ => M) E) :
     lift φ ∘ₗ ↑(reindex R M e) = lift (φ.domDomCongr e.symm) := by ext; simp
 #align pi_tensor_product.lift_comp_reindex PiTensorProduct.lift_comp_reindex
+-/
 
+#print PiTensorProduct.lift_reindex /-
 @[simp]
 theorem lift_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ => M) E) (x : ⨂[R] i, M) :
     lift φ (reindex R M e x) = lift (φ.domDomCongr e.symm) x :=
   LinearMap.congr_fun (lift_comp_reindex e φ) x
 #align pi_tensor_product.lift_reindex PiTensorProduct.lift_reindex
+-/
 
+#print PiTensorProduct.reindex_trans /-
 @[simp]
 theorem reindex_trans (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) :
     (reindex R M e).trans (reindex R M e') = reindex R M (e.trans e') :=
@@ -504,18 +569,24 @@ theorem reindex_trans (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) :
     reindex_comp_tprod]
   congr
 #align pi_tensor_product.reindex_trans PiTensorProduct.reindex_trans
+-/
 
+#print PiTensorProduct.reindex_reindex /-
 @[simp]
 theorem reindex_reindex (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) (x : ⨂[R] i, M) :
     reindex R M e' (reindex R M e x) = reindex R M (e.trans e') x :=
   LinearEquiv.congr_fun (reindex_trans e e' : _ = reindex R M (e.trans e')) x
 #align pi_tensor_product.reindex_reindex PiTensorProduct.reindex_reindex
+-/
 
+#print PiTensorProduct.reindex_symm /-
 @[simp]
 theorem reindex_symm (e : ι ≃ ι₂) : (reindex R M e).symm = reindex R M e.symm :=
   rfl
 #align pi_tensor_product.reindex_symm PiTensorProduct.reindex_symm
+-/
 
+#print PiTensorProduct.reindex_refl /-
 @[simp]
 theorem reindex_refl : reindex R M (Equiv.refl ι) = LinearEquiv.refl R _ :=
   by
@@ -524,9 +595,11 @@ theorem reindex_refl : reindex R M (Equiv.refl ι) = LinearEquiv.refl R _ :=
   rw [reindex_comp_tprod, LinearEquiv.refl_toLinearMap, Equiv.refl_symm]
   rfl
 #align pi_tensor_product.reindex_refl PiTensorProduct.reindex_refl
+-/
 
 variable (ι)
 
+#print PiTensorProduct.isEmptyEquiv /-
 /-- The tensor product over an empty index type `ι` is isomorphic to the base ring. -/
 @[simps symm_apply]
 def isEmptyEquiv [IsEmpty ι] : ⨂[R] i : ι, M ≃ₗ[R] R
@@ -547,14 +620,18 @@ def isEmptyEquiv [IsEmpty ι] : ⨂[R] i : ι, M ≃ₗ[R] R
   map_add' := LinearMap.map_add _
   map_smul' := LinearMap.map_smul _
 #align pi_tensor_product.is_empty_equiv PiTensorProduct.isEmptyEquiv
+-/
 
+#print PiTensorProduct.isEmptyEquiv_apply_tprod /-
 @[simp]
 theorem isEmptyEquiv_apply_tprod [IsEmpty ι] (f : ι → M) : isEmptyEquiv ι (tprod R f) = 1 :=
   lift.tprod _
 #align pi_tensor_product.is_empty_equiv_apply_tprod PiTensorProduct.isEmptyEquiv_apply_tprod
+-/
 
 variable {ι}
 
+#print PiTensorProduct.subsingletonEquiv /-
 /-- The tensor product over an single index is isomorphic to the module -/
 @[simps symm_apply]
 def subsingletonEquiv [Subsingleton ι] (i₀ : ι) : ⨂[R] i : ι, M ≃ₗ[R] M
@@ -579,12 +656,15 @@ def subsingletonEquiv [Subsingleton ι] (i₀ : ι) : ⨂[R] i : ι, M ≃ₗ[R]
   map_add' := LinearMap.map_add _
   map_smul' := LinearMap.map_smul _
 #align pi_tensor_product.subsingleton_equiv PiTensorProduct.subsingletonEquiv
+-/
 
+#print PiTensorProduct.subsingletonEquiv_apply_tprod /-
 @[simp]
 theorem subsingletonEquiv_apply_tprod [Subsingleton ι] (i : ι) (f : ι → M) :
     subsingletonEquiv i (tprod R f) = f i :=
   lift.tprod _
 #align pi_tensor_product.subsingleton_equiv_apply_tprod PiTensorProduct.subsingletonEquiv_apply_tprod
+-/
 
 section Tmul
 
@@ -618,6 +698,7 @@ variable (R M)
 
 attribute [local ext] TensorProduct.ext
 
+#print PiTensorProduct.tmulEquiv /-
 /-- Equivalence between a `tensor_product` of `pi_tensor_product`s and a single
 `pi_tensor_product` indexed by a `sum` type.
 
@@ -635,18 +716,23 @@ def tmulEquiv : (⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M ≃ₗ[R] ⨂[R] i
       show tmul_symm (tmul (tprod R x ⊗ₜ[R] tprod R y)) = tprod R x ⊗ₜ[R] tprod R y
       simp only [tmul_apply, tmul_symm_apply, Sum.elim_inl, Sum.elim_inr])
 #align pi_tensor_product.tmul_equiv PiTensorProduct.tmulEquiv
+-/
 
+#print PiTensorProduct.tmulEquiv_apply /-
 @[simp]
 theorem tmulEquiv_apply (a : ι → M) (b : ι₂ → M) :
     tmulEquiv R M ((⨂ₜ[R] i, a i) ⊗ₜ[R] ⨂ₜ[R] i, b i) = ⨂ₜ[R] i, Sum.elim a b i :=
   tmul_apply a b
 #align pi_tensor_product.tmul_equiv_apply PiTensorProduct.tmulEquiv_apply
+-/
 
+#print PiTensorProduct.tmulEquiv_symm_apply /-
 @[simp]
 theorem tmulEquiv_symm_apply (a : Sum ι ι₂ → M) :
     (tmulEquiv R M).symm (⨂ₜ[R] i, a i) = (⨂ₜ[R] i, a (Sum.inl i)) ⊗ₜ[R] ⨂ₜ[R] i, a (Sum.inr i) :=
   tmulSymm_apply a
 #align pi_tensor_product.tmul_equiv_symm_apply PiTensorProduct.tmulEquiv_symm_apply
+-/
 
 end Tmul
 
Diff
@@ -131,7 +131,7 @@ variable {R}
 
 -- mathport name: pi_tensor_product
 -- This enables the notation `⨂[R] i : ι, s i` for the pi tensor product, given `s : ι → Type*`.
-scoped[TensorProduct] notation3:100"⨂["R"] "(...)", "r:(scoped f => PiTensorProduct R f) => r
+scoped[TensorProduct] notation3:100"⨂["R"] "(...)", "r:67:(scoped f => PiTensorProduct R f) => r
 
 open scoped TensorProduct
 
@@ -207,7 +207,7 @@ def liftAddHom (φ : (R × ∀ i, s i) → F)
     (C_smul :
       ∀ [DecidableEq ι] (r : R) (f : ∀ i, s i) (i : ι) (r' : R),
         φ (r, update f i (r' • f i)) = φ (r' * r, f)) :
-    (⨂[R] i, s i) →+ F :=
+    ⨂[R] i, s i →+ F :=
   (addConGen (PiTensorProduct.Eqv R s)).lift (FreeAddMonoid.lift φ) <|
     AddCon.addConGen_le fun x y hxy =>
       match x, y, hxy with
@@ -226,7 +226,7 @@ def liftAddHom (φ : (R × ∀ i, s i) → F)
 #align pi_tensor_product.lift_add_hom PiTensorProduct.liftAddHom
 
 @[elab_as_elim]
-protected theorem induction_on' {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i)
+protected theorem induction_on' {C : ⨂[R] i, s i → Prop} (z : ⨂[R] i, s i)
     (C1 : ∀ {r : R} {f : ∀ i, s i}, C (tprodCoeff R r f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
     C z :=
   by
@@ -337,7 +337,7 @@ def tprod : MultilinearMap R s (⨂[R] i, s i)
 variable {R}
 
 -- mathport name: «expr⨂ₜ[ ] , »
-notation3:100"⨂ₜ["R"] "(...)", "r:(scoped f => tprod R f) => r
+notation3:100"⨂ₜ["R"] "(...)", "r:67:(scoped f => tprod R f) => r
 
 @[simp]
 theorem tprodCoeff_eq_smul_tprod (z : R) (f : ∀ i, s i) : tprodCoeff R z f = z • tprod R f :=
@@ -349,7 +349,7 @@ theorem tprodCoeff_eq_smul_tprod (z : R) (f : ∀ i, s i) : tprodCoeff R z f = z
 #align pi_tensor_product.tprod_coeff_eq_smul_tprod PiTensorProduct.tprodCoeff_eq_smul_tprod
 
 @[elab_as_elim]
-protected theorem induction_on {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i)
+protected theorem induction_on {C : ⨂[R] i, s i → Prop} (z : ⨂[R] i, s i)
     (C1 : ∀ {r : R} {f : ∀ i, s i}, C (r • tprod R f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
     C z := by
   simp_rw [← tprod_coeff_eq_smul_tprod] at C1 
@@ -357,7 +357,7 @@ protected theorem induction_on {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i
 #align pi_tensor_product.induction_on PiTensorProduct.induction_on
 
 @[ext]
-theorem ext {φ₁ φ₂ : (⨂[R] i, s i) →ₗ[R] E}
+theorem ext {φ₁ φ₂ : ⨂[R] i, s i →ₗ[R] E}
     (H : φ₁.compMultilinearMap (tprod R) = φ₂.compMultilinearMap (tprod R)) : φ₁ = φ₂ :=
   by
   refine' LinearMap.ext _
@@ -380,7 +380,7 @@ variable {s}
 /-- Auxiliary function to constructing a linear map `(⨂[R] i, s i) → E` given a
 `multilinear map R s E` with the property that its composition with the canonical
 `multilinear_map R s (⨂[R] i, s i)` is the given multilinear map. -/
-def liftAux (φ : MultilinearMap R s E) : (⨂[R] i, s i) →+ E :=
+def liftAux (φ : MultilinearMap R s E) : ⨂[R] i, s i →+ E :=
   liftAddHom (fun p : R × ∀ i, s i => p.1 • φ p.2)
     (fun z f i hf => by rw [map_coord_zero φ i hf, smul_zero]) (fun f => by rw [zero_smul])
     (fun _ z f i m₁ m₂ => by skip; rw [← smul_add, φ.map_add]) (fun z₁ z₂ f => by rw [← add_smul])
@@ -410,7 +410,7 @@ theorem liftAux.smul {φ : MultilinearMap R s E} (r : R) (x : ⨂[R] i, s i) :
 /-- Constructing a linear map `(⨂[R] i, s i) → E` given a `multilinear_map R s E` with the
 property that its composition with the canonical `multilinear_map R s E` is
 the given multilinear map `φ`. -/
-def lift : MultilinearMap R s E ≃ₗ[R] (⨂[R] i, s i) →ₗ[R] E
+def lift : MultilinearMap R s E ≃ₗ[R] ⨂[R] i, s i →ₗ[R] E
     where
   toFun φ := { liftAux φ with map_smul' := liftAux.smul }
   invFun φ' := φ'.compMultilinearMap (tprod R)
@@ -427,17 +427,17 @@ theorem lift.tprod (f : ∀ i, s i) : lift φ (tprod R f) = φ f :=
   liftAux_tprod φ f
 #align pi_tensor_product.lift.tprod PiTensorProduct.lift.tprod
 
-theorem lift.unique' {φ' : (⨂[R] i, s i) →ₗ[R] E} (H : φ'.compMultilinearMap (tprod R) = φ) :
+theorem lift.unique' {φ' : ⨂[R] i, s i →ₗ[R] E} (H : φ'.compMultilinearMap (tprod R) = φ) :
     φ' = lift φ :=
   ext <| H.symm ▸ (lift.symm_apply_apply φ).symm
 #align pi_tensor_product.lift.unique' PiTensorProduct.lift.unique'
 
-theorem lift.unique {φ' : (⨂[R] i, s i) →ₗ[R] E} (H : ∀ f, φ' (tprod R f) = φ f) : φ' = lift φ :=
+theorem lift.unique {φ' : ⨂[R] i, s i →ₗ[R] E} (H : ∀ f, φ' (tprod R f) = φ f) : φ' = lift φ :=
   lift.unique' (MultilinearMap.ext H)
 #align pi_tensor_product.lift.unique PiTensorProduct.lift.unique
 
 @[simp]
-theorem lift_symm (φ' : (⨂[R] i, s i) →ₗ[R] E) : lift.symm φ' = φ'.compMultilinearMap (tprod R) :=
+theorem lift_symm (φ' : ⨂[R] i, s i →ₗ[R] E) : lift.symm φ' = φ'.compMultilinearMap (tprod R) :=
   rfl
 #align pi_tensor_product.lift_symm PiTensorProduct.lift_symm
 
@@ -454,7 +454,7 @@ variable (R M)
 
 For simplicity, this is defined only for homogeneously- (rather than dependently-) typed components.
 -/
-def reindex (e : ι ≃ ι₂) : (⨂[R] i : ι, M) ≃ₗ[R] ⨂[R] i : ι₂, M :=
+def reindex (e : ι ≃ ι₂) : ⨂[R] i : ι, M ≃ₗ[R] ⨂[R] i : ι₂, M :=
   LinearEquiv.ofLinear (lift (domDomCongr e.symm (tprod R : MultilinearMap R _ (⨂[R] i : ι₂, M))))
     (lift (domDomCongr e (tprod R : MultilinearMap R _ (⨂[R] i : ι, M))))
     (by ext;
@@ -477,7 +477,7 @@ theorem reindex_tprod (e : ι ≃ ι₂) (f : ∀ i, M) :
 
 @[simp]
 theorem reindex_comp_tprod (e : ι ≃ ι₂) :
-    (reindex R M e : (⨂[R] i : ι, M) →ₗ[R] ⨂[R] i : ι₂, M).compMultilinearMap (tprod R) =
+    (reindex R M e : ⨂[R] i : ι, M →ₗ[R] ⨂[R] i : ι₂, M).compMultilinearMap (tprod R) =
       (tprod R : MultilinearMap R (fun i => M) _).domDomCongr e.symm :=
   MultilinearMap.ext <| reindex_tprod e
 #align pi_tensor_product.reindex_comp_tprod PiTensorProduct.reindex_comp_tprod
@@ -529,7 +529,7 @@ variable (ι)
 
 /-- The tensor product over an empty index type `ι` is isomorphic to the base ring. -/
 @[simps symm_apply]
-def isEmptyEquiv [IsEmpty ι] : (⨂[R] i : ι, M) ≃ₗ[R] R
+def isEmptyEquiv [IsEmpty ι] : ⨂[R] i : ι, M ≃ₗ[R] R
     where
   toFun := lift (constOfIsEmpty R _ 1)
   invFun r := r • tprod R (@isEmptyElim _ _ _)
@@ -557,7 +557,7 @@ variable {ι}
 
 /-- The tensor product over an single index is isomorphic to the module -/
 @[simps symm_apply]
-def subsingletonEquiv [Subsingleton ι] (i₀ : ι) : (⨂[R] i : ι, M) ≃ₗ[R] M
+def subsingletonEquiv [Subsingleton ι] (i₀ : ι) : ⨂[R] i : ι, M ≃ₗ[R] M
     where
   toFun := lift (MultilinearMap.ofSubsingleton R M i₀)
   invFun m := tprod R fun v => m
@@ -589,7 +589,7 @@ theorem subsingletonEquiv_apply_tprod [Subsingleton ι] (i : ι) (f : ι → M)
 section Tmul
 
 /-- Collapse a `tensor_product` of `pi_tensor_product`s. -/
-private def tmul : ((⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M) →ₗ[R] ⨂[R] i : Sum ι ι₂, M :=
+private def tmul : (⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M →ₗ[R] ⨂[R] i : Sum ι ι₂, M :=
   TensorProduct.lift
     { toFun := fun a =>
         PiTensorProduct.lift <|
@@ -605,7 +605,7 @@ private theorem tmul_apply (a : ι → M) (b : ι₂ → M) :
   rfl
 
 /-- Expand `pi_tensor_product` into a `tensor_product` of two factors. -/
-private def tmul_symm : (⨂[R] i : Sum ι ι₂, M) →ₗ[R] (⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M :=
+private def tmul_symm : ⨂[R] i : Sum ι ι₂, M →ₗ[R] (⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M :=
   -- by using tactic mode, we avoid the need for a lot of `@`s and `_`s
     PiTensorProduct.lift <|
     by apply MultilinearMap.domCoprod <;> [exact tprod R; exact tprod R]
@@ -623,7 +623,7 @@ attribute [local ext] TensorProduct.ext
 
 For simplicity, this is defined only for homogeneously- (rather than dependently-) typed components.
 -/
-def tmulEquiv : ((⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M) ≃ₗ[R] ⨂[R] i : Sum ι ι₂, M :=
+def tmulEquiv : (⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M ≃ₗ[R] ⨂[R] i : Sum ι ι₂, M :=
   LinearEquiv.ofLinear tmul tmulSymm
     (by
       ext x
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Frédéric Dupuis, Eric Wieser
 
 ! This file was ported from Lean 3 source module linear_algebra.pi_tensor_product
-! leanprover-community/mathlib commit ce11c3c2a285bbe6937e26d9792fda4e51f3fe1a
+! leanprover-community/mathlib commit 5c1efce12ba86d4901463f61019832f6a4b1a0d0
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -14,6 +14,9 @@ import Mathbin.LinearAlgebra.Multilinear.TensorProduct
 /-!
 # Tensor product of an indexed family of modules over commutative semirings
 
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
+
 We define the tensor product of an indexed family `s : ι → Type*` of modules over commutative
 semirings. We denote this space by `⨂[R] i, s i` and define it as `free_add_monoid (R × Π i, s i)`
 quotiented by the appropriate equivalence relation. The treatment follows very closely that of the
@@ -89,6 +92,7 @@ include R
 
 variable (R) (s)
 
+#print PiTensorProduct.Eqv /-
 /-- The relation on `free_add_monoid (R × Π i, s i)` that generates a congruence whose quotient is
 the tensor product. -/
 inductive Eqv : FreeAddMonoid (R × ∀ i, s i) → FreeAddMonoid (R × ∀ i, s i) → Prop
@@ -109,16 +113,19 @@ inductive Eqv : FreeAddMonoid (R × ∀ i, s i) → FreeAddMonoid (R × ∀ i, s
       eqv (FreeAddMonoid.of (r, update f i (r' • f i))) (FreeAddMonoid.of (r' * r, f))
   | add_comm : ∀ x y, eqv (x + y) (y + x)
 #align pi_tensor_product.eqv PiTensorProduct.Eqv
+-/
 
 end PiTensorProduct
 
 variable (R) (s)
 
+#print PiTensorProduct /-
 /-- `pi_tensor_product R s` with `R` a commutative semiring and `s : ι → Type*` is the tensor
   product of all the `s i`'s. This is denoted by `⨂[R] i, s i`. -/
 def PiTensorProduct : Type _ :=
   (addConGen (PiTensorProduct.Eqv R s)).Quotient
 #align pi_tensor_product PiTensorProduct
+-/
 
 variable {R}
 
@@ -143,12 +150,14 @@ instance : Inhabited (⨂[R] i, s i) :=
 
 variable (R) {s}
 
+#print PiTensorProduct.tprodCoeff /-
 /-- `tprod_coeff R r f` with `r : R` and `f : Π i, s i` is the tensor product of the vectors `f i`
 over all `i : ι`, multiplied by the coefficient `r`. Note that this is meant as an auxiliary
 definition for this file alone, and that one should use `tprod` defined below for most purposes. -/
 def tprodCoeff (r : R) (f : ∀ i, s i) : ⨂[R] i, s i :=
   AddCon.mk' _ <| FreeAddMonoid.of (r, f)
 #align pi_tensor_product.tprod_coeff PiTensorProduct.tprodCoeff
+-/
 
 variable {R}
 
@@ -156,9 +165,9 @@ theorem zero_tprodCoeff (f : ∀ i, s i) : tprodCoeff R 0 f = 0 :=
   Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_zero_scalar _
 #align pi_tensor_product.zero_tprod_coeff PiTensorProduct.zero_tprodCoeff
 
-theorem zero_tprod_coeff' (z : R) (f : ∀ i, s i) (i : ι) (hf : f i = 0) : tprodCoeff R z f = 0 :=
+theorem zero_tprodCoeff' (z : R) (f : ∀ i, s i) (i : ι) (hf : f i = 0) : tprodCoeff R z f = 0 :=
   Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_zero _ _ i hf
-#align pi_tensor_product.zero_tprod_coeff' PiTensorProduct.zero_tprod_coeff'
+#align pi_tensor_product.zero_tprod_coeff' PiTensorProduct.zero_tprodCoeff'
 
 theorem add_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i) :
     tprodCoeff R z (update f i m₁) + tprodCoeff R z (update f i m₂) =
@@ -166,10 +175,10 @@ theorem add_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (m₁
   Quotient.sound' <| AddConGen.Rel.of _ _ (Eqv.of_add _ z f i m₁ m₂)
 #align pi_tensor_product.add_tprod_coeff PiTensorProduct.add_tprodCoeff
 
-theorem add_tprod_coeff' (z₁ z₂ : R) (f : ∀ i, s i) :
+theorem add_tprodCoeff' (z₁ z₂ : R) (f : ∀ i, s i) :
     tprodCoeff R z₁ f + tprodCoeff R z₂ f = tprodCoeff R (z₁ + z₂) f :=
   Quotient.sound' <| AddConGen.Rel.of _ _ (Eqv.of_add_scalar z₁ z₂ f)
-#align pi_tensor_product.add_tprod_coeff' PiTensorProduct.add_tprod_coeff'
+#align pi_tensor_product.add_tprod_coeff' PiTensorProduct.add_tprodCoeff'
 
 theorem smul_tprodCoeff_aux [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r : R) :
     tprodCoeff R z (update f i (r • f i)) = tprodCoeff R (r * z) f :=
@@ -227,7 +236,7 @@ protected theorem induction_on' {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s
   refine' AddCon.induction_on z fun x => FreeAddMonoid.recOn x C0 _
   simp_rw [AddCon.coe_add]
   refine' fun f y ih => Cp _ ih
-  convert@C1 f.1 f.2
+  convert @C1 f.1 f.2
   simp only [Prod.mk.eta]
 #align pi_tensor_product.induction_on' PiTensorProduct.induction_on'
 
@@ -251,10 +260,10 @@ instance hasSmul' : SMul R₁ (⨂[R] i, s i) :=
 instance : SMul R (⨂[R] i, s i) :=
   PiTensorProduct.hasSmul'
 
-theorem smul_tprod_coeff' (r : R₁) (z : R) (f : ∀ i, s i) :
+theorem smul_tprodCoeff' (r : R₁) (z : R) (f : ∀ i, s i) :
     r • tprodCoeff R z f = tprodCoeff R (r • z) f :=
   rfl
-#align pi_tensor_product.smul_tprod_coeff' PiTensorProduct.smul_tprod_coeff'
+#align pi_tensor_product.smul_tprod_coeff' PiTensorProduct.smul_tprodCoeff'
 
 protected theorem smul_add (r : R₁) (x y : ⨂[R] i, s i) : r • (x + y) = r • x + r • y :=
   AddMonoidHom.map_add _ _ _
@@ -273,18 +282,17 @@ instance distribMulAction' : DistribMulAction R₁ (⨂[R] i, s i)
   smul_zero r := AddMonoidHom.map_zero _
 #align pi_tensor_product.distrib_mul_action' PiTensorProduct.distribMulAction'
 
-instance smul_comm_class' [SMulCommClass R₁ R₂ R] : SMulCommClass R₁ R₂ (⨂[R] i, s i) :=
+instance smulCommClass' [SMulCommClass R₁ R₂ R] : SMulCommClass R₁ R₂ (⨂[R] i, s i) :=
   ⟨fun r' r'' x =>
     PiTensorProduct.induction_on' x (fun xr xf => by simp only [smul_tprod_coeff', smul_comm])
       fun z y ihz ihy => by simp_rw [PiTensorProduct.smul_add, ihz, ihy]⟩
-#align pi_tensor_product.smul_comm_class' PiTensorProduct.smul_comm_class'
+#align pi_tensor_product.smul_comm_class' PiTensorProduct.smulCommClass'
 
-instance is_scalar_tower' [SMul R₁ R₂] [IsScalarTower R₁ R₂ R] :
-    IsScalarTower R₁ R₂ (⨂[R] i, s i) :=
+instance isScalarTower' [SMul R₁ R₂] [IsScalarTower R₁ R₂ R] : IsScalarTower R₁ R₂ (⨂[R] i, s i) :=
   ⟨fun r' r'' x =>
     PiTensorProduct.induction_on' x (fun xr xf => by simp only [smul_tprod_coeff', smul_assoc])
       fun z y ihz ihy => by simp_rw [PiTensorProduct.smul_add, ihz, ihy]⟩
-#align pi_tensor_product.is_scalar_tower' PiTensorProduct.is_scalar_tower'
+#align pi_tensor_product.is_scalar_tower' PiTensorProduct.isScalarTower'
 
 end DistribMulAction
 
@@ -308,10 +316,10 @@ instance : Module R (⨂[R] i, s i) :=
   PiTensorProduct.module'
 
 instance : SMulCommClass R R (⨂[R] i, s i) :=
-  PiTensorProduct.smul_comm_class'
+  PiTensorProduct.smulCommClass'
 
 instance : IsScalarTower R R (⨂[R] i, s i) :=
-  PiTensorProduct.is_scalar_tower'
+  PiTensorProduct.isScalarTower'
 
 variable {R}
 
Diff
@@ -223,7 +223,7 @@ protected theorem induction_on' {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s
   by
   have C0 : C 0 := by
     have h₁ := @C1 0 0
-    rwa [zero_tprod_coeff] at h₁
+    rwa [zero_tprod_coeff] at h₁ 
   refine' AddCon.induction_on z fun x => FreeAddMonoid.recOn x C0 _
   simp_rw [AddCon.coe_add]
   refine' fun f y ih => Cp _ ih
@@ -344,7 +344,7 @@ theorem tprodCoeff_eq_smul_tprod (z : R) (f : ∀ i, s i) : tprodCoeff R z f = z
 protected theorem induction_on {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i)
     (C1 : ∀ {r : R} {f : ∀ i, s i}, C (r • tprod R f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
     C z := by
-  simp_rw [← tprod_coeff_eq_smul_tprod] at C1
+  simp_rw [← tprod_coeff_eq_smul_tprod] at C1 
   exact PiTensorProduct.induction_on' z @C1 @Cp
 #align pi_tensor_product.induction_on PiTensorProduct.induction_on
 
@@ -600,7 +600,7 @@ private theorem tmul_apply (a : ι → M) (b : ι₂ → M) :
 private def tmul_symm : (⨂[R] i : Sum ι ι₂, M) →ₗ[R] (⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M :=
   -- by using tactic mode, we avoid the need for a lot of `@`s and `_`s
     PiTensorProduct.lift <|
-    by apply MultilinearMap.domCoprod <;> [exact tprod R;exact tprod R]
+    by apply MultilinearMap.domCoprod <;> [exact tprod R; exact tprod R]
 
 private theorem tmul_symm_apply (a : Sum ι ι₂ → M) :
     tmulSymm (⨂ₜ[R] i, a i) = (⨂ₜ[R] i, a (Sum.inl i)) ⊗ₜ[R] ⨂ₜ[R] i, a (Sum.inr i) :=
Diff
@@ -126,7 +126,7 @@ variable {R}
 -- This enables the notation `⨂[R] i : ι, s i` for the pi tensor product, given `s : ι → Type*`.
 scoped[TensorProduct] notation3:100"⨂["R"] "(...)", "r:(scoped f => PiTensorProduct R f) => r
 
-open TensorProduct
+open scoped TensorProduct
 
 namespace PiTensorProduct
 
@@ -654,7 +654,7 @@ namespace PiTensorProduct
 
 open PiTensorProduct
 
-open TensorProduct
+open scoped TensorProduct
 
 variable {ι : Type _} {R : Type _} [CommRing R]
 
Diff
@@ -299,9 +299,7 @@ instance module' [Semiring R₁] [Module R₁ R] [SMulCommClass R₁ R R] : Modu
         by simp [PiTensorProduct.smul_add, ihx, ihy, add_add_add_comm]
     zero_smul := fun x =>
       PiTensorProduct.induction_on' x
-        (fun r f => by
-          simp_rw [smul_tprod_coeff' _ _, zero_smul]
-          exact zero_tprod_coeff _)
+        (fun r f => by simp_rw [smul_tprod_coeff' _ _, zero_smul]; exact zero_tprod_coeff _)
         fun x y ihx ihy => by rw [PiTensorProduct.smul_add, ihx, ihy, add_zero] }
 #align pi_tensor_product.module' PiTensorProduct.module'
 
@@ -377,13 +375,8 @@ variable {s}
 def liftAux (φ : MultilinearMap R s E) : (⨂[R] i, s i) →+ E :=
   liftAddHom (fun p : R × ∀ i, s i => p.1 • φ p.2)
     (fun z f i hf => by rw [map_coord_zero φ i hf, smul_zero]) (fun f => by rw [zero_smul])
-    (fun _ z f i m₁ m₂ => by
-      skip
-      rw [← smul_add, φ.map_add])
-    (fun z₁ z₂ f => by rw [← add_smul]) fun _ z f i r =>
-    by
-    skip
-    simp [φ.map_smul, smul_smul, mul_comm]
+    (fun _ z f i m₁ m₂ => by skip; rw [← smul_add, φ.map_add]) (fun z₁ z₂ f => by rw [← add_smul])
+    fun _ z f i r => by skip; simp [φ.map_smul, smul_smul, mul_comm]
 #align pi_tensor_product.lift_aux PiTensorProduct.liftAux
 
 theorem liftAux_tprod (φ : MultilinearMap R s E) (f : ∀ i, s i) : liftAux φ (tprod R f) = φ f := by
@@ -413,18 +406,10 @@ def lift : MultilinearMap R s E ≃ₗ[R] (⨂[R] i, s i) →ₗ[R] E
     where
   toFun φ := { liftAux φ with map_smul' := liftAux.smul }
   invFun φ' := φ'.compMultilinearMap (tprod R)
-  left_inv φ := by
-    ext
-    simp [lift_aux_tprod, LinearMap.compMultilinearMap]
-  right_inv φ := by
-    ext
-    simp [lift_aux_tprod]
-  map_add' φ₁ φ₂ := by
-    ext
-    simp [lift_aux_tprod]
-  map_smul' r φ₂ := by
-    ext
-    simp [lift_aux_tprod]
+  left_inv φ := by ext; simp [lift_aux_tprod, LinearMap.compMultilinearMap]
+  right_inv φ := by ext; simp [lift_aux_tprod]
+  map_add' φ₁ φ₂ := by ext; simp [lift_aux_tprod]
+  map_smul' r φ₂ := by ext; simp [lift_aux_tprod]
 #align pi_tensor_product.lift PiTensorProduct.lift
 
 variable {φ : MultilinearMap R s E}
@@ -464,13 +449,11 @@ For simplicity, this is defined only for homogeneously- (rather than dependently
 def reindex (e : ι ≃ ι₂) : (⨂[R] i : ι, M) ≃ₗ[R] ⨂[R] i : ι₂, M :=
   LinearEquiv.ofLinear (lift (domDomCongr e.symm (tprod R : MultilinearMap R _ (⨂[R] i : ι₂, M))))
     (lift (domDomCongr e (tprod R : MultilinearMap R _ (⨂[R] i : ι, M))))
-    (by
-      ext
+    (by ext;
       simp only [LinearMap.comp_apply, LinearMap.id_apply, lift_tprod,
         LinearMap.compMultilinearMap_apply, lift.tprod, dom_dom_congr_apply,
         Equiv.apply_symm_apply])
-    (by
-      ext
+    (by ext;
       simp only [LinearMap.comp_apply, LinearMap.id_apply, lift_tprod,
         LinearMap.compMultilinearMap_apply, lift.tprod, dom_dom_congr_apply,
         Equiv.symm_apply_apply])
@@ -493,10 +476,7 @@ theorem reindex_comp_tprod (e : ι ≃ ι₂) :
 
 @[simp]
 theorem lift_comp_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ : ι₂ => M) E) :
-    lift φ ∘ₗ ↑(reindex R M e) = lift (φ.domDomCongr e.symm) :=
-  by
-  ext
-  simp
+    lift φ ∘ₗ ↑(reindex R M e) = lift (φ.domDomCongr e.symm) := by ext; simp
 #align pi_tensor_product.lift_comp_reindex PiTensorProduct.lift_comp_reindex
 
 @[simp]
Diff
@@ -609,26 +609,22 @@ private def tmul : ((⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M) →ₗ[R] ⨂
       map_add' := fun a b => by simp only [LinearEquiv.map_add, LinearMap.map_add]
       map_smul' := fun r a => by
         simp only [LinearEquiv.map_smul, LinearMap.map_smul, RingHom.id_apply] }
-#align pi_tensor_product.tmul pi_tensor_product.tmul
 
 private theorem tmul_apply (a : ι → M) (b : ι₂ → M) :
     tmul ((⨂ₜ[R] i, a i) ⊗ₜ[R] ⨂ₜ[R] i, b i) = ⨂ₜ[R] i, Sum.elim a b i :=
   by
   erw [TensorProduct.lift.tmul, PiTensorProduct.lift.tprod, PiTensorProduct.lift.tprod]
   rfl
-#align pi_tensor_product.tmul_apply pi_tensor_product.tmul_apply
 
 /-- Expand `pi_tensor_product` into a `tensor_product` of two factors. -/
 private def tmul_symm : (⨂[R] i : Sum ι ι₂, M) →ₗ[R] (⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M :=
   -- by using tactic mode, we avoid the need for a lot of `@`s and `_`s
     PiTensorProduct.lift <|
     by apply MultilinearMap.domCoprod <;> [exact tprod R;exact tprod R]
-#align pi_tensor_product.tmul_symm pi_tensor_product.tmul_symm
 
 private theorem tmul_symm_apply (a : Sum ι ι₂ → M) :
     tmulSymm (⨂ₜ[R] i, a i) = (⨂ₜ[R] i, a (Sum.inl i)) ⊗ₜ[R] ⨂ₜ[R] i, a (Sum.inr i) :=
   PiTensorProduct.lift.tprod _
-#align pi_tensor_product.tmul_symm_apply pi_tensor_product.tmul_symm_apply
 
 variable (R M)
 
Diff
@@ -622,7 +622,7 @@ private theorem tmul_apply (a : ι → M) (b : ι₂ → M) :
 private def tmul_symm : (⨂[R] i : Sum ι ι₂, M) →ₗ[R] (⨂[R] i : ι, M) ⊗[R] ⨂[R] i : ι₂, M :=
   -- by using tactic mode, we avoid the need for a lot of `@`s and `_`s
     PiTensorProduct.lift <|
-    by apply MultilinearMap.domCoprod <;> [exact tprod R, exact tprod R]
+    by apply MultilinearMap.domCoprod <;> [exact tprod R;exact tprod R]
 #align pi_tensor_product.tmul_symm pi_tensor_product.tmul_symm
 
 private theorem tmul_symm_apply (a : Sum ι ι₂ → M) :
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Frédéric Dupuis, Eric Wieser
 
 ! This file was ported from Lean 3 source module linear_algebra.pi_tensor_product
-! leanprover-community/mathlib commit 44b58b42794e5abe2bf86397c38e26b587e07e59
+! leanprover-community/mathlib commit ce11c3c2a285bbe6937e26d9792fda4e51f3fe1a
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -46,6 +46,10 @@ binary tensor product in `linear_algebra/tensor_product.lean`.
 * We have not restricted the index type `ι` to be a `fintype`, as nothing we do here strictly
   requires it. However, problems may arise in the case where `ι` is infinite; use at your own
   caution.
+* Instead of requiring `decidable_eq ι` as an argument to `pi_tensor_product` itself, we include it
+  as an argument in the constructors of the relation. A decidability isntance still has to come
+  from somewhere due to the use of `function.update`, but this hides it from the downstream user.
+  See the implementation notes for `multilinear_map` for an extended discussion of this choice.
 
 ## TODO
 
@@ -65,7 +69,7 @@ open Function
 
 section Semiring
 
-variable {ι ι₂ ι₃ : Type _} [DecidableEq ι] [DecidableEq ι₂] [DecidableEq ι₃]
+variable {ι ι₂ ι₃ : Type _}
 
 variable {R : Type _} [CommSemiring R]
 
@@ -92,7 +96,7 @@ inductive Eqv : FreeAddMonoid (R × ∀ i, s i) → FreeAddMonoid (R × ∀ i, s
   | of_zero_scalar : ∀ f : ∀ i, s i, eqv (FreeAddMonoid.of (0, f)) 0
   |
   of_add :
-    ∀ (r : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i),
+    ∀ (inst : DecidableEq ι) (r : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i),
       eqv (FreeAddMonoid.of (r, update f i m₁) + FreeAddMonoid.of (r, update f i m₂))
         (FreeAddMonoid.of (r, update f i (m₁ + m₂)))
   |
@@ -101,7 +105,7 @@ inductive Eqv : FreeAddMonoid (R × ∀ i, s i) → FreeAddMonoid (R × ∀ i, s
       eqv (FreeAddMonoid.of (r, f) + FreeAddMonoid.of (r', f)) (FreeAddMonoid.of (r + r', f))
   |
   of_smul :
-    ∀ (r : R) (f : ∀ i, s i) (i : ι) (r' : R),
+    ∀ (inst : DecidableEq ι) (r : R) (f : ∀ i, s i) (i : ι) (r' : R),
       eqv (FreeAddMonoid.of (r, update f i (r' • f i))) (FreeAddMonoid.of (r' * r, f))
   | add_comm : ∀ x y, eqv (x + y) (y + x)
 #align pi_tensor_product.eqv PiTensorProduct.Eqv
@@ -156,10 +160,10 @@ theorem zero_tprod_coeff' (z : R) (f : ∀ i, s i) (i : ι) (hf : f i = 0) : tpr
   Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_zero _ _ i hf
 #align pi_tensor_product.zero_tprod_coeff' PiTensorProduct.zero_tprod_coeff'
 
-theorem add_tprodCoeff (z : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i) :
+theorem add_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i) :
     tprodCoeff R z (update f i m₁) + tprodCoeff R z (update f i m₂) =
       tprodCoeff R z (update f i (m₁ + m₂)) :=
-  Quotient.sound' <| AddConGen.Rel.of _ _ (Eqv.of_add z f i m₁ m₂)
+  Quotient.sound' <| AddConGen.Rel.of _ _ (Eqv.of_add _ z f i m₁ m₂)
 #align pi_tensor_product.add_tprod_coeff PiTensorProduct.add_tprodCoeff
 
 theorem add_tprod_coeff' (z₁ z₂ : R) (f : ∀ i, s i) :
@@ -167,13 +171,13 @@ theorem add_tprod_coeff' (z₁ z₂ : R) (f : ∀ i, s i) :
   Quotient.sound' <| AddConGen.Rel.of _ _ (Eqv.of_add_scalar z₁ z₂ f)
 #align pi_tensor_product.add_tprod_coeff' PiTensorProduct.add_tprod_coeff'
 
-theorem smul_tprodCoeff_aux (z : R) (f : ∀ i, s i) (i : ι) (r : R) :
+theorem smul_tprodCoeff_aux [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r : R) :
     tprodCoeff R z (update f i (r • f i)) = tprodCoeff R (r * z) f :=
-  Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_smul _ _ _ _
+  Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_smul _ _ _ _ _
 #align pi_tensor_product.smul_tprod_coeff_aux PiTensorProduct.smul_tprodCoeff_aux
 
-theorem smul_tprodCoeff (z : R) (f : ∀ i, s i) (i : ι) (r : R₁) [SMul R₁ R] [IsScalarTower R₁ R R]
-    [SMul R₁ (s i)] [IsScalarTower R₁ R (s i)] :
+theorem smul_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r : R₁) [SMul R₁ R]
+    [IsScalarTower R₁ R R] [SMul R₁ (s i)] [IsScalarTower R₁ R (s i)] :
     tprodCoeff R z (update f i (r • f i)) = tprodCoeff R (r • z) f :=
   by
   have h₁ : r • z = r • (1 : R) * z := by rw [smul_mul_assoc, one_mul]
@@ -188,11 +192,12 @@ def liftAddHom (φ : (R × ∀ i, s i) → F)
     (C0 : ∀ (r : R) (f : ∀ i, s i) (i : ι) (hf : f i = 0), φ (r, f) = 0)
     (C0' : ∀ f : ∀ i, s i, φ (0, f) = 0)
     (C_add :
-      ∀ (r : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i),
+      ∀ [DecidableEq ι] (r : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i),
         φ (r, update f i m₁) + φ (r, update f i m₂) = φ (r, update f i (m₁ + m₂)))
     (C_add_scalar : ∀ (r r' : R) (f : ∀ i, s i), φ (r, f) + φ (r', f) = φ (r + r', f))
     (C_smul :
-      ∀ (r : R) (f : ∀ i, s i) (i : ι) (r' : R), φ (r, update f i (r' • f i)) = φ (r' * r, f)) :
+      ∀ [DecidableEq ι] (r : R) (f : ∀ i, s i) (i : ι) (r' : R),
+        φ (r, update f i (r' • f i)) = φ (r' * r, f)) :
     (⨂[R] i, s i) →+ F :=
   (addConGen (PiTensorProduct.Eqv R s)).lift (FreeAddMonoid.lift φ) <|
     AddCon.addConGen_le fun x y hxy =>
@@ -201,12 +206,12 @@ def liftAddHom (φ : (R × ∀ i, s i) → F)
         (AddCon.ker_rel _).2 <| by simp [FreeAddMonoid.lift_eval_of, C0 r' f i hf]
       | _, _, eqv.of_zero_scalar f =>
         (AddCon.ker_rel _).2 <| by simp [FreeAddMonoid.lift_eval_of, C0']
-      | _, _, eqv.of_add z f i m₁ m₂ =>
-        (AddCon.ker_rel _).2 <| by simp [FreeAddMonoid.lift_eval_of, C_add]
+      | _, _, eqv.of_add inst z f i m₁ m₂ =>
+        (AddCon.ker_rel _).2 <| by simp [FreeAddMonoid.lift_eval_of, @C_add inst]
       | _, _, eqv.of_add_scalar z₁ z₂ f =>
         (AddCon.ker_rel _).2 <| by simp [FreeAddMonoid.lift_eval_of, C_add_scalar]
-      | _, _, eqv.of_smul z f i r' =>
-        (AddCon.ker_rel _).2 <| by simp [FreeAddMonoid.lift_eval_of, C_smul]
+      | _, _, eqv.of_smul inst z f i r' =>
+        (AddCon.ker_rel _).2 <| by simp [FreeAddMonoid.lift_eval_of, @C_smul inst]
       | _, _, eqv.add_comm x y =>
         (AddCon.ker_rel _).2 <| by simp_rw [AddMonoidHom.map_add, add_comm]
 #align pi_tensor_product.lift_add_hom PiTensorProduct.liftAddHom
@@ -318,9 +323,9 @@ variable (R)
 def tprod : MultilinearMap R s (⨂[R] i, s i)
     where
   toFun := tprodCoeff R 1
-  map_add' f i x y := (add_tprodCoeff (1 : R) f i x y).symm
-  map_smul' f i r x := by
-    simp_rw [smul_tprod_coeff', ← smul_tprod_coeff (1 : R) _ i, update_idem, update_same]
+  map_add' _ f i x y := (add_tprod_coeff (1 : R) f i x y).symm
+  map_smul' _ f i r x := by
+    skip <;> simp_rw [smul_tprod_coeff', ← smul_tprod_coeff (1 : R) _ i, update_idem, update_same]
 #align pi_tensor_product.tprod PiTensorProduct.tprod
 
 variable {R}
@@ -372,8 +377,13 @@ variable {s}
 def liftAux (φ : MultilinearMap R s E) : (⨂[R] i, s i) →+ E :=
   liftAddHom (fun p : R × ∀ i, s i => p.1 • φ p.2)
     (fun z f i hf => by rw [map_coord_zero φ i hf, smul_zero]) (fun f => by rw [zero_smul])
-    (fun z f i m₁ m₂ => by rw [← smul_add, φ.map_add]) (fun z₁ z₂ f => by rw [← add_smul])
-    fun z f i r => by simp [φ.map_smul, smul_smul, mul_comm]
+    (fun _ z f i m₁ m₂ => by
+      skip
+      rw [← smul_add, φ.map_add])
+    (fun z₁ z₂ f => by rw [← add_smul]) fun _ z f i r =>
+    by
+    skip
+    simp [φ.map_smul, smul_smul, mul_comm]
 #align pi_tensor_product.lift_aux PiTensorProduct.liftAux
 
 theorem liftAux_tprod (φ : MultilinearMap R s E) (f : ∀ i, s i) : liftAux φ (tprod R f) = φ f := by
@@ -670,7 +680,7 @@ open PiTensorProduct
 
 open TensorProduct
 
-variable {ι : Type _} [DecidableEq ι] {R : Type _} [CommRing R]
+variable {ι : Type _} {R : Type _} [CommRing R]
 
 variable {s : ι → Type _} [∀ i, AddCommGroup (s i)] [∀ i, Module R (s i)]
 
Diff
@@ -222,7 +222,7 @@ protected theorem induction_on' {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s
   refine' AddCon.induction_on z fun x => FreeAddMonoid.recOn x C0 _
   simp_rw [AddCon.coe_add]
   refine' fun f y ih => Cp _ ih
-  convert @C1 f.1 f.2
+  convert@C1 f.1 f.2
   simp only [Prod.mk.eta]
 #align pi_tensor_product.induction_on' PiTensorProduct.induction_on'
 

Changes in mathlib4

mathlib3
mathlib4
style: replace '.-/' by '. -/' (#11938)

Purely automatic replacement. If this is in any way controversial; I'm happy to just close this PR.

Diff
@@ -330,7 +330,7 @@ lemma _root_.FreeAddMonoid.toPiTensorProduct (p : FreeAddMonoid (R × Π i, s i)
   | x :: ps => rw [List.map_cons, List.sum_cons, ← List.singleton_append, ← toPiTensorProduct ps,
                  ← tprodCoeff_eq_smul_tprod]; rfl
 
-/-- The set of lifts of an element `x` of `⨂[R] i, s i` in `FreeAddMonoid (R × Π i, s i)`.-/
+/-- The set of lifts of an element `x` of `⨂[R] i, s i` in `FreeAddMonoid (R × Π i, s i)`. -/
 def lifts (x : ⨂[R] i, s i) : Set (FreeAddMonoid (R × Π i, s i)) :=
   {p | AddCon.toQuotient (c := addConGen (PiTensorProduct.Eqv R s)) p = x}
 
@@ -398,7 +398,7 @@ theorem ext {φ₁ φ₂ : (⨂[R] i, s i) →ₗ[R] E}
 #align pi_tensor_product.ext PiTensorProduct.ext
 
 /-- The pure tensors (i.e. the elements of the image of `PiTensorProduct.tprod`) span
-the tensor product.-/
+the tensor product. -/
 theorem span_tprod_eq_top :
     Submodule.span R (Set.range (tprod R)) = (⊤ : Submodule R (⨂[R] i, s i)) :=
   Submodule.eq_top_iff'.mpr fun t ↦ t.induction_on
@@ -569,7 +569,7 @@ theorem map_mul (f₁ f₂ : Π i, s i →ₗ[R] s i) :
     map (fun i ↦ f₁ i * f₂ i) = map f₁ * map f₂ :=
   map_comp f₁ f₂
 
-/-- Upgrading `PiTensorProduct.map` to a `MonoidHom` when `s = t`.-/
+/-- Upgrading `PiTensorProduct.map` to a `MonoidHom` when `s = t`. -/
 @[simps]
 def mapMonoidHom : (Π i, s i →ₗ[R] s i) →* ((⨂[R] i, s i) →ₗ[R] ⨂[R] i, s i) where
   toFun := map
@@ -716,7 +716,7 @@ section
 variable (R M)
 
 variable (s) in
-/-- Re-index the components of the tensor power by `e`.-/
+/-- Re-index the components of the tensor power by `e`. -/
 def reindex (e : ι ≃ ι₂) : (⨂[R] i : ι, s i) ≃ₗ[R] ⨂[R] i : ι₂, s (e.symm i) :=
   let f := domDomCongrLinearEquiv' R R s (⨂[R] (i : ι₂), s (e.symm i)) e
   let g := domDomCongrLinearEquiv' R R s (⨂[R] (i : ι), s i) e
@@ -807,7 +807,7 @@ variable {t : ι → Type*}
 variable [∀ i, AddCommMonoid (t i)] [∀ i, Module R (t i)]
 
 /-- Re-indexing the components of the tensor product by an equivalence `e` is compatible
-with `PiTensorProduct.map`.-/
+with `PiTensorProduct.map`. -/
 theorem map_comp_reindex_eq (f : Π i, s i →ₗ[R] t i) (e : ι ≃ ι₂) :
     map (fun i ↦ f (e.symm i)) ∘ₗ reindex R s e = reindex R t e ∘ₗ map f := by
   ext m
feat(Analysis/NormedSpace/PiTensorProduct/{InjectiveNorm, ProjectiveNorm}, LinearAlgebra/PiTensorProduct): define the injective and projective norms on PiTensorProduct and prove the universal property of the first one (#11534)

Define the injective and projective cross norms on a PiTensorProduct of normed vector spaces Eᵢ over a nontrivially normed field 𝕜 (cf https://en.wikipedia.org/wiki/Topological_tensor_product#Cross_norms_and_tensor_products_of_Banach_spaces).

The projective norm, defined in Analysis/NormedSpace/PiTensorProduct/ProjectiveNorm.lean, is the biggest norm on the PiTensorProduct satisfying ‖⨂ₜ[𝕜] i, m i‖ ≤ Π i, ‖m i‖ for every m in Π i, Eᵢ. We are mainly interested in the injective norm in this PR, so we just give the definition of the projective norm and its basic properties. To help with the proofs, we introduce some lemmas in LinearAlgebra/PiTensorProduct.lean about the set of lifts in FreeAddMonoid (R × Π i, s i) of an element x of ⨂[R] i, s i.

The injective norm, defined in Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean, is chosen to satisfy the following property: for every normed 𝕜-vector space F, the linear equivalence MultilinearMap 𝕜 E F ≃ₗ[𝕜] (⨂[𝕜] i, Eᵢ) →ₗ[𝕜] F expressing the universal property of the tensor product induces an isometric linear equivalence ContinuousMultilinearMap 𝕜 E F ≃ₗᵢ[𝕜] (⨂[𝕜] i, Eᵢ) →L[𝕜] F.

The idea is the following: Every normed 𝕜-vector space F defines a linear map from ⨂[𝕜] i, Eᵢ to ContinuousMultilinearMap 𝕜 E F →ₗ[𝕜] F, which sends x to the map f ↦ f.lift x. Thanks to PiTensorProduct.projectiveSeminorm_bound, this map lands in ContinuousMultilinearMap 𝕜 E F →L[𝕜] F. As this last space has a natural operator seminorm, we get an induced seminorm on ⨂[𝕜] i, Eᵢ, which, by PiTensorProduct.projectiveSeminorm_bound, is bounded above by the projective seminorm. We then take the sup of these seminorms as F varies; as this family of seminorms is bounded, its sup has good properties.

In fact, we cannot take the sup over all normed spaces F because of set-theoretical issues, so we only take spaces F in the same universe as ⨂[𝕜] i, Eᵢ. We then prove in PiTensorProduct.norm_eval_le_injectiveSeminorm that this gives the same result, because every multilinear map from E to F factors though a normed vector space in the same universe as ⨂[𝕜] i, Eᵢ.

Main definitions

  • PiTensorProduct.projectiveSeminorm: The projective seminorm on ⨂[𝕜] i, Eᵢ.
  • PiTensorProduct.toDualContinuousMultilinearMap: The 𝕜-linear map from ⨂[𝕜] i, Eᵢ to ContinuousMultilinearMap 𝕜 E F →L[𝕜] F sending x to the map f ↦ f x.
  • PiTensorProduct.injectiveSeminorm: The injective seminorm on ⨂[𝕜] i, Eᵢ.
  • PiTensorProduct.liftEquiv: The bijection between ContinuousMultilinearMap 𝕜 E F and (⨂[𝕜] i, Eᵢ) →L[𝕜] F, as a continuous linear equivalence.
  • PiTensorProduct.liftIsometry: The bijection between ContinuousMultilinearMap 𝕜 E F and (⨂[𝕜] i, Eᵢ) →L[𝕜] F, as an isometric linear equivalence.
  • PiTensorProduct.tprodL: The cacnonical continuous multilinear map from E to ⨂[𝕜] i, Eᵢ.
  • PiTensorProduct.mapL: The continuous linear map from ⨂[𝕜] i, Eᵢ to ⨂[𝕜] i, E'ᵢ induced by a family of continuous linear maps Eᵢ →L[𝕜] E'ᵢ.
  • PiTensorProduct.mapLMultilinear: The continuous multilinear map from fun i ↦ (Eᵢ →L[𝕜] E'ᵢ) to (⨂[𝕜] i, Eᵢ) →L[𝕜] (⨂[𝕜] i, E'ᵢ) sending a family f to PiTensorProduct.mapL f.

Main results

  • PiTensorProduct.norm_eval_le_projectiveSeminorm: For every x in ⨂[𝕜] i, Eᵢ and every continuous multilinear map f from E to a normed space F, we have ‖f.lift x‖ ≤ ‖f‖ * projectiveSeminorm x . This implies in particular:
  • PiTensorProduct.injectiveSeminorm_le_projectiveSeminorm: The injective seminorm is bounded above by the projective seminorm.
  • PiTensorProduct.norm_eval_le_injectiveSeminorm: The main property of the injective seminorm on ⨂[𝕜] i, Eᵢ: for every x in ⨂[𝕜] i, Eᵢ and every continuous multilinear map f from E to a normed space F, we have ‖f.lift x‖ ≤ ‖f‖ * injectiveSeminorm x .
  • PiTensorProduct.mapL_opNorm: If f is a family of continuous linear maps fᵢ : Eᵢ →L[𝕜] Fᵢ, then ‖PiTensorProduct.mapL f‖ ≤ ∏ i, ‖fᵢ‖.
  • PiTensorProduct.mapLMultilinear_opNorm : If F is a normed vecteor space, then ‖mapLMultilinear 𝕜 E F‖ ≤ 1.

TODO (in a future PR)

If all Eᵢ are separated and satisfy SeparatingDual, then the seminorm on ⨂[𝕜] i, Eᵢ is a norm. This uses the construction of a basis of the PiTensorProduct, hence depends on PR #11156. It should probably go in a separate file, which is why I am creating a directory Analysis/NormedSpace/PiTensorProduct.

Technical issues

  • Ideally, I would prefer not to define liftEquiv and to have only liftIsometry, but I am using liftEquiv.left_inv in the proof that liftIsometry preserves norms.

Co-authored-by: smorel394 <67864981+smorel394@users.noreply.github.com>

Diff
@@ -319,6 +319,62 @@ theorem tprodCoeff_eq_smul_tprod (z : R) (f : Π i, s i) : tprodCoeff R z f = z
   conv_lhs => rw [this]
 #align pi_tensor_product.tprod_coeff_eq_smul_tprod PiTensorProduct.tprodCoeff_eq_smul_tprod
 
+/-- The image of an element `p` of `FreeAddMonoid (R × Π i, s i)` in the `PiTensorProduct` is
+equal to the sum of `a • ⨂ₜ[R] i, m i` over all the entries `(a, m)` of `p`.
+-/
+lemma _root_.FreeAddMonoid.toPiTensorProduct (p : FreeAddMonoid (R × Π i, s i)) :
+    AddCon.toQuotient (c := addConGen (PiTensorProduct.Eqv R s)) p =
+    List.sum (List.map (fun x ↦ x.1 • ⨂ₜ[R] i, x.2 i) p) := by
+  match p with
+  | [] => rw [List.map_nil, List.sum_nil]; rfl
+  | x :: ps => rw [List.map_cons, List.sum_cons, ← List.singleton_append, ← toPiTensorProduct ps,
+                 ← tprodCoeff_eq_smul_tprod]; rfl
+
+/-- The set of lifts of an element `x` of `⨂[R] i, s i` in `FreeAddMonoid (R × Π i, s i)`.-/
+def lifts (x : ⨂[R] i, s i) : Set (FreeAddMonoid (R × Π i, s i)) :=
+  {p | AddCon.toQuotient (c := addConGen (PiTensorProduct.Eqv R s)) p = x}
+
+/-- An element `p` of `FreeAddMonoid (R × Π i, s i)` lifts an element `x` of `⨂[R] i, s i`
+if and only if `x` is equal to to the sum of `a • ⨂ₜ[R] i, m i` over all the entries
+`(a, m)` of `p`.
+-/
+lemma mem_lifts_iff (x : ⨂[R] i, s i) (p : FreeAddMonoid (R × Π i, s i)) :
+    p ∈ lifts x ↔ List.sum (List.map (fun x ↦ x.1 • ⨂ₜ[R] i, x.2 i) p) = x := by
+  simp only [lifts, Set.mem_setOf_eq, FreeAddMonoid.toPiTensorProduct]
+
+/-- Every element of `⨂[R] i, s i` has a lift in `FreeAddMonoid (R × Π i, s i)`.
+-/
+lemma nonempty_lifts (x : ⨂[R] i, s i) : Set.Nonempty (lifts x) := by
+  existsi @Quotient.out _ (addConGen (PiTensorProduct.Eqv R s)).toSetoid x
+  simp only [lifts, Set.mem_setOf_eq]
+  rw [← AddCon.quot_mk_eq_coe]
+  erw [Quot.out_eq]
+
+/-- The empty list lifts the element `0` of `⨂[R] i, s i`.
+-/
+lemma lifts_zero : 0 ∈ lifts (0 : ⨂[R] i, s i) := by
+  rw [mem_lifts_iff]; erw [List.map_nil]; rw [List.sum_nil]
+
+/-- If elements `p,q` of `FreeAddMonoid (R × Π i, s i)` lift elements `x,y` of `⨂[R] i, s i`
+respectively, then `p + q` lifts `x + y`.
+-/
+lemma lifts_add {x y : ⨂[R] i, s i} {p q : FreeAddMonoid (R × Π i, s i)}
+    (hp : p ∈ lifts x) (hq : q ∈ lifts y): p + q ∈ lifts (x + y) := by
+  simp only [lifts, Set.mem_setOf_eq, AddCon.coe_add]
+  rw [hp, hq]
+
+/-- If an element `p` of `FreeAddMonoid (R × Π i, s i)` lifts an element `x` of `⨂[R] i, s i`,
+and if `a` is an element of `R`, then the list obtained by multiplying the first entry of each
+element of `p` by `a` lifts `a • x`.
+-/
+lemma lifts_smul {x : ⨂[R] i, s i} {p : FreeAddMonoid (R × Π i, s i)} (h : p ∈ lifts x) (a : R) :
+    List.map (fun (y : R × Π i, s i) ↦ (a * y.1, y.2)) p ∈ lifts (a • x) := by
+  rw [mem_lifts_iff] at h ⊢
+  rw [← List.comp_map, ← h, List.smul_sum, ← List.comp_map]
+  congr 2
+  ext _
+  simp only [comp_apply, smul_smul]
+
 /-- Induct using scaled versions of `PiTensorProduct.tprod`. -/
 @[elab_as_elim]
 protected theorem induction_on {motive : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i)
@@ -476,7 +532,7 @@ def map : (⨂[R] i, s i) →ₗ[R] ⨂[R] i, t i :=
 
 theorem map_range_eq_span_tprod :
     LinearMap.range (map f) =
-      Submodule.span R { t | ∃ (m : Π i, s i), tprod R (fun i ↦ f i (m i)) = t } := by
+      Submodule.span R {t | ∃ (m : Π i, s i), tprod R (fun i ↦ f i (m i)) = t} := by
   rw [← Submodule.map_top, ← span_tprod_eq_top, Submodule.map_span, ← Set.range_comp]
   apply congrArg; ext x
   simp only [Set.mem_range, comp_apply, map_tprod, Set.mem_setOf_eq]
chore(*): remove empty lines between variable statements (#11418)

Empty lines were removed by executing the following Python script twice

import os
import re


# Loop through each file in the repository
for dir_path, dirs, files in os.walk('.'):
  for filename in files:
    if filename.endswith('.lean'):
      file_path = os.path.join(dir_path, filename)

      # Open the file and read its contents
      with open(file_path, 'r') as file:
        content = file.read()

      # Use a regular expression to replace sequences of "variable" lines separated by empty lines
      # with sequences without empty lines
      modified_content = re.sub(r'(variable.*\n)\n(variable(?! .* in))', r'\1\2', content)

      # Write the modified content back to the file
      with open(file_path, 'w') as file:
        file.write(modified_content)
Diff
@@ -69,17 +69,11 @@ open Function
 section Semiring
 
 variable {ι ι₂ ι₃ : Type*}
-
 variable {R : Type*} [CommSemiring R]
-
 variable {R₁ R₂ : Type*}
-
 variable {s : ι → Type*} [∀ i, AddCommMonoid (s i)] [∀ i, Module R (s i)]
-
 variable {M : Type*} [AddCommMonoid M] [Module R M]
-
 variable {E : Type*} [AddCommMonoid E] [Module R E]
-
 variable {F : Type*} [AddCommMonoid F]
 
 namespace PiTensorProduct
@@ -222,7 +216,6 @@ protected theorem induction_on' {motive : (⨂[R] i, s i) → Prop} (z : ⨂[R]
 section DistribMulAction
 
 variable [Monoid R₁] [DistribMulAction R₁ R] [SMulCommClass R₁ R R]
-
 variable [Monoid R₂] [DistribMulAction R₂ R] [SMulCommClass R₂ R R]
 
 -- Most of the time we want the instance below this one, which is easier for typeclass resolution
@@ -927,7 +920,6 @@ open PiTensorProduct
 open TensorProduct
 
 variable {ι : Type*} {R : Type*} [CommRing R]
-
 variable {s : ι → Type*} [∀ i, AddCommGroup (s i)] [∀ i, Module R (s i)]
 
 /- Unlike for the binary tensor product, we require `R` to be a `CommRing` here, otherwise
chore: classify new theorem / theorem porting notes (#11432)

Classifies by adding issue number #10756 to porting notes claiming anything equivalent to:

  • "added theorem"
  • "added theorems"
  • "new theorem"
  • "new theorems"
  • "added lemma"
  • "new lemma"
  • "new lemmas"
Diff
@@ -316,7 +316,7 @@ unsuppress_compilation in
 @[inherit_doc tprod]
 notation3:100 "⨂ₜ["R"] "(...)", "r:(scoped f => tprod R f) => r
 
--- Porting note: new theorem
+-- Porting note (#10756): new theorem
 theorem tprod_eq_tprodCoeff_one :
     ⇑(tprod R : MultilinearMap R s (⨂[R] i, s i)) = tprodCoeff R 1 := rfl
 
perf(LinearAlgebra.PiTensorProduct): don't unfold piTensorHomMap₂ (#11307)

The currently definition of piTensorHomMap₂ results in a large term causing dsimp and simp to work too hard. This PR breaks up the definition into a function defnition and two lemmas. The result is a 17% speed up.

Diff
@@ -623,6 +623,25 @@ lemma map₂_tprod_tprod (f : Π i, s i →ₗ[R] t i →ₗ[R] t' i) (x : Π i,
     map₂ f (tprod R x) (tprod R y) = tprod R fun i ↦ f i (x i) (y i) := by
   simp [map₂]
 
+/--
+Let `sᵢ`, `tᵢ` and `t'ᵢ` be families of `R`-modules.
+Then there is a function from `⨂ᵢ Hom(sᵢ, Hom(tᵢ, t'ᵢ))` to `Hom(⨂ᵢ sᵢ, Hom(⨂ tᵢ, ⨂ᵢ t'ᵢ))`
+defined by `⨂ᵢ fᵢ ↦ ⨂ᵢ aᵢ ↦ ⨂ᵢ bᵢ ↦ ⨂ᵢ fᵢ aᵢ bᵢ`. -/
+def piTensorHomMapFun₂ : (⨂[R] i, s i →ₗ[R] t i →ₗ[R] t' i) →
+    (⨂[R] i, s i) →ₗ[R] (⨂[R] i, t i) →ₗ[R] (⨂[R] i, t' i) :=
+  fun φ => lift <| LinearMap.compMultilinearMap piTensorHomMap <|
+    (lift <| MultilinearMap.piLinearMap <| tprod R) φ
+
+theorem piTensorHomMapFun₂_add (φ ψ : ⨂[R] i, s i →ₗ[R] t i →ₗ[R] t' i) :
+    piTensorHomMapFun₂ (φ + ψ) = piTensorHomMapFun₂ φ + piTensorHomMapFun₂ ψ := by
+  dsimp [piTensorHomMapFun₂]; ext; simp only [map_add, LinearMap.compMultilinearMap_apply,
+    lift.tprod, add_apply, LinearMap.add_apply]
+
+theorem piTensorHomMapFun₂_smul (r : R) (φ : ⨂[R] i, s i →ₗ[R] t i →ₗ[R] t' i) :
+    piTensorHomMapFun₂ (r • φ) = r • piTensorHomMapFun₂ φ := by
+  dsimp [piTensorHomMapFun₂]; ext; simp only [map_smul, LinearMap.compMultilinearMap_apply,
+    lift.tprod, smul_apply, LinearMap.smul_apply]
+
 /--
 Let `sᵢ`, `tᵢ` and `t'ᵢ` be families of `R`-modules.
 Then there is an linear map from `⨂ᵢ Hom(sᵢ, Hom(tᵢ, t'ᵢ))` to `Hom(⨂ᵢ sᵢ, Hom(⨂ tᵢ, ⨂ᵢ t'ᵢ))`
@@ -632,15 +651,14 @@ This is `TensorProduct.homTensorHomMap` for two arbitrary families of modules.
 -/
 def piTensorHomMap₂ : (⨂[R] i, s i →ₗ[R] t i →ₗ[R] t' i) →ₗ[R]
     (⨂[R] i, s i) →ₗ[R] (⨂[R] i, t i) →ₗ[R] (⨂[R] i, t' i) where
-  toFun φ := lift <| LinearMap.compMultilinearMap piTensorHomMap <|
-    (lift <| MultilinearMap.piLinearMap <| tprod R) φ
-  map_add' x y := by dsimp; ext; simp
-  map_smul' r x := by dsimp; ext; simp
+  toFun := piTensorHomMapFun₂
+  map_add' x y := piTensorHomMapFun₂_add x y
+  map_smul' x y :=  piTensorHomMapFun₂_smul x y
 
 @[simp] lemma piTensorHomMap₂_tprod_tprod_tprod
     (f : ∀ i, s i →ₗ[R] t i →ₗ[R] t' i) (a : ∀ i, s i) (b : ∀ i, t i) :
     piTensorHomMap₂ (tprod R f) (tprod R a) (tprod R b) = tprod R (fun i ↦ f i (a i) (b i)) := by
-  simp [piTensorHomMap₂]
+  simp [piTensorHomMapFun₂, piTensorHomMap₂]
 
 end map
 
feat(LinearAlgebra/PiTensorProduct): some more functoriality properties of PiTensorProduct (#11152)
  • Prove some properties of PiTensorProduct.map, for example the compatibility with composition and reindeixing, and the fact that it sends the identity to the identity.
  • Construct PiTensorProduct.map as a MultilinearMap on the family of linear maps.
  • Upgrade PiTensorProduct.map f to a linear equivalence called PiTensorProduct.congr f when f is a family of linear equivalences.
  • For ι a Fintype, define the canonical linear equivalence (given by multiplication) constantBaseRingEquiv from ⨂ i : ι, R and R.

Co-authored-by: smorel394 <67864981+smorel394@users.noreply.github.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -348,6 +348,15 @@ theorem ext {φ₁ φ₂ : (⨂[R] i, s i) →ₗ[R] E}
     exact MultilinearMap.congr_fun H f
 #align pi_tensor_product.ext PiTensorProduct.ext
 
+/-- The pure tensors (i.e. the elements of the image of `PiTensorProduct.tprod`) span
+the tensor product.-/
+theorem span_tprod_eq_top :
+    Submodule.span R (Set.range (tprod R)) = (⊤ : Submodule R (⨂[R] i, s i)) :=
+  Submodule.eq_top_iff'.mpr fun t ↦ t.induction_on
+    (fun _ _ ↦ Submodule.smul_mem _ _
+      (Submodule.subset_span (by simp only [Set.mem_range, exists_apply_eq_apply])))
+    (fun _ _ hx hy ↦ Submodule.add_mem _ hx hy)
+
 end Module
 
 section Multilinear
@@ -454,6 +463,7 @@ section map
 variable {t t' : ι → Type*}
 variable [∀ i, AddCommMonoid (t i)] [∀ i, Module R (t i)]
 variable [∀ i, AddCommMonoid (t' i)] [∀ i, Module R (t' i)]
+variable (g : Π i, t i →ₗ[R] t' i) (f : Π i, s i →ₗ[R] t i)
 
 /--
 Let `sᵢ` and `tᵢ` be two families of `R`-modules.
@@ -462,13 +472,99 @@ then there is an induced map `⨂ᵢ sᵢ → ⨂ᵢ tᵢ` by `⨂ aᵢ ↦ ⨂
 
 This is `TensorProduct.map` for an arbitrary family of modules.
 -/
-def map (f : Π i, s i →ₗ[R] t i) : (⨂[R] i, s i) →ₗ[R] ⨂[R] i, t i :=
+def map : (⨂[R] i, s i) →ₗ[R] ⨂[R] i, t i :=
   lift <| (tprod R).compLinearMap f
 
-@[simp] lemma map_tprod (f : Π i, s i →ₗ[R] t i) (x : Π i, s i) :
+@[simp] lemma map_tprod (x : Π i, s i) :
     map f (tprod R x) = tprod R fun i ↦ f i (x i) :=
   lift.tprod _
 
+-- No lemmas about associativity, because we don't have associativity of `PiTensorProduct` yet.
+
+theorem map_range_eq_span_tprod :
+    LinearMap.range (map f) =
+      Submodule.span R { t | ∃ (m : Π i, s i), tprod R (fun i ↦ f i (m i)) = t } := by
+  rw [← Submodule.map_top, ← span_tprod_eq_top, Submodule.map_span, ← Set.range_comp]
+  apply congrArg; ext x
+  simp only [Set.mem_range, comp_apply, map_tprod, Set.mem_setOf_eq]
+
+/-- Given submodules `p i ⊆ s i`, this is the natural map: `⨂[R] i, p i → ⨂[R] i, s i`.
+This is `TensorProduct.mapIncl` for an arbitrary family of modules.
+-/
+@[simp]
+def mapIncl (p : Π i, Submodule R (s i)) : (⨂[R] i, p i) →ₗ[R] ⨂[R] i, s i :=
+  map fun (i : ι) ↦ (p i).subtype
+
+theorem map_comp : map (fun (i : ι) ↦ g i ∘ₗ f i) = map g ∘ₗ map f := by
+  ext
+  simp only [LinearMap.compMultilinearMap_apply, map_tprod, LinearMap.coe_comp, Function.comp_apply]
+
+theorem lift_comp_map (h : MultilinearMap R t E) :
+    lift h ∘ₗ map f = lift (h.compLinearMap f) := by
+  ext
+  simp only [LinearMap.compMultilinearMap_apply, LinearMap.coe_comp, Function.comp_apply,
+    map_tprod, lift.tprod, MultilinearMap.compLinearMap_apply]
+
+attribute [local ext high] ext
+
+@[simp]
+theorem map_id : map (fun i ↦ (LinearMap.id : s i →ₗ[R] s i)) = .id := by
+  ext
+  simp only [LinearMap.compMultilinearMap_apply, map_tprod, LinearMap.id_coe, id_eq]
+
+@[simp]
+theorem map_one : map (fun (i : ι) ↦ (1 : s i →ₗ[R] s i)) = 1 :=
+  map_id
+
+theorem map_mul (f₁ f₂ : Π i, s i →ₗ[R] s i) :
+    map (fun i ↦ f₁ i * f₂ i) = map f₁ * map f₂ :=
+  map_comp f₁ f₂
+
+/-- Upgrading `PiTensorProduct.map` to a `MonoidHom` when `s = t`.-/
+@[simps]
+def mapMonoidHom : (Π i, s i →ₗ[R] s i) →* ((⨂[R] i, s i) →ₗ[R] ⨂[R] i, s i) where
+  toFun := map
+  map_one' := map_one
+  map_mul' := map_mul
+
+@[simp]
+protected theorem map_pow (f : Π i, s i →ₗ[R] s i) (n : ℕ) :
+    map (f ^ n) = map f ^ n := MonoidHom.map_pow mapMonoidHom _ _
+
+open Function in
+private theorem map_add_smul_aux [DecidableEq ι] (i : ι) (x : Π i, s i) (u : s i →ₗ[R] t i) :
+    (fun j ↦ update f i u j (x j)) = update (fun j ↦ (f j) (x j)) i (u (x i)) := by
+  ext j
+  exact apply_update (fun i F => F (x i)) f i u j
+
+open Function in
+protected theorem map_add [DecidableEq ι] (i : ι) (u v : s i →ₗ[R] t i) :
+    map (update f i (u + v)) = map (update f i u) + map (update f i v) := by
+  ext x
+  simp only [LinearMap.compMultilinearMap_apply, map_tprod, map_add_smul_aux, LinearMap.add_apply,
+    MultilinearMap.map_add]
+
+open Function in
+protected theorem map_smul [DecidableEq ι] (i : ι) (c : R) (u : s i →ₗ[R] t i) :
+    map (update f i (c • u)) = c • map (update f i u) := by
+  ext x
+  simp only [LinearMap.compMultilinearMap_apply, map_tprod, map_add_smul_aux, LinearMap.smul_apply,
+    MultilinearMap.map_smul]
+
+variable (R s t)
+
+/-- The tensor of a family of linear maps from `sᵢ` to `tᵢ`, as a multilinear map of
+the family.
+-/
+@[simps]
+noncomputable def mapMultilinear :
+    MultilinearMap R (fun (i : ι) ↦ s i →ₗ[R] t i) ((⨂[R] i, s i) →ₗ[R] ⨂[R] i, t i) where
+  toFun := map
+  map_smul' _ _ _ _ := PiTensorProduct.map_smul _ _ _ _
+  map_add' _ _ _ _ := PiTensorProduct.map_add _ _ _ _
+
+variable {R s t}
+
 /--
 Let `sᵢ` and `tᵢ` be families of `R`-modules.
 Then there is an `R`-linear map between `⨂ᵢ Hom(sᵢ, tᵢ)` and `Hom(⨂ᵢ sᵢ, ⨂ tᵢ)` defined by
@@ -489,6 +585,29 @@ lemma piTensorHomMap_tprod_eq_map (f : Π i, s i →ₗ[R] t i) :
     piTensorHomMap (tprod R f) = map f := by
   ext; simp
 
+/-- If `s i` and `t i` are linearly equivalent for every `i` in `ι`, then `⨂[R] i, s i` and
+`⨂[R] i, t i` are linearly equivalent.
+
+This is the n-ary version of `TensorProduct.congr`
+-/
+noncomputable def congr (f : Π i, s i ≃ₗ[R] t i) :
+    (⨂[R] i, s i) ≃ₗ[R] ⨂[R] i, t i :=
+  .ofLinear
+    (map (fun i ↦ f i))
+    (map (fun i ↦ (f i).symm))
+    (by ext; simp)
+    (by ext; simp)
+
+@[simp]
+theorem congr_tprod (f : Π i, s i ≃ₗ[R] t i) (m : Π i, s i) :
+    congr f (tprod R m) = tprod R (fun (i : ι) ↦ (f i) (m i)) := by
+  simp only [congr, LinearEquiv.ofLinear_apply, map_tprod, LinearEquiv.coe_coe]
+
+@[simp]
+theorem congr_symm_tprod (f : Π i, s i ≃ₗ[R] t i) (p : Π i, t i) :
+    (congr f).symm (tprod R p) = tprod R (fun (i : ι) ↦ (f i).symm (p i)) := by
+  simp only [congr, LinearEquiv.ofLinear_symm_apply, map_tprod, LinearEquiv.coe_coe]
+
 /--
 Let `sᵢ`, `tᵢ` and `t'ᵢ` be families of `R`-modules, then `f : Πᵢ sᵢ → tᵢ → t'ᵢ` induces an
 element of `Hom(⨂ᵢ sᵢ, Hom(⨂ tᵢ, ⨂ᵢ t'ᵢ))` defined by `⨂ᵢ aᵢ ↦ ⨂ᵢ bᵢ ↦ ⨂ᵢ fᵢ aᵢ bᵢ`.
@@ -617,6 +736,32 @@ theorem reindex_refl : reindex R s (Equiv.refl ι) = LinearEquiv.refl R _ := by
   congr
 #align pi_tensor_product.reindex_refl PiTensorProduct.reindex_refl
 
+variable {t : ι → Type*}
+variable [∀ i, AddCommMonoid (t i)] [∀ i, Module R (t i)]
+
+/-- Re-indexing the components of the tensor product by an equivalence `e` is compatible
+with `PiTensorProduct.map`.-/
+theorem map_comp_reindex_eq (f : Π i, s i →ₗ[R] t i) (e : ι ≃ ι₂) :
+    map (fun i ↦ f (e.symm i)) ∘ₗ reindex R s e = reindex R t e ∘ₗ map f := by
+  ext m
+  simp only [LinearMap.compMultilinearMap_apply, LinearMap.coe_comp, LinearEquiv.coe_coe,
+    LinearMap.comp_apply, reindex_tprod, map_tprod]
+
+theorem map_reindex (f : Π i, s i →ₗ[R] t i) (e : ι ≃ ι₂) (x : ⨂[R] i, s i) :
+    map (fun i ↦ f (e.symm i)) (reindex R s e x) = reindex R t e (map f x) :=
+  DFunLike.congr_fun (map_comp_reindex_eq _ _) _
+
+theorem map_comp_reindex_symm (f : Π i, s i →ₗ[R] t i) (e : ι ≃ ι₂) :
+    map f ∘ₗ (reindex R s e).symm = (reindex R t e).symm ∘ₗ map (fun i => f (e.symm i)) := by
+  ext m
+  apply LinearEquiv.injective (reindex R t e)
+  simp only [LinearMap.compMultilinearMap_apply, LinearMap.coe_comp, LinearEquiv.coe_coe,
+    comp_apply, ← map_reindex, LinearEquiv.apply_symm_apply, map_tprod]
+
+theorem map_reindex_symm (f : Π i, s i →ₗ[R] t i) (e : ι ≃ ι₂) (x : ⨂[R] i, s (e.symm i)) :
+    map f ((reindex R s e).symm x) = (reindex R t e).symm (map (fun i ↦ f (e.symm i)) x) :=
+  DFunLike.congr_fun (map_comp_reindex_symm _ _) _
+
 variable (ι)
 
 attribute [local simp] eq_iff_true_of_subsingleton in
@@ -644,7 +789,7 @@ def isEmptyEquiv [IsEmpty ι] : (⨂[R] i : ι, s i) ≃ₗ[R] R where
 #align pi_tensor_product.is_empty_equiv PiTensorProduct.isEmptyEquiv
 
 @[simp]
-theorem isEmptyEquiv_apply_tprod [IsEmpty ι] (f : (i : ι) → s i) :
+theorem isEmptyEquiv_apply_tprod [IsEmpty ι] (f : Π i, s i) :
     isEmptyEquiv ι (tprod R f) = 1 :=
   lift.tprod _
 #align pi_tensor_product.is_empty_equiv_apply_tprod PiTensorProduct.isEmptyEquiv_apply_tprod
chore: move Mathlib to v4.7.0-rc1 (#11162)

This is a very large PR, but it has been reviewed piecemeal already in PRs to the bump/v4.7.0 branch as we update to intermediate nightlies.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Kyle Miller <kmill31415@gmail.com> Co-authored-by: damiano <adomani@gmail.com>

Diff
@@ -6,7 +6,6 @@ Authors: Frédéric Dupuis, Eric Wieser
 import Mathlib.GroupTheory.Congruence
 import Mathlib.LinearAlgebra.Basic
 import Mathlib.LinearAlgebra.Multilinear.TensorProduct
-import Mathlib.Tactic.LibrarySearch
 
 #align_import linear_algebra.pi_tensor_product from "leanprover-community/mathlib"@"ce11c3c2a285bbe6937e26d9792fda4e51f3fe1a"
 
@@ -535,7 +534,12 @@ variable (s) in
 def reindex (e : ι ≃ ι₂) : (⨂[R] i : ι, s i) ≃ₗ[R] ⨂[R] i : ι₂, s (e.symm i) :=
   let f := domDomCongrLinearEquiv' R R s (⨂[R] (i : ι₂), s (e.symm i)) e
   let g := domDomCongrLinearEquiv' R R s (⨂[R] (i : ι), s i) e
-  LinearEquiv.ofLinear (lift <| f.symm <| tprod R) (lift <| g <| tprod R) (by aesop) (by aesop)
+  LinearEquiv.ofLinear (lift <| f.symm <| tprod R) (lift <| g <| tprod R)
+    -- Adaptation note: v4.7.0-rc1
+    -- An alternative here would be `aesop (simp_config := {zetaDelta := true})`
+    -- or a wrapper macro to that effect.
+    (by aesop (add norm simp [f, g]))
+    (by aesop (add norm simp [f, g]))
 #align pi_tensor_product.reindex PiTensorProduct.reindex
 
 end
style: homogenise porting notes (#11145)

Homogenises porting notes via capitalisation and addition of whitespace.

It makes the following changes:

  • converts "--porting note" into "-- Porting note";
  • converts "porting note" into "Porting note".
Diff
@@ -317,7 +317,7 @@ unsuppress_compilation in
 @[inherit_doc tprod]
 notation3:100 "⨂ₜ["R"] "(...)", "r:(scoped f => tprod R f) => r
 
---Porting note: new theorem
+-- Porting note: new theorem
 theorem tprod_eq_tprodCoeff_one :
     ⇑(tprod R : MultilinearMap R s (⨂[R] i, s i)) = tprodCoeff R 1 := rfl
 
feat(LinearAlgebra/PiTensorProduct): arbitrary tensor product of algebras (#9395)

Let $R$ be a commutative ring and $(A_i)$ a bunch of $R$-algebras, then $\bigotimes_{R} A$ is an $R$-algebra as well. In particular, taking $R$ to be $\mathbb{Z}$, we get tensor product of rings

Co-authored-by: Riccardo Brasca <riccardo.brasca@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -357,6 +357,8 @@ open MultilinearMap
 
 variable {s}
 
+section lift
+
 /-- Auxiliary function to constructing a linear map `(⨂[R] i, s i) → E` given a
 `MultilinearMap R s E` with the property that its composition with the canonical
 `MultilinearMap R s (⨂[R] i, s i)` is the given multilinear map. -/
@@ -446,6 +448,84 @@ theorem lift_tprod : lift (tprod R : MultilinearMap R s _) = LinearMap.id :=
   Eq.symm <| lift.unique' rfl
 #align pi_tensor_product.lift_tprod PiTensorProduct.lift_tprod
 
+end lift
+
+section map
+
+variable {t t' : ι → Type*}
+variable [∀ i, AddCommMonoid (t i)] [∀ i, Module R (t i)]
+variable [∀ i, AddCommMonoid (t' i)] [∀ i, Module R (t' i)]
+
+/--
+Let `sᵢ` and `tᵢ` be two families of `R`-modules.
+Let `f` be a family of `R`-linear maps between `sᵢ` and `tᵢ`, i.e. `f : Πᵢ sᵢ → tᵢ`,
+then there is an induced map `⨂ᵢ sᵢ → ⨂ᵢ tᵢ` by `⨂ aᵢ ↦ ⨂ fᵢ aᵢ`.
+
+This is `TensorProduct.map` for an arbitrary family of modules.
+-/
+def map (f : Π i, s i →ₗ[R] t i) : (⨂[R] i, s i) →ₗ[R] ⨂[R] i, t i :=
+  lift <| (tprod R).compLinearMap f
+
+@[simp] lemma map_tprod (f : Π i, s i →ₗ[R] t i) (x : Π i, s i) :
+    map f (tprod R x) = tprod R fun i ↦ f i (x i) :=
+  lift.tprod _
+
+/--
+Let `sᵢ` and `tᵢ` be families of `R`-modules.
+Then there is an `R`-linear map between `⨂ᵢ Hom(sᵢ, tᵢ)` and `Hom(⨂ᵢ sᵢ, ⨂ tᵢ)` defined by
+`⨂ᵢ fᵢ ↦ ⨂ᵢ aᵢ ↦ ⨂ᵢ fᵢ aᵢ`.
+
+This is `TensorProduct.homTensorHomMap` for an arbitrary family of modules.
+
+Note that `PiTensorProduct.piTensorHomMap (tprod R f)` is equal to `PiTensorProduct.map f`.
+-/
+def piTensorHomMap : (⨂[R] i, s i →ₗ[R] t i) →ₗ[R] (⨂[R] i, s i) →ₗ[R] ⨂[R] i, t i :=
+  lift.toLinearMap ∘ₗ lift (MultilinearMap.piLinearMap <| tprod R)
+
+@[simp] lemma piTensorHomMap_tprod_tprod (f : Π i, s i →ₗ[R] t i) (x : Π i, s i) :
+    piTensorHomMap (tprod R f) (tprod R x) = tprod R fun i ↦ f i (x i) := by
+  simp [piTensorHomMap]
+
+lemma piTensorHomMap_tprod_eq_map (f : Π i, s i →ₗ[R] t i) :
+    piTensorHomMap (tprod R f) = map f := by
+  ext; simp
+
+/--
+Let `sᵢ`, `tᵢ` and `t'ᵢ` be families of `R`-modules, then `f : Πᵢ sᵢ → tᵢ → t'ᵢ` induces an
+element of `Hom(⨂ᵢ sᵢ, Hom(⨂ tᵢ, ⨂ᵢ t'ᵢ))` defined by `⨂ᵢ aᵢ ↦ ⨂ᵢ bᵢ ↦ ⨂ᵢ fᵢ aᵢ bᵢ`.
+
+This is `PiTensorProduct.map` for two arbitrary families of modules.
+This is `TensorProduct.map₂` for families of modules.
+-/
+def map₂ (f : Π i, s i →ₗ[R] t i →ₗ[R] t' i) :
+    (⨂[R] i, s i) →ₗ[R] (⨂[R] i, t i) →ₗ[R] ⨂[R] i, t' i:=
+  lift <| LinearMap.compMultilinearMap piTensorHomMap <| (tprod R).compLinearMap f
+
+lemma map₂_tprod_tprod (f : Π i, s i →ₗ[R] t i →ₗ[R] t' i) (x : Π i, s i) (y : Π i, t i) :
+    map₂ f (tprod R x) (tprod R y) = tprod R fun i ↦ f i (x i) (y i) := by
+  simp [map₂]
+
+/--
+Let `sᵢ`, `tᵢ` and `t'ᵢ` be families of `R`-modules.
+Then there is an linear map from `⨂ᵢ Hom(sᵢ, Hom(tᵢ, t'ᵢ))` to `Hom(⨂ᵢ sᵢ, Hom(⨂ tᵢ, ⨂ᵢ t'ᵢ))`
+defined by `⨂ᵢ fᵢ ↦ ⨂ᵢ aᵢ ↦ ⨂ᵢ bᵢ ↦ ⨂ᵢ fᵢ aᵢ bᵢ`.
+
+This is `TensorProduct.homTensorHomMap` for two arbitrary families of modules.
+-/
+def piTensorHomMap₂ : (⨂[R] i, s i →ₗ[R] t i →ₗ[R] t' i) →ₗ[R]
+    (⨂[R] i, s i) →ₗ[R] (⨂[R] i, t i) →ₗ[R] (⨂[R] i, t' i) where
+  toFun φ := lift <| LinearMap.compMultilinearMap piTensorHomMap <|
+    (lift <| MultilinearMap.piLinearMap <| tprod R) φ
+  map_add' x y := by dsimp; ext; simp
+  map_smul' r x := by dsimp; ext; simp
+
+@[simp] lemma piTensorHomMap₂_tprod_tprod_tprod
+    (f : ∀ i, s i →ₗ[R] t i →ₗ[R] t' i) (a : ∀ i, s i) (b : ∀ i, t i) :
+    piTensorHomMap₂ (tprod R f) (tprod R a) (tprod R b) = tprod R (fun i ↦ f i (a i) (b i)) := by
+  simp [piTensorHomMap₂]
+
+end map
+
 section
 
 variable (R M)
doc(LinearAlgebra/PiTensorProduct): improve docstring for tprod notation (#11063)

Also remove a TODO by @kmill; tprod r fun i => f i delaborates correctly now. tprod R f does not use notation, but this is no different to the behavior of Finset.sum s f.

Diff
@@ -35,7 +35,7 @@ binary tensor product in `LinearAlgebra/TensorProduct.lean`.
 ## Notations
 
 * `⨂[R] i, s i` is defined as localized notation in locale `TensorProduct`.
-* `⨂ₜ[R] i, f i` with `f : ∀ i, f i` is defined globally as the tensor product of all the `f i`'s.
+* `⨂ₜ[R] i, f i` with `f : ∀ i, s i` is defined globally as the tensor product of all the `f i`'s.
 
 ## Implementation notes
 
@@ -301,7 +301,9 @@ instance : IsScalarTower R R (⨂[R] i, s i) :=
 
 variable (R)
 
-/-- The canonical `MultilinearMap R s (⨂[R] i, s i)`. -/
+/-- The canonical `MultilinearMap R s (⨂[R] i, s i)`.
+
+`tprod R fun i => f i` has notation `⨂ₜ[R] i, f i`. -/
 def tprod : MultilinearMap R s (⨂[R] i, s i) where
   toFun := tprodCoeff R 1
   map_add' {_ f} i x y := (add_tprodCoeff (1 : R) f i x y).symm
@@ -312,8 +314,7 @@ def tprod : MultilinearMap R s (⨂[R] i, s i) where
 variable {R}
 
 unsuppress_compilation in
-/-- pure tensor in tensor product over some index type -/
--- TODO(kmill) The generated delaborator never applies; figure out why this doesn't pretty print.
+@[inherit_doc tprod]
 notation3:100 "⨂ₜ["R"] "(...)", "r:(scoped f => tprod R f) => r
 
 --Porting note: new theorem
chore: rename arguments to PiTensorProduct induction principles (#10904)

This looks much nicer in the induction tactic than C1 and Cp, as

induction a using PiTensorProduct.induction_on with
| smul_tprod r a => sorry
| add x y hx hy => sorry
Diff
@@ -205,17 +205,19 @@ def liftAddHom (φ : (R × Π i, s i) → F)
         (AddCon.ker_rel _).2 <| by simp_rw [AddMonoidHom.map_add, add_comm]
 #align pi_tensor_product.lift_add_hom PiTensorProduct.liftAddHom
 
+/-- Induct using `tprodCoeff` -/
 @[elab_as_elim]
-protected theorem induction_on' {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i)
-    (C1 : ∀ {r : R} {f : Π i, s i}, C (tprodCoeff R r f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
-    C z := by
-  have C0 : C 0 := by
-    have h₁ := @C1 0 0
+protected theorem induction_on' {motive : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i)
+    (tprodCoeff : ∀ (r : R) (f : Π i, s i), motive (tprodCoeff R r f))
+    (add : ∀ x y, motive x → motive y → motive (x + y)) :
+    motive z := by
+  have C0 : motive 0 := by
+    have h₁ := tprodCoeff 0 0
     rwa [zero_tprodCoeff] at h₁
   refine' AddCon.induction_on z fun x ↦ FreeAddMonoid.recOn x C0 _
   simp_rw [AddCon.coe_add]
-  refine' fun f y ih ↦ Cp _ ih
-  convert@C1 f.1 f.2
+  refine' fun f y ih ↦ add _ _ _ ih
+  convert tprodCoeff f.1 f.2
 #align pi_tensor_product.induction_on' PiTensorProduct.induction_on'
 
 section DistribMulAction
@@ -324,12 +326,14 @@ theorem tprodCoeff_eq_smul_tprod (z : R) (f : Π i, s i) : tprodCoeff R z f = z
   conv_lhs => rw [this]
 #align pi_tensor_product.tprod_coeff_eq_smul_tprod PiTensorProduct.tprodCoeff_eq_smul_tprod
 
+/-- Induct using scaled versions of `PiTensorProduct.tprod`. -/
 @[elab_as_elim]
-protected theorem induction_on {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i)
-    (C1 : ∀ {r : R} {f : Π i, s i}, C (r • tprod R f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
-    C z := by
-  simp_rw [← tprodCoeff_eq_smul_tprod] at C1
-  exact PiTensorProduct.induction_on' z @C1 @Cp
+protected theorem induction_on {motive : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i)
+    (smul_tprod : ∀ (r : R) (f : Π i, s i), motive (r • tprod R f))
+    (add : ∀ x y, motive x → motive y → motive (x + y)) :
+    motive z := by
+  simp_rw [← tprodCoeff_eq_smul_tprod] at smul_tprod
+  exact PiTensorProduct.induction_on' z smul_tprod add
 #align pi_tensor_product.induction_on PiTensorProduct.induction_on
 
 @[ext]
chore: Move LinearMap.ker to a new file (#10233)

This shortens Mathlib.LinearAlgebra.Basic, which is both longer than we like and doesn't have a clear scope.

Diff
@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Frédéric Dupuis, Eric Wieser
 -/
 import Mathlib.GroupTheory.Congruence
+import Mathlib.LinearAlgebra.Basic
 import Mathlib.LinearAlgebra.Multilinear.TensorProduct
 import Mathlib.Tactic.LibrarySearch
 
refactor(Data/FunLike): use unbundled inheritance from FunLike (#8386)

The FunLike hierarchy is very big and gets scanned through each time we need a coercion (via the CoeFun instance). It looks like unbundled inheritance suits Lean 4 better here. The only class that still extends FunLike is EquivLike, since that has a custom coe_injective' field that is easier to implement. All other classes should take FunLike or EquivLike as a parameter.

Zulip thread

Important changes

Previously, morphism classes would be Type-valued and extend FunLike:

/-- `MyHomClass F A B` states that `F` is a type of `MyClass.op`-preserving morphisms.
You should extend this class when you extend `MyHom`. -/
class MyHomClass (F : Type*) (A B : outParam <| Type*) [MyClass A] [MyClass B]
  extends FunLike F A B :=
(map_op : ∀ (f : F) (x y : A), f (MyClass.op x y) = MyClass.op (f x) (f y))

After this PR, they should be Prop-valued and take FunLike as a parameter:

/-- `MyHomClass F A B` states that `F` is a type of `MyClass.op`-preserving morphisms.
You should extend this class when you extend `MyHom`. -/
class MyHomClass (F : Type*) (A B : outParam <| Type*) [MyClass A] [MyClass B]
  [FunLike F A B] : Prop :=
(map_op : ∀ (f : F) (x y : A), f (MyClass.op x y) = MyClass.op (f x) (f y))

(Note that A B stay marked as outParam even though they are not purely required to be so due to the FunLike parameter already filling them in. This is required to see through type synonyms, which is important in the category theory library. Also, I think keeping them as outParam is slightly faster.)

Similarly, MyEquivClass should take EquivLike as a parameter.

As a result, every mention of [MyHomClass F A B] should become [FunLike F A B] [MyHomClass F A B].

Remaining issues

Slower (failing) search

While overall this gives some great speedups, there are some cases that are noticeably slower. In particular, a failing application of a lemma such as map_mul is more expensive. This is due to suboptimal processing of arguments. For example:

variable [FunLike F M N] [Mul M] [Mul N] (f : F) (x : M) (y : M)

theorem map_mul [MulHomClass F M N] : f (x * y) = f x * f y

example [AddHomClass F A B] : f (x * y) = f x * f y := map_mul f _ _

Before this PR, applying map_mul f gives the goals [Mul ?M] [Mul ?N] [MulHomClass F ?M ?N]. Since M and N are out_params, [MulHomClass F ?M ?N] is synthesized first, supplies values for ?M and ?N and then the Mul M and Mul N instances can be found.

After this PR, the goals become [FunLike F ?M ?N] [Mul ?M] [Mul ?N] [MulHomClass F ?M ?N]. Now [FunLike F ?M ?N] is synthesized first, supplies values for ?M and ?N and then the Mul M and Mul N instances can be found, before trying MulHomClass F M N which fails. Since the Mul hierarchy is very big, this can be slow to fail, especially when there is no such Mul instance.

A long-term but harder to achieve solution would be to specify the order in which instance goals get solved. For example, we'd like to change the arguments to map_mul to look like [FunLike F M N] [Mul M] [Mul N] [highPriority <| MulHomClass F M N] because MulHomClass fails or succeeds much faster than the others.

As a consequence, the simpNF linter is much slower since by design it tries and fails to apply many map_ lemmas. The same issue occurs a few times in existing calls to simp [map_mul], where map_mul is tried "too soon" and fails. Thanks to the speedup of leanprover/lean4#2478 the impact is very limited, only in files that already were close to the timeout.

simp not firing sometimes

This affects map_smulₛₗ and related definitions. For simp lemmas Lean apparently uses a slightly different mechanism to find instances, so that rw can find every argument to map_smulₛₗ successfully but simp can't: leanprover/lean4#3701.

Missing instances due to unification failing

Especially in the category theory library, we might sometimes have a type A which is also accessible as a synonym (Bundled A hA).1. Instance synthesis doesn't always work if we have f : A →* B but x * y : (Bundled A hA).1 or vice versa. This seems to be mostly fixed by keeping A B as outParams in MulHomClass F A B. (Presumably because Lean will do a definitional check A =?= (Bundled A hA).1 instead of using the syntax in the discrimination tree.)

Workaround for issues

The timeouts can be worked around for now by specifying which map_mul we mean, either as map_mul f for some explicit f, or as e.g. MonoidHomClass.map_mul.

map_smulₛₗ not firing as simp lemma can be worked around by going back to the pre-FunLike situation and making LinearMap.map_smulₛₗ a simp lemma instead of the generic map_smulₛₗ. Writing simp [map_smulₛₗ _] also works.

Co-authored-by: Matthew Ballard <matt@mrb.email> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Scott Morrison <scott@tqft.net> Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>

Diff
@@ -538,7 +538,8 @@ def isEmptyEquiv [IsEmpty ι] : (⨂[R] i : ι, s i) ≃ₗ[R] R where
   left_inv x := by
     refine x.induction_on ?_ ?_
     · intro x y
-      simp only [map_smulₛₗ, RingHom.id_apply, lift.tprod, constOfIsEmpty_apply, const_apply,
+      -- Note: #8386 had to change `map_smulₛₗ` into `map_smulₛₗ _`
+      simp only [map_smulₛₗ _, RingHom.id_apply, lift.tprod, constOfIsEmpty_apply, const_apply,
         smul_eq_mul, mul_one]
       congr
       aesop
feat(LinearAlgebra/PiTensorProduct): make reindex dependently typed (#9445)

used to be (⨂[R] _ : ι, M) ≃ₗ[R] ⨂[R] _ : ι₂, M, now M can vary according to the indexing set.

Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -13,7 +13,7 @@ import Mathlib.Tactic.LibrarySearch
 # Tensor product of an indexed family of modules over commutative semirings
 
 We define the tensor product of an indexed family `s : ι → Type*` of modules over commutative
-semirings. We denote this space by `⨂[R] i, s i` and define it as `FreeAddMonoid (R × ∀ i, s i)`
+semirings. We denote this space by `⨂[R] i, s i` and define it as `FreeAddMonoid (R × Π i, s i)`
 quotiented by the appropriate equivalence relation. The treatment follows very closely that of the
 binary tensor product in `LinearAlgebra/TensorProduct.lean`.
 
@@ -21,10 +21,10 @@ binary tensor product in `LinearAlgebra/TensorProduct.lean`.
 
 * `PiTensorProduct R s` with `R` a commutative semiring and `s : ι → Type*` is the tensor product
   of all the `s i`'s. This is denoted by `⨂[R] i, s i`.
-* `tprod R f` with `f : ∀ i, s i` is the tensor product of the vectors `f i` over all `i : ι`.
-  This is bundled as a multilinear map from `∀ i, s i` to `⨂[R] i, s i`.
+* `tprod R f` with `f : Π i, s i` is the tensor product of the vectors `f i` over all `i : ι`.
+  This is bundled as a multilinear map from `Π i, s i` to `⨂[R] i, s i`.
 * `liftAddHom` constructs an `AddMonoidHom` from `(⨂[R] i, s i)` to some space `F` from a
-  function `φ : (R × ∀ i, s i) → F` with the appropriate properties.
+  function `φ : (R × Π i, s i) → F` with the appropriate properties.
 * `lift φ` with `φ : MultilinearMap R s E` is the corresponding linear map
   `(⨂[R] i, s i) →ₗ[R] E`. This is bundled as a linear equivalence.
 * `PiTensorProduct.reindex e` re-indexes the components of `⨂[R] i : ι, M` along `e : ι ≃ ι₂`.
@@ -38,8 +38,8 @@ binary tensor product in `LinearAlgebra/TensorProduct.lean`.
 
 ## Implementation notes
 
-* We define it via `FreeAddMonoid (R × ∀ i, s i)` with the `R` representing a "hidden" tensor
-  factor, rather than `FreeAddMonoid (∀ i, s i)` to ensure that, if `ι` is an empty type,
+* We define it via `FreeAddMonoid (R × Π i, s i)` with the `R` representing a "hidden" tensor
+  factor, rather than `FreeAddMonoid (Π i, s i)` to ensure that, if `ι` is an empty type,
   the space is isomorphic to the base ring `R`.
 * We have not restricted the index type `ι` to be a `Fintype`, as nothing we do here strictly
   requires it. However, problems may arise in the case where `ι` is infinite; use at your own
@@ -86,17 +86,17 @@ namespace PiTensorProduct
 
 variable (R) (s)
 
-/-- The relation on `FreeAddMonoid (R × ∀ i, s i)` that generates a congruence whose quotient is
+/-- The relation on `FreeAddMonoid (R × Π i, s i)` that generates a congruence whose quotient is
 the tensor product. -/
-inductive Eqv : FreeAddMonoid (R × ∀ i, s i) → FreeAddMonoid (R × ∀ i, s i) → Prop
-  | of_zero : ∀ (r : R) (f : ∀ i, s i) (i : ι) (_ : f i = 0), Eqv (FreeAddMonoid.of (r, f)) 0
-  | of_zero_scalar : ∀ f : ∀ i, s i, Eqv (FreeAddMonoid.of (0, f)) 0
-  | of_add : ∀ (_ : DecidableEq ι) (r : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i),
+inductive Eqv : FreeAddMonoid (R × Π i, s i) → FreeAddMonoid (R × Π i, s i) → Prop
+  | of_zero : ∀ (r : R) (f : Π i, s i) (i : ι) (_ : f i = 0), Eqv (FreeAddMonoid.of (r, f)) 0
+  | of_zero_scalar : ∀ f : Π i, s i, Eqv (FreeAddMonoid.of (0, f)) 0
+  | of_add : ∀ (_ : DecidableEq ι) (r : R) (f : Π i, s i) (i : ι) (m₁ m₂ : s i),
       Eqv (FreeAddMonoid.of (r, update f i m₁) + FreeAddMonoid.of (r, update f i m₂))
         (FreeAddMonoid.of (r, update f i (m₁ + m₂)))
-  | of_add_scalar : ∀ (r r' : R) (f : ∀ i, s i),
+  | of_add_scalar : ∀ (r r' : R) (f : Π i, s i),
       Eqv (FreeAddMonoid.of (r, f) + FreeAddMonoid.of (r', f)) (FreeAddMonoid.of (r + r', f))
-  | of_smul : ∀ (_ : DecidableEq ι) (r : R) (f : ∀ i, s i) (i : ι) (r' : R),
+  | of_smul : ∀ (_ : DecidableEq ι) (r : R) (f : Π i, s i) (i : ι) (r' : R),
       Eqv (FreeAddMonoid.of (r, update f i (r' • f i))) (FreeAddMonoid.of (r' * r, f))
   | add_comm : ∀ x y, Eqv (x + y) (y + x)
 #align pi_tensor_product.eqv PiTensorProduct.Eqv
@@ -134,40 +134,40 @@ instance : Inhabited (⨂[R] i, s i) := ⟨0⟩
 
 variable (R) {s}
 
-/-- `tprodCoeff R r f` with `r : R` and `f : ∀ i, s i` is the tensor product of the vectors `f i`
+/-- `tprodCoeff R r f` with `r : R` and `f : Π i, s i` is the tensor product of the vectors `f i`
 over all `i : ι`, multiplied by the coefficient `r`. Note that this is meant as an auxiliary
 definition for this file alone, and that one should use `tprod` defined below for most purposes. -/
-def tprodCoeff (r : R) (f : ∀ i, s i) : ⨂[R] i, s i :=
+def tprodCoeff (r : R) (f : Π i, s i) : ⨂[R] i, s i :=
   AddCon.mk' _ <| FreeAddMonoid.of (r, f)
 #align pi_tensor_product.tprod_coeff PiTensorProduct.tprodCoeff
 
 variable {R}
 
-theorem zero_tprodCoeff (f : ∀ i, s i) : tprodCoeff R 0 f = 0 :=
+theorem zero_tprodCoeff (f : Π i, s i) : tprodCoeff R 0 f = 0 :=
   Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_zero_scalar _
 #align pi_tensor_product.zero_tprod_coeff PiTensorProduct.zero_tprodCoeff
 
-theorem zero_tprodCoeff' (z : R) (f : ∀ i, s i) (i : ι) (hf : f i = 0) : tprodCoeff R z f = 0 :=
+theorem zero_tprodCoeff' (z : R) (f : Π i, s i) (i : ι) (hf : f i = 0) : tprodCoeff R z f = 0 :=
   Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_zero _ _ i hf
 #align pi_tensor_product.zero_tprod_coeff' PiTensorProduct.zero_tprodCoeff'
 
-theorem add_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i) :
+theorem add_tprodCoeff [DecidableEq ι] (z : R) (f : Π i, s i) (i : ι) (m₁ m₂ : s i) :
     tprodCoeff R z (update f i m₁) + tprodCoeff R z (update f i m₂) =
       tprodCoeff R z (update f i (m₁ + m₂)) :=
   Quotient.sound' <| AddConGen.Rel.of _ _ (Eqv.of_add _ z f i m₁ m₂)
 #align pi_tensor_product.add_tprod_coeff PiTensorProduct.add_tprodCoeff
 
-theorem add_tprodCoeff' (z₁ z₂ : R) (f : ∀ i, s i) :
+theorem add_tprodCoeff' (z₁ z₂ : R) (f : Π i, s i) :
     tprodCoeff R z₁ f + tprodCoeff R z₂ f = tprodCoeff R (z₁ + z₂) f :=
   Quotient.sound' <| AddConGen.Rel.of _ _ (Eqv.of_add_scalar z₁ z₂ f)
 #align pi_tensor_product.add_tprod_coeff' PiTensorProduct.add_tprodCoeff'
 
-theorem smul_tprodCoeff_aux [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r : R) :
+theorem smul_tprodCoeff_aux [DecidableEq ι] (z : R) (f : Π i, s i) (i : ι) (r : R) :
     tprodCoeff R z (update f i (r • f i)) = tprodCoeff R (r * z) f :=
   Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_smul _ _ _ _ _
 #align pi_tensor_product.smul_tprod_coeff_aux PiTensorProduct.smul_tprodCoeff_aux
 
-theorem smul_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r : R₁) [SMul R₁ R]
+theorem smul_tprodCoeff [DecidableEq ι] (z : R) (f : Π i, s i) (i : ι) (r : R₁) [SMul R₁ R]
     [IsScalarTower R₁ R R] [SMul R₁ (s i)] [IsScalarTower R₁ R (s i)] :
     tprodCoeff R z (update f i (r • f i)) = tprodCoeff R (r • z) f := by
   have h₁ : r • z = r • (1 : R) * z := by rw [smul_mul_assoc, one_mul]
@@ -177,14 +177,14 @@ theorem smul_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r :
 #align pi_tensor_product.smul_tprod_coeff PiTensorProduct.smul_tprodCoeff
 
 /-- Construct an `AddMonoidHom` from `(⨂[R] i, s i)` to some space `F` from a function
-`φ : (R × ∀ i, s i) → F` with the appropriate properties. -/
-def liftAddHom (φ : (R × ∀ i, s i) → F)
-    (C0 : ∀ (r : R) (f : ∀ i, s i) (i : ι) (_ : f i = 0), φ (r, f) = 0)
-    (C0' : ∀ f : ∀ i, s i, φ (0, f) = 0)
-    (C_add : ∀ [DecidableEq ι] (r : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i),
+`φ : (R × Π i, s i) → F` with the appropriate properties. -/
+def liftAddHom (φ : (R × Π i, s i) → F)
+    (C0 : ∀ (r : R) (f : Π i, s i) (i : ι) (_ : f i = 0), φ (r, f) = 0)
+    (C0' : ∀ f : Π i, s i, φ (0, f) = 0)
+    (C_add : ∀ [DecidableEq ι] (r : R) (f : Π i, s i) (i : ι) (m₁ m₂ : s i),
       φ (r, update f i m₁) + φ (r, update f i m₂) = φ (r, update f i (m₁ + m₂)))
-    (C_add_scalar : ∀ (r r' : R) (f : ∀ i, s i), φ (r, f) + φ (r', f) = φ (r + r', f))
-    (C_smul : ∀ [DecidableEq ι] (r : R) (f : ∀ i, s i) (i : ι) (r' : R),
+    (C_add_scalar : ∀ (r r' : R) (f : Π i, s i), φ (r, f) + φ (r', f) = φ (r + r', f))
+    (C_smul : ∀ [DecidableEq ι] (r : R) (f : Π i, s i) (i : ι) (r' : R),
       φ (r, update f i (r' • f i)) = φ (r' * r, f)) :
     (⨂[R] i, s i) →+ F :=
   (addConGen (PiTensorProduct.Eqv R s)).lift (FreeAddMonoid.lift φ) <|
@@ -206,7 +206,7 @@ def liftAddHom (φ : (R × ∀ i, s i) → F)
 
 @[elab_as_elim]
 protected theorem induction_on' {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i)
-    (C1 : ∀ {r : R} {f : ∀ i, s i}, C (tprodCoeff R r f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
+    (C1 : ∀ {r : R} {f : Π i, s i}, C (tprodCoeff R r f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
     C z := by
   have C0 : C 0 := by
     have h₁ := @C1 0 0
@@ -227,7 +227,7 @@ variable [Monoid R₂] [DistribMulAction R₂ R] [SMulCommClass R₂ R R]
 -- to find.
 instance hasSMul' : SMul R₁ (⨂[R] i, s i) :=
   ⟨fun r ↦
-    liftAddHom (fun f : R × ∀ i, s i ↦ tprodCoeff R (r • f.1) f.2)
+    liftAddHom (fun f : R × Π i, s i ↦ tprodCoeff R (r • f.1) f.2)
       (fun r' f i hf ↦ by simp_rw [zero_tprodCoeff' _ f i hf])
       (fun f ↦ by simp [zero_tprodCoeff]) (fun r' f i m₁ m₂ ↦ by simp [add_tprodCoeff])
       (fun r' r'' f ↦ by simp [add_tprodCoeff', mul_add]) fun z f i r' ↦ by
@@ -237,7 +237,7 @@ instance hasSMul' : SMul R₁ (⨂[R] i, s i) :=
 instance : SMul R (⨂[R] i, s i) :=
   PiTensorProduct.hasSMul'
 
-theorem smul_tprodCoeff' (r : R₁) (z : R) (f : ∀ i, s i) :
+theorem smul_tprodCoeff' (r : R₁) (z : R) (f : Π i, s i) :
     r • tprodCoeff R z f = tprodCoeff R (r • z) f := rfl
 #align pi_tensor_product.smul_tprod_coeff' PiTensorProduct.smul_tprodCoeff'
 
@@ -318,14 +318,14 @@ theorem tprod_eq_tprodCoeff_one :
     ⇑(tprod R : MultilinearMap R s (⨂[R] i, s i)) = tprodCoeff R 1 := rfl
 
 @[simp]
-theorem tprodCoeff_eq_smul_tprod (z : R) (f : ∀ i, s i) : tprodCoeff R z f = z • tprod R f := by
+theorem tprodCoeff_eq_smul_tprod (z : R) (f : Π i, s i) : tprodCoeff R z f = z • tprod R f := by
   have : z = z • (1 : R) := by simp only [mul_one, Algebra.id.smul_eq_mul]
   conv_lhs => rw [this]
 #align pi_tensor_product.tprod_coeff_eq_smul_tprod PiTensorProduct.tprodCoeff_eq_smul_tprod
 
 @[elab_as_elim]
 protected theorem induction_on {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i)
-    (C1 : ∀ {r : R} {f : ∀ i, s i}, C (r • tprod R f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
+    (C1 : ∀ {r : R} {f : Π i, s i}, C (r • tprod R f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) :
     C z := by
   simp_rw [← tprodCoeff_eq_smul_tprod] at C1
   exact PiTensorProduct.induction_on' z @C1 @Cp
@@ -355,7 +355,7 @@ variable {s}
 `MultilinearMap R s E` with the property that its composition with the canonical
 `MultilinearMap R s (⨂[R] i, s i)` is the given multilinear map. -/
 def liftAux (φ : MultilinearMap R s E) : (⨂[R] i, s i) →+ E :=
-  liftAddHom (fun p : R × ∀ i, s i ↦ p.1 • φ p.2)
+  liftAddHom (fun p : R × Π i, s i ↦ p.1 • φ p.2)
     (fun z f i hf ↦ by simp_rw [map_coord_zero φ i hf, smul_zero])
     (fun f ↦ by simp_rw [zero_smul])
     (fun z f i m₁ m₂ ↦ by simp_rw [← smul_add, φ.map_add])
@@ -363,7 +363,7 @@ def liftAux (φ : MultilinearMap R s E) : (⨂[R] i, s i) →+ E :=
     fun z f i r ↦ by simp [φ.map_smul, smul_smul, mul_comm]
 #align pi_tensor_product.lift_aux PiTensorProduct.liftAux
 
-theorem liftAux_tprod (φ : MultilinearMap R s E) (f : ∀ i, s i) : liftAux φ (tprod R f) = φ f := by
+theorem liftAux_tprod (φ : MultilinearMap R s E) (f : Π i, s i) : liftAux φ (tprod R f) = φ f := by
   simp only [liftAux, liftAddHom, tprod_eq_tprodCoeff_one, tprodCoeff, AddCon.coe_mk']
   -- The end of this proof was very different before leanprover/lean4#2644:
   -- rw [FreeAddMonoid.of, FreeAddMonoid.ofList, Equiv.refl_apply, AddCon.lift_coe]
@@ -380,7 +380,7 @@ theorem liftAux_tprod (φ : MultilinearMap R s E) (f : ∀ i, s i) : liftAux φ
 
 #align pi_tensor_product.lift_aux_tprod PiTensorProduct.liftAux_tprod
 
-theorem liftAux_tprodCoeff (φ : MultilinearMap R s E) (z : R) (f : ∀ i, s i) :
+theorem liftAux_tprodCoeff (φ : MultilinearMap R s E) (z : R) (f : Π i, s i) :
     liftAux φ (tprodCoeff R z f) = z • φ f := rfl
 #align pi_tensor_product.lift_aux_tprod_coeff PiTensorProduct.liftAux_tprodCoeff
 
@@ -416,7 +416,7 @@ def lift : MultilinearMap R s E ≃ₗ[R] (⨂[R] i, s i) →ₗ[R] E where
 variable {φ : MultilinearMap R s E}
 
 @[simp]
-theorem lift.tprod (f : ∀ i, s i) : lift φ (tprod R f) = φ f :=
+theorem lift.tprod (f : Π i, s i) : lift φ (tprod R f) = φ f :=
   liftAux_tprod φ f
 #align pi_tensor_product.lift.tprod PiTensorProduct.lift.tprod
 
@@ -444,61 +444,55 @@ section
 
 variable (R M)
 
-/-- Re-index the components of the tensor power by `e`.
-
-For simplicity, this is defined only for homogeneously- (rather than dependently-) typed components.
--/
-def reindex (e : ι ≃ ι₂) : (⨂[R] _ : ι, M) ≃ₗ[R] ⨂[R] _ : ι₂, M :=
-  LinearEquiv.ofLinear (lift (domDomCongr e.symm (tprod R : MultilinearMap R _ (⨂[R] _ : ι₂, M))))
-    (lift (domDomCongr e (tprod R : MultilinearMap R _ (⨂[R] _ : ι, M))))
-    (by
-      ext
-      simp only [LinearMap.comp_apply, LinearMap.id_apply, lift_tprod,
-        LinearMap.compMultilinearMap_apply, lift.tprod, domDomCongr_apply]
-      congr
-      ext
-      rw [e.apply_symm_apply])
-    (by
-      ext
-      simp only [LinearMap.comp_apply, LinearMap.id_apply, lift_tprod,
-        LinearMap.compMultilinearMap_apply, lift.tprod, domDomCongr_apply]
-      congr
-      ext
-      rw [e.symm_apply_apply])
+variable (s) in
+/-- Re-index the components of the tensor power by `e`.-/
+def reindex (e : ι ≃ ι₂) : (⨂[R] i : ι, s i) ≃ₗ[R] ⨂[R] i : ι₂, s (e.symm i) :=
+  let f := domDomCongrLinearEquiv' R R s (⨂[R] (i : ι₂), s (e.symm i)) e
+  let g := domDomCongrLinearEquiv' R R s (⨂[R] (i : ι), s i) e
+  LinearEquiv.ofLinear (lift <| f.symm <| tprod R) (lift <| g <| tprod R) (by aesop) (by aesop)
 #align pi_tensor_product.reindex PiTensorProduct.reindex
 
 end
 
 @[simp]
-theorem reindex_tprod (e : ι ≃ ι₂) (f : ι → M) :
-    reindex R M e (tprod R f) = tprod R fun i ↦ f (e.symm i) := by
+theorem reindex_tprod (e : ι ≃ ι₂) (f : Π i, s i) :
+    reindex R s e (tprod R f) = tprod R fun i ↦ f (e.symm i) := by
   dsimp [reindex]
   exact liftAux_tprod _ f
 #align pi_tensor_product.reindex_tprod PiTensorProduct.reindex_tprod
 
 @[simp]
 theorem reindex_comp_tprod (e : ι ≃ ι₂) :
-    (reindex R M e : (⨂[R] _ : ι, M) →ₗ[R] ⨂[R] _ : ι₂, M).compMultilinearMap (tprod R) =
-      (tprod R : MultilinearMap R (fun _ ↦ M) _).domDomCongr e.symm :=
+    (reindex R s e).compMultilinearMap (tprod R) =
+    (domDomCongrLinearEquiv' R R s _ e).symm (tprod R) :=
   MultilinearMap.ext <| reindex_tprod e
 #align pi_tensor_product.reindex_comp_tprod PiTensorProduct.reindex_comp_tprod
 
-@[simp]
-theorem lift_comp_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ : ι₂ ↦ M) E) :
-    lift φ ∘ₗ ↑(reindex R M e) = lift (φ.domDomCongr e.symm) := by
-  ext
-  simp
+theorem lift_comp_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun i ↦ s (e.symm i)) E) :
+    lift φ ∘ₗ (reindex R s e) = lift ((domDomCongrLinearEquiv' R R s _ e).symm φ) := by
+  ext; simp [reindex]
 #align pi_tensor_product.lift_comp_reindex PiTensorProduct.lift_comp_reindex
 
 @[simp]
-theorem lift_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ ↦ M) E) (x : ⨂[R] _, M) :
-    lift φ (reindex R M e x) = lift (φ.domDomCongr e.symm) x :=
+theorem lift_comp_reindex_symm (e : ι ≃ ι₂) (φ : MultilinearMap R s E) :
+    lift φ ∘ₗ (reindex R s e).symm = lift (domDomCongrLinearEquiv' R R s _ e φ) := by
+  ext; simp [reindex]
+
+theorem lift_reindex
+    (e : ι ≃ ι₂) (φ : MultilinearMap R (fun i ↦ s (e.symm i)) E) (x : ⨂[R] i, s i) :
+    lift φ (reindex R s e x) = lift ((domDomCongrLinearEquiv' R R s _ e).symm φ) x :=
   LinearMap.congr_fun (lift_comp_reindex e φ) x
 #align pi_tensor_product.lift_reindex PiTensorProduct.lift_reindex
 
+@[simp]
+theorem lift_reindex_symm
+    (e : ι ≃ ι₂) (φ : MultilinearMap R s E) (x : ⨂[R] i, s (e.symm i)) :
+    lift φ (reindex R s e |>.symm x) = lift (domDomCongrLinearEquiv' R R s _ e φ) x :=
+  LinearMap.congr_fun (lift_comp_reindex_symm e φ) x
+
 @[simp]
 theorem reindex_trans (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) :
-    (reindex R M e).trans (reindex R M e') = reindex R M (e.trans e') := by
+    (reindex R s e).trans (reindex R _ e') = reindex R s (e.trans e') := by
   apply LinearEquiv.toLinearMap_injective
   ext f
   simp only [LinearEquiv.trans_apply, LinearEquiv.coe_coe, reindex_tprod,
@@ -507,22 +501,30 @@ theorem reindex_trans (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) :
   congr
 #align pi_tensor_product.reindex_trans PiTensorProduct.reindex_trans
 
-@[simp]
-theorem reindex_reindex (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) (x : ⨂[R] _, M) :
-    reindex R M e' (reindex R M e x) = reindex R M (e.trans e') x :=
-  LinearEquiv.congr_fun (reindex_trans e e' : _ = reindex R M (e.trans e')) x
+theorem reindex_reindex (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) (x : ⨂[R] i, s i) :
+    reindex R _ e' (reindex R s e x) = reindex R s (e.trans e') x :=
+  LinearEquiv.congr_fun (reindex_trans e e' : _ = reindex R s (e.trans e')) x
 #align pi_tensor_product.reindex_reindex PiTensorProduct.reindex_reindex
 
+/-- This lemma is impractical to state in the dependent case. -/
 @[simp]
-theorem reindex_symm (e : ι ≃ ι₂) : (reindex R M e).symm = reindex R M e.symm := rfl
+theorem reindex_symm (e : ι ≃ ι₂) :
+    (reindex R (fun _ ↦ M) e).symm = reindex R (fun _ ↦ M) e.symm := by
+  ext x
+  simp only [reindex, domDomCongrLinearEquiv', LinearEquiv.coe_symm_mk, LinearEquiv.coe_mk,
+    LinearEquiv.ofLinear_symm_apply, Equiv.symm_symm_apply, LinearEquiv.ofLinear_apply,
+    Equiv.piCongrLeft'_symm]
 #align pi_tensor_product.reindex_symm PiTensorProduct.reindex_symm
 
 @[simp]
-theorem reindex_refl : reindex R M (Equiv.refl ι) = LinearEquiv.refl R _ := by
+theorem reindex_refl : reindex R s (Equiv.refl ι) = LinearEquiv.refl R _ := by
   apply LinearEquiv.toLinearMap_injective
   ext
-  rw [reindex_comp_tprod, LinearEquiv.refl_toLinearMap, Equiv.refl_symm]
-  rfl
+  simp only [Equiv.refl_symm, Equiv.refl_apply, reindex, domDomCongrLinearEquiv',
+    LinearEquiv.coe_symm_mk, LinearMap.compMultilinearMap_apply, LinearEquiv.coe_coe,
+    LinearEquiv.refl_toLinearMap, LinearMap.id_coe, id_eq]
+  erw [lift.tprod]
+  congr
 #align pi_tensor_product.reindex_refl PiTensorProduct.reindex_refl
 
 variable (ι)
@@ -530,7 +532,7 @@ variable (ι)
 attribute [local simp] eq_iff_true_of_subsingleton in
 /-- The tensor product over an empty index type `ι` is isomorphic to the base ring. -/
 @[simps symm_apply]
-def isEmptyEquiv [IsEmpty ι] : (⨂[R] _ : ι, M) ≃ₗ[R] R where
+def isEmptyEquiv [IsEmpty ι] : (⨂[R] i : ι, s i) ≃ₗ[R] R where
   toFun := lift (constOfIsEmpty R _ 1)
   invFun r := r • tprod R (@isEmptyElim _ _ _)
   left_inv x := by
@@ -551,7 +553,8 @@ def isEmptyEquiv [IsEmpty ι] : (⨂[R] _ : ι, M) ≃ₗ[R] R where
 #align pi_tensor_product.is_empty_equiv PiTensorProduct.isEmptyEquiv
 
 @[simp]
-theorem isEmptyEquiv_apply_tprod [IsEmpty ι] (f : ι → M) : isEmptyEquiv ι (tprod R f) = 1 :=
+theorem isEmptyEquiv_apply_tprod [IsEmpty ι] (f : (i : ι) → s i) :
+    isEmptyEquiv ι (tprod R f) = 1 :=
   lift.tprod _
 #align pi_tensor_product.is_empty_equiv_apply_tprod PiTensorProduct.isEmptyEquiv_apply_tprod
 
chore(*): use α → β instead of ∀ _ : α, β (#9529)
Diff
@@ -470,7 +470,7 @@ def reindex (e : ι ≃ ι₂) : (⨂[R] _ : ι, M) ≃ₗ[R] ⨂[R] _ : ι₂,
 end
 
 @[simp]
-theorem reindex_tprod (e : ι ≃ ι₂) (f : ∀ _, M) :
+theorem reindex_tprod (e : ι ≃ ι₂) (f : ι → M) :
     reindex R M e (tprod R f) = tprod R fun i ↦ f (e.symm i) := by
   dsimp [reindex]
   exact liftAux_tprod _ f
refactor(*/Multilinear): change *.ofSubsingleton (#8694)

Change MultilinearMap.ofSubsingleton and other similar definitions so that they are now equivalences between linear maps and 1-multilinear maps.

Diff
@@ -562,22 +562,21 @@ Tensor product of `M` over a singleton set is equivalent to `M`
 -/
 @[simps symm_apply]
 def subsingletonEquiv [Subsingleton ι] (i₀ : ι) : (⨂[R] _ : ι, M) ≃ₗ[R] M where
-  toFun := lift (MultilinearMap.ofSubsingleton R M i₀)
+  toFun := lift (MultilinearMap.ofSubsingleton R M M i₀ .id)
   invFun m := tprod R fun _ ↦ m
   left_inv x := by
     dsimp only
-    have : ∀ (f : ι → M) (z : M), (fun _ : ι ↦ z) = update f i₀ z := by
-      intro f z
+    have : ∀ (f : ι → M) (z : M), (fun _ : ι ↦ z) = update f i₀ z := fun f z ↦ by
       ext i
       rw [Subsingleton.elim i i₀, Function.update_same]
     refine x.induction_on ?_ ?_
     · intro r f
-      simp only [LinearMap.map_smul, lift.tprod, ofSubsingleton_apply, Function.eval, this f,
-        MultilinearMap.map_smul, update_eq_self]
+      simp only [LinearMap.map_smul, LinearMap.id_apply, lift.tprod, ofSubsingleton_apply_apply,
+        this f, MultilinearMap.map_smul, update_eq_self]
     · intro x y hx hy
       rw [LinearMap.map_add, this 0 (_ + _), MultilinearMap.map_add, ← this 0 (lift _ _), hx,
         ← this 0 (lift _ _), hy]
-  right_inv t := by simp only [ofSubsingleton_apply, lift.tprod, Function.eval_apply]
+  right_inv t := by simp only [ofSubsingleton_apply_apply, LinearMap.id_apply, lift.tprod]
   map_add' := LinearMap.map_add _
   map_smul' := fun r x => by
     simp only
fix: attribute [simp] ... in -> attribute [local simp] ... in (#7678)

Mathlib.Logic.Unique contains the line attribute [simp] eq_iff_true_of_subsingleton in ...:

https://github.com/leanprover-community/mathlib4/blob/96a11c7aac574c00370c2b3dab483cb676405c5d/Mathlib/Logic/Unique.lean#L255-L256

Despite what the in part may imply, this adds the lemma to the simp set "globally", including for downstream files; it is likely that attribute [local simp] eq_iff_true_of_subsingleton in ... was meant instead (or maybe scoped simp, but I think "scoped" refers to the current namespace). Indeed, the relevant lemma is not marked with @[simp] for possible slowness: https://github.com/leanprover/std4/blob/846e9e1d6bb534774d1acd2dc430e70987da3c18/Std/Logic.lean#L749. Adding it to the simp set causes the example at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Regression.20in.20simp to slow down.

This PR changes this and fixes the relevant downstream simps. There was also one ocurrence of attribute [simp] FullSubcategory.comp_def FullSubcategory.id_def in in Mathlib.CategoryTheory.Monoidal.Subcategory but that was much easier to fix.

https://github.com/leanprover-community/mathlib4/blob/bc49eb9ba756a233370b4b68bcdedd60402f71ed/Mathlib/CategoryTheory/Monoidal/Subcategory.lean#L118-L119

Diff
@@ -527,6 +527,7 @@ theorem reindex_refl : reindex R M (Equiv.refl ι) = LinearEquiv.refl R _ := by
 
 variable (ι)
 
+attribute [local simp] eq_iff_true_of_subsingleton in
 /-- The tensor product over an empty index type `ι` is isomorphic to the base ring. -/
 @[simps symm_apply]
 def isEmptyEquiv [IsEmpty ι] : (⨂[R] _ : ι, M) ≃ₗ[R] R where
feat: enable scoped[ns] prefix for notation3 (#8096)
Diff
@@ -114,10 +114,9 @@ def PiTensorProduct : Type _ :=
 variable {R}
 
 unsuppress_compilation in
--- This enables the notation `⨂[R] i : ι, s i` for the pi tensor product, given `s : ι → Type*`.
---scoped[TensorProduct] -- Porting note: `scoped` caused an error, so I commented it out.
-/-- notation for tensor product over some indexed type -/
-notation3:100"⨂["R"] "(...)", "r:(scoped f => PiTensorProduct R f) => r
+/-- This enables the notation `⨂[R] i : ι, s i` for the pi tensor product `PiTensorProduct`,
+given an indexed family of types `s : ι → Type*`. -/
+scoped[TensorProduct] notation3:100"⨂["R"] "(...)", "r:(scoped f => PiTensorProduct R f) => r
 
 open TensorProduct
 
feat: have notation3 use elaborator when generating matchers, add support for pi/lambda (#6833)

notation3 was generating matchers directly from syntax, which included a half-baked implementation of a term elaborator. This switches to elaborating the term and then generating matchers from the elaborated term. This

  1. is more robust and consistent, since it uses the main elaborator and one can make use of other notations
  2. has the nice side effect of adding term info to expansions in the notation3 command
  3. can unfortunately generate matchers that are more restrictive than before since they also match against elaborated features such as implicit arguments.

We now also generate matchers for expansions that have pi types and lambda expressions.

Diff
@@ -311,9 +311,8 @@ variable {R}
 
 unsuppress_compilation in
 /-- pure tensor in tensor product over some index type -/
--- Porting note: use `FunLike.coe` as an explicit coercion to help `notation3` pretty print,
--- was just `tprod R f`.
-notation3:100 "⨂ₜ["R"] "(...)", "r:(scoped f => FunLike.coe (tprod R) f) => r
+-- TODO(kmill) The generated delaborator never applies; figure out why this doesn't pretty print.
+notation3:100 "⨂ₜ["R"] "(...)", "r:(scoped f => tprod R f) => r
 
 --Porting note: new theorem
 theorem tprod_eq_tprodCoeff_one :
Revert "chore: revert #7703 (#7710)"

This reverts commit f3695eb2.

Diff
@@ -367,10 +367,19 @@ def liftAux (φ : MultilinearMap R s E) : (⨂[R] i, s i) →+ E :=
 
 theorem liftAux_tprod (φ : MultilinearMap R s E) (f : ∀ i, s i) : liftAux φ (tprod R f) = φ f := by
   simp only [liftAux, liftAddHom, tprod_eq_tprodCoeff_one, tprodCoeff, AddCon.coe_mk']
-  rw [FreeAddMonoid.of, FreeAddMonoid.ofList, Equiv.refl_apply, AddCon.lift_coe]
-  dsimp [FreeAddMonoid.lift, FreeAddMonoid.sumAux]
-  show _ • _ = _
-  rw [one_smul]
+  -- The end of this proof was very different before leanprover/lean4#2644:
+  -- rw [FreeAddMonoid.of, FreeAddMonoid.ofList, Equiv.refl_apply, AddCon.lift_coe]
+  -- dsimp [FreeAddMonoid.lift, FreeAddMonoid.sumAux]
+  -- show _ • _ = _
+  -- rw [one_smul]
+  erw [AddCon.lift_coe]
+  erw [FreeAddMonoid.of]
+  dsimp [FreeAddMonoid.ofList]
+  rw [← one_smul R (φ f)]
+  erw [Equiv.refl_apply]
+  convert one_smul R (φ f)
+  simp
+
 #align pi_tensor_product.lift_aux_tprod PiTensorProduct.liftAux_tprod
 
 theorem liftAux_tprodCoeff (φ : MultilinearMap R s E) (z : R) (f : ∀ i, s i) :
chore: revert #7703 (#7710)

This reverts commit 26eb2b0a.

Diff
@@ -367,19 +367,10 @@ def liftAux (φ : MultilinearMap R s E) : (⨂[R] i, s i) →+ E :=
 
 theorem liftAux_tprod (φ : MultilinearMap R s E) (f : ∀ i, s i) : liftAux φ (tprod R f) = φ f := by
   simp only [liftAux, liftAddHom, tprod_eq_tprodCoeff_one, tprodCoeff, AddCon.coe_mk']
-  -- The end of this proof was very different before leanprover/lean4#2644:
-  -- rw [FreeAddMonoid.of, FreeAddMonoid.ofList, Equiv.refl_apply, AddCon.lift_coe]
-  -- dsimp [FreeAddMonoid.lift, FreeAddMonoid.sumAux]
-  -- show _ • _ = _
-  -- rw [one_smul]
-  erw [AddCon.lift_coe]
-  erw [FreeAddMonoid.of]
-  dsimp [FreeAddMonoid.ofList]
-  rw [← one_smul R (φ f)]
-  erw [Equiv.refl_apply]
-  convert one_smul R (φ f)
-  simp
-
+  rw [FreeAddMonoid.of, FreeAddMonoid.ofList, Equiv.refl_apply, AddCon.lift_coe]
+  dsimp [FreeAddMonoid.lift, FreeAddMonoid.sumAux]
+  show _ • _ = _
+  rw [one_smul]
 #align pi_tensor_product.lift_aux_tprod PiTensorProduct.liftAux_tprod
 
 theorem liftAux_tprodCoeff (φ : MultilinearMap R s E) (z : R) (f : ∀ i, s i) :
chore: bump toolchain to v4.2.0-rc2 (#7703)

This includes all the changes from #7606.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -367,10 +367,19 @@ def liftAux (φ : MultilinearMap R s E) : (⨂[R] i, s i) →+ E :=
 
 theorem liftAux_tprod (φ : MultilinearMap R s E) (f : ∀ i, s i) : liftAux φ (tprod R f) = φ f := by
   simp only [liftAux, liftAddHom, tprod_eq_tprodCoeff_one, tprodCoeff, AddCon.coe_mk']
-  rw [FreeAddMonoid.of, FreeAddMonoid.ofList, Equiv.refl_apply, AddCon.lift_coe]
-  dsimp [FreeAddMonoid.lift, FreeAddMonoid.sumAux]
-  show _ • _ = _
-  rw [one_smul]
+  -- The end of this proof was very different before leanprover/lean4#2644:
+  -- rw [FreeAddMonoid.of, FreeAddMonoid.ofList, Equiv.refl_apply, AddCon.lift_coe]
+  -- dsimp [FreeAddMonoid.lift, FreeAddMonoid.sumAux]
+  -- show _ • _ = _
+  -- rw [one_smul]
+  erw [AddCon.lift_coe]
+  erw [FreeAddMonoid.of]
+  dsimp [FreeAddMonoid.ofList]
+  rw [← one_smul R (φ f)]
+  erw [Equiv.refl_apply]
+  convert one_smul R (φ f)
+  simp
+
 #align pi_tensor_product.lift_aux_tprod PiTensorProduct.liftAux_tprod
 
 theorem liftAux_tprodCoeff (φ : MultilinearMap R s E) (z : R) (f : ∀ i, s i) :
feat: use suppress_compilation in tensor products (#7504)

More principled version of #7281.

Diff
@@ -62,6 +62,7 @@ binary tensor product in `LinearAlgebra/TensorProduct.lean`.
 multilinear, tensor, tensor product
 -/
 
+suppress_compilation
 
 open Function
 
@@ -112,6 +113,7 @@ def PiTensorProduct : Type _ :=
 
 variable {R}
 
+unsuppress_compilation in
 -- This enables the notation `⨂[R] i : ι, s i` for the pi tensor product, given `s : ι → Type*`.
 --scoped[TensorProduct] -- Porting note: `scoped` caused an error, so I commented it out.
 /-- notation for tensor product over some indexed type -/
@@ -307,6 +309,7 @@ def tprod : MultilinearMap R s (⨂[R] i, s i) where
 
 variable {R}
 
+unsuppress_compilation in
 /-- pure tensor in tensor product over some index type -/
 -- Porting note: use `FunLike.coe` as an explicit coercion to help `notation3` pretty print,
 -- was just `tprod R f`.
chore: only four spaces for subsequent lines (#7286)

Co-authored-by: Moritz Firsching <firsching@google.com>

Diff
@@ -314,7 +314,7 @@ notation3:100 "⨂ₜ["R"] "(...)", "r:(scoped f => FunLike.coe (tprod R) f) =>
 
 --Porting note: new theorem
 theorem tprod_eq_tprodCoeff_one :
-  ⇑(tprod R : MultilinearMap R s (⨂[R] i, s i)) = tprodCoeff R 1 := rfl
+    ⇑(tprod R : MultilinearMap R s (⨂[R] i, s i)) = tprodCoeff R 1 := rfl
 
 @[simp]
 theorem tprodCoeff_eq_smul_tprod (z : R) (f : ∀ i, s i) : tprodCoeff R z f = z • tprod R f := by
perf: remove overspecified fields (#6965)

This removes redundant field values of the form add := add for smaller terms and less unfolding during unification.

A list of all files containing a structure instance of the form { a1, ... with x1 := val, ... } where some xi is a field of some aj was generated by modifying the structure instance elaboration algorithm to print such overlaps to stdout in a custom toolchain.

Using that toolchain, I went through each file on the list and attempted to remove algebraic fields that overlapped and were redundant, eg add := add and not toFun (though some other ones did creep in). If things broke (which was the case in a couple of cases), I did not push further and reverted.

It is possible that pushing harder and trying to remove all redundant overlaps will yield further improvements.

Diff
@@ -275,7 +275,6 @@ end DistribMulAction
 -- to find.
 instance module' [Semiring R₁] [Module R₁ R] [SMulCommClass R₁ R R] : Module R₁ (⨂[R] i, s i) :=
   { PiTensorProduct.distribMulAction' with
-    smul := (· • ·)
     add_smul := fun r r' x ↦
       PiTensorProduct.induction_on' x
         (fun {r f} ↦ by simp_rw [smul_tprodCoeff', add_smul, add_tprodCoeff'])
chore: banish Type _ and Sort _ (#6499)

We remove all possible occurences of Type _ and Sort _ in favor of Type* and Sort*.

This has nice performance benefits.

Diff
@@ -12,14 +12,14 @@ import Mathlib.Tactic.LibrarySearch
 /-!
 # Tensor product of an indexed family of modules over commutative semirings
 
-We define the tensor product of an indexed family `s : ι → Type _` of modules over commutative
+We define the tensor product of an indexed family `s : ι → Type*` of modules over commutative
 semirings. We denote this space by `⨂[R] i, s i` and define it as `FreeAddMonoid (R × ∀ i, s i)`
 quotiented by the appropriate equivalence relation. The treatment follows very closely that of the
 binary tensor product in `LinearAlgebra/TensorProduct.lean`.
 
 ## Main definitions
 
-* `PiTensorProduct R s` with `R` a commutative semiring and `s : ι → Type _` is the tensor product
+* `PiTensorProduct R s` with `R` a commutative semiring and `s : ι → Type*` is the tensor product
   of all the `s i`'s. This is denoted by `⨂[R] i, s i`.
 * `tprod R f` with `f : ∀ i, s i` is the tensor product of the vectors `f i` over all `i : ι`.
   This is bundled as a multilinear map from `∀ i, s i` to `⨂[R] i, s i`.
@@ -67,19 +67,19 @@ open Function
 
 section Semiring
 
-variable {ι ι₂ ι₃ : Type _}
+variable {ι ι₂ ι₃ : Type*}
 
-variable {R : Type _} [CommSemiring R]
+variable {R : Type*} [CommSemiring R]
 
-variable {R₁ R₂ : Type _}
+variable {R₁ R₂ : Type*}
 
-variable {s : ι → Type _} [∀ i, AddCommMonoid (s i)] [∀ i, Module R (s i)]
+variable {s : ι → Type*} [∀ i, AddCommMonoid (s i)] [∀ i, Module R (s i)]
 
-variable {M : Type _} [AddCommMonoid M] [Module R M]
+variable {M : Type*} [AddCommMonoid M] [Module R M]
 
-variable {E : Type _} [AddCommMonoid E] [Module R E]
+variable {E : Type*} [AddCommMonoid E] [Module R E]
 
-variable {F : Type _} [AddCommMonoid F]
+variable {F : Type*} [AddCommMonoid F]
 
 namespace PiTensorProduct
 
@@ -104,7 +104,7 @@ end PiTensorProduct
 
 variable (R) (s)
 
-/-- `PiTensorProduct R s` with `R` a commutative semiring and `s : ι → Type _` is the tensor
+/-- `PiTensorProduct R s` with `R` a commutative semiring and `s : ι → Type*` is the tensor
   product of all the `s i`'s. This is denoted by `⨂[R] i, s i`. -/
 def PiTensorProduct : Type _ :=
   (addConGen (PiTensorProduct.Eqv R s)).Quotient
@@ -112,7 +112,7 @@ def PiTensorProduct : Type _ :=
 
 variable {R}
 
--- This enables the notation `⨂[R] i : ι, s i` for the pi tensor product, given `s : ι → Type _`.
+-- This enables the notation `⨂[R] i : ι, s i` for the pi tensor product, given `s : ι → Type*`.
 --scoped[TensorProduct] -- Porting note: `scoped` caused an error, so I commented it out.
 /-- notation for tensor product over some indexed type -/
 notation3:100"⨂["R"] "(...)", "r:(scoped f => PiTensorProduct R f) => r
@@ -660,9 +660,9 @@ open PiTensorProduct
 
 open TensorProduct
 
-variable {ι : Type _} {R : Type _} [CommRing R]
+variable {ι : Type*} {R : Type*} [CommRing R]
 
-variable {s : ι → Type _} [∀ i, AddCommGroup (s i)] [∀ i, Module R (s i)]
+variable {s : ι → Type*} [∀ i, AddCommGroup (s i)] [∀ i, Module R (s i)]
 
 /- Unlike for the binary tensor product, we require `R` to be a `CommRing` here, otherwise
 this is false in the case where `ι` is empty. -/
chore: script to replace headers with #align_import statements (#5979)

Open in Gitpod

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -2,16 +2,13 @@
 Copyright (c) 2020 Frédéric Dupuis. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Frédéric Dupuis, Eric Wieser
-
-! This file was ported from Lean 3 source module linear_algebra.pi_tensor_product
-! leanprover-community/mathlib commit ce11c3c2a285bbe6937e26d9792fda4e51f3fe1a
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathlib.GroupTheory.Congruence
 import Mathlib.LinearAlgebra.Multilinear.TensorProduct
 import Mathlib.Tactic.LibrarySearch
 
+#align_import linear_algebra.pi_tensor_product from "leanprover-community/mathlib"@"ce11c3c2a285bbe6937e26d9792fda4e51f3fe1a"
+
 /-!
 # Tensor product of an indexed family of modules over commutative semirings
 
chore: fix focusing dots (#5708)

This PR is the result of running

find . -type f -name "*.lean" -exec sed -i -E 's/^( +)\. /\1· /' {} \;
find . -type f -name "*.lean" -exec sed -i -E 'N;s/^( +·)\n +(.*)$/\1 \2/;P;D' {} \;

which firstly replaces . focusing dots with · and secondly removes isolated instances of such dots, unifying them with the following line. A new rule is placed in the style linter to verify this.

Diff
@@ -533,7 +533,7 @@ def isEmptyEquiv [IsEmpty ι] : (⨂[R] _ : ι, M) ≃ₗ[R] R where
         smul_eq_mul, mul_one]
       congr
       aesop
-    . simp only
+    · simp only
       intro x y hx hy
       rw [map_add, add_smul, hx, hy]
   right_inv t := by simp
chore: tidy various files (#5355)
Diff
@@ -115,7 +115,6 @@ def PiTensorProduct : Type _ :=
 
 variable {R}
 
--- mathport name: pi_tensor_product
 -- This enables the notation `⨂[R] i : ι, s i` for the pi tensor product, given `s : ι → Type _`.
 --scoped[TensorProduct] -- Porting note: `scoped` caused an error, so I commented it out.
 /-- notation for tensor product over some indexed type -/
@@ -228,17 +227,17 @@ variable [Monoid R₂] [DistribMulAction R₂ R] [SMulCommClass R₂ R R]
 
 -- Most of the time we want the instance below this one, which is easier for typeclass resolution
 -- to find.
-instance hasSmul' : SMul R₁ (⨂[R] i, s i) :=
+instance hasSMul' : SMul R₁ (⨂[R] i, s i) :=
   ⟨fun r ↦
     liftAddHom (fun f : R × ∀ i, s i ↦ tprodCoeff R (r • f.1) f.2)
       (fun r' f i hf ↦ by simp_rw [zero_tprodCoeff' _ f i hf])
       (fun f ↦ by simp [zero_tprodCoeff]) (fun r' f i m₁ m₂ ↦ by simp [add_tprodCoeff])
       (fun r' r'' f ↦ by simp [add_tprodCoeff', mul_add]) fun z f i r' ↦ by
       simp [smul_tprodCoeff, mul_smul_comm]⟩
-#align pi_tensor_product.has_smul' PiTensorProduct.hasSmul'
+#align pi_tensor_product.has_smul' PiTensorProduct.hasSMul'
 
 instance : SMul R (⨂[R] i, s i) :=
-  PiTensorProduct.hasSmul'
+  PiTensorProduct.hasSMul'
 
 theorem smul_tprodCoeff' (r : R₁) (z : R) (f : ∀ i, s i) :
     r • tprodCoeff R z f = tprodCoeff R (r • z) f := rfl
@@ -312,7 +311,6 @@ def tprod : MultilinearMap R s (⨂[R] i, s i) where
 
 variable {R}
 
--- mathport name: «expr⨂ₜ[ ] , »
 /-- pure tensor in tensor product over some index type -/
 -- Porting note: use `FunLike.coe` as an explicit coercion to help `notation3` pretty print,
 -- was just `tprod R f`.
@@ -399,15 +397,12 @@ def lift : MultilinearMap R s E ≃ₗ[R] (⨂[R] i, s i) →ₗ[R] E where
     ext
     simp [liftAux_tprod, LinearMap.compMultilinearMap]
   right_inv φ := by
-    refine ext ?_
     ext
     simp [liftAux_tprod]
   map_add' φ₁ φ₂ := by
-    refine ext ?_
     ext
     simp [liftAux_tprod]
   map_smul' r φ₂ := by
-    refine ext ?_
     ext
     simp [liftAux_tprod]
 #align pi_tensor_product.lift PiTensorProduct.lift
@@ -451,7 +446,6 @@ def reindex (e : ι ≃ ι₂) : (⨂[R] _ : ι, M) ≃ₗ[R] ⨂[R] _ : ι₂,
   LinearEquiv.ofLinear (lift (domDomCongr e.symm (tprod R : MultilinearMap R _ (⨂[R] _ : ι₂, M))))
     (lift (domDomCongr e (tprod R : MultilinearMap R _ (⨂[R] _ : ι, M))))
     (by
-      refine ext ?_
       ext
       simp only [LinearMap.comp_apply, LinearMap.id_apply, lift_tprod,
         LinearMap.compMultilinearMap_apply, lift.tprod, domDomCongr_apply]
@@ -459,7 +453,6 @@ def reindex (e : ι ≃ ι₂) : (⨂[R] _ : ι, M) ≃ₗ[R] ⨂[R] _ : ι₂,
       ext
       rw [e.apply_symm_apply])
     (by
-      refine ext ?_
       ext
       simp only [LinearMap.comp_apply, LinearMap.id_apply, lift_tprod,
         LinearMap.compMultilinearMap_apply, lift.tprod, domDomCongr_apply]
@@ -487,7 +480,6 @@ theorem reindex_comp_tprod (e : ι ≃ ι₂) :
 @[simp]
 theorem lift_comp_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ : ι₂ ↦ M) E) :
     lift φ ∘ₗ ↑(reindex R M e) = lift (φ.domDomCongr e.symm) := by
-  refine ext ?_
   ext
   simp
 #align pi_tensor_product.lift_comp_reindex PiTensorProduct.lift_comp_reindex
@@ -502,7 +494,6 @@ theorem lift_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ ↦ M) E)
 theorem reindex_trans (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) :
     (reindex R M e).trans (reindex R M e') = reindex R M (e.trans e') := by
   apply LinearEquiv.toLinearMap_injective
-  refine ext ?_
   ext f
   simp only [LinearEquiv.trans_apply, LinearEquiv.coe_coe, reindex_tprod,
     LinearMap.coe_compMultilinearMap, Function.comp_apply, MultilinearMap.domDomCongr_apply,
@@ -523,7 +514,7 @@ theorem reindex_symm (e : ι ≃ ι₂) : (reindex R M e).symm = reindex R M e.s
 @[simp]
 theorem reindex_refl : reindex R M (Equiv.refl ι) = LinearEquiv.refl R _ := by
   apply LinearEquiv.toLinearMap_injective
-  refine ext ?_
+  ext
   rw [reindex_comp_tprod, LinearEquiv.refl_toLinearMap, Equiv.refl_symm]
   rfl
 #align pi_tensor_product.reindex_refl PiTensorProduct.reindex_refl
@@ -628,18 +619,18 @@ attribute [local ext] TensorProduct.ext
 For simplicity, this is defined only for homogeneously- (rather than dependently-) typed components.
 -/
 def tmulEquiv : ((⨂[R] _ : ι, M) ⊗[R] ⨂[R] _ : ι₂, M) ≃ₗ[R] ⨂[R] _ : Sum ι ι₂, M :=
-  LinearEquiv.ofLinear tmul tmulSymm (by
-    refine ext (MultilinearMap.ext (fun (x : ι ⊕ ι₂ → M) => ?_))
-    show tmul (tmulSymm (tprod R x)) = tprod R x
-    -- Speed up the call to `simp`.
-    simp only [tmulSymm_apply, tmul_apply]
-    erw [Sum.elim_comp_inl_inr]) <| by
-      -- Porting note : even with `attribute [local ext] TensorProduct.ext`, Lean still doesn't
-      -- pick up this
-      refine TensorProduct.ext <| ext <| MultilinearMap.ext fun (x : ι → M) => ext <|
-        MultilinearMap.ext fun (y : ι₂ → M) => ?_
+  LinearEquiv.ofLinear tmul tmulSymm
+    (by
+      ext x
+      show tmul (tmulSymm (tprod R x)) = tprod R x -- Speed up the call to `simp`.
+      simp only [tmulSymm_apply, tmul_apply]
+      -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5026):
+      -- was part of `simp only` above
+      erw [Sum.elim_comp_inl_inr])
+    (by
+      ext x y
       show tmulSymm (tmul (tprod R x ⊗ₜ[R] tprod R y)) = tprod R x ⊗ₜ[R] tprod R y
-      simp only [tmul_apply, tmulSymm_apply, Sum.elim_inl, Sum.elim_inr]
+      simp only [tmul_apply, tmulSymm_apply, Sum.elim_inl, Sum.elim_inr])
 #align pi_tensor_product.tmul_equiv PiTensorProduct.tmulEquiv
 
 @[simp]
chore: fix many typos (#4967)

These are all doc fixes

Diff
@@ -48,7 +48,7 @@ binary tensor product in `LinearAlgebra/TensorProduct.lean`.
   requires it. However, problems may arise in the case where `ι` is infinite; use at your own
   caution.
 * Instead of requiring `DecidableEq ι` as an argument to `PiTensorProduct` itself, we include it
-  as an argument in the constructors of the relation. A decidability isntance still has to come
+  as an argument in the constructors of the relation. A decidability instance still has to come
   from somewhere due to the use of `Function.update`, but this hides it from the downstream user.
   See the implementation notes for `MultilinearMap` for an extended discussion of this choice.
 
style: allow _ for an argument in notation3 & replace _foo with _ in notation3 (#4652)
Diff
@@ -447,9 +447,9 @@ variable (R M)
 
 For simplicity, this is defined only for homogeneously- (rather than dependently-) typed components.
 -/
-def reindex (e : ι ≃ ι₂) : (⨂[R] _i : ι, M) ≃ₗ[R] ⨂[R] _i : ι₂, M :=
-  LinearEquiv.ofLinear (lift (domDomCongr e.symm (tprod R : MultilinearMap R _ (⨂[R] _i : ι₂, M))))
-    (lift (domDomCongr e (tprod R : MultilinearMap R _ (⨂[R] _i : ι, M))))
+def reindex (e : ι ≃ ι₂) : (⨂[R] _ : ι, M) ≃ₗ[R] ⨂[R] _ : ι₂, M :=
+  LinearEquiv.ofLinear (lift (domDomCongr e.symm (tprod R : MultilinearMap R _ (⨂[R] _ : ι₂, M))))
+    (lift (domDomCongr e (tprod R : MultilinearMap R _ (⨂[R] _ : ι, M))))
     (by
       refine ext ?_
       ext
@@ -479,7 +479,7 @@ theorem reindex_tprod (e : ι ≃ ι₂) (f : ∀ _, M) :
 
 @[simp]
 theorem reindex_comp_tprod (e : ι ≃ ι₂) :
-    (reindex R M e : (⨂[R] _i : ι, M) →ₗ[R] ⨂[R] _i : ι₂, M).compMultilinearMap (tprod R) =
+    (reindex R M e : (⨂[R] _ : ι, M) →ₗ[R] ⨂[R] _ : ι₂, M).compMultilinearMap (tprod R) =
       (tprod R : MultilinearMap R (fun _ ↦ M) _).domDomCongr e.symm :=
   MultilinearMap.ext <| reindex_tprod e
 #align pi_tensor_product.reindex_comp_tprod PiTensorProduct.reindex_comp_tprod
@@ -493,7 +493,7 @@ theorem lift_comp_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ : ι
 #align pi_tensor_product.lift_comp_reindex PiTensorProduct.lift_comp_reindex
 
 @[simp]
-theorem lift_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ ↦ M) E) (x : ⨂[R] _i, M) :
+theorem lift_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ ↦ M) E) (x : ⨂[R] _, M) :
     lift φ (reindex R M e x) = lift (φ.domDomCongr e.symm) x :=
   LinearMap.congr_fun (lift_comp_reindex e φ) x
 #align pi_tensor_product.lift_reindex PiTensorProduct.lift_reindex
@@ -511,7 +511,7 @@ theorem reindex_trans (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) :
 #align pi_tensor_product.reindex_trans PiTensorProduct.reindex_trans
 
 @[simp]
-theorem reindex_reindex (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) (x : ⨂[R] _i, M) :
+theorem reindex_reindex (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) (x : ⨂[R] _, M) :
     reindex R M e' (reindex R M e x) = reindex R M (e.trans e') x :=
   LinearEquiv.congr_fun (reindex_trans e e' : _ = reindex R M (e.trans e')) x
 #align pi_tensor_product.reindex_reindex PiTensorProduct.reindex_reindex
@@ -532,7 +532,7 @@ variable (ι)
 
 /-- The tensor product over an empty index type `ι` is isomorphic to the base ring. -/
 @[simps symm_apply]
-def isEmptyEquiv [IsEmpty ι] : (⨂[R] _i : ι, M) ≃ₗ[R] R where
+def isEmptyEquiv [IsEmpty ι] : (⨂[R] _ : ι, M) ≃ₗ[R] R where
   toFun := lift (constOfIsEmpty R _ 1)
   invFun r := r • tprod R (@isEmptyElim _ _ _)
   left_inv x := by
@@ -563,7 +563,7 @@ variable {ι}
 Tensor product of `M` over a singleton set is equivalent to `M`
 -/
 @[simps symm_apply]
-def subsingletonEquiv [Subsingleton ι] (i₀ : ι) : (⨂[R] _i : ι, M) ≃ₗ[R] M where
+def subsingletonEquiv [Subsingleton ι] (i₀ : ι) : (⨂[R] _ : ι, M) ≃ₗ[R] M where
   toFun := lift (MultilinearMap.ofSubsingleton R M i₀)
   invFun m := tprod R fun _ ↦ m
   left_inv x := by
@@ -595,7 +595,7 @@ theorem subsingletonEquiv_apply_tprod [Subsingleton ι] (i : ι) (f : ι → M)
 section Tmul
 
 /-- Collapse a `TensorProduct` of `PiTensorProduct`s. -/
-private def tmul : ((⨂[R] _i : ι, M) ⊗[R] ⨂[R] _i : ι₂, M) →ₗ[R] ⨂[R] _i : Sum ι ι₂, M :=
+private def tmul : ((⨂[R] _ : ι, M) ⊗[R] ⨂[R] _ : ι₂, M) →ₗ[R] ⨂[R] _ : Sum ι ι₂, M :=
   TensorProduct.lift
     { toFun := fun a ↦
         PiTensorProduct.lift <|
@@ -610,7 +610,7 @@ private theorem tmul_apply (a : ι → M) (b : ι₂ → M) :
   rfl
 
 /-- Expand `PiTensorProduct` into a `TensorProduct` of two factors. -/
-private def tmulSymm : (⨂[R] _i : Sum ι ι₂, M) →ₗ[R] (⨂[R] _i : ι, M) ⊗[R] ⨂[R] _i : ι₂, M :=
+private def tmulSymm : (⨂[R] _ : Sum ι ι₂, M) →ₗ[R] (⨂[R] _ : ι, M) ⊗[R] ⨂[R] _ : ι₂, M :=
   -- by using tactic mode, we avoid the need for a lot of `@`s and `_`s
   PiTensorProduct.lift <| MultilinearMap.domCoprod (tprod R) (tprod R)
 
@@ -627,7 +627,7 @@ attribute [local ext] TensorProduct.ext
 
 For simplicity, this is defined only for homogeneously- (rather than dependently-) typed components.
 -/
-def tmulEquiv : ((⨂[R] _i : ι, M) ⊗[R] ⨂[R] _i : ι₂, M) ≃ₗ[R] ⨂[R] _i : Sum ι ι₂, M :=
+def tmulEquiv : ((⨂[R] _ : ι, M) ⊗[R] ⨂[R] _ : ι₂, M) ≃ₗ[R] ⨂[R] _ : Sum ι ι₂, M :=
   LinearEquiv.ofLinear tmul tmulSymm (by
     refine ext (MultilinearMap.ext (fun (x : ι ⊕ ι₂ → M) => ?_))
     show tmul (tmulSymm (tprod R x)) = tprod R x
feat: port LinearAlgebra.PiTensorProduct (#3361)

Co-authored-by: Jujian Zhang <jujian.zhang1998@outlook.com> Co-authored-by: ChrisHughes24 <chrishughes24@gmail.com> Co-authored-by: Chris Hughes <chrishughes24@gmail.com> Co-authored-by: Kyle Miller <kmill31415@gmail.com>

Dependencies 8 + 382

383 files ported (98.0%)
158914 lines ported (98.1%)
Show graph

The unported dependencies are