linear_algebra.pi_tensor_product
⟷
Mathlib.LinearAlgebra.PiTensorProduct
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.
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(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)
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -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
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -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"
mathlib commit https://github.com/leanprover-community/mathlib/commit/32a7e535287f9c73f2e4d2aef306a39190f0b504
@@ -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 :=
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/6285167a053ad0990fc88e56c48ccd9fae6550eb
@@ -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) :
mathlib commit https://github.com/leanprover-community/mathlib/commit/2a0ce625dbb0ffbc7d1316597de0b25c1ec75303
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/9fb8964792b4237dac6200193a0d533f1b3f7423
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/a3e83f0fa4391c8740f7d773a7a9b74e311ae2a3
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/5f25c089cb34db4db112556f23c50d12da81b297
@@ -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}
mathlib commit https://github.com/leanprover-community/mathlib/commit/cca40788df1b8755d5baf17ab2f27dacc2e17acb
@@ -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) :=
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -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]
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -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]
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -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)
mathlib commit https://github.com/leanprover-community/mathlib/commit/8d33f09cd7089ecf074b4791907588245aec5d1b
@@ -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) :
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce11c3c2a285bbe6937e26d9792fda4e51f3fe1a
@@ -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)]
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce7e9d53d4bbc38065db3b595cd5bd73c323bc1d
@@ -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'
mathlib commit https://github.com/leanprover-community/mathlib/commit/bd9851ca476957ea4549eb19b40e7b5ade9428cc
Purely automatic replacement. If this is in any way controversial; I'm happy to just close this PR.
@@ -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
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ᵢ
.
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
.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
.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.
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>
@@ -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]
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)
@@ -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
@@ -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
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.
@@ -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
PiTensorProduct
(#11152)
PiTensorProduct.map
, for example the compatibility with composition and reindeixing, and the fact that it sends the identity to the identity.PiTensorProduct.map
as a MultilinearMap
on the family of linear maps.PiTensorProduct.map f
to a linear equivalence called PiTensorProduct.congr f
when f
is a family of linear equivalences.ι
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>
@@ -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
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>
@@ -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
Homogenises porting notes via capitalisation and addition of whitespace.
It makes the following changes:
@@ -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
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>
@@ -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)
@@ -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
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
@@ -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]
This shortens Mathlib.LinearAlgebra.Basic
, which is both longer than we like and doesn't have a clear scope.
@@ -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
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.
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]
.
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_param
s, [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 sometimesThis 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.
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 outParam
s 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.)
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>
@@ -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
@@ -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
@@ -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
*.ofSubsingleton
(#8694)
Change MultilinearMap.ofSubsingleton
and other similar definitions
so that they are now equivalences between linear maps
and 1
-multilinear maps.
@@ -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
attribute [simp] ... in
-> attribute [local simp] ... in
(#7678)
Mathlib.Logic.Unique contains the line attribute [simp] eq_iff_true_of_subsingleton in ...
:
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 simp
s. 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.
@@ -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
@@ -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
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
notation3
commandWe now also generate matchers for expansions that have pi types and lambda expressions.
@@ -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 :
@@ -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) :
@@ -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) :
@@ -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) :
@@ -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`.
@@ -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
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.
@@ -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'])
Type _
and Sort _
(#6499)
We remove all possible occurences of Type _
and Sort _
in favor of Type*
and Sort*
.
This has nice performance benefits.
@@ -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. -/
@@ -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
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.
@@ -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
@@ -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]
@@ -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.
@@ -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
The unported dependencies are